1: <?php
2:
3: namespace Neodynamic\SDK\Web;
4: use Exception;
5: use ZipArchive;
6:
7:
8: WebClientPrint::$licenseOwner = '';
9: WebClientPrint::$licenseKey = '';
10:
11:
12: 13: 14: 15: 16: 17: 18: 19: 20:
21: class WebClientPrint {
22:
23: const VERSION = '3.0.2016.0';
24: const CLIENT_PRINT_JOB = 'clientPrint';
25: const WCP = 'WEB_CLIENT_PRINT';
26: const WCP_SCRIPT_AXD_GET_PRINTERS = 'getPrinters';
27: const WCPP_SET_PRINTERS = 'printers';
28: const WCP_SCRIPT_AXD_GET_WCPPVERSION = 'getWcppVersion';
29: const WCPP_SET_VERSION = 'wcppVer';
30: const GEN_WCP_SCRIPT_URL = 'u';
31: const GEN_DETECT_WCPP_SCRIPT = 'd';
32: const SID = 'sid';
33: const PING = 'wcppping';
34:
35: const WCP_CACHE_WCPP_INSTALLED = 'WCPP_INSTALLED';
36: const WCP_CACHE_WCPP_VER = 'WCPP_VER';
37: const WCP_CACHE_PRINTERS = 'PRINTERS';
38:
39:
40: 41: 42: 43:
44: static $licenseOwner = '';
45: 46: 47: 48:
49: static $licenseKey = '';
50: 51: 52: 53:
54: static $webClientPrintAbsoluteUrl = '';
55: 56: 57: 58: 59:
60: static $wcpCacheFolder = '';
61:
62: 63: 64: 65: 66: 67: 68:
69: public static function cacheAdd($sid, $key, $val){
70: if (Utils::isNullOrEmptyString(self::$wcpCacheFolder)){
71: throw new Exception('WebClientPrint wcpCacheFolder is missing, please specify it.');
72: }
73: if (Utils::isNullOrEmptyString($sid)){
74: throw new Exception('WebClientPrint FileName cache is missing, please specify it.');
75: }
76: $cacheFileName = (Utils::strEndsWith(self::$wcpCacheFolder, '/')?self::$wcpCacheFolder:self::$wcpCacheFolder.'/').$sid.'.wcpcache';
77: $dataWCPP_VER = '';
78: $dataPRINTERS = '';
79:
80: if(file_exists($cacheFileName)){
81: $cache_info = parse_ini_file($cacheFileName);
82:
83: $dataWCPP_VER = $cache_info[self::WCP_CACHE_WCPP_VER];
84: $dataPRINTERS = $cache_info[self::WCP_CACHE_PRINTERS];
85: }
86:
87: if ($key === self::WCP_CACHE_WCPP_VER){
88: $dataWCPP_VER = self::WCP_CACHE_WCPP_VER.'='.'"'.$val.'"';
89: $dataPRINTERS = self::WCP_CACHE_PRINTERS.'='.'"'.$dataPRINTERS.'"';
90: } else if ($key === self::WCP_CACHE_PRINTERS){
91: $dataWCPP_VER = self::WCP_CACHE_WCPP_VER.'='.'"'.$dataWCPP_VER.'"';
92: $dataPRINTERS = self::WCP_CACHE_PRINTERS.'='.'"'.$val.'"';
93: }
94:
95: $data = $dataWCPP_VER.chr(13).chr(10).$dataPRINTERS;
96: $handle = fopen($cacheFileName, 'w') or die('Cannot open file: '.$cacheFileName);
97: fwrite($handle, $data);
98: fclose($handle);
99:
100: }
101:
102: 103: 104: 105: 106: 107: 108:
109: public static function cacheGet($sid, $key){
110: if (Utils::isNullOrEmptyString(self::$wcpCacheFolder)){
111: throw new Exception('WebClientPrint wcpCacheFolder is missing, please specify it.');
112: }
113: if (Utils::isNullOrEmptyString($sid)){
114: throw new Exception('WebClientPrint FileName cache is missing, please specify it.');
115: }
116: $cacheFileName = (Utils::strEndsWith(self::$wcpCacheFolder, '/')?self::$wcpCacheFolder:self::$wcpCacheFolder.'/').$sid.'.wcpcache';
117: if(file_exists($cacheFileName)){
118: $cache_info = parse_ini_file($cacheFileName, FALSE, INI_SCANNER_RAW);
119:
120: if($key===self::WCP_CACHE_WCPP_VER || $key===self::WCP_CACHE_WCPP_INSTALLED){
121: return $cache_info[self::WCP_CACHE_WCPP_VER];
122: }else if($key===self::WCP_CACHE_PRINTERS){
123: return $cache_info[self::WCP_CACHE_PRINTERS];
124: }else{
125: return '';
126: }
127: }else{
128: return '';
129: }
130: }
131:
132: 133: 134: 135:
136: public static function cacheClean($minutes){
137: if (!Utils::isNullOrEmptyString(self::$wcpCacheFolder)){
138: $cacheDir = (Utils::strEndsWith(self::$wcpCacheFolder, '/')?self::$wcpCacheFolder:self::$wcpCacheFolder.'/');
139: if ($handle = opendir($cacheDir)) {
140: while (false !== ($file = readdir($handle))) {
141: if ($file!='.' && $file!='..' && (time()-filectime($cacheDir.$file)) > (60*$minutes)) {
142: unlink($cacheDir.$file);
143: }
144: }
145: closedir($handle);
146: }
147: }
148: }
149:
150: 151: 152: 153: 154: 155: 156: 157: 158: 159: 160: 161: 162: 163: 164: 165: 166: 167: 168:
169: public static function createWcppDetectionScript($webClientPrintControllerAbsoluteUrl, $sessionID){
170:
171: if (Utils::isNullOrEmptyString($webClientPrintControllerAbsoluteUrl) ||
172: !Utils::strStartsWith($webClientPrintControllerAbsoluteUrl, 'http')){
173: throw new Exception('WebClientPrintController absolute URL is missing, please specify it.');
174: }
175: if (Utils::isNullOrEmptyString($sessionID)){
176: throw new Exception('Session ID is missing, please specify it.');
177: }
178:
179: $url = $webClientPrintControllerAbsoluteUrl.'?'.self::GEN_DETECT_WCPP_SCRIPT.'='.$sessionID;
180: return '<script src="'.$url.'" type="text/javascript"></script>';
181:
182: }
183:
184:
185: 186: 187: 188: 189: 190: 191: 192: 193: 194:
195: public static function createScript($webClientPrintControllerAbsoluteUrl, $clientPrintJobAbsoluteUrl, $sessionID){
196: if (Utils::isNullOrEmptyString($webClientPrintControllerAbsoluteUrl) ||
197: !Utils::strStartsWith($webClientPrintControllerAbsoluteUrl, 'http')){
198: throw new Exception('WebClientPrintController absolute URL is missing, please specify it.');
199: }
200: if (Utils::isNullOrEmptyString($clientPrintJobAbsoluteUrl) ||
201: !Utils::strStartsWith($clientPrintJobAbsoluteUrl, 'http')){
202: throw new Exception('ClientPrintJob absolute URL is missing, please specify it.');
203: }
204: if (Utils::isNullOrEmptyString($sessionID)){
205: throw new Exception('Session ID is missing, please specify it.');
206: }
207:
208:
209: $wcpHandler = $webClientPrintControllerAbsoluteUrl.'?';
210: $wcpHandler .= self::VERSION;
211: $wcpHandler .= '&';
212: $wcpHandler .= microtime(true);
213: $wcpHandler .= '&sid=';
214: $wcpHandler .= $sessionID;
215: $wcpHandler .= '&'.self::GEN_WCP_SCRIPT_URL.'=';
216: $wcpHandler .= base64_encode($clientPrintJobAbsoluteUrl);
217: return '<script src="'.$wcpHandler.'" type="text/javascript"></script>';
218: }
219:
220:
221: 222: 223: 224: 225: 226:
227: public static function generateScript($webClientPrintControllerAbsoluteUrl, $queryString)
228: {
229: if (Utils::isNullOrEmptyString($webClientPrintControllerAbsoluteUrl) ||
230: !Utils::strStartsWith($webClientPrintControllerAbsoluteUrl, 'http')){
231: throw new Exception('WebClientPrintController absolute URL is missing, please specify it.');
232: }
233:
234: parse_str($queryString, $qs);
235:
236: if(isset($qs[self::GEN_DETECT_WCPP_SCRIPT])){
237:
238: $curSID = $qs[self::GEN_DETECT_WCPP_SCRIPT];
239: $onSuccessScript = 'wcppDetectOnSuccess(data);';
240: $onFailureScript = 'wcppDetectOnFailure();';
241: $dynamicIframeId = 'i'.substr(uniqid(), 0, 3);
242: $absoluteWcpAxd = $webClientPrintControllerAbsoluteUrl.'?'.self::SID.'='.$curSID;
243:
244: $s1 = 'dmFyIGpzV0NQUD0oZnVuY3Rpb24oKXt2YXIgc2V0PDw8LU5FTy1IVE1MLUlELT4+Pj1mdW5jdGlvbigpe2lmKHdpbmRvdy5jaHJvbWUpeyQoJyM8PDwtTkVPLUhUTUwtSUQtPj4+JykuYXR0cignaHJlZicsJ3dlYmNsaWVudHByaW50OicrYXJndW1lbnRzWzBdKTt2YXIgYT0kKCdhIzw8PC1ORU8tSFRNTC1JRC0+Pj4nKVswXTt2YXIgZXZPYmo9ZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ01vdXNlRXZlbnRzJyk7ZXZPYmouaW5pdEV2ZW50KCdjbGljaycsdHJ1ZSx0cnVlKTthLmRpc3BhdGNoRXZlbnQoZXZPYmopfWVsc2V7JCgnIzw8PC1ORU8tSFRNTC1JRC0+Pj4nKS5hdHRyKCdzcmMnLCd3ZWJjbGllbnRwcmludDonK2FyZ3VtZW50c1swXSl9fTtyZXR1cm57aW5pdDpmdW5jdGlvbigpe2lmKHdpbmRvdy5jaHJvbWUpeyQoJzxhIC8+Jyx7aWQ6Jzw8PC1ORU8tSFRNTC1JRC0+Pj4nfSkuYXBwZW5kVG8oJ2JvZHknKX1lbHNleyQoJzxpZnJhbWUgLz4nLHtuYW1lOic8PDwtTkVPLUhUTUwtSUQtPj4+JyxpZDonPDw8LU5FTy1IVE1MLUlELT4+Picsd2lkdGg6JzEnLGhlaWdodDonMScsc3R5bGU6J3Zpc2liaWxpdHk6aGlkZGVuO3Bvc2l0aW9uOmFic29sdXRlJ30pLmFwcGVuZFRvKCdib2R5Jyl9fSxwaW5nOmZ1bmN0aW9uKCl7c2V0PDw8LU5FTy1IVE1MLUlELT4+PignPDw8LU5FTy1QSU5HLVVSTC0+Pj4nKyhhcmd1bWVudHMubGVuZ3RoPT0xPycmJythcmd1bWVudHNbMF06JycpKTt2YXIgZGVsYXlfbXM9KHR5cGVvZiB3Y3BwUGluZ0RlbGF5X21zPT09J3VuZGVmaW5lZCcpPzEwMDAwOndjcHBQaW5nRGVsYXlfbXM7c2V0VGltZW91dChmdW5jdGlvbigpeyQuZ2V0KCc8PDwtTkVPLVVTRVItSEFTLVdDUFAtPj4+JyxmdW5jdGlvbihkYXRhKXtpZihkYXRhLmxlbmd0aCA+IDApezw8PC1ORU8tT04tU1VDQ0VTUy1TQ1JJUFQtPj4+fWVsc2V7PDw8LU5FTy1PTi1GQUlMVVJFLVNDUklQVC0+Pj59fSl9LGRlbGF5X21zKX19fSkoKTsgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKXtqc1dDUFAuaW5pdCgpO2pzV0NQUC5waW5nKCk7fSk7';
245:
246: $s2 = base64_decode($s1);
247: $s2 = str_replace('<<<-NEO-HTML-ID->>>', $dynamicIframeId, $s2);
248: $s2 = str_replace('<<<-NEO-PING-URL->>>', $absoluteWcpAxd.'&'.self::PING, $s2);
249: $s2 = str_replace('<<<-NEO-USER-HAS-WCPP->>>', $absoluteWcpAxd, $s2);
250: $s2 = str_replace('<<<-NEO-ON-SUCCESS-SCRIPT->>>', $onSuccessScript, $s2);
251: $s2 = str_replace('<<<-NEO-ON-FAILURE-SCRIPT->>>', $onFailureScript, $s2);
252:
253: return $s2;
254:
255: }else if(isset($qs[self::GEN_WCP_SCRIPT_URL])){
256:
257: $clientPrintJobUrl = base64_decode($qs[self::GEN_WCP_SCRIPT_URL]);
258: if (strpos($clientPrintJobUrl, '?')>0){
259: $clientPrintJobUrl .= '&';
260: }else{
261: $clientPrintJobUrl .= '?';
262: }
263: $clientPrintJobUrl .= self::CLIENT_PRINT_JOB;
264: $absoluteWcpAxd = $webClientPrintControllerAbsoluteUrl;
265: $wcppGetPrintersParam = '-getPrinters:'.$absoluteWcpAxd.'?'.self::WCP.'&'.self::SID.'=';
266: $wcpHandlerGetPrinters = $absoluteWcpAxd.'?'.self::WCP.'&'.self::WCP_SCRIPT_AXD_GET_PRINTERS.'&'.self::SID.'=';
267: $wcppGetWcppVerParam = '-getWcppVersion:'.$absoluteWcpAxd.'?'.self::WCP.'&'.self::SID.'=';
268: $wcpHandlerGetWcppVer = $absoluteWcpAxd.'?'.self::WCP.'&'.self::WCP_SCRIPT_AXD_GET_WCPPVERSION.'&'.self::SID.'=';
269: $sessionIDVal = $qs[self::SID];
270:
271: $s1 = 'dmFyIGpzV2ViQ2xpZW50UHJpbnQ9KGZ1bmN0aW9uKCl7dmFyIHNldEE9ZnVuY3Rpb24oKXt2YXIgZV9pZD0naWRfJytuZXcgRGF0ZSgpLmdldFRpbWUoKTtpZih3aW5kb3cuY2hyb21lKXskKCdib2R5JykuYXBwZW5kKCc8YSBpZD1cIicrZV9pZCsnXCI+PC9hPicpOyQoJyMnK2VfaWQpLmF0dHIoJ2hyZWYnLCd3ZWJjbGllbnRwcmludDonK2FyZ3VtZW50c1swXSk7dmFyIGE9JCgnYSMnK2VfaWQpWzBdO3ZhciBldk9iaj1kb2N1bWVudC5jcmVhdGVFdmVudCgnTW91c2VFdmVudHMnKTtldk9iai5pbml0RXZlbnQoJ2NsaWNrJyx0cnVlLHRydWUpO2EuZGlzcGF0Y2hFdmVudChldk9iail9ZWxzZXskKCdib2R5JykuYXBwZW5kKCc8aWZyYW1lIG5hbWU9XCInK2VfaWQrJ1wiIGlkPVwiJytlX2lkKydcIiB3aWR0aD1cIjFcIiBoZWlnaHQ9XCIxXCIgc3R5bGU9XCJ2aXNpYmlsaXR5OmhpZGRlbjtwb3NpdGlvbjphYnNvbHV0ZVwiIC8+Jyk7JCgnIycrZV9pZCkuYXR0cignc3JjJywnd2ViY2xpZW50cHJpbnQ6Jythcmd1bWVudHNbMF0pfXNldFRpbWVvdXQoZnVuY3Rpb24oKXskKCcjJytlX2lkKS5yZW1vdmUoKX0sNTAwMCl9O3JldHVybntwcmludDpmdW5jdGlvbigpe3NldEEoJ1VSTF9QUklOVF9KT0InKyhhcmd1bWVudHMubGVuZ3RoPT0xPycmJythcmd1bWVudHNbMF06JycpKX0sZ2V0UHJpbnRlcnM6ZnVuY3Rpb24oKXtzZXRBKCdVUkxfV0NQX0FYRF9XSVRIX0dFVF9QUklOVEVSU19DT01NQU5EJysnPDw8LU5FTy1TRVNTSU9OLUlELT4+PicpO3ZhciBkZWxheV9tcz0odHlwZW9mIHdjcHBHZXRQcmludGVyc0RlbGF5X21zPT09J3VuZGVmaW5lZCcpPzEwMDAwOndjcHBHZXRQcmludGVyc0RlbGF5X21zO3NldFRpbWVvdXQoZnVuY3Rpb24oKXskLmdldCgnVVJMX1dDUF9BWERfR0VUX1BSSU5URVJTJysnPDw8LU5FTy1TRVNTSU9OLUlELT4+PicsZnVuY3Rpb24oZGF0YSl7aWYoZGF0YS5sZW5ndGg+MCl7d2NwR2V0UHJpbnRlcnNPblN1Y2Nlc3MoZGF0YSl9ZWxzZXt3Y3BHZXRQcmludGVyc09uRmFpbHVyZSgpfX0pfSxkZWxheV9tcyl9LGdldFdjcHBWZXI6ZnVuY3Rpb24oKXtzZXRBKCdVUkxfV0NQX0FYRF9XSVRIX0dFVF9XQ1BQVkVSU0lPTl9DT01NQU5EJysnPDw8LU5FTy1TRVNTSU9OLUlELT4+PicpO3ZhciBkZWxheV9tcz0odHlwZW9mIHdjcHBHZXRWZXJEZWxheV9tcz09PSd1bmRlZmluZWQnKT8xMDAwMDp3Y3BwR2V0VmVyRGVsYXlfbXM7c2V0VGltZW91dChmdW5jdGlvbigpeyQuZ2V0KCdVUkxfV0NQX0FYRF9HRVRfV0NQUFZFUlNJT04nKyc8PDwtTkVPLVNFU1NJT04tSUQtPj4+JyxmdW5jdGlvbihkYXRhKXtpZihkYXRhLmxlbmd0aD4wKXt3Y3BHZXRXY3BwVmVyT25TdWNjZXNzKGRhdGEpfWVsc2V7d2NwR2V0V2NwcFZlck9uRmFpbHVyZSgpfX0pfSxkZWxheV9tcyl9LHNlbmQ6ZnVuY3Rpb24oKXtzZXRBLmFwcGx5KHRoaXMsYXJndW1lbnRzKX19fSkoKTs=';
272:
273: $s2 = base64_decode($s1);
274: $s2 = str_replace('URL_PRINT_JOB', $clientPrintJobUrl, $s2);
275: $s2 = str_replace('URL_WCP_AXD_WITH_GET_PRINTERS_COMMAND', $wcppGetPrintersParam, $s2);
276: $s2 = str_replace('URL_WCP_AXD_GET_PRINTERS', $wcpHandlerGetPrinters, $s2);
277: $s2 = str_replace('URL_WCP_AXD_WITH_GET_WCPPVERSION_COMMAND', $wcppGetWcppVerParam, $s2);
278: $s2 = str_replace('URL_WCP_AXD_GET_WCPPVERSION', $wcpHandlerGetWcppVer, $s2);
279: $s2 = str_replace('<<<-NEO-SESSION-ID->>>', $sessionIDVal, $s2);
280:
281: return $s2;
282: }
283:
284: }
285:
286:
287: 288: 289:
290: const GenPrintScript = 0;
291: 292: 293:
294: const GenWcppDetectScript = 1;
295: 296: 297:
298: const ClientSetInstalledPrinters = 2;
299: 300: 301:
302: const ClientGetInstalledPrinters = 3;
303: 304: 305:
306: const ClientSetWcppVersion = 4;
307: 308: 309:
310: const ClientGetWcppVersion = 5;
311:
312: 313: 314: 315: 316: 317: 318:
319: public static function GetProcessRequestType($queryString){
320: parse_str($queryString, $qs);
321:
322: if(isset($qs[self::SID])){
323: if(isset($qs[self::PING])){
324: return self::ClientSetWcppVersion;
325: } else if(isset($qs[self::WCPP_SET_VERSION])){
326: return self::ClientSetWcppVersion;
327: } else if(isset($qs[self::WCPP_SET_PRINTERS])){
328: return self::ClientSetInstalledPrinters;
329: } else if(isset($qs[self::WCP_SCRIPT_AXD_GET_WCPPVERSION])){
330: return self::ClientGetWcppVersion;
331: } else if(isset($qs[self::WCP_SCRIPT_AXD_GET_PRINTERS])){
332: return self::ClientGetInstalledPrinters;
333: } else if(isset($qs[self::GEN_WCP_SCRIPT_URL])){
334: return self::GenPrintScript;
335: } else {
336: return self::ClientGetWcppVersion;
337: }
338: } else if(isset($qs[self::GEN_DETECT_WCPP_SCRIPT])){
339: return self::GenWcppDetectScript;
340: } else {
341: throw new Exception('No valid ProcessRequestType was found in the specified QueryString.');
342: }
343: }
344:
345: }
346:
347: 348: 349:
350: abstract class ClientPrinter{
351:
352: public $printerId;
353: public function serialize(){
354:
355: }
356: }
357:
358: 359: 360:
361: class DefaultPrinter extends ClientPrinter{
362: public function __construct() {
363: $this->printerId = chr(0);
364: }
365:
366: public function serialize() {
367: return $this->printerId;
368: }
369: }
370:
371: 372: 373:
374: class InstalledPrinter extends ClientPrinter{
375:
376: 377: 378: 379:
380: public $printerName = '';
381:
382: 383: 384: 385:
386: public $printToDefaultIfNotFound = false;
387:
388: 389: 390: 391:
392: public function __construct($printerName) {
393: $this->printerId = chr(1);
394: $this->printerName = $printerName;
395: }
396:
397: public function serialize() {
398:
399: if (Utils::isNullOrEmptyString($this->printerName)){
400: throw new Exception("The specified printer name is null or empty.");
401: }
402:
403: if ($this->printToDefaultIfNotFound){
404: return $this->printerId.$this->printerName.Utils::SER_SEP.'1';
405: } else {
406: return $this->printerId.$this->printerName;
407: }
408:
409: }
410: }
411:
412: 413: 414:
415: class ParallelPortPrinter extends ClientPrinter{
416:
417: 418: 419: 420:
421: public $portName = "LPT1";
422:
423: 424: 425: 426:
427: public function __construct($portName) {
428: $this->printerId = chr(2);
429: $this->portName = $portName;
430: }
431:
432: public function serialize() {
433:
434: if (Utils::isNullOrEmptyString($this->portName)){
435: throw new Exception("The specified parallel port name is null or empty.");
436: }
437:
438: return $this->printerId.$this->portName;
439: }
440: }
441:
442: 443: 444:
445: class SerialPortPrinter extends ClientPrinter{
446:
447: 448: 449: 450:
451: public $portName = "COM1";
452: 453: 454: 455:
456: public $baudRate = 9600;
457: 458: 459: 460: 461:
462: public $parity = SerialPortParity::NONE;
463: 464: 465: 466: 467:
468: public $stopBits = SerialPortStopBits::ONE;
469: 470: 471: 472:
473: public $dataBits = 8;
474: 475: 476: 477: 478:
479: public $flowControl = SerialPortHandshake::XON_XOFF;
480:
481: 482: 483: 484: 485: 486: 487: 488: 489:
490: public function __construct($portName, $baudRate, $parity, $stopBits, $dataBits, $flowControl) {
491: $this->printerId = chr(3);
492: $this->portName = $portName;
493: $this->baudRate = $baudRate;
494: $this->parity = $parity;
495: $this->stopBits = $stopBits;
496: $this->dataBits = $dataBits;
497: $this->flowControl = $flowControl;
498: }
499:
500: public function serialize() {
501:
502: if (Utils::isNullOrEmptyString($this->portName)){
503: throw new Exception("The specified serial port name is null or empty.");
504: }
505:
506: return $this->printerId.$this->portName.Utils::SER_SEP.$this->baudRate.Utils::SER_SEP.$this->dataBits.Utils::SER_SEP.$this->flowControl.Utils::SER_SEP.$this->parity.Utils::SER_SEP.$this->stopBits;
507: }
508: }
509:
510: 511: 512:
513: class NetworkPrinter extends ClientPrinter{
514:
515: 516: 517: 518:
519: public $dnsName = "";
520: 521: 522: 523:
524: public $ipAddress = "";
525: 526: 527: 528:
529: public $port = 0;
530:
531: 532: 533: 534: 535: 536:
537: public function __construct($dnsName, $ipAddress, $port) {
538: $this->printerId = chr(4);
539: $this->dnsName = $dnsName;
540: $this->ipAddress = $ipAddress;
541: $this->port = $port;
542: }
543:
544: public function serialize() {
545:
546: if (Utils::isNullOrEmptyString($this->dnsName) && Utils::isNullOrEmptyString($this->ipAddress)){
547: throw new Exception("The specified network printer settings is not valid. You must specify the DNS Printer Name or its IP address.");
548: }
549:
550: return $this->printerId.$this->dnsName.Utils::SER_SEP.$this->ipAddress.Utils::SER_SEP.$this->port;
551: }
552: }
553:
554: 555: 556:
557: class UserSelectedPrinter extends ClientPrinter{
558: public function __construct() {
559: $this->printerId = chr(5);
560: }
561:
562: public function serialize() {
563: return $this->printerId;
564: }
565: }
566:
567: 568: 569:
570: class SerialPortParity{
571: const NONE = 0;
572: const ODD = 1;
573: const EVEN = 2;
574: const MARK = 3;
575: const SPACE = 4;
576: }
577:
578: 579: 580:
581: class SerialPortStopBits{
582: const NONE = 0;
583: const ONE = 1;
584: const TWO = 2;
585: const ONE_POINT_FIVE = 3;
586: }
587:
588: 589: 590:
591: class SerialPortHandshake{
592: const NONE = 0;
593: const REQUEST_TO_SEND = 2;
594: const REQUEST_TO_SEND_XON_XOFF = 3;
595: const XON_XOFF = 1;
596: }
597:
598: 599: 600:
601: class PrintFile{
602:
603: 604: 605: 606:
607: public $filePath = '';
608: 609: 610: 611: 612:
613: public $fileName = '';
614: 615: 616: 617:
618: public $fileBinaryContent = '';
619:
620: 621: 622: 623:
624: public $copies = 1;
625:
626: const PREFIX = 'wcpPF:';
627: const SEP = '|';
628:
629: 630: 631: 632: 633: 634:
635: public function __construct($filePath, $fileName, $fileBinaryContent) {
636: $this->filePath = $filePath;
637: $this->fileName = $fileName;
638: $this->fileBinaryContent = $fileBinaryContent;
639:
640: }
641:
642: public function serialize() {
643: $file = str_replace('\\', 'BACKSLASHCHAR',$this->fileName );
644: if($this->copies > 1){
645: $pfc = 'PFC='.$this->copies;
646: $file = substr($file, 0, strrpos($file, '.')).$pfc.substr($file, strrpos($file, '.'));
647: }
648: return self::PREFIX.$file.self::SEP.$this->getFileContent();
649: }
650:
651: public function getFileContent(){
652: $content = $this->fileBinaryContent;
653: if(!Utils::isNullOrEmptyString($this->filePath)){
654: $handle = fopen($this->filePath, 'rb');
655: $content = fread($handle, filesize($this->filePath));
656: fclose($handle);
657: }
658: return $content;
659: }
660: }
661:
662: 663: 664:
665: class Utils{
666: const SER_SEP = "|";
667:
668: static function isNullOrEmptyString($s){
669: return (!isset($s) || trim($s)==='');
670: }
671:
672: static function formatHexValues($s){
673:
674: $buffer = '';
675:
676: $l = strlen($s);
677: $i = 0;
678:
679: while ($i < $l)
680: {
681: if ($s[$i] == '0')
682: {
683: if ($i + 1 < $l && ($s[$i] == '0' && $s[$i + 1] == 'x'))
684: {
685: if ($i + 2 < $l &&
686: (($s[$i + 2] >= '0' && $s[$i + 2] <= '9') || ($s[$i + 2] >= 'a' && $s[$i + 2] <= 'f') || ($s[$i + 2] >= 'A' && $s[$i + 2] <= 'F')))
687: {
688: if ($i + 3 < $l &&
689: (($s[$i + 3] >= '0' && $s[$i + 3] <= '9') || ($s[$i + 3] >= 'a' && $s[$i + 3] <= 'f') || ($s[$i + 3] >= 'A' && $s[$i + 3] <= 'F')))
690: {
691: try{
692: $buffer .= chr(substr($s, $i, 4));
693: $i += 4;
694: continue;
695:
696: } catch (Exception $ex) {
697: throw new Exception("Invalid hex notation in the specified printer commands at index: ".$i);
698: }
699:
700:
701: }
702: else
703: {
704: try{
705:
706: $buffer .= chr(substr($s, $i, 3));
707: $i += 3;
708: continue;
709:
710: } catch (Exception $ex) {
711: throw new ArgumentException("Invalid hex notation in the specified printer commands at index: ".$i);
712: }
713: }
714: }
715: }
716: }
717:
718: $buffer .= substr($s, $i, 1);
719:
720: $i++;
721: }
722:
723: return $buffer;
724:
725: }
726:
727: public static function intToArray($i){
728: return pack("L", $i);
729: }
730:
731: public static function strleft($s1, $s2) {
732: return substr($s1, 0, strpos($s1, $s2));
733: }
734:
735: public static function strContains($s1, $s2){
736: return (strpos($s1, $s2) !== false);
737: }
738:
739: public static function strEndsWith($s1, $s2)
740: {
741: return substr($s1, -strlen($s2)) === $s2;
742: }
743:
744: public static function strStartsWith($s1, $s2)
745: {
746: return substr($s1, 0, strlen($s2)) === $s2;
747: }
748:
749: }
750:
751: 752: 753:
754: class ClientPrintJob{
755:
756: 757: 758: 759: 760: 761: 762: 763: 764: 765:
766: public $clientPrinter = null;
767: 768: 769: 770:
771: public $printerCommands = '';
772: 773: 774: 775: 776: 777: 778:
779: public $printerCommandsCopies = 1;
780: 781: 782: 783: 784: 785: 786: 787: 788:
789: public $formatHexValues = false;
790: 791: 792: 793:
794: public $printFile = null;
795: 796: 797: 798:
799: public $printFileGroup = null;
800:
801:
802: 803: 804: 805: 806:
807: public function sendToClient(){
808:
809: $cpjHeader = chr(99).chr(112).chr(106).chr(2);
810:
811: $buffer = '';
812:
813: if (!Utils::isNullOrEmptyString($this->printerCommands)){
814: if ($this->printerCommandsCopies > 1){
815: $buffer .= 'PCC='.$this->printerCommandsCopies.Utils::SER_SEP;
816: }
817: if($this->formatHexValues){
818: $buffer .= Utils::formatHexValues ($this->printerCommands);
819: } else {
820: $buffer .= $this->printerCommands;
821: }
822: } else if (isset ($this->printFile)){
823: $buffer = $this->printFile->serialize();
824: } else if (isset ($this->printFileGroup)){
825: $buffer = 'wcpPFG:';
826: $zip = new ZipArchive;
827: $cacheFileName = (Utils::strEndsWith(WebClientPrint::$wcpCacheFolder, '/')?WebClientPrint::$wcpCacheFolder:WebClientPrint::$wcpCacheFolder.'/').'PFG'.uniqid().'.zip';
828: $res = $zip->open($cacheFileName, ZipArchive::CREATE);
829: if ($res === TRUE) {
830: foreach ($this->printFileGroup as $printFile) {
831: $file = $printFile->fileName;
832: if($printFile->copies > 1){
833: $pfc = 'PFC='.$printFile->copies;
834: $file = substr($file, 0, strrpos($file, '.')).$pfc.substr($file, strrpos($file, '.'));
835: }
836: $zip->addFromString($file, $printFile->getFileContent());
837: }
838: $zip->close();
839: $handle = fopen($cacheFileName, 'rb');
840: $buffer .= fread($handle, filesize($cacheFileName));
841: fclose($handle);
842: unlink($cacheFileName);
843: } else {
844: $buffer='Creating PrintFileGroup failed. Cannot create zip file.';
845: }
846: }
847:
848: $arrIdx1 = Utils::intToArray(strlen($buffer));
849:
850: if (!isset($this->clientPrinter)){
851: $this->clientPrinter = new UserSelectedPrinter();
852: }
853:
854: $buffer .= $this->clientPrinter->serialize();
855:
856: $arrIdx2 = Utils::intToArray(strlen($buffer));
857:
858: $lo = '';
859: if(Utils::isNullOrEmptyString(WebClientPrint::$licenseOwner)){
860: $lo = substr(uniqid(), 0, 8);
861: } else {
862: $lo = 'php>'.base64_encode(WebClientPrint::$licenseOwner);
863: }
864: $lk = '';
865: if(Utils::isNullOrEmptyString(WebClientPrint::$licenseKey)){
866: $lk = substr(uniqid(), 0, 8);
867: } else {
868: $lk = WebClientPrint::$licenseKey;
869: }
870: $buffer .= $lo.chr(124).$lk;
871:
872: return $cpjHeader.$arrIdx1.$arrIdx2.$buffer;
873: }
874:
875: }
876:
877: 878: 879:
880: class ClientPrintJobGroup{
881:
882: 883: 884: 885:
886: public $clientPrintJobGroup = null;
887:
888: 889: 890: 891: 892:
893: public function sendToClient(){
894:
895: if (isset ($this->clientPrintJobGroup)){
896: $groups = count($this->clientPrintJobGroup);
897:
898: $dataPartIndexes = Utils::intToArray(strlen($groups));
899:
900: $cpjgHeader = chr(99).chr(112).chr(106).chr(103).chr(2);
901:
902: $buffer = '';
903:
904: $cpjBytesCount = 0;
905:
906: foreach ($this->clientPrintJobGroup as $cpj) {
907: $cpjBuffer = '';
908:
909: if (!Utils::isNullOrEmptyString($cpj->printerCommands)){
910: if ($cpj->printerCommandsCopies > 1){
911: $cpjBuffer .= 'PCC='.$cpj->printerCommandsCopies.Utils::SER_SEP;
912: }
913: if($cpj->formatHexValues){
914: $cpjBuffer .= Utils::formatHexValues ($cpj->printerCommands);
915: } else {
916: $cpjBuffer .= $cpj->printerCommands;
917: }
918: } else if (isset ($cpj->printFile)){
919: $cpjBuffer = $cpj->printFile->serialize();
920: } else if (isset ($cpj->printFileGroup)){
921: $cpjBuffer = 'wcpPFG:';
922: $zip = new ZipArchive;
923: $cacheFileName = (Utils::strEndsWith(WebClientPrint::$wcpCacheFolder, '/')?WebClientPrint::$wcpCacheFolder:WebClientPrint::$wcpCacheFolder.'/').'PFG'.uniqid().'.zip';
924: $res = $zip->open($cacheFileName, ZipArchive::CREATE);
925: if ($res === TRUE) {
926: foreach ($cpj->printFileGroup as $printFile) {
927: $file = $printFile->fileName;
928: if($printFile->copies > 1){
929: $pfc = 'PFC='.$printFile->copies;
930: $file = substr($file, 0, strrpos($file, '.')).$pfc.substr($file, strrpos($file, '.'));
931: }
932: $zip->addFromString($file, $printFile->getFileContent());
933: }
934: $zip->close();
935: $handle = fopen($cacheFileName, 'rb');
936: $cpjBuffer .= fread($handle, filesize($cacheFileName));
937: fclose($handle);
938: unlink($cacheFileName);
939: } else {
940: $cpjBuffer='Creating PrintFileGroup failed. Cannot create zip file.';
941: }
942: }
943:
944: $arrIdx1 = Utils::intToArray(strlen($cpjBuffer));
945:
946: if (!isset($cpj->clientPrinter)){
947: $cpj->clientPrinter = new UserSelectedPrinter();
948: }
949:
950: $cpjBuffer .= $cpj->clientPrinter->serialize();
951:
952: $cpjBytesCount += strlen($cpjBuffer);
953:
954: $dataPartIndexes .= Utils::intToArray(strlen($cpjBytesCount));
955:
956: $buffer .= $arrIdx1.$cpjBuffer;
957: }
958:
959:
960: $lo = '';
961: if(Utils::isNullOrEmptyString(WebClientPrint::$licenseOwner)){
962: $lo = substr(uniqid(), 0, 8);
963: } else {
964: $lo = 'php>'.base64_encode(WebClientPrint::$licenseOwner);
965: }
966: $lk = '';
967: if(Utils::isNullOrEmptyString(WebClientPrint::$licenseKey)){
968: $lk = substr(uniqid(), 0, 8);
969: } else {
970: $lk = WebClientPrint::$licenseKey;
971: }
972: $buffer .= $lo.chr(124).$lk;
973:
974: return $cpjgHeader.$dataPartIndexes.$buffer;
975:
976:
977: } else {
978:
979: return NULL;
980: }
981:
982:
983: }
984: }
985:
986: return '';