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: }