1 #include "EXTERN.h"
2 #include "perl.h"
3 #include "XSUB.h"
4
5 #include "ppport.h"
6
7 #include <cups/cups.h>
8 #if (CUPS_VERSION_MAJOR > 1) || (CUPS_VERSION_MINOR > 5)
9 #define HAVE_CUPS_1_6 1
10 #endif
11
12 /*#include <cups/backend.h>*/
13 #include <cups/http.h>
14 #ifdef HAVE_CUPS_1_6
15 #include <cupsfilters/image.h>
16 #else
17 #include <cups/image.h>
18 #endif
19 #include <cups/ipp.h>
20 #include <cups/ppd.h>
21 #include <cups/file.h>
22 #include <cups/dir.h>
23 #include <cups/language.h>
24 #include <cups/transcode.h>
25 #include <cups/adminutil.h>
26
27 #include "const-c.inc"
28 #include "packer.c"
29
30 #ifndef HAVE_CUPS_1_6
31 #define ippGetGroupTag(attr) attr->group_tag
32 #define ippGetName(attr) attr->name
33 #define ippGetCount(attr) attr->num_values
34 #define ippGetValueTag(attr) attr->value_tag
35 #define ippGetInteger(attr, element) attr->values[element].integer
36 #define ippGetBoolean(attr, element) attr->values[element].boolean
37 #define ippGetString(attr, element, language) attr->values[element].string.text
38 #define ippGetStatusCode(ipp) ipp->request.status.status_code
39 #define ippFirstAttribute(ipp) ipp->current = ipp->attrs
40 #define ippNextAttribute(ipp) ipp->current = ipp->current->next
41 #endif
42
43 static SV *password_cb = (SV*) NULL;
44
45 const char *
password_cb_wrapper(const char * prompt)46 password_cb_wrapper(const char *prompt)
47 {
48 /* This variable will show up as unused on certain platforms. */
49 STRLEN n_a;
50 static char password[255] = { '\0' };
51
52 if (! password_cb)
53 return NULL;
54
55 dSP;
56 ENTER;
57 SAVETMPS;
58 PUSHMARK(SP);
59 XPUSHs(sv_2mortal(newSVpv(prompt, 0)));
60 PUTBACK;
61 call_sv(password_cb, G_SCALAR);
62 SPAGAIN;
63 strncpy(password, POPpx, 254);
64
65 PUTBACK;
66 FREETMPS;
67 LEAVE;
68
69 return password;
70 }
71
cupsCloneDest(cups_dest_t * src)72 cups_dest_t* cupsCloneDest(cups_dest_t* src) {
73 int i;
74 cups_dest_t *dst = malloc(sizeof(cups_dest_t));
75 memcpy(dst, src, sizeof(cups_dest_t));
76 if(src->name != NULL)
77 dst->name = strdup(src->name);
78 if(src->instance != NULL)
79 dst->instance = strdup(src->instance);
80 dst->options = malloc(src->num_options * sizeof(cups_option_t));
81 for(i = 0; i < src->num_options; i++) {
82 memcpy(&dst->options[i], &src->options[i], sizeof(cups_option_t));
83 if(src->options[i].name != NULL)
84 dst->options[i].name = strdup(src->options[i].name);
85 if(src->options[i].value != NULL)
86 dst->options[i].value = strdup(src->options[i].value);
87 }
88 return(dst);
89 }
90
91 MODULE = Net::CUPS PACKAGE = Net::CUPS
92
93 PROTOTYPES: DISABLE
94
95 INCLUDE: const-xs.inc
96
97 const char*
98 NETCUPS_getServer()
99 CODE:
100 RETVAL = cupsServer();
101 OUTPUT:
102 RETVAL
103
104 const char*
105 NETCUPS_getUsername()
106 CODE:
107 RETVAL = cupsUser();
108 OUTPUT:
109 RETVAL
110
111 void
112 NETCUPS_setServer( name )
113 const char* name;
114 CODE:
115 cupsSetServer( name );
116
117 void
118 NETCUPS_setUsername( username )
119 const char* username;
120 CODE:
121 cupsSetUser( username );
122
123 void
NETCUPS_setPasswordCB(callback)124 NETCUPS_setPasswordCB( callback )
125 SV* callback;
126 CODE:
127 if( password_cb == (SV*) NULL )
128 {
129 password_cb = newSVsv( callback );
130 cupsSetPasswordCB( password_cb_wrapper );
131 }
132 else
133 {
134 SvSetSV( password_cb, callback );
135 }
136
137 const char*
138 NETCUPS_getPassword( prompt )
139 const char* prompt;
140 CODE:
141 RETVAL = cupsGetPassword( prompt );
142 OUTPUT:
143 RETVAL
144
145 void
146 NETCUPS_getDestination( name )
147 char* name;
148 PPCODE:
149 cups_dest_t * destinations = NULL;
150 cups_dest_t * destination = NULL;
151 int count = 0;
152 SV* rv = NULL;
153 count = cupsGetDests( &destinations );
154 /* If we have a NULL for destination name, then we are going
155 to assume we want the default. */
156 if( !strlen( name ) )
157 {
158 name = cupsGetDefault();
159 }
160 destination = cupsGetDest( name, NULL, count, destinations );
161 rv = sv_newmortal();
162 sv_setref_pv( rv, "Net::CUPS::Destination", destination );
163 XPUSHs( rv );
164 XSRETURN( 1 );
165
166 void
167 NETCUPS_getDestinations()
168 PPCODE:
169 cups_dest_t * destinations = NULL;
170 int count = 0;
171 int loop = 0;
172 SV* rv = NULL;
173 count = cupsGetDests( &destinations );
174 for( loop = 0; loop < count; loop++ )
175 {
176 rv = sv_newmortal();
177 /* FIXME cloning is probably not the best way to go at this.
178 It's at best a band aid for incorrect memory management
179 throughout this code base. Also there's a cupsCopyDest
180 function that seems to be doing the same as cupsCloneDest. */
181 cups_dest_t *single = cupsCloneDest( &destinations[loop] );
182 sv_setref_pv( rv, "Net::CUPS::Destination", single );
183 XPUSHs( rv );
184 }
185 cupsFreeDests(count, destinations);
186 XSRETURN( count );
187
188 ppd_file_t*
189 NETCUPS_getPPD( name )
190 const char* name;
191 INIT:
192 const char* filename = NULL;
193 CODE:
194 filename = cupsGetPPD( name );
195 RETVAL = ppdOpenFile( filename );
196 OUTPUT:
197 RETVAL
198
199 void
200 NETCUPS_requestData( request, resource, filename )
201 ipp_t* request;
202 const char* resource;
203 const char* filename;
204 PPCODE:
205 http_t* http = NULL;
206 ipp_t* response = NULL;
207 const char* server = NULL;
208 SV* rv = NULL;
209 int port;
210 server = cupsServer();
211 port = ippPort();
212 httpInitialize();
213 http = httpConnect( server, port );
214 if( strlen( filename ) == 0 )
215 filename = NULL;
216 response = cupsDoFileRequest( http, request, resource, filename );
217 rv = sv_newmortal();
218 sv_setref_pv( rv, "Net::CUPS::IPP", response );
219 XPUSHs( rv );
220 httpClose( http );
221 XSRETURN( 1 );
222
223 void
224 NETCUPS_getPPDMakes()
225 http_t *http; /* HTTP object */
226 ipp_t *request; /* IPP request object */
227 ipp_t *response; /* IPP response object */
228 ipp_attribute_t *attr; /* Current IPP attribute */
229
230 PPCODE:
231 SV* rv = NULL;
232 int count = 0;
233 cups_lang_t *language;
234 language = cupsLangDefault();
235 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
236 request = ippNewRequest(CUPS_GET_PPDS);
237 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
238 "attributes-charset", NULL, "utf-8");
239 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
240 "attributes-natural-language", NULL, language->language);
241 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
242 "requested-attributes", NULL, "ppd-make");
243
244 response = cupsDoRequest(http, request, "/");
245
246 if (response != NULL) {
247 attr = ippFindAttribute(response, "ppd-make", IPP_TAG_TEXT);
248 rv = sv_newmortal();
249 sv_setpv(rv, ippGetString(attr, 0, NULL));
250 XPUSHs(rv);
251 count++;
252
253 while (attr != NULL) {
254 attr = ippFindNextAttribute(response, "ppd-make", IPP_TAG_TEXT);
255 if (attr == NULL) {
256 break;
257 }
258
259 rv = sv_newmortal();
260 sv_setpv(rv, ippGetString(attr, 0, NULL));
261 XPUSHs(rv);
262 count++;
263 }
264
265 ippDelete(response);
266 httpClose(http);
267 }
268 else {
269 XSRETURN ( 0 );
270 }
271 XSRETURN( count );
272
273
274 void
275 NETCUPS_getAllPPDs ()
276 http_t *http; /* HTTP object */
277 ipp_t *request; /* IPP request object */
278 ipp_t *response; /* IPP response object */
279 ipp_attribute_t *attr; /* Current IPP attribute */
280
281 PPCODE:
282 SV* rv = NULL;
283 int count = 0;
284 cups_lang_t *language;
285 language = cupsLangDefault();
286 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
287 request = ippNewRequest(CUPS_GET_PPDS);
288 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
289 "attributes-charset", NULL, "utf-8");
290 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
291 "attributes-natural-language", NULL, language->language);
292 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_KEYWORD,
293 "requested-attributes", NULL, "ppd-make-and-model");
294 response = cupsDoRequest(http, request, "/");
295
296 if (response != NULL) {
297 attr = ippFindAttribute(response,
298 "ppd-make-and-model",
299 IPP_TAG_TEXT);
300 rv = sv_newmortal();
301 sv_setpv(rv, ippGetString(attr, 0, NULL));
302 XPUSHs(rv);
303 count++;
304 while (attr != NULL) {
305 attr = ippFindNextAttribute(response,
306 "ppd-make-and-model",
307 IPP_TAG_TEXT);
308 if (attr == NULL) {
309 break;
310 }
311 rv = sv_newmortal();
312 sv_setpv(rv, ippGetString(attr, 0, NULL));
313 XPUSHs(rv);
314 count++;
315 }
316
317 ippDelete(response);
318 httpClose(http);
319 }
320 else {
321 XSRETURN ( 0 );
322 }
323 XSRETURN( count );
324
325 void
326 NETCUPS_deleteDestination( destination );
327 const char* destination;
328
329 PPCODE:
330 ipp_t *request;
331 http_t *http;
332 char uri[HTTP_MAX_URI];
333
334 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
335 cupsServer(), 0, "/printers/%s", destination);
336 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
337 request = ippNewRequest(CUPS_DELETE_PRINTER);
338 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
339 NULL, uri);
340 ippDelete(cupsDoRequest(http, request, "/admin/"));
341
342 void
343 NETCUPS_addDestination(name, location, printer_info, ppd_name, device_uri);
344 const char* name;
345 const char* location;
346 const char* printer_info;
347 const char* ppd_name;
348 const char* device_uri;
349
350 PPCODE:
351 http_t *http = NULL; /* HTTP object */
352 ipp_t *request = NULL; /* IPP request object */
353 char uri[HTTP_MAX_URI]; /* Job URI */
354
355 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
356
357 request = ippNewRequest(CUPS_ADD_PRINTER);
358
359 httpAssembleURIf(HTTP_URI_CODING_ALL, uri, sizeof(uri), "ipp", NULL,
360 cupsServer(), 0, "/printers/%s", name);
361 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri",
362 NULL, uri);
363 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-location",
364 NULL, location);
365 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_TEXT, "printer-info",
366 NULL, printer_info );
367 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_NAME, "ppd-name",
368 NULL, ppd_name);
369 strncpy(uri, device_uri, sizeof(uri));
370 ippAddString(request, IPP_TAG_PRINTER, IPP_TAG_URI, "device-uri",
371 NULL, uri);
372 ippAddBoolean(request, IPP_TAG_PRINTER, "printer-is-accepting-jobs", 1);
373 ippAddInteger(request, IPP_TAG_PRINTER, IPP_TAG_ENUM, "printer-state",
374 IPP_PRINTER_IDLE);
375 ippDelete(cupsDoRequest(http, request, "/admin/"));
376
377 void
378 NETCUPS_getPPDFileName(ppdfilename);
379 const char* ppdfilename;
380
381 PPCODE:
382 http_t *http; /* HTTP object */
383 ipp_t *request; /* IPP request object */
384 ipp_t *response; /* IPP response object */
385 ipp_attribute_t *attr; /* Current IPP attribute */
386 int i = 0;
387 char* tmpppd;
388 char test[1024];
389 SV* rv = NULL;
390
391 http = httpConnectEncrypt(cupsServer(), ippPort(), cupsEncryption());
392
393 request = ippNewRequest(CUPS_GET_PPDS);
394
395 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_CHARSET,
396 "attributes-charset", NULL, "utf-8");
397 ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE,
398 "attributes-natural-language", NULL, "en");
399
400 response = cupsDoRequest(http, request, "/");
401
402 if (response != NULL) {
403 attr = ippFindAttribute(response, "ppd-name", IPP_TAG_NAME );
404 while ((attr != NULL) && (i < 1)) {
405 tmpppd = ippGetString(attr, 0, NULL);
406 attr = ippFindNextAttribute(response,
407 "ppd-make",
408 IPP_TAG_TEXT);
409 attr = ippFindNextAttribute(response,
410 "ppd-make-and-model",
411 IPP_TAG_TEXT);
412 if (strcmp(ippGetString(attr, 0, NULL), ppdfilename) == 0 ) {
413 /* return tmpppd; */
414 strcpy(test, tmpppd);
415 break;
416 }
417 attr = ippFindNextAttribute(response, "ppd-name", IPP_TAG_NAME);
418 }
419 }
420 ippDelete(response);
421 httpClose(http);
422 rv = sv_newmortal();
423 sv_setpv( rv, test);
424 XPUSHs( rv );
425
426 MODULE = Net::CUPS PACKAGE = Net::CUPS::Destination
427
428 PROTOTYPES: DISABLE
429
430 INCLUDE: const-xs.inc
431
432 void
433 NETCUPS_getDeviceAttribute( device, attribute, attribute_type )
434 const char* device;
435 const char* attribute;
436 int attribute_type;
437
438 PPCODE:
439 http_t *http = NULL; /* HTTP object */
440 ipp_t *request = NULL; /* IPP request */
441 ipp_t *response = NULL; /* IPP response */
442 ipp_attribute_t *attr = NULL; /* IPP attribute */
443 SV* rv = NULL;
444 char *description = NULL;
445
446 http = httpConnectEncrypt( cupsServer(), ippPort(), cupsEncryption() );
447
448 if (http == NULL) {
449 perror ("Unable to connect to server");
450 /* return (1); */
451 }
452
453 request = ippNewRequest (CUPS_GET_PRINTERS);
454
455 if ((response = cupsDoRequest (http, request, "/")) != NULL) {
456 rv = sv_newmortal();
457 int match = 0;
458 for (attr = ippFirstAttribute(response); attr != NULL; attr = ippNextAttribute(response)) {
459 if (ippGetName(attr) == NULL) {
460 if (match) break; else continue;
461 }
462 if (!strcmp(ippGetName(attr), "printer-name") && ippGetValueTag(attr) == IPP_TAG_NAME) {
463 match = !strcmp(ippGetString(attr, 0, NULL), device);
464 } else if (!strcmp(ippGetName(attr), attribute) && ippGetValueTag(attr) == attribute_type) {
465 if (ippGetCount(attr) == 1) {
466 switch (attribute_type) {
467 case IPP_TAG_TEXT:
468 case IPP_TAG_NAME:
469 case IPP_TAG_KEYWORD:
470 case IPP_TAG_URI:
471 case IPP_TAG_CHARSET:
472 case IPP_TAG_LANGUAGE:
473 sv_setpv(rv, ippGetString(attr, 0, NULL));
474 break;
475 case IPP_TAG_BOOLEAN:
476 sv_setiv(rv, ippGetBoolean(attr, 0));
477 break;
478 case IPP_TAG_INTEGER:
479 case IPP_TAG_ENUM:
480 sv_setiv(rv, ippGetInteger(attr, 0));
481 break;
482 }
483 } else {
484 /* XXX */
485 }
486 }
487 }
488 if (match) XPUSHs(rv);
489 }
490 ippDelete( response );
491 httpClose( http );
492 XSRETURN( 1 );
493
494 int
495 NETCUPS_addOption( self, name, value )
496 cups_dest_t* self;
497 const char* name;
498 const char* value;
499 CODE:
500 int num_options;
501 num_options =
502 cupsAddOption( name, value, self->num_options, &self->options );
503 self->num_options = num_options;
504 RETVAL = num_options;
505 OUTPUT:
506 RETVAL
507
508 int
509 NETCUPS_cancelJob( self, jobid )
510 const char* self;
511 int jobid;
512 CODE:
513 RETVAL = cupsCancelJob( self, jobid );
514 OUTPUT:
515 RETVAL
516
517 int
518 NETCUPS_freeDestination( self )
519 cups_dest_t* self;
520 CODE:
521 /* If we use the following function, then we will get errors */
522 /* about double frees. */
523 /*cupsFreeDests( 1, self ); */
524 if( self->instance )
525 free( self->instance );
526 cupsFreeOptions( self->num_options, self->options );
527 /* I am working under the assumption that the actual 'cups_dest_t */
528 /* will be freed when perl does its garbage collection. */
529 /* I really need to research it more. */
530 RETVAL = 1;
531 OUTPUT:
532 RETVAL
533
534 char*
535 NETCUPS_getDestinationName( self )
536 cups_dest_t *self;
537 CODE:
538 RETVAL = self->name;
539 OUTPUT:
540 RETVAL
541
542 const char*
543 NETCUPS_getDestinationOptionValue( self, option )
544 cups_dest_t *self;
545 char* option;
546 CODE:
547 RETVAL = cupsGetOption( option, self->num_options, self->options );
548 OUTPUT:
549 RETVAL
550
551 void
552 NETCUPS_getDestinationOptions( self )
553 cups_dest_t* self
554 INIT:
555 int count = 0;
556 int loop = 0;
557 SV* rv = NULL;
558 cups_option_t* options = NULL;
559 PPCODE:
560 count = self->num_options;
561 options = self->options;
562
563 for( loop = 0; loop < count; loop++ )
564 {
565 rv = newSV(0);
566 sv_setpv( rv, options[loop].name );
567 XPUSHs( rv );
568 }
569 XSRETURN( count );
570
571 SV*
572 NETCUPS_getJob( dest, jobid )
573 const char* dest;
574 int jobid;
575 CODE:
576 int loop = 0;
577 int count = 0;
578 HV* hv = NULL;
579 cups_job_t* jobs = NULL;
580 char *tstate = NULL;
581 RETVAL = &PL_sv_undef;
582 count = cupsGetJobs( &jobs, dest, 0, -1 );
583 for( loop = 0; loop < count; loop++ )
584 {
585 if( jobs[loop].id == jobid )
586 {
587 hv = newHV();
588
589 hv_store( hv, "completed_time",
590 strlen( "completed_time" ),
591 newSVnv( jobs[loop].completed_time ),
592 0 );
593
594 hv_store( hv, "creation_time",
595 strlen( "creation_time" ),
596 newSVnv( jobs[loop].creation_time ),
597 0 );
598
599 hv_store( hv, "dest",
600 strlen( "dest" ),
601 newSVpv( jobs[loop].dest,
602 strlen( jobs[loop].dest ) ), 0 );
603
604 hv_store( hv, "format",
605 strlen( "format" ),
606 newSVpv( jobs[loop].format,
607 strlen( jobs[loop].format ) ), 0 );
608
609 hv_store( hv, "id",
610 strlen( "id" ),
611 newSViv( jobs[loop].id ), 0 );
612
613 hv_store( hv, "priority",
614 strlen( "priority" ),
615 newSViv( jobs[loop].priority ), 0 );
616
617 hv_store( hv, "processing_time",
618 strlen( "processing_time" ),
619 newSVnv( jobs[loop].processing_time ), 0 );
620
621 hv_store( hv, "size",
622 strlen( "size" ),
623 newSViv( jobs[loop].size ), 0 );
624
625 hv_store( hv, "state",
626 strlen( "state" ),
627 newSViv( jobs[loop].state ), 0 );
628
629 hv_store( hv, "title",
630 strlen( "title" ),
631 newSVpv( jobs[loop].title,
632 strlen( jobs[loop].title ) ), 0 );
633
634 hv_store( hv, "user",
635 strlen( "user" ),
636 newSVpv( jobs[loop].user,
637 strlen( jobs[loop].user ) ), 0 );
638
639 switch( jobs[loop].state )
640 {
641 case IPP_JOB_PENDING:
642 {
643 tstate = "pending";
644 break;
645 }
646 case IPP_JOB_HELD:
647 {
648 tstate = "held";
649 break;
650 }
651 case IPP_JOB_PROCESSING:
652 {
653 tstate = "processing";
654 break;
655 }
656 case IPP_JOB_STOPPED:
657 {
658 tstate = "stopped";
659 break;
660 }
661 /* CANCELLED is not a TYPO! (Well, it is, but it
662 is not my fault! */
663 case IPP_JOB_CANCELLED:
664 {
665 tstate = "canceled";
666 break;
667 }
668 case IPP_JOB_ABORTED:
669 {
670 tstate = "aborted";
671 break;
672 }
673 case IPP_JOB_COMPLETED:
674 {
675 tstate = "completed";
676 break;
677 }
678 default:
679 {
680 tstate = "unknown";
681 break;
682 }
683 }
684
685 hv_store( hv, "state_text",
686 strlen( "state_text" ),
687 newSVpv( tstate,
688 strlen( tstate ) ), 0 );
689
690 RETVAL = newRV((SV*)hv);
691 }
692 }
693 OUTPUT:
694 RETVAL
695
696 void
697 NETCUPS_getJobs( dest, whose, scope )
698 const char* dest;
699 int whose;
700 int scope;
701 PPCODE:
702 int loop = 0;
703 int count = 0;
704 SV* rv = NULL;
705 cups_job_t* jobs = NULL;
706 count = cupsGetJobs( &jobs, dest, whose, scope );
707 for( loop = 0; loop < count; loop++ )
708 {
709 rv = newSV(0);
710 sv_setiv( rv, jobs[loop].id );
711 XPUSHs( rv );
712 }
713 XSRETURN( count );
714
715 const char*
716 NETCUPS_getError()
717 CODE:
718 RETVAL = cupsLastErrorString();
719 OUTPUT:
720 RETVAL
721
722 int
723 NETCUPS_printFile( self, filename, title )
724 cups_dest_t* self;
725 const char* filename;
726 const char* title;
727 CODE:
728 RETVAL = cupsPrintFile( self->name,
729 filename,
730 title,
731 self->num_options,
732 self->options );
733 OUTPUT:
734 RETVAL
735
736
737 MODULE = Net::CUPS PACKAGE = Net::CUPS::PPD
738
739 PROTOTYPES: DISABLE
740
741 INCLUDE: const-xs.inc
742
743 int
744 NETCUPS_freePPD( ppd )
745 ppd_file_t *ppd;
746 CODE:
747 ppdClose( ppd );
748 RETVAL = 1;
749 OUTPUT:
750 RETVAL
751
752 HV*
753 NETCUPS_getFirstOption( ppd )
754 ppd_file_t *ppd;
755 INIT:
756 ppd_option_t *option;
757 CODE:
758 option = ppdFirstOption( ppd );
759 RETVAL = hash_ppd_option_t( option );
760 if (RETVAL == 0)
761 XSRETURN_UNDEF;
762 OUTPUT:
763 RETVAL
764
765 HV*
766 NETCUPS_getNextOption( ppd )
767 ppd_file_t *ppd;
768 INIT:
769 ppd_option_t *option;
770 CODE:
771 option = ppdNextOption( ppd );
772 RETVAL = hash_ppd_option_t( option );
773 if (RETVAL == 0)
774 XSRETURN_UNDEF;
775 OUTPUT:
776 RETVAL
777
778 HV*
779 NETCUPS_getOption( ppd, keyword )
780 ppd_file_t *ppd;
781 const char* keyword;
782 INIT:
783 ppd_option_t *option;
784 CODE:
785 option = ppdFindOption( ppd, keyword );
786 RETVAL = hash_ppd_option_t( option );
787 if (RETVAL == 0)
788 XSRETURN_UNDEF;
789 OUTPUT:
790 RETVAL
791
792 int
793 NETCUPS_getPageLength( ppd, size )
794 ppd_file_t *ppd;
795 const char* size;
796 CODE:
797 RETVAL = ppdPageLength( ppd, size );
798 OUTPUT:
799 RETVAL
800
801 HV*
802 NETCUPS_getPageSize( ppd, size )
803 ppd_file_t *ppd;
804 const char* size;
805 INIT:
806 ppd_size_t* page_size;
807 HV* hv;
808 CODE:
809 page_size = ppdPageSize( ppd, size );
810 hv = newHV();
811
812 if( page_size != NULL )
813 {
814 hv_store( hv, "bottom",
815 strlen( "bottom" ),
816 newSViv( page_size->bottom ), 0 );
817
818 hv_store( hv, "left",
819 strlen( "left" ),
820 newSViv( page_size->left ), 0 );
821
822 hv_store( hv, "length",
823 strlen( "length" ),
824 newSViv( page_size->length ), 0 );
825
826 hv_store( hv, "marked",
827 strlen( "marked" ),
828 newSViv( page_size->marked ), 0 );
829
830 hv_store( hv, "name",
831 strlen( "name" ),
832 newSVpv( page_size->name, PPD_MAX_NAME ), 0 );
833
834 hv_store( hv, "right",
835 strlen( "right" ),
836 newSViv( page_size->right ), 0 );
837
838 hv_store( hv, "top",
839 strlen( "top" ),
840 newSViv( page_size->top ), 0 );
841
842 hv_store( hv, "width",
843 strlen( "width" ),
844 newSViv( page_size->width ), 0 );
845 }
846 RETVAL = hv;
847 OUTPUT:
848 RETVAL
849
850 int
851 NETCUPS_getPageWidth( ppd, size )
852 ppd_file_t *ppd;
853 const char* size;
854 CODE:
855 RETVAL = ppdPageWidth( ppd, size );
856 OUTPUT:
857 RETVAL
858
859
860 int
861 NETCUPS_isMarked( ppd, option, choice )
862 ppd_file_t *ppd;
863 const char* option;
864 const char* choice;
865 CODE:
866 RETVAL = ppdIsMarked( ppd, option, choice );
867 OUTPUT:
868 RETVAL
869
870 int
871 NETCUPS_markDefaults( ppd )
872 ppd_file_t *ppd;
873 CODE:
874 ppdMarkDefaults( ppd );
875 RETVAL = 1;
876 OUTPUT:
877 RETVAL
878
879 int
880 NETCUPS_markOption( ppd, option, choice )
881 ppd_file_t *ppd;
882 const char* option;
883 const char* choice;
884 CODE:
885 RETVAL = ppdMarkOption( ppd, option, choice );
886 OUTPUT:
887 RETVAL
888
889 MODULE = Net::CUPS PACKAGE = Net::CUPS::IPP
890
891 PROTOTYPES: DISABLE
892
893 INCLUDE: const-xs.inc
894
895 int
896 NETCUPS_freeIPP( ipp )
897 ipp_t* ipp;
898 CODE:
899 ippDelete( ipp );
900 RETVAL = 1;
901 OUTPUT:
902 RETVAL
903
904 int
905 NETCUPS_addString( ipp, group, type, name, charset, value )
906 ipp_t* ipp;
907 ipp_tag_t group;
908 ipp_tag_t type;
909 const char* name;
910 const char* charset;
911 const char* value;
912 CODE:
913 ipp_attribute_t* attribute = NULL;
914 attribute = ippAddString( ipp, group, type, name, charset, value );
915 RETVAL = 1;
916 OUTPUT:
917 RETVAL
918
919
920 void
921 NETCUPS_getAttributes( ipp )
922 ipp_t* ipp;
923 PPCODE:
924 SV* rv = NULL;
925 int count = 0;
926 ipp_attribute_t* attr = NULL;
927 for (attr = ippFirstAttribute(ipp); attr != NULL; attr = ippNextAttribute(ipp))
928 {
929 while (attr != NULL && ippGetGroupTag(attr) != IPP_TAG_JOB)
930 attr = ippNextAttribute(ipp);
931
932 if (attr == NULL)
933 break;
934 rv = sv_newmortal();
935 sv_setpv( rv, ippGetName(attr) );
936 XPUSHs( rv );
937 count++;
938 }
939 XSRETURN( count );
940
941 void
942 NETCUPS_getAttributeValue( ipp, name )
943 ipp_t* ipp;
944 const char* name;
945 PPCODE:
946 SV* rv = NULL;
947 int count = 0;
948 ipp_attribute_t* attr = NULL;
949 for (attr = ippFirstAttribute(ipp); attr != NULL; attr = ippNextAttribute(ipp))
950 {
951 while (attr != NULL && ippGetGroupTag(attr) != IPP_TAG_JOB)
952 attr = ippNextAttribute(ipp);
953
954 if (attr == NULL)
955 break;
956
957 if( !strcmp( ippGetName(attr), name ) )
958 {
959 rv = sv_newmortal();
960 if( ( ippGetValueTag(attr) == IPP_TAG_INTEGER ) ||
961 ( ippGetValueTag(attr) == IPP_TAG_ENUM ) )
962 {
963 /* We have a number with any luck ... */
964 sv_setiv( rv, ippGetInteger(attr, 0) );
965 }
966 else
967 {
968 /* We have a string ... maybe ... try to set it. */
969 sv_setpv( rv, ippGetString(attr, 0, NULL) );
970 }
971
972 XPUSHs( rv );
973 count++;
974 break;
975 }
976 }
977 XSRETURN( count );
978
979 int
980 NETCUPS_getPort()
981 CODE:
982 RETVAL = ippPort();
983 OUTPUT:
984 RETVAL
985
986 size_t
987 NETCUPS_getSize( ipp )
988 ipp_t* ipp;
989 CODE:
990 RETVAL = ippLength( ipp );
991 OUTPUT:
992 RETVAL
993
994 void
995 NETCUPS_newIPP()
996 PPCODE:
997 ipp_t * ipp = NULL;
998 SV* rv = NULL;
999 ipp = ippNew();
1000 rv = sv_newmortal();
1001 sv_setref_pv( rv, "Net::CUPS::IPP", ipp );
1002 XPUSHs( rv );
1003 XSRETURN( 1 );
1004
1005 void
1006 NETCUPS_newIPPRequest( op )
1007 ipp_op_t op;
1008 PPCODE:
1009 ipp_t * ipp = NULL;
1010 SV* rv = NULL;
1011 ipp = ippNewRequest( op );
1012 rv = sv_newmortal();
1013 sv_setref_pv( rv, "Net::CUPS::IPP", ipp );
1014 XPUSHs( rv );
1015 XSRETURN( 1 );
1016
1017 int
1018 NETCUPS_setPort( port )
1019 int port;
1020 CODE:
1021 ippSetPort( port );
1022 RETVAL = ippPort();
1023 OUTPUT:
1024 RETVAL
1025