├── README.md └── src ├── DemoPrintCommands.php ├── DemoPrintCommandsController.php ├── DemoPrintFile.php ├── DemoPrintFileController.php ├── DemoPrintFileDOC.php ├── DemoPrintFileDOCController.php ├── DemoPrintFilePDF.php ├── DemoPrintFilePDFController.php ├── DemoPrintFileTIF.php ├── DemoPrintFileTIFController.php ├── DemoPrintFileWithEncryption.php ├── DemoPrintFileWithEncryptionController.php ├── DemoPrintFileWithPwdProtection.php ├── DemoPrintFileWithPwdProtectionController.php ├── DemoPrintFileXLS.php ├── DemoPrintFileXLSController.php ├── PrintersInfo.php ├── WebClientPrint.php ├── WebClientPrintController.php ├── files ├── GuidingPrinciplesBusinessHR_EN.pdf ├── LoremIpsum-PasswordProtected.doc ├── LoremIpsum-PasswordProtected.pdf ├── LoremIpsum.doc ├── LoremIpsum.pdf ├── LoremIpsum.txt ├── Project-Scheduling-Monitoring-Tool.xls ├── Sample-Employee-Handbook.doc ├── SamplePngImage.png ├── SampleSheet-PasswordProtected.xls ├── SampleSheet.xls ├── mixed-page-orientation.pdf ├── patent2pages.tif └── penguins300dpi.jpg ├── index.php ├── phpseclib ├── Crypt │ ├── AES.php │ ├── Base.php │ ├── Blowfish.php │ ├── DES.php │ ├── Hash.php │ ├── RC2.php │ ├── RC4.php │ ├── RSA.php │ ├── Random.php │ ├── Rijndael.php │ ├── TripleDES.php │ └── Twofish.php ├── File │ ├── ANSI.php │ ├── ASN1.php │ ├── ASN1 │ │ └── Element.php │ └── X509.php └── Math │ └── BigInteger.php ├── samples.php └── template.php /README.md: -------------------------------------------------------------------------------- 1 | # WebClientPrint 6.0 for **PHP** 2 | 3 | ## Overview 4 | [**WebClientPrint 6.0 for PHP**](http://neodynamic.com/products/printing/raw-data/php) is a lightweight and ***plugin-free*** solution for **Client-side Raw Data Printing** scenarios for **Windows**, **Linux**, **Raspberry Pi (Linux ARM)** & **Mac** clients, exclusively designed for **Classic PHP & MVC Frameworks** projects. With the **WebClientPrint solution**, you can easily send raw data, text and native commands as well as known file & document formats to printers installed at the client machine without showing or displaying any print dialog box! 5 | 6 | Learn more about [**WebClientPrint 6.0 for PHP**](http://neodynamic.com/products/printing/raw-data/php/) solution! 7 | 8 | ## About this repo 9 | This PHP project is a sample to getting you started with WebClientPrint 6.0 for PHP Solution 10 | 11 | Website project for **Classic PHP**. If you're using **Laravel**, then please refer to the [**WebClientPrint for PHP Articles**](http://neodynamic.com/products/printing/raw-data/php/articles/) that includes many printing topics with source code. 12 | 13 | ## Know How WebClientPrint 6.0 for PHP Works 14 | Refer to the [Online Help Documentation](http://neodynamic.com/Products/Help/WebClientPrintPHP6.0/index.html) 15 | 16 | ## Licensing 17 | 18 | **WebClientPrint is a Commercial** product. Licensing model and prices are available [here](https://neodynamic.com/products/printing/raw-data/php/buy) 19 | 20 | ## Support 21 | 22 | Tech questions are handled by [Neodynamic Dev Team](https://neodynamic/support) 23 | -------------------------------------------------------------------------------- /src/DemoPrintCommands.php: -------------------------------------------------------------------------------- 1 | 64 | 65 |

 Print Raw/Text Commands

66 | 67 |
68 |
69 |
70 | 71 | 72 | 73 |
74 | Client Printer Settings 75 | 76 |
77 | WebClientPrint does support all common printer communications like USB-Installed 78 | Drivers, Network/IP-Ethernet, Serial COM-RS232 and Parallel (LPT). 79 |
80 |
81 | I want to:   82 | 90 |
91 |
92 |
93 |
94 |
95 | 96 |
97 |
98 | WebClientPrint can detect the installed printers in your machine. Load installed printers... 99 |

100 |
101 | 102 | 103 | 104 | 105 | 130 | 131 |
132 | 133 |
134 | 135 | 136 | 137 | 138 |
139 | 140 |
141 | 142 | 143 |
144 | 145 |
146 | 147 | 148 | 156 | 157 | 182 | 183 |
149 | 150 | 151 | 152 | 153 | 154 | 155 | 158 | 159 | 166 | 167 | 168 | 173 | 174 | 175 | 181 |
184 | 185 | 186 |
187 | 188 |
189 |
190 | Printer Commands 191 | 192 |

193 | Enter the printer's commands you want to send and is supported by the specified printer (ESC/P, PCL, ZPL, EPL, DPL, IPL, EZPL, etc). 194 |

195 | NOTE: You can use the hex notation of VB or C# for non-printable characters e.g. for Carriage Return (ASCII 13) you could use &H0D or 0x0D 196 |

197 |
198 | Upload Files
199 | This online demo does not allow you to upload files. So, if you have a file containing the printer commands like a PRN file, Postscript, PCL, ZPL, etc, then we recommend you to download WebClientPrint and test it by using the sample source code included in the package. Feel free to contact our Tech Support for further assistance, help, doubts or questions. 200 |
201 | 202 | 203 |
204 |
205 | Ready to print! 206 |

Your settings were saved! Now it's time to Print

207 |

208 |
209 |

210 | 211 |
212 |
213 |
214 |
215 |
216 |
217 | 218 | 219 | 223 | 224 | 225 | 244 | 245 | 246 | 378 | 379 | 380 | 387 | 388 | -------------------------------------------------------------------------------- /src/DemoPrintCommandsController.php: -------------------------------------------------------------------------------- 1 | clientPrinter = $clientPrinter; 63 | $cpj->printerCommands = $printerCommands; 64 | $cpj->formatHexValues = true; 65 | 66 | //Send ClientPrintJob back to the client 67 | ob_start(); 68 | ob_clean(); 69 | header('Content-type: application/octet-stream'); 70 | echo $cpj->sendToClient(); 71 | ob_end_flush(); 72 | exit(); 73 | } 74 | 75 | } 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/DemoPrintFile.php: -------------------------------------------------------------------------------- 1 | 12 | 13 |
14 |
15 | 16 |

 Print Known File Formats without displaying any Print dialog! (if needed)

17 |

18 | With WebClientPrint for PHP solution you can print most common file formats (PDF, TXT, DOC/X, XLS/X, JPG/JPEG, PNG, TIF/TIFF) right to any installed printer at the client side. 19 |

20 | 21 |
22 |
23 | 29 |
30 |
31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 |
File FormatWindows ClientsLinux, Raspberry Pi & Mac Clients
DOC, DOCXMicrosoft Word is requiredLibreOffice is required
XLS, XLSXMicrosoft Excel is requiredLibreOffice is required
PDFNatively supported!Natively supported!
TXTNatively supported!Natively supported!
JPEGNatively supported!Natively supported!
PNGNatively supported!Natively supported!
BMPNatively supported!Natively supported!
Printer SupportYou can print files to local installed printers ONLY! Parallel, Serial and IP/Ethernet printers are NOT supported for printing files but for printing raw commands.You can print files to any installed printers through CUPS system.
82 | 83 |
84 |
85 |
86 |
87 | 93 |
94 |
95 |

96 | The following are pre-selected files to test WebClientPrint File Printing feature. 97 |

98 |
99 |
100 |
101 |
102 | 106 |
107 |
108 | Click to load and select one of the installed printers! 109 |
110 | Load installed printers... 111 |
112 |
113 |
114 | 118 | 143 |
144 |
145 |
146 |
147 | 148 | 157 |
158 | Print File... 159 |
160 |
161 |
162 |
File Preview
163 | 164 | 165 |
166 |
167 |
168 | 169 |
170 | 171 | 172 |
173 |
174 | 175 | 176 | 180 | 181 | 182 | 202 | 203 | 215 | 216 | 223 | 224 | -------------------------------------------------------------------------------- /src/DemoPrintFileController.php: -------------------------------------------------------------------------------- 1 | printRotation = PrintRotation::None; 57 | //$myfile->pagesRange = '1,2,3,10-15'; 58 | //$myfile->printAnnotations = true; 59 | //$myfile->printAsGrayscale = true; 60 | //$myfile->printInReverseOrder = true; 61 | $cpj->printFile = $myfile; 62 | } 63 | else if ($qs['filetype'] === 'TXT') 64 | { 65 | $myfile = new PrintFileTXT($filePath, $fileName, null); 66 | $myfile->printOrientation = PrintOrientation::Portrait; 67 | $myfile->fontName = 'Arial'; 68 | $myfile->fontSizeInPoints = 12; 69 | //$myfile->textColor = '#ff00ff'; 70 | //$myfile->textAlignment = TextAlignment::Center; 71 | //$myfile->fontBold = true; 72 | //$myfile->fontItalic = true; 73 | //$myfile->fontUnderline = true; 74 | //$myfile->fontStrikeThrough = true; 75 | //$myfile->marginLeft = 1; // INCH Unit!!! 76 | //$myfile->marginTop = 1; // INCH Unit!!! 77 | //$myfile->marginRight = 1; // INCH Unit!!! 78 | //$myfile->marginBottom = 1; // INCH Unit!!! 79 | $cpj->printFile = $myfile; 80 | } 81 | else 82 | { 83 | $cpj->printFile = new PrintFile($filePath, $fileName, null); 84 | } 85 | 86 | if ($useDefaultPrinter || $printerName === 'null') { 87 | $cpj->clientPrinter = new DefaultPrinter(); 88 | } else { 89 | $cpj->clientPrinter = new InstalledPrinter($printerName); 90 | } 91 | 92 | //Send ClientPrintJob back to the client 93 | ob_start(); 94 | ob_clean(); 95 | header('Content-type: application/octet-stream'); 96 | echo $cpj->sendToClient(); 97 | ob_end_flush(); 98 | exit(); 99 | } 100 | } 101 | } 102 | 103 | 104 | 105 | -------------------------------------------------------------------------------- /src/DemoPrintFileDOC.php: -------------------------------------------------------------------------------- 1 | 37 | 38 | 39 | 40 | 41 |
42 |
43 | 44 |
45 |

 Advanced DOC Printing

46 |

47 | With WebClientPrint for PHP solution you can print DOC files right to any installed printer at the client side with advanced settings. 48 |

49 |
Requirements: 50 |
    51 |
  • Available for Windows clients only
  • 52 |
  • Microsoft Word 97+ must be installed at the client machine
  • 53 |
  • DOC files can be any of these file formats: *.docx, *.docm, *.dotx, *.dotm, *.doc, *.dot, *.rtf, and *.odt
  • 54 |
55 |
56 | 57 |
58 |

Click on "Get Printers Info" button to get installed Printers

59 |
60 | 61 |
62 | Get Printers... 63 |
64 |
65 | 66 |
67 |
68 | 69 |
70 |
71 | 72 | 73 |
74 |
75 | 76 | 77 |
78 |
79 |
80 | 81 |
82 |
83 |
84 |
85 | 86 |
87 |
88 |
89 |
90 |
91 | 92 |
93 | Print DOC... 94 |
95 |
96 |
97 |

DOC File Sample Preview - 38 Pages!!!

98 | 99 | 100 |
101 | 102 |
103 | 104 | 105 |
106 |
107 | 108 | 133 | 134 | 135 | 136 | 140 | 141 | 142 | 162 | 163 | 170 | 171 | -------------------------------------------------------------------------------- /src/DemoPrintFileDOCController.php: -------------------------------------------------------------------------------- 1 | pagesRange = $qs['pagesRange']; 28 | $myfile->printInReverseOrder = ($qs['printInReverseOrder']=='true'); 29 | $myfile->duplexPrinting = ($qs['duplexPrinting']=='true'); 30 | //myfile->duplexPrintingDialogMessage = 'Your custom dialog message for duplex printing'; 31 | 32 | //Create a ClientPrintJob obj that will be processed at the client side by the WCPP 33 | $cpj = new ClientPrintJob(); 34 | $cpj->printFile = $myfile; 35 | 36 | //Create an InstalledPrinter obj 37 | $printerName = urldecode($qs['printerName']); 38 | if ($printerName == 'null'){ 39 | $myPrinter = new DefaultPrinter(); 40 | } else { 41 | $myPrinter = new InstalledPrinter($printerName); 42 | } 43 | 44 | $cpj->clientPrinter = $myPrinter; 45 | 46 | //Send ClientPrintJob back to the client 47 | ob_start(); 48 | ob_clean(); 49 | header('Content-type: application/octet-stream'); 50 | echo $cpj->sendToClient(); 51 | ob_end_flush(); 52 | exit(); 53 | 54 | } 55 | } 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/DemoPrintFilePDF.php: -------------------------------------------------------------------------------- 1 | 37 | 38 | 39 | 40 |
41 |
42 | 43 |
44 |

 Advanced PDF Printing

45 |

46 | With WebClientPrint for PHP solution you can print PDF files right to any installed printer at the client side with advanced settings. 47 |

48 | 49 |
50 |

Click on "Get Printers Info" button to get Printers Name, Supported Papers and Trays

51 |
52 | 53 | 56 |
57 | 58 |
59 |
60 | 61 |
62 |
63 | 64 | 65 |
66 |
67 | 68 | 69 |
70 |
71 | 72 | 73 |
74 |
75 | 76 | 82 |
83 |
84 |
85 |
86 | 87 | 88 |
89 |
90 |
91 | 92 |
93 |
94 |
95 |
96 | 97 |
98 |
99 | 100 |
101 |
102 |
103 |
104 | 105 |
106 |
107 | 108 |
109 |
110 | 111 |
112 |
113 |
114 | 115 | 119 |
120 |
121 |
122 | 123 |
124 |
125 |
126 |
127 | 128 |
129 |
130 |
131 |
132 | 133 |
134 | Print PDF... 135 |
136 |
137 |
138 |

PDF File Sample Preview - 13 Pages

139 | 140 | 141 |
142 | 143 |
144 | 145 | 146 |
147 |
148 | 149 | 150 | 220 | 221 | 222 | 226 | 227 | 228 | 248 | 249 | 256 | 257 | -------------------------------------------------------------------------------- /src/DemoPrintFilePDFController.php: -------------------------------------------------------------------------------- 1 | printRotation = PrintRotation::parse($qs['printRotation']); 31 | $myfile->pagesRange = $qs['pagesRange']; 32 | $myfile->printAnnotations = ($qs['printAnnotations']=='true'); 33 | $myfile->printAsGrayscale = ($qs['printAsGrayscale']=='true'); 34 | $myfile->printInReverseOrder = ($qs['printInReverseOrder']=='true'); 35 | //$myfile->copies = 1; 36 | $manualDuplexPrinting = ($qs['manualDuplexPrinting'] == 'true'); 37 | $driverDuplexPrinting = ($qs['driverDuplexPrinting'] == 'true'); 38 | 39 | if ($manualDuplexPrinting && $driverDuplexPrinting){ 40 | $manualDuplexPrinting = false; 41 | } 42 | 43 | if ($manualDuplexPrinting){ 44 | $myfile->duplexPrinting = $manualDuplexPrinting; 45 | //myfile->duplexPrintingDialogMessage = 'Your custom dialog message for duplex printing'; 46 | } 47 | 48 | $myfile->sizing = Sizing::parse($qs['pageSizing']); 49 | $myfile->autoCenter = ($qs['autoCenter'] == 'true'); 50 | $myfile->autoRotate = ($qs['autoRotate'] == 'true'); 51 | 52 | 53 | //Create a ClientPrintJob obj that will be processed at the client side by the WCPP 54 | $cpj = new ClientPrintJob(); 55 | $cpj->printFile = $myfile; 56 | 57 | //Create an InstalledPrinter obj 58 | $printerName = urldecode($qs['printerName']); 59 | if ($printerName == 'null'){ 60 | $myPrinter = new DefaultPrinter(); 61 | } else { 62 | $myPrinter = new InstalledPrinter($printerName); 63 | $myPrinter->trayName = $qs['trayName']; 64 | $myPrinter->paperName = $qs['paperName']; 65 | if ($driverDuplexPrinting){ 66 | $myPrinter->duplex = Duplex::Vertical; 67 | } 68 | } 69 | 70 | $cpj->clientPrinter = $myPrinter; 71 | 72 | //Send ClientPrintJob back to the client 73 | ob_start(); 74 | ob_clean(); 75 | header('Content-type: application/octet-stream'); 76 | echo $cpj->sendToClient(); 77 | ob_end_flush(); 78 | exit(); 79 | 80 | } 81 | } 82 | 83 | 84 | 85 | -------------------------------------------------------------------------------- /src/DemoPrintFileTIF.php: -------------------------------------------------------------------------------- 1 | 37 | 38 | 39 | 40 |
41 |
42 | 43 |
44 |

 Advanced TIF Printing

45 |

46 | With WebClientPrint for PHP solution you can print TIF files right to any installed printer at the client side with advanced settings. 47 |

48 | 49 |
50 |

Click on "Get Printers Info" button to get Printers Name, Supported Papers and Trays

51 |
52 | 53 | 56 |
57 | 58 |
59 |
60 | 61 |
62 |
63 | 64 | 65 |
66 |
67 | 68 | 69 |
70 |
71 | 72 | 73 |
74 |
75 | 76 | 82 |
83 |
84 |
85 |
86 | 87 | 88 |
89 |
90 |
91 | 92 |
93 |
94 |
95 |
96 | 97 |
98 |
99 | 100 |
101 |
102 |
103 |
104 | 105 |
106 |
107 | 108 |
109 |
110 |
111 | 112 | 116 |
117 |
118 |
119 | 120 |
121 |
122 |
123 |
124 | 125 |
126 |
127 |
128 |
129 | 130 |
131 | Print TIF... 132 |
133 |
134 |
135 |

PDF File Sample Preview - 13 Pages

136 | 137 | 138 |
139 | 140 |
141 | 142 | 143 |
144 |
145 | 146 | 147 | 217 | 218 | 219 | 223 | 224 | 225 | 245 | 246 | 247 | 254 | 255 | -------------------------------------------------------------------------------- /src/DemoPrintFileTIFController.php: -------------------------------------------------------------------------------- 1 | printRotation = PrintRotation::parse($qs['printRotation']); 31 | $myfile->pagesRange = $qs['pagesRange']; 32 | $myfile->printAsGrayscale = ($qs['printAsGrayscale']=='true'); 33 | $myfile->printInReverseOrder = ($qs['printInReverseOrder']=='true'); 34 | //$myfile->copies = 1; 35 | $manualDuplexPrinting = ($qs['manualDuplexPrinting'] == 'true'); 36 | $driverDuplexPrinting = ($qs['driverDuplexPrinting'] == 'true'); 37 | 38 | if ($manualDuplexPrinting && $driverDuplexPrinting){ 39 | $manualDuplexPrinting = false; 40 | } 41 | 42 | if ($manualDuplexPrinting){ 43 | $myfile->duplexPrinting = $manualDuplexPrinting; 44 | //myfile->duplexPrintingDialogMessage = 'Your custom dialog message for duplex printing'; 45 | } 46 | 47 | $myfile->sizing = Sizing::parse($qs['pageSizing']); 48 | $myfile->autoCenter = ($qs['autoCenter'] == 'true'); 49 | $myfile->autoRotate = ($qs['autoRotate'] == 'true'); 50 | 51 | 52 | //Create a ClientPrintJob obj that will be processed at the client side by the WCPP 53 | $cpj = new ClientPrintJob(); 54 | $cpj->printFile = $myfile; 55 | 56 | //Create an InstalledPrinter obj 57 | $printerName = urldecode($qs['printerName']); 58 | if ($printerName == 'null'){ 59 | $myPrinter = new DefaultPrinter(); 60 | } else { 61 | $myPrinter = new InstalledPrinter($printerName); 62 | $myPrinter->trayName = $qs['trayName']; 63 | $myPrinter->paperName = $qs['paperName']; 64 | if ($driverDuplexPrinting){ 65 | $myPrinter->duplex = Duplex::Vertical; 66 | } 67 | } 68 | 69 | $cpj->clientPrinter = $myPrinter; 70 | 71 | //Send ClientPrintJob back to the client 72 | ob_start(); 73 | ob_clean(); 74 | header('Content-type: application/octet-stream'); 75 | echo $cpj->sendToClient(); 76 | ob_end_flush(); 77 | exit(); 78 | 79 | } 80 | } 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /src/DemoPrintFileWithEncryption.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 |
15 |
16 | 17 |

 Print Encrypted Files without displaying any Print dialog! (if needed)

18 |

19 | With WebClientPrint for PHP solution you can print encrypted files in PDF, TXT, JPG/JPEG & PNG formats right to any installed printer at the client side. 20 |

21 | 22 |
23 | WebClientPrint uses RSA asymetric encryption with a dynamic public key generated by WCPP utility for each printing request to encrypt the AES-256 params. The file to print is encrypted by using AES-256 symetric encryption in the server side and stored at the client machine disk. At printing time, WCPP will decrypt the file to print in system memory. 24 |
25 | 26 |
27 |

28 | The following are pre-selected files to test WebClientPrint File Printing with Encryption feature enabled. 29 |

30 |
31 |
32 |
33 |
34 | 38 |
39 |
40 | Click to load and select one of the installed printers! 41 |
42 | Load installed printers... 43 |
44 |
45 |
46 | 50 | 75 |
76 |
77 |
78 |
79 | 80 | 86 |
87 | Print File... 88 |
89 |
90 |
91 | 92 |
93 | 94 | 95 |
96 |
97 | 98 | 99 | 103 | 104 | 105 | 125 | 126 | 127 | 134 | 135 | -------------------------------------------------------------------------------- /src/DemoPrintFileWithEncryptionController.php: -------------------------------------------------------------------------------- 1 | printRotation = PrintRotation::None; 61 | //$myfile->pagesRange = '1,2,3,10-15'; 62 | //$myfile->printAnnotations = true; 63 | //$myfile->printAsGrayscale = true; 64 | //$myfile->printInReverseOrder = true; 65 | 66 | $myfile->encryptMetadata = $encMetadata; 67 | 68 | $cpj->printFile = $myfile; 69 | } 70 | else if ($qs['filetype'] === 'TXT') 71 | { 72 | $myfile = new PrintFileTXT($filePath, $fileName, null); 73 | $myfile->printOrientation = PrintOrientation::Portrait; 74 | $myfile->fontName = 'Arial'; 75 | $myfile->fontSizeInPoints = 12; 76 | //$myfile->textColor = '#ff00ff'; 77 | //$myfile->textAlignment = TextAlignment::Center; 78 | //$myfile->fontBold = true; 79 | //$myfile->fontItalic = true; 80 | //$myfile->fontUnderline = true; 81 | //$myfile->fontStrikeThrough = true; 82 | //$myfile->marginLeft = 1; // INCH Unit!!! 83 | //$myfile->marginTop = 1; // INCH Unit!!! 84 | //$myfile->marginRight = 1; // INCH Unit!!! 85 | //$myfile->marginBottom = 1; // INCH Unit!!! 86 | 87 | $myfile->encryptMetadata = $encMetadata; 88 | 89 | $cpj->printFile = $myfile; 90 | } 91 | else 92 | { 93 | $myfile = new PrintFile($filePath, $fileName, null); 94 | $myfile->encryptMetadata = $encMetadata; 95 | 96 | $cpj->printFile = $myfile; 97 | } 98 | 99 | 100 | if ($useDefaultPrinter || $printerName === 'null') { 101 | $cpj->clientPrinter = new DefaultPrinter(); 102 | } else { 103 | $cpj->clientPrinter = new InstalledPrinter($printerName); 104 | } 105 | 106 | //Send ClientPrintJob back to the client 107 | ob_start(); 108 | ob_clean(); 109 | header('Content-type: application/octet-stream'); 110 | //set the Encryption Metadata 111 | setcookie('wcp_enc_metadata', $encMetadata->serialize()); 112 | //set the ClientPrintJob content 113 | echo $cpj->sendToClient(); 114 | ob_end_flush(); 115 | exit(); 116 | 117 | } 118 | } 119 | } 120 | } 121 | 122 | 123 | 124 | -------------------------------------------------------------------------------- /src/DemoPrintFileWithPwdProtection.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 |
15 |
16 | 17 |

 Print Files With Password Protection without displaying any Print dialog! (if needed)

18 |

19 | With WebClientPrint for PHP solution you can print password protected PDF, DOC & XLS files right to any installed printer at the client side. 20 |

21 | 22 |
23 | The file password is set at server side and then it's encrypted (using RSA) and embedded into the file metadata. Although the file is downloaded to the client machine, it keeps password protected. The WebClientPrint Processor app, loads the file in memory and unlock the file in system memory for printing it. 24 |
25 | 26 |
27 |

28 | The following are pre-selected files to test WebClientPrint File Printing with Password Protection feature enabled. You can download the files for testing them. The password for all files is ABC123 29 |

30 |
31 |
32 |
33 |
34 | 38 |
39 |
40 | Click to load and select one of the installed printers! 41 |
42 | Load installed printers... 43 |
44 |
45 |
46 | 50 | 75 |
76 |
77 |
78 |
79 | 80 | 85 |
86 | Print File... 87 |

88 |  PDF 89 |  DOC 90 |  XLS 91 |
92 |
93 |
94 | 95 |
96 | 97 | 98 |
99 |
100 | 101 | 102 | 106 | 107 | 108 | 128 | 129 | 130 | 137 | 138 | -------------------------------------------------------------------------------- /src/DemoPrintFileWithPwdProtectionController.php: -------------------------------------------------------------------------------- 1 | password = $plainTextPassword; 63 | //$myfile->printRotation = PrintRotation::None; 64 | //$myfile->pagesRange = '1,2,3,10-15'; 65 | //$myfile->printAnnotations = true; 66 | //$myfile->printAsGrayscale = true; 67 | //$myfile->printInReverseOrder = true; 68 | 69 | $myfile->encryptMetadata = $encMetadata; 70 | 71 | $cpj->printFile = $myfile; 72 | } 73 | else if ($qs['filetype'] === 'DOC') 74 | { 75 | $myfile = new PrintFileDOC($filePath, $fileName, null); 76 | $myfile->password = $plainTextPassword; 77 | //$myfile->pagesRange = $qs['pagesRange']; 78 | //$myfile->printInReverseOrder = ($qs['printInReverseOrder']=='true'); 79 | 80 | $myfile->encryptMetadata = $encMetadata; 81 | 82 | $cpj->printFile = $myfile; 83 | } 84 | else if ($qs['filetype'] === 'XLS') 85 | { 86 | $myfile = new PrintFileXLS($filePath, $fileName, null); 87 | $myfile->password = $plainTextPassword; 88 | //$myfile->$pagesFrom = 0; 89 | //$myfile->$pagesTo = 0; 90 | 91 | $myfile->encryptMetadata = $encMetadata; 92 | 93 | $cpj->printFile = $myfile; 94 | } 95 | 96 | if ($useDefaultPrinter || $printerName === 'null') { 97 | $cpj->clientPrinter = new DefaultPrinter(); 98 | } else { 99 | $cpj->clientPrinter = new InstalledPrinter($printerName); 100 | } 101 | 102 | //Send ClientPrintJob back to the client 103 | ob_start(); 104 | ob_clean(); 105 | header('Content-type: application/octet-stream'); 106 | echo $cpj->sendToClient(); 107 | ob_end_flush(); 108 | exit(); 109 | 110 | } 111 | } 112 | } 113 | } 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /src/DemoPrintFileXLS.php: -------------------------------------------------------------------------------- 1 | 37 | 38 | 39 | 40 | 41 |
42 |
43 | 44 |
45 |

 Advanced XLS Printing

46 |

47 | With WebClientPrint for PHP solution you can print XLS files right to any installed printer at the client side with advanced settings. 48 |

49 |
Requirements: 50 |
    51 |
  • Available for Windows clients only
  • 52 |
  • Microsoft Excel 97+ must be installed at the client machine
  • 53 |
  • XLS files can be any of these file formats: *.xl, *.xlsx, *.xlsm, *.xlsb, *.xlam, *.xltx, *.xltm, *.xls, *.xla, *.xlt, *.xlm, *.xlw and *.ods
  • 54 |
55 |
56 | 57 |
58 |

Click on "Get Printers Info" button to get installed Printers

59 |
60 | 61 |
62 | Get Printers... 63 |
64 |
65 | 66 |
67 |
68 | 69 |
70 |
71 | 72 | 73 |
74 |
75 | 76 | 77 |
78 |
79 | 80 | 81 | 82 |
83 | 84 |
85 |
86 |
87 | 88 |
89 | Print XLS... 90 |
91 |
92 |
93 |

XLS File Sample Preview - 13 Pages!!!

94 | 95 | 96 |
97 | 98 |
99 | 100 | 101 |
102 |
103 | 104 | 129 | 130 | 131 | 132 | 136 | 137 | 138 | 158 | 159 | 160 | 167 | 168 | -------------------------------------------------------------------------------- /src/DemoPrintFileXLSController.php: -------------------------------------------------------------------------------- 1 | pagesFrom = intval($pagesFrom); 30 | } 31 | $pagesTo = $qs['pagesTo']; 32 | if (!Utils::isNullOrEmptyString($pagesTo)){ 33 | $myfile->pagesTo = intval($pagesTo); 34 | } 35 | 36 | //Create a ClientPrintJob obj that will be processed at the client side by the WCPP 37 | $cpj = new ClientPrintJob(); 38 | $cpj->printFile = $myfile; 39 | 40 | //Create an InstalledPrinter obj 41 | $printerName = urldecode($qs['printerName']); 42 | if ($printerName == 'null'){ 43 | $myPrinter = new DefaultPrinter(); 44 | } else { 45 | $myPrinter = new InstalledPrinter($printerName); 46 | } 47 | 48 | $cpj->clientPrinter = $myPrinter; 49 | 50 | //Send ClientPrintJob back to the client 51 | ob_start(); 52 | ob_clean(); 53 | header('Content-type: application/octet-stream'); 54 | echo $cpj->sendToClient(); 55 | ob_end_flush(); 56 | exit(); 57 | 58 | } 59 | } 60 | 61 | 62 | 63 | -------------------------------------------------------------------------------- /src/PrintersInfo.php: -------------------------------------------------------------------------------- 1 | 37 | 38 |

 Getting Printers Info

39 | 40 |

The following section shows you how to get useful info from the client printers. Please click in the button Get Printers Info below.

41 | 42 |
43 | 44 |
45 |
46 | 47 | 50 |
51 | 52 |
53 |
54 | 55 | 56 |
57 |
58 |
59 |
60 |
61 | 62 | 63 | 64 | 65 |
66 |
67 | 68 |
69 |

70 |
71 |
72 |
73 | 74 | 75 | 76 | 77 | 78 |
79 |
80 | 81 | 82 | 83 | 84 |
85 |
86 |
87 |
88 |
89 |
90 | 91 | 92 | 93 | 94 | 97 | 98 | 101 | 102 | 105 | 106 | 107 | 111 | 114 | 117 | 118 | 119 | 122 | 125 | 128 | 129 | 130 | 133 | 136 | 139 | 140 | 141 |
Port Name: 95 | 96 | Horizontal Resolution (dpi): 99 | 100 | Vertical Resolution (dpi): 103 | 104 |
108 |

  Is Connected?

109 | 110 |
112 |

  Is Default?

113 |
115 |

  Is BIDI Enabled?

116 |
120 |

  Is Local?

121 |
123 |

  Is Network?

124 |
126 |

  Is Shared?

127 |
131 |

  Duplex Support?

132 |
134 | 135 | 137 | 138 |
142 |
143 |
144 |
145 |
146 |
147 | 148 |
149 | 150 | 151 | 240 | 241 | 242 | 246 | 247 | 248 | 268 | 269 | 270 | 277 | 278 | -------------------------------------------------------------------------------- /src/WebClientPrintController.php: -------------------------------------------------------------------------------- 1 | 0){ 82 | WebClientPrint::cacheAdd($sid, WebClientPrint::WCP_CACHE_WCPP_VER, $qs[WebClientPrint::WCPP_SET_VERSION]); 83 | } 84 | return; 85 | } 86 | else if ($reqType == WebClientPrint::ClientSetInstalledPrinters) 87 | { 88 | //WCPP Utility is sending the installed printers at client side 89 | //so store this info with the specified session ID 90 | WebClientPrint::cacheAdd($sid, WebClientPrint::WCP_CACHE_PRINTERS, strlen($qs[WebClientPrint::WCPP_SET_PRINTERS]) > 0 ? $qs[WebClientPrint::WCPP_SET_PRINTERS] : ''); 91 | return; 92 | } 93 | else if ($reqType == WebClientPrint::ClientSetInstalledPrintersInfo) 94 | { 95 | //WCPP Utility is sending the installed printers at client side with detailed info 96 | //so store this info with the specified session ID 97 | //Printers Info is in JSON format 98 | $printersInfo = $_POST['printersInfoContent']; 99 | 100 | WebClientPrint::cacheAdd($sid, WebClientPrint::WCP_CACHE_PRINTERSINFO, $printersInfo); 101 | return; 102 | } 103 | else if ($reqType == WebClientPrint::ClientGetWcppVersion) 104 | { 105 | //return the WCPP version for the specified Session ID (sid) if any 106 | ob_start(); 107 | ob_clean(); 108 | header('Content-type: text/plain'); 109 | echo WebClientPrint::cacheGet($sid, WebClientPrint::WCP_CACHE_WCPP_VER); 110 | return; 111 | } 112 | else if ($reqType == WebClientPrint::ClientGetInstalledPrinters) 113 | { 114 | //return the installed printers for the specified Session ID (sid) if any 115 | ob_start(); 116 | ob_clean(); 117 | header('Content-type: text/plain'); 118 | echo base64_decode(WebClientPrint::cacheGet($sid, WebClientPrint::WCP_CACHE_PRINTERS)); 119 | return; 120 | } 121 | else if ($reqType == WebClientPrint::ClientGetInstalledPrintersInfo) 122 | { 123 | //return the installed printers with detailed info for the specified Session ID (sid) if any 124 | ob_start(); 125 | ob_clean(); 126 | header('Content-type: text/plain'); 127 | echo base64_decode(WebClientPrint::cacheGet($sid, WebClientPrint::WCP_CACHE_PRINTERSINFO)); 128 | return; 129 | } 130 | } 131 | catch (Exception $ex) 132 | { 133 | throw $ex; 134 | } 135 | 136 | } -------------------------------------------------------------------------------- /src/files/GuidingPrinciplesBusinessHR_EN.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/GuidingPrinciplesBusinessHR_EN.pdf -------------------------------------------------------------------------------- /src/files/LoremIpsum-PasswordProtected.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/LoremIpsum-PasswordProtected.doc -------------------------------------------------------------------------------- /src/files/LoremIpsum-PasswordProtected.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/LoremIpsum-PasswordProtected.pdf -------------------------------------------------------------------------------- /src/files/LoremIpsum.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/LoremIpsum.doc -------------------------------------------------------------------------------- /src/files/LoremIpsum.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/LoremIpsum.pdf -------------------------------------------------------------------------------- /src/files/LoremIpsum.txt: -------------------------------------------------------------------------------- 1 | Printed By WebClientPrint 2 | ========================= 3 | 4 | Lorem ipsum dolor sit amet, consectetur adipiscing elit. Fusce urna massa, eleifend non posuere quis, iaculis et libero. Curabitur lacinia dolor non nisl pharetra tempus. Nunc non purus eget lacus sollicitudin commodo sit amet non magna. Sed euismod massa id justo pellentesque interdum. Ut a nisi aliquam augue blandit facilisis semper eu enim. Vivamus cursus sollicitudin orci vitae elementum. Nulla ornare tortor vitae arcu suscipit eu vestibulum diam auctor. Nullam convallis sem eget velit interdum id commodo arcu condimentum. Vestibulum egestas, odio nec volutpat placerat, tellus massa rhoncus turpis, id posuere est justo ut ante. 5 | 6 | Aenean vel lacus diam. Curabitur nec ligula felis. Donec ut enim id orci aliquet tincidunt. Proin feugiat sapien at tellus viverra in porttitor magna fermentum. Sed vel sapien quis turpis semper condimentum sit amet vel tellus. Pellentesque et lorem sed lorem congue ultricies tempus nec sapien. Donec sed lectus id urna pellentesque hendrerit. Mauris pretium, justo ut varius tincidunt, purus elit tempus nibh, in ullamcorper dui est ut eros. Phasellus eget augue quis urna consequat iaculis. Aliquam ac consequat mi. Nullam lectus odio, sodales vitae dictum a, bibendum vel nisl. 7 | 8 | Nulla ut vestibulum lorem. Aliquam vel consectetur mi. Aliquam pretium dui non nunc cursus ut blandit sapien sodales. Aliquam dictum pellentesque ligula, quis mollis magna ullamcorper nec. Etiam fermentum adipiscing nibh, vitae mattis quam vestibulum non. Pellentesque volutpat lorem vel nisl luctus scelerisque. Nulla vitae mauris a orci vestibulum auctor. Phasellus vehicula dictum eros, quis porta libero cursus in. Ut sit amet tempus ante. Nulla sit amet congue libero. Aliquam erat volutpat. Phasellus lacus dolor, varius sit amet vestibulum varius, pretium nec felis. Vivamus sed vehicula magna. Praesent et mi vel magna fringilla posuere. Curabitur nunc est, scelerisque ut luctus tincidunt, blandit ac diam. 9 | 10 | Maecenas consequat consectetur nulla, id dignissim mauris volutpat ac. In mattis convallis ornare. Ut condimentum vestibulum mi id aliquam. Mauris lacinia accumsan neque vitae malesuada. Praesent dignissim diam eu mi adipiscing vehicula. Proin egestas, justo interdum convallis vehicula, elit massa eleifend arcu, tincidunt mattis neque elit ut eros. Duis neque neque, tincidunt ut venenatis eu, blandit eget massa. Aliquam sit amet ligula convallis dolor porta placerat et sed arcu. Ut suscipit urna et nisi dictum placerat. Phasellus a nisl mi. Ut ut nunc ut metus tempor iaculis sit amet eu magna. Phasellus risus eros, volutpat eu tempor sit amet, volutpat venenatis nisl. 11 | 12 | Aliquam scelerisque commodo justo, a dictum metus dapibus vel. Aenean ac volutpat velit. Proin semper euismod velit sit amet mattis. Cras ut dolor arcu. Nullam hendrerit sagittis elit vel dictum. Etiam nisl nisi, eleifend vel molestie tincidunt, porttitor ac nunc. Vestibulum vulputate magna gravida neque imperdiet ac viverra nulla suscipit. -------------------------------------------------------------------------------- /src/files/Project-Scheduling-Monitoring-Tool.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/Project-Scheduling-Monitoring-Tool.xls -------------------------------------------------------------------------------- /src/files/Sample-Employee-Handbook.doc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/Sample-Employee-Handbook.doc -------------------------------------------------------------------------------- /src/files/SamplePngImage.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/SamplePngImage.png -------------------------------------------------------------------------------- /src/files/SampleSheet-PasswordProtected.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/SampleSheet-PasswordProtected.xls -------------------------------------------------------------------------------- /src/files/SampleSheet.xls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/SampleSheet.xls -------------------------------------------------------------------------------- /src/files/mixed-page-orientation.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/mixed-page-orientation.pdf -------------------------------------------------------------------------------- /src/files/patent2pages.tif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/patent2pages.tif -------------------------------------------------------------------------------- /src/files/penguins300dpi.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/neodynamic/WebClientPrint-PHP/0b2379c94cd243ddeac9b98df5798278c71f9227/src/files/penguins300dpi.jpg -------------------------------------------------------------------------------- /src/index.php: -------------------------------------------------------------------------------- 1 | 25 | 26 | 27 | 28 |
29 |
30 |
31 |

Detecting WCPP utility at client side...

32 |

Please wait a few seconds...

33 |
34 |
35 | 52 | 53 | 54 | 58 | 59 | 60 | 81 | 82 | 83 | 101 | 102 | -------------------------------------------------------------------------------- /src/phpseclib/Crypt/AES.php: -------------------------------------------------------------------------------- 1 | 25 | * setKey('abcdefghijklmnop'); 31 | * 32 | * $size = 10 * 1024; 33 | * $plaintext = ''; 34 | * for ($i = 0; $i < $size; $i++) { 35 | * $plaintext.= 'a'; 36 | * } 37 | * 38 | * echo $aes->decrypt($aes->encrypt($plaintext)); 39 | * ?> 40 | * 41 | * 42 | * @category Crypt 43 | * @package AES 44 | * @author Jim Wigginton 45 | * @copyright 2008 Jim Wigginton 46 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 47 | * @link http://phpseclib.sourceforge.net 48 | */ 49 | 50 | namespace phpseclib\Crypt; 51 | 52 | /** 53 | * Pure-PHP implementation of AES. 54 | * 55 | * @package AES 56 | * @author Jim Wigginton 57 | * @access public 58 | */ 59 | class AES extends Rijndael 60 | { 61 | /** 62 | * Dummy function 63 | * 64 | * Since \phpseclib\Crypt\AES extends \phpseclib\Crypt\Rijndael, this function is, technically, available, but it doesn't do anything. 65 | * 66 | * @see \phpseclib\Crypt\Rijndael::setBlockLength() 67 | * @access public 68 | * @param int $length 69 | */ 70 | function setBlockLength($length) 71 | { 72 | return; 73 | } 74 | 75 | /** 76 | * Sets the key length 77 | * 78 | * Valid key lengths are 128, 192, and 256. If the length is less than 128, it will be rounded up to 79 | * 128. If the length is greater than 128 and invalid, it will be rounded down to the closest valid amount. 80 | * 81 | * @see \phpseclib\Crypt\Rijndael:setKeyLength() 82 | * @access public 83 | * @param int $length 84 | */ 85 | function setKeyLength($length) 86 | { 87 | switch ($length) { 88 | case 160: 89 | $length = 192; 90 | break; 91 | case 224: 92 | $length = 256; 93 | } 94 | parent::setKeyLength($length); 95 | } 96 | 97 | /** 98 | * Sets the key. 99 | * 100 | * Rijndael supports five different key lengths, AES only supports three. 101 | * 102 | * @see \phpseclib\Crypt\Rijndael:setKey() 103 | * @see setKeyLength() 104 | * @access public 105 | * @param string $key 106 | */ 107 | function setKey($key) 108 | { 109 | parent::setKey($key); 110 | 111 | if (!$this->explicit_key_length) { 112 | $length = strlen($key); 113 | switch (true) { 114 | case $length <= 16: 115 | $this->key_length = 16; 116 | break; 117 | case $length <= 24: 118 | $this->key_length = 24; 119 | break; 120 | default: 121 | $this->key_length = 32; 122 | } 123 | $this->_setEngine(); 124 | } 125 | } 126 | } 127 | -------------------------------------------------------------------------------- /src/phpseclib/Crypt/RC4.php: -------------------------------------------------------------------------------- 1 | 20 | * setKey('abcdefgh'); 26 | * 27 | * $size = 10 * 1024; 28 | * $plaintext = ''; 29 | * for ($i = 0; $i < $size; $i++) { 30 | * $plaintext.= 'a'; 31 | * } 32 | * 33 | * echo $rc4->decrypt($rc4->encrypt($plaintext)); 34 | * ?> 35 | * 36 | * 37 | * @category Crypt 38 | * @package RC4 39 | * @author Jim Wigginton 40 | * @copyright 2007 Jim Wigginton 41 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 42 | * @link http://phpseclib.sourceforge.net 43 | */ 44 | 45 | namespace phpseclib\Crypt; 46 | 47 | /** 48 | * Pure-PHP implementation of RC4. 49 | * 50 | * @package RC4 51 | * @author Jim Wigginton 52 | * @access public 53 | */ 54 | class RC4 extends Base 55 | { 56 | /**#@+ 57 | * @access private 58 | * @see \phpseclib\Crypt\RC4::_crypt() 59 | */ 60 | const ENCRYPT = 0; 61 | const DECRYPT = 1; 62 | /**#@-*/ 63 | 64 | /** 65 | * Block Length of the cipher 66 | * 67 | * RC4 is a stream cipher 68 | * so we the block_size to 0 69 | * 70 | * @see \phpseclib\Crypt\Base::block_size 71 | * @var int 72 | * @access private 73 | */ 74 | var $block_size = 0; 75 | 76 | /** 77 | * Key Length (in bytes) 78 | * 79 | * @see \phpseclib\Crypt\RC4::setKeyLength() 80 | * @var int 81 | * @access private 82 | */ 83 | var $key_length = 128; // = 1024 bits 84 | 85 | /** 86 | * The mcrypt specific name of the cipher 87 | * 88 | * @see \phpseclib\Crypt\Base::cipher_name_mcrypt 89 | * @var string 90 | * @access private 91 | */ 92 | var $cipher_name_mcrypt = 'arcfour'; 93 | 94 | /** 95 | * Holds whether performance-optimized $inline_crypt() can/should be used. 96 | * 97 | * @see \phpseclib\Crypt\Base::inline_crypt 98 | * @var mixed 99 | * @access private 100 | */ 101 | var $use_inline_crypt = false; // currently not available 102 | 103 | /** 104 | * The Key 105 | * 106 | * @see self::setKey() 107 | * @var string 108 | * @access private 109 | */ 110 | var $key; 111 | 112 | /** 113 | * The Key Stream for decryption and encryption 114 | * 115 | * @see self::setKey() 116 | * @var array 117 | * @access private 118 | */ 119 | var $stream; 120 | 121 | /** 122 | * Default Constructor. 123 | * 124 | * Determines whether or not the mcrypt extension should be used. 125 | * 126 | * @see \phpseclib\Crypt\Base::__construct() 127 | * @return \phpseclib\Crypt\RC4 128 | * @access public 129 | */ 130 | function __construct() 131 | { 132 | parent::__construct(Base::MODE_STREAM); 133 | } 134 | 135 | /** 136 | * Test for engine validity 137 | * 138 | * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() 139 | * 140 | * @see \phpseclib\Crypt\Base::__construct() 141 | * @param int $engine 142 | * @access public 143 | * @return bool 144 | */ 145 | function isValidEngine($engine) 146 | { 147 | if ($engine == Base::ENGINE_OPENSSL) { 148 | if (version_compare(PHP_VERSION, '5.3.7') >= 0) { 149 | $this->cipher_name_openssl = 'rc4-40'; 150 | } else { 151 | switch (strlen($this->key)) { 152 | case 5: 153 | $this->cipher_name_openssl = 'rc4-40'; 154 | break; 155 | case 8: 156 | $this->cipher_name_openssl = 'rc4-64'; 157 | break; 158 | case 16: 159 | $this->cipher_name_openssl = 'rc4'; 160 | break; 161 | default: 162 | return false; 163 | } 164 | } 165 | } 166 | 167 | return parent::isValidEngine($engine); 168 | } 169 | 170 | /** 171 | * Dummy function. 172 | * 173 | * Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1]. 174 | * If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before 175 | * calling setKey(). 176 | * 177 | * [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol, 178 | * the IV's are relatively easy to predict, an attack described by 179 | * {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir} 180 | * can be used to quickly guess at the rest of the key. The following links elaborate: 181 | * 182 | * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009} 183 | * {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack} 184 | * 185 | * @param string $iv 186 | * @see self::setKey() 187 | * @access public 188 | */ 189 | function setIV($iv) 190 | { 191 | } 192 | 193 | /** 194 | * Sets the key length 195 | * 196 | * Keys can be between 1 and 256 bytes long. 197 | * 198 | * @access public 199 | * @param int $length 200 | */ 201 | function setKeyLength($length) 202 | { 203 | if ($length < 8) { 204 | $this->key_length = 1; 205 | } elseif ($length > 2048) { 206 | $this->key_length = 256; 207 | } else { 208 | $this->key_length = $length >> 3; 209 | } 210 | 211 | parent::setKeyLength($length); 212 | } 213 | 214 | /** 215 | * Encrypts a message. 216 | * 217 | * @see \phpseclib\Crypt\Base::decrypt() 218 | * @see self::_crypt() 219 | * @access public 220 | * @param string $plaintext 221 | * @return string $ciphertext 222 | */ 223 | function encrypt($plaintext) 224 | { 225 | if ($this->engine != Base::ENGINE_INTERNAL) { 226 | return parent::encrypt($plaintext); 227 | } 228 | return $this->_crypt($plaintext, self::ENCRYPT); 229 | } 230 | 231 | /** 232 | * Decrypts a message. 233 | * 234 | * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)). 235 | * At least if the continuous buffer is disabled. 236 | * 237 | * @see \phpseclib\Crypt\Base::encrypt() 238 | * @see self::_crypt() 239 | * @access public 240 | * @param string $ciphertext 241 | * @return string $plaintext 242 | */ 243 | function decrypt($ciphertext) 244 | { 245 | if ($this->engine != Base::ENGINE_INTERNAL) { 246 | return parent::decrypt($ciphertext); 247 | } 248 | return $this->_crypt($ciphertext, self::DECRYPT); 249 | } 250 | 251 | /** 252 | * Encrypts a block 253 | * 254 | * @access private 255 | * @param string $in 256 | */ 257 | function _encryptBlock($in) 258 | { 259 | // RC4 does not utilize this method 260 | } 261 | 262 | /** 263 | * Decrypts a block 264 | * 265 | * @access private 266 | * @param string $in 267 | */ 268 | function _decryptBlock($in) 269 | { 270 | // RC4 does not utilize this method 271 | } 272 | 273 | /** 274 | * Setup the key (expansion) 275 | * 276 | * @see \phpseclib\Crypt\Base::_setupKey() 277 | * @access private 278 | */ 279 | function _setupKey() 280 | { 281 | $key = $this->key; 282 | $keyLength = strlen($key); 283 | $keyStream = range(0, 255); 284 | $j = 0; 285 | for ($i = 0; $i < 256; $i++) { 286 | $j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255; 287 | $temp = $keyStream[$i]; 288 | $keyStream[$i] = $keyStream[$j]; 289 | $keyStream[$j] = $temp; 290 | } 291 | 292 | $this->stream = array(); 293 | $this->stream[self::DECRYPT] = $this->stream[self::ENCRYPT] = array( 294 | 0, // index $i 295 | 0, // index $j 296 | $keyStream 297 | ); 298 | } 299 | 300 | /** 301 | * Encrypts or decrypts a message. 302 | * 303 | * @see self::encrypt() 304 | * @see self::decrypt() 305 | * @access private 306 | * @param string $text 307 | * @param int $mode 308 | * @return string $text 309 | */ 310 | function _crypt($text, $mode) 311 | { 312 | if ($this->changed) { 313 | $this->_setup(); 314 | $this->changed = false; 315 | } 316 | 317 | $stream = &$this->stream[$mode]; 318 | if ($this->continuousBuffer) { 319 | $i = &$stream[0]; 320 | $j = &$stream[1]; 321 | $keyStream = &$stream[2]; 322 | } else { 323 | $i = $stream[0]; 324 | $j = $stream[1]; 325 | $keyStream = $stream[2]; 326 | } 327 | 328 | $len = strlen($text); 329 | for ($k = 0; $k < $len; ++$k) { 330 | $i = ($i + 1) & 255; 331 | $ksi = $keyStream[$i]; 332 | $j = ($j + $ksi) & 255; 333 | $ksj = $keyStream[$j]; 334 | 335 | $keyStream[$i] = $ksj; 336 | $keyStream[$j] = $ksi; 337 | $text[$k] = $text[$k] ^ chr($keyStream[($ksj + $ksi) & 255]); 338 | } 339 | 340 | return $text; 341 | } 342 | } 343 | -------------------------------------------------------------------------------- /src/phpseclib/Crypt/Random.php: -------------------------------------------------------------------------------- 1 | 10 | * 15 | * 16 | * 17 | * @category Crypt 18 | * @package Random 19 | * @author Jim Wigginton 20 | * @copyright 2007 Jim Wigginton 21 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 22 | * @link http://phpseclib.sourceforge.net 23 | */ 24 | 25 | namespace phpseclib\Crypt; 26 | 27 | /** 28 | * Pure-PHP Random Number Generator 29 | * 30 | * @package Random 31 | * @author Jim Wigginton 32 | * @access public 33 | */ 34 | class Random 35 | { 36 | /** 37 | * Generate a random string. 38 | * 39 | * Although microoptimizations are generally discouraged as they impair readability this function is ripe with 40 | * microoptimizations because this function has the potential of being called a huge number of times. 41 | * eg. for RSA key generation. 42 | * 43 | * @param int $length 44 | * @return string 45 | */ 46 | static function string($length) 47 | { 48 | if (!$length) { 49 | return ''; 50 | } 51 | 52 | if (version_compare(PHP_VERSION, '7.0.0', '>=')) { 53 | try { 54 | return \random_bytes($length); 55 | } catch (\Throwable $e) { 56 | // If a sufficient source of randomness is unavailable, random_bytes() will throw an 57 | // object that implements the Throwable interface (Exception, TypeError, Error). 58 | // We don't actually need to do anything here. The string() method should just continue 59 | // as normal. Note, however, that if we don't have a sufficient source of randomness for 60 | // random_bytes(), most of the other calls here will fail too, so we'll end up using 61 | // the PHP implementation. 62 | } 63 | } 64 | 65 | if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') { 66 | // method 1. prior to PHP 5.3 this would call rand() on windows hence the function_exists('class_alias') call. 67 | // ie. class_alias is a function that was introduced in PHP 5.3 68 | if (extension_loaded('mcrypt') && function_exists('class_alias')) { 69 | return @mcrypt_create_iv($length); 70 | } 71 | // method 2. openssl_random_pseudo_bytes was introduced in PHP 5.3.0 but prior to PHP 5.3.4 there was, 72 | // to quote , "possible blocking behavior". as of 5.3.4 73 | // openssl_random_pseudo_bytes and mcrypt_create_iv do the exact same thing on Windows. ie. they both 74 | // call php_win32_get_random_bytes(): 75 | // 76 | // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/openssl/openssl.c#L5008 77 | // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1392 78 | // 79 | // php_win32_get_random_bytes() is defined thusly: 80 | // 81 | // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/win32/winutil.c#L80 82 | // 83 | // we're calling it, all the same, in the off chance that the mcrypt extension is not available 84 | if (extension_loaded('openssl') && version_compare(PHP_VERSION, '5.3.4', '>=')) { 85 | return openssl_random_pseudo_bytes($length); 86 | } 87 | } else { 88 | // method 1. the fastest 89 | if (extension_loaded('openssl')) { 90 | return openssl_random_pseudo_bytes($length); 91 | } 92 | // method 2 93 | static $fp = true; 94 | if ($fp === true) { 95 | // warning's will be output unles the error suppression operator is used. errors such as 96 | // "open_basedir restriction in effect", "Permission denied", "No such file or directory", etc. 97 | $fp = @fopen('/dev/urandom', 'rb'); 98 | } 99 | if ($fp !== true && $fp !== false) { // surprisingly faster than !is_bool() or is_resource() 100 | return fread($fp, $length); 101 | } 102 | // method 3. pretty much does the same thing as method 2 per the following url: 103 | // https://github.com/php/php-src/blob/7014a0eb6d1611151a286c0ff4f2238f92c120d6/ext/mcrypt/mcrypt.c#L1391 104 | // surprisingly slower than method 2. maybe that's because mcrypt_create_iv does a bunch of error checking that we're 105 | // not doing. regardless, this'll only be called if this PHP script couldn't open /dev/urandom due to open_basedir 106 | // restrictions or some such 107 | if (extension_loaded('mcrypt')) { 108 | return @mcrypt_create_iv($length, MCRYPT_DEV_URANDOM); 109 | } 110 | } 111 | // at this point we have no choice but to use a pure-PHP CSPRNG 112 | 113 | // cascade entropy across multiple PHP instances by fixing the session and collecting all 114 | // environmental variables, including the previous session data and the current session 115 | // data. 116 | // 117 | // mt_rand seeds itself by looking at the PID and the time, both of which are (relatively) 118 | // easy to guess at. linux uses mouse clicks, keyboard timings, etc, as entropy sources, but 119 | // PHP isn't low level to be able to use those as sources and on a web server there's not likely 120 | // going to be a ton of keyboard or mouse action. web servers do have one thing that we can use 121 | // however, a ton of people visiting the website. obviously you don't want to base your seeding 122 | // soley on parameters a potential attacker sends but (1) not everything in $_SERVER is controlled 123 | // by the user and (2) this isn't just looking at the data sent by the current user - it's based 124 | // on the data sent by all users. one user requests the page and a hash of their info is saved. 125 | // another user visits the page and the serialization of their data is utilized along with the 126 | // server envirnment stuff and a hash of the previous http request data (which itself utilizes 127 | // a hash of the session data before that). certainly an attacker should be assumed to have 128 | // full control over his own http requests. he, however, is not going to have control over 129 | // everyone's http requests. 130 | static $crypto = false, $v; 131 | if ($crypto === false) { 132 | // save old session data 133 | $old_session_id = session_id(); 134 | $old_use_cookies = ini_get('session.use_cookies'); 135 | $old_session_cache_limiter = session_cache_limiter(); 136 | $_OLD_SESSION = isset($_SESSION) ? $_SESSION : false; 137 | if ($old_session_id != '') { 138 | session_write_close(); 139 | } 140 | 141 | session_id(1); 142 | ini_set('session.use_cookies', 0); 143 | session_cache_limiter(''); 144 | session_start(); 145 | 146 | $v = $seed = $_SESSION['seed'] = pack('H*', sha1( 147 | (isset($_SERVER) ? phpseclib_safe_serialize($_SERVER) : '') . 148 | (isset($_POST) ? phpseclib_safe_serialize($_POST) : '') . 149 | (isset($_GET) ? phpseclib_safe_serialize($_GET) : '') . 150 | (isset($_COOKIE) ? phpseclib_safe_serialize($_COOKIE) : '') . 151 | phpseclib_safe_serialize($GLOBALS) . 152 | phpseclib_safe_serialize($_SESSION) . 153 | phpseclib_safe_serialize($_OLD_SESSION) 154 | )); 155 | if (!isset($_SESSION['count'])) { 156 | $_SESSION['count'] = 0; 157 | } 158 | $_SESSION['count']++; 159 | 160 | session_write_close(); 161 | 162 | // restore old session data 163 | if ($old_session_id != '') { 164 | session_id($old_session_id); 165 | session_start(); 166 | ini_set('session.use_cookies', $old_use_cookies); 167 | session_cache_limiter($old_session_cache_limiter); 168 | } else { 169 | if ($_OLD_SESSION !== false) { 170 | $_SESSION = $_OLD_SESSION; 171 | unset($_OLD_SESSION); 172 | } else { 173 | unset($_SESSION); 174 | } 175 | } 176 | 177 | // in SSH2 a shared secret and an exchange hash are generated through the key exchange process. 178 | // the IV client to server is the hash of that "nonce" with the letter A and for the encryption key it's the letter C. 179 | // if the hash doesn't produce enough a key or an IV that's long enough concat successive hashes of the 180 | // original hash and the current hash. we'll be emulating that. for more info see the following URL: 181 | // 182 | // http://tools.ietf.org/html/rfc4253#section-7.2 183 | // 184 | // see the is_string($crypto) part for an example of how to expand the keys 185 | $key = pack('H*', sha1($seed . 'A')); 186 | $iv = pack('H*', sha1($seed . 'C')); 187 | 188 | // ciphers are used as per the nist.gov link below. also, see this link: 189 | // 190 | // http://en.wikipedia.org/wiki/Cryptographically_secure_pseudorandom_number_generator#Designs_based_on_cryptographic_primitives 191 | switch (true) { 192 | case class_exists('\phpseclib\Crypt\AES'): 193 | $crypto = new AES(Base::MODE_CTR); 194 | break; 195 | case class_exists('\phpseclib\Crypt\Twofish'): 196 | $crypto = new Twofish(Base::MODE_CTR); 197 | break; 198 | case class_exists('\phpseclib\Crypt\Blowfish'): 199 | $crypto = new Blowfish(Base::MODE_CTR); 200 | break; 201 | case class_exists('\phpseclib\Crypt\TripleDES'): 202 | $crypto = new TripleDES(Base::MODE_CTR); 203 | break; 204 | case class_exists('\phpseclib\Crypt\DES'): 205 | $crypto = new DES(Base::MODE_CTR); 206 | break; 207 | case class_exists('\phpseclib\Crypt\RC4'): 208 | $crypto = new RC4(); 209 | break; 210 | default: 211 | user_error(__CLASS__ . ' requires at least one symmetric cipher be loaded'); 212 | return false; 213 | } 214 | 215 | $crypto->setKey($key); 216 | $crypto->setIV($iv); 217 | $crypto->enableContinuousBuffer(); 218 | } 219 | 220 | //return $crypto->encrypt(str_repeat("\0", $length)); 221 | 222 | // the following is based off of ANSI X9.31: 223 | // 224 | // http://csrc.nist.gov/groups/STM/cavp/documents/rng/931rngext.pdf 225 | // 226 | // OpenSSL uses that same standard for it's random numbers: 227 | // 228 | // http://www.opensource.apple.com/source/OpenSSL/OpenSSL-38/openssl/fips-1.0/rand/fips_rand.c 229 | // (do a search for "ANS X9.31 A.2.4") 230 | $result = ''; 231 | while (strlen($result) < $length) { 232 | $i = $crypto->encrypt(microtime()); // strlen(microtime()) == 21 233 | $r = $crypto->encrypt($i ^ $v); // strlen($v) == 20 234 | $v = $crypto->encrypt($r ^ $i); // strlen($r) == 20 235 | $result.= $r; 236 | } 237 | return substr($result, 0, $length); 238 | } 239 | } 240 | 241 | if (!function_exists('phpseclib_safe_serialize')) { 242 | /** 243 | * Safely serialize variables 244 | * 245 | * If a class has a private __sleep() method it'll give a fatal error on PHP 5.2 and earlier. 246 | * PHP 5.3 will emit a warning. 247 | * 248 | * @param mixed $arr 249 | * @access public 250 | */ 251 | function phpseclib_safe_serialize(&$arr) 252 | { 253 | if (is_object($arr)) { 254 | return ''; 255 | } 256 | if (!is_array($arr)) { 257 | return serialize($arr); 258 | } 259 | // prevent circular array recursion 260 | if (isset($arr['__phpseclib_marker'])) { 261 | return ''; 262 | } 263 | $safearr = array(); 264 | $arr['__phpseclib_marker'] = true; 265 | foreach (array_keys($arr) as $key) { 266 | // do not recurse on the '__phpseclib_marker' key itself, for smaller memory usage 267 | if ($key !== '__phpseclib_marker') { 268 | $safearr[$key] = phpseclib_safe_serialize($arr[$key]); 269 | } 270 | } 271 | unset($arr['__phpseclib_marker']); 272 | return serialize($safearr); 273 | } 274 | } 275 | -------------------------------------------------------------------------------- /src/phpseclib/Crypt/TripleDES.php: -------------------------------------------------------------------------------- 1 | 12 | * setKey('abcdefghijklmnopqrstuvwx'); 18 | * 19 | * $size = 10 * 1024; 20 | * $plaintext = ''; 21 | * for ($i = 0; $i < $size; $i++) { 22 | * $plaintext.= 'a'; 23 | * } 24 | * 25 | * echo $des->decrypt($des->encrypt($plaintext)); 26 | * ?> 27 | * 28 | * 29 | * @category Crypt 30 | * @package TripleDES 31 | * @author Jim Wigginton 32 | * @copyright 2007 Jim Wigginton 33 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 34 | * @link http://phpseclib.sourceforge.net 35 | */ 36 | 37 | namespace phpseclib\Crypt; 38 | 39 | /** 40 | * Pure-PHP implementation of Triple DES. 41 | * 42 | * @package TripleDES 43 | * @author Jim Wigginton 44 | * @access public 45 | */ 46 | class TripleDES extends DES 47 | { 48 | /** 49 | * Encrypt / decrypt using inner chaining 50 | * 51 | * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (self::MODE_CBC3). 52 | */ 53 | const MODE_3CBC = -2; 54 | 55 | /** 56 | * Encrypt / decrypt using outer chaining 57 | * 58 | * Outer chaining is used by SSH-2 and when the mode is set to \phpseclib\Crypt\Base::MODE_CBC. 59 | */ 60 | const MODE_CBC3 = Base::MODE_CBC; 61 | 62 | /** 63 | * Key Length (in bytes) 64 | * 65 | * @see \phpseclib\Crypt\TripleDES::setKeyLength() 66 | * @var int 67 | * @access private 68 | */ 69 | var $key_length = 24; 70 | 71 | /** 72 | * The default salt used by setPassword() 73 | * 74 | * @see \phpseclib\Crypt\Base::password_default_salt 75 | * @see \phpseclib\Crypt\Base::setPassword() 76 | * @var string 77 | * @access private 78 | */ 79 | var $password_default_salt = 'phpseclib'; 80 | 81 | /** 82 | * The mcrypt specific name of the cipher 83 | * 84 | * @see \phpseclib\Crypt\DES::cipher_name_mcrypt 85 | * @see \phpseclib\Crypt\Base::cipher_name_mcrypt 86 | * @var string 87 | * @access private 88 | */ 89 | var $cipher_name_mcrypt = 'tripledes'; 90 | 91 | /** 92 | * Optimizing value while CFB-encrypting 93 | * 94 | * @see \phpseclib\Crypt\Base::cfb_init_len 95 | * @var int 96 | * @access private 97 | */ 98 | var $cfb_init_len = 750; 99 | 100 | /** 101 | * max possible size of $key 102 | * 103 | * @see self::setKey() 104 | * @see \phpseclib\Crypt\DES::setKey() 105 | * @var string 106 | * @access private 107 | */ 108 | var $key_length_max = 24; 109 | 110 | /** 111 | * Internal flag whether using self::MODE_3CBC or not 112 | * 113 | * @var bool 114 | * @access private 115 | */ 116 | var $mode_3cbc; 117 | 118 | /** 119 | * The \phpseclib\Crypt\DES objects 120 | * 121 | * Used only if $mode_3cbc === true 122 | * 123 | * @var array 124 | * @access private 125 | */ 126 | var $des; 127 | 128 | /** 129 | * Default Constructor. 130 | * 131 | * Determines whether or not the mcrypt extension should be used. 132 | * 133 | * $mode could be: 134 | * 135 | * - \phpseclib\Crypt\Base::MODE_ECB 136 | * 137 | * - \phpseclib\Crypt\Base::MODE_CBC 138 | * 139 | * - \phpseclib\Crypt\Base::MODE_CTR 140 | * 141 | * - \phpseclib\Crypt\Base::MODE_CFB 142 | * 143 | * - \phpseclib\Crypt\Base::MODE_OFB 144 | * 145 | * - \phpseclib\Crypt\TripleDES::MODE_3CBC 146 | * 147 | * If not explicitly set, \phpseclib\Crypt\Base::MODE_CBC will be used. 148 | * 149 | * @see \phpseclib\Crypt\DES::__construct() 150 | * @see \phpseclib\Crypt\Base::__construct() 151 | * @param int $mode 152 | * @access public 153 | */ 154 | function __construct($mode = Base::MODE_CBC) 155 | { 156 | switch ($mode) { 157 | // In case of self::MODE_3CBC, we init as CRYPT_DES_MODE_CBC 158 | // and additional flag us internally as 3CBC 159 | case self::MODE_3CBC: 160 | parent::__construct(Base::MODE_CBC); 161 | $this->mode_3cbc = true; 162 | 163 | // This three $des'es will do the 3CBC work (if $key > 64bits) 164 | $this->des = array( 165 | new DES(Base::MODE_CBC), 166 | new DES(Base::MODE_CBC), 167 | new DES(Base::MODE_CBC), 168 | ); 169 | 170 | // we're going to be doing the padding, ourselves, so disable it in the \phpseclib\Crypt\DES objects 171 | $this->des[0]->disablePadding(); 172 | $this->des[1]->disablePadding(); 173 | $this->des[2]->disablePadding(); 174 | break; 175 | // If not 3CBC, we init as usual 176 | default: 177 | parent::__construct($mode); 178 | } 179 | } 180 | 181 | /** 182 | * Test for engine validity 183 | * 184 | * This is mainly just a wrapper to set things up for \phpseclib\Crypt\Base::isValidEngine() 185 | * 186 | * @see \phpseclib\Crypt\Base::__construct() 187 | * @param int $engine 188 | * @access public 189 | * @return bool 190 | */ 191 | function isValidEngine($engine) 192 | { 193 | if ($engine == self::ENGINE_OPENSSL) { 194 | $this->cipher_name_openssl_ecb = 'des-ede3'; 195 | $mode = $this->_openssl_translate_mode(); 196 | $this->cipher_name_openssl = $mode == 'ecb' ? 'des-ede3' : 'des-ede3-' . $mode; 197 | } 198 | 199 | return parent::isValidEngine($engine); 200 | } 201 | 202 | /** 203 | * Sets the initialization vector. (optional) 204 | * 205 | * SetIV is not required when \phpseclib\Crypt\Base::MODE_ECB is being used. If not explicitly set, it'll be assumed 206 | * to be all zero's. 207 | * 208 | * @see \phpseclib\Crypt\Base::setIV() 209 | * @access public 210 | * @param string $iv 211 | */ 212 | function setIV($iv) 213 | { 214 | parent::setIV($iv); 215 | if ($this->mode_3cbc) { 216 | $this->des[0]->setIV($iv); 217 | $this->des[1]->setIV($iv); 218 | $this->des[2]->setIV($iv); 219 | } 220 | } 221 | 222 | /** 223 | * Sets the key length. 224 | * 225 | * Valid key lengths are 64, 128 and 192 226 | * 227 | * @see \phpseclib\Crypt\Base:setKeyLength() 228 | * @access public 229 | * @param int $length 230 | */ 231 | function setKeyLength($length) 232 | { 233 | $length >>= 3; 234 | switch (true) { 235 | case $length <= 8: 236 | $this->key_length = 8; 237 | break; 238 | case $length <= 16: 239 | $this->key_length = 16; 240 | break; 241 | default: 242 | $this->key_length = 24; 243 | } 244 | 245 | parent::setKeyLength($length); 246 | } 247 | 248 | /** 249 | * Sets the key. 250 | * 251 | * Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or 252 | * 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate. 253 | * 254 | * DES also requires that every eighth bit be a parity bit, however, we'll ignore that. 255 | * 256 | * If the key is not explicitly set, it'll be assumed to be all null bytes. 257 | * 258 | * @access public 259 | * @see \phpseclib\Crypt\DES::setKey() 260 | * @see \phpseclib\Crypt\Base::setKey() 261 | * @param string $key 262 | */ 263 | function setKey($key) 264 | { 265 | $length = $this->explicit_key_length ? $this->key_length : strlen($key); 266 | if ($length > 8) { 267 | $key = str_pad(substr($key, 0, 24), 24, chr(0)); 268 | // if $key is between 64 and 128-bits, use the first 64-bits as the last, per this: 269 | // http://php.net/function.mcrypt-encrypt#47973 270 | $key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24); 271 | } else { 272 | $key = str_pad($key, 8, chr(0)); 273 | } 274 | parent::setKey($key); 275 | 276 | // And in case of self::MODE_3CBC: 277 | // if key <= 64bits we not need the 3 $des to work, 278 | // because we will then act as regular DES-CBC with just a <= 64bit key. 279 | // So only if the key > 64bits (> 8 bytes) we will call setKey() for the 3 $des. 280 | if ($this->mode_3cbc && $length > 8) { 281 | $this->des[0]->setKey(substr($key, 0, 8)); 282 | $this->des[1]->setKey(substr($key, 8, 8)); 283 | $this->des[2]->setKey(substr($key, 16, 8)); 284 | } 285 | } 286 | 287 | /** 288 | * Encrypts a message. 289 | * 290 | * @see \phpseclib\Crypt\Base::encrypt() 291 | * @access public 292 | * @param string $plaintext 293 | * @return string $cipertext 294 | */ 295 | function encrypt($plaintext) 296 | { 297 | // parent::en/decrypt() is able to do all the work for all modes and keylengths, 298 | // except for: self::MODE_3CBC (inner chaining CBC) with a key > 64bits 299 | 300 | // if the key is smaller then 8, do what we'd normally do 301 | if ($this->mode_3cbc && strlen($this->key) > 8) { 302 | return $this->des[2]->encrypt( 303 | $this->des[1]->decrypt( 304 | $this->des[0]->encrypt( 305 | $this->_pad($plaintext) 306 | ) 307 | ) 308 | ); 309 | } 310 | 311 | return parent::encrypt($plaintext); 312 | } 313 | 314 | /** 315 | * Decrypts a message. 316 | * 317 | * @see \phpseclib\Crypt\Base::decrypt() 318 | * @access public 319 | * @param string $ciphertext 320 | * @return string $plaintext 321 | */ 322 | function decrypt($ciphertext) 323 | { 324 | if ($this->mode_3cbc && strlen($this->key) > 8) { 325 | return $this->_unpad( 326 | $this->des[0]->decrypt( 327 | $this->des[1]->encrypt( 328 | $this->des[2]->decrypt( 329 | str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, "\0") 330 | ) 331 | ) 332 | ) 333 | ); 334 | } 335 | 336 | return parent::decrypt($ciphertext); 337 | } 338 | 339 | /** 340 | * Treat consecutive "packets" as if they are a continuous buffer. 341 | * 342 | * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets 343 | * will yield different outputs: 344 | * 345 | * 346 | * echo $des->encrypt(substr($plaintext, 0, 8)); 347 | * echo $des->encrypt(substr($plaintext, 8, 8)); 348 | * 349 | * 350 | * echo $des->encrypt($plaintext); 351 | * 352 | * 353 | * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates 354 | * another, as demonstrated with the following: 355 | * 356 | * 357 | * $des->encrypt(substr($plaintext, 0, 8)); 358 | * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8))); 359 | * 360 | * 361 | * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8))); 362 | * 363 | * 364 | * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different 365 | * outputs. The reason is due to the fact that the initialization vector's change after every encryption / 366 | * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant. 367 | * 368 | * Put another way, when the continuous buffer is enabled, the state of the \phpseclib\Crypt\DES() object changes after each 369 | * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that 370 | * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them), 371 | * however, they are also less intuitive and more likely to cause you problems. 372 | * 373 | * @see \phpseclib\Crypt\Base::enableContinuousBuffer() 374 | * @see self::disableContinuousBuffer() 375 | * @access public 376 | */ 377 | function enableContinuousBuffer() 378 | { 379 | parent::enableContinuousBuffer(); 380 | if ($this->mode_3cbc) { 381 | $this->des[0]->enableContinuousBuffer(); 382 | $this->des[1]->enableContinuousBuffer(); 383 | $this->des[2]->enableContinuousBuffer(); 384 | } 385 | } 386 | 387 | /** 388 | * Treat consecutive packets as if they are a discontinuous buffer. 389 | * 390 | * The default behavior. 391 | * 392 | * @see \phpseclib\Crypt\Base::disableContinuousBuffer() 393 | * @see self::enableContinuousBuffer() 394 | * @access public 395 | */ 396 | function disableContinuousBuffer() 397 | { 398 | parent::disableContinuousBuffer(); 399 | if ($this->mode_3cbc) { 400 | $this->des[0]->disableContinuousBuffer(); 401 | $this->des[1]->disableContinuousBuffer(); 402 | $this->des[2]->disableContinuousBuffer(); 403 | } 404 | } 405 | 406 | /** 407 | * Creates the key schedule 408 | * 409 | * @see \phpseclib\Crypt\DES::_setupKey() 410 | * @see \phpseclib\Crypt\Base::_setupKey() 411 | * @access private 412 | */ 413 | function _setupKey() 414 | { 415 | switch (true) { 416 | // if $key <= 64bits we configure our internal pure-php cipher engine 417 | // to act as regular [1]DES, not as 3DES. mcrypt.so::tripledes does the same. 418 | case strlen($this->key) <= 8: 419 | $this->des_rounds = 1; 420 | break; 421 | 422 | // otherwise, if $key > 64bits, we configure our engine to work as 3DES. 423 | default: 424 | $this->des_rounds = 3; 425 | 426 | // (only) if 3CBC is used we have, of course, to setup the $des[0-2] keys also separately. 427 | if ($this->mode_3cbc) { 428 | $this->des[0]->_setupKey(); 429 | $this->des[1]->_setupKey(); 430 | $this->des[2]->_setupKey(); 431 | 432 | // because $des[0-2] will, now, do all the work we can return here 433 | // not need unnecessary stress parent::_setupKey() with our, now unused, $key. 434 | return; 435 | } 436 | } 437 | // setup our key 438 | parent::_setupKey(); 439 | } 440 | 441 | /** 442 | * Sets the internal crypt engine 443 | * 444 | * @see \phpseclib\Crypt\Base::__construct() 445 | * @see \phpseclib\Crypt\Base::setPreferredEngine() 446 | * @param int $engine 447 | * @access public 448 | * @return int 449 | */ 450 | function setPreferredEngine($engine) 451 | { 452 | if ($this->mode_3cbc) { 453 | $this->des[0]->setPreferredEngine($engine); 454 | $this->des[1]->setPreferredEngine($engine); 455 | $this->des[2]->setPreferredEngine($engine); 456 | } 457 | 458 | return parent::setPreferredEngine($engine); 459 | } 460 | } 461 | -------------------------------------------------------------------------------- /src/phpseclib/File/ANSI.php: -------------------------------------------------------------------------------- 1 | 16 | * @copyright 2012 Jim Wigginton 17 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 18 | * @link http://phpseclib.sourceforge.net 19 | */ 20 | 21 | namespace phpseclib\File; 22 | 23 | /** 24 | * Pure-PHP ANSI Decoder 25 | * 26 | * @package ANSI 27 | * @author Jim Wigginton 28 | * @access public 29 | */ 30 | class ANSI 31 | { 32 | /** 33 | * Max Width 34 | * 35 | * @var int 36 | * @access private 37 | */ 38 | var $max_x; 39 | 40 | /** 41 | * Max Height 42 | * 43 | * @var int 44 | * @access private 45 | */ 46 | var $max_y; 47 | 48 | /** 49 | * Max History 50 | * 51 | * @var int 52 | * @access private 53 | */ 54 | var $max_history; 55 | 56 | /** 57 | * History 58 | * 59 | * @var array 60 | * @access private 61 | */ 62 | var $history; 63 | 64 | /** 65 | * History Attributes 66 | * 67 | * @var array 68 | * @access private 69 | */ 70 | var $history_attrs; 71 | 72 | /** 73 | * Current Column 74 | * 75 | * @var int 76 | * @access private 77 | */ 78 | var $x; 79 | 80 | /** 81 | * Current Row 82 | * 83 | * @var int 84 | * @access private 85 | */ 86 | var $y; 87 | 88 | /** 89 | * Old Column 90 | * 91 | * @var int 92 | * @access private 93 | */ 94 | var $old_x; 95 | 96 | /** 97 | * Old Row 98 | * 99 | * @var int 100 | * @access private 101 | */ 102 | var $old_y; 103 | 104 | /** 105 | * An empty attribute cell 106 | * 107 | * @var object 108 | * @access private 109 | */ 110 | var $base_attr_cell; 111 | 112 | /** 113 | * The current attribute cell 114 | * 115 | * @var object 116 | * @access private 117 | */ 118 | var $attr_cell; 119 | 120 | /** 121 | * An empty attribute row 122 | * 123 | * @var array 124 | * @access private 125 | */ 126 | var $attr_row; 127 | 128 | /** 129 | * The current screen text 130 | * 131 | * @var array 132 | * @access private 133 | */ 134 | var $screen; 135 | 136 | /** 137 | * The current screen attributes 138 | * 139 | * @var array 140 | * @access private 141 | */ 142 | var $attrs; 143 | 144 | /** 145 | * Current ANSI code 146 | * 147 | * @var string 148 | * @access private 149 | */ 150 | var $ansi; 151 | 152 | /** 153 | * Tokenization 154 | * 155 | * @var array 156 | * @access private 157 | */ 158 | var $tokenization; 159 | 160 | /** 161 | * Default Constructor. 162 | * 163 | * @return \phpseclib\File\ANSI 164 | * @access public 165 | */ 166 | function __construct() 167 | { 168 | $attr_cell = new \stdClass(); 169 | $attr_cell->bold = false; 170 | $attr_cell->underline = false; 171 | $attr_cell->blink = false; 172 | $attr_cell->background = 'black'; 173 | $attr_cell->foreground = 'white'; 174 | $attr_cell->reverse = false; 175 | $this->base_attr_cell = clone $attr_cell; 176 | $this->attr_cell = clone $attr_cell; 177 | 178 | $this->setHistory(200); 179 | $this->setDimensions(80, 24); 180 | } 181 | 182 | /** 183 | * Set terminal width and height 184 | * 185 | * Resets the screen as well 186 | * 187 | * @param int $x 188 | * @param int $y 189 | * @access public 190 | */ 191 | function setDimensions($x, $y) 192 | { 193 | $this->max_x = $x - 1; 194 | $this->max_y = $y - 1; 195 | $this->x = $this->y = 0; 196 | $this->history = $this->history_attrs = array(); 197 | $this->attr_row = array_fill(0, $this->max_x + 2, $this->base_attr_cell); 198 | $this->screen = array_fill(0, $this->max_y + 1, ''); 199 | $this->attrs = array_fill(0, $this->max_y + 1, $this->attr_row); 200 | $this->ansi = ''; 201 | } 202 | 203 | /** 204 | * Set the number of lines that should be logged past the terminal height 205 | * 206 | * @param int $x 207 | * @param int $y 208 | * @access public 209 | */ 210 | function setHistory($history) 211 | { 212 | $this->max_history = $history; 213 | } 214 | 215 | /** 216 | * Load a string 217 | * 218 | * @param string $source 219 | * @access public 220 | */ 221 | function loadString($source) 222 | { 223 | $this->setDimensions($this->max_x + 1, $this->max_y + 1); 224 | $this->appendString($source); 225 | } 226 | 227 | /** 228 | * Appdend a string 229 | * 230 | * @param string $source 231 | * @access public 232 | */ 233 | function appendString($source) 234 | { 235 | $this->tokenization = array(''); 236 | for ($i = 0; $i < strlen($source); $i++) { 237 | if (strlen($this->ansi)) { 238 | $this->ansi.= $source[$i]; 239 | $chr = ord($source[$i]); 240 | // http://en.wikipedia.org/wiki/ANSI_escape_code#Sequence_elements 241 | // single character CSI's not currently supported 242 | switch (true) { 243 | case $this->ansi == "\x1B=": 244 | $this->ansi = ''; 245 | continue 2; 246 | case strlen($this->ansi) == 2 && $chr >= 64 && $chr <= 95 && $chr != ord('['): 247 | case strlen($this->ansi) > 2 && $chr >= 64 && $chr <= 126: 248 | break; 249 | default: 250 | continue 2; 251 | } 252 | $this->tokenization[] = $this->ansi; 253 | $this->tokenization[] = ''; 254 | // http://ascii-table.com/ansi-escape-sequences-vt-100.php 255 | switch ($this->ansi) { 256 | case "\x1B[H": // Move cursor to upper left corner 257 | $this->old_x = $this->x; 258 | $this->old_y = $this->y; 259 | $this->x = $this->y = 0; 260 | break; 261 | case "\x1B[J": // Clear screen from cursor down 262 | $this->history = array_merge($this->history, array_slice(array_splice($this->screen, $this->y + 1), 0, $this->old_y)); 263 | $this->screen = array_merge($this->screen, array_fill($this->y, $this->max_y, '')); 264 | 265 | $this->history_attrs = array_merge($this->history_attrs, array_slice(array_splice($this->attrs, $this->y + 1), 0, $this->old_y)); 266 | $this->attrs = array_merge($this->attrs, array_fill($this->y, $this->max_y, $this->attr_row)); 267 | 268 | if (count($this->history) == $this->max_history) { 269 | array_shift($this->history); 270 | array_shift($this->history_attrs); 271 | } 272 | case "\x1B[K": // Clear screen from cursor right 273 | $this->screen[$this->y] = substr($this->screen[$this->y], 0, $this->x); 274 | 275 | array_splice($this->attrs[$this->y], $this->x + 1, $this->max_x - $this->x, array_fill($this->x, $this->max_x - $this->x - 1, $this->base_attr_cell)); 276 | break; 277 | case "\x1B[2K": // Clear entire line 278 | $this->screen[$this->y] = str_repeat(' ', $this->x); 279 | $this->attrs[$this->y] = $this->attr_row; 280 | break; 281 | case "\x1B[?1h": // set cursor key to application 282 | case "\x1B[?25h": // show the cursor 283 | case "\x1B(B": // set united states g0 character set 284 | break; 285 | case "\x1BE": // Move to next line 286 | $this->_newLine(); 287 | $this->x = 0; 288 | break; 289 | default: 290 | switch (true) { 291 | case preg_match('#\x1B\[(\d+)B#', $this->ansi, $match): // Move cursor down n lines 292 | $this->old_y = $this->y; 293 | $this->y+= $match[1]; 294 | break; 295 | case preg_match('#\x1B\[(\d+);(\d+)H#', $this->ansi, $match): // Move cursor to screen location v,h 296 | $this->old_x = $this->x; 297 | $this->old_y = $this->y; 298 | $this->x = $match[2] - 1; 299 | $this->y = $match[1] - 1; 300 | break; 301 | case preg_match('#\x1B\[(\d+)C#', $this->ansi, $match): // Move cursor right n lines 302 | $this->old_x = $this->x; 303 | $this->x+= $match[1]; 304 | break; 305 | case preg_match('#\x1B\[(\d+)D#', $this->ansi, $match): // Move cursor left n lines 306 | $this->old_x = $this->x; 307 | $this->x-= $match[1]; 308 | if ($this->x < 0) { 309 | $this->x = 0; 310 | } 311 | break; 312 | case preg_match('#\x1B\[(\d+);(\d+)r#', $this->ansi, $match): // Set top and bottom lines of a window 313 | break; 314 | case preg_match('#\x1B\[(\d*(?:;\d*)*)m#', $this->ansi, $match): // character attributes 315 | $attr_cell = &$this->attr_cell; 316 | $mods = explode(';', $match[1]); 317 | foreach ($mods as $mod) { 318 | switch ($mod) { 319 | case 0: // Turn off character attributes 320 | $attr_cell = clone $this->base_attr_cell; 321 | break; 322 | case 1: // Turn bold mode on 323 | $attr_cell->bold = true; 324 | break; 325 | case 4: // Turn underline mode on 326 | $attr_cell->underline = true; 327 | break; 328 | case 5: // Turn blinking mode on 329 | $attr_cell->blink = true; 330 | break; 331 | case 7: // Turn reverse video on 332 | $attr_cell->reverse = !$attr_cell->reverse; 333 | $temp = $attr_cell->background; 334 | $attr_cell->background = $attr_cell->foreground; 335 | $attr_cell->foreground = $temp; 336 | break; 337 | default: // set colors 338 | //$front = $attr_cell->reverse ? &$attr_cell->background : &$attr_cell->foreground; 339 | $front = &$attr_cell->{ $attr_cell->reverse ? 'background' : 'foreground' }; 340 | //$back = $attr_cell->reverse ? &$attr_cell->foreground : &$attr_cell->background; 341 | $back = &$attr_cell->{ $attr_cell->reverse ? 'foreground' : 'background' }; 342 | switch ($mod) { 343 | // @codingStandardsIgnoreStart 344 | case 30: $front = 'black'; break; 345 | case 31: $front = 'red'; break; 346 | case 32: $front = 'green'; break; 347 | case 33: $front = 'yellow'; break; 348 | case 34: $front = 'blue'; break; 349 | case 35: $front = 'magenta'; break; 350 | case 36: $front = 'cyan'; break; 351 | case 37: $front = 'white'; break; 352 | 353 | case 40: $back = 'black'; break; 354 | case 41: $back = 'red'; break; 355 | case 42: $back = 'green'; break; 356 | case 43: $back = 'yellow'; break; 357 | case 44: $back = 'blue'; break; 358 | case 45: $back = 'magenta'; break; 359 | case 46: $back = 'cyan'; break; 360 | case 47: $back = 'white'; break; 361 | // @codingStandardsIgnoreEnd 362 | 363 | default: 364 | //user_error('Unsupported attribute: ' . $mod); 365 | $this->ansi = ''; 366 | break 2; 367 | } 368 | } 369 | } 370 | break; 371 | default: 372 | //user_error("{$this->ansi} is unsupported\r\n"); 373 | } 374 | } 375 | $this->ansi = ''; 376 | continue; 377 | } 378 | 379 | $this->tokenization[count($this->tokenization) - 1].= $source[$i]; 380 | switch ($source[$i]) { 381 | case "\r": 382 | $this->x = 0; 383 | break; 384 | case "\n": 385 | $this->_newLine(); 386 | break; 387 | case "\x08": // backspace 388 | if ($this->x) { 389 | $this->x--; 390 | $this->attrs[$this->y][$this->x] = clone $this->base_attr_cell; 391 | $this->screen[$this->y] = substr_replace( 392 | $this->screen[$this->y], 393 | $source[$i], 394 | $this->x, 395 | 1 396 | ); 397 | } 398 | break; 399 | case "\x0F": // shift 400 | break; 401 | case "\x1B": // start ANSI escape code 402 | $this->tokenization[count($this->tokenization) - 1] = substr($this->tokenization[count($this->tokenization) - 1], 0, -1); 403 | //if (!strlen($this->tokenization[count($this->tokenization) - 1])) { 404 | // array_pop($this->tokenization); 405 | //} 406 | $this->ansi.= "\x1B"; 407 | break; 408 | default: 409 | $this->attrs[$this->y][$this->x] = clone $this->attr_cell; 410 | if ($this->x > strlen($this->screen[$this->y])) { 411 | $this->screen[$this->y] = str_repeat(' ', $this->x); 412 | } 413 | $this->screen[$this->y] = substr_replace( 414 | $this->screen[$this->y], 415 | $source[$i], 416 | $this->x, 417 | 1 418 | ); 419 | 420 | if ($this->x > $this->max_x) { 421 | $this->x = 0; 422 | $this->_newLine(); 423 | } else { 424 | $this->x++; 425 | } 426 | } 427 | } 428 | } 429 | 430 | /** 431 | * Add a new line 432 | * 433 | * Also update the $this->screen and $this->history buffers 434 | * 435 | * @access private 436 | */ 437 | function _newLine() 438 | { 439 | //if ($this->y < $this->max_y) { 440 | // $this->y++; 441 | //} 442 | 443 | while ($this->y >= $this->max_y) { 444 | $this->history = array_merge($this->history, array(array_shift($this->screen))); 445 | $this->screen[] = ''; 446 | 447 | $this->history_attrs = array_merge($this->history_attrs, array(array_shift($this->attrs))); 448 | $this->attrs[] = $this->attr_row; 449 | 450 | if (count($this->history) >= $this->max_history) { 451 | array_shift($this->history); 452 | array_shift($this->history_attrs); 453 | } 454 | 455 | $this->y--; 456 | } 457 | $this->y++; 458 | } 459 | 460 | /** 461 | * Returns the current coordinate without preformating 462 | * 463 | * @access private 464 | * @return string 465 | */ 466 | function _processCoordinate($last_attr, $cur_attr, $char) 467 | { 468 | $output = ''; 469 | 470 | if ($last_attr != $cur_attr) { 471 | $close = $open = ''; 472 | if ($last_attr->foreground != $cur_attr->foreground) { 473 | if ($cur_attr->foreground != 'white') { 474 | $open.= ''; 475 | } 476 | if ($last_attr->foreground != 'white') { 477 | $close = '' . $close; 478 | } 479 | } 480 | if ($last_attr->background != $cur_attr->background) { 481 | if ($cur_attr->background != 'black') { 482 | $open.= ''; 483 | } 484 | if ($last_attr->background != 'black') { 485 | $close = '' . $close; 486 | } 487 | } 488 | if ($last_attr->bold != $cur_attr->bold) { 489 | if ($cur_attr->bold) { 490 | $open.= ''; 491 | } else { 492 | $close = '' . $close; 493 | } 494 | } 495 | if ($last_attr->underline != $cur_attr->underline) { 496 | if ($cur_attr->underline) { 497 | $open.= ''; 498 | } else { 499 | $close = '' . $close; 500 | } 501 | } 502 | if ($last_attr->blink != $cur_attr->blink) { 503 | if ($cur_attr->blink) { 504 | $open.= ''; 505 | } else { 506 | $close = '' . $close; 507 | } 508 | } 509 | $output.= $close . $open; 510 | } 511 | 512 | $output.= htmlspecialchars($char); 513 | 514 | return $output; 515 | } 516 | 517 | /** 518 | * Returns the current screen without preformating 519 | * 520 | * @access private 521 | * @return string 522 | */ 523 | function _getScreen() 524 | { 525 | $output = ''; 526 | $last_attr = $this->base_attr_cell; 527 | for ($i = 0; $i <= $this->max_y; $i++) { 528 | for ($j = 0; $j <= $this->max_x; $j++) { 529 | $cur_attr = $this->attrs[$i][$j]; 530 | $output.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->screen[$i][$j]) ? $this->screen[$i][$j] : ''); 531 | $last_attr = $this->attrs[$i][$j]; 532 | } 533 | $output.= "\r\n"; 534 | } 535 | $output = substr($output, 0, -2); 536 | // close any remaining open tags 537 | $output.= $this->_processCoordinate($last_attr, $this->base_attr_cell, ''); 538 | return rtrim($output); 539 | } 540 | 541 | /** 542 | * Returns the current screen 543 | * 544 | * @access public 545 | * @return string 546 | */ 547 | function getScreen() 548 | { 549 | return '
' . $this->_getScreen() . '
'; 550 | } 551 | 552 | /** 553 | * Returns the current screen and the x previous lines 554 | * 555 | * @access public 556 | * @return string 557 | */ 558 | function getHistory() 559 | { 560 | $scrollback = ''; 561 | $last_attr = $this->base_attr_cell; 562 | for ($i = 0; $i < count($this->history); $i++) { 563 | for ($j = 0; $j <= $this->max_x + 1; $j++) { 564 | $cur_attr = $this->history_attrs[$i][$j]; 565 | $scrollback.= $this->_processCoordinate($last_attr, $cur_attr, isset($this->history[$i][$j]) ? $this->history[$i][$j] : ''); 566 | $last_attr = $this->history_attrs[$i][$j]; 567 | } 568 | $scrollback.= "\r\n"; 569 | } 570 | $base_attr_cell = $this->base_attr_cell; 571 | $this->base_attr_cell = $last_attr; 572 | $scrollback.= $this->_getScreen(); 573 | $this->base_attr_cell = $base_attr_cell; 574 | 575 | return '
' . $scrollback . '
'; 576 | } 577 | } 578 | -------------------------------------------------------------------------------- /src/phpseclib/File/ASN1/Element.php: -------------------------------------------------------------------------------- 1 | 10 | * @copyright 2012 Jim Wigginton 11 | * @license http://www.opensource.org/licenses/mit-license.html MIT License 12 | * @link http://phpseclib.sourceforge.net 13 | */ 14 | 15 | namespace phpseclib\File\ASN1; 16 | 17 | /** 18 | * ASN.1 Element 19 | * 20 | * Bypass normal encoding rules in phpseclib\File\ASN1::encodeDER() 21 | * 22 | * @package ASN1 23 | * @author Jim Wigginton 24 | * @access public 25 | */ 26 | class Element 27 | { 28 | /** 29 | * Raw element value 30 | * 31 | * @var string 32 | * @access private 33 | */ 34 | var $element; 35 | 36 | /** 37 | * Constructor 38 | * 39 | * @param string $encoded 40 | * @return \phpseclib\File\ASN1\Element 41 | * @access public 42 | */ 43 | function __construct($encoded) 44 | { 45 | $this->element = $encoded; 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /src/samples.php: -------------------------------------------------------------------------------- 1 | 6 | 7 |

Available Samples

8 | 9 |
10 |
11 |
12 |

13 |  Raw Data Printing 14 |

15 |

16 | Send any raw data & commands supported by the client printer like Epson ESC/POS, HP PCL, PostScript, Zebra ZPL and Eltron EPL, and more! 17 |

18 |
19 |
20 |

21 |  Print Files 22 |

23 |

24 | Print PDF, TXT, DOC, XLS, JPG & PNG images to a client printer without displaying any Print dialog! 25 |

26 |
27 |
28 |

29 |  Printers Info 30 |

31 |

32 | Collect many useful info from all the installed printers in the client machine. 33 |

34 |
35 |
36 |
37 |
38 |

39 |  Advanced PDF Printing 40 |

41 |

42 | Print PDF files specifying advanced settings like tray, paper source, print rotation, duplex printing, pages range and more! 43 |

44 |
45 |
46 |

47 |  Advanced DOC Printing 48 |

49 |

50 | Print DOC files specifying advanced settings like duplex printing, pages range, print in reverse and more! Windows Only 51 |

52 |
53 |
54 |

55 |  Advanced XLS Printing 56 |

57 |

58 | Print XLS files specifying advanced settings like pages range (From - To) and more! Windows Only 59 |

60 |
61 |
62 |
63 |
64 |

65 |  Advanced TIF Printing 66 |

67 |

68 | Print Multipage TIF files specifying advanced settings like tray, paper source, print rotation, duplex printing, pages range and more! 69 |

70 |
71 |
72 |

73 |  Print Files With Encryption 74 |

75 |

76 | Encrypt and Print PDF, TXT, JPG & PNG files! 77 |

78 |
79 |
80 |

81 |  Print Files With Password Protection 82 |

83 |

84 | Print Password Protected PDF, DOC & XLS files! 85 |

86 |
87 |
88 |
89 | 90 | 91 | 97 | 98 | -------------------------------------------------------------------------------- /src/template.php: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | <?php echo $title; ?> 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 | 119 | 120 | 130 |
131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | --------------------------------------------------------------------------------