1 /*
2 * Printing utilities for CUPS.
3 *
4 * Copyright 2007-2011 by Apple Inc.
5 * Copyright 1997-2007 by Easy Software Products.
6 *
7 * These coded instructions, statements, and computer programs are the
8 * property of Apple Inc. and are protected by Federal copyright
9 * law. Distribution and use rights are outlined in the file "COPYING"
10 * which should have been included with this file.
11 *
12 * Contents:
13 *
14 * cups_convert_options() - Convert a PHP options array to a CUPS options array.
15 * zm_startup_phpcups() - Initialize the CUPS module.
16 * zif_cups_cancel_job() - Cancel a job.
17 * zif_cups_get_dests() - Get a list of printers and classes.
18 * zif_cups_get_jobs() - Get a list of jobs.
19 * zif_cups_last_error() - Return the last IPP status code.
20 * zif_cups_last_error_string() - Return the last IPP status
21 * zif_cups_print_file() - Print a single file.
22 * zif_cups_print_files() - Print multiple files.
23 */
24
25 /*
26 * Include necessary headers...
27 */
28
29 #include <cups/string-private.h>
30 #include "php.h"
31 #include "php_ini.h"
32 #include "ext/standard/info.h"
33 #include "phpcups.h"
34
35
36 /*
37 * PHP function list...
38 */
39
40 function_entry phpcups_functions[] =
41 {
42 PHP_FE(cups_cancel_job, NULL)
43 PHP_FE(cups_get_dests, NULL)
44 PHP_FE(cups_get_jobs, NULL)
45 PHP_FE(cups_last_error, NULL)
46 PHP_FE(cups_last_error_string, NULL)
47 PHP_FE(cups_print_file, NULL)
48 PHP_FE(cups_print_files, NULL)
49 {NULL, NULL, NULL}
50 };
51
52
53 /*
54 * PHP module info...
55 */
56
57 zend_module_entry phpcups_module_entry =
58 {
59 STANDARD_MODULE_HEADER,
60 "phpcups",
61 phpcups_functions,
62 PHP_MINIT(phpcups),
63 NULL,
64 NULL,
65 NULL,
66 NULL,
67 CUPS_SVERSION,
68 STANDARD_MODULE_PROPERTIES
69 };
70
71
ZEND_GET_MODULE(phpcups)72 ZEND_GET_MODULE(phpcups)
73
74
75 /*
76 * 'cups_convert_options()' - Convert a PHP options array to a CUPS options array.
77 */
78
79 static int /* O - Number of options */
80 cups_convert_options(
81 zval *optionsobj, /* I - Options array object */
82 cups_option_t **options) /* O - Options */
83 {
84 int num_options; /* Number of options */
85 HashTable *ht; /* Option array hash table */
86 Bucket *current; /* Current element in array */
87 zval *value; /* Current value in array */
88 char temp[255]; /* String value for numbers */
89
90
91 ht = Z_ARRVAL_P(optionsobj);
92 num_options = 0;
93
94 for (current = ht->pListHead; current; current = current->pListNext)
95 {
96 value = (zval *)current->pDataPtr;
97
98 switch (Z_TYPE_P(value))
99 {
100 case IS_LONG :
101 sprintf(temp, "%ld", Z_LVAL_P(value));
102 num_options = cupsAddOption(current->arKey, temp, num_options,
103 options);
104 break;
105
106 case IS_DOUBLE :
107 sprintf(temp, "%g", Z_DVAL_P(value));
108 num_options = cupsAddOption(current->arKey, temp, num_options,
109 options);
110 break;
111
112 case IS_BOOL :
113 num_options = cupsAddOption(current->arKey,
114 Z_BVAL_P(value) ? "true" : "false",
115 num_options, options);
116 break;
117
118 case IS_STRING :
119 num_options = cupsAddOption(current->arKey, Z_STRVAL_P(value),
120 num_options, options);
121 break;
122 }
123 }
124
125 return (num_options);
126 }
127
128
129 /*
130 * 'zm_startup_phpcups()' - Initialize the CUPS module.
131 */
132
PHP_MINIT_FUNCTION(phpcups)133 PHP_MINIT_FUNCTION(phpcups)
134 {
135 REGISTER_LONG_CONSTANT("CUPS_PRINTER_LOCAL", CUPS_PRINTER_LOCAL, CONST_CS);
136 REGISTER_LONG_CONSTANT("CUPS_PRINTER_CLASS", CUPS_PRINTER_CLASS, CONST_CS);
137 REGISTER_LONG_CONSTANT("CUPS_PRINTER_REMOTE", CUPS_PRINTER_REMOTE, CONST_CS);
138 REGISTER_LONG_CONSTANT("CUPS_PRINTER_BW", CUPS_PRINTER_BW, CONST_CS);
139 REGISTER_LONG_CONSTANT("CUPS_PRINTER_COLOR", CUPS_PRINTER_COLOR, CONST_CS);
140 REGISTER_LONG_CONSTANT("CUPS_PRINTER_DUPLEX", CUPS_PRINTER_DUPLEX, CONST_CS);
141 REGISTER_LONG_CONSTANT("CUPS_PRINTER_STAPLE", CUPS_PRINTER_STAPLE, CONST_CS);
142 REGISTER_LONG_CONSTANT("CUPS_PRINTER_COPIES", CUPS_PRINTER_COPIES, CONST_CS);
143 REGISTER_LONG_CONSTANT("CUPS_PRINTER_COLLATE", CUPS_PRINTER_COLLATE, CONST_CS);
144 REGISTER_LONG_CONSTANT("CUPS_PRINTER_PUNCH", CUPS_PRINTER_PUNCH, CONST_CS);
145 REGISTER_LONG_CONSTANT("CUPS_PRINTER_COVER", CUPS_PRINTER_COVER, CONST_CS);
146 REGISTER_LONG_CONSTANT("CUPS_PRINTER_BIND", CUPS_PRINTER_BIND, CONST_CS);
147 REGISTER_LONG_CONSTANT("CUPS_PRINTER_SORT", CUPS_PRINTER_SORT, CONST_CS);
148 REGISTER_LONG_CONSTANT("CUPS_PRINTER_SMALL", CUPS_PRINTER_SMALL, CONST_CS);
149 REGISTER_LONG_CONSTANT("CUPS_PRINTER_MEDIUM", CUPS_PRINTER_MEDIUM, CONST_CS);
150 REGISTER_LONG_CONSTANT("CUPS_PRINTER_LARGE", CUPS_PRINTER_LARGE, CONST_CS);
151 REGISTER_LONG_CONSTANT("CUPS_PRINTER_VARIABLE", CUPS_PRINTER_VARIABLE, CONST_CS);
152 REGISTER_LONG_CONSTANT("CUPS_PRINTER_IMPLICIT", CUPS_PRINTER_IMPLICIT, CONST_CS);
153 REGISTER_LONG_CONSTANT("CUPS_PRINTER_DEFAULT", CUPS_PRINTER_DEFAULT, CONST_CS);
154 REGISTER_LONG_CONSTANT("CUPS_PRINTER_FAX", CUPS_PRINTER_FAX, CONST_CS);
155 REGISTER_LONG_CONSTANT("CUPS_PRINTER_REJECTING", CUPS_PRINTER_REJECTING, CONST_CS);
156 REGISTER_LONG_CONSTANT("CUPS_PRINTER_DELETE", CUPS_PRINTER_DELETE, CONST_CS);
157 REGISTER_LONG_CONSTANT("CUPS_PRINTER_NOT_SHARED", CUPS_PRINTER_NOT_SHARED, CONST_CS);
158 REGISTER_LONG_CONSTANT("CUPS_PRINTER_AUTHENTICATED", CUPS_PRINTER_AUTHENTICATED, CONST_CS);
159 REGISTER_LONG_CONSTANT("CUPS_PRINTER_COMMANDS", CUPS_PRINTER_COMMANDS, CONST_CS);
160 REGISTER_LONG_CONSTANT("CUPS_PRINTER_DISCOVERED", CUPS_PRINTER_DISCOVERED, CONST_CS);
161 REGISTER_LONG_CONSTANT("CUPS_PRINTER_OPTIONS", CUPS_PRINTER_OPTIONS, CONST_CS);
162
163 REGISTER_LONG_CONSTANT("IPP_OK", IPP_OK, CONST_CS);
164 REGISTER_LONG_CONSTANT("IPP_OK_SUBST", IPP_OK_SUBST, CONST_CS);
165 REGISTER_LONG_CONSTANT("IPP_OK_CONFLICT", IPP_OK_CONFLICT, CONST_CS);
166 REGISTER_LONG_CONSTANT("IPP_OK_IGNORED_SUBSCRIPTIONS", IPP_OK_IGNORED_SUBSCRIPTIONS, CONST_CS);
167 REGISTER_LONG_CONSTANT("IPP_OK_IGNORED_NOTIFICATIONS", IPP_OK_IGNORED_NOTIFICATIONS, CONST_CS);
168 REGISTER_LONG_CONSTANT("IPP_OK_TOO_MANY_EVENTS", IPP_OK_TOO_MANY_EVENTS, CONST_CS);
169 REGISTER_LONG_CONSTANT("IPP_OK_BUT_CANCEL_SUBSCRIPTION", IPP_OK_BUT_CANCEL_SUBSCRIPTION, CONST_CS);
170 REGISTER_LONG_CONSTANT("IPP_OK_EVENTS_COMPLETE", IPP_OK_EVENTS_COMPLETE, CONST_CS);
171 REGISTER_LONG_CONSTANT("IPP_REDIRECTION_OTHER_SITE", IPP_REDIRECTION_OTHER_SITE, CONST_CS);
172 REGISTER_LONG_CONSTANT("IPP_BAD_REQUEST", IPP_BAD_REQUEST, CONST_CS);
173 REGISTER_LONG_CONSTANT("IPP_FORBIDDEN", IPP_FORBIDDEN, CONST_CS);
174 REGISTER_LONG_CONSTANT("IPP_NOT_AUTHENTICATED", IPP_NOT_AUTHENTICATED, CONST_CS);
175 REGISTER_LONG_CONSTANT("IPP_NOT_AUTHORIZED", IPP_NOT_AUTHORIZED, CONST_CS);
176 REGISTER_LONG_CONSTANT("IPP_NOT_POSSIBLE", IPP_NOT_POSSIBLE, CONST_CS);
177 REGISTER_LONG_CONSTANT("IPP_TIMEOUT", IPP_TIMEOUT, CONST_CS);
178 REGISTER_LONG_CONSTANT("IPP_NOT_FOUND", IPP_NOT_FOUND, CONST_CS);
179 REGISTER_LONG_CONSTANT("IPP_GONE", IPP_GONE, CONST_CS);
180 REGISTER_LONG_CONSTANT("IPP_REQUEST_ENTITY", IPP_REQUEST_ENTITY, CONST_CS);
181 REGISTER_LONG_CONSTANT("IPP_REQUEST_VALUE", IPP_REQUEST_VALUE, CONST_CS);
182 REGISTER_LONG_CONSTANT("IPP_DOCUMENT_FORMAT", IPP_DOCUMENT_FORMAT, CONST_CS);
183 REGISTER_LONG_CONSTANT("IPP_ATTRIBUTES", IPP_ATTRIBUTES, CONST_CS);
184 REGISTER_LONG_CONSTANT("IPP_URI_SCHEME", IPP_URI_SCHEME, CONST_CS);
185 REGISTER_LONG_CONSTANT("IPP_CHARSET", IPP_CHARSET, CONST_CS);
186 REGISTER_LONG_CONSTANT("IPP_CONFLICT", IPP_CONFLICT, CONST_CS);
187 REGISTER_LONG_CONSTANT("IPP_COMPRESSION_NOT_SUPPORTED", IPP_COMPRESSION_NOT_SUPPORTED, CONST_CS);
188 REGISTER_LONG_CONSTANT("IPP_COMPRESSION_ERROR", IPP_COMPRESSION_ERROR, CONST_CS);
189 REGISTER_LONG_CONSTANT("IPP_DOCUMENT_FORMAT_ERROR", IPP_DOCUMENT_FORMAT_ERROR, CONST_CS);
190 REGISTER_LONG_CONSTANT("IPP_DOCUMENT_ACCESS_ERROR", IPP_DOCUMENT_ACCESS_ERROR, CONST_CS);
191 REGISTER_LONG_CONSTANT("IPP_ATTRIBUTES_NOT_SETTABLE", IPP_ATTRIBUTES_NOT_SETTABLE, CONST_CS);
192 REGISTER_LONG_CONSTANT("IPP_IGNORED_ALL_SUBSCRIPTIONS", IPP_IGNORED_ALL_SUBSCRIPTIONS, CONST_CS);
193 REGISTER_LONG_CONSTANT("IPP_TOO_MANY_SUBSCRIPTIONS", IPP_TOO_MANY_SUBSCRIPTIONS, CONST_CS);
194 REGISTER_LONG_CONSTANT("IPP_IGNORED_ALL_NOTIFICATIONS", IPP_IGNORED_ALL_NOTIFICATIONS, CONST_CS);
195 REGISTER_LONG_CONSTANT("IPP_PRINT_SUPPORT_FILE_NOT_FOUND", IPP_PRINT_SUPPORT_FILE_NOT_FOUND, CONST_CS);
196 REGISTER_LONG_CONSTANT("IPP_INTERNAL_ERROR", IPP_INTERNAL_ERROR, CONST_CS);
197 REGISTER_LONG_CONSTANT("IPP_OPERATION_NOT_SUPPORTED", IPP_OPERATION_NOT_SUPPORTED, CONST_CS);
198 REGISTER_LONG_CONSTANT("IPP_SERVICE_UNAVAILABLE", IPP_SERVICE_UNAVAILABLE, CONST_CS);
199 REGISTER_LONG_CONSTANT("IPP_VERSION_NOT_SUPPORTED", IPP_VERSION_NOT_SUPPORTED, CONST_CS);
200 REGISTER_LONG_CONSTANT("IPP_DEVICE_ERROR", IPP_DEVICE_ERROR, CONST_CS);
201 REGISTER_LONG_CONSTANT("IPP_TEMPORARY_ERROR", IPP_TEMPORARY_ERROR, CONST_CS);
202 REGISTER_LONG_CONSTANT("IPP_NOT_ACCEPTING", IPP_NOT_ACCEPTING, CONST_CS);
203 REGISTER_LONG_CONSTANT("IPP_PRINTER_BUSY", IPP_PRINTER_BUSY, CONST_CS);
204 REGISTER_LONG_CONSTANT("IPP_ERROR_JOB_CANCELLED", IPP_ERROR_JOB_CANCELLED, CONST_CS);
205 REGISTER_LONG_CONSTANT("IPP_MULTIPLE_JOBS_NOT_SUPPORTED", IPP_MULTIPLE_JOBS_NOT_SUPPORTED, CONST_CS);
206 REGISTER_LONG_CONSTANT("IPP_PRINTER_IS_DEACTIVATED", IPP_PRINTER_IS_DEACTIVATED, CONST_CS);
207
208 return (SUCCESS);
209 }
210
211 /*
212 * 'zif_cups_cancel_job()' - Cancel a job.
213 */
214
PHP_FUNCTION(cups_cancel_job)215 PHP_FUNCTION(cups_cancel_job)
216 {
217 char *dest; /* Destination */
218 int dest_len, /* Length of destination */
219 id; /* Job ID */
220
221
222 if (ZEND_NUM_ARGS() != 2 ||
223 zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl", &dest, &dest_len, &id))
224 {
225 WRONG_PARAM_COUNT;
226 }
227
228 RETURN_LONG(cupsCancelJob(dest, id));
229 }
230
231
232 /*
233 * 'zif_cups_get_dests()' - Get a list of printers and classes.
234 */
235
PHP_FUNCTION(cups_get_dests)236 PHP_FUNCTION(cups_get_dests)
237 {
238 int i, j, /* Looping vars */
239 num_dests; /* Number of destinations */
240 cups_dest_t *dests, /* Destinations */
241 *dest; /* Current destination */
242 cups_option_t *option; /* Current option */
243 zval *destobj, /* Destination object */
244 *optionsobj; /* Options object */
245
246
247 if (ZEND_NUM_ARGS() != 0)
248 {
249 WRONG_PARAM_COUNT;
250 }
251
252 if ((num_dests = cupsGetDests(&dests)) <= 0)
253 {
254 RETURN_NULL();
255 }
256
257 if (array_init(return_value) == SUCCESS)
258 {
259 for (i = 0, dest = dests; i < num_dests; i ++, dest ++)
260 {
261 MAKE_STD_ZVAL(destobj);
262
263 if (object_init(destobj) == SUCCESS)
264 {
265 /*
266 * Add properties to the destination for each of the cups_dest_t
267 * members...
268 */
269
270 add_property_string(destobj, "name", dest->name, 1);
271 add_property_string(destobj, "instance",
272 dest->instance ? dest->instance : "", 1);
273 add_property_long(destobj, "is_default", dest->is_default);
274
275 /*
276 * Create an associative array for the options...
277 */
278
279 MAKE_STD_ZVAL(optionsobj);
280
281 if (array_init(optionsobj) == SUCCESS)
282 {
283 for (j = 0, option = dest->options;
284 j < dest->num_options;
285 j ++, option ++)
286 add_assoc_string(optionsobj, option->name, option->value, 1);
287
288 add_property_zval(destobj, "options", optionsobj);
289 }
290
291 add_index_zval(return_value, i, destobj);
292 }
293 }
294 }
295
296 cupsFreeDests(num_dests, dests);
297 }
298
299
300 /*
301 * 'zif_cups_get_jobs()' - Get a list of jobs.
302 */
303
PHP_FUNCTION(cups_get_jobs)304 PHP_FUNCTION(cups_get_jobs)
305 {
306 char *dest; /* Destination */
307 int dest_len, /* Length of destination */
308 myjobs, /* Only show my jobs? */
309 completed; /* Show completed jobs? */
310 int i, /* Looping var */
311 num_jobs; /* Number of jobs */
312 cups_job_t *jobs, /* Jobs */
313 *job; /* Current job */
314 zval *jobobj; /* Job object */
315
316
317
318
319 if (ZEND_NUM_ARGS() != 3 ||
320 zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sll", &dest, &dest_len, &myjobs, &completed))
321 {
322 WRONG_PARAM_COUNT;
323 }
324
325 if (!*dest)
326 dest = NULL;
327
328 if ((num_jobs = cupsGetJobs(&jobs, dest, myjobs, completed)) <= 0)
329 {
330 RETURN_NULL();
331 }
332
333 if (array_init(return_value) == SUCCESS)
334 {
335 for (i = 0, job = jobs; i < num_jobs; i ++, job ++)
336 {
337 MAKE_STD_ZVAL(jobobj);
338
339 if (object_init(jobobj) == SUCCESS)
340 {
341 /*
342 * Add properties to the job for each of the cups_job_t
343 * members...
344 */
345
346 add_property_long(jobobj, "id", job->id);
347 add_property_string(jobobj, "dest", job->dest, 1);
348 add_property_string(jobobj, "title", job->title, 1);
349 add_property_string(jobobj, "user", job->user, 1);
350 add_property_string(jobobj, "format", job->format, 1);
351 add_property_long(jobobj, "state", job->state);
352 add_property_long(jobobj, "size", job->size);
353 add_property_long(jobobj, "priority", job->priority);
354 add_property_long(jobobj, "completed_time", job->completed_time);
355 add_property_long(jobobj, "creation_time", job->creation_time);
356 add_property_long(jobobj, "processing_time", job->processing_time);
357
358 add_index_zval(return_value, i, jobobj);
359 }
360 }
361 }
362
363 cupsFreeJobs(num_jobs, jobs);
364 }
365
366
367 /*
368 * 'zif_cups_last_error()' - Return the last IPP status code.
369 */
370
PHP_FUNCTION(cups_last_error)371 PHP_FUNCTION(cups_last_error)
372 {
373 if (ZEND_NUM_ARGS() != 0)
374 {
375 WRONG_PARAM_COUNT;
376 }
377
378 RETURN_LONG(cupsLastError());
379 }
380
381
382 /*
383 * 'zif_cups_last_error_string()' - Return the last IPP status-message.
384 */
385
PHP_FUNCTION(cups_last_error_string)386 PHP_FUNCTION(cups_last_error_string)
387 {
388 if (ZEND_NUM_ARGS() != 0)
389 {
390 WRONG_PARAM_COUNT;
391 }
392
393 RETURN_STRING((char *)cupsLastErrorString(), 1);
394 }
395
396
397 /*
398 * 'zif_cups_print_file()' - Print a single file.
399 */
400
PHP_FUNCTION(cups_print_file)401 PHP_FUNCTION(cups_print_file)
402 {
403 char *dest; /* Destination */
404 int dest_len; /* Length of destination */
405 char *filename; /* Filename */
406 int filename_len; /* Length of filename */
407 char *title; /* Title */
408 int title_len; /* Length of title */
409 zval *optionsobj; /* Array of options */
410 int num_options; /* Number of options */
411 cups_option_t *options; /* Options */
412 int id; /* Job ID */
413
414
415 if (ZEND_NUM_ARGS() != 4 ||
416 zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sssa", &dest, &dest_len,
417 &filename, &filename_len,
418 &title, &title_len, &optionsobj))
419 {
420 WRONG_PARAM_COUNT;
421 }
422
423 num_options = cups_convert_options(optionsobj, &options);
424
425 id = cupsPrintFile(dest, filename, title, num_options, options);
426
427 cupsFreeOptions(num_options, options);
428
429 RETURN_LONG(id);
430 }
431
432
433 /*
434 * 'zif_cups_print_files()' - Print multiple files.
435 */
436
PHP_FUNCTION(cups_print_files)437 PHP_FUNCTION(cups_print_files)
438 {
439 char *dest; /* Destination */
440 int dest_len; /* Length of destination */
441 zval *filesobj; /* Files array */
442 int num_files; /* Number of files */
443 const char *files[1000]; /* Files */
444 char *title; /* Title */
445 int title_len; /* Length of title */
446 zval *optionsobj; /* Array of options */
447 int num_options; /* Number of options */
448 cups_option_t *options; /* Options */
449 HashTable *ht2; /* Option array hash table */
450 Bucket *current; /* Current element in array */
451 int id; /* Job ID */
452
453
454 if (ZEND_NUM_ARGS() != 4 ||
455 zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sasa", &dest, &dest_len, &filesobj,
456 &title, &title_len, &optionsobj))
457 {
458 WRONG_PARAM_COUNT;
459 }
460
461 ht2 = Z_ARRVAL_P(filesobj);
462 num_files = 0;
463
464 for (current = ht2->pListHead; current; current = current->pListNext)
465 {
466 files[num_files ++] = Z_STRVAL_P(((zval *)current->pDataPtr));
467
468 if (num_files >= (int)(sizeof(files) / sizeof(files[0])))
469 break;
470 }
471
472 num_options = cups_convert_options(optionsobj, &options);
473
474 id = cupsPrintFiles(dest, num_files, files, title, num_options, options);
475
476 cupsFreeOptions(num_options, options);
477
478 RETURN_LONG(id);
479 }
480
481