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: WebClientPrint::$webClientPrintAbsoluteUrl = Utils::getRoot().'/wcpdev/source/WebClientPrint.php';
15:
16:
17: WebClientPrint::$wcpCacheFolder = 'wcpcache/';
18:
19:
20:
21:
22: WebClientPrint::cacheClean(5);
23:
24:
25: $urlParts = parse_url($_SERVER['REQUEST_URI']);
26: if (isset($urlParts['query'])){
27: if (Utils::strContains($urlParts['query'], WebClientPrint::WCP)){
28: WebClientPrint::processRequest($urlParts['query']);
29: }
30: }
31:
32:
33: 34: 35: 36: 37: 38: 39: 40: 41:
42: class WebClientPrint {
43:
44: const VERSION = '2.0.0.0';
45: const CLIENT_PRINT_JOB = "clientPrint";
46: const WCP = 'WEB_CLIENT_PRINT';
47:
48: const WCP_CACHE_WCPP_INSTALLED = 'WCPP_INSTALLED';
49: const WCP_CACHE_WCPP_VER = 'WCPP_VER';
50: const WCP_CACHE_PRINTERS = 'PRINTERS';
51:
52: 53: 54: 55:
56: static $licenseOwner = '';
57: 58: 59: 60:
61: static $licenseKey = '';
62: 63: 64: 65:
66: static $webClientPrintAbsoluteUrl = '';
67: 68: 69: 70: 71:
72: static $wcpCacheFolder = '';
73:
74: 75: 76: 77: 78: 79: 80:
81: public static function cacheAdd($sid, $key, $val){
82: if (Utils::isNullOrEmptyString(self::$wcpCacheFolder)){
83: throw new Exception('WebClientPrint wcpCacheFolder is missing, please specify it.');
84: }
85: if (Utils::isNullOrEmptyString($sid)){
86: throw new Exception('WebClientPrint FileName cache is missing, please specify it.');
87: }
88: $cacheFileName = (Utils::strEndsWith(self::$wcpCacheFolder, '/')?self::$wcpCacheFolder:self::$wcpCacheFolder.'/').$sid.'.wcpcache';
89: $dataWCPP_VER = '';
90: $dataPRINTERS = '';
91:
92: if(file_exists($cacheFileName)){
93: $cache_info = parse_ini_file($cacheFileName);
94:
95: $dataWCPP_VER = $cache_info[self::WCP_CACHE_WCPP_VER];
96: $dataPRINTERS = $cache_info[self::WCP_CACHE_PRINTERS];
97: }
98:
99: if ($key === self::WCP_CACHE_WCPP_VER){
100: $dataWCPP_VER = self::WCP_CACHE_WCPP_VER.'='.'"'.$val.'"';
101: $dataPRINTERS = self::WCP_CACHE_PRINTERS.'='.'"'.$dataPRINTERS.'"';
102: } else if ($key === self::WCP_CACHE_PRINTERS){
103: $dataWCPP_VER = self::WCP_CACHE_WCPP_VER.'='.'"'.$dataWCPP_VER.'"';
104: $dataPRINTERS = self::WCP_CACHE_PRINTERS.'='.'"'.$val.'"';
105: }
106:
107: $data = $dataWCPP_VER.chr(13).chr(10).$dataPRINTERS;
108: $handle = fopen($cacheFileName, 'w') or die('Cannot open file: '.$cacheFileName);
109: fwrite($handle, $data);
110: fclose($handle);
111:
112: }
113:
114: 115: 116: 117: 118: 119: 120:
121: public static function cacheGet($sid, $key){
122: if (Utils::isNullOrEmptyString(self::$wcpCacheFolder)){
123: throw new Exception('WebClientPrint wcpCacheFolder is missing, please specify it.');
124: }
125: if (Utils::isNullOrEmptyString($sid)){
126: throw new Exception('WebClientPrint FileName cache is missing, please specify it.');
127: }
128: $cacheFileName = (Utils::strEndsWith(self::$wcpCacheFolder, '/')?self::$wcpCacheFolder:self::$wcpCacheFolder.'/').$sid.'.wcpcache';
129: if(file_exists($cacheFileName)){
130: $cache_info = parse_ini_file($cacheFileName);
131:
132: if($key===self::WCP_CACHE_WCPP_VER || $key===self::WCP_CACHE_WCPP_INSTALLED){
133: return $cache_info[self::WCP_CACHE_WCPP_VER];
134: }else if($key===self::WCP_CACHE_PRINTERS){
135: return $cache_info[self::WCP_CACHE_PRINTERS];
136: }else{
137: return '';
138: }
139: }else{
140: return '';
141: }
142: }
143:
144: 145: 146: 147:
148: public static function cacheClean($minutes){
149: if (!Utils::isNullOrEmptyString(self::$wcpCacheFolder)){
150: $cacheDir = (Utils::strEndsWith(self::$wcpCacheFolder, '/')?self::$wcpCacheFolder:self::$wcpCacheFolder.'/');
151: if ($handle = opendir($cacheDir)) {
152: while (false !== ($file = readdir($handle))) {
153: if ($file!='.' && $file!='..' && (time()-filectime($cacheDir.$file)) > (60*$minutes)) {
154: unlink($cacheDir.$file);
155: }
156: }
157: closedir($handle);
158: }
159: }
160: }
161:
162: 163: 164: 165: 166: 167: 168: 169: 170: 171: 172: 173: 174: 175: 176: 177: 178:
179: public static function createWcppDetectionScript(){
180:
181: if (Utils::isNullOrEmptyString(self::$webClientPrintAbsoluteUrl)){
182: throw new Exception('WebClientPrint absolute URL is missing, please specify it.');
183: }
184:
185: $buffer = '<script type="text/javascript">';
186: if(Utils::isIE6to9() || Utils::isIE10orGreater()){
187: $buffer .= 'var wcppPingNow=false;';
188: } else {
189: $buffer .= 'var wcppPingNow=true;';
190: }
191: $buffer .= '</script>';
192:
193: $wcpHandler = self::$webClientPrintAbsoluteUrl.'?'.self::WCP.'&d='.session_id();
194: $buffer .= '<script src="'.$wcpHandler.'" type="text/javascript"></script>';
195:
196: if(Utils::isIE6to9() || Utils::isIE10orGreater()){
197: $crlf = chr(13).chr(10);
198: $buffer .= $crlf.$crlf;
199: $buffer .= '<!--[if WCPP]>'.$crlf;
200: $buffer .= '<script type="text/javascript">'.$crlf;
201: $buffer .= '$(document).ready(function(){jsWCPP.ping();});'.$crlf;
202: $buffer .= '</script>'.$crlf;
203: $buffer .= '<![endif]-->'.$crlf;
204: $buffer .= '<!--[if !WCPP]>'.$crlf;
205: $buffer .= '<script type="text/javascript">'.$crlf;
206: $buffer .= '$(document).ready(function(){wcppDetectOnFailure();});'.$crlf;
207: $buffer .= '</script>'.$crlf;
208: $buffer .= '<![endif]-->'.$crlf;
209: }
210:
211: return $buffer;
212: }
213:
214: 215: 216: 217: 218: 219: 220: 221: 222:
223: public static function getWcppDetectionMetaTag(){
224: return Utils::isIE10orGreater()?'<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9" />':'';
225: }
226:
227: 228: 229: 230: 231: 232: 233: 234:
235: public static function createScript($clientPrintJobUrl){
236: if (Utils::isNullOrEmptyString(self::$webClientPrintAbsoluteUrl)){
237: throw new Exception('WebClientPrint absolute URL is missing, please specify it.');
238: }
239: $wcpHandler = self::$webClientPrintAbsoluteUrl.'?';
240: $wcpHandler .= self::WCP;
241: $wcpHandler .= '&';
242: $wcpHandler .= self::VERSION;
243: $wcpHandler .= '&';
244: $wcpHandler .= microtime(true);
245: $wcpHandler .= '&u=';
246: $wcpHandler .= base64_encode($clientPrintJobUrl);
247: return '<script src="'.$wcpHandler.'" type="text/javascript"></script>';
248: }
249:
250: public static function processRequest($data){
251:
252: $PING = 'wcppping';
253: $SID = 'sid';
254: $HAS_WCPP = 'wcppInstalled';
255:
256: $GEN_WCP_SCRIPT_VERSION = 'v2.0.0.0';
257: $GEN_WCP_SCRIPT_URL = 'u';
258: $GEN_DETECT_WCPP_SCRIPT = 'd';
259: $WCP_SCRIPT_AXD_GET_PRINTERS = 'getPrinters';
260: $WCPP_SET_PRINTERS = 'printers';
261: $WCP_SCRIPT_AXD_GET_WCPPVERSION = 'getWcppVersion';
262: $WCPP_SET_VERSION = 'wcppVer';
263:
264: $wcpUrl=Utils::getRoot().$_SERVER['REQUEST_URI'];
265: $wcpUrl=substr($wcpUrl, 0, strpos($wcpUrl, '.php?')+4);
266:
267: parse_str($data, $qs);
268:
269: if(isset($qs[$SID])){
270: if(isset($qs[$PING])){
271: if (isset($qs[$WCPP_SET_VERSION])){
272: self::cacheAdd($qs[$SID], self::WCP_CACHE_WCPP_VER, $qs[$WCPP_SET_VERSION]);
273: }else{
274: self::cacheAdd($qs[$SID], self::WCP_CACHE_WCPP_VER,'1.0.0.0');
275: }
276: }else if(isset($qs[$WCPP_SET_PRINTERS])){
277: self::cacheAdd($qs[$SID], self::WCP_CACHE_PRINTERS, strlen($qs[$WCPP_SET_PRINTERS]) > 0 ? base64_decode($qs[$WCPP_SET_PRINTERS]) : '');
278: }else if(strpos($data, $WCP_SCRIPT_AXD_GET_PRINTERS)>0){
279: ob_clean();
280: header('Content-type: text/plain');
281: echo self::cacheGet($qs[$SID], self::WCP_CACHE_PRINTERS);
282: }else if(isset($qs[$WCPP_SET_VERSION])){
283: if(strlen($qs[$WCPP_SET_VERSION]) > 0){
284: self::cacheAdd($qs[$SID], self::WCP_CACHE_WCPP_VER, $qs[$WCPP_SET_VERSION]);
285: }
286: }else if(strpos($data, $WCP_SCRIPT_AXD_GET_WCPPVERSION)>0){
287: ob_clean();
288: header('Content-type: text/plain');
289: echo self::cacheGet($qs[$SID], self::WCP_CACHE_WCPP_VER);
290: }else{
291: ob_clean();
292: header('Content-type: text/plain');
293: echo self::cacheGet($qs[$SID], self::WCP_CACHE_WCPP_INSTALLED);
294: }
295: }else if(isset($qs[$GEN_DETECT_WCPP_SCRIPT])){
296:
297: $curSID = $qs[$GEN_DETECT_WCPP_SCRIPT];
298: $onSuccessScript = 'wcppDetectOnSuccess(data);';
299: $onFailureScript = 'wcppDetectOnFailure();';
300: $dynamicIframeId = 'i'.substr(uniqid(), 0, 3);
301: $absoluteWcpAxd = $wcpUrl.'?'.self::WCP.'&'.$SID.'='.$curSID;
302:
303: $s1 = 'dmFyIGpzV0NQUD0oZnVuY3Rpb24oKXt2YXIgc2V0WFhYLU5FTy1IVE1MLUlELVhYWD1mdW5jdGlvbigpe2lmKHdpbmRvdy5jaHJvbWUpeyQoJyNYWFgtTkVPLUhUTUwtSUQtWFhYJykuYXR0cignaHJlZicsJ3dlYmNsaWVudHByaW50OicrYXJndW1lbnRzWzBdKTt2YXIgYT0kKCdhI1hYWC1ORU8tSFRNTC1JRC1YWFgnKVswXTt2YXIgZXZPYmo9ZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ01vdXNlRXZlbnRzJyk7ZXZPYmouaW5pdEV2ZW50KCdjbGljaycsdHJ1ZSx0cnVlKTthLmRpc3BhdGNoRXZlbnQoZXZPYmopfWVsc2V7JCgnI1hYWC1ORU8tSFRNTC1JRC1YWFgnKS5hdHRyKCdzcmMnLCd3ZWJjbGllbnRwcmludDonK2FyZ3VtZW50c1swXSl9fTtyZXR1cm57aW5pdDpmdW5jdGlvbigpe2lmKHdpbmRvdy5jaHJvbWUpeyQoJzxhIC8+Jyx7aWQ6J1hYWC1ORU8tSFRNTC1JRC1YWFgnfSkuYXBwZW5kVG8oJ2JvZHknKX1lbHNleyQoJzxpZnJhbWUgLz4nLHtuYW1lOidYWFgtTkVPLUhUTUwtSUQtWFhYJyxpZDonWFhYLU5FTy1IVE1MLUlELVhYWCcsd2lkdGg6JzEnLGhlaWdodDonMScsc3R5bGU6J3Zpc2liaWxpdHk6aGlkZGVuO3Bvc2l0aW9uOmFic29sdXRlJ30pLmFwcGVuZFRvKCdib2R5Jyl9fSxwaW5nOmZ1bmN0aW9uKCl7c2V0WFhYLU5FTy1IVE1MLUlELVhYWCgnWFhYLU5FTy1QSU5HLVVSTC1YWFgnKyhhcmd1bWVudHMubGVuZ3RoPT0xPycmJythcmd1bWVudHNbMF06JycpKTt2YXIgZGVsYXlfbXM9KHR5cGVvZiB3Y3BwUGluZ0RlbGF5X21zPT09J3VuZGVmaW5lZCcpPzEwMDAwOndjcHBQaW5nRGVsYXlfbXM7c2V0VGltZW91dChmdW5jdGlvbigpeyQuZ2V0KCdYWFgtTkVPLVVTRVItSEFTLVdDUFAtWFhYJyxmdW5jdGlvbihkYXRhKXtpZihkYXRhIT0nZicpe1hYWC1ORU8tT04tU1VDQ0VTUy1TQ1JJUFQtWFhYfWVsc2V7WFhYLU5FTy1PTi1GQUlMVVJFLVNDUklQVC1YWFh9fSl9LGRlbGF5X21zKX19fSkoKTsgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKXtqc1dDUFAuaW5pdCgpO2lmKHdjcHBQaW5nTm93KWpzV0NQUC5waW5nKCk7fSk7';
304: $s2 = base64_decode($s1);
305: $s2 = str_replace('XXX-NEO-HTML-ID-XXX', $dynamicIframeId, $s2);
306: $s2 = str_replace('XXX-NEO-PING-URL-XXX', $absoluteWcpAxd.'&'.$PING, $s2);
307: $s2 = str_replace('XXX-NEO-USER-HAS-WCPP-XXX', $absoluteWcpAxd, $s2);
308: $s2 = str_replace('XXX-NEO-ON-SUCCESS-SCRIPT-XXX', $onSuccessScript, $s2);
309: $s2 = str_replace('XXX-NEO-ON-FAILURE-SCRIPT-XXX', $onFailureScript, $s2);
310:
311: ob_clean();
312: header('Content-type: application/javascript');
313: echo $s2;
314:
315: }else if(isset($qs[$GEN_WCP_SCRIPT_URL])){
316:
317: $clientPrintJobUrl = base64_decode($qs[$GEN_WCP_SCRIPT_URL]);
318: if (strpos($clientPrintJobUrl, '?')>0){
319: $clientPrintJobUrl .= '&';
320: }else{
321: $clientPrintJobUrl .= '?';
322: }
323: $clientPrintJobUrl .= self::CLIENT_PRINT_JOB;
324: $absoluteWcpAxd = $wcpUrl;
325: $wcppGetPrintersParam = '-getPrinters:'.$absoluteWcpAxd.'?'.self::WCP.'&'.$SID.'=';
326: $wcpHandlerGetPrinters = $absoluteWcpAxd.'?'.self::WCP.'&'.$WCP_SCRIPT_AXD_GET_PRINTERS.'&'.$SID.'=';
327: $wcppGetWcppVerParam = '-getWcppVersion:'.$absoluteWcpAxd.'?'.self::WCP.'&'.$SID.'=';
328: $wcpHandlerGetWcppVer = $absoluteWcpAxd.'?'.self::WCP.'&'.$WCP_SCRIPT_AXD_GET_WCPPVERSION.'&'.$SID.'=';
329:
330: $s1 = 'dmFyIGpzV2ViQ2xpZW50UHJpbnQ9KGZ1bmN0aW9uKCl7dmFyIHNldEE9ZnVuY3Rpb24oKXt2YXIgZV9pZD0naWRfJytuZXcgRGF0ZSgpLmdldFRpbWUoKTtpZih3aW5kb3cuY2hyb21lKXskKCdib2R5JykuYXBwZW5kKCc8YSBpZD0iJytlX2lkKyciPjwvYT4nKTskKCcjJytlX2lkKS5hdHRyKCdocmVmJywnd2ViY2xpZW50cHJpbnQ6Jythcmd1bWVudHNbMF0pO3ZhciBhPSQoJ2EjJytlX2lkKVswXTt2YXIgZXZPYmo9ZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ01vdXNlRXZlbnRzJyk7ZXZPYmouaW5pdEV2ZW50KCdjbGljaycsdHJ1ZSx0cnVlKTthLmRpc3BhdGNoRXZlbnQoZXZPYmopfWVsc2V7JCgnYm9keScpLmFwcGVuZCgnPGlmcmFtZSBuYW1lPSInK2VfaWQrJyIgaWQ9IicrZV9pZCsnIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBzdHlsZT0idmlzaWJpbGl0eTpoaWRkZW47cG9zaXRpb246YWJzb2x1dGUiIC8+Jyk7JCgnIycrZV9pZCkuYXR0cignc3JjJywnd2ViY2xpZW50cHJpbnQ6Jythcmd1bWVudHNbMF0pfXNldFRpbWVvdXQoZnVuY3Rpb24oKXskKCcjJytlX2lkKS5yZW1vdmUoKX0sNTAwMCl9O3JldHVybntwcmludDpmdW5jdGlvbigpe3NldEEoJ1VSTF9QUklOVF9KT0InKyhhcmd1bWVudHMubGVuZ3RoPT0xPycmJythcmd1bWVudHNbMF06JycpKX0sZ2V0UHJpbnRlcnM6ZnVuY3Rpb24oKXtzZXRBKCdVUkxfV0NQX0FYRF9XSVRIX0dFVF9QUklOVEVSU19DT01NQU5EJyskKCcjc2lkJykudmFsKCkpO3ZhciBkZWxheV9tcz0odHlwZW9mIHdjcHBHZXRQcmludGVyc0RlbGF5X21zPT09J3VuZGVmaW5lZCcpPzEwMDAwOndjcHBHZXRQcmludGVyc0RlbGF5X21zO3NldFRpbWVvdXQoZnVuY3Rpb24oKXskLmdldCgnVVJMX1dDUF9BWERfR0VUX1BSSU5URVJTJyskKCcjc2lkJykudmFsKCksZnVuY3Rpb24oZGF0YSl7aWYoZGF0YS5sZW5ndGg+MCl7d2NwR2V0UHJpbnRlcnNPblN1Y2Nlc3MoZGF0YSl9ZWxzZXt3Y3BHZXRQcmludGVyc09uRmFpbHVyZSgpfX0pfSxkZWxheV9tcyl9LGdldFdjcHBWZXI6ZnVuY3Rpb24oKXtzZXRBKCdVUkxfV0NQX0FYRF9XSVRIX0dFVF9XQ1BQVkVSU0lPTl9DT01NQU5EJyskKCcjc2lkJykudmFsKCkpO3ZhciBkZWxheV9tcz0odHlwZW9mIHdjcHBHZXRWZXJEZWxheV9tcz09PSd1bmRlZmluZWQnKT8xMDAwMDp3Y3BwR2V0VmVyRGVsYXlfbXM7c2V0VGltZW91dChmdW5jdGlvbigpeyQuZ2V0KCdVUkxfV0NQX0FYRF9HRVRfV0NQUFZFUlNJT04nKyQoJyNzaWQnKS52YWwoKSxmdW5jdGlvbihkYXRhKXtpZihkYXRhLmxlbmd0aD4wKXt3Y3BHZXRXY3BwVmVyT25TdWNjZXNzKGRhdGEpfWVsc2V7d2NwR2V0V2NwcFZlck9uRmFpbHVyZSgpfX0pfSxkZWxheV9tcyl9LHNlbmQ6ZnVuY3Rpb24oKXtzZXRBLmFwcGx5KHRoaXMsYXJndW1lbnRzKX19fSkoKTs=';
331: $s2 = base64_decode($s1);
332: $s2 = str_replace('URL_PRINT_JOB', $clientPrintJobUrl, $s2);
333: $s2 = str_replace('URL_WCP_AXD_WITH_GET_PRINTERS_COMMAND', $wcppGetPrintersParam, $s2);
334: $s2 = str_replace('URL_WCP_AXD_GET_PRINTERS', $wcpHandlerGetPrinters, $s2);
335: $s2 = str_replace('URL_WCP_AXD_WITH_GET_WCPPVERSION_COMMAND', $wcppGetWcppVerParam, $s2);
336: $s2 = str_replace('URL_WCP_AXD_GET_WCPPVERSION', $wcpHandlerGetWcppVer, $s2);
337:
338: ob_clean();
339: header('Content-type: application/javascript');
340: echo $s2;
341: }
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 function __construct($printerName) {
387: $this->printerId = chr(1);
388: $this->printerName = $printerName;
389: }
390:
391:
392: public function serialize() {
393:
394: if (Utils::isNullOrEmptyString($this->printerName)){
395: throw new Exception("The specified printer name is null or empty.");
396: }
397:
398: return $this->printerId.$this->printerName;
399: }
400: }
401:
402: 403: 404:
405: class ParallelPortPrinter extends ClientPrinter{
406:
407: 408: 409: 410:
411: public $portName = "LPT1";
412:
413: 414: 415: 416:
417: public function __construct($portName) {
418: $this->printerId = chr(2);
419: $this->portName = $portName;
420: }
421:
422: public function serialize() {
423:
424: if (Utils::isNullOrEmptyString($this->portName)){
425: throw new Exception("The specified parallel port name is null or empty.");
426: }
427:
428: return $this->printerId.$this->portName;
429: }
430: }
431:
432: 433: 434:
435: class SerialPortPrinter extends ClientPrinter{
436:
437: 438: 439: 440:
441: public $portName = "COM1";
442: 443: 444: 445:
446: public $baudRate = 9600;
447: 448: 449: 450: 451:
452: public $parity = SerialPortParity::NONE;
453: 454: 455: 456: 457:
458: public $stopBits = SerialPortStopBits::ONE;
459: 460: 461: 462:
463: public $dataBits = 8;
464: 465: 466: 467: 468:
469: public $flowControl = SerialPortHandshake::XON_XOFF;
470:
471: 472: 473: 474: 475: 476: 477: 478: 479:
480: public function __construct($portName, $baudRate, $parity, $stopBits, $dataBits, $flowControl) {
481: $this->printerId = chr(3);
482: $this->portName = $portName;
483: $this->baudRate = $baudRate;
484: $this->parity = $parity;
485: $this->stopBits = $stopBits;
486: $this->dataBits = $dataBits;
487: $this->flowControl = $flowControl;
488: }
489:
490: public function serialize() {
491:
492: if (Utils::isNullOrEmptyString($this->portName)){
493: throw new Exception("The specified serial port name is null or empty.");
494: }
495:
496: 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;
497: }
498: }
499:
500: 501: 502:
503: class NetworkPrinter extends ClientPrinter{
504:
505: 506: 507: 508:
509: public $dnsName = "";
510: 511: 512: 513:
514: public $ipAddress = "";
515: 516: 517: 518:
519: public $port = 0;
520:
521: 522: 523: 524: 525: 526:
527: public function __construct($dnsName, $ipAddress, $port) {
528: $this->printerId = chr(4);
529: $this->dnsName = $dnsName;
530: $this->ipAddress = $ipAddress;
531: $this->port = $port;
532: }
533:
534: public function serialize() {
535:
536: if (Utils::isNullOrEmptyString($this->dnsName) && Utils::isNullOrEmptyString($this->ipAddress)){
537: throw new Exception("The specified network printer settings is not valid. You must specify the DNS Printer Name or its IP address.");
538: }
539:
540: return $this->printerId.$this->dnsName.Utils::SER_SEP.$this->ipAddress.Utils::SER_SEP.$this->port;
541: }
542: }
543:
544: 545: 546:
547: class UserSelectedPrinter extends ClientPrinter{
548: public function __construct() {
549: $this->printerId = chr(5);
550: }
551:
552: public function serialize() {
553: return $this->printerId;
554: }
555: }
556:
557: 558: 559:
560: class SerialPortParity{
561: const NONE = 0;
562: const ODD = 1;
563: const EVEN = 2;
564: const MARK = 3;
565: const SPACE = 4;
566: }
567:
568: 569: 570:
571: class SerialPortStopBits{
572: const NONE = 0;
573: const ONE = 1;
574: const TWO = 2;
575: const ONE_POINT_FIVE = 3;
576: }
577:
578: 579: 580:
581: class SerialPortHandshake{
582: const NONE = 0;
583: const REQUEST_TO_SEND = 2;
584: const REQUEST_TO_SEND_XON_XOFF = 3;
585: const XON_XOFF = 1;
586: }
587:
588: 589: 590:
591: class PrintFile{
592:
593: 594: 595: 596:
597: public $filePath = '';
598: 599: 600: 601: 602:
603: public $fileName = '';
604: 605: 606: 607:
608: public $fileBinaryContent = '';
609:
610: const PREFIX = 'wcpPF:';
611: const SEP = '|';
612:
613: 614: 615: 616: 617: 618:
619: public function __construct($filePath, $fileName, $fileBinaryContent) {
620: $this->filePath = $filePath;
621: $this->fileName = $fileName;
622: $this->fileBinaryContent = $fileBinaryContent;
623:
624: }
625:
626: public function serialize() {
627: return self::PREFIX.$this->fileName.self::SEP.$this->getFileContent();
628: }
629:
630: public function getFileContent(){
631: $content = $this->fileBinaryContent;
632: if(!Utils::isNullOrEmptyString($this->filePath)){
633: $handle = fopen($this->filePath, 'rb');
634: $content = fread($handle, filesize($this->filePath));
635: fclose($handle);
636: }
637: return $content;
638: }
639: }
640:
641: 642: 643:
644: class Utils{
645: const SER_SEP = "|";
646:
647: static function isNullOrEmptyString($s){
648: return (!isset($s) || trim($s)==='');
649: }
650:
651: static function formatHexValues($s){
652:
653: $buffer = '';
654:
655: $l = strlen($s);
656: $i = 0;
657:
658: while ($i < $l)
659: {
660: if ($s[$i] == '0')
661: {
662: if ($i + 1 < $l && ($s[$i] == '0' && $s[$i + 1] == 'x'))
663: {
664: if ($i + 2 < $l &&
665: (($s[$i + 2] >= '0' && $s[$i + 2] <= '9') || ($s[$i + 2] >= 'a' && $s[$i + 2] <= 'f') || ($s[$i + 2] >= 'A' && $s[$i + 2] <= 'F')))
666: {
667: if ($i + 3 < $l &&
668: (($s[$i + 3] >= '0' && $s[$i + 3] <= '9') || ($s[$i + 3] >= 'a' && $s[$i + 3] <= 'f') || ($s[$i + 3] >= 'A' && $s[$i + 3] <= 'F')))
669: {
670: try{
671: $buffer .= chr(substr($s, $i, 4));
672: $i += 4;
673: continue;
674:
675: } catch (Exception $ex) {
676: throw new Exception("Invalid hex notation in the specified printer commands at index: ".$i);
677: }
678:
679:
680: }
681: else
682: {
683: try{
684:
685: $buffer .= chr(substr($s, $i, 3));
686: $i += 3;
687: continue;
688:
689: } catch (Exception $ex) {
690: throw new ArgumentException("Invalid hex notation in the specified printer commands at index: ".$i);
691: }
692: }
693: }
694: }
695: }
696:
697: $buffer .= substr($s, $i, 1);
698:
699: $i++;
700: }
701:
702: return $buffer;
703:
704: }
705:
706: public static function intToArray($i){
707: return pack("L", $i);
708: }
709:
710: public static function getRoot(){
711: $s = empty($_SERVER["HTTPS"]) ? '' : ($_SERVER["HTTPS"] == "on") ? "s" : "";
712: $protocol = static::strleft(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s;
713: $port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":".$_SERVER["SERVER_PORT"]);
714: return $protocol."://".$_SERVER['SERVER_NAME'].$port;
715: }
716:
717: public static function strleft($s1, $s2) {
718: return substr($s1, 0, strpos($s1, $s2));
719: }
720:
721: public static function strContains($s1, $s2){
722: return (strpos($s1, $s2) !== false);
723: }
724:
725: public static function strEndsWith($s1, $s2)
726: {
727: return substr($s1, -strlen($s2)) === $s2;
728: }
729:
730: public static function getUA(){
731: return $_SERVER['HTTP_USER_AGENT'];
732: }
733:
734: public static function isIE6to9(){
735: $ua = static::getUA();
736: return ((static::strContains($ua,"MSIE 6.") ||
737: static::strContains($ua,"MSIE 7.") ||
738: static::strContains($ua,"MSIE 8.") ||
739: static::strContains($ua,"MSIE 9.")) &&
740: static::strContains($ua,"Opera") === false);
741: }
742:
743: public static function isIE5orOlder(){
744: $ua = static::getUA();
745: return ((static::strContains($ua,"MSIE 5.") ||
746: static::strContains($ua,"MSIE 4.") ||
747: static::strContains($ua,"MSIE 3.") ||
748: static::strContains($ua,"MSIE 2.")) &&
749: static::strContains($ua,"Opera") === false);
750: }
751:
752: public static function isIE10orGreater(){
753: $ua = static::getUA();
754: return (static::strContains($ua,"MSIE") || static::strContains($ua,"Trident/")) && static::isIE6to9() === false && static::isIE5orOlder() === false && static::strContains($ua,"Opera") === false;
755: }
756:
757: }
758:
759: 760: 761:
762: class ClientPrintJob{
763:
764: 765: 766: 767: 768: 769: 770: 771: 772: 773:
774: public $clientPrinter = null;
775: 776: 777: 778:
779: public $printerCommands = '';
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: header('Content-type: application/octet-stream');
810:
811: $cpjHeader = chr(99).chr(112).chr(106).chr(2);
812:
813: $buffer = '';
814:
815: if (!Utils::isNullOrEmptyString($this->printerCommands)){
816: if($this->formatHexValues){
817: $buffer = Utils::formatHexValues ($this->printerCommands);
818: } else {
819: $buffer = $this->printerCommands;
820: }
821: } else if (isset ($this->printFile)){
822: $buffer = $this->printFile->serialize();
823: } else if (isset ($this->printFileGroup)){
824: $buffer = 'wcpPFG:';
825: $zip = new ZipArchive;
826: $cacheFileName = (Utils::strEndsWith(WebClientPrint::$wcpCacheFolder, '/')?WebClientPrint::$wcpCacheFolder:WebClientPrint::$wcpCacheFolder.'/').'PFG'.uniqid().'.zip';
827: $res = $zip->open($cacheFileName, ZipArchive::CREATE);
828: if ($res === TRUE) {
829: foreach ($this->printFileGroup as $printFile) {
830: $zip->addFromString($printFile->fileName, $printFile->getFileContent());
831: }
832: $zip->close();
833: $handle = fopen($cacheFileName, 'rb');
834: $buffer .= fread($handle, filesize($cacheFileName));
835: fclose($handle);
836: unlink($cacheFileName);
837: } else {
838: $buffer='Creating PrintFileGroup failed. Cannot create zip file.';
839: }
840: }
841:
842: $arrIdx1 = Utils::intToArray(strlen($buffer));
843:
844: if (!isset($this->clientPrinter)){
845: $this->clientPrinter = new UserSelectedPrinter();
846: }
847:
848: $buffer .= $this->clientPrinter->serialize();
849:
850: $arrIdx2 = Utils::intToArray(strlen($buffer));
851:
852: $lo = '';
853: if(Utils::isNullOrEmptyString(WebClientPrint::$licenseOwner)){
854: $lo = substr(uniqid(), 0, 8);
855: } else {
856: $lo = WebClientPrint::$licenseOwner;
857: }
858: $lk = '';
859: if(Utils::isNullOrEmptyString(WebClientPrint::$licenseKey)){
860: $lk = substr(uniqid(), 0, 8);
861: } else {
862: $lk = WebClientPrint::$licenseKey;
863: }
864: $buffer .= $lo.chr(124).$lk;
865:
866: return $cpjHeader.$arrIdx1.$arrIdx2.$buffer;
867: }
868:
869: }