1 /*
2 cupsext - Python extension class for CUPS 1.1+
3 
4 (c) Copyright 2003-2015 HP Development Company, L.P.
5 
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
10 
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 GNU General Public License for more details.
15 
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
19 
20 
21 Portions based on:
22 "lpadmin" command for the Common UNIX Printing System (CUPS).
23 
24 Copyright 1997-2003 by Easy Software Products.
25 
26 These coded instructions, statements, and computer programs are the
27 property of Easy Software Products and are protected by Federal
28 copyright law.  Distribution and use rights are outlined in the file
29 "LICENSE.txt" which should have been included with this file.  If this
30 file is missing or damaged please contact Easy Software Products
31 at:
32 
33 Attn: CUPS Licensing Information
34 Easy Software Products
35 44141 Airport View Drive, Suite 204
36 Hollywood, Maryland 20636-3111 USA
37 
38 Voice: (301) 373-9603
39 EMail: cups-info@cups.org
40   WWW: http://www.cups.org
41 
42 Redistribution and use in source and binary forms, with or without
43 modification, are permitted provided that the following conditions
44 are met:
45 1. Redistributions of source code must retain the above copyright
46 notice, this list of conditions and the following disclaimer.
47 2. Redistributions in binary form must reproduce the above copyright
48 notice, this list of conditions and the following disclaimer in the
49 documentation and/or other materials provided with the distribution.
50 3. Neither the name of HP nor the names of its
51 contributors may be used to endorse or promote products derived
52 from this software without specific prior written permission.
53 
54 THIS SOFTWARE IS PROVIDED BY THE AUTHOR "AS IS" AND ANY EXPRESS OR IMPLIED
55 WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
56 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.  IN
57 NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
58 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
59 TO, PATENT INFRINGEMENT; PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
60 OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
61 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
62 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
63 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
64 
65 
66 Requires:
67 CUPS 1.1+
68 Python 2.2+
69 
70 Author:
71 Don Welch
72 Yashwant Kumar Sahu
73 Sanjay Kumar
74 */
75 
76 
77 #include <Python.h>
78 #include <structmember.h>
79 #include <cups/cups.h>
80 #include <cups/language.h>
81 #include <cups/ppd.h>
82 #include <syslog.h>
83 #include <stdarg.h>
84 #include <sys/types.h>
85 #include <pwd.h>
86 
87 
88 #include "cupsext.h"
89 #include "hp_ipp.h"
90 #include "utils.h"
91 
92 
93 /* Ref: PEP 353 (Python 2.5) */
94 #if PY_VERSION_HEX < 0x02050000
95 typedef int Py_ssize_t;
96 #define PY_SSIZE_T_MAX INT_MAX
97 #define PY_SSIZE_T_MIN INT_MIN
98 #endif
99 
100 #define _STRINGIZE(x) #x
101 #define STRINGIZE(x) _STRINGIZE(x)
102 
103 
104 //static http_t * http = NULL;     /* HTTP object */
105 
releaseCupsInstance(PyObject * self,PyObject * args)106 PyObject * releaseCupsInstance( PyObject * self, PyObject * args )
107 {
108     _releaseCupsInstance();
109 
110     return Py_BuildValue( "i", 1 );
111 }
112 
113 int g_num_options = 0;
114 cups_option_t * g_options;
115 
116 ppd_file_t * ppd = NULL;
117 cups_dest_t * dest = NULL;
118 
119 cups_dest_t * g_dests = NULL;
120 int g_num_dests = 0;
121 
122 //static int auth_cancel_req = 0;    // 0--> authentication cancel is not requested, 1 --> authentication cancelled
123 
124 const char * g_ppd_file = NULL;
125 
getUserName()126 static char *getUserName()
127 {
128   struct passwd *pw = getpwuid(geteuid());
129   if (pw)
130   {
131     return pw->pw_name;
132   }
133   return NULL;
134 }
135 
PyObj_from_UTF8(const char * utf8)136 static PyObject * PyObj_from_UTF8(const char *utf8)
137 {
138     PyObject *val = PyUnicode_Decode(utf8, strlen(utf8), "utf-8", NULL);
139 
140     if (!val)
141     {
142         // CUPS 1.2 always gives us UTF-8.  Before CUPS 1.2, the
143         // ppd-* strings come straight from the PPD with no
144         // transcoding, but the attributes-charset is still 'utf-8'
145         // so we've no way of knowing the real encoding.
146         // In that case, detect the error and force it to ASCII.
147         char * ascii;
148         const char * orig = utf8;
149         int i;
150 
151         PyErr_Clear();
152         ascii = malloc(1 + strlen (orig));
153 
154         for (i = 0; orig[i]; i++)
155         {
156             ascii[i] = orig[i] & 0x7f;
157         }
158 
159         ascii[i] = '\0';
160         //val = PyString_FromString( ascii );
161         val = PYUnicode_STRING( ascii );
162         free( ascii );
163     }
164 
165     return val;
166 }
167 
debug(const char * text)168 void debug(const char * text)
169 {
170     char buf[4096];
171     sprintf( buf, "print '%s'", text);
172     PyRun_SimpleString( buf );
173 
174 }
175 
176 //staticforward PyTypeObject printer_Type;
177 static PyTypeObject printer_Type;
178 
179 #define printerObject_Check(v) ((v)->ob_type == &printer_Type)
180 
181 typedef struct
182 {
183     PyObject_HEAD
184     PyObject * device_uri;
185     PyObject * printer_uri;
186     PyObject * name;
187     PyObject * location;
188     PyObject * makemodel;
189     PyObject * info;
190     int accepting;
191     int state;
192 }
193 printer_Object;
194 
195 
printer_dealloc(printer_Object * self)196 static void printer_dealloc( printer_Object * self )
197 {
198 
199     Py_XDECREF( self->name );
200     Py_XDECREF( self->device_uri );
201     Py_XDECREF( self->printer_uri );
202     Py_XDECREF( self->location );
203     Py_XDECREF( self->makemodel );
204     Py_XDECREF( self->info );
205     PyObject_DEL( self );
206 }
207 
208 
209 static PyMemberDef printer_members[] =
210 {
211     { "device_uri", T_OBJECT_EX, offsetof( printer_Object, device_uri ), 0, "Device URI (device-uri)" },
212     { "printer_uri", T_OBJECT_EX, offsetof( printer_Object, printer_uri ), 0, "Printer URI (printer-uri)" },
213     { "name", T_OBJECT_EX, offsetof( printer_Object, name ), 0, "Name (printer-name)" },
214     { "location", T_OBJECT_EX, offsetof( printer_Object, location ), 0, "Location (printer-location)" },
215     { "makemodel", T_OBJECT_EX, offsetof( printer_Object, makemodel ), 0, "Make and model (printer-make-and-model)" },
216     { "state", T_INT, offsetof( printer_Object, state ), 0, "State (printer-state)" },
217     { "info", T_OBJECT_EX, offsetof( printer_Object, info ), 0, "Info/description (printer-info)" },
218     { "accepting", T_INT, offsetof( printer_Object, accepting ), 0, "Accepting/rejecting" },
219     {0}
220 };
221 
222 static PyTypeObject printer_Type =
223 {
224     /* PyObject_HEAD_INIT( &PyType_Type ) */
225     /* 0, */
226     /*                                  /\* ob_size *\/ */
227     PyVarObject_HEAD_INIT( &PyType_Type, 0 )
228     "cupsext.Printer",                   /* tp_name */
229     sizeof( printer_Object ),              /* tp_basicsize */
230     0,                                     /* tp_itemsize */
231     ( destructor ) printer_dealloc,           /* tp_dealloc */
232     0,                                     /* tp_print */
233     0,                                     /* tp_getattr */
234     0,                                     /* tp_setattr */
235     0,                                     /* tp_compare */
236     0,                                     /* tp_repr */
237     0,                                     /* tp_as_number */
238     0,                                     /* tp_as_sequence */
239     0,                                     /* tp_as_mapping */
240     0,                                     /* tp_hash */
241     0,                                     /* tp_call */
242     0,                                     /* tp_str */
243     PyObject_GenericGetAttr,               /* tp_getattro */
244     PyObject_GenericSetAttr,               /* tp_setattro */
245     0,                                     /* tp_as_buffer */
246     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,         /* tp_flags */
247     "CUPS Printer object",                 /* tp_doc */
248     0,                                     /* tp_traverse */
249     0,                                     /* tp_clear */
250     0,                                     /* tp_richcompare */
251     0,                                     /* tp_weaklistoffset */
252     0,                                     /* tp_iter */
253     0,                                     /* tp_iternext */
254     0,         /*job_methods, */           /* tp_methods */
255     printer_members,                       /* tp_members */
256     0,                                     /* tp_getset */
257     0,                                     /* tp_base */
258     0,                                     /* tp_dict */
259     0,                                     /* tp_descr_get */
260     0,                                     /* tp_descr_set */
261     0,                                     /* tp_dictoffset */
262     0,                                     /* tp_init */
263     0,                                     /* tp_alloc */
264     0,                                     /* tp_new */
265 };
266 
267 
268 
269 
_newPrinter(char * device_uri,char * name,char * printer_uri,char * location,char * makemodel,char * info,int state,int accepting)270 static PyObject * _newPrinter( char * device_uri,
271                                char * name,
272                                char * printer_uri,
273                                char * location,
274                                char * makemodel,
275                                char * info,
276                                int state,
277                                int accepting )
278 {
279     printer_Object * self = PyObject_New( printer_Object, &printer_Type );
280 
281     if ( !self )
282         return NULL;
283 
284     if ( device_uri != NULL )
285         self->device_uri = Py_BuildValue( "s", device_uri );
286 
287     if ( printer_uri != NULL )
288         self->printer_uri = Py_BuildValue( "s", printer_uri );
289 
290     if ( name != NULL )
291         self->name = Py_BuildValue( "s", name );
292 
293     if ( location != NULL )
294         self->location = Py_BuildValue( "s", location );
295 
296     if ( makemodel != NULL )
297         self->makemodel = Py_BuildValue( "s", makemodel );
298 
299     if ( info != NULL )
300         self->info = Py_BuildValue( "s", info );
301 
302     self->accepting = accepting;
303     self->state = state;
304 
305     return ( PyObject * ) self;
306 }
307 
newPrinter(PyObject * self,PyObject * args,PyObject * kwargs)308 static PyObject * newPrinter( PyObject * self, PyObject * args, PyObject * kwargs )
309 {
310     char * device_uri = "";
311     char * name = "";
312     char * location = "";
313     char * makemodel = "";
314     int state = 0;
315     char * printer_uri = "";
316     char * info = "";
317     int accepting = 0;
318 
319     char * kwds[] = { "device_uri", "name", "printer_uri", "location",
320                       "makemodel", "info", "state", "accepting", NULL
321                     };
322 
323     if ( !PyArg_ParseTupleAndKeywords( args, kwargs, "zz|zzzzii", kwds,
324                                        &device_uri, &name, &printer_uri,
325                                        &location, &makemodel, &info, &state,
326                                        &accepting )        )
327         return NULL;
328 
329     return _newPrinter( device_uri, printer_uri, name, location, makemodel, info, state, accepting);
330 }
331 
332 
getPrinters(PyObject * self,PyObject * args)333 PyObject * getPrinters( PyObject * self, PyObject * args )
334 {
335     int status = 0;
336     int index = 0;
337     printer_t *printer = NULL;
338     printer_t *printer_list = NULL;
339 
340     PyObject * pyprinter_list;
341     pyprinter_list = PyList_New( 0 );
342 
343 
344     status = getCupsPrinters(&printer_list);
345 
346     for (printer = printer_list; printer!=NULL; printer=printer->next)
347     {
348         printer_Object * pyprinter;
349         pyprinter = ( printer_Object * ) _newPrinter( printer->device_uri,
350                                                     printer->name,
351                                                     printer->printer_uri,
352                                                     printer->location,
353                                                     printer->make_model,
354                                                     printer->info,
355                                                     printer->state,
356                                                     printer->accepting );
357 
358 
359         PyList_Append( pyprinter_list, ( PyObject * ) pyprinter );
360     }
361 
362 abort:
363     if (printer_list != NULL) {
364         freePrinterList(printer_list);
365     }
366 
367     return pyprinter_list;
368 }
369 
370 
addPrinter(PyObject * self,PyObject * args)371 PyObject * addPrinter( PyObject * self, PyObject * args )
372 {
373     int status = 0;
374     char * name, * device_uri, *location, *ppd_file, * info, * model;
375     const char * status_str = "successful-ok";
376 
377     if ( !PyArg_ParseTuple( args, "zzzzzz",
378                             &name,             // name of printer
379                             &device_uri,       // DeviceURI (e.g., hp:/usb/PSC_2200_Series?serial=0000000010)
380                             &location,         // location of printer
381                             &ppd_file,         // path to PPD file (uncompressed, must exist)
382                             &model,            // model name (e.g., foomatic:...)
383                             &info              // info/description
384                           ) )
385     {
386         status_str = "Invalid arguments";
387         goto abort;
388     }
389 
390     status = addCupsPrinter(name, device_uri, location, ppd_file, model, info);
391     status_str = getCupsErrorString(status);
392 
393 abort:
394 
395     return Py_BuildValue( "is", status, status_str );
396 
397 }
398 
399 /*
400  * 'delPrinter()' - Delete a printer from the system...
401  */
delPrinter(PyObject * self,PyObject * args)402 PyObject * delPrinter( PyObject * self, PyObject * args )
403 {
404     char * name;
405     int status = 0;
406     const char * status_str = "";
407 
408     if ( !PyArg_ParseTuple( args, "z",
409                             &name ) )         // name of printer
410     {
411         goto abort;
412     }
413 
414     status = delCupsPrinter(name);
415     status_str = getCupsErrorString(status);
416 
417 abort:
418 
419     return Py_BuildValue( "is", status ,status_str);
420 }
421 
422 
423 /*
424  * 'setDefaultPrinter()' - Set the default printing destination.
425  */
426 
setDefaultPrinter(PyObject * self,PyObject * args)427 PyObject * setDefaultPrinter( PyObject * self, PyObject * args )
428 
429 {
430     char * name;
431     int status = 0;
432     const char * status_str = "";
433 
434     if ( !PyArg_ParseTuple( args, "z",
435                             &name ) )         // name of printer
436     {
437         goto abort;
438     }
439 
440     status  = setDefaultCupsPrinter(name);
441     status_str = getCupsErrorString(status);
442 
443 abort:
444     return Py_BuildValue( "is", status, status_str );
445 }
446 
447 
448 
controlPrinter(PyObject * self,PyObject * args)449 PyObject * controlPrinter( PyObject * self, PyObject * args )
450 {
451     int status = 0;
452     int op;
453     char *name;
454     const char * status_str = "";
455 
456     if ( !PyArg_ParseTuple( args, "zi", &name, &op) )
457     {
458         goto abort;
459     }
460 
461     status = controlCupsPrinter(name, op);
462 
463     status_str = getCupsErrorString(status);
464     if ( status <= IPP_OK_CONFLICT)
465         status = IPP_OK;
466 
467 abort:
468     return Py_BuildValue( "is", status, status_str );
469 }
470 
471 
472 
473 //staticforward PyTypeObject job_Type;
474 static PyTypeObject job_Type;
475 typedef struct
476 {
477     PyObject_HEAD
478     int id;
479     PyObject * dest;
480     PyObject * title;
481     PyObject * user;
482     int state;
483     int size;
484 }
485 job_Object;
486 
487 
488 
job_dealloc(job_Object * self)489 static void job_dealloc( job_Object * self )
490 {
491 
492     Py_XDECREF( self->dest );
493     Py_XDECREF( self->title );
494     Py_XDECREF( self->user );
495     PyObject_DEL( self );
496 }
497 
498 static PyMemberDef job_members[] =
499 {
500     { "id", T_INT, offsetof( job_Object, id ), 0, "Id" },
501     { "dest", T_OBJECT_EX, offsetof( job_Object, dest ), 0, "Destination" },
502     { "state", T_INT, offsetof( job_Object, state ), 0, "State" },
503     { "title", T_OBJECT_EX, offsetof( job_Object, title ), 0, "Title" },
504     { "user", T_OBJECT_EX, offsetof( job_Object, user ), 0, "User" },
505     { "size", T_INT, offsetof( job_Object, size ), 0, "Size" },
506     {0}
507 };
508 
509 
510 
511 static PyTypeObject job_Type =
512 {
513     /* PyObject_HEAD_INIT( &PyType_Type ) */
514     /* 0,                                     /\* ob_size *\/ */
515     PyVarObject_HEAD_INIT( &PyType_Type, 0 )
516     "Job",                                 /* tp_name */
517     sizeof( job_Object ),                  /* tp_basicsize */
518     0,                                     /* tp_itemsize */
519     ( destructor ) job_dealloc,               /* tp_dealloc */
520     0,                                     /* tp_print */
521     0,                                     /* tp_getattr */
522     0,                                     /* tp_setattr */
523     0,                                     /* tp_compare */
524     0,                                     /* tp_repr */
525     0,                                     /* tp_as_number */
526     0,                                     /* tp_as_sequence */
527     0,                                     /* tp_as_mapping */
528     0,                                     /* tp_hash */
529     0,                                     /* tp_call */
530     0,                                     /* tp_str */
531     PyObject_GenericGetAttr,               /* tp_getattro */
532     PyObject_GenericSetAttr,               /* tp_setattro */
533     0,                                     /* tp_as_buffer */
534     Py_TPFLAGS_DEFAULT,                    /* tp_flags */
535     "CUPS Job object",                     /* tp_doc */
536     0,                                     /* tp_traverse */
537     0,                                     /* tp_clear */
538     0,                                     /* tp_richcompare */
539     0,                                     /* tp_weaklistoffset */
540     0,                                     /* tp_iter */
541     0,                                     /* tp_iternext */
542     0,         /*job_methods, */                  /* tp_methods */
543     job_members,                           /* tp_members */
544     0,                                     /* tp_getset */
545     0,                                     /* tp_base */
546     0,                                     /* tp_dict */
547     0,                                     /* tp_descr_get */
548     0,                                     /* tp_descr_set */
549     0,                                     /* tp_dictoffset */
550     0,                                     /* tp_init */
551     0,        //(initproc)job_init,            /* tp_init */
552     0,                                     /* tp_alloc */
553     //PyType_GenericAlloc,
554     0,         //job_new,                       /* tp_new */
555     //PyType_GenericNew,
556 };
557 
558 
_newJob(int id,int state,char * dest,char * title,char * user,int size)559 static /*job_Object **/ PyObject * _newJob( int id, int state, char * dest, char * title, char * user, int size )
560 {
561     job_Object * jo;
562     jo = PyObject_New( job_Object, &job_Type );
563     if ( jo == NULL )
564         return NULL;
565     jo->id = id;
566     jo->size = size;
567     jo->state = state;
568     if ( dest != NULL )
569         jo->dest = PyObj_from_UTF8( dest );
570     else
571         jo->dest = Py_BuildValue( "" );
572 
573     if ( title != NULL )
574         jo->title = PyObj_from_UTF8( title );
575     else
576         jo->title = Py_BuildValue( "" );
577 
578     if ( user != NULL )
579         jo->user = PyObj_from_UTF8( user );
580     else
581         jo->user = Py_BuildValue( "" );
582 
583     return ( PyObject * ) jo;
584 
585 }
586 
newJob(PyObject * self,PyObject * args,PyObject * kwargs)587 static /*job_Object **/ PyObject * newJob( PyObject * self, PyObject * args, PyObject * kwargs )
588 {
589     char * dest = "";
590     int id = 0;
591     int state = 0;
592     char * title = "";
593     char * user = "";
594     int size = 0;
595 
596     char * kwds[] = { "id", "state", "dest", "title", "user", "size", NULL };
597 
598     if ( !PyArg_ParseTupleAndKeywords( args, kwargs, "i|izzzi", kwds,
599                                        &id, &state, &dest, &title, &user, &size ) )
600         return NULL;
601 
602     return _newJob( id, state, dest, title, user, size );
603 
604 }
605 
606 
getDefaultPrinter(PyObject * self,PyObject * args)607 PyObject * getDefaultPrinter( PyObject * self, PyObject * args )
608 {
609     const char * defdest;
610     defdest = cupsGetDefault();
611 
612     /*char buf[1024];
613     sprintf( buf, "print 'Default Printer: %s'", defdest);
614     PyRun_SimpleString( buf );
615     */
616 
617     if ( defdest == NULL )
618         return Py_BuildValue( "" ); // None
619     else
620         return Py_BuildValue( "s", defdest );
621 
622 }
623 
624 
cancelJob(PyObject * self,PyObject * args)625 PyObject * cancelJob( PyObject * self, PyObject * args )         // cancelJob( dest, jobid )
626 {
627     int status;
628     int jobid;
629     char * dest;
630 
631     if ( !PyArg_ParseTuple( args, "si", &dest, &jobid ) )
632     {
633         return Py_BuildValue( "i", 0 );
634     }
635 
636     status = cupsCancelJob( dest, jobid );
637 
638     return Py_BuildValue( "i", status );
639 }
640 
getJobs(PyObject * self,PyObject * args)641 PyObject * getJobs( PyObject * self, PyObject * args )
642 {
643     cups_job_t * jobs;
644     Py_ssize_t i;
645     int num_jobs;
646     PyObject * job_list;
647     int my_job;
648     int completed;
649 
650     if ( !PyArg_ParseTuple( args, "ii", &my_job, &completed ) )
651     {
652         return PyList_New( ( Py_ssize_t ) 0 );
653     }
654 
655     num_jobs = cupsGetJobs( &jobs, NULL, my_job, completed );
656 
657     if ( num_jobs > 0 )
658     {
659         job_list = PyList_New( num_jobs );
660 
661         for ( i = 0; i < num_jobs; i++ )
662         {
663             job_Object * newjob;
664             newjob = ( job_Object * ) _newJob( jobs[ i ].id,
665                                                jobs[ i ].state,
666                                                jobs[ i ].dest,
667                                                jobs[ i ].title,
668                                                jobs[ i ].user,
669                                                jobs[ i ].size );
670 
671             PyList_SetItem( job_list, i, ( PyObject * ) newjob );
672 
673         }
674         cupsFreeJobs( num_jobs, jobs );
675     }
676     else
677     {
678         job_list = PyList_New( ( Py_ssize_t ) 0 );
679     }
680     return job_list;
681 }
682 
getVersion(PyObject * self,PyObject * args)683 PyObject * getVersion( PyObject * self, PyObject * args )
684 {
685     return Py_BuildValue( "f", CUPS_VERSION );
686 }
687 
getVersionTuple(PyObject * self,PyObject * args)688 PyObject * getVersionTuple( PyObject * self, PyObject * args )
689 {
690     return Py_BuildValue( "(iii)", CUPS_VERSION_MAJOR, CUPS_VERSION_MINOR, CUPS_VERSION_PATCH );
691 }
692 
getServer(PyObject * self,PyObject * args)693 PyObject * getServer( PyObject * self, PyObject * args )
694 {
695     return Py_BuildValue( "s", cupsServer() );
696 }
697 
setServer(PyObject * self,PyObject * args)698 PyObject * setServer( PyObject * self, PyObject * args )
699 {
700     char * server = NULL;
701 
702     if (!PyArg_ParseTuple(args, "z", &server))
703         return Py_BuildValue( "" );
704 
705     if (!strlen(server)) // Pass an empty string to restore default server
706         server = NULL;
707 
708     cupsSetServer(server);
709 
710     return Py_BuildValue( "" );
711 }
712 
713 
714 // ***************************************************************************************************
715 
716 #if 0
717 PyObject * getPPDList( PyObject * self, PyObject * args )
718 {
719     int status = 0;
720     PyObject * result;
721 
722     result = PyDict_New ();
723 
724     status = getCupsPPDList();
725 
726 abort:
727     return result;
728 }
729 #endif
730 
getPPDList(PyObject * self,PyObject * args)731 PyObject *getPPDList( PyObject * self, PyObject * args )
732 {
733 
734     /*Py_BuildValue( "s", device_uri )
735         * Build a CUPS_GET_PPDS request, which requires the following
736         * attributes:
737         *
738         *    attributes-charset
739         *    attributes-natural-language
740         *    printer-uri
741         */
742 
743     ipp_t *request = NULL,                 /* IPP Request */
744                      *response = NULL;                /* IPP Response */
745     PyObject * result;
746     cups_lang_t *language;
747     ipp_attribute_t * attr;
748 
749     result = PyDict_New ();
750 
751     if (acquireCupsInstance () == NULL)
752     {
753         goto abort;
754     }
755 
756     request = ippNew();
757 
758     ippSetOperation( request, CUPS_GET_PPDS );
759     ippSetRequestId ( request, 1 );
760 
761     language = cupsLangDefault();
762 
763     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
764                  "attributes-charset", NULL, cupsLangEncoding(language));
765 
766     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
767                  "attributes-natural-language", NULL, language->language);
768 
769     //ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
770     //             NULL, "ipp://localhost/printers/");
771 
772     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
773                  NULL, "ipp://localhost/printers/officejet_4100");
774 
775     ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "requested-attributes",
776                  NULL, "all");
777 
778     /*
779     * Do the request and get back a response...
780     */
781 
782     if ((response = cupsDoRequest(http, request, "/")) != NULL)
783     {
784 
785         for (attr = ippFirstAttribute( response ); attr; attr = ippNextAttribute( response ))
786         {
787             PyObject *dict;
788             char *ppdname = NULL;
789 
790             while (attr && ippGetGroupTag( attr ) != IPP_TAG_PRINTER)
791                 attr = ippNextAttribute( response );
792 
793             if (!attr)
794                 break;
795 
796             dict = PyDict_New ();
797 
798             for (; attr && ippGetGroupTag( attr ) == IPP_TAG_PRINTER; attr = ippNextAttribute( response ))
799             {
800                 PyObject *val = NULL;
801 
802                 if (!strcmp (ippGetName( attr ), "ppd-name") && ippGetValueTag( attr ) == IPP_TAG_NAME)
803                 {
804                     ppdname = ippGetString( attr, 0, NULL );
805 
806                     //sprintf( buf, "print '%s'", ppdname);
807                     //PyRun_SimpleString( buf );
808                 }
809 
810                 else if (ippGetValueTag( attr ) == IPP_TAG_TEXT || ippGetValueTag( attr ) == IPP_TAG_NAME || ippGetValueTag( attr ) == IPP_TAG_KEYWORD)
811                     //else if ((!strcmp (ippGetName( attr ), "ppd-natural-language") && ippGetValueTag( attr ) == IPP_TAG_LANGUAGE) ||
812                     //    (!strcmp (ippGetName( attr ), "ppd-make-and-model") && ippGetValueTag( attr ) == IPP_TAG_TEXT) ||
813                     //    (!strcmp (ippGetName( attr ), "ppd-make") && ippGetValueTag( attr ) == IPP_TAG_TEXT) ||
814                     //    (!strcmp (ippGetName( attr ), "ppd-device-id") && ippGetValueTag( attr ) == IPP_TAG_TEXT))
815                 {
816                     val = PyObj_from_UTF8(ippGetString( attr, 0, NULL ));
817                 }
818 
819                 if (val)
820                 {
821                     PyDict_SetItemString (dict, ippGetName( attr ), val);
822                     Py_DECREF (val);
823                 }
824             }
825 
826             if (ppdname)
827             {
828                 PyDict_SetItemString (result, ppdname, dict);
829             }
830             else
831             {
832                 Py_DECREF (dict);
833             }
834 
835             if (!attr)
836                 break;
837         }
838 
839         //return result;
840     }
841 
842 abort:
843     if ( response != NULL )
844         ippDelete( response );
845 
846     return result;
847 }
848 
849 
850 
851 //////////////////////////////////////////////////////////////////////////
852 //NEW IPP CHANGES
853 //////////////////////////////////////////////////////////////////////////
854 
855 /*
856  * 'getStatusAttributes()' - This function gets Printer status and cartridge info attributes
857  *  It creates python dictionary  out of those attributes and then return to the caller.
858  */
getStatusAttributes(PyObject * self,PyObject * args)859 PyObject * getStatusAttributes( PyObject * self, PyObject * args )
860 {
861     ipp_t *response = NULL;           /* IPP response object */
862     ipp_attribute_t *attr = NULL;     /* Current IPP attribute */
863     attr_t* attr_list = NULL;
864     PyObject * dict;
865     PyObject * pyval;
866     int attr_count = 0;
867     int index = 0;
868     int valueindex = 0;
869     char * device_uri;
870 
871     if ( !PyArg_ParseTuple( args, "z", &device_uri) )
872     {
873         goto abort;
874     }
875 
876     response = getDeviceStatusAttributes(device_uri, &attr_count);
877     if(!response)
878         goto abort;
879 
880     //Parse the response and create the dictionary. Dictionary will look something like below.
881 
882     /*{
883         ('printer-state-reasons', ['none']),
884         ('printer-state', [3]),
885         ('marker-types', ['inkCartridge', 'inkCartridge', 'inkCartridge', 'inkCartridge']),
886         ('marker-levels', [80, 60, 70, 60]),
887         ('marker-low-levels', [1, 1, 1, 1]),
888         ('marker-names', ['black ink', 'cyan ink', 'magenta ink', 'yellow ink']),
889       }
890 
891     */
892 
893     dict = PyDict_New();
894     if (dict == NULL)
895         goto abort;
896 
897     for ( attr = ippFirstAttribute( response ); attr != NULL; attr = ippNextAttribute( response ) )
898     {
899         if ( strcmp( ippGetName( attr ), "attributes-charset" ) == 0 || strcmp(ippGetName( attr ), "attributes-natural-language" ) == 0 )
900             continue; //Don't pass common attributes
901 
902         pyval = PyList_New(0);
903 
904         for(index = 0; index < ippGetCount(attr); index++)
905         {
906             if (ippGetValueTag( attr ) == IPP_TAG_ENUM || ippGetValueTag( attr ) == IPP_TAG_INTEGER)
907             {
908                 PyList_Append(pyval, Py_BuildValue( "i", ippGetInteger( attr, index)));
909             }
910             else if (ippGetValueTag( attr ) == IPP_TAG_TEXT || ippGetValueTag( attr ) == IPP_TAG_NAME || ippGetValueTag( attr ) == IPP_TAG_KEYWORD)
911             {
912                 PyList_Append(pyval, Py_BuildValue( "s", ippGetString( attr, index, NULL )));
913             }
914             else
915             {
916                 PyList_Append(pyval, Py_BuildValue( "s", "?"));
917             }
918         }
919 
920         PyDict_SetItemString (dict, ippGetName( attr ), pyval);
921         Py_DECREF (pyval);
922     }
923 
924 abort:
925     if ( response != NULL )
926         ippDelete( response );
927 
928     return dict;
929 }
930 
931 //////////////////////////////////////////////////////////////////////////
932 //NEW IPP CHANGES
933 //////////////////////////////////////////////////////////////////////////
934 
935 
openPPD(PyObject * self,PyObject * args)936 PyObject * openPPD( PyObject * self, PyObject * args )
937 {
938     char * printer;
939     FILE * file;
940     int j;
941 
942     if ( !PyArg_ParseTuple( args, "z", &printer ) )
943     {
944         return Py_BuildValue( "" ); // None
945     }
946 
947     if ( ( g_ppd_file = cupsGetPPD( ( const char * ) printer ) ) == NULL )
948     {
949         goto bailout;
950     }
951 
952     if ( ( file = fopen( g_ppd_file, "r" )) == NULL )
953     {
954         unlink(g_ppd_file);
955         g_ppd_file = NULL;
956         goto bailout;
957     }
958 
959     ppd = ppdOpen( file );
960     ppdLocalize( ppd );
961     fclose( file );
962 
963     g_num_dests = cupsGetDests( &g_dests );
964 
965     if ( g_num_dests == 0 )
966     {
967         goto bailout;
968     }
969 
970     if ( ( dest = cupsGetDest( printer, NULL, g_num_dests, g_dests ) ) == NULL )
971     {
972         goto bailout;
973     }
974 
975     ppdMarkDefaults( ppd );
976     cupsMarkOptions( ppd, dest->num_options, dest->options );
977 
978     for ( j = 0; j < dest->num_options; j++ )
979     {
980         if ( cupsGetOption( dest->options[ j ].name, g_num_options, g_options ) == NULL )
981         {
982             g_num_options = cupsAddOption( dest->options[ j ].name, dest->options[ j ].value, g_num_options, &g_options );
983         }
984     }
985 
986 bailout:
987     return Py_BuildValue( "s", g_ppd_file );
988 }
989 
990 
closePPD(PyObject * self,PyObject * args)991 PyObject * closePPD( PyObject * self, PyObject * args )
992 {
993     if ( ppd != NULL )
994     {
995         ppdClose( ppd );
996         unlink( g_ppd_file );
997     }
998 
999     ppd = NULL;
1000 
1001     return Py_BuildValue( "" ); // None
1002 }
1003 
1004 
getPPD(PyObject * self,PyObject * args)1005 PyObject * getPPD( PyObject * self, PyObject * args )
1006 {
1007     char * printer;
1008 
1009     if ( !PyArg_ParseTuple( args, "z", &printer ) )
1010     {
1011         return Py_BuildValue( "" ); // None
1012     }
1013 
1014     const char * ppd_file;
1015     ppd_file = cupsGetPPD( ( const char * ) printer );
1016 
1017     return Py_BuildValue( "s", ppd_file );
1018 
1019 }
1020 
1021 
getPPDOption(PyObject * self,PyObject * args)1022 PyObject * getPPDOption( PyObject * self, PyObject * args )
1023 {
1024     if ( ppd != NULL )
1025     {
1026         char * option;
1027 
1028         if ( !PyArg_ParseTuple( args, "z", &option ) )
1029         {
1030             return Py_BuildValue( "" ); // None
1031         }
1032 
1033         ppd_choice_t * marked_choice;
1034         marked_choice = ppdFindMarkedChoice( ppd, option );
1035 
1036         if ( marked_choice == NULL )
1037         {
1038             return Py_BuildValue( "" ); // None
1039         }
1040         else
1041         {
1042             return Py_BuildValue( "s", marked_choice->text );
1043         }
1044     }
1045     else
1046     {
1047         return Py_BuildValue( "" ); // None
1048     }
1049 }
1050 
findPPDAttribute(PyObject * self,PyObject * args)1051 PyObject * findPPDAttribute( PyObject * self, PyObject * args )
1052 {
1053     if ( ppd != NULL )
1054     {
1055         char * name;
1056         char * spec;
1057 
1058         if ( !PyArg_ParseTuple( args, "zz", &name, &spec ) )
1059         {
1060             return Py_BuildValue( "" ); // None
1061         }
1062 
1063         ppd_attr_t * ppd_attr;
1064         ppd_attr = ppdFindAttr(ppd, name, spec );
1065         if ( ppd_attr == NULL )
1066         {
1067             return Py_BuildValue( "" ); // None
1068         }
1069         else
1070         {
1071             return Py_BuildValue( "s", ppd_attr->value );
1072         }
1073     }
1074     else
1075     {
1076         return Py_BuildValue( "" ); // None
1077     }
1078 }
1079 
getPPDPageSize(PyObject * self,PyObject * args)1080 PyObject * getPPDPageSize( PyObject * self, PyObject * args )
1081 {
1082     //char buf[1024];
1083 
1084     if ( ppd != NULL )
1085     {
1086         ppd_size_t * size = NULL;
1087         float width = 0.0;
1088         float length = 0.0;
1089         ppd_choice_t * page_size = NULL;
1090 
1091         page_size = ppdFindMarkedChoice( ppd, "PageSize" );
1092 
1093         //sprintf( buf, "print '%s'", page_size->text );
1094         //PyRun_SimpleString( buf );
1095 
1096         if ( page_size == NULL )
1097             goto bailout;
1098 
1099         size = ppdPageSize( ppd, page_size->text );
1100 
1101         if ( size == NULL )
1102             goto bailout;
1103 
1104         //sprintf( buf, "print '%s'", size->name );
1105         //PyRun_SimpleString( buf );
1106 
1107         width = ppdPageWidth( ppd, page_size->text );
1108         length = ppdPageLength( ppd, page_size->text );
1109 
1110         return Py_BuildValue( "(sffffff)", page_size->text, width, length, size->left,
1111                               size->bottom, size->right, size->top );
1112     }
1113 
1114 bailout:
1115     return Py_BuildValue( "(sffffff)", "", 0.0, 0.0, 0.0, 0.0, 0.0, 0.0 );
1116 }
1117 
1118 // ***************************************************************************************************
1119 
1120 
1121 
resetOptions(PyObject * self,PyObject * args)1122 PyObject * resetOptions( PyObject * self, PyObject * args )
1123 {
1124     if ( g_num_options > 0 )
1125         cupsFreeOptions( g_num_options, g_options );
1126     g_num_options = 0;
1127     g_options = ( cups_option_t * ) 0;
1128 
1129     return Py_BuildValue( "" );
1130 
1131 }
1132 
addOption(PyObject * self,PyObject * args)1133 PyObject * addOption( PyObject * self, PyObject * args )
1134 {
1135     char * option;
1136 
1137     if ( !PyArg_ParseTuple( args, "z", &option ) )
1138     {
1139         return Py_BuildValue( "i", 0 );
1140     }
1141 
1142     g_num_options = cupsParseOptions( option, g_num_options, &g_options );
1143 
1144     return Py_BuildValue( "i", g_num_options ); // >0
1145 }
1146 
removeOption(PyObject * self,PyObject * args)1147 PyObject * removeOption( PyObject * self, PyObject * args )
1148 {
1149     char * option;
1150     int j;
1151     int r = 0;
1152 
1153     if ( !PyArg_ParseTuple( args, "z", &option ) )
1154     {
1155         return Py_BuildValue( "i", 0 );
1156     }
1157 
1158     for (j = 0; j < g_num_options; j++)
1159     {
1160         if ( !strcasecmp(g_options[j].name, option) )
1161         {
1162             g_num_options--;
1163 
1164             if ( j < g_num_options )
1165             {
1166                 memcpy( (g_options + j), (g_options + j + 1),
1167                         sizeof(cups_option_t) * (g_num_options - j) );
1168 
1169                 r = 1;
1170             }
1171         }
1172     }
1173 
1174     return Py_BuildValue( "i", r );
1175 }
1176 
1177 
getOptions(PyObject * self,PyObject * args)1178 PyObject * getOptions( PyObject * self, PyObject * args )
1179 {
1180     PyObject * option_list;
1181     int j;
1182 
1183     option_list = PyList_New( ( Py_ssize_t ) 0 );
1184     for ( j = 0; j < g_num_options; j++ )
1185     {
1186         PyList_Append( option_list, Py_BuildValue( "(ss)", g_options[ j ].name, g_options[ j ].value ) );
1187     }
1188 
1189     return option_list;
1190 }
1191 
duplicateSection(PyObject * self,PyObject * args)1192 PyObject * duplicateSection( PyObject * self, PyObject * args )
1193 {
1194     int i = 0, j, k, len;
1195     const char *section;
1196 
1197     if ( !PyArg_ParseTuple( args, "z", &section ) )
1198     {
1199         return Py_BuildValue( "" ); // None
1200     }
1201 
1202     len = strlen(section);
1203     if ( ppd != NULL )
1204     {
1205         for( j = 0; j < ppd->num_groups; j++)
1206         {
1207             for( k = 0; k < ppd->groups[j].num_options; k++)
1208             {
1209                 if(strncasecmp(ppd->groups[j].options[k].keyword, section, len) == 0)
1210                 {
1211                     i = 1;
1212                 }
1213             }
1214         }
1215     }
1216     return Py_BuildValue( "i", i);
1217 }
1218 
1219 // ***************************************************************************************************
1220 
1221 
1222 
getGroupList(PyObject * self,PyObject * args)1223 PyObject * getGroupList( PyObject * self, PyObject * args )
1224 {
1225     PyObject * group_list;
1226     ppd_group_t *group;
1227     int i;
1228 
1229     /*  debug("at 0"); */
1230 
1231     if ( ppd != NULL && dest != NULL )
1232     {
1233         /*      debug("at 1"); */
1234 
1235         group_list = PyList_New( ( Py_ssize_t ) 0 );
1236         for ( i = ppd->num_groups, group = ppd->groups; i > 0; i--, group++ )
1237         {
1238             /*          debug(group->name); */
1239             PyList_Append( group_list, PyObj_from_UTF8( group->name ) );
1240         }
1241 
1242         return group_list;
1243     }
1244 
1245     return PyList_New( ( Py_ssize_t ) 0 );
1246 }
1247 
1248 
getGroup(PyObject * self,PyObject * args)1249 PyObject * getGroup( PyObject * self, PyObject * args )
1250 {
1251     const char *the_group;
1252     ppd_group_t *group;
1253     int i;
1254 
1255     if ( !PyArg_ParseTuple( args, "z", &the_group ) )
1256     {
1257         goto bailout;
1258     }
1259 
1260     if ( ppd != NULL && dest != NULL )
1261     {
1262         for ( i = ppd->num_groups, group = ppd->groups; i > 0; i--, group++ )
1263         {
1264             if ( strcasecmp( group->name, the_group ) == 0 )
1265             {
1266                 return Py_BuildValue( "(si)", group->text, group->num_subgroups);
1267             }
1268         }
1269     }
1270 
1271 bailout:
1272     return Py_BuildValue( "" );
1273 }
1274 
1275 
1276 
getOptionList(PyObject * self,PyObject * args)1277 PyObject * getOptionList( PyObject * self, PyObject * args )
1278 {
1279     PyObject * option_list;
1280     const char *the_group;
1281     ppd_group_t *group;
1282     int i, j;
1283     ppd_option_t *option;
1284 
1285     if ( !PyArg_ParseTuple( args, "z", &the_group ) )
1286     {
1287         goto bailout;
1288     }
1289 
1290     if ( ppd != NULL && dest != NULL )
1291     {
1292         option_list = PyList_New( ( Py_ssize_t ) 0 );
1293 
1294         for ( i = ppd->num_groups, group = ppd->groups; i > 0; i--, group++ )
1295         {
1296             if ( strcasecmp( group->name, the_group ) == 0 )
1297             {
1298                 for ( j = group->num_options, option = group->options; j > 0; j--, option++ )
1299                 {
1300                     PyList_Append( option_list, PyObj_from_UTF8( option->keyword ) );
1301                 }
1302 
1303                 break;
1304             }
1305         }
1306 
1307         return option_list;
1308     }
1309 
1310 
1311 
1312 bailout:
1313     return PyList_New( ( Py_ssize_t ) 0 );
1314 }
1315 
1316 
1317 
1318 
getOption(PyObject * self,PyObject * args)1319 PyObject * getOption( PyObject * self, PyObject * args )
1320 {
1321     const char *the_group;
1322     const char *the_option;
1323     ppd_group_t *group;
1324     int i, j;
1325     ppd_option_t *option;
1326 
1327 
1328     if ( !PyArg_ParseTuple( args, "zz", &the_group, &the_option ) )
1329     {
1330         goto bailout;
1331     }
1332 
1333     if ( ppd != NULL && dest != NULL )
1334     {
1335 
1336         for ( i = ppd->num_groups, group = ppd->groups; i > 0; i--, group++ )
1337         {
1338             if ( strcasecmp( group->name, the_group ) == 0 )
1339             {
1340                 for ( j = group->num_options, option = group->options; j > 0; j--, option++ )
1341                 {
1342                     if ( strcasecmp( option->keyword, the_option ) == 0 )
1343                     {
1344                         return Py_BuildValue( "(ssbi)", option->text, option->defchoice,
1345                                               option->conflicted > 0 ? 1 : 0, option->ui );
1346                     }
1347                 }
1348             }
1349         }
1350     }
1351 
1352 bailout:
1353     return Py_BuildValue( "" );
1354 }
1355 
1356 
getChoiceList(PyObject * self,PyObject * args)1357 PyObject * getChoiceList( PyObject * self, PyObject * args )
1358 {
1359     PyObject * choice_list;
1360     const char *the_group;
1361     const char *the_option;
1362     ppd_group_t *group;
1363     int i, j, k;
1364     ppd_option_t *option;
1365     ppd_choice_t *choice;
1366 
1367     if ( !PyArg_ParseTuple( args, "zz", &the_group, &the_option ) )
1368     {
1369         goto bailout;
1370     }
1371 
1372     if ( ppd != NULL && dest != NULL )
1373     {
1374         choice_list = PyList_New( ( Py_ssize_t ) 0 );
1375 
1376         for ( i = ppd->num_groups, group = ppd->groups; i > 0; i--, group++ )
1377         {
1378             if ( strcasecmp( group->name, the_group ) == 0 )
1379             {
1380                 for ( j = group->num_options, option = group->options; j > 0; j--, option++ )
1381                 {
1382                     if ( strcasecmp( option->keyword, the_option ) == 0 )
1383                     {
1384                         for ( k = option->num_choices, choice = option->choices; k > 0; k--, choice++ )
1385                         {
1386                             PyList_Append( choice_list, PyObj_from_UTF8( choice->choice ) );
1387                         }
1388 
1389                         break;
1390                     }
1391                 }
1392                 break;
1393             }
1394         }
1395 
1396         return choice_list;
1397     }
1398 
1399 
1400 bailout:
1401     return PyList_New( ( Py_ssize_t ) 0 );
1402 }
1403 
1404 
1405 
getChoice(PyObject * self,PyObject * args)1406 PyObject * getChoice( PyObject * self, PyObject * args )
1407 {
1408     const char * the_group;
1409     const char *the_option;
1410     const char *the_choice;
1411     ppd_group_t *group;
1412     int i, j, k;
1413     ppd_option_t *option;
1414     ppd_choice_t *choice;
1415 
1416 
1417     if ( !PyArg_ParseTuple( args, "zzz", &the_group, &the_option, &the_choice ) )
1418     {
1419         goto bailout;
1420     }
1421 
1422     if ( ppd != NULL && dest != NULL )
1423     {
1424         for ( i = ppd->num_groups, group = ppd->groups; i > 0; i--, group++ )
1425         {
1426             if ( strcasecmp( group->name, the_group ) == 0 )
1427             {
1428                 for ( j = group->num_options, option = group->options; j > 0; j--, option++ )
1429                 {
1430                     if ( strcasecmp( option->keyword, the_option ) == 0 )
1431                     {
1432                         for ( k = option->num_choices, choice = option->choices; k > 0; k--, choice++ )
1433                         {
1434                             if ( strcasecmp( choice->choice, the_choice ) == 0 )
1435                             {
1436                                 return Py_BuildValue( "(sb)", choice->text, choice->marked > 0 ? 1 : 0 );
1437                             }
1438                         }
1439                     }
1440                 }
1441             }
1442         }
1443     }
1444 
1445 
1446 bailout:
1447     return Py_BuildValue( "" );
1448 
1449 
1450 
1451 }
1452 
setOptions(PyObject * self,PyObject * args)1453 PyObject * setOptions( PyObject * self, PyObject * args )
1454 {
1455     if ( ppd != NULL && dest != NULL )
1456     {
1457         cupsFreeOptions( dest->num_options, dest->options );
1458         dest->num_options = g_num_options;
1459         dest->options = g_options;
1460         cupsSetDests( g_num_dests, g_dests );
1461         cupsMarkOptions( ppd, dest->num_options, dest->options );
1462     }
1463 
1464     return Py_BuildValue( "" );
1465 }
1466 
1467 // ***************************************************************************************************
1468 
printFileWithOptions(PyObject * self,PyObject * args)1469 PyObject * printFileWithOptions( PyObject * self, PyObject * args )
1470 {
1471     char * printer;
1472     char * filename;
1473     char * title;
1474     int job_id = -1;
1475     cups_dest_t * dests = NULL;
1476     cups_dest_t * dest = NULL;
1477     int num_dests = 0;
1478     int i = 0;
1479     char *requesting_user_name = NULL;
1480 
1481     if ( !PyArg_ParseTuple( args, "zzz", &printer, &filename, &title ) )
1482     {
1483         return Py_BuildValue( "" ); // None
1484     }
1485     requesting_user_name = getUserName();
1486     if(requesting_user_name)
1487     {
1488         cupsSetUser(requesting_user_name);
1489     }
1490 
1491     num_dests = cupsGetDests(&dests);
1492     dest = cupsGetDest( printer, NULL, num_dests, dests );
1493 
1494     if ( dest != NULL )
1495     {
1496         for( i = 0; i < dest->num_options; i++ )
1497         {
1498             if ( cupsGetOption( dest->options[i].name, g_num_options, g_options ) == NULL )
1499                 g_num_options = cupsAddOption( dest->options[i].name, dest->options[i].value, g_num_options, &g_options );
1500 
1501         }
1502 
1503         job_id = cupsPrintFile( dest->name, filename, title, g_num_options, g_options );
1504 
1505         return Py_BuildValue( "i", job_id );
1506     }
1507 
1508 
1509     return Py_BuildValue( "i", -1 );
1510 }
1511 
1512 // ***************************************************************************************************
1513 
1514 static PyObject * passwordFunc = NULL;
1515 static char *passwordPrompt = NULL;
1516 
password_callback(const char * prompt)1517 const char * password_callback(const char * prompt)
1518 {
1519 
1520     PyObject *result = NULL;
1521     PyObject *usernameObj = NULL;
1522     PyObject *passwordObj = NULL;
1523     char *username = NULL;
1524     char *password = NULL;
1525 
1526     if (passwordFunc != NULL)
1527     {
1528 
1529         if (passwordPrompt)
1530             prompt = passwordPrompt;
1531 
1532         result = PyObject_CallFunction(passwordFunc, "s", prompt);
1533         if (!result)
1534             return "";
1535 
1536         usernameObj = PyTuple_GetItem(result, 0);
1537         if (!usernameObj)
1538             return "";
1539         username = PYUnicode_UNICODE(usernameObj);
1540         /*      printf("usernameObj=%p, username='%s'\n", usernameObj, username); */
1541         if (!username)
1542             return "";
1543 
1544         auth_cancel_req = ('\0' == username[0])? 1 : 0 ;
1545 
1546         passwordObj = PyTuple_GetItem(result, 1);
1547         if (!passwordObj)
1548             return "";
1549         password = PYUnicode_UNICODE(passwordObj);
1550         /*      printf("passwordObj=%p, password='%s'\n", passwordObj, password); */
1551         if (!password)
1552             return "";
1553 
1554         cupsSetUser(username);
1555         return password;
1556 
1557     }
1558 
1559     return "";
1560 
1561 }
1562 
setPasswordPrompt(PyObject * self,PyObject * args)1563 PyObject *setPasswordPrompt(PyObject *self, PyObject *args)
1564 {
1565 
1566     char *userPrompt = NULL;
1567 
1568     if (!PyArg_ParseTuple(args, "z", &userPrompt))
1569         return Py_BuildValue("");
1570 
1571     if (strlen(userPrompt) != 0)
1572         passwordPrompt = userPrompt;
1573     else
1574         passwordPrompt = NULL;
1575 
1576     return Py_BuildValue("");
1577 
1578 }
1579 
setPasswordCallback(PyObject * self,PyObject * args)1580 PyObject * setPasswordCallback( PyObject * self, PyObject * args )
1581 {
1582     if( !PyArg_ParseTuple( args, "O", &passwordFunc ) )
1583     {
1584         return Py_BuildValue( "i", 0 );
1585     }
1586 
1587     cupsSetPasswordCB(password_callback);
1588 
1589     return Py_BuildValue( "i", 1 );
1590 }
1591 
1592 
getPassword(PyObject * self,PyObject * args)1593 PyObject * getPassword( PyObject * self, PyObject * args )
1594 {
1595     const char * pwd;
1596     char * prompt;
1597 
1598     if( !PyArg_ParseTuple( args, "s", &prompt ) )
1599     {
1600         return Py_BuildValue( "" );
1601     }
1602 
1603     pwd = cupsGetPassword( prompt );
1604 
1605     if( pwd )
1606     {
1607         return Py_BuildValue( "s", pwd );
1608     }
1609     else
1610     {
1611         return Py_BuildValue( "" );
1612     }
1613 }
1614 
1615 
1616 
1617 // ***************************************************************************************************
1618 
1619 static PyMethodDef cupsext_methods[] =
1620 {
1621     { "getPrinters", ( PyCFunction ) getPrinters, METH_VARARGS },
1622     { "addPrinter", ( PyCFunction ) addPrinter, METH_VARARGS },
1623     { "delPrinter", ( PyCFunction ) delPrinter, METH_VARARGS },
1624     { "getDefaultPrinter", ( PyCFunction ) getDefaultPrinter, METH_VARARGS },
1625     { "setDefaultPrinter", ( PyCFunction ) setDefaultPrinter, METH_VARARGS },
1626     { "controlPrinter", ( PyCFunction ) controlPrinter, METH_VARARGS },
1627     { "getPPDList", ( PyCFunction ) getPPDList, METH_VARARGS },
1628     { "getPPD", ( PyCFunction ) getPPD, METH_VARARGS },
1629     { "openPPD", ( PyCFunction ) openPPD, METH_VARARGS },
1630     { "closePPD", ( PyCFunction ) closePPD, METH_VARARGS },
1631     { "getPPDOption", ( PyCFunction ) getPPDOption, METH_VARARGS },
1632     { "getPPDPageSize", ( PyCFunction ) getPPDPageSize, METH_VARARGS },
1633     { "getVersion", ( PyCFunction ) getVersion, METH_VARARGS },
1634     { "getVersionTuple", ( PyCFunction ) getVersionTuple, METH_VARARGS },
1635     { "cancelJob", ( PyCFunction ) cancelJob, METH_VARARGS },
1636     { "getJobs", ( PyCFunction ) getJobs, METH_VARARGS },
1637     { "getServer", ( PyCFunction ) getServer, METH_VARARGS },
1638     { "setServer", ( PyCFunction ) setServer, METH_VARARGS },
1639     { "addOption", ( PyCFunction ) addOption, METH_VARARGS },
1640     { "removeOption", ( PyCFunction ) removeOption, METH_VARARGS },
1641     { "resetOptions", ( PyCFunction ) resetOptions, METH_VARARGS },
1642     { "printFileWithOptions", ( PyCFunction ) printFileWithOptions, METH_VARARGS },
1643     { "Job", ( PyCFunction ) newJob, METH_VARARGS | METH_KEYWORDS },
1644     { "Printer", ( PyCFunction ) newPrinter, METH_VARARGS | METH_KEYWORDS },
1645     { "getGroupList", ( PyCFunction ) getGroupList, METH_VARARGS },
1646     { "getGroup", ( PyCFunction ) getGroup, METH_VARARGS },
1647     { "getOptionList", ( PyCFunction ) getOptionList, METH_VARARGS },
1648     { "getOption", ( PyCFunction ) getOption, METH_VARARGS },
1649     { "getChoiceList", ( PyCFunction ) getChoiceList, METH_VARARGS },
1650     { "getChoice", ( PyCFunction ) getChoice, METH_VARARGS },
1651     { "setOptions", ( PyCFunction ) setOptions, METH_VARARGS },
1652     { "getOptions", ( PyCFunction ) getOptions, METH_VARARGS },
1653     { "duplicateSection", ( PyCFunction ) duplicateSection, METH_VARARGS },
1654     { "setPasswordPrompt", (PyCFunction) setPasswordPrompt, METH_VARARGS },
1655     { "setPasswordCallback", ( PyCFunction ) setPasswordCallback, METH_VARARGS },
1656     { "getPassword", ( PyCFunction ) getPassword, METH_VARARGS },
1657     { "findPPDAttribute", ( PyCFunction ) findPPDAttribute, METH_VARARGS },
1658     { "releaseCupsInstance", ( PyCFunction ) releaseCupsInstance, METH_VARARGS },
1659     { "getStatusAttributes", ( PyCFunction ) getStatusAttributes, METH_VARARGS },
1660     { NULL, NULL }
1661 };
1662 
1663 
1664 static char cupsext_documentation[] = "Python extension for CUPS 1.x";
1665 
1666 /* void initcupsext( void ) */
1667 /* { */
1668 
1669 /*     PyObject * mod = Py_InitModule4( "cupsext", cupsext_methods, */
1670 /*                                      cupsext_documentation, ( PyObject* ) NULL, */
1671 /*                                      PYTHON_API_VERSION ); */
1672 
1673 /*     if ( mod == NULL ) */
1674 /*         return ; */
1675 /* } */
1676 
1677 
MOD_INIT(cupsext)1678 MOD_INIT(cupsext)  {
1679 
1680   PyObject* mod ;
1681   MOD_DEF(mod, "cupsext", cupsext_documentation, cupsext_methods);
1682   if (mod == NULL)
1683     return MOD_ERROR_VAL;
1684 
1685   return MOD_SUCCESS_VAL(mod);
1686 
1687 }
1688 
1689