1: <?php
2:
3: namespace Neodynamic\SDK\Web;
4: use Exception;
5: use ZipArchive;
6:
7:
8: include '/phpseclib/Math/BigInteger.php';
9: include '/phpseclib/Crypt/Hash.php';
10: include '/phpseclib/Crypt/Random.php';
11: include '/phpseclib/Crypt/Base.php';
12: include '/phpseclib/Crypt/RSA.php';
13: include '/phpseclib/Crypt/Rijndael.php';
14: include '/phpseclib/Crypt/AES.php';
15:
16:
17: WebClientPrint::$licenseOwner = '';
18: WebClientPrint::$licenseKey = '';
19:
20:
21:
22: WebClientPrint::$wcpCacheFolder = 'wcpcache/';
23:
24: 25: 26: 27: 28: 29: 30: 31: 32:
33: class WebClientPrint {
34:
35: const VERSION = '5.0.0.0';
36: const CLIENT_PRINT_JOB = 'clientPrint';
37: const WCP = 'WEB_CLIENT_PRINT';
38: const WCP_SCRIPT_AXD_GET_PRINTERS = 'getPrinters';
39: const WCP_SCRIPT_AXD_GET_PRINTERSINFO = 'getPrintersInfo';
40: const WCPP_SET_PRINTERS = 'printers';
41: const WCPP_SET_PRINTERSINFO = 'printersInfo';
42: const WCP_SCRIPT_AXD_GET_WCPPVERSION = 'getWcppVersion';
43: const WCPP_SET_VERSION = 'wcppVer';
44: const GEN_WCP_SCRIPT_URL = 'u';
45: const GEN_DETECT_WCPP_SCRIPT = 'd';
46: const SID = 'sid';
47: const PING = 'wcppping';
48:
49: const WCP_CACHE_WCPP_INSTALLED = 'WCPP_INSTALLED';
50: const WCP_CACHE_WCPP_VER = 'WCPP_VER';
51: const WCP_CACHE_PRINTERS = 'PRINTERS';
52: const WCP_CACHE_PRINTERSINFO = 'PRINTERSINFO';
53:
54:
55: 56: 57: 58:
59: static $licenseOwner = '';
60: 61: 62: 63:
64: static $licenseKey = '';
65: 66: 67: 68:
69: static $webClientPrintAbsoluteUrl = '';
70: 71: 72: 73: 74:
75: static $wcpCacheFolder = '';
76:
77: 78: 79: 80: 81: 82: 83:
84: public static function cacheAdd($sid, $key, $val){
85: if (Utils::isNullOrEmptyString(self::$wcpCacheFolder)){
86: throw new Exception('WebClientPrint wcpCacheFolder is missing, please specify it.');
87: }
88: if (Utils::isNullOrEmptyString($sid)){
89: throw new Exception('WebClientPrint FileName cache is missing, please specify it.');
90: }
91: $cacheFileName = (Utils::strEndsWith(self::$wcpCacheFolder, '/')?self::$wcpCacheFolder:self::$wcpCacheFolder.'/').$sid.'.wcpcache';
92: $dataWCPP_VER = '';
93: $dataPRINTERS = '';
94: $dataPRINTERSINFO = '';
95:
96: if(file_exists($cacheFileName)){
97: $cache_info = parse_ini_file($cacheFileName);
98:
99: $dataWCPP_VER = $cache_info[self::WCP_CACHE_WCPP_VER];
100: $dataPRINTERS = $cache_info[self::WCP_CACHE_PRINTERS];
101: $dataPRINTERSINFO = $cache_info[self::WCP_CACHE_PRINTERSINFO];
102: }
103:
104: if ($key === self::WCP_CACHE_WCPP_VER){
105: $dataWCPP_VER = self::WCP_CACHE_WCPP_VER.'='.'"'.$val.'"';
106: $dataPRINTERS = self::WCP_CACHE_PRINTERS.'='.'"'.$dataPRINTERS.'"';
107: $dataPRINTERSINFO = self::WCP_CACHE_PRINTERSINFO.'='.'"'.$dataPRINTERSINFO.'"';
108: } else if ($key === self::WCP_CACHE_PRINTERS){
109: $dataWCPP_VER = self::WCP_CACHE_WCPP_VER.'='.'"'.$dataWCPP_VER.'"';
110: $dataPRINTERS = self::WCP_CACHE_PRINTERS.'='.'"'.$val.'"';
111: $dataPRINTERSINFO = self::WCP_CACHE_PRINTERSINFO.'='.'"'.$dataPRINTERSINFO.'"';
112: } else if ($key === self::WCP_CACHE_PRINTERSINFO){
113: $dataWCPP_VER = self::WCP_CACHE_WCPP_VER.'='.'"'.$dataWCPP_VER.'"';
114: $dataPRINTERS = self::WCP_CACHE_PRINTERS.'='.'"'.$dataPRINTERS.'"';
115: $dataPRINTERSINFO = self::WCP_CACHE_PRINTERSINFO.'='.'"'.$val.'"';
116: }
117:
118: $data = $dataWCPP_VER.chr(13).chr(10).$dataPRINTERS.chr(13).chr(10).$dataPRINTERSINFO;
119: $handle = fopen($cacheFileName, 'w') or die('Cannot open file: '.$cacheFileName);
120: fwrite($handle, $data);
121: fclose($handle);
122:
123: }
124:
125: 126: 127: 128: 129: 130: 131:
132: public static function cacheGet($sid, $key){
133: if (Utils::isNullOrEmptyString(self::$wcpCacheFolder)){
134: throw new Exception('WebClientPrint wcpCacheFolder is missing, please specify it.');
135: }
136: if (Utils::isNullOrEmptyString($sid)){
137: throw new Exception('WebClientPrint FileName cache is missing, please specify it.');
138: }
139: $cacheFileName = (Utils::strEndsWith(self::$wcpCacheFolder, '/')?self::$wcpCacheFolder:self::$wcpCacheFolder.'/').$sid.'.wcpcache';
140: if(file_exists($cacheFileName)){
141: $cache_info = parse_ini_file($cacheFileName, FALSE, INI_SCANNER_RAW);
142:
143: if($key===self::WCP_CACHE_WCPP_VER || $key===self::WCP_CACHE_WCPP_INSTALLED){
144: return $cache_info[self::WCP_CACHE_WCPP_VER];
145: }else if($key===self::WCP_CACHE_PRINTERS){
146: return $cache_info[self::WCP_CACHE_PRINTERS];
147: }else if($key===self::WCP_CACHE_PRINTERSINFO){
148: return $cache_info[self::WCP_CACHE_PRINTERSINFO];
149: }else{
150: return '';
151: }
152: }else{
153: return '';
154: }
155: }
156:
157: 158: 159: 160:
161: public static function cacheClean($minutes){
162: if (!Utils::isNullOrEmptyString(self::$wcpCacheFolder)){
163: $cacheDir = (Utils::strEndsWith(self::$wcpCacheFolder, '/')?self::$wcpCacheFolder:self::$wcpCacheFolder.'/');
164: if ($handle = opendir($cacheDir)) {
165: while (false !== ($file = readdir($handle))) {
166: if ($file!='.' && $file!='..' && (time()-filectime($cacheDir.$file)) > (60*$minutes)) {
167: unlink($cacheDir.$file);
168: }
169: }
170: closedir($handle);
171: }
172: }
173: }
174:
175: 176: 177: 178: 179: 180: 181: 182: 183: 184: 185: 186: 187: 188: 189: 190: 191: 192: 193:
194: public static function createWcppDetectionScript($webClientPrintControllerAbsoluteUrl, $sessionID){
195:
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($sessionID)){
201: throw new Exception('Session ID is missing, please specify it.');
202: }
203:
204: $url = $webClientPrintControllerAbsoluteUrl.'?'.self::GEN_DETECT_WCPP_SCRIPT.'='.$sessionID;
205: return '<script src="'.$url.'" type="text/javascript"></script>';
206:
207: }
208:
209:
210: 211: 212: 213: 214: 215: 216: 217: 218: 219:
220: public static function createScript($webClientPrintControllerAbsoluteUrl, $clientPrintJobAbsoluteUrl, $sessionID){
221: if (Utils::isNullOrEmptyString($webClientPrintControllerAbsoluteUrl) ||
222: !Utils::strStartsWith($webClientPrintControllerAbsoluteUrl, 'http')){
223: throw new Exception('WebClientPrintController absolute URL is missing, please specify it.');
224: }
225: if (Utils::isNullOrEmptyString($clientPrintJobAbsoluteUrl) ||
226: !Utils::strStartsWith($clientPrintJobAbsoluteUrl, 'http')){
227: throw new Exception('ClientPrintJob absolute URL is missing, please specify it.');
228: }
229: if (Utils::isNullOrEmptyString($sessionID)){
230: throw new Exception('Session ID is missing, please specify it.');
231: }
232:
233:
234: $wcpHandler = $webClientPrintControllerAbsoluteUrl.'?';
235: $wcpHandler .= self::VERSION;
236: $wcpHandler .= '&';
237: $wcpHandler .= microtime(true);
238: $wcpHandler .= '&sid=';
239: $wcpHandler .= $sessionID;
240: $wcpHandler .= '&'.self::GEN_WCP_SCRIPT_URL.'=';
241: $wcpHandler .= base64_encode($clientPrintJobAbsoluteUrl);
242: return '<script src="'.$wcpHandler.'" type="text/javascript"></script>';
243: }
244:
245:
246: 247: 248: 249: 250: 251:
252: public static function generateScript($webClientPrintControllerAbsoluteUrl, $queryString)
253: {
254: if (Utils::isNullOrEmptyString($webClientPrintControllerAbsoluteUrl) ||
255: !Utils::strStartsWith($webClientPrintControllerAbsoluteUrl, 'http')){
256: throw new Exception('WebClientPrintController absolute URL is missing, please specify it.');
257: }
258:
259: parse_str($queryString, $qs);
260:
261: if(isset($qs[self::GEN_DETECT_WCPP_SCRIPT])){
262:
263: $curSID = $qs[self::GEN_DETECT_WCPP_SCRIPT];
264: $dynamicIframeId = 'i'.substr(uniqid(), 0, 3);
265: $absoluteWcpAxd = $webClientPrintControllerAbsoluteUrl.'?'.self::SID.'='.$curSID;
266:
267: $s1 = 'dmFyIGpzV0NQUD0oZnVuY3Rpb24oKXt2YXIgc2V0PDw8LU5FTy1IVE1MLUlELT4+Pj1mdW5jdGlvbigpe2lmKHdpbmRvdy5jaHJvbWUpeyQoJyM8PDwtTkVPLUhUTUwtSUQtPj4+JykuYXR0cignaHJlZicsJ3dlYmNsaWVudHByaW50djonK2FyZ3VtZW50c1swXSk7dmFyIGE9JCgnYSM8PDwtTkVPLUhUTUwtSUQtPj4+JylbMF07dmFyIGV2T2JqPWRvY3VtZW50LmNyZWF0ZUV2ZW50KCdNb3VzZUV2ZW50cycpO2V2T2JqLmluaXRFdmVudCgnY2xpY2snLHRydWUsdHJ1ZSk7YS5kaXNwYXRjaEV2ZW50KGV2T2JqKX1lbHNleyQoJyM8PDwtTkVPLUhUTUwtSUQtPj4+JykuYXR0cignc3JjJywnd2ViY2xpZW50cHJpbnR2OicrYXJndW1lbnRzWzBdKX19O3JldHVybntpbml0OmZ1bmN0aW9uKCl7aWYod2luZG93LmNocm9tZSl7JCgnPGEgLz4nLHtpZDonPDw8LU5FTy1IVE1MLUlELT4+Pid9KS5hcHBlbmRUbygnYm9keScpfWVsc2V7JCgnPGlmcmFtZSAvPicse25hbWU6Jzw8PC1ORU8tSFRNTC1JRC0+Pj4nLGlkOic8PDwtTkVPLUhUTUwtSUQtPj4+Jyx3aWR0aDonMScsaGVpZ2h0OicxJyxzdHlsZTondmlzaWJpbGl0eTpoaWRkZW47cG9zaXRpb246YWJzb2x1dGUnfSkuYXBwZW5kVG8oJ2JvZHknKX19LHBpbmc6ZnVuY3Rpb24oKXtzZXQ8PDwtTkVPLUhUTUwtSUQtPj4+KCc8PDwtTkVPLVBJTkctVVJMLT4+PicrKGFyZ3VtZW50cy5sZW5ndGg9PTE/JyYnK2FyZ3VtZW50c1swXTonJykpO3ZhciBkZWxheV9tcz0odHlwZW9mIHdjcHBQaW5nRGVsYXlfbXM9PT0ndW5kZWZpbmVkJyk/MDp3Y3BwUGluZ0RlbGF5X21zO2lmKGRlbGF5X21zPjApe3NldFRpbWVvdXQoZnVuY3Rpb24oKXskLmdldCgnPDw8LU5FTy1VU0VSLUhBUy1XQ1BQLT4+PicsZnVuY3Rpb24oZGF0YSl7aWYoZGF0YS5sZW5ndGg+MCl7d2NwcERldGVjdE9uU3VjY2VzcyhkYXRhKX1lbHNle3djcHBEZXRlY3RPbkZhaWx1cmUoKX19KX0sZGVsYXlfbXMpfWVsc2V7dmFyIGZuY1dDUFA9c2V0SW50ZXJ2YWwoZ2V0V0NQUFZlcix3Y3BwUGluZ1RpbWVvdXRTdGVwX21zKTt2YXIgd2NwcF9jb3VudD0wO2Z1bmN0aW9uIGdldFdDUFBWZXIoKXtpZih3Y3BwX2NvdW50PD13Y3BwUGluZ1RpbWVvdXRfbXMpeyQuZ2V0KCc8PDwtTkVPLVVTRVItSEFTLVdDUFAtPj4+Jyx7J18nOiQubm93KCl9LGZ1bmN0aW9uKGRhdGEpe2lmKGRhdGEubGVuZ3RoPjApe2NsZWFySW50ZXJ2YWwoZm5jV0NQUCk7d2NwcERldGVjdE9uU3VjY2VzcyhkYXRhKX19KTt3Y3BwX2NvdW50Kz13Y3BwUGluZ1RpbWVvdXRTdGVwX21zfWVsc2V7Y2xlYXJJbnRlcnZhbChmbmNXQ1BQKTt3Y3BwRGV0ZWN0T25GYWlsdXJlKCl9fX19fX0pKCk7JChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKXtqc1dDUFAuaW5pdCgpO2pzV0NQUC5waW5nKCl9KTs=';
268:
269: $s2 = base64_decode($s1);
270: $s2 = str_replace('<<<-NEO-HTML-ID->>>', $dynamicIframeId, $s2);
271: $s2 = str_replace('<<<-NEO-PING-URL->>>', $absoluteWcpAxd.'&'.self::PING, $s2);
272: $s2 = str_replace('<<<-NEO-USER-HAS-WCPP->>>', $absoluteWcpAxd, $s2);
273:
274: return $s2;
275:
276: }else if(isset($qs[self::GEN_WCP_SCRIPT_URL])){
277:
278: $clientPrintJobUrl = base64_decode($qs[self::GEN_WCP_SCRIPT_URL]);
279: if (strpos($clientPrintJobUrl, '?')>0){
280: $clientPrintJobUrl .= '&';
281: }else{
282: $clientPrintJobUrl .= '?';
283: }
284: $clientPrintJobUrl .= self::CLIENT_PRINT_JOB;
285: $absoluteWcpAxd = $webClientPrintControllerAbsoluteUrl;
286: $wcppGetPrintersParam = '-getPrinters:'.$absoluteWcpAxd.'?'.self::WCP.'&'.self::SID.'=';
287: $wcpHandlerGetPrinters = $absoluteWcpAxd.'?'.self::WCP.'&'.self::WCP_SCRIPT_AXD_GET_PRINTERS.'&'.self::SID.'=';
288: $wcppGetPrintersInfoParam = '-getPrintersInfo:'.$absoluteWcpAxd.'?'.self::WCP.'&'.self::SID.'=';
289: $wcpHandlerGetPrintersInfo = $absoluteWcpAxd.'?'.self::WCP.'&'.self::WCP_SCRIPT_AXD_GET_PRINTERSINFO.'&'.self::SID.'=';
290: $wcppGetWcppVerParam = '-getWcppVersion:'.$absoluteWcpAxd.'?'.self::WCP.'&'.self::SID.'=';
291: $wcpHandlerGetWcppVer = $absoluteWcpAxd.'?'.self::WCP.'&'.self::WCP_SCRIPT_AXD_GET_WCPPVERSION.'&'.self::SID.'=';
292: $sessionIDVal = $qs[self::SID];
293:
294: $s1 = 'dmFyIGpzV2ViQ2xpZW50UHJpbnQ9KGZ1bmN0aW9uKCl7dmFyIHNldEE9ZnVuY3Rpb24oKXt2YXIgZV9pZD0naWRfJytuZXcgRGF0ZSgpLmdldFRpbWUoKTtpZih3aW5kb3cuY2hyb21lKXskKCdib2R5JykuYXBwZW5kKCc8YSBpZD1cIicrZV9pZCsnXCI+PC9hPicpOyQoJyMnK2VfaWQpLmF0dHIoJ2hyZWYnLCd3ZWJjbGllbnRwcmludHY6Jythcmd1bWVudHNbMF0pO3ZhciBhPSQoJ2EjJytlX2lkKVswXTt2YXIgZXZPYmo9ZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ01vdXNlRXZlbnRzJyk7ZXZPYmouaW5pdEV2ZW50KCdjbGljaycsdHJ1ZSx0cnVlKTthLmRpc3BhdGNoRXZlbnQoZXZPYmopfWVsc2V7JCgnYm9keScpLmFwcGVuZCgnPGlmcmFtZSBuYW1lPVwiJytlX2lkKydcIiBpZD1cIicrZV9pZCsnXCIgd2lkdGg9XCIxXCIgaGVpZ2h0PVwiMVwiIHN0eWxlPVwidmlzaWJpbGl0eTpoaWRkZW47cG9zaXRpb246YWJzb2x1dGVcIiAvPicpOyQoJyMnK2VfaWQpLmF0dHIoJ3NyYycsJ3dlYmNsaWVudHByaW50djonK2FyZ3VtZW50c1swXSl9c2V0VGltZW91dChmdW5jdGlvbigpeyQoJyMnK2VfaWQpLnJlbW92ZSgpfSw1MDAwKX07cmV0dXJue3ByaW50OmZ1bmN0aW9uKCl7c2V0QSgnVVJMX1BSSU5UX0pPQicrKGFyZ3VtZW50cy5sZW5ndGg9PTE/JyYnK2FyZ3VtZW50c1swXTonJykpfSxnZXRQcmludGVyczpmdW5jdGlvbigpe3NldEEoJ1VSTF9XQ1BfQVhEX1dJVEhfR0VUX1BSSU5URVJTX0NPTU1BTkQnKyc8PDwtTkVPLVNFU1NJT04tSUQtPj4+Jyk7dmFyIGRlbGF5X21zPSh0eXBlb2Ygd2NwcEdldFByaW50ZXJzRGVsYXlfbXM9PT0ndW5kZWZpbmVkJyk/MDp3Y3BwR2V0UHJpbnRlcnNEZWxheV9tcztpZihkZWxheV9tcz4wKXtzZXRUaW1lb3V0KGZ1bmN0aW9uKCl7JC5nZXQoJ1VSTF9XQ1BfQVhEX0dFVF9QUklOVEVSUycrJzw8PC1ORU8tU0VTU0lPTi1JRC0+Pj4nLGZ1bmN0aW9uKGRhdGEpe2lmKGRhdGEubGVuZ3RoPjApe3djcEdldFByaW50ZXJzT25TdWNjZXNzKGRhdGEpfWVsc2V7d2NwR2V0UHJpbnRlcnNPbkZhaWx1cmUoKX19KX0sZGVsYXlfbXMpfWVsc2V7dmFyIGZuY0dldFByaW50ZXJzPXNldEludGVydmFsKGdldENsaWVudFByaW50ZXJzLHdjcHBHZXRQcmludGVyc1RpbWVvdXRTdGVwX21zKTt2YXIgd2NwcF9jb3VudD0wO2Z1bmN0aW9uIGdldENsaWVudFByaW50ZXJzKCl7aWYod2NwcF9jb3VudDw9d2NwcEdldFByaW50ZXJzVGltZW91dF9tcyl7JC5nZXQoJ1VSTF9XQ1BfQVhEX0dFVF9QUklOVEVSUycrJzw8PC1ORU8tU0VTU0lPTi1JRC0+Pj4nLHsnXyc6JC5ub3coKX0sZnVuY3Rpb24oZGF0YSl7aWYoZGF0YS5sZW5ndGg+MCl7Y2xlYXJJbnRlcnZhbChmbmNHZXRQcmludGVycyk7d2NwR2V0UHJpbnRlcnNPblN1Y2Nlc3MoZGF0YSl9fSk7d2NwcF9jb3VudCs9d2NwcEdldFByaW50ZXJzVGltZW91dFN0ZXBfbXN9ZWxzZXtjbGVhckludGVydmFsKGZuY0dldFByaW50ZXJzKTt3Y3BHZXRQcmludGVyc09uRmFpbHVyZSgpfX19fSxnZXRQcmludGVyc0luZm86ZnVuY3Rpb24oKXtzZXRBKCdVUkxfV0NQX0FYRF9XSVRIX0dFVF9QUklOVEVSU0lORk9fQ09NTUFORCcrJzw8PC1ORU8tU0VTU0lPTi1JRC0+Pj4nKTt2YXIgZGVsYXlfbXM9KHR5cGVvZiB3Y3BwR2V0UHJpbnRlcnNEZWxheV9tcz09PSd1bmRlZmluZWQnKT8wOndjcHBHZXRQcmludGVyc0RlbGF5X21zO2lmKGRlbGF5X21zPjApe3NldFRpbWVvdXQoZnVuY3Rpb24oKXskLmdldCgnVVJMX1dDUF9BWERfR0VUX1BSSU5URVJTSU5GTycrJzw8PC1ORU8tU0VTU0lPTi1JRC0+Pj4nLGZ1bmN0aW9uKGRhdGEpe2lmKGRhdGEubGVuZ3RoPjApe3djcEdldFByaW50ZXJzT25TdWNjZXNzKGRhdGEpfWVsc2V7d2NwR2V0UHJpbnRlcnNPbkZhaWx1cmUoKX19KX0sZGVsYXlfbXMpfWVsc2V7dmFyIGZuY0dldFByaW50ZXJzSW5mbz1zZXRJbnRlcnZhbChnZXRDbGllbnRQcmludGVyc0luZm8sd2NwcEdldFByaW50ZXJzVGltZW91dFN0ZXBfbXMpO3ZhciB3Y3BwX2NvdW50PTA7ZnVuY3Rpb24gZ2V0Q2xpZW50UHJpbnRlcnNJbmZvKCl7aWYod2NwcF9jb3VudDw9d2NwcEdldFByaW50ZXJzVGltZW91dF9tcyl7JC5nZXQoJ1VSTF9XQ1BfQVhEX0dFVF9QUklOVEVSU0lORk8nKyc8PDwtTkVPLVNFU1NJT04tSUQtPj4+Jyx7J18nOiQubm93KCl9LGZ1bmN0aW9uKGRhdGEpe2lmKGRhdGEubGVuZ3RoPjApe2NsZWFySW50ZXJ2YWwoZm5jR2V0UHJpbnRlcnNJbmZvKTt3Y3BHZXRQcmludGVyc09uU3VjY2VzcyhkYXRhKX19KTt3Y3BwX2NvdW50Kz13Y3BwR2V0UHJpbnRlcnNUaW1lb3V0U3RlcF9tc31lbHNle2NsZWFySW50ZXJ2YWwoZm5jR2V0UHJpbnRlcnNJbmZvKTt3Y3BHZXRQcmludGVyc09uRmFpbHVyZSgpfX19fSxnZXRXY3BwVmVyOmZ1bmN0aW9uKCl7c2V0QSgnVVJMX1dDUF9BWERfV0lUSF9HRVRfV0NQUFZFUlNJT05fQ09NTUFORCcrJzw8PC1ORU8tU0VTU0lPTi1JRC0+Pj4nKTt2YXIgZGVsYXlfbXM9KHR5cGVvZiB3Y3BwR2V0VmVyRGVsYXlfbXM9PT0ndW5kZWZpbmVkJyk/MDp3Y3BwR2V0VmVyRGVsYXlfbXM7aWYoZGVsYXlfbXM+MCl7c2V0VGltZW91dChmdW5jdGlvbigpeyQuZ2V0KCdVUkxfV0NQX0FYRF9HRVRfV0NQUFZFUlNJT04nKyc8PDwtTkVPLVNFU1NJT04tSUQtPj4+JyxmdW5jdGlvbihkYXRhKXtpZihkYXRhLmxlbmd0aD4wKXt3Y3BHZXRXY3BwVmVyT25TdWNjZXNzKGRhdGEpfWVsc2V7d2NwR2V0V2NwcFZlck9uRmFpbHVyZSgpfX0pfSxkZWxheV9tcyl9ZWxzZXt2YXIgZm5jV0NQUD1zZXRJbnRlcnZhbChnZXRDbGllbnRWZXIsd2NwcEdldFZlclRpbWVvdXRTdGVwX21zKTt2YXIgd2NwcF9jb3VudD0wO2Z1bmN0aW9uIGdldENsaWVudFZlcigpe2lmKHdjcHBfY291bnQ8PXdjcHBHZXRWZXJUaW1lb3V0X21zKXskLmdldCgnVVJMX1dDUF9BWERfR0VUX1dDUFBWRVJTSU9OJysnPDw8LU5FTy1TRVNTSU9OLUlELT4+PicseydfJzokLm5vdygpfSxmdW5jdGlvbihkYXRhKXtpZihkYXRhLmxlbmd0aD4wKXtjbGVhckludGVydmFsKGZuY1dDUFApO3djcEdldFdjcHBWZXJPblN1Y2Nlc3MoZGF0YSl9fSk7d2NwcF9jb3VudCs9d2NwcEdldFZlclRpbWVvdXRTdGVwX21zfWVsc2V7Y2xlYXJJbnRlcnZhbChmbmNXQ1BQKTt3Y3BHZXRXY3BwVmVyT25GYWlsdXJlKCl9fX19LHNlbmQ6ZnVuY3Rpb24oKXtzZXRBLmFwcGx5KHRoaXMsYXJndW1lbnRzKX19fSkoKTs=';
295:
296: $s2 = base64_decode($s1);
297: $s2 = str_replace('URL_PRINT_JOB', $clientPrintJobUrl, $s2);
298: $s2 = str_replace('URL_WCP_AXD_WITH_GET_PRINTERSINFO_COMMAND', $wcppGetPrintersInfoParam, $s2);
299: $s2 = str_replace('URL_WCP_AXD_GET_PRINTERSINFO', $wcpHandlerGetPrintersInfo, $s2);
300: $s2 = str_replace('URL_WCP_AXD_WITH_GET_PRINTERS_COMMAND', $wcppGetPrintersParam, $s2);
301: $s2 = str_replace('URL_WCP_AXD_GET_PRINTERS', $wcpHandlerGetPrinters, $s2);
302: $s2 = str_replace('URL_WCP_AXD_WITH_GET_WCPPVERSION_COMMAND', $wcppGetWcppVerParam, $s2);
303: $s2 = str_replace('URL_WCP_AXD_GET_WCPPVERSION', $wcpHandlerGetWcppVer, $s2);
304: $s2 = str_replace('<<<-NEO-SESSION-ID->>>', $sessionIDVal, $s2);
305:
306: return $s2;
307: }
308:
309: }
310:
311:
312: 313: 314:
315: const GenPrintScript = 0;
316: 317: 318:
319: const GenWcppDetectScript = 1;
320: 321: 322:
323: const ClientSetInstalledPrinters = 2;
324: 325: 326:
327: const ClientGetInstalledPrinters = 3;
328: 329: 330:
331: const ClientSetWcppVersion = 4;
332: 333: 334:
335: const ClientGetWcppVersion = 5;
336: 337: 338:
339: const ClientSetInstalledPrintersInfo = 6;
340: 341: 342:
343: const ClientGetInstalledPrintersInfo = 7;
344:
345:
346: 347: 348: 349: 350: 351: 352:
353: public static function GetProcessRequestType($queryString){
354: parse_str($queryString, $qs);
355:
356: if(isset($qs[self::SID])){
357: if(isset($qs[self::PING])){
358: return self::ClientSetWcppVersion;
359: } else if(isset($qs[self::WCPP_SET_VERSION])){
360: return self::ClientSetWcppVersion;
361: } else if(isset($qs[self::WCPP_SET_PRINTERS])){
362: return self::ClientSetInstalledPrinters;
363: } else if(isset($qs[self::WCPP_SET_PRINTERSINFO])){
364: return self::ClientSetInstalledPrintersInfo;
365: } else if(isset($qs[self::WCP_SCRIPT_AXD_GET_WCPPVERSION])){
366: return self::ClientGetWcppVersion;
367: } else if(isset($qs[self::WCP_SCRIPT_AXD_GET_PRINTERS])){
368: return self::ClientGetInstalledPrinters;
369: } else if(isset($qs[self::WCP_SCRIPT_AXD_GET_PRINTERSINFO])){
370: return self::ClientGetInstalledPrintersInfo;
371: } else if(isset($qs[self::GEN_WCP_SCRIPT_URL])){
372: return self::GenPrintScript;
373: } else {
374: return self::ClientGetWcppVersion;
375: }
376: } else if(isset($qs[self::GEN_DETECT_WCPP_SCRIPT])){
377: return self::GenWcppDetectScript;
378: } else {
379: throw new Exception('No valid ProcessRequestType was found in the specified QueryString.');
380: }
381: }
382:
383: }
384:
385: 386: 387:
388: class Duplex
389: {
390: 391: 392:
393: const DEF = 0;
394: 395: 396:
397: const SIMPLEX = 1;
398: 399: 400:
401: const VERTICAL = 2;
402: 403: 404:
405: const HORIZONTAL = 3;
406:
407: public static function parse($val){
408: if($val === 'DEF') return 0;
409: if($val === 'SIMPLEX') return 1;
410: if($val === 'VERTICAL') return 2;
411: if($val === 'HORIZONTAL') return 3;
412: return 0;
413: }
414: }
415:
416:
417: 418: 419:
420: abstract class ClientPrinter{
421:
422: public $printerId;
423: public function serialize(){
424:
425: }
426: }
427:
428: 429: 430:
431: class DefaultPrinter extends ClientPrinter{
432: public function __construct() {
433: $this->printerId = chr(0);
434: }
435:
436: public function serialize() {
437: return $this->printerId;
438: }
439: }
440:
441: 442: 443:
444: class InstalledPrinter extends ClientPrinter{
445:
446: 447: 448: 449:
450: public $printerName = '';
451:
452: 453: 454: 455:
456: public $printToDefaultIfNotFound = false;
457:
458:
459: 460: 461: 462:
463: public $trayName = '';
464:
465: 466: 467: 468:
469: public $paperName = '';
470:
471: 472: 473: 474: 475:
476: public $duplex = Duplex::DEF;
477:
478:
479: 480: 481: 482:
483: public function __construct($printerName) {
484: $this->printerId = chr(1);
485: $this->printerName = $printerName;
486: }
487:
488: public function serialize() {
489:
490: if (Utils::isNullOrEmptyString($this->printerName)){
491: throw new Exception("The specified printer name is null or empty.");
492: }
493:
494: $serData = $this->printerId.$this->printerName;
495:
496: if ($this->printToDefaultIfNotFound){
497: $serData .= Utils::SER_SEP.'1';
498: } else {
499: $serData .= Utils::SER_SEP.'0';
500: }
501:
502: if ($this->trayName){
503: $serData .= Utils::SER_SEP.$this->trayName;
504: } else {
505: $serData .= Utils::SER_SEP.'def';
506: }
507:
508: if ($this->paperName){
509: $serData .= Utils::SER_SEP.$this->paperName;
510: } else {
511: $serData .= Utils::SER_SEP.'def';
512: }
513:
514: $serData .= Utils::SER_SEP.((int)$this->duplex);
515:
516: return $serData;
517: }
518: }
519:
520: 521: 522:
523: class ParallelPortPrinter extends ClientPrinter{
524:
525: 526: 527: 528:
529: public $portName = "LPT1";
530:
531: 532: 533: 534:
535: public function __construct($portName) {
536: $this->printerId = chr(2);
537: $this->portName = $portName;
538: }
539:
540: public function serialize() {
541:
542: if (Utils::isNullOrEmptyString($this->portName)){
543: throw new Exception("The specified parallel port name is null or empty.");
544: }
545:
546: return $this->printerId.$this->portName;
547: }
548: }
549:
550: 551: 552:
553: class SerialPortPrinter extends ClientPrinter{
554:
555: 556: 557: 558:
559: public $portName = "COM1";
560: 561: 562: 563:
564: public $baudRate = 9600;
565: 566: 567: 568: 569:
570: public $parity = SerialPortParity::NONE;
571: 572: 573: 574: 575:
576: public $stopBits = SerialPortStopBits::ONE;
577: 578: 579: 580:
581: public $dataBits = 8;
582: 583: 584: 585: 586:
587: public $flowControl = SerialPortHandshake::XON_XOFF;
588:
589: 590: 591: 592: 593: 594: 595: 596: 597:
598: public function __construct($portName, $baudRate, $parity, $stopBits, $dataBits, $flowControl) {
599: $this->printerId = chr(3);
600: $this->portName = $portName;
601: $this->baudRate = $baudRate;
602: $this->parity = $parity;
603: $this->stopBits = $stopBits;
604: $this->dataBits = $dataBits;
605: $this->flowControl = $flowControl;
606: }
607:
608: public function serialize() {
609:
610: if (Utils::isNullOrEmptyString($this->portName)){
611: throw new Exception("The specified serial port name is null or empty.");
612: }
613:
614: return $this->printerId.$this->portName.Utils::SER_SEP.$this->baudRate.Utils::SER_SEP.$this->dataBits.Utils::SER_SEP.((int)$this->flowControl).Utils::SER_SEP.((int)$this->parity).Utils::SER_SEP.((int)$this->stopBits);
615: }
616: }
617:
618: 619: 620:
621: class NetworkPrinter extends ClientPrinter{
622:
623: 624: 625: 626:
627: public $dnsName = "";
628: 629: 630: 631:
632: public $ipAddress = "";
633: 634: 635: 636:
637: public $port = 0;
638:
639: 640: 641: 642: 643: 644:
645: public function __construct($dnsName, $ipAddress, $port) {
646: $this->printerId = chr(4);
647: $this->dnsName = $dnsName;
648: $this->ipAddress = $ipAddress;
649: $this->port = $port;
650: }
651:
652: public function serialize() {
653:
654: if (Utils::isNullOrEmptyString($this->dnsName) && Utils::isNullOrEmptyString($this->ipAddress)){
655: throw new Exception("The specified network printer settings is not valid. You must specify the DNS Printer Name or its IP address.");
656: }
657:
658: return $this->printerId.$this->dnsName.Utils::SER_SEP.$this->ipAddress.Utils::SER_SEP.$this->port;
659: }
660: }
661:
662: 663: 664:
665: class UserSelectedPrinter extends ClientPrinter{
666: public function __construct() {
667: $this->printerId = chr(5);
668: }
669:
670: public function serialize() {
671: return $this->printerId;
672: }
673: }
674:
675: 676: 677:
678: class SerialPortParity{
679: const NONE = 0;
680: const ODD = 1;
681: const EVEN = 2;
682: const MARK = 3;
683: const SPACE = 4;
684: public static function parse($val){
685: if($val === 'NONE') return 0;
686: if($val === 'ODD') return 1;
687: if($val === 'EVEN') return 2;
688: if($val === 'MARK') return 3;
689: if($val === 'SPACE') return 4;
690: return 0;
691: }
692: }
693:
694: 695: 696:
697: class SerialPortStopBits{
698: const NONE = 0;
699: const ONE = 1;
700: const TWO = 2;
701: const ONE_POINT_FIVE = 3;
702: public static function parse($val){
703: if($val === 'NONE') return 0;
704: if($val === 'ONE') return 1;
705: if($val === 'TWO') return 2;
706: if($val === 'ONE_POINT_FIVE') return 3;
707: return 0;
708: }
709: }
710:
711: 712: 713:
714: class SerialPortHandshake{
715: const NONE = 0;
716: const REQUEST_TO_SEND = 2;
717: const REQUEST_TO_SEND_XON_XOFF = 3;
718: const XON_XOFF = 1;
719: public static function parse($val){
720: if($val === 'NONE') return 0;
721: if($val === 'XON_XOFF') return 1;
722: if($val === 'REQUEST_TO_SEND') return 2;
723: if($val === 'REQUEST_TO_SEND_XON_XOFF') return 3;
724: return 0;
725: }
726: }
727:
728: 729: 730:
731: class EncryptMetadata{
732:
733: 734: 735:
736: public $publicKeyBase64 = '';
737: 738: 739:
740: public $publicKeySignatureBase64 = '';
741: 742: 743:
744: public $password = '';
745: 746: 747:
748: public $salt = '';
749: 750: 751:
752: public $iv = '';
753: 754: 755:
756: public $iterations = 1000;
757:
758:
759: 760: 761: 762: 763:
764: public function __construct($pubKeyBase64, $pubKeySignatureKeyBase64) {
765: $this->publicKeyBase64 = $pubKeyBase64;
766: $this->publicKeySignatureBase64 = $pubKeySignatureKeyBase64;
767: }
768:
769: public function serialize() {
770:
771: $this->validateMetadata();
772:
773: $sep = '|';
774:
775: $buffer = base64_encode(SecUtils::rsaVerifyAndEncrypt($this->publicKeyBase64, $this->publicKeySignatureBase64, $this->password));
776: $buffer .= $sep;
777: $buffer .= base64_encode(SecUtils::rsaVerifyAndEncrypt($this->publicKeyBase64, $this->publicKeySignatureBase64, $this->salt));
778: $buffer .= $sep;
779: $buffer .= base64_encode(SecUtils::rsaVerifyAndEncrypt($this->publicKeyBase64, $this->publicKeySignatureBase64, $this->iv));
780: $buffer .= $sep;
781: $buffer .= base64_encode(SecUtils::rsaVerifyAndEncrypt($this->publicKeyBase64, $this->publicKeySignatureBase64, strval($this->iterations)));
782:
783: return $buffer;
784: }
785:
786: public function validateMetadata(){
787: if(Utils::isNullOrEmptyString($this->password)){
788: $this->password = Utils::genRandomString(33, 126, 32);
789: }else if (strlen($this->password) > 100){
790: throw new Exception("Password cannot be greater than 100 ASCII chars/bytes.");
791: }
792:
793: if(Utils::isNullOrEmptyString($this->salt)){
794: $this->salt = Utils::genRandomString(33, 126, 32);
795: }else if (strlen($this->salt) > 100){
796: throw new Exception("Salt cannot be greater than 100 ASCII chars/bytes.");
797: }
798:
799: if(Utils::isNullOrEmptyString($this->iv)){
800: $this->iv = Utils::genRandomString(33, 126, 16);
801: }else if (strlen($this->iv) > 16){
802: throw new Exception("IV cannot be greater than 16 ASCII chars/bytes.");
803: }
804:
805: if ($this->iterations < 1000){
806: $this->iterations = 1000;
807: }
808: }
809: }
810:
811:
812: 813: 814:
815: class PrintFile{
816:
817: public $fileIsPasswordProtected = false;
818: public $fileExtension = '';
819:
820: 821: 822: 823:
824: public $filePath = '';
825: 826: 827: 828: 829:
830: public $fileName = '';
831: 832: 833: 834:
835: public $fileBinaryContent = '';
836:
837: 838: 839: 840:
841: public $copies = 1;
842: 843: 844: 845:
846: public $encryptMetadata = null;
847:
848: 849: 850: 851:
852: public $deleteAfterPrinting = true;
853:
854: const PREFIX = 'wcpPF:';
855: const SEP = '|';
856:
857: 858: 859: 860: 861: 862:
863: public function __construct($filePath, $fileName, $fileBinaryContent) {
864: $this->filePath = $filePath;
865: $this->fileName = $fileName;
866: $this->fileBinaryContent = $fileBinaryContent;
867:
868: }
869:
870: public function serialize() {
871: $file = str_replace('\\', 'BACKSLASHCHAR',$this->fileName );
872: $pfc = '';
873: if($this->copies > 1){
874: $pfc = 'PFC='.$this->copies;
875: }
876: $df = 'DEL=F';
877: if($this->deleteAfterPrinting){
878: $df = '';
879: }
880:
881: $fn = $file;
882: $ext = '';
883: if (strrpos($fn, '.') > 0){
884: $fn = substr($fn, 0, strrpos($fn, '.'));
885: $ext = substr($file, strrpos($file, '.'));
886: }
887:
888: if(Utils::isNullOrEmptyString($this->fileExtension)){
889: $file = $fn.$pfc.$df.$ext;
890: } else {
891: $file = $fn.$pfc.$df.$this->fileExtension;
892: }
893:
894: $fileContent = $this->getFileContent();
895:
896: if($this->encryptMetadata != null &&
897: Utils::isNullOrEmptyString($this->encryptMetadata->publicKeyBase64) == false &&
898: $this->fileIsPasswordProtected == false){
899:
900:
901: $this->encryptMetadata->validateMetadata();
902:
903: $fileContent = SecUtils::aesEncrypt($fileContent,
904: $this->encryptMetadata->password,
905: $this->encryptMetadata->salt,
906: $this->encryptMetadata->iv,
907: $this->encryptMetadata->iterations);
908:
909: }
910:
911: return self::PREFIX.$file.self::SEP.$fileContent;
912: }
913:
914: public function getFileContent(){
915: if(!Utils::isNullOrEmptyString($this->filePath)){
916: $handle = fopen($this->filePath, 'rb');
917: $content = fread($handle, filesize($this->filePath));
918: fclose($handle);
919: } else {
920: $content = $this->fileBinaryContent;
921: }
922: return $content;
923: }
924:
925: }
926:
927: 928: 929:
930: class PrintRotation
931: {
932: 933: 934:
935: const None = 0;
936: 937: 938:
939: const Rot90 = 1;
940: 941: 942:
943: const Rot180 = 2;
944: 945: 946:
947: const Rot270 = 3;
948:
949: public static function parse($val){
950: if($val === 'None') return 0;
951: if($val === 'Rot90') return 1;
952: if($val === 'Rot180') return 2;
953: if($val === 'Rot270') return 3;
954: return 0;
955: }
956: }
957:
958: 959: 960:
961: class Sizing
962: {
963: 964: 965:
966: const None = 0;
967: 968: 969:
970: const Fit = 1;
971:
972: public static function parse($val){
973: if($val === 'None') return 0;
974: if($val === 'Fit') return 1;
975: return 0;
976: }
977: }
978:
979: 980: 981:
982: class PrintFilePDF extends PrintFile{
983:
984: 985: 986: 987:
988: public $printAsGrayscale = false;
989:
990: 991: 992: 993:
994: public $printAnnotations = false;
995:
996: 997: 998: 999:
1000: public $pagesRange = '';
1001:
1002: 1003: 1004: 1005:
1006: public $printInReverseOrder = false;
1007:
1008: 1009: 1010: 1011:
1012: public $printRotation = PrintRotation::None;
1013:
1014: 1015: 1016: 1017:
1018: public $password = '';
1019:
1020: 1021: 1022: 1023:
1024: public $duplexPrinting = false;
1025:
1026: 1027: 1028: 1029:
1030: public $duplexPrintingDialogMessage = '';
1031:
1032: 1033: 1034: 1035:
1036: public $autoRotate = false;
1037:
1038: 1039: 1040: 1041:
1042: public $autoCenter = false;
1043:
1044: 1045: 1046: 1047:
1048: public $sizing = Sizing::Fit;
1049:
1050:
1051: public function serialize() {
1052:
1053: $this->fileExtension = '.wpdf';
1054:
1055: return parent::serialize();
1056: }
1057:
1058: public function getFileContent(){
1059:
1060: $pr = urldecode($this->pagesRange);
1061: if (!Utils::isNullOrEmptyString($pr)){
1062: if (preg_match('/^(?!([ \d]*-){2})\d+(?: *[-,] *\d+)*$/', $pr))
1063: {
1064:
1065: $ranges = explode(',',str_replace(' ', '', $pr));
1066:
1067: for ($i = 0; $i < count($ranges); $i++)
1068: {
1069: if (strpos($ranges[$i], '-') > 0)
1070: {
1071: $pages = explode('-', $ranges[$i]);
1072: if (intval($pages[0]) > intval($pages[1]))
1073: {
1074: throw new Exception("The specified PageRange is not valid.");
1075: }
1076: }
1077: }
1078: }
1079: else{
1080: throw new Exception("The specified PageRange is not valid.");
1081: }
1082: }
1083:
1084: $metadata = ($this->printAsGrayscale ? '1' : '0');
1085: $metadata .= Utils::SER_SEP.($this->printAnnotations ? '1' : '0');
1086: $metadata .= Utils::SER_SEP.(Utils::isNullOrEmptyString($pr) ? 'A' : $pr);
1087: $metadata .= Utils::SER_SEP.($this->printInReverseOrder ? '1' : '0');
1088: $metadata .= Utils::SER_SEP.$this->printRotation;
1089: $metadata .= Utils::SER_SEP;
1090:
1091: $this->fileIsPasswordProtected = !Utils::isNullOrEmptyString($this->password);
1092:
1093: if ($this->fileIsPasswordProtected == false){
1094: $metadata .= 'N';
1095: } else {
1096: if (Utils::isNullOrEmptyString($this->encryptMetadata->publicKeyBase64) == false) {
1097: $metadata .= base64_encode(SecUtils::rsaVerifyAndEncrypt($this->encryptMetadata->publicKeyBase64, $this->encryptMetadata->publicKeySignatureBase64, $this->password));
1098: } else {
1099: $metadata .= base64_encode($this->password);
1100: }
1101: }
1102:
1103: $metadata .= Utils::SER_SEP.($this->duplexPrinting ? '1' : '0');
1104: $metadata .= Utils::SER_SEP.(Utils::isNullOrEmptyString($this->duplexPrintingDialogMessage) ? 'D' : base64_encode($this->duplexPrintingDialogMessage));
1105: $metadata .= Utils::SER_SEP.($this->autoRotate ? '1' : '0');
1106: $metadata .= Utils::SER_SEP.($this->autoCenter ? '1' : '0');
1107: $metadata .= Utils::SER_SEP.(strval(Sizing::parse($this->sizing)));
1108:
1109: $metadataLength = strlen($metadata);
1110: $metadata .= Utils::SER_SEP;
1111: $metadataLength++;
1112: $metadataLength += strlen(strval($metadataLength));
1113: $metadata .= strval($metadataLength);
1114:
1115: if(!Utils::isNullOrEmptyString($this->filePath)){
1116: $handle = fopen($this->filePath, 'rb');
1117: $content = fread($handle, filesize($this->filePath));
1118: fclose($handle);
1119: } else {
1120: $content = $this->fileBinaryContent;
1121: }
1122: return $content.$metadata;
1123: }
1124: }
1125:
1126: 1127: 1128:
1129: class PrintOrientation
1130: {
1131: 1132: 1133:
1134: const Portrait = 0;
1135: 1136: 1137:
1138: const Landscape = 1;
1139:
1140: public static function parse($val){
1141: if($val === 'Portrait') return 0;
1142: if($val === 'Landscape') return 1;
1143: return 0;
1144: }
1145: }
1146:
1147: 1148: 1149:
1150: class TextAlignment
1151: {
1152: 1153: 1154:
1155: const Left = 0;
1156: 1157: 1158:
1159: const Right = 2;
1160: 1161: 1162:
1163: const Center = 1;
1164: 1165: 1166:
1167: const Justify = 3;
1168: 1169: 1170:
1171: const None = 4;
1172:
1173:
1174: public static function parse($val){
1175: if($val === 'Left') return 0;
1176: if($val === 'Center') return 1;
1177: if($val === 'Right') return 2;
1178: if($val === 'Justify') return 3;
1179: if($val === 'None') return 4;
1180: return 0;
1181: }
1182: }
1183:
1184: 1185: 1186:
1187: class PrintFileTXT extends PrintFile{
1188:
1189: 1190: 1191: 1192:
1193: public $textContent = '';
1194:
1195: 1196: 1197: 1198:
1199: public $textAlignment = TextAlignment::Left;
1200:
1201: 1202: 1203: 1204:
1205: public $fontName = 'Arial';
1206:
1207: 1208: 1209: 1210:
1211: public $fontBold = false;
1212:
1213: 1214: 1215: 1216:
1217: public $fontItalic = false;
1218:
1219: 1220: 1221: 1222:
1223: public $fontUnderline = false;
1224:
1225: 1226: 1227: 1228:
1229: public $fontStrikeThrough = false;
1230:
1231: 1232: 1233: 1234:
1235: public $fontSizeInPoints = 10.0;
1236:
1237: 1238: 1239: 1240:
1241: public $textColor = "#000000";
1242:
1243: 1244: 1245: 1246:
1247: public $printOrientation = PrintOrientation::Portrait;
1248:
1249: 1250: 1251: 1252:
1253: public $marginLeft = 0.5;
1254:
1255: 1256: 1257: 1258:
1259: public $marginRight = 0.5;
1260:
1261: 1262: 1263: 1264:
1265: public $marginTop = 0.5;
1266:
1267: 1268: 1269: 1270:
1271: public $marginBottom = 0.5;
1272:
1273:
1274: public function serialize() {
1275: $this->fileIsPasswordProtected = false;
1276:
1277: $this->fileExtension = '.wtxt';
1278:
1279: return parent::serialize();
1280: }
1281:
1282: public function getFileContent(){
1283:
1284: $metadata = $this->printOrientation;
1285: $metadata .= Utils::SER_SEP.$this->textAlignment;
1286: $metadata .= Utils::SER_SEP.$this->fontName;
1287: $metadata .= Utils::SER_SEP.strval($this->fontSizeInPoints);
1288: $metadata .= Utils::SER_SEP.($this->fontBold ? '1' : '0');
1289: $metadata .= Utils::SER_SEP.($this->fontItalic ? '1' : '0');
1290: $metadata .= Utils::SER_SEP.($this->fontUnderline ? '1' : '0');
1291: $metadata .= Utils::SER_SEP.($this->fontStrikeThrough ? '1' : '0');
1292: $metadata .= Utils::SER_SEP.$this->textColor;
1293: $metadata .= Utils::SER_SEP.strval($this->marginLeft);
1294: $metadata .= Utils::SER_SEP.strval($this->marginTop);
1295: $metadata .= Utils::SER_SEP.strval($this->marginRight);
1296: $metadata .= Utils::SER_SEP.strval($this->marginBottom);
1297:
1298: $content = $this->textContent;
1299: if (Utils::isNullOrEmptyString($content)){
1300: if(!Utils::isNullOrEmptyString($this->filePath)){
1301: $handle = fopen($this->filePath, 'rb');
1302: $content = fread($handle, filesize($this->filePath));
1303: fclose($handle);
1304: } else {
1305: $content = $this->fileBinaryContent;
1306: }
1307: }
1308:
1309: if (Utils::isNullOrEmptyString($content)){
1310: throw new Exception('The specified Text file is empty and cannot be printed.');
1311: }
1312:
1313: return $metadata.chr(10).$content;
1314: }
1315: }
1316:
1317:
1318: 1319: 1320:
1321: class PrintFileDOC extends PrintFile{
1322:
1323: 1324: 1325: 1326:
1327: public $pagesRange = '';
1328:
1329: 1330: 1331: 1332:
1333: public $printInReverseOrder = false;
1334:
1335: 1336: 1337: 1338:
1339: public $password = '';
1340:
1341: 1342: 1343: 1344:
1345: public $duplexPrinting = false;
1346:
1347: 1348: 1349: 1350:
1351: public $duplexPrintingDialogMessage = '';
1352:
1353:
1354: public function serialize() {
1355: $this->fileExtension = '.wdoc';
1356:
1357: return parent::serialize();
1358: }
1359:
1360: public function getFileContent(){
1361:
1362: $pr = urldecode($this->pagesRange);
1363: if (!Utils::isNullOrEmptyString($pr)){
1364: if (preg_match('/^(?!([ \d]*-){2})\d+(?: *[-,] *\d+)*$/', $pr))
1365: {
1366:
1367: $ranges = explode(',',str_replace(' ', '', $pr));
1368:
1369: for ($i = 0; $i < count($ranges); $i++)
1370: {
1371: if (strpos($ranges[$i], '-') > 0)
1372: {
1373: $pages = explode('-', $ranges[$i]);
1374: if (intval($pages[0]) > intval($pages[1]))
1375: {
1376: throw new Exception("The specified PageRange is not valid.");
1377: }
1378: }
1379: }
1380: }
1381: else
1382: throw new Exception("The specified PageRange is not valid.");
1383:
1384: }
1385:
1386: $metadata = (Utils::isNullOrEmptyString($pr) ? 'A' : $pr);
1387: $metadata .= Utils::SER_SEP.($this->printInReverseOrder ? '1' : '0');
1388: $metadata .= Utils::SER_SEP;
1389:
1390: $this->fileIsPasswordProtected = !Utils::isNullOrEmptyString($this->password);
1391:
1392: if ($this->fileIsPasswordProtected == false){
1393: $metadata .= 'N';
1394: } else {
1395: if (Utils::isNullOrEmptyString($this->encryptMetadata->publicKeyBase64) == false) {
1396: $metadata .= base64_encode(SecUtils::rsaVerifyAndEncrypt($this->encryptMetadata->publicKeyBase64, $this->encryptMetadata->publicKeySignatureBase64, $this->password));
1397: } else {
1398: $metadata .= base64_encode($this->password);
1399: }
1400: }
1401:
1402: $metadata .= Utils::SER_SEP.($this->duplexPrinting ? '1' : '0');
1403: $metadata .= Utils::SER_SEP.(Utils::isNullOrEmptyString($this->duplexPrintingDialogMessage) ? 'D' : base64_encode($this->duplexPrintingDialogMessage));
1404:
1405: $metadataLength = strlen($metadata);
1406: $metadata .= Utils::SER_SEP;
1407: $metadataLength++;
1408: $metadataLength += strlen(strval($metadataLength));
1409: $metadata .= strval($metadataLength);
1410:
1411:
1412: if(!Utils::isNullOrEmptyString($this->filePath)){
1413: $handle = fopen($this->filePath, 'rb');
1414: $content = fread($handle, filesize($this->filePath));
1415: fclose($handle);
1416: } else {
1417: $content = $this->fileBinaryContent;
1418: }
1419:
1420: return $content.$metadata;
1421: }
1422: }
1423:
1424:
1425: 1426: 1427:
1428: class PrintFileXLS extends PrintFile{
1429:
1430: 1431: 1432: 1433:
1434: public $pagesFrom = 0;
1435:
1436: 1437: 1438: 1439:
1440: public $pagesTo = 0;
1441:
1442:
1443: 1444: 1445: 1446:
1447: public $password = '';
1448:
1449: 1450: 1451: 1452:
1453: public $duplexPrinting = false;
1454:
1455: 1456: 1457: 1458:
1459: public $duplexPrintingDialogMessage = '';
1460:
1461:
1462: public function serialize() {
1463: $this->fileExtension = '.wxls';
1464:
1465: return parent::serialize();
1466: }
1467:
1468: public function getFileContent(){
1469:
1470: $metadata = strval($this->pagesFrom);
1471: $metadata .= Utils::SER_SEP.strval($this->pagesTo);
1472: $metadata .= Utils::SER_SEP;
1473:
1474: $this->fileIsPasswordProtected = !Utils::isNullOrEmptyString($this->password);
1475:
1476: if ($this->fileIsPasswordProtected == false){
1477: $metadata .= 'N';
1478: } else {
1479: if (Utils::isNullOrEmptyString($this->encryptMetadata->publicKeyBase64) == false) {
1480: $metadata .= base64_encode(SecUtils::rsaVerifyAndEncrypt($this->encryptMetadata->publicKeyBase64, $this->encryptMetadata->publicKeySignatureBase64, $this->password));
1481: } else {
1482: $metadata .= base64_encode($this->password);
1483: }
1484: }
1485:
1486: $metadata .= Utils::SER_SEP.($this->duplexPrinting ? '1' : '0');
1487: $metadata .= Utils::SER_SEP.(Utils::isNullOrEmptyString($this->duplexPrintingDialogMessage) ? 'D' : base64_encode($this->duplexPrintingDialogMessage));
1488:
1489: $metadataLength = strlen($metadata);
1490: $metadata .= Utils::SER_SEP;
1491: $metadataLength++;
1492: $metadataLength += strlen(strval($metadataLength));
1493: $metadata .= strval($metadataLength);
1494:
1495: if(!Utils::isNullOrEmptyString($this->filePath)){
1496: $handle = fopen($this->filePath, 'rb');
1497: $content = fread($handle, filesize($this->filePath));
1498: fclose($handle);
1499: } else {
1500: $content = $this->fileBinaryContent;
1501: }
1502:
1503: return $content.$metadata;
1504: }
1505: }
1506:
1507: 1508: 1509:
1510: class SecUtils{
1511:
1512: private static function getPubKey(){
1513: return '<RSAKeyValue><Modulus>reXqa092+txbh684R9kUsMMIG2UTEJQChhFkZ3u/kg1OsPAspaWnjRgecq1lTKIbppPXa4NztFNPw5c7W6sN+3GiuRAbOT6E+ynQIyo298znCoeW+W93WZ8imF32HwWn9lUvI6VFJULwjZ16G91ok/YPTuREc8ri7jclC3ie8g0=</Modulus><Exponent>AQAB</Exponent></RSAKeyValue>';
1514: }
1515:
1516: public static function rsaVerifyAndEncrypt($pubKeyBase64, $pubKeySignatureBase64, $dataToEncrypt){
1517: $rsa = new \phpseclib\Crypt\RSA();
1518: $rsa->loadKey(self::getPubKey());
1519: $rsa->setSignatureMode(2);
1520: if ($rsa->verify(base64_decode($pubKeyBase64), base64_decode($pubKeySignatureBase64))) {
1521: $rsa->loadKey(base64_decode($pubKeyBase64));
1522: $rsa->setEncryptionMode(2);
1523: return $rsa->encrypt($dataToEncrypt);
1524: }
1525: else{
1526: throw new Exception('Cannot verify the provided RSA Public Key.');
1527: }
1528: }
1529:
1530: public static function aesEncrypt($dataToEncrypt, $password, $salt, $iv, $iterations){
1531: $aes = new \phpseclib\Crypt\AES(\phpseclib\Crypt\AES::MODE_CBC);
1532: $aes->setPassword($password,
1533: 'pbkdf2' ,
1534: 'sha1' ,
1535: $salt,
1536: $iterations,
1537: 256 / 8
1538: );
1539: $aes->setIV($iv);
1540: return $aes->encrypt($dataToEncrypt);
1541: }
1542:
1543: }
1544:
1545: 1546: 1547:
1548: class Utils{
1549: const SER_SEP = '|';
1550:
1551: static function isNullOrEmptyString($s){
1552: return (!isset($s) || trim($s)==='');
1553: }
1554:
1555: static function formatHexValues($s){
1556:
1557: $buffer = '';
1558:
1559: $l = strlen($s);
1560: $i = 0;
1561:
1562: while ($i < $l)
1563: {
1564: if ($s[$i] == '0')
1565: {
1566: if ($i + 1 < $l && ($s[$i] == '0' && $s[$i + 1] == 'x'))
1567: {
1568: if ($i + 2 < $l &&
1569: (($s[$i + 2] >= '0' && $s[$i + 2] <= '9') || ($s[$i + 2] >= 'a' && $s[$i + 2] <= 'f') || ($s[$i + 2] >= 'A' && $s[$i + 2] <= 'F')))
1570: {
1571: if ($i + 3 < $l &&
1572: (($s[$i + 3] >= '0' && $s[$i + 3] <= '9') || ($s[$i + 3] >= 'a' && $s[$i + 3] <= 'f') || ($s[$i + 3] >= 'A' && $s[$i + 3] <= 'F')))
1573: {
1574: try{
1575: $buffer .= chr(intval(substr($s, $i, 4),16));
1576: $i += 4;
1577: continue;
1578:
1579: } catch (Exception $ex) {
1580: throw new Exception("Invalid hex notation in the specified printer commands at index: ".$i);
1581: }
1582:
1583:
1584: }
1585: else
1586: {
1587: try{
1588:
1589: $buffer .= chr(intval(substr($s, $i, 3),16));
1590: $i += 3;
1591: continue;
1592:
1593: } catch (Exception $ex) {
1594: throw new ArgumentException("Invalid hex notation in the specified printer commands at index: ".$i);
1595: }
1596: }
1597: }
1598: }
1599: }
1600:
1601: $buffer .= substr($s, $i, 1);
1602:
1603: $i++;
1604: }
1605:
1606: return $buffer;
1607:
1608: }
1609:
1610: public static function intToArray($i){
1611: return pack('C4',
1612: ($i >> 0) & 0xFF,
1613: ($i >> 8) & 0xFF,
1614: ($i >> 16) & 0xFF,
1615: ($i >> 24) & 0xFF
1616: );
1617: }
1618:
1619: public static function strleft($s1, $s2) {
1620: return substr($s1, 0, strpos($s1, $s2));
1621: }
1622:
1623: public static function strContains($s1, $s2){
1624: return (strpos($s1, $s2) !== false);
1625: }
1626:
1627: public static function strEndsWith($s1, $s2)
1628: {
1629: return substr($s1, -strlen($s2)) === $s2;
1630: }
1631:
1632: public static function strStartsWith($s1, $s2)
1633: {
1634: return substr($s1, 0, strlen($s2)) === $s2;
1635: }
1636:
1637: public static function genRandomString($asciiCharStart = 33, $asciiCharEnd = 126, $charsCount = 32) {
1638:
1639: $allowed_chars = '';
1640: for($i = $asciiCharStart; $i <= $asciiCharEnd; $i++) {
1641: $allowed_chars .= chr($i);
1642: }
1643:
1644: $len = strlen($allowed_chars);
1645: $random_string = '';
1646: for($i = 0; $i < $charsCount; $i++) {
1647: $random_string .= $allowed_chars[mt_rand(0, $len - 1)];
1648: }
1649:
1650: return $random_string;
1651: }
1652:
1653: public static function getLicense()
1654: {
1655: $lo = WebClientPrint::$licenseOwner;
1656: $lk = WebClientPrint::$licenseKey;
1657:
1658: $uid = substr(uniqid(), 0, 8);
1659:
1660: $buffer = 'php>';
1661:
1662: if (Utils::isNullOrEmptyString($lo)){
1663: $buffer .= substr(uniqid(), 0, 8);
1664: } else {
1665: $buffer .= $lo;
1666: }
1667:
1668: $buffer .= chr(124);
1669:
1670: $license_hash = '';
1671:
1672: if (Utils::isNullOrEmptyString($lk)){
1673: $license_hash = substr(uniqid(), 0, 8);
1674: } else {
1675: $license_hash = hash('sha256', $lk . $uid, false);
1676: }
1677:
1678: $buffer .= $license_hash;
1679: $buffer .= chr(124);
1680: $buffer .= $uid;
1681:
1682: return $buffer;
1683: }
1684: }
1685:
1686: 1687: 1688:
1689: class ClientPrintJob{
1690:
1691: 1692: 1693: 1694: 1695: 1696: 1697: 1698: 1699: 1700:
1701: public $clientPrinter = null;
1702: 1703: 1704: 1705:
1706: public $printerCommands = '';
1707: 1708: 1709: 1710: 1711: 1712: 1713:
1714: public $printerCommandsCopies = 1;
1715: 1716: 1717: 1718: 1719: 1720: 1721: 1722: 1723:
1724: public $formatHexValues = false;
1725: 1726: 1727: 1728:
1729: public $printFile = null;
1730: 1731: 1732: 1733:
1734: public $printFileGroup = null;
1735:
1736:
1737: 1738: 1739: 1740: 1741:
1742: public function sendToClient(){
1743:
1744: $cpjHeader = chr(99).chr(112).chr(106).chr(2);
1745:
1746: $buffer = '';
1747:
1748: if (!Utils::isNullOrEmptyString($this->printerCommands)){
1749: if ($this->printerCommandsCopies > 1){
1750: $buffer .= 'PCC='.$this->printerCommandsCopies.Utils::SER_SEP;
1751: }
1752: if($this->formatHexValues){
1753: $buffer .= Utils::formatHexValues ($this->printerCommands);
1754: } else {
1755: $buffer .= $this->printerCommands;
1756: }
1757: } else if (isset ($this->printFile)){
1758: $buffer = $this->printFile->serialize();
1759: } else if (isset ($this->printFileGroup)){
1760: $buffer = 'wcpPFG:';
1761: $zip = new ZipArchive;
1762: $cacheFileName = (Utils::strEndsWith(WebClientPrint::$wcpCacheFolder, '/')?WebClientPrint::$wcpCacheFolder:WebClientPrint::$wcpCacheFolder.'/').'PFG'.uniqid().'.zip';
1763: $res = $zip->open($cacheFileName, ZipArchive::CREATE);
1764: if ($res === TRUE) {
1765: foreach ($this->printFileGroup as $printFile) {
1766: $file = $printFile->fileName;
1767: if($printFile->copies > 1){
1768: $pfc = 'PFC='.$printFile->copies;
1769: $file = substr($file, 0, strrpos($file, '.')).$pfc.substr($file, strrpos($file, '.'));
1770: }
1771: if(is_a($printFile, 'PrintFilePDF')) $file .= '.wpdf';
1772: if(is_a($printFile, 'PrintFileTXT')) $file .= '.wtxt';
1773:
1774: $zip->addFromString($file, $printFile->getFileContent());
1775: }
1776: $zip->close();
1777: $handle = fopen($cacheFileName, 'rb');
1778: $buffer .= fread($handle, filesize($cacheFileName));
1779: fclose($handle);
1780: unlink($cacheFileName);
1781: } else {
1782: $buffer='Creating PrintFileGroup failed. Cannot create zip file.';
1783: }
1784: }
1785:
1786: $arrIdx1 = Utils::intToArray(strlen($buffer));
1787:
1788: if (!isset($this->clientPrinter)){
1789: $this->clientPrinter = new UserSelectedPrinter();
1790: }
1791:
1792: $buffer .= $this->clientPrinter->serialize();
1793:
1794: $arrIdx2 = Utils::intToArray(strlen($buffer));
1795:
1796: $buffer .= Utils::getLicense();
1797:
1798: return $cpjHeader.$arrIdx1.$arrIdx2.$buffer;
1799: }
1800:
1801: }
1802:
1803: 1804: 1805:
1806: class ClientPrintJobGroup{
1807:
1808: 1809: 1810: 1811:
1812: public $clientPrintJobGroup = null;
1813:
1814: 1815: 1816: 1817: 1818:
1819: public function sendToClient(){
1820:
1821: if (isset ($this->clientPrintJobGroup)){
1822: $groups = count($this->clientPrintJobGroup);
1823:
1824: $dataPartIndexes = Utils::intToArray($groups);
1825:
1826: $cpjgHeader = chr(99).chr(112).chr(106).chr(103).chr(2);
1827:
1828: $buffer = '';
1829:
1830: $cpjBytesCount = 0;
1831:
1832: foreach ($this->clientPrintJobGroup as $cpj) {
1833: $cpjBuffer = '';
1834:
1835: if (!Utils::isNullOrEmptyString($cpj->printerCommands)){
1836: if ($cpj->printerCommandsCopies > 1){
1837: $cpjBuffer .= 'PCC='.$cpj->printerCommandsCopies.Utils::SER_SEP;
1838: }
1839: if($cpj->formatHexValues){
1840: $cpjBuffer .= Utils::formatHexValues ($cpj->printerCommands);
1841: } else {
1842: $cpjBuffer .= $cpj->printerCommands;
1843: }
1844: } else if (isset ($cpj->printFile)){
1845: $cpjBuffer = $cpj->printFile->serialize();
1846: } else if (isset ($cpj->printFileGroup)){
1847: $cpjBuffer = 'wcpPFG:';
1848: $zip = new ZipArchive;
1849: $cacheFileName = (Utils::strEndsWith(WebClientPrint::$wcpCacheFolder, '/')?WebClientPrint::$wcpCacheFolder:WebClientPrint::$wcpCacheFolder.'/').'PFG'.uniqid().'.zip';
1850: $res = $zip->open($cacheFileName, ZipArchive::CREATE);
1851: if ($res === TRUE) {
1852: foreach ($cpj->printFileGroup as $printFile) {
1853: $file = $printFile->fileName;
1854: if($printFile->copies > 1){
1855: $pfc = 'PFC='.$printFile->copies;
1856: $file = substr($file, 0, strrpos($file, '.')).$pfc.substr($file, strrpos($file, '.'));
1857: }
1858: if(is_a($printFile, 'PrintFilePDF')) $file .= '.wpdf';
1859: if(is_a($printFile, 'PrintFileTXT')) $file .= '.wtxt';
1860:
1861: $zip->addFromString($file, $printFile->getFileContent());
1862: }
1863: $zip->close();
1864: $handle = fopen($cacheFileName, 'rb');
1865: $cpjBuffer .= fread($handle, filesize($cacheFileName));
1866: fclose($handle);
1867: unlink($cacheFileName);
1868: } else {
1869: $cpjBuffer='Creating PrintFileGroup failed. Cannot create zip file.';
1870: }
1871: }
1872:
1873: $arrIdx1 = Utils::intToArray(strlen($cpjBuffer));
1874:
1875: if (!isset($cpj->clientPrinter)){
1876: $cpj->clientPrinter = new UserSelectedPrinter();
1877: }
1878:
1879: $cpjBuffer .= $cpj->clientPrinter->serialize();
1880:
1881: $cpjBytesCount += strlen($arrIdx1.$cpjBuffer);
1882:
1883: $dataPartIndexes .= Utils::intToArray($cpjBytesCount);
1884:
1885: $buffer .= $arrIdx1.$cpjBuffer;
1886: }
1887:
1888:
1889: $buffer .= Utils::getLicense();
1890:
1891: return $cpjgHeader.$dataPartIndexes.$buffer;
1892:
1893:
1894: } else {
1895:
1896: return NULL;
1897: }
1898:
1899:
1900: }
1901: }