1 /*
2  * cups - Python bindings for CUPS
3  * Copyright (C) 2002-2020  Red Hat, Inc
4  * Authors: Tim Waugh <twaugh@redhat.com>
5  *          Zdenek Dohnal <zdohnal@redhat.com>
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20  */
21 
22 #include <stdarg.h>
23 #include <Python.h>
24 #include <cups/cups.h>
25 #include <cups/language.h>
26 
27 #include "cupsmodule.h"
28 
29 #include <locale.h>
30 #include <pthread.h>
31 #include <wchar.h>
32 #include <wctype.h>
33 
34 #include "cupsconnection.h"
35 #include "cupsppd.h"
36 #include "cupsipp.h"
37 
38 static pthread_key_t tls_key = -1;
39 static pthread_once_t tls_key_once = PTHREAD_ONCE_INIT;
40 
41 # define CUPS_SERVER_REMOTE_PRINTERS	"_remote_printers"
42 
43 //////////////////////
44 // Worker functions //
45 //////////////////////
46 
47 /*
48  * Thread local storage functions
49  */
50 
51 static void
destroy_TLS(void * value)52 destroy_TLS (void *value)
53 {
54   struct TLS *tls = (struct TLS *) value;
55 
56   /* CPython API needs to be run only when our process holds
57    * Python global interpret lock */
58   PyGILState_STATE gilstate;
59   gilstate = PyGILState_Ensure();
60 
61   Py_XDECREF (tls->cups_password_callback);
62 
63   Py_XDECREF (tls->cups_password_callback_context);
64 
65   // release global interpret lock
66   PyGILState_Release(gilstate);
67 
68   free (value);
69 }
70 
71 static void
init_TLS(void)72 init_TLS (void)
73 {
74   pthread_key_create (&tls_key, destroy_TLS);
75 }
76 
77 struct TLS *
get_TLS(void)78 get_TLS (void)
79 {
80   struct TLS *tls;
81   pthread_once (&tls_key_once, init_TLS);
82   tls = (struct TLS *) pthread_getspecific (tls_key);
83   if (tls == NULL)
84     {
85       tls = calloc (1, sizeof (struct TLS));
86       pthread_setspecific (tls_key, tls);
87     }
88 
89   return tls;
90 }
91 
92 static int
do_model_compare(const wchar_t * a,const wchar_t * b)93 do_model_compare (const wchar_t *a, const wchar_t *b)
94 {
95   const wchar_t *digits = L"0123456789";
96   wchar_t quick_a, quick_b;
97   while ((quick_a = *a) != L'\0' && (quick_b = *b) != L'\0') {
98     int end_a = wcsspn (a, digits);
99     int end_b = wcsspn (b, digits);
100     int min;
101     int a_is_digit = 1;
102     int cmp;
103 
104     if (quick_a != quick_b && !iswdigit (quick_a) && !iswdigit (quick_b)) {
105       if (quick_a < quick_b) return -1;
106       else return 1;
107     }
108 
109     if (!end_a) {
110       end_a = wcscspn (a, digits);
111       a_is_digit = 0;
112     }
113 
114     if (!end_b) {
115       if (a_is_digit)
116 	return -1;
117       end_b = wcscspn (b, digits);
118     } else if (!a_is_digit)
119       return 1;
120 
121     if (a_is_digit) {
122       unsigned long n_a, n_b;
123       n_a = wcstoul (a, NULL, 10);
124       n_b = wcstoul (b, NULL, 10);
125       if (n_a < n_b) cmp = -1;
126       else if (n_a == n_b) cmp = 0;
127       else cmp = 1;
128     } else {
129       min = end_a < end_b ? end_a : end_b;
130       cmp = wcsncmp (a, b, min);
131     }
132 
133     if (!cmp) {
134       if (end_a != end_b)
135 	return end_a < end_b ? -1 : 1;
136 
137       a += end_a;
138       b += end_b;
139       continue;
140     }
141 
142     return cmp;
143   }
144 
145   if (quick_a == L'\0') {
146     if (*b == L'\0')
147       return 0;
148 
149     return -1;
150   }
151 
152   return 1;
153 }
154 
155 //////////////////////////
156 // Module-level methods //
157 //////////////////////////
158 
159 static PyObject *
cups_modelSort(PyObject * self,PyObject * args)160 cups_modelSort (PyObject *self, PyObject *args)
161 {
162   PyObject *Oa, *Ob, *a, *b;
163   long unsigned int len_a, len_b;
164   size_t size_a, size_b;
165   wchar_t *wca, *wcb;
166 
167   if (!PyArg_ParseTuple (args, "OO", &Oa, &Ob))
168     return NULL;
169 
170   a = PyUnicode_FromObject (Oa);
171   b = PyUnicode_FromObject (Ob);
172   if (a == NULL || b == NULL || !PyUnicode_Check (a) || !PyUnicode_Check (b)) {
173     if (a) {
174       Py_DECREF (a);
175     }
176     if (b) {
177       Py_DECREF (b);
178     }
179 
180     PyErr_SetString (PyExc_TypeError, "Unable to convert to Unicode");
181     return NULL;
182   }
183 
184   len_a = 1 + (long unsigned)PyUnicode_GetLength (a);
185   size_a = len_a * sizeof (wchar_t);
186   if ((size_a / sizeof (wchar_t)) != len_a) {
187     Py_DECREF (a);
188     Py_DECREF (b);
189     PyErr_SetString (PyExc_RuntimeError, "String too long");
190     return NULL;
191   }
192 
193   len_b = 1 + (long unsigned)PyUnicode_GetLength (b);
194   size_b = len_b * sizeof (wchar_t);
195   if ((size_b / sizeof (wchar_t)) != len_b) {
196     Py_DECREF (a);
197     Py_DECREF (b);
198     PyErr_SetString (PyExc_RuntimeError, "String too long");
199     return NULL;
200   }
201 
202   wca = malloc (size_a);
203   wcb = malloc (size_b);
204   if (wca == NULL || wcb == NULL) {
205     Py_DECREF (a);
206     Py_DECREF (b);
207     free (wca);
208     free (wcb);
209     PyErr_SetString (PyExc_RuntimeError, "Insufficient memory");
210     return NULL;
211   }
212   PyUnicode_AsWideChar (a, wca, size_a);
213   PyUnicode_AsWideChar (b, wcb, size_b);
214   Py_DECREF (a);
215   Py_DECREF (b);
216   return Py_BuildValue ("i", do_model_compare (wca, wcb));
217 }
218 
219 static PyObject *
cups_setUser(PyObject * self,PyObject * args)220 cups_setUser (PyObject *self, PyObject *args)
221 {
222   PyObject *userobj;
223   char *user;
224 
225   if (!PyArg_ParseTuple (args, "O", &userobj))
226     return NULL;
227 
228   if (UTF8_from_PyObj (&user, userobj) == NULL)
229     return NULL;
230 
231   cupsSetUser (user);
232   free (user);
233   Py_RETURN_NONE;
234 }
235 
236 static PyObject *
cups_setServer(PyObject * self,PyObject * args)237 cups_setServer (PyObject *self, PyObject *args)
238 {
239   PyObject *serverobj;
240   char *server;
241 
242   if (!PyArg_ParseTuple (args, "O", &serverobj))
243     return NULL;
244 
245   if (UTF8_from_PyObj (&server, serverobj) == NULL)
246     return NULL;
247 
248   cupsSetServer (server);
249   free (server);
250   Py_RETURN_NONE;
251 }
252 
253 static PyObject *
cups_setPort(PyObject * self,PyObject * args)254 cups_setPort (PyObject *self, PyObject *args)
255 {
256   int port;
257 
258   if (!PyArg_ParseTuple (args, "i", &port))
259     return NULL;
260 
261   ippSetPort (port);
262   Py_RETURN_NONE;
263 }
264 
265 static PyObject *
cups_setEncryption(PyObject * self,PyObject * args)266 cups_setEncryption (PyObject *self, PyObject *args)
267 {
268   int e;
269   if (!PyArg_ParseTuple (args, "i", &e))
270     return NULL;
271 
272   cupsSetEncryption (e);
273   Py_RETURN_NONE;
274 }
275 
276 static PyObject *
cups_getUser(PyObject * self)277 cups_getUser (PyObject *self)
278 {
279   return PyUnicode_FromString (cupsUser ());
280 }
281 
282 static PyObject *
cups_getServer(PyObject * self)283 cups_getServer (PyObject *self)
284 {
285   return PyUnicode_FromString (cupsServer ());
286 }
287 
288 static PyObject *
cups_getPort(PyObject * self)289 cups_getPort (PyObject *self)
290 {
291   return Py_BuildValue ("i", ippPort ());
292 }
293 
294 static PyObject *
cups_getEncryption(PyObject * self)295 cups_getEncryption (PyObject *self)
296 {
297   return Py_BuildValue ("i", cupsEncryption ());
298 }
299 
300 static PyObject *
cups_setPasswordCB(PyObject * self,PyObject * args)301 cups_setPasswordCB (PyObject *self, PyObject *args)
302 {
303   struct TLS *tls = get_TLS ();
304   PyObject *cb;
305 
306   if (!PyArg_ParseTuple (args, "O:cups_setPasswordCB", &cb))
307     return NULL;
308 
309   if (!PyCallable_Check (cb)) {
310     PyErr_SetString (PyExc_TypeError, "Parameter must be callable");
311     return NULL;
312   }
313 
314   debugprintf ("-> cups_setPasswordCB\n");
315   Py_XDECREF (tls->cups_password_callback_context);
316   tls->cups_password_callback_context = NULL;
317 
318   Py_XINCREF (cb);
319   Py_XDECREF (tls->cups_password_callback);
320   tls->cups_password_callback = cb;
321 
322   cupsSetPasswordCB2 (password_callback_oldstyle, NULL);
323 
324   debugprintf ("<- cups_setPasswordCB\n");
325   Py_RETURN_NONE;
326 }
327 
328 static PyObject *
cups_setPasswordCB2(PyObject * self,PyObject * args)329 cups_setPasswordCB2 (PyObject *self, PyObject *args)
330 {
331   struct TLS *tls = get_TLS ();
332   PyObject *cb;
333   PyObject *cb_context = NULL;
334 
335   if (!PyArg_ParseTuple (args, "O|O", &cb, &cb_context))
336     return NULL;
337 
338   if (cb == Py_None && cb_context != NULL) {
339     PyErr_SetString (PyExc_TypeError, "Default callback takes no context");
340     return NULL;
341   }
342   else if (cb != Py_None && !PyCallable_Check (cb)) {
343     PyErr_SetString (PyExc_TypeError, "Parameter must be callable");
344     return NULL;
345   }
346 
347   debugprintf ("-> cups_setPasswordCB2\n");
348 
349   Py_XINCREF (cb_context);
350   Py_XDECREF (tls->cups_password_callback_context);
351   tls->cups_password_callback_context = cb_context;
352 
353   if (cb == Py_None)
354   {
355     Py_XDECREF (tls->cups_password_callback);
356     tls->cups_password_callback = NULL;
357     cupsSetPasswordCB2 (NULL, NULL);
358   }
359   else
360   {
361     Py_XINCREF (cb);
362     Py_XDECREF (tls->cups_password_callback);
363     tls->cups_password_callback = cb;
364     cupsSetPasswordCB2 (password_callback_newstyle, cb_context);
365   }
366 
367   debugprintf ("<- cups_setPasswordCB2\n");
368   Py_RETURN_NONE;
369 }
370 
371 static PyObject *
cups_ppdSetConformance(PyObject * self,PyObject * args)372 cups_ppdSetConformance (PyObject *self, PyObject *args)
373 {
374   int level;
375   if (!PyArg_ParseTuple (args, "i", &level))
376     return NULL;
377 
378   ppdSetConformance (level);
379   Py_RETURN_NONE;
380 }
381 
382 static PyObject *
cups_enumDests(PyObject * self,PyObject * args,PyObject * kwds)383 cups_enumDests (PyObject *self, PyObject *args, PyObject *kwds)
384 {
385   PyObject *cb;
386   int flags = 0;
387   int msec = -1;
388   int type = 0;
389   int mask = 0;
390   PyObject *user_data = NULL;
391   CallbackContext context;
392   int ret;
393   static char *kwlist[] = { "cb",
394 			    "flags",
395 			    "msec",
396 			    "type",
397 			    "mask",
398 			    "user_data",
399 			    NULL };
400 
401   if (!PyArg_ParseTupleAndKeywords (args, kwds, "O|iiiiO", kwlist,
402 				    &cb,
403 				    &flags,
404 				    &msec,
405 				    &type,
406 				    &mask,
407 				    &user_data))
408     return NULL;
409 
410   if (!PyCallable_Check (cb)) {
411     PyErr_SetString (PyExc_TypeError, "cb must be callable");
412     return NULL;
413   }
414 
415   if (!user_data)
416     user_data = Py_None;
417 
418   Py_XINCREF (cb);
419   Py_XINCREF (user_data);
420   context.cb = cb;
421   context.user_data = user_data;
422   ret = cupsEnumDests (flags,
423 		       msec,
424 		       NULL,
425 		       type,
426 		       mask,
427 		       cups_dest_cb,
428 		       &context);
429   Py_XDECREF (cb);
430   Py_XDECREF (user_data);
431 
432   if (!ret) {
433     PyErr_SetString (PyExc_RuntimeError, "cupsEnumDests failed");
434     return NULL;
435   }
436 
437   Py_RETURN_NONE;
438 }
439 
440 static PyObject *
cups_connectDest(PyObject * self,PyObject * args,PyObject * kwds)441 cups_connectDest (PyObject *self, PyObject *args, PyObject *kwds)
442 {
443   PyObject *destobj;
444   PyObject *cb;
445   int flags = 0;
446   int msec = -1;
447   PyObject *user_data = NULL;
448   CallbackContext context;
449   char resource[HTTP_MAX_URI];
450   http_t *conn;
451   Connection *connobj;
452   Dest *dest_o;
453   cups_dest_t dest;
454   PyObject *ret;
455   static char *kwlist[] = { "dest",
456 			    "cb",
457 			    "flags",
458 			    "msec",
459 			    "user_data",
460 			    NULL };
461 
462   if (!PyArg_ParseTupleAndKeywords (args, kwds, "OO|iiO", kwlist,
463 				    &destobj,
464 				    &cb,
465 				    &flags,
466 				    &msec,
467 				    &user_data))
468     return NULL;
469 
470   if (Py_TYPE(destobj) != &cups_DestType) {
471     PyErr_SetString (PyExc_TypeError, "dest must be Dest object");
472     return NULL;
473   }
474 
475   if (!PyCallable_Check (cb)) {
476     PyErr_SetString (PyExc_TypeError, "cb must be callable");
477     return NULL;
478   }
479 
480   if (!user_data)
481     user_data = Py_None;
482 
483   Py_XINCREF (cb);
484   Py_XINCREF (user_data);
485   context.cb = cb;
486   context.user_data = user_data;
487   resource[0] = '\0';
488 
489   dest_o = (Dest *) destobj;
490   dest.is_default = dest_o->is_default;
491   dest.name = dest_o->destname;
492   dest.instance = dest_o->instance;
493   dest.num_options = dest_o->num_options;
494   dest.options = malloc (dest_o->num_options * sizeof (dest.options[0]));
495   int i;
496   for (i = 0; i < dest_o->num_options; i++) {
497     dest.options[i].name = dest_o->name[i];
498     dest.options[i].value = dest_o->value[i];
499   }
500 
501   conn = cupsConnectDest (&dest,
502 			  flags,
503 			  msec,
504 			  NULL,
505 			  resource,
506 			  sizeof (resource),
507 			  cups_dest_cb,
508 			  &context);
509   Py_XDECREF (cb);
510   Py_XDECREF (user_data);
511   free (dest.options);
512 
513   if (!conn) {
514     set_ipp_error (cupsLastError (), cupsLastErrorString ());
515     return NULL;
516   }
517 
518   PyObject *largs = Py_BuildValue ("()");
519   PyObject *lkwlist = Py_BuildValue ("{}");
520   connobj = (Connection *) PyType_GenericNew (&cups_ConnectionType,
521 					      largs, lkwlist);
522   Py_DECREF (largs);
523   Py_DECREF (lkwlist);
524   connobj->host = strdup ("");
525   connobj->http = conn;
526 
527   ret = Py_BuildValue ("(Os)", (PyObject *) connobj, resource);
528   return ret;
529 }
530 
531 static PyObject *
cups_ippErrorString(PyObject * self,PyObject * args)532 cups_ippErrorString (PyObject *self, PyObject *args)
533 {
534   int op;
535 
536   if (!PyArg_ParseTuple (args, "i", &op))
537     return NULL;
538 
539   return PyUnicode_FromString (ippErrorString (op));
540 }
541 
542 static PyObject *
cups_ippOpString(PyObject * self,PyObject * args)543 cups_ippOpString (PyObject *self, PyObject *args)
544 {
545   int op;
546 
547   if (!PyArg_ParseTuple (args, "i", &op))
548     return NULL;
549 
550   return PyUnicode_FromString (ippOpString (op));
551 }
552 
553 static PyObject *
cups_require(PyObject * self,PyObject * args)554 cups_require (PyObject *self, PyObject *args)
555 {
556   const char *version = VERSION;
557   const char *required;
558   const char *pver, *preq;
559   char *end;
560   unsigned long nreq, nver;
561 
562   if (!PyArg_ParseTuple (args, "s", &required))
563     return NULL;
564 
565   pver = version;
566   preq = required;
567   nreq = strtoul (preq, &end, 0);
568   while (preq != end)
569   {
570     preq = end;
571     if (*preq == '.')
572       preq++;
573 
574     nver = strtoul (pver, &end, 0);
575     if (pver == end)
576       goto fail;
577     else {
578       pver = end;
579       if (*pver == '.')
580 	pver++;
581     }
582 
583     if (nver < nreq)
584       goto fail;
585     if (nver > nreq)
586       goto good;
587 
588     nreq = strtoul (preq, &end, 0);
589   }
590 
591 good:
592   Py_RETURN_NONE;
593 fail:
594   PyErr_SetString (PyExc_RuntimeError, "I am version " VERSION);
595   return NULL;
596 }
597 
598 struct module_state {
599     PyObject *error;
600 };
601 
602 #define GETSTATE(m) ((struct module_state*)PyModule_GetState(m))
603 
604 
605 static PyMethodDef cups_methods[] = {
606   { "modelSort", cups_modelSort, METH_VARARGS,
607     "modelSort(s1,s2) -> integer\n\n"
608     "Sort two model strings.\n\n"
609     "@type s1: string\n"
610     "@param s1: first string\n"
611     "@type s2: string\n"
612     "@param s2: second string\n"
613     "@return: strcmp-style comparison result"},
614 
615   { "setUser", cups_setUser, METH_VARARGS,
616     "setUser(user) -> None\n\n"
617     "Set user to connect as.\n\n"
618     "@type user: string\n"
619     "@param user: username"},
620 
621   { "setServer", cups_setServer, METH_VARARGS,
622     "setServer(server) -> None\n\n"
623     "Set server to connect to.\n\n"
624     "@type server: string\n"
625     "@param server: server hostname" },
626 
627   { "setPort", cups_setPort, METH_VARARGS,
628     "setPort(port) -> None\n\n"
629     "Set IPP port to connect to.\n\n"
630     "@type port: integer\n"
631     "@param port: IPP port" },
632 
633   { "setEncryption", cups_setEncryption, METH_VARARGS,
634     "setEncryption(policy) -> None\n\n"
635     "Set encryption policy.\n\n"
636     "@type policy: integer\n"
637     "@param policy: L{HTTP_ENCRYPT_ALWAYS}, L{HTTP_ENCRYPT_IF_REQUESTED}, \n"
638     "L{HTTP_ENCRYPT_NEVER}, or L{HTTP_ENCRYPT_REQUIRED}" },
639 
640   { "getUser", (PyCFunction) cups_getUser, METH_NOARGS,
641     "getUser() -> string\n\n"
642     "@return: user to connect as." },
643 
644   { "getServer", (PyCFunction) cups_getServer, METH_NOARGS,
645     "getServer() -> string\n\n"
646     "@return: server to connect to." },
647 
648   { "getPort", (PyCFunction) cups_getPort, METH_NOARGS,
649     "getPort() -> integer\n\n"
650     "@return: IPP port to connect to." },
651 
652   { "getEncryption", (PyCFunction) cups_getEncryption, METH_NOARGS,
653     "getEncryption() -> integer\n\n"
654     "Get encryption policy.\n"
655     "@see: L{setEncryption}" },
656 
657   { "setPasswordCB", cups_setPasswordCB, METH_VARARGS,
658     "setPasswordCB(fn) -> None\n\n"
659     "Set password callback function.  This Python function will be called \n"
660     "when a password is required.  It must take one string parameter \n"
661     "(the password prompt) and it must return a string (the password), or \n"
662     "None to abort the operation.\n\n"
663     "@type fn: callable object\n"
664     "@param fn: callback function" },
665 
666   { "setPasswordCB2", cups_setPasswordCB2, METH_VARARGS,
667     "setPasswordCB2(fn, context=None) -> None\n\n"
668     "Set password callback function.  This Python function will be called \n"
669     "when a password is required.  It must take parameters of type string \n"
670     "(the password prompt), instance (the cups.Connection), string (the \n"
671     "HTTP method), string (the HTTP resource) and, optionally, the user-\n"
672     "supplied context.  It must return a string (the password), or None \n"
673     "to abort the operation.\n\n"
674     "@type fn: callable object, or None for default handler\n"
675     "@param fn: callback function" },
676 
677   { "ppdSetConformance", cups_ppdSetConformance, METH_VARARGS,
678     "ppdSetConformance(level) -> None\n\n"
679     "Set PPD conformance level.\n\n"
680     "@type level: integer\n"
681     "@param level: PPD_CONFORM_RELAXED or PPD_CONFORM_STRICT" },
682 
683   { "enumDests",
684     (PyCFunction) cups_enumDests, METH_VARARGS | METH_KEYWORDS,
685     "enumDests(cb,flags=0,msec=-1,type=0,mask=0,user_data=None) -> None\n\n"
686     "@type cb: callable\n"
687     "@param cb: callback function, given user_data, dest flags, and dest.\n"
688     "Should return 1 to continue enumeration and 0 to cancel.\n"
689     "@type flags: integer\n"
690     "@param flags: enumeration flags\n"
691     "@type msec: integer\n"
692     "@param msec: timeout, or -1 for no timeout\n"
693     "@type type: integer\n"
694     "@param type: bitmask of printer types to return\n"
695     "@type mask: integer\n"
696     "@param mask: bitmask of type bits to examine\n"
697     "@type user_data: object\n"
698     "@param user_data: user data to pass to callback function\n"},
699 
700   { "connectDest",
701     (PyCFunction) cups_connectDest, METH_VARARGS | METH_KEYWORDS,
702     "connectDest(dest,cb,flags=0,msec=-1,user_data=None) -> (conn, resource)\n\n"
703     "@type dest: Dest object\n"
704     "@param dest: destination to connect to\n"
705     "@type cb: callable\n"
706     "@param cb: callback function, given user_data, dest flags, and dest.\n"
707     "Should return 1 to continue enumeration and 0 to cancel.\n"
708     "@type flags: integer\n"
709     "@param flags: enumeration flags\n"
710     "@type msec: integer\n"
711     "@param msec: timeout, or -1 for no timeout\n"
712     "@type user_data: object\n"
713     "@param user_data: user data to pass to callback function\n"
714     "@return: a 2-tuple of the Connection object and the HTTP resource.\n"},
715 
716   { "ippErrorString",
717     (PyCFunction) cups_ippErrorString, METH_VARARGS,
718     "ippErrorString(statuscode) -> name\n\n"
719     "@type statuscode: integer\n"
720     "@param statuscode: IPP Request status code\n"
721     "@return: a string describing the status code\n"},
722 
723   { "ippOpString",
724     (PyCFunction) cups_ippOpString, METH_VARARGS,
725     "ippOpString(op) -> name\n\n"
726     "@type op: integer\n"
727     "@param op: IPP Request operation\n"
728     "@return: a string representing the operation name\n"},
729 
730   { "require", cups_require, METH_VARARGS,
731     "require(version) -> None\n\n"
732     "Require pycups version.\n\n"
733     "@type version: string\n"
734     "@param version: minimum pycups version required\n"
735     "@raise RuntimeError: requirement not met" },
736 
737   { NULL, NULL, 0, NULL }
738 };
739 
cups_traverse(PyObject * m,visitproc visit,void * arg)740 static int cups_traverse(PyObject *m, visitproc visit, void *arg) {
741     Py_VISIT(GETSTATE(m)->error);
742     return 0;
743 }
744 
cups_clear(PyObject * m)745 static int cups_clear(PyObject *m) {
746     Py_CLEAR(GETSTATE(m)->error);
747     return 0;
748 }
749 
750 
751 static struct PyModuleDef moduledef = {
752         PyModuleDef_HEAD_INIT,
753         "cups",
754         NULL,
755         sizeof(struct module_state),
756         cups_methods,
757         NULL,
758         cups_traverse,
759         cups_clear,
760         NULL
761 };
762 
763 #define INITERROR return NULL
764 
765 PyObject *
PyInit_cups(void)766 PyInit_cups(void)
767 {
768     PyObject *m = PyModule_Create(&moduledef);
769 
770   if (m == NULL)
771     INITERROR;
772   struct module_state *st = GETSTATE(m);
773 
774   st->error = PyErr_NewException("cups.Error", NULL, NULL);
775   if (st->error == NULL) {
776     Py_DECREF(m);
777     INITERROR;
778   }
779 
780   PyObject *d = PyModule_GetDict (m);
781   PyObject *obj;
782 
783   // Connection type
784   cups_ConnectionType.tp_new = PyType_GenericNew;
785   if (PyType_Ready (&cups_ConnectionType) < 0)
786     INITERROR;
787 
788   PyModule_AddObject (m, "Connection",
789 		      (PyObject *)&cups_ConnectionType);
790 
791   // PPD type
792   cups_PPDType.tp_new = PyType_GenericNew;
793   if (PyType_Ready (&cups_PPDType) < 0)
794     INITERROR;
795 
796   PyModule_AddObject (m, "PPD",
797 		      (PyObject *)&cups_PPDType);
798 
799   // Option type
800   cups_OptionType.tp_new = PyType_GenericNew;
801   if (PyType_Ready (&cups_OptionType) < 0)
802     INITERROR;
803 
804   PyModule_AddObject (m, "Option",
805 		      (PyObject *)&cups_OptionType);
806 
807   // Group type
808   cups_GroupType.tp_new = PyType_GenericNew;
809   if (PyType_Ready (&cups_GroupType) < 0)
810     INITERROR;
811 
812   PyModule_AddObject (m, "Group",
813 		      (PyObject *)&cups_GroupType);
814 
815   // Constraint type
816   cups_ConstraintType.tp_new = PyType_GenericNew;
817   if (PyType_Ready (&cups_ConstraintType) < 0)
818     INITERROR;
819 
820   PyModule_AddObject (m, "Constraint",
821 		      (PyObject *)&cups_ConstraintType);
822 
823   // Attribute type
824   cups_AttributeType.tp_new = PyType_GenericNew;
825   if (PyType_Ready (&cups_AttributeType) < 0)
826     INITERROR;
827 
828   PyModule_AddObject (m, "Attribute",
829 		      (PyObject *)&cups_AttributeType);
830 
831   // Dest type
832   cups_DestType.tp_new = PyType_GenericNew;
833   if (PyType_Ready (&cups_DestType) < 0)
834     INITERROR;
835 
836   PyModule_AddObject (m, "Dest",
837 		      (PyObject *)&cups_DestType);
838 
839   // IPPRequest type
840   cups_IPPRequestType.tp_new = PyType_GenericNew;
841   if (PyType_Ready (&cups_IPPRequestType) < 0)
842       INITERROR;
843 
844   PyModule_AddObject (m, "IPPRequest",
845 		      (PyObject *)&cups_IPPRequestType);
846 
847   // IPPAttribute type
848   cups_IPPAttributeType.tp_new = PyType_GenericNew;
849   if (PyType_Ready (&cups_IPPAttributeType) < 0)
850       INITERROR;
851 
852   PyModule_AddObject (m, "IPPAttribute",
853 		      (PyObject *)&cups_IPPAttributeType);
854 
855   // Constants
856 #  define INT_CONSTANT(name)					\
857     PyDict_SetItemString (d, #name, PyLong_FromLong (name))
858 #  define INT_CONSTANT_AS(name,alias)				\
859     PyDict_SetItemString (d, alias, PyLong_FromLong (name))
860 #  define INT_CONSTANT_ALIAS(name,alias)			\
861     PyDict_SetItemString (d, #name, PyLong_FromLong (name));	\
862     PyDict_SetItemString (d, alias, PyLong_FromLong (name))
863 #define STR_CONSTANT(name)					\
864   PyDict_SetItemString (d, #name, PyUnicode_FromString (name))
865 
866 #  define INT_17_CONSTANT(newname,oldname)	\
867   INT_CONSTANT_ALIAS(newname,#oldname)
868 #  define INT_17_CONSTANT_NEWNAME(newname,oldname)	\
869   INT_CONSTANT(newname)
870 
871   // CUPS printer types
872   INT_CONSTANT (CUPS_PRINTER_LOCAL);
873   INT_CONSTANT (CUPS_PRINTER_CLASS);
874   INT_CONSTANT (CUPS_PRINTER_REMOTE);
875   INT_CONSTANT (CUPS_PRINTER_BW);
876   INT_CONSTANT (CUPS_PRINTER_COLOR);
877   INT_CONSTANT (CUPS_PRINTER_DUPLEX);
878   INT_CONSTANT (CUPS_PRINTER_STAPLE);
879   INT_CONSTANT (CUPS_PRINTER_COPIES);
880   INT_CONSTANT (CUPS_PRINTER_COLLATE);
881   INT_CONSTANT (CUPS_PRINTER_PUNCH);
882   INT_CONSTANT (CUPS_PRINTER_COVER);
883   INT_CONSTANT (CUPS_PRINTER_BIND);
884   INT_CONSTANT (CUPS_PRINTER_SORT);
885   INT_CONSTANT (CUPS_PRINTER_SMALL);
886   INT_CONSTANT (CUPS_PRINTER_MEDIUM);
887   INT_CONSTANT (CUPS_PRINTER_LARGE);
888   INT_CONSTANT (CUPS_PRINTER_VARIABLE);
889   INT_CONSTANT (CUPS_PRINTER_IMPLICIT);
890   INT_CONSTANT (CUPS_PRINTER_DEFAULT);
891   INT_CONSTANT (CUPS_PRINTER_FAX);
892   INT_CONSTANT (CUPS_PRINTER_REJECTING);
893   INT_CONSTANT (CUPS_PRINTER_DELETE);
894   INT_CONSTANT (CUPS_PRINTER_NOT_SHARED);
895   INT_CONSTANT (CUPS_PRINTER_AUTHENTICATED);
896   INT_CONSTANT (CUPS_PRINTER_COMMANDS);
897   INT_CONSTANT (CUPS_PRINTER_OPTIONS);
898   INT_CONSTANT (CUPS_PRINTER_DISCOVERED);
899 
900   // HTTP encryption
901   INT_CONSTANT (HTTP_ENCRYPT_IF_REQUESTED);
902   INT_CONSTANT (HTTP_ENCRYPT_NEVER);
903   INT_CONSTANT (HTTP_ENCRYPT_REQUIRED);
904   INT_CONSTANT (HTTP_ENCRYPT_ALWAYS);
905 
906   // Document formats
907   STR_CONSTANT (CUPS_FORMAT_AUTO);
908   STR_CONSTANT (CUPS_FORMAT_COMMAND);
909   STR_CONSTANT (CUPS_FORMAT_PDF);
910   STR_CONSTANT (CUPS_FORMAT_POSTSCRIPT);
911   STR_CONSTANT (CUPS_FORMAT_RAW);
912   STR_CONSTANT (CUPS_FORMAT_TEXT);
913 
914   // Selected HTTP status codes
915   /* Also define legacy names */
916 #  define INT_HTTP_STATUS_CONSTANT(name)		\
917   INT_CONSTANT_ALIAS(HTTP_STATUS_##name, "HTTP_"#name)
918 
919   INT_HTTP_STATUS_CONSTANT (ERROR);
920   INT_HTTP_STATUS_CONSTANT (OK);
921   INT_HTTP_STATUS_CONSTANT (NOT_MODIFIED);
922   INT_HTTP_STATUS_CONSTANT (BAD_REQUEST);
923   INT_HTTP_STATUS_CONSTANT (UNAUTHORIZED);
924   INT_HTTP_STATUS_CONSTANT (FORBIDDEN);
925   INT_HTTP_STATUS_CONSTANT (NOT_FOUND);
926   INT_HTTP_STATUS_CONSTANT (REQUEST_TIMEOUT);
927   INT_HTTP_STATUS_CONSTANT (UPGRADE_REQUIRED);
928   INT_HTTP_STATUS_CONSTANT (SERVER_ERROR);
929   INT_HTTP_STATUS_CONSTANT (NOT_IMPLEMENTED);
930   INT_HTTP_STATUS_CONSTANT (BAD_GATEWAY);
931   INT_HTTP_STATUS_CONSTANT (SERVICE_UNAVAILABLE);
932   INT_HTTP_STATUS_CONSTANT (GATEWAY_TIMEOUT);
933   INT_HTTP_STATUS_CONSTANT (NOT_SUPPORTED);
934   INT_17_CONSTANT (HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED,
935 		   HTTP_AUTHORIZATION_CANCELED);
936   INT_17_CONSTANT (HTTP_STATUS_CUPS_PKI_ERROR, HTTP_PKI_ERROR);
937 
938   // PPD UI enum
939   INT_CONSTANT (PPD_UI_BOOLEAN);
940   INT_CONSTANT (PPD_UI_PICKONE);
941   INT_CONSTANT (PPD_UI_PICKMANY);
942 
943   // PPD Order dependency enum
944   INT_CONSTANT (PPD_ORDER_ANY);
945   INT_CONSTANT (PPD_ORDER_DOCUMENT);
946   INT_CONSTANT (PPD_ORDER_EXIT);
947   INT_CONSTANT (PPD_ORDER_JCL);
948   INT_CONSTANT (PPD_ORDER_PAGE);
949   INT_CONSTANT (PPD_ORDER_PROLOG);
950 
951   // Job states
952   INT_CONSTANT (IPP_JOB_PENDING);
953   INT_CONSTANT (IPP_JOB_HELD);
954   INT_CONSTANT (IPP_JOB_PROCESSING);
955   INT_CONSTANT (IPP_JOB_STOPPED);
956   INT_CONSTANT (IPP_JOB_CANCELED);
957   INT_CONSTANT (IPP_JOB_ABORTED);
958   INT_CONSTANT (IPP_JOB_COMPLETED);
959 
960   // Printer states
961   INT_CONSTANT (IPP_PRINTER_IDLE);
962   INT_CONSTANT (IPP_PRINTER_PROCESSING);
963   INT_CONSTANT (IPP_PRINTER_STOPPED);
964 
965   // IPP resolution units
966   INT_CONSTANT (IPP_RES_PER_CM);
967   INT_CONSTANT (IPP_RES_PER_INCH);
968 
969   // IPP finishings
970   INT_CONSTANT (IPP_FINISHINGS_NONE);
971   INT_CONSTANT (IPP_FINISHINGS_STAPLE);
972   INT_CONSTANT (IPP_FINISHINGS_PUNCH);
973   INT_CONSTANT (IPP_FINISHINGS_COVER);
974   INT_CONSTANT (IPP_FINISHINGS_BIND);
975   INT_CONSTANT (IPP_FINISHINGS_SADDLE_STITCH);
976   INT_CONSTANT (IPP_FINISHINGS_EDGE_STITCH);
977   INT_CONSTANT (IPP_FINISHINGS_FOLD);
978   INT_CONSTANT (IPP_FINISHINGS_TRIM);
979   INT_CONSTANT (IPP_FINISHINGS_BALE);
980   INT_CONSTANT (IPP_FINISHINGS_BOOKLET_MAKER);
981   INT_CONSTANT (IPP_FINISHINGS_JOB_OFFSET);
982   INT_CONSTANT (IPP_FINISHINGS_STAPLE_TOP_LEFT);
983   INT_CONSTANT (IPP_FINISHINGS_STAPLE_BOTTOM_LEFT);
984   INT_CONSTANT (IPP_FINISHINGS_STAPLE_TOP_RIGHT);
985   INT_CONSTANT (IPP_FINISHINGS_STAPLE_BOTTOM_RIGHT);
986   INT_CONSTANT (IPP_FINISHINGS_EDGE_STITCH_LEFT);
987   INT_CONSTANT (IPP_FINISHINGS_EDGE_STITCH_TOP);
988   INT_CONSTANT (IPP_FINISHINGS_EDGE_STITCH_RIGHT);
989   INT_CONSTANT (IPP_FINISHINGS_EDGE_STITCH_BOTTOM);
990   INT_CONSTANT (IPP_FINISHINGS_STAPLE_DUAL_LEFT);
991   INT_CONSTANT (IPP_FINISHINGS_STAPLE_DUAL_TOP);
992   INT_CONSTANT (IPP_FINISHINGS_STAPLE_DUAL_RIGHT);
993   INT_CONSTANT (IPP_FINISHINGS_STAPLE_DUAL_BOTTOM);
994   INT_CONSTANT (IPP_FINISHINGS_BIND_LEFT);
995   INT_CONSTANT (IPP_FINISHINGS_BIND_TOP);
996   INT_CONSTANT (IPP_FINISHINGS_BIND_RIGHT);
997   INT_CONSTANT (IPP_FINISHINGS_BIND_BOTTOM);
998 
999   // IPP orientations
1000   /* Also define legacy names */
1001 #  define INT_IPP_ORIENT_CONSTANT(name)	\
1002   INT_CONSTANT_ALIAS(IPP_ORIENT_##name, "IPP_"#name)
1003 
1004   INT_IPP_ORIENT_CONSTANT (PORTRAIT);
1005   INT_IPP_ORIENT_CONSTANT (LANDSCAPE);
1006   INT_IPP_ORIENT_CONSTANT (REVERSE_PORTRAIT);
1007   INT_IPP_ORIENT_CONSTANT (REVERSE_LANDSCAPE);
1008 
1009   // IPP qualities
1010   INT_CONSTANT (IPP_QUALITY_DRAFT);
1011   INT_CONSTANT (IPP_QUALITY_NORMAL);
1012   INT_CONSTANT (IPP_QUALITY_HIGH);
1013 
1014   // IPP errors
1015   /* Also define legacy names */
1016 #  define INT_IPP_STATUS_ERROR_CONSTANT(name)	\
1017   INT_CONSTANT_ALIAS(IPP_STATUS_ERROR_##name, "IPP_"#name)
1018 #  define INT_IPP_STATUS_OK_CONSTANT(name)	\
1019   INT_CONSTANT_ALIAS(IPP_STATUS_##name, "IPP_"#name)
1020 
1021   INT_IPP_STATUS_OK_CONSTANT (OK);
1022   INT_17_CONSTANT (IPP_STATUS_OK_IGNORED_OR_SUBSTITUTED, IPP_OK_SUBST);
1023   INT_17_CONSTANT (IPP_STATUS_OK_CONFLICTING, IPP_OK_CONFLICT);
1024   INT_IPP_STATUS_OK_CONSTANT (OK_IGNORED_SUBSCRIPTIONS);
1025   INT_IPP_STATUS_OK_CONSTANT (OK_IGNORED_NOTIFICATIONS);
1026   INT_IPP_STATUS_OK_CONSTANT (OK_TOO_MANY_EVENTS);
1027   INT_IPP_STATUS_OK_CONSTANT (OK_BUT_CANCEL_SUBSCRIPTION);
1028   INT_IPP_STATUS_OK_CONSTANT (OK_EVENTS_COMPLETE);
1029   INT_17_CONSTANT (IPP_STATUS_REDIRECTION_OTHER_SITE,
1030 		   IPP_REDIRECTION_OTHER_SITE);
1031   INT_IPP_STATUS_ERROR_CONSTANT (BAD_REQUEST);
1032   INT_IPP_STATUS_ERROR_CONSTANT (FORBIDDEN);
1033   INT_IPP_STATUS_ERROR_CONSTANT (NOT_AUTHENTICATED);
1034   INT_IPP_STATUS_ERROR_CONSTANT (NOT_AUTHORIZED);
1035   INT_IPP_STATUS_ERROR_CONSTANT (NOT_POSSIBLE);
1036   INT_IPP_STATUS_ERROR_CONSTANT (TIMEOUT);
1037   INT_IPP_STATUS_ERROR_CONSTANT (NOT_FOUND);
1038   INT_IPP_STATUS_ERROR_CONSTANT (GONE);
1039   INT_IPP_STATUS_ERROR_CONSTANT (REQUEST_ENTITY);
1040   INT_IPP_STATUS_ERROR_CONSTANT (REQUEST_VALUE);
1041   INT_17_CONSTANT (IPP_STATUS_ERROR_DOCUMENT_FORMAT_NOT_SUPPORTED,
1042 		   IPP_DOCUMENT_FORMAT);
1043   INT_17_CONSTANT (IPP_STATUS_ERROR_ATTRIBUTES_OR_VALUES, IPP_ATTRIBUTES);
1044   INT_IPP_STATUS_ERROR_CONSTANT (URI_SCHEME);
1045   INT_IPP_STATUS_ERROR_CONSTANT (CHARSET);
1046   INT_17_CONSTANT (IPP_STATUS_ERROR_CONFLICTING, IPP_CONFLICT);
1047   INT_IPP_STATUS_ERROR_CONSTANT (COMPRESSION_NOT_SUPPORTED);
1048   INT_IPP_STATUS_ERROR_CONSTANT (COMPRESSION_ERROR);
1049   INT_IPP_STATUS_ERROR_CONSTANT (DOCUMENT_FORMAT_ERROR);
1050   INT_17_CONSTANT (IPP_STATUS_ERROR_DOCUMENT_ACCESS, IPP_DOCUMENT_ACCESS_ERROR);
1051   INT_IPP_STATUS_ERROR_CONSTANT (ATTRIBUTES_NOT_SETTABLE);
1052   INT_IPP_STATUS_ERROR_CONSTANT (IGNORED_ALL_SUBSCRIPTIONS);
1053   INT_IPP_STATUS_ERROR_CONSTANT (TOO_MANY_SUBSCRIPTIONS);
1054   INT_IPP_STATUS_ERROR_CONSTANT (IGNORED_ALL_NOTIFICATIONS);
1055   INT_IPP_STATUS_ERROR_CONSTANT (PRINT_SUPPORT_FILE_NOT_FOUND);
1056   INT_17_CONSTANT (IPP_STATUS_ERROR_INTERNAL, IPP_INTERNAL_ERROR);
1057   INT_IPP_STATUS_ERROR_CONSTANT (OPERATION_NOT_SUPPORTED);
1058   INT_IPP_STATUS_ERROR_CONSTANT (SERVICE_UNAVAILABLE);
1059   INT_IPP_STATUS_ERROR_CONSTANT (VERSION_NOT_SUPPORTED);
1060   INT_17_CONSTANT (IPP_STATUS_ERROR_DEVICE, IPP_DEVICE_ERROR);
1061   INT_17_CONSTANT (IPP_STATUS_ERROR_TEMPORARY, IPP_TEMPORARY_ERROR);
1062   INT_17_CONSTANT (IPP_STATUS_ERROR_NOT_ACCEPTING_JOBS, IPP_NOT_ACCEPTING);
1063   INT_17_CONSTANT (IPP_STATUS_ERROR_BUSY, IPP_PRINTER_BUSY);
1064   INT_17_CONSTANT (IPP_STATUS_ERROR_JOB_CANCELED, IPP_ERROR_JOB_CANCELED);
1065   INT_IPP_STATUS_ERROR_CONSTANT (MULTIPLE_JOBS_NOT_SUPPORTED);
1066   INT_IPP_STATUS_ERROR_CONSTANT (PRINTER_IS_DEACTIVATED);
1067   INT_17_CONSTANT (IPP_STATUS_ERROR_CUPS_AUTHENTICATION_CANCELED,
1068 		   IPP_AUTHENTICATION_CANCELED);
1069   INT_17_CONSTANT (IPP_STATUS_ERROR_CUPS_PKI, IPP_PKI_ERROR);
1070   INT_17_CONSTANT (IPP_STATUS_ERROR_CUPS_UPGRADE_REQUIRED,
1071 		   IPP_UPGRADE_REQUIRED);
1072 
1073   // IPP states
1074   /* Also define legacy names */
1075 #  define INT_IPP_STATE_CONSTANT(name)	\
1076   INT_CONSTANT_ALIAS(IPP_STATE_##name, "IPP_"#name)
1077 
1078   INT_IPP_STATE_CONSTANT (ERROR);
1079   INT_IPP_STATE_CONSTANT (IDLE);
1080   INT_IPP_STATE_CONSTANT (HEADER);
1081   INT_IPP_STATE_CONSTANT (ATTRIBUTE);
1082   INT_IPP_STATE_CONSTANT (DATA);
1083 
1084   // IPP attribute tags
1085   INT_CONSTANT (IPP_TAG_ZERO);
1086   INT_CONSTANT (IPP_TAG_OPERATION);
1087   INT_CONSTANT (IPP_TAG_JOB);
1088   INT_CONSTANT (IPP_TAG_PRINTER);
1089   INT_CONSTANT (IPP_TAG_INTEGER);
1090   INT_CONSTANT (IPP_TAG_BOOLEAN);
1091   INT_CONSTANT (IPP_TAG_ENUM);
1092   INT_CONSTANT (IPP_TAG_STRING);
1093   INT_CONSTANT (IPP_TAG_RANGE);
1094   INT_CONSTANT (IPP_TAG_TEXT);
1095   INT_CONSTANT (IPP_TAG_NAME);
1096   INT_CONSTANT (IPP_TAG_KEYWORD);
1097   INT_CONSTANT (IPP_TAG_URI);
1098   INT_CONSTANT (IPP_TAG_CHARSET);
1099   INT_CONSTANT (IPP_TAG_LANGUAGE);
1100   INT_CONSTANT (IPP_TAG_MIMETYPE);
1101 
1102   // IPP operations
1103 #  define INT_IPP_OP_CONSTANT(name)		\
1104   INT_CONSTANT(IPP_OP_##name)
1105 
1106   INT_IPP_OP_CONSTANT (PRINT_JOB);
1107   INT_IPP_OP_CONSTANT (PRINT_URI);
1108   INT_IPP_OP_CONSTANT (VALIDATE_JOB);
1109   INT_IPP_OP_CONSTANT (CREATE_JOB);
1110   INT_IPP_OP_CONSTANT (SEND_DOCUMENT);
1111   INT_IPP_OP_CONSTANT (SEND_URI);
1112   INT_IPP_OP_CONSTANT (CANCEL_JOB);
1113   INT_IPP_OP_CONSTANT (GET_JOB_ATTRIBUTES);
1114   INT_IPP_OP_CONSTANT (GET_JOBS);
1115   INT_IPP_OP_CONSTANT (GET_PRINTER_ATTRIBUTES);
1116   INT_IPP_OP_CONSTANT (HOLD_JOB);
1117   INT_IPP_OP_CONSTANT (RELEASE_JOB);
1118   INT_IPP_OP_CONSTANT (RESTART_JOB);
1119   INT_IPP_OP_CONSTANT (PAUSE_PRINTER);
1120   INT_IPP_OP_CONSTANT (RESUME_PRINTER);
1121   INT_IPP_OP_CONSTANT (PURGE_JOBS);
1122   INT_IPP_OP_CONSTANT (SET_PRINTER_ATTRIBUTES);
1123   INT_IPP_OP_CONSTANT (SET_JOB_ATTRIBUTES);
1124   INT_IPP_OP_CONSTANT (GET_PRINTER_SUPPORTED_VALUES);
1125   INT_17_CONSTANT (IPP_OP_CREATE_PRINTER_SUBSCRIPTIONS,
1126 		   IPP_CREATE_PRINTER_SUBSCRIPTION);
1127   INT_17_CONSTANT (IPP_OP_CREATE_JOB_SUBSCRIPTIONS,
1128 		   IPP_CREATE_JOB_SUBSCRIPTION);
1129   INT_IPP_OP_CONSTANT (GET_SUBSCRIPTIONS);
1130   INT_IPP_OP_CONSTANT (RENEW_SUBSCRIPTION);
1131   INT_IPP_OP_CONSTANT (CANCEL_SUBSCRIPTION);
1132   INT_IPP_OP_CONSTANT (GET_NOTIFICATIONS);
1133   INT_IPP_OP_CONSTANT (SEND_NOTIFICATIONS);
1134   INT_IPP_OP_CONSTANT (GET_RESOURCE_ATTRIBUTES);
1135   INT_IPP_OP_CONSTANT (GET_RESOURCE_DATA);
1136   INT_IPP_OP_CONSTANT (GET_RESOURCES);
1137   INT_IPP_OP_CONSTANT (GET_PRINT_SUPPORT_FILES);
1138   INT_IPP_OP_CONSTANT (ENABLE_PRINTER);
1139   INT_IPP_OP_CONSTANT (DISABLE_PRINTER);
1140   INT_IPP_OP_CONSTANT (PAUSE_PRINTER_AFTER_CURRENT_JOB);
1141   INT_IPP_OP_CONSTANT (HOLD_NEW_JOBS);
1142   INT_IPP_OP_CONSTANT (RELEASE_HELD_NEW_JOBS);
1143   INT_IPP_OP_CONSTANT (DEACTIVATE_PRINTER);
1144   INT_IPP_OP_CONSTANT (ACTIVATE_PRINTER);
1145   INT_IPP_OP_CONSTANT (RESTART_PRINTER);
1146   INT_IPP_OP_CONSTANT (SHUTDOWN_PRINTER);
1147   INT_IPP_OP_CONSTANT (STARTUP_PRINTER);
1148   INT_IPP_OP_CONSTANT (REPROCESS_JOB);
1149   INT_IPP_OP_CONSTANT (CANCEL_CURRENT_JOB);
1150   INT_IPP_OP_CONSTANT (SUSPEND_CURRENT_JOB);
1151   INT_IPP_OP_CONSTANT (RESUME_JOB);
1152   INT_IPP_OP_CONSTANT (PROMOTE_JOB);
1153   INT_IPP_OP_CONSTANT (SCHEDULE_JOB_AFTER);
1154   INT_IPP_OP_CONSTANT (CANCEL_JOBS);
1155   INT_IPP_OP_CONSTANT (CANCEL_MY_JOBS);
1156   INT_IPP_OP_CONSTANT (RESUBMIT_JOB);
1157   INT_IPP_OP_CONSTANT (CLOSE_JOB);
1158   INT_IPP_OP_CONSTANT (IDENTIFY_PRINTER);
1159   INT_IPP_OP_CONSTANT (VALIDATE_DOCUMENT);
1160   INT_IPP_OP_CONSTANT (SEND_HARDCOPY_DOCUMENT);
1161   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_GET_DEFAULT, CUPS_GET_DEFAULT);
1162   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_GET_PRINTERS, CUPS_GET_PRINTERS);
1163   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_ADD_MODIFY_PRINTER,
1164 			   CUPS_ADD_MODIFY_PRINTER);
1165   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_DELETE_PRINTER, CUPS_DELETE_PRINTER);
1166   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_GET_CLASSES, CUPS_GET_CLASSES);
1167   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_ADD_MODIFY_CLASS, CUPS_ADD_MODIFY_CLASS);
1168   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_DELETE_CLASS, CUPS_DELETE_CLASS);
1169   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_ACCEPT_JOBS, CUPS_ACCEPT_JOBS);
1170   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_REJECT_JOBS, CUPS_REJECT_JOBS);
1171   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_SET_DEFAULT, CUPS_SET_DEFAULT);
1172   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_GET_PPDS, CUPS_GET_PPDS);
1173   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_MOVE_JOB, CUPS_MOVE_JOB);
1174   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_AUTHENTICATE_JOB, CUPS_AUTHENTICATE_JOB);
1175   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_GET_PPD, CUPS_GET_PPD);
1176   INT_17_CONSTANT_NEWNAME (IPP_OP_CUPS_GET_DOCUMENT, CUPS_GET_DOCUMENT);
1177 
1178   // Limits
1179   INT_CONSTANT (IPP_MAX_NAME);
1180 
1181   // PPD conformance levels
1182   INT_CONSTANT (PPD_CONFORM_RELAXED);
1183   INT_CONSTANT (PPD_CONFORM_STRICT);
1184 
1185   // Admin Util constants
1186   STR_CONSTANT (CUPS_SERVER_DEBUG_LOGGING);
1187   STR_CONSTANT (CUPS_SERVER_REMOTE_ADMIN);
1188   STR_CONSTANT (CUPS_SERVER_REMOTE_PRINTERS);
1189   STR_CONSTANT (CUPS_SERVER_SHARE_PRINTERS);
1190   STR_CONSTANT (CUPS_SERVER_USER_CANCEL_ANY);
1191   STR_CONSTANT (CUPS_SERVER_REMOTE_ANY);
1192 
1193   // Dest enumeration flags
1194   INT_CONSTANT (CUPS_DEST_FLAGS_NONE);
1195   INT_CONSTANT (CUPS_DEST_FLAGS_UNCONNECTED);
1196   INT_CONSTANT (CUPS_DEST_FLAGS_MORE);
1197   INT_CONSTANT (CUPS_DEST_FLAGS_REMOVED);
1198   INT_CONSTANT (CUPS_DEST_FLAGS_ERROR);
1199   INT_CONSTANT (CUPS_DEST_FLAGS_RESOLVING);
1200   INT_CONSTANT (CUPS_DEST_FLAGS_CONNECTING);
1201   INT_CONSTANT (CUPS_DEST_FLAGS_CANCELED);
1202 
1203   // Exceptions
1204   obj = PyDict_New ();
1205   PyDict_SetItemString (obj, "__doc__", PyUnicode_FromString(
1206     "This exception is raised when an HTTP problem has occurred.  It \n"
1207     "provides an integer HTTP status code.\n\n"
1208     "Use it like this::\n"
1209     "  try:\n"
1210     "    ...\n"
1211     "  except cups.HTTPError as (status):\n"
1212     "    print 'HTTP status is %d' % status\n"));
1213   HTTPError = PyErr_NewException ("cups.HTTPError", NULL, obj);
1214   Py_DECREF (obj);
1215   if (HTTPError == NULL)
1216     INITERROR;
1217   Py_INCREF (HTTPError);
1218   PyModule_AddObject (m, "HTTPError", HTTPError);
1219 
1220   obj = PyDict_New ();
1221   PyDict_SetItemString (obj, "__doc__", PyUnicode_FromString(
1222     "This exception is raised when an IPP error has occurred.  It \n"
1223     "provides an integer IPP status code, and a human-readable string \n"
1224     "describing the error.\n\n"
1225     "Use it like this::\n"
1226     "  try:\n"
1227     "    ...\n"
1228     "  except cups.IPPError as (status, description):\n"
1229     "    print 'IPP status is %d' % status\n"
1230     "    print 'Meaning:', description\n"));
1231   IPPError = PyErr_NewException ("cups.IPPError", NULL, obj);
1232   Py_DECREF (obj);
1233   if (IPPError == NULL)
1234     INITERROR;
1235   Py_INCREF (IPPError);
1236   PyModule_AddObject (m, "IPPError", IPPError);
1237 
1238     return m;
1239 }
1240 
1241 ///////////////
1242 // Debugging //
1243 ///////////////
1244 
1245 #define ENVAR "PYCUPS_DEBUG"
1246 static int debugging_enabled = -1;
1247 
1248 void
debugprintf(const char * fmt,...)1249 debugprintf (const char *fmt, ...)
1250 {
1251   if (!debugging_enabled)
1252     return;
1253 
1254   if (debugging_enabled == -1)
1255     {
1256       if (!getenv (ENVAR))
1257 	{
1258 	  debugging_enabled = 0;
1259 	  return;
1260 	}
1261 
1262       debugging_enabled = 1;
1263     }
1264 
1265   {
1266     va_list ap;
1267     va_start (ap, fmt);
1268     vfprintf (stderr, fmt, ap);
1269     va_end (ap);
1270   }
1271 }
1272