Overview

Namespaces

  • Neodynamic
    • SDK
      • Web
  • PHP

Classes

  • ClientPrinter
  • ClientPrintJob
  • DefaultPrinter
  • InstalledPrinter
  • NetworkPrinter
  • ParallelPortPrinter
  • PrintFile
  • SerialPortHandshake
  • SerialPortParity
  • SerialPortPrinter
  • SerialPortStopBits
  • UserSelectedPrinter
  • Utils
  • WebClientPrint
  • Overview
  • Namespace
  • Class
  • Tree
  1: <?php
  2: 
  3: namespace Neodynamic\SDK\Web;
  4: use Exception;
  5: use ZipArchive;
  6: 
  7: // Setting WebClientPrint
  8: WebClientPrint::$licenseOwner = '';
  9: WebClientPrint::$licenseKey = '';
 10: 
 11: //IMPORTANT SETTINGS:
 12: //===================
 13: //Set ABSOLUTE URL to WebClientPrint.php file
 14: WebClientPrint::$webClientPrintAbsoluteUrl = Utils::getRoot().'/wcpdev/source/WebClientPrint.php';
 15: //Set wcpcache folder RELATIVE to WebClientPrint.php file
 16: //FILE WRITE permission on this folder is required!!!
 17: WebClientPrint::$wcpCacheFolder = 'wcpcache/';
 18: //===================
 19: 
 20: // Clean built-in Cache
 21: // NOTE: Remove it if you implement your own cache system
 22: WebClientPrint::cacheClean(5); //in minutes
 23: 
 24: // Process request
 25: $urlParts = parse_url($_SERVER['REQUEST_URI']);
 26: if (isset($urlParts['query'])){
 27:     if (Utils::strContains($urlParts['query'], WebClientPrint::WCP)){
 28:         WebClientPrint::processRequest($urlParts['query']);
 29:     }
 30: } 
 31: 
 32: 
 33: /**
 34:  * WebClientPrint provides functions for registering the "WebClientPrint for PHP" solution 
 35:  * script code in PHP web pages as well as for processing client requests and managing the
 36:  * internal cache.
 37:  * 
 38:  * @author Neodynamic <http://neodynamic.com/support>
 39:  * @copyright (c) 2013, Neodynamic SRL
 40:  * @license http://neodynamic.com/eula Neodynamic EULA
 41:  */
 42: class WebClientPrint {
 43:    
 44:     const VERSION = '2.0.0.0';
 45:     const CLIENT_PRINT_JOB = "clientPrint";
 46:     const WCP = 'WEB_CLIENT_PRINT';
 47:     
 48:     const WCP_CACHE_WCPP_INSTALLED = 'WCPP_INSTALLED';
 49:     const WCP_CACHE_WCPP_VER = 'WCPP_VER';
 50:     const WCP_CACHE_PRINTERS = 'PRINTERS';
 51:     
 52:     /**
 53:      * Gets or sets the License Owner
 54:      * @var string 
 55:      */
 56:     static $licenseOwner = '';
 57:     /**
 58:      * Gets or sets the License Key
 59:      * @var string
 60:      */
 61:     static $licenseKey = '';
 62:     /**
 63:      * Gets or sets the ABSOLUTE URL to WebClientPrint.php file
 64:      * @var string
 65:      */
 66:     static $webClientPrintAbsoluteUrl = '';
 67:     /**
 68:      * Gets or sets the wcpcache folder URL RELATIVE to WebClientPrint.php file. 
 69:      * FILE WRITE permission on this folder is required!!!
 70:      * @var string
 71:      */
 72:     static $wcpCacheFolder = '';
 73:     
 74:     /**
 75:      * Adds a new entry to the built-in file system cache. 
 76:      * @param string $sid The user's session id
 77:      * @param string $key The cache entry key
 78:      * @param string $val The data value to put in the cache
 79:      * @throws Exception
 80:      */
 81:     public static function cacheAdd($sid, $key, $val){
 82:         if (Utils::isNullOrEmptyString(self::$wcpCacheFolder)){
 83:             throw new Exception('WebClientPrint wcpCacheFolder is missing, please specify it.');
 84:         }
 85:         if (Utils::isNullOrEmptyString($sid)){
 86:             throw new Exception('WebClientPrint FileName cache is missing, please specify it.');
 87:         }
 88:         $cacheFileName = (Utils::strEndsWith(self::$wcpCacheFolder, '/')?self::$wcpCacheFolder:self::$wcpCacheFolder.'/').$sid.'.wcpcache';
 89:         $dataWCPP_VER = '';
 90:         $dataPRINTERS = '';
 91:             
 92:         if(file_exists($cacheFileName)){
 93:             $cache_info = parse_ini_file($cacheFileName);
 94:             
 95:             $dataWCPP_VER = $cache_info[self::WCP_CACHE_WCPP_VER];
 96:             $dataPRINTERS = $cache_info[self::WCP_CACHE_PRINTERS];
 97:         }
 98:         
 99:         if ($key === self::WCP_CACHE_WCPP_VER){
100:             $dataWCPP_VER = self::WCP_CACHE_WCPP_VER.'='.'"'.$val.'"';
101:             $dataPRINTERS = self::WCP_CACHE_PRINTERS.'='.'"'.$dataPRINTERS.'"';
102:         } else if ($key === self::WCP_CACHE_PRINTERS){
103:             $dataWCPP_VER = self::WCP_CACHE_WCPP_VER.'='.'"'.$dataWCPP_VER.'"';
104:             $dataPRINTERS = self::WCP_CACHE_PRINTERS.'='.'"'.$val.'"';
105:         }
106: 
107:         $data = $dataWCPP_VER.chr(13).chr(10).$dataPRINTERS;
108:         $handle = fopen($cacheFileName, 'w') or die('Cannot open file:  '.$cacheFileName);  
109:         fwrite($handle, $data);
110:         fclose($handle);
111:         
112:     }
113:     
114:     /**
115:      * Gets a value from the built-in file system cache based on the specified sid & key 
116:      * @param string $sid The user's session id
117:      * @param string $key The cache entry key
118:      * @return string Returns the value from the cache for the specified sid & key if it's found; or an empty string otherwise.
119:      * @throws Exception
120:      */
121:     public static function cacheGet($sid, $key){
122:         if (Utils::isNullOrEmptyString(self::$wcpCacheFolder)){
123:             throw new Exception('WebClientPrint wcpCacheFolder is missing, please specify it.');
124:         }
125:         if (Utils::isNullOrEmptyString($sid)){
126:             throw new Exception('WebClientPrint FileName cache is missing, please specify it.');
127:         }
128:         $cacheFileName = (Utils::strEndsWith(self::$wcpCacheFolder, '/')?self::$wcpCacheFolder:self::$wcpCacheFolder.'/').$sid.'.wcpcache';
129:         if(file_exists($cacheFileName)){
130:             $cache_info = parse_ini_file($cacheFileName);
131:                 
132:             if($key===self::WCP_CACHE_WCPP_VER || $key===self::WCP_CACHE_WCPP_INSTALLED){
133:                 return $cache_info[self::WCP_CACHE_WCPP_VER];
134:             }else if($key===self::WCP_CACHE_PRINTERS){
135:                 return $cache_info[self::WCP_CACHE_PRINTERS];
136:             }else{
137:                 return '';
138:             }
139:         }else{
140:             return '';
141:         }
142:     }
143:     
144:     /**
145:      * Cleans the built-in file system cache
146:      * @param type $minutes The number of minutes after any files on the cache will be removed.
147:      */
148:     public static function cacheClean($minutes){
149:         if (!Utils::isNullOrEmptyString(self::$wcpCacheFolder)){
150:             $cacheDir = (Utils::strEndsWith(self::$wcpCacheFolder, '/')?self::$wcpCacheFolder:self::$wcpCacheFolder.'/');
151:             if ($handle = opendir($cacheDir)) {
152:                  while (false !== ($file = readdir($handle))) {
153:                     if ($file!='.' && $file!='..' && (time()-filectime($cacheDir.$file)) > (60*$minutes)) {
154:                         unlink($cacheDir.$file);
155:                     }
156:                  }
157:                  closedir($handle);
158:             }
159:         }
160:     }
161:     
162:     /**
163:      * Returns script code for detecting whether WCPP is installed at the client machine.
164:      *
165:      * The WCPP-detection script code ends with a 'success' or 'failure' status.
166:      * You can handle both situation by creating two javascript functions which names 
167:      * must be wcppDetectOnSuccess() and wcppDetectOnFailure(). 
168:      * These two functions will be automatically invoked by the WCPP-detection script code.
169:      * 
170:      * The WCPP-detection script uses a delay time variable which by default is 10000 ms (10 sec). 
171:      * You can change it by creating a javascript global variable which name must be wcppPingDelay_ms. 
172:      * For example, to use 5 sec instead of 10, you should add this to your script: 
173:      *   
174:      * var wcppPingDelay_ms = 5000;
175:      *    
176:      * @return string A [script] tag linking to the WCPP-detection script code.
177:      * @throws Exception
178:      */
179:     public static function createWcppDetectionScript(){
180:         
181:         if (Utils::isNullOrEmptyString(self::$webClientPrintAbsoluteUrl)){
182:             throw new Exception('WebClientPrint absolute URL is missing, please specify it.');
183:         }
184:         
185:         $buffer = '<script type="text/javascript">';
186:         if(Utils::isIE6to9() || Utils::isIE10orGreater()){
187:             $buffer .= 'var wcppPingNow=false;'; 
188:         } else {
189:             $buffer .= 'var wcppPingNow=true;';
190:         }
191:         $buffer .= '</script>';
192:         
193:         $wcpHandler = self::$webClientPrintAbsoluteUrl.'?'.self::WCP.'&d='.session_id();
194:         $buffer .= '<script src="'.$wcpHandler.'" type="text/javascript"></script>';
195:         
196:         if(Utils::isIE6to9() || Utils::isIE10orGreater()){
197:             $crlf = chr(13).chr(10);
198:             $buffer .= $crlf.$crlf;
199:             $buffer .= '<!--[if WCPP]>'.$crlf;
200:             $buffer .= '<script type="text/javascript">'.$crlf;
201:             $buffer .= '$(document).ready(function(){jsWCPP.ping();});'.$crlf;
202:             $buffer .= '</script>'.$crlf;
203:             $buffer .= '<![endif]-->'.$crlf;
204:             $buffer .= '<!--[if !WCPP]>'.$crlf;
205:             $buffer .= '<script type="text/javascript">'.$crlf;
206:             $buffer .= '$(document).ready(function(){wcppDetectOnFailure();});'.$crlf;
207:             $buffer .= '</script>'.$crlf;
208:             $buffer .= '<![endif]-->'.$crlf;
209:          }
210:          
211:          return $buffer;
212:     }
213:     
214:     /**
215:      * Returns a string containing a HTML meta tag for the WCPP-detection procedure.
216:      * 
217:      * The meta tag X-UA-Compatible is generated for Internet Explorer (IE) 10 or greater to emulate IE9. 
218:      * If this meta tag is not generated, then IE10 or greater will display some unwanted dialog box to 
219:      * the user when the WCPP-detection script is executed.
220:      * 
221:      * @return string A string containing a HTML meta tag for the WCPP-detection procedure.
222:      */
223:     public static function getWcppDetectionMetaTag(){
224:          return Utils::isIE10orGreater()?'<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE9" />':'';
225:     }
226:     
227:     /**
228:      * Returns a [script] tag linking to the WebClientPrint script code by using 
229:      * the specified URL for the client print job generation.
230:      * 
231:      * @param string $clientPrintJobUrl The URL to the php file that creates ClientPrintJob objects.
232:      * @return string A [script] tag linking to the WebClientPrint script code by using the specified URL for the client print job generation.
233:      * @throws Exception
234:      */
235:     public static function createScript($clientPrintJobUrl){
236:         if (Utils::isNullOrEmptyString(self::$webClientPrintAbsoluteUrl)){
237:             throw new Exception('WebClientPrint absolute URL is missing, please specify it.');
238:         }
239:         $wcpHandler = self::$webClientPrintAbsoluteUrl.'?';
240:         $wcpHandler .= self::WCP;
241:         $wcpHandler .= '&';
242:         $wcpHandler .= self::VERSION;
243:         $wcpHandler .= '&';
244:         $wcpHandler .= microtime(true);
245:         $wcpHandler .= '&u=';
246:         $wcpHandler .= base64_encode($clientPrintJobUrl);
247:         return '<script src="'.$wcpHandler.'" type="text/javascript"></script>';
248:     }
249:     
250:     public static function processRequest($data){
251:         
252:         $PING = 'wcppping';
253:         $SID = 'sid';
254:         $HAS_WCPP = 'wcppInstalled';
255:         
256:         $GEN_WCP_SCRIPT_VERSION = 'v2.0.0.0';
257:         $GEN_WCP_SCRIPT_URL = 'u';
258:         $GEN_DETECT_WCPP_SCRIPT = 'd';
259:         $WCP_SCRIPT_AXD_GET_PRINTERS = 'getPrinters';
260:         $WCPP_SET_PRINTERS = 'printers';
261:         $WCP_SCRIPT_AXD_GET_WCPPVERSION = 'getWcppVersion';
262:         $WCPP_SET_VERSION = 'wcppVer';
263:         
264:         $wcpUrl=Utils::getRoot().$_SERVER['REQUEST_URI'];
265:         $wcpUrl=substr($wcpUrl, 0, strpos($wcpUrl, '.php?')+4);
266:         
267:         parse_str($data, $qs);
268:     
269:         if(isset($qs[$SID])){
270:             if(isset($qs[$PING])){
271:                 if (isset($qs[$WCPP_SET_VERSION])){
272:                     self::cacheAdd($qs[$SID], self::WCP_CACHE_WCPP_VER, $qs[$WCPP_SET_VERSION]);
273:                 }else{
274:                     self::cacheAdd($qs[$SID], self::WCP_CACHE_WCPP_VER,'1.0.0.0');
275:                 }
276:             }else if(isset($qs[$WCPP_SET_PRINTERS])){
277:                 self::cacheAdd($qs[$SID], self::WCP_CACHE_PRINTERS, strlen($qs[$WCPP_SET_PRINTERS]) > 0 ? base64_decode($qs[$WCPP_SET_PRINTERS]) : '');
278:             }else if(strpos($data, $WCP_SCRIPT_AXD_GET_PRINTERS)>0){
279:                 ob_clean();
280:                 header('Content-type: text/plain');
281:                 echo self::cacheGet($qs[$SID], self::WCP_CACHE_PRINTERS);
282:             }else if(isset($qs[$WCPP_SET_VERSION])){
283:                 if(strlen($qs[$WCPP_SET_VERSION]) > 0){
284:                     self::cacheAdd($qs[$SID], self::WCP_CACHE_WCPP_VER, $qs[$WCPP_SET_VERSION]);
285:                 }
286:             }else if(strpos($data, $WCP_SCRIPT_AXD_GET_WCPPVERSION)>0){
287:                 ob_clean();
288:                 header('Content-type: text/plain');
289:                 echo self::cacheGet($qs[$SID], self::WCP_CACHE_WCPP_VER);
290:             }else{
291:                 ob_clean();
292:                 header('Content-type: text/plain');
293:                 echo self::cacheGet($qs[$SID], self::WCP_CACHE_WCPP_INSTALLED);
294:             }
295:         }else if(isset($qs[$GEN_DETECT_WCPP_SCRIPT])){
296:             
297:             $curSID = $qs[$GEN_DETECT_WCPP_SCRIPT];
298:             $onSuccessScript = 'wcppDetectOnSuccess(data);';
299:             $onFailureScript = 'wcppDetectOnFailure();';
300:             $dynamicIframeId = 'i'.substr(uniqid(), 0, 3);
301:             $absoluteWcpAxd = $wcpUrl.'?'.self::WCP.'&'.$SID.'='.$curSID;
302:             
303:             $s1 = 'dmFyIGpzV0NQUD0oZnVuY3Rpb24oKXt2YXIgc2V0WFhYLU5FTy1IVE1MLUlELVhYWD1mdW5jdGlvbigpe2lmKHdpbmRvdy5jaHJvbWUpeyQoJyNYWFgtTkVPLUhUTUwtSUQtWFhYJykuYXR0cignaHJlZicsJ3dlYmNsaWVudHByaW50OicrYXJndW1lbnRzWzBdKTt2YXIgYT0kKCdhI1hYWC1ORU8tSFRNTC1JRC1YWFgnKVswXTt2YXIgZXZPYmo9ZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ01vdXNlRXZlbnRzJyk7ZXZPYmouaW5pdEV2ZW50KCdjbGljaycsdHJ1ZSx0cnVlKTthLmRpc3BhdGNoRXZlbnQoZXZPYmopfWVsc2V7JCgnI1hYWC1ORU8tSFRNTC1JRC1YWFgnKS5hdHRyKCdzcmMnLCd3ZWJjbGllbnRwcmludDonK2FyZ3VtZW50c1swXSl9fTtyZXR1cm57aW5pdDpmdW5jdGlvbigpe2lmKHdpbmRvdy5jaHJvbWUpeyQoJzxhIC8+Jyx7aWQ6J1hYWC1ORU8tSFRNTC1JRC1YWFgnfSkuYXBwZW5kVG8oJ2JvZHknKX1lbHNleyQoJzxpZnJhbWUgLz4nLHtuYW1lOidYWFgtTkVPLUhUTUwtSUQtWFhYJyxpZDonWFhYLU5FTy1IVE1MLUlELVhYWCcsd2lkdGg6JzEnLGhlaWdodDonMScsc3R5bGU6J3Zpc2liaWxpdHk6aGlkZGVuO3Bvc2l0aW9uOmFic29sdXRlJ30pLmFwcGVuZFRvKCdib2R5Jyl9fSxwaW5nOmZ1bmN0aW9uKCl7c2V0WFhYLU5FTy1IVE1MLUlELVhYWCgnWFhYLU5FTy1QSU5HLVVSTC1YWFgnKyhhcmd1bWVudHMubGVuZ3RoPT0xPycmJythcmd1bWVudHNbMF06JycpKTt2YXIgZGVsYXlfbXM9KHR5cGVvZiB3Y3BwUGluZ0RlbGF5X21zPT09J3VuZGVmaW5lZCcpPzEwMDAwOndjcHBQaW5nRGVsYXlfbXM7c2V0VGltZW91dChmdW5jdGlvbigpeyQuZ2V0KCdYWFgtTkVPLVVTRVItSEFTLVdDUFAtWFhYJyxmdW5jdGlvbihkYXRhKXtpZihkYXRhIT0nZicpe1hYWC1ORU8tT04tU1VDQ0VTUy1TQ1JJUFQtWFhYfWVsc2V7WFhYLU5FTy1PTi1GQUlMVVJFLVNDUklQVC1YWFh9fSl9LGRlbGF5X21zKX19fSkoKTsgJChkb2N1bWVudCkucmVhZHkoZnVuY3Rpb24oKXtqc1dDUFAuaW5pdCgpO2lmKHdjcHBQaW5nTm93KWpzV0NQUC5waW5nKCk7fSk7';
304:             $s2 = base64_decode($s1);
305:             $s2 = str_replace('XXX-NEO-HTML-ID-XXX', $dynamicIframeId, $s2);
306:             $s2 = str_replace('XXX-NEO-PING-URL-XXX', $absoluteWcpAxd.'&'.$PING, $s2);
307:             $s2 = str_replace('XXX-NEO-USER-HAS-WCPP-XXX', $absoluteWcpAxd, $s2);
308:             $s2 = str_replace('XXX-NEO-ON-SUCCESS-SCRIPT-XXX', $onSuccessScript, $s2);
309:             $s2 = str_replace('XXX-NEO-ON-FAILURE-SCRIPT-XXX', $onFailureScript, $s2);
310:             
311:             ob_clean();
312:             header('Content-type: application/javascript');
313:             echo $s2;
314:             
315:         }else if(isset($qs[$GEN_WCP_SCRIPT_URL])){
316:             
317:             $clientPrintJobUrl = base64_decode($qs[$GEN_WCP_SCRIPT_URL]);
318:             if (strpos($clientPrintJobUrl, '?')>0){
319:                 $clientPrintJobUrl .= '&';
320:             }else{
321:                 $clientPrintJobUrl .= '?';
322:             }
323:             $clientPrintJobUrl .= self::CLIENT_PRINT_JOB;
324:             $absoluteWcpAxd = $wcpUrl;
325:             $wcppGetPrintersParam = '-getPrinters:'.$absoluteWcpAxd.'?'.self::WCP.'&'.$SID.'=';
326:             $wcpHandlerGetPrinters = $absoluteWcpAxd.'?'.self::WCP.'&'.$WCP_SCRIPT_AXD_GET_PRINTERS.'&'.$SID.'=';
327:             $wcppGetWcppVerParam = '-getWcppVersion:'.$absoluteWcpAxd.'?'.self::WCP.'&'.$SID.'=';
328:             $wcpHandlerGetWcppVer = $absoluteWcpAxd.'?'.self::WCP.'&'.$WCP_SCRIPT_AXD_GET_WCPPVERSION.'&'.$SID.'=';
329: 
330:             $s1 = 'dmFyIGpzV2ViQ2xpZW50UHJpbnQ9KGZ1bmN0aW9uKCl7dmFyIHNldEE9ZnVuY3Rpb24oKXt2YXIgZV9pZD0naWRfJytuZXcgRGF0ZSgpLmdldFRpbWUoKTtpZih3aW5kb3cuY2hyb21lKXskKCdib2R5JykuYXBwZW5kKCc8YSBpZD0iJytlX2lkKyciPjwvYT4nKTskKCcjJytlX2lkKS5hdHRyKCdocmVmJywnd2ViY2xpZW50cHJpbnQ6Jythcmd1bWVudHNbMF0pO3ZhciBhPSQoJ2EjJytlX2lkKVswXTt2YXIgZXZPYmo9ZG9jdW1lbnQuY3JlYXRlRXZlbnQoJ01vdXNlRXZlbnRzJyk7ZXZPYmouaW5pdEV2ZW50KCdjbGljaycsdHJ1ZSx0cnVlKTthLmRpc3BhdGNoRXZlbnQoZXZPYmopfWVsc2V7JCgnYm9keScpLmFwcGVuZCgnPGlmcmFtZSBuYW1lPSInK2VfaWQrJyIgaWQ9IicrZV9pZCsnIiB3aWR0aD0iMSIgaGVpZ2h0PSIxIiBzdHlsZT0idmlzaWJpbGl0eTpoaWRkZW47cG9zaXRpb246YWJzb2x1dGUiIC8+Jyk7JCgnIycrZV9pZCkuYXR0cignc3JjJywnd2ViY2xpZW50cHJpbnQ6Jythcmd1bWVudHNbMF0pfXNldFRpbWVvdXQoZnVuY3Rpb24oKXskKCcjJytlX2lkKS5yZW1vdmUoKX0sNTAwMCl9O3JldHVybntwcmludDpmdW5jdGlvbigpe3NldEEoJ1VSTF9QUklOVF9KT0InKyhhcmd1bWVudHMubGVuZ3RoPT0xPycmJythcmd1bWVudHNbMF06JycpKX0sZ2V0UHJpbnRlcnM6ZnVuY3Rpb24oKXtzZXRBKCdVUkxfV0NQX0FYRF9XSVRIX0dFVF9QUklOVEVSU19DT01NQU5EJyskKCcjc2lkJykudmFsKCkpO3ZhciBkZWxheV9tcz0odHlwZW9mIHdjcHBHZXRQcmludGVyc0RlbGF5X21zPT09J3VuZGVmaW5lZCcpPzEwMDAwOndjcHBHZXRQcmludGVyc0RlbGF5X21zO3NldFRpbWVvdXQoZnVuY3Rpb24oKXskLmdldCgnVVJMX1dDUF9BWERfR0VUX1BSSU5URVJTJyskKCcjc2lkJykudmFsKCksZnVuY3Rpb24oZGF0YSl7aWYoZGF0YS5sZW5ndGg+MCl7d2NwR2V0UHJpbnRlcnNPblN1Y2Nlc3MoZGF0YSl9ZWxzZXt3Y3BHZXRQcmludGVyc09uRmFpbHVyZSgpfX0pfSxkZWxheV9tcyl9LGdldFdjcHBWZXI6ZnVuY3Rpb24oKXtzZXRBKCdVUkxfV0NQX0FYRF9XSVRIX0dFVF9XQ1BQVkVSU0lPTl9DT01NQU5EJyskKCcjc2lkJykudmFsKCkpO3ZhciBkZWxheV9tcz0odHlwZW9mIHdjcHBHZXRWZXJEZWxheV9tcz09PSd1bmRlZmluZWQnKT8xMDAwMDp3Y3BwR2V0VmVyRGVsYXlfbXM7c2V0VGltZW91dChmdW5jdGlvbigpeyQuZ2V0KCdVUkxfV0NQX0FYRF9HRVRfV0NQUFZFUlNJT04nKyQoJyNzaWQnKS52YWwoKSxmdW5jdGlvbihkYXRhKXtpZihkYXRhLmxlbmd0aD4wKXt3Y3BHZXRXY3BwVmVyT25TdWNjZXNzKGRhdGEpfWVsc2V7d2NwR2V0V2NwcFZlck9uRmFpbHVyZSgpfX0pfSxkZWxheV9tcyl9LHNlbmQ6ZnVuY3Rpb24oKXtzZXRBLmFwcGx5KHRoaXMsYXJndW1lbnRzKX19fSkoKTs=';
331:             $s2 = base64_decode($s1);
332:             $s2 = str_replace('URL_PRINT_JOB', $clientPrintJobUrl, $s2);
333:             $s2 = str_replace('URL_WCP_AXD_WITH_GET_PRINTERS_COMMAND', $wcppGetPrintersParam, $s2);
334:             $s2 = str_replace('URL_WCP_AXD_GET_PRINTERS', $wcpHandlerGetPrinters, $s2);
335:             $s2 = str_replace('URL_WCP_AXD_WITH_GET_WCPPVERSION_COMMAND', $wcppGetWcppVerParam, $s2);
336:             $s2 = str_replace('URL_WCP_AXD_GET_WCPPVERSION', $wcpHandlerGetWcppVer, $s2);
337:             
338:             ob_clean();
339:             header('Content-type: application/javascript');
340:             echo $s2;
341:         }
342:         
343:     }
344:     
345: }
346: 
347: /**
348:  * The base class for all kind of printers supported at the client side.
349:  */
350: abstract class ClientPrinter{
351:     
352:     public $printerId;
353:     public function serialize(){
354:         
355:     }
356: }
357: 
358: /**
359:  * It represents the default printer installed in the client machine.
360:  */
361: class DefaultPrinter extends ClientPrinter{
362:     public function __construct() {
363:         $this->printerId = chr(0);
364:     }
365:     
366:     public function serialize() {
367:         return $this->printerId;
368:     }
369: }
370: 
371: /**
372:  * It represents a printer installed in the client machine with an associated OS driver.
373:  */
374: class InstalledPrinter extends ClientPrinter{
375:     
376:     /**
377:      * Gets or sets the name of the printer installed in the client machine. Default value is an empty string.
378:      * @var string 
379:      */
380:     public $printerName = '';
381: 
382:     /**
383:      * Creates an instance of the InstalledPrinter class with the specified printer name.
384:      * @param string $printerName The name of the printer installed in the client machine.
385:      */
386:     public function __construct($printerName) {
387:         $this->printerId = chr(1);
388:         $this->printerName = $printerName;
389:     }
390:     
391:     
392:     public function serialize() {
393:         
394:         if (Utils::isNullOrEmptyString($this->printerName)){
395:              throw new Exception("The specified printer name is null or empty.");
396:         }
397:         
398:         return $this->printerId.$this->printerName;
399:     }
400: }
401: 
402: /**
403:  * It represents a printer which is connected through a parallel port in the client machine.
404:  */
405: class ParallelPortPrinter extends ClientPrinter{
406:     
407:     /**
408:      * Gets or sets the parallel port name, for example LPT1. Default value is "LPT1"
409:      * @var string 
410:      */
411:     public $portName = "LPT1";
412: 
413:     /**
414:      * Creates an instance of the ParallelPortPrinter class with the specified port name.
415:      * @param string $portName The parallel port name, for example LPT1.
416:      */
417:     public function __construct($portName) {
418:         $this->printerId = chr(2);
419:         $this->portName = $portName;
420:     }
421:     
422:     public function serialize() {
423:         
424:         if (Utils::isNullOrEmptyString($this->portName)){
425:              throw new Exception("The specified parallel port name is null or empty.");
426:         }
427:         
428:         return $this->printerId.$this->portName;
429:     }
430: }
431: 
432: /**
433:  * It represents a printer which is connected through a serial port in the client machine.
434:  */
435: class SerialPortPrinter extends ClientPrinter{
436:     
437:     /**
438:      * Gets or sets the serial port name, for example COM1. Default value is "COM1"
439:      * @var string 
440:      */
441:     public $portName = "COM1";
442:     /**
443:      * Gets or sets the serial port baud rate in bits per second. Default value is 9600
444:      * @var integer 
445:      */
446:     public $baudRate = 9600;
447:     /**
448:      * Gets or sets the serial port parity-checking protocol. Default value is NONE = 0
449:      * NONE = 0, ODD = 1, EVEN = 2, MARK = 3, SPACE = 4
450:      * @var integer 
451:      */
452:     public $parity = SerialPortParity::NONE;
453:     /**
454:      * Gets or sets the serial port standard number of stopbits per byte. Default value is ONE = 1
455:      * ONE = 1, TWO = 2, ONE_POINT_FIVE = 3
456:      * @var integer
457:      */
458:     public $stopBits = SerialPortStopBits::ONE;
459:     /**
460:      * Gets or sets the serial port standard length of data bits per byte. Default value is 8
461:      * @var integer
462:      */
463:     public $dataBits = 8;
464:     /**
465:      * Gets or sets the handshaking protocol for serial port transmission of data. Default value is XON_XOFF = 1
466:      * NONE = 0, REQUEST_TO_SEND = 2, REQUEST_TO_SEND_XON_XOFF = 3, XON_XOFF = 1
467:      * @var integer
468:      */
469:     public $flowControl = SerialPortHandshake::XON_XOFF;
470:     
471:     /**
472:      * Creates an instance of the SerialPortPrinter class wiht the specified information.
473:      * @param string $portName The serial port name, for example COM1.
474:      * @param integer $baudRate The serial port baud rate in bits per second.
475:      * @param integer $parity The serial port parity-checking protocol.
476:      * @param integer $stopBits The serial port standard number of stopbits per byte.
477:      * @param integer $dataBits The serial port standard length of data bits per byte.
478:      * @param integer $flowControl The handshaking protocol for serial port transmission of data.
479:      */
480:     public function __construct($portName, $baudRate, $parity, $stopBits, $dataBits, $flowControl) {
481:         $this->printerId = chr(3);
482:         $this->portName = $portName;
483:         $this->baudRate = $baudRate;
484:         $this->parity = $parity;
485:         $this->stopBits = $stopBits;
486:         $this->dataBits = $dataBits;
487:         $this->flowControl = $flowControl;
488:     }
489:     
490:     public function serialize() {
491:         
492:         if (Utils::isNullOrEmptyString($this->portName)){
493:              throw new Exception("The specified serial port name is null or empty.");
494:         }
495:         
496:         return $this->printerId.$this->portName.Utils::SER_SEP.$this->baudRate.Utils::SER_SEP.$this->dataBits.Utils::SER_SEP.$this->flowControl.Utils::SER_SEP.$this->parity.Utils::SER_SEP.$this->stopBits;
497:     }
498: }
499: 
500: /**
501:  * It represents a Network IP/Ethernet printer which can be reached from the client machine.
502:  */
503: class NetworkPrinter extends ClientPrinter{
504:     
505:     /**
506:      * Gets or sets the DNS name assigned to the printer. Default is an empty string
507:      * @var string 
508:      */
509:     public $dnsName = "";
510:     /**
511:      * Gets or sets the Internet Protocol (IP) address assigned to the printer. Default value is an empty string
512:      * @var string 
513:      */
514:     public $ipAddress = "";
515:     /**
516:      * Gets or sets the port number assigned to the printer. Default value is 0
517:      * @var integer 
518:      */
519:     public $port = 0;
520:     
521:     /**
522:      * Creates an instance of the NetworkPrinter class with the specified DNS name or IP Address, and port number.
523:      * @param string $dnsName The DNS name assigned to the printer.
524:      * @param string $ipAddress The Internet Protocol (IP) address assigned to the printer.
525:      * @param integer $port The port number assigned to the printer.
526:      */
527:     public function __construct($dnsName, $ipAddress, $port) {
528:         $this->printerId = chr(4);
529:         $this->dnsName = $dnsName;
530:         $this->ipAddress = $ipAddress;
531:         $this->port = $port;
532:     }
533:     
534:     public function serialize() {
535:         
536:         if (Utils::isNullOrEmptyString($this->dnsName) && Utils::isNullOrEmptyString($this->ipAddress)){
537:              throw new Exception("The specified network printer settings is not valid. You must specify the DNS Printer Name or its IP address.");
538:         }
539:         
540:         return $this->printerId.$this->dnsName.Utils::SER_SEP.$this->ipAddress.Utils::SER_SEP.$this->port;
541:     }
542: }
543: 
544: /**
545:  *  It represents a printer which will be selected by the user in the client machine. The user will be prompted with a print dialog.
546:  */
547: class UserSelectedPrinter extends ClientPrinter{
548:     public function __construct() {
549:         $this->printerId = chr(5);
550:     }
551:     
552:     public function serialize() {
553:         return $this->printerId;
554:     }
555: }
556: 
557: /**
558:  * Specifies the parity bit for Serial Port settings. 
559:  */
560: class SerialPortParity{
561:     const NONE = 0;
562:     const ODD = 1;
563:     const EVEN = 2;
564:     const MARK = 3;
565:     const SPACE = 4;
566: }
567: 
568: /**
569:  * Specifies the number of stop bits used for Serial Port settings.
570:  */
571: class SerialPortStopBits{
572:     const NONE = 0;
573:     const ONE = 1;
574:     const TWO = 2;
575:     const ONE_POINT_FIVE = 3;
576: }
577: 
578: /**
579:  * Specifies the control protocol used in establishing a serial port communication.
580:  */
581: class SerialPortHandshake{
582:     const NONE = 0;
583:     const REQUEST_TO_SEND = 2;
584:     const REQUEST_TO_SEND_XON_XOFF = 3;
585:     const XON_XOFF = 1;
586: }
587: 
588: /**
589:  * It represents a file in the server that will be printed at the client side.
590:  */
591: class PrintFile{
592:     
593:     /**
594:      * Gets or sets the path of the file at the server side that will be printed at the client side.
595:      * @var string 
596:      */
597:     public $filePath = '';
598:     /**
599:      * Gets or sets the file name that will be created at the client side. 
600:      * It must include the file extension like .pdf, .txt, .doc, .xls, etc.
601:      * @var string 
602:      */
603:     public $fileName = '';
604:     /**
605:      * Gets or sets the binary content of the file at the server side that will be printed at the client side.
606:      * @var string 
607:      */
608:     public $fileBinaryContent = '';
609:     
610:     const PREFIX = 'wcpPF:';
611:     const SEP = '|';
612:         
613:     /**
614:      * 
615:      * @param string $filePath The path of the file at the server side that will be printed at the client side.
616:      * @param string $fileName The file name that will be created at the client side. It must include the file extension like .pdf, .txt, .doc, .xls, etc.
617:      * @param string $fileBinaryContent The binary content of the file at the server side that will be printed at the client side.
618:      */
619:     public function __construct($filePath, $fileName, $fileBinaryContent) {
620:         $this->filePath = $filePath;
621:         $this->fileName = $fileName;
622:         $this->fileBinaryContent = $fileBinaryContent;
623:         
624:     }
625:     
626:     public function serialize() {
627:         return self::PREFIX.$this->fileName.self::SEP.$this->getFileContent();
628:     }
629:     
630:     public function getFileContent(){
631:         $content = $this->fileBinaryContent;
632:         if(!Utils::isNullOrEmptyString($this->filePath)){
633:             $handle = fopen($this->filePath, 'rb');
634:             $content = fread($handle, filesize($this->filePath));
635:             fclose($handle);
636:         }
637:         return $content;
638:     }
639: }
640: 
641: /**
642:  * Some utility functions used by WebClientPrint for PHP solution.
643:  */
644: class Utils{
645:     const SER_SEP = "|";
646:     
647:     static function isNullOrEmptyString($s){
648:         return (!isset($s) || trim($s)==='');
649:     }
650:     
651:     static function formatHexValues($s){
652:         
653:         $buffer = '';
654:             
655:         $l = strlen($s);
656:         $i = 0;
657: 
658:         while ($i < $l)
659:         {
660:             if ($s[$i] == '0')
661:             {
662:                 if ($i + 1 < $l && ($s[$i] == '0' && $s[$i + 1] == 'x'))
663:                 {
664:                     if ($i + 2 < $l &&
665:                         (($s[$i + 2] >= '0' && $s[$i + 2] <= '9') || ($s[$i + 2] >= 'a' && $s[$i + 2] <= 'f') || ($s[$i + 2] >= 'A' && $s[$i + 2] <= 'F')))
666:                     {
667:                         if ($i + 3 < $l &&
668:                            (($s[$i + 3] >= '0' && $s[$i + 3] <= '9') || ($s[$i + 3] >= 'a' && $s[$i + 3] <= 'f') || ($s[$i + 3] >= 'A' && $s[$i + 3] <= 'F')))
669:                         {
670:                             try{
671:                                 $buffer .= chr(substr($s, $i, 4));
672:                                 $i += 4;
673:                                 continue;
674:                                 
675:                             } catch (Exception $ex) {
676:                                 throw new Exception("Invalid hex notation in the specified printer commands at index: ".$i);
677:                             }
678:                                 
679:                             
680:                         }
681:                         else
682:                         {
683:                             try{
684:                                 
685:                                 $buffer .= chr(substr($s, $i, 3));
686:                                 $i += 3;
687:                                 continue;
688:                                 
689:                             } catch (Exception $ex) {
690:                                 throw new ArgumentException("Invalid hex notation in the specified printer commands at index: ".$i);
691:                             }
692:                         }
693:                     }
694:                 }
695:             }
696: 
697:             $buffer .= substr($s, $i, 1);
698:             
699:             $i++;
700:         }
701: 
702:         return $buffer;
703:         
704:     }
705:     
706:     public static function intToArray($i){
707:         return pack("L", $i);
708:     }
709:         
710:     public static function getRoot(){
711:         $s = empty($_SERVER["HTTPS"]) ? '' : ($_SERVER["HTTPS"] == "on") ? "s" : "";
712:         $protocol = static::strleft(strtolower($_SERVER["SERVER_PROTOCOL"]), "/").$s;
713:         $port = ($_SERVER["SERVER_PORT"] == "80") ? "" : (":".$_SERVER["SERVER_PORT"]);
714:         return $protocol."://".$_SERVER['SERVER_NAME'].$port;    
715:     }
716:    
717:     public static function strleft($s1, $s2) {
718:     return substr($s1, 0, strpos($s1, $s2));
719:     }
720:     
721:     public static function strContains($s1, $s2){
722:         return (strpos($s1, $s2) !== false);
723:     }
724:     
725:     public static function strEndsWith($s1, $s2)
726:     {
727:         return substr($s1, -strlen($s2)) === $s2;
728:     }
729:     
730:     public static function getUA(){
731:         return $_SERVER['HTTP_USER_AGENT'];
732:     }
733:     
734:     public static function isIE6to9(){
735:         $ua = static::getUA();
736:         return ((static::strContains($ua,"MSIE 6.") ||
737:                  static::strContains($ua,"MSIE 7.") ||
738:                  static::strContains($ua,"MSIE 8.") ||
739:                  static::strContains($ua,"MSIE 9.")) &&
740:                  static::strContains($ua,"Opera") === false);
741:     }
742: 
743:     public static function isIE5orOlder(){
744:         $ua = static::getUA();
745:         return ((static::strContains($ua,"MSIE 5.") ||
746:                  static::strContains($ua,"MSIE 4.") ||
747:                  static::strContains($ua,"MSIE 3.") ||
748:                  static::strContains($ua,"MSIE 2.")) &&
749:                  static::strContains($ua,"Opera") === false);
750:     }
751:         
752:     public static function isIE10orGreater(){
753:         $ua = static::getUA();
754:         return (static::strContains($ua,"MSIE") || static::strContains($ua,"Trident/")) && static::isIE6to9() === false && static::isIE5orOlder() === false && static::strContains($ua,"Opera") === false;
755:     }
756:     
757: }
758: 
759: /**
760:  * Specifies information about the print job to be processed at the client side.
761:  */
762: class ClientPrintJob{
763:     
764:     /**
765:      * Gets or sets the ClientPrinter object. Default is NULL.
766:      * The ClientPrinter object refers to the kind of printer that the client machine has attached or can reach.
767:      * - Use a DefaultPrinter object for using the default printer installed in the client machine.
768:      * - Use a InstalledPrinter object for using a printer installed in the client machine with an associated Windows driver.
769:      * - Use a ParallelPortPrinter object for using a printer which is connected through a parallel port in the client machine.
770:      * - Use a SerialPortPrinter object for using a printer which is connected through a serial port in the client machine.
771:      * - Use a NetworkPrinter object for using a Network IP/Ethernet printer which can be reached from the client machine.
772:      * @var ClientPrinter 
773:      */
774:     public $clientPrinter = null;
775:     /**
776:      * Gets or sets the printer's commands in text plain format. Default is an empty string.
777:      * @var string 
778:      */
779:     public $printerCommands = '';
780:     /**
781:      * Gets or sets whether the printer commands have chars expressed in hexadecimal notation. Default is false.
782:      * The string set to the $printerCommands property can contain chars expressed in hexadecimal notation.
783:      * Many printer languages have commands which are represented by non-printable chars and to express these commands 
784:      * in a string could require many concatenations and hence be not so readable.
785:      * By using hex notation, you can make it simple and elegant. Here is an example: if you need to encode ASCII 27 (escape), 
786:      * then you can represent it as 0x27.        
787:      * @var boolean 
788:      */
789:     public $formatHexValues = false;
790:     /**
791:      * Gets or sets the PrintFile object to be printed at the client side. Default is NULL.
792:      * @var PrintFile 
793:      */
794:     public $printFile = null;
795:     /**
796:      * Gets or sets an array of PrintFile objects to be printed at the client side. Default is NULL.
797:      * @var array 
798:      */
799:     public $printFileGroup = null;
800:     
801:     
802:     /**
803:      * Sends this ClientPrintJob object to the client for further processing.
804:      * The ClientPrintJob object will be processed by the WCPP installed at the client machine.
805:      * @return string A string representing a ClientPrintJob object.
806:      */
807:     public function sendToClient(){
808:         
809:         header('Content-type: application/octet-stream');
810:         
811:         $cpjHeader = chr(99).chr(112).chr(106).chr(2);
812:         
813:         $buffer = '';
814:         
815:         if (!Utils::isNullOrEmptyString($this->printerCommands)){
816:             if($this->formatHexValues){
817:                 $buffer = Utils::formatHexValues ($this->printerCommands);
818:             } else {
819:                 $buffer = $this->printerCommands;
820:             }
821:         } else if (isset ($this->printFile)){
822:             $buffer = $this->printFile->serialize();
823:         } else if (isset ($this->printFileGroup)){
824:             $buffer = 'wcpPFG:';
825:             $zip = new ZipArchive;
826:             $cacheFileName = (Utils::strEndsWith(WebClientPrint::$wcpCacheFolder, '/')?WebClientPrint::$wcpCacheFolder:WebClientPrint::$wcpCacheFolder.'/').'PFG'.uniqid().'.zip';
827:             $res = $zip->open($cacheFileName, ZipArchive::CREATE);
828:             if ($res === TRUE) {
829:                 foreach ($this->printFileGroup as $printFile) {
830:                     $zip->addFromString($printFile->fileName, $printFile->getFileContent());
831:                 }
832:                 $zip->close();
833:                 $handle = fopen($cacheFileName, 'rb');
834:                 $buffer .= fread($handle, filesize($cacheFileName));
835:                 fclose($handle);
836:                 unlink($cacheFileName);
837:             } else {
838:                 $buffer='Creating PrintFileGroup failed. Cannot create zip file.';
839:             }
840:         }
841:         
842:         $arrIdx1 = Utils::intToArray(strlen($buffer));
843:         
844:         if (!isset($this->clientPrinter)){
845:             $this->clientPrinter = new UserSelectedPrinter();
846:         }    
847:         
848:         $buffer .= $this->clientPrinter->serialize();
849:         
850:         $arrIdx2 = Utils::intToArray(strlen($buffer));
851:         
852:         $lo = '';
853:         if(Utils::isNullOrEmptyString(WebClientPrint::$licenseOwner)){
854:             $lo = substr(uniqid(), 0, 8);
855:         }  else {
856:             $lo = WebClientPrint::$licenseOwner;
857:         }
858:         $lk = '';
859:         if(Utils::isNullOrEmptyString(WebClientPrint::$licenseKey)){
860:             $lk = substr(uniqid(), 0, 8);
861:         }  else {
862:             $lk = WebClientPrint::$licenseKey;
863:         }
864:         $buffer .= $lo.chr(124).$lk;
865:         
866:         return $cpjHeader.$arrIdx1.$arrIdx2.$buffer;
867:     }
868:     
869: }
Neodynamic WebClientPrint for PHP Documentation
Copyright © 2003 - Neodynamic - All rights reserved.