[Pkg-cups-devel] r417 - in cupsys/branches/cups-1.2/debian: .
patches
Kenshi Muto
kmuto at alioth.debian.org
Thu Dec 28 13:48:32 UTC 2006
Author: kmuto
Date: Thu Dec 28 14:48:31 2006
New Revision: 417
Added:
cupsys/branches/cups-1.2/debian/patches/00_00str2111.dpatch (contents, props changed)
cupsys/branches/cups-1.2/debian/patches/00_01str2137.dpatch (contents, props changed)
cupsys/branches/cups-1.2/debian/patches/00_02str2144.dpatch (contents, props changed)
cupsys/branches/cups-1.2/debian/patches/00_03str2106.dpatch (contents, props changed)
cupsys/branches/cups-1.2/debian/patches/00_04str2117.dpatch (contents, props changed)
cupsys/branches/cups-1.2/debian/patches/00_05str2133.dpatch (contents, props changed)
cupsys/branches/cups-1.2/debian/patches/00_06str2121.dpatch (contents, props changed)
cupsys/branches/cups-1.2/debian/patches/00_07str2123.dpatch (contents, props changed)
cupsys/branches/cups-1.2/debian/patches/00_08str2135.dpatch (contents, props changed)
Removed:
cupsys/branches/cups-1.2/debian/patches/00_r6149.dpatch
cupsys/branches/cups-1.2/debian/patches/66_setegid.dpatch
Modified:
cupsys/branches/cups-1.2/debian/changelog
cupsys/branches/cups-1.2/debian/patches/00list
Log:
merge STR2121,2137,2133,2117,2123,2135,2106,2144,2111. removed 66_setegid,00_r6149.
Modified: cupsys/branches/cups-1.2/debian/changelog
==============================================================================
--- cupsys/branches/cups-1.2/debian/changelog (original)
+++ cupsys/branches/cups-1.2/debian/changelog Thu Dec 28 14:48:31 2006
@@ -1,15 +1,25 @@
-cupsys (1.2.7-2) UNRELEASED; urgency=low
+cupsys (1.2.7-2) UNRELEASED; urgency=high
[ Kenshi Muto ]
- * Apply upstream r6149. Fixed some bugs around raster handling,
- printer status, IPv6 and so on.
- * Trying to revert seteuid way of upstream. (disabled 06_disable
- _backend_setuid patch to let backend works as upstream imagined)
- Put 66_setegid.dpatch to set GID.
- * Add Printcap/PrintcapFormat/PrintcapGUI variables to cupsd.conf
- file. (closes: #401981)
- (It's a known problem that when you reset configuration file
- from Web interface, configuration won't back to 100% original.)
+ * Applied upstream patches to fix some (include RC) bugs as dpatch style:
+ - STR2106: Raw PBM files did not print correctly
+ - STR2111: The PostScript filter did not properly output
+ document setup commands for reversed output (closes: Bug#403703)
+ - STR2117: The scheduler did not parse IPv6 netmask properly
+ - STR2121: cupsDoAuthentication() did not translate the password
+ prompt
+ - STR2123: The backends incorrectly used STATUS:
+ media-tray-empty-error messages for out-of-paper conditions
+ - STR2133: httpGetLength2() did not handle error messages without
+ content correctly
+ - STR2135: cupsMarkOptions() did not handle the
+ multiple-document-handling option
+ - STR2137: Collated output produced by the PostScript filter could
+ lose some options
+ - STR2144: job-hold-until with time values for the next day would
+ be held for 60 days
+ * 67_printcap: Add Printcap/PrintcapFormat/PrintcapGUI variables to
+ cupsd.conf file. (closes: #401981)
-- Kenshi Muto <kmuto at debian.org> Wed, 6 Dec 2006 22:42:34 +0000
Added: cupsys/branches/cups-1.2/debian/patches/00_00str2111.dpatch
==============================================================================
--- (empty file)
+++ cupsys/branches/cups-1.2/debian/patches/00_00str2111.dpatch Thu Dec 28 14:48:31 2006
@@ -0,0 +1,51 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 00_00str2111.dpatch by Kenshi Muto <kmuto at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad cupsys-1.2.7~/filter/pstops.c cupsys-1.2.7/filter/pstops.c
+--- cupsys-1.2.7~/filter/pstops.c 2006-12-28 12:00:51.000000000 +0000
++++ cupsys-1.2.7/filter/pstops.c 2006-12-28 12:50:15.000000000 +0000
+@@ -909,23 +909,26 @@
+ * for the JCL options...
+ */
+
+- if (!doc->saw_eof)
+- puts("%%EOF");
+-
+- if (doc->emit_jcl)
++ if (number)
+ {
+- if (ppd && ppd->jcl_end)
+- ppdEmitJCLEnd(ppd, stdout);
+- else
+- putchar(0x04);
++ if (!doc->saw_eof)
++ puts("%%EOF");
+
+- ppdEmitJCL(ppd, stdout, doc->job_id, doc->user, doc->title);
+- }
++ if (doc->emit_jcl)
++ {
++ if (ppd && ppd->jcl_end)
++ ppdEmitJCLEnd(ppd, stdout);
++ else
++ putchar(0x04);
+
+- puts("%!PS-Adobe-3.0");
+- puts("%%Pages: (atend)");
+- puts("%%BoundingBox: (atend)");
+- puts("%%EndComments");
++ ppdEmitJCL(ppd, stdout, doc->job_id, doc->user, doc->title);
++ }
++
++ puts("%!PS-Adobe-3.0");
++ puts("%%Pages: (atend)");
++ puts("%%BoundingBox: (atend)");
++ puts("%%EndComments");
++ }
+
+ /*
+ * Then copy all of the pages...
Added: cupsys/branches/cups-1.2/debian/patches/00_01str2137.dpatch
==============================================================================
--- (empty file)
+++ cupsys/branches/cups-1.2/debian/patches/00_01str2137.dpatch Thu Dec 28 14:48:31 2006
@@ -0,0 +1,504 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 00_01str2137.dpatch by Kenshi Muto <kmuto at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad cupsys-1.2.7~/filter/pstops.c cupsys-1.2.7/filter/pstops.c
+--- cupsys-1.2.7~/filter/pstops.c 2006-12-28 12:58:22.000000000 +0000
++++ cupsys-1.2.7/filter/pstops.c 2006-12-28 12:58:34.000000000 +0000
+@@ -205,6 +205,9 @@
+ size_t linesize);
+ static void start_nup(pstops_doc_t *doc, int number,
+ int show_border, const int *bounding_box);
++static void write_label_prolog(pstops_doc_t *doc, const char *label,
++ float bottom, float top,
++ float width);
+ static void write_labels(pstops_doc_t *doc, int orient);
+
+
+@@ -665,12 +668,12 @@
+ else if (!strncmp(line, "%%For:", 6))
+ {
+ saw_for = 1;
+- printf("%s\n", line);
++ doc_printf(doc, "%s\n", line);
+ }
+ else if (!strncmp(line, "%%Title:", 8))
+ {
+ saw_title = 1;
+- printf("%s\n", line);
++ doc_printf(doc, "%s\n", line);
+ }
+ else if (!strncmp(line, "%cupsRotation:", 14))
+ {
+@@ -697,7 +700,7 @@
+ break;
+ }
+ else if (strncmp(line, "%!", 2) && strncmp(line, "%cups", 5))
+- printf("%s\n", line);
++ doc_printf(doc, "%s\n", line);
+
+ if ((linelen = cupsFileGetLine(fp, line, linesize)) == 0)
+ break;
+@@ -722,15 +725,15 @@
+ * that are required...
+ */
+
+- printf("%%%%Requirements: numcopies(%d)%s%s\n", doc->copies,
+- doc->collate ? " collate" : "",
+- Duplex ? " duplex" : "");
++ doc_printf(doc, "%%%%Requirements: numcopies(%d)%s%s\n", doc->copies,
++ doc->collate ? " collate" : "",
++ Duplex ? " duplex" : "");
+
+ /*
+ * Apple uses RBI comments for various non-PPD options...
+ */
+
+- printf("%%RBINumCopies: %d\n", doc->copies);
++ doc_printf(doc, "%%RBINumCopies: %d\n", doc->copies);
+ }
+ else
+ {
+@@ -739,18 +742,18 @@
+ */
+
+ if (Duplex)
+- puts("%%Requirements: duplex");
++ doc_puts(doc, "%%Requirements: duplex\n");
+
+ /*
+ * Apple uses RBI comments for various non-PPD options...
+ */
+
+- puts("%RBINumCopies: 1");
++ doc_puts(doc, "%RBINumCopies: 1\n");
+ }
+
+- puts("%%Pages: (atend)");
+- puts("%%BoundingBox: (atend)");
+- puts("%%EndComments");
++ doc_puts(doc, "%%Pages: (atend)\n");
++ doc_puts(doc, "%%BoundingBox: (atend)\n");
++ doc_puts(doc, "%%EndComments\n");
+
+ return (linelen);
+ }
+@@ -811,7 +814,7 @@
+
+ while (strncmp(line, "%%Page:", 7) && strncmp(line, "%%Trailer", 9))
+ {
+- fwrite(line, 1, linelen, stdout);
++ doc_write(doc, line, linelen);
+
+ if ((linelen = cupsFileGetLine(fp, line, linesize)) == 0)
+ break;
+@@ -909,25 +912,36 @@
+ * for the JCL options...
+ */
+
+- if (number)
++ if (number && doc->emit_jcl && ppd && ppd->jcl_end)
+ {
+- if (!doc->saw_eof)
+- puts("%%EOF");
++ /*
++ * Send the trailer...
++ */
+
+- if (doc->emit_jcl)
+- {
+- if (ppd && ppd->jcl_end)
+- ppdEmitJCLEnd(ppd, stdout);
+- else
+- putchar(0x04);
++ puts("%%Trailer");
++ printf("%%%%Pages: %d\n", cupsArrayCount(doc->pages));
++ if (doc->number_up > 1 || doc->fitplot)
++ printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
++ PageLeft, PageBottom, PageRight, PageTop);
++ else
++ printf("%%%%BoundingBox: %d %d %d %d\n",
++ doc->new_bounding_box[0], doc->new_bounding_box[1],
++ doc->new_bounding_box[2], doc->new_bounding_box[3]);
++ puts("%%EOF");
+
+- ppdEmitJCL(ppd, stdout, doc->job_id, doc->user, doc->title);
+- }
++ /*
++ * Start a new document...
++ */
++
++ ppdEmitJCLEnd(ppd, stdout);
++ ppdEmitJCL(ppd, stdout, doc->job_id, doc->user, doc->title);
+
+ puts("%!PS-Adobe-3.0");
+- puts("%%Pages: (atend)");
+- puts("%%BoundingBox: (atend)");
+- puts("%%EndComments");
++
++ pageinfo = (pstops_page_t *)cupsArrayFirst(doc->pages);
++ copy_bytes(doc->temp, 0, pageinfo->offset);
++
++ number = 0;
+ }
+
+ /*
+@@ -1639,13 +1653,13 @@
+ if (!strncmp(line, "%%BeginSetup", 12) || !strncmp(line, "%%Page:", 7))
+ break;
+
+- fwrite(line, 1, linelen, stdout);
++ doc_write(doc, line, linelen);
+
+ if ((linelen = cupsFileGetLine(fp, line, linesize)) == 0)
+ break;
+ }
+
+- puts("%%BeginProlog");
++ doc_puts(doc, "%%BeginProlog\n");
+
+ do_prolog(doc, ppd);
+
+@@ -1658,7 +1672,7 @@
+ !strncmp(line, "%%Page:", 7))
+ break;
+
+- fwrite(line, 1, linelen, stdout);
++ doc_write(doc, line, linelen);
+ }
+
+ if (!strncmp(line, "%%EndProlog", 11))
+@@ -1667,7 +1681,7 @@
+ fputs("ERROR: Missing %%EndProlog!\n", stderr);
+ }
+
+- puts("%%EndProlog");
++ doc_puts(doc, "%%EndProlog\n");
+
+ return (linelen);
+ }
+@@ -1693,13 +1707,13 @@
+ if (!strncmp(line, "%%Page:", 7))
+ break;
+
+- fwrite(line, 1, linelen, stdout);
++ doc_write(doc, line, linelen);
+
+ if ((linelen = cupsFileGetLine(fp, line, linesize)) == 0)
+ break;
+ }
+
+- puts("%%BeginSetup");
++ doc_puts(doc, "%%BeginSetup\n");
+
+ do_setup(doc, ppd);
+
+@@ -1720,7 +1734,7 @@
+ &(doc->options));
+ }
+ else if (strncmp(line, "%%BeginSetup", 12))
+- fwrite(line, 1, linelen, stdout);
++ doc_write(doc, line, linelen);
+
+ if ((linelen = cupsFileGetLine(fp, line, linesize)) == 0)
+ break;
+@@ -1732,7 +1746,7 @@
+ fputs("ERROR: Missing %%EndSetup!\n", stderr);
+ }
+
+- puts("%%EndSetup");
++ doc_puts(doc, "%%EndSetup\n");
+
+ return (linelen);
+ }
+@@ -1795,18 +1809,25 @@
+ do_prolog(pstops_doc_t *doc, /* I - Document information */
+ ppd_file_t *ppd) /* I - PPD file */
+ {
++ char *ps; /* PS commands */
++
++
+ /*
+ * Send the document prolog commands...
+ */
+
+ if (ppd && ppd->patches)
+ {
+- puts("%%BeginFeature: *JobPatchFile 1");
+- puts(ppd->patches);
+- puts("%%EndFeature");
++ doc_puts(doc, "%%BeginFeature: *JobPatchFile 1\n");
++ doc_puts(doc, ppd->patches);
++ doc_puts(doc, "\n%%EndFeature\n");
+ }
+
+- ppdEmit(ppd, stdout, PPD_ORDER_PROLOG);
++ if ((ps = ppdEmitString(ppd, PPD_ORDER_PROLOG, 0.0)) != NULL)
++ {
++ doc_puts(doc, ps);
++ free(ps);
++ }
+
+ /*
+ * Define ESPshowpage here so that applications that define their
+@@ -1814,9 +1835,8 @@
+ */
+
+ if (doc->use_ESPshowpage)
+- puts("userdict/ESPshowpage/showpage load put\n"
+- "userdict/showpage{}put");
+-
++ doc_puts(doc, "userdict/ESPshowpage/showpage load put\n"
++ "userdict/showpage{}put\n");
+ }
+
+
+@@ -1828,13 +1848,16 @@
+ do_setup(pstops_doc_t *doc, /* I - Document information */
+ ppd_file_t *ppd) /* I - PPD file */
+ {
++ char *ps; /* PS commands */
++
++
+ /*
+ * Disable CTRL-D so that embedded files don't cause printing
+ * errors...
+ */
+
+- puts("% Disable CTRL-D as an end-of-file marker...");
+- puts("userdict dup(\\004)cvn{}put (\\004\\004)cvn{}put");
++ doc_puts(doc, "% Disable CTRL-D as an end-of-file marker...\n");
++ doc_puts(doc, "userdict dup(\\004)cvn{}put (\\004\\004)cvn{}put\n");
+
+ /*
+ * Mark any options from %%IncludeFeature: comments...
+@@ -1846,8 +1869,17 @@
+ * Send all the printer-specific setup commands...
+ */
+
+- ppdEmit(ppd, stdout, PPD_ORDER_DOCUMENT);
+- ppdEmit(ppd, stdout, PPD_ORDER_ANY);
++ if ((ps = ppdEmitString(ppd, PPD_ORDER_DOCUMENT, 0.0)) != NULL)
++ {
++ doc_puts(doc, ps);
++ free(ps);
++ }
++
++ if ((ps = ppdEmitString(ppd, PPD_ORDER_ANY, 0.0)) != NULL)
++ {
++ doc_puts(doc, ps);
++ free(ps);
++ }
+
+ /*
+ * Set the number of copies for the job...
+@@ -1855,11 +1887,13 @@
+
+ if (doc->copies != 1 && (!doc->collate || !doc->slow_collate))
+ {
+- printf("%%RBIBeginNonPPDFeature: *NumCopies %d\n", doc->copies);
+- printf("%d/languagelevel where{pop languagelevel 2 ge}{false}ifelse\n"
+- "{1 dict begin/NumCopies exch def currentdict end setpagedevice}\n"
+- "{userdict/#copies 3 -1 roll put}ifelse\n", doc->copies);
+- puts("%RBIEndNonPPDFeature");
++ doc_printf(doc, "%%RBIBeginNonPPDFeature: *NumCopies %d\n", doc->copies);
++ doc_printf(doc,
++ "%d/languagelevel where{pop languagelevel 2 ge}{false}ifelse\n"
++ "{1 dict begin/NumCopies exch def currentdict end "
++ "setpagedevice}\n"
++ "{userdict/#copies 3 -1 roll put}ifelse\n", doc->copies);
++ doc_puts(doc, "%RBIEndNonPPDFeature\n");
+ }
+
+ /*
+@@ -1867,7 +1901,7 @@
+ */
+
+ if (doc->number_up > 1)
+- puts("userdict/setpagedevice{pop}bind put");
++ doc_puts(doc, "userdict/setpagedevice{pop}bind put\n");
+
+ /*
+ * Changes to the transfer function must be made AFTER any
+@@ -1875,15 +1909,31 @@
+ */
+
+ if (doc->gamma != 1.0f || doc->brightness != 1.0f)
+- printf("{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
+- "ifelse %.3f mul } bind settransfer\n", doc->gamma,
+- doc->brightness);
++ doc_printf(doc, "{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
++ "ifelse %.3f mul } bind settransfer\n",
++ doc->gamma, doc->brightness);
+
+ /*
+ * Make sure we have rectclip and rectstroke procedures of some sort...
+ */
+
+- WriteCommon();
++ doc_puts(doc,
++ "% x y w h ESPrc - Clip to a rectangle.\n"
++ "userdict/ESPrc/rectclip where{pop/rectclip load}\n"
++ "{{newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
++ "neg 0 rlineto closepath clip newpath}bind}ifelse put\n");
++
++ doc_puts(doc,
++ "% x y w h ESPrf - Fill a rectangle.\n"
++ "userdict/ESPrf/rectfill where{pop/rectfill load}\n"
++ "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
++ "neg 0 rlineto closepath fill grestore}bind}ifelse put\n");
++
++ doc_puts(doc,
++ "% x y w h ESPrs - Stroke a rectangle.\n"
++ "userdict/ESPrs/rectstroke where{pop/rectstroke load}\n"
++ "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
++ "neg 0 rlineto closepath stroke grestore}bind}ifelse put\n");
+
+ /*
+ * Write the page and label prologs...
+@@ -1897,13 +1947,14 @@
+ */
+
+ if (Orientation & 1)
+- WriteLabelProlog(doc->page_label, PageBottom,
+- PageWidth - PageLength + PageTop, PageLength);
++ write_label_prolog(doc, doc->page_label, PageBottom,
++ PageWidth - PageLength + PageTop, PageLength);
+ else
+- WriteLabelProlog(doc->page_label, PageLeft, PageRight, PageLength);
++ write_label_prolog(doc, doc->page_label, PageLeft, PageRight,
++ PageLength);
+ }
+ else
+- WriteLabelProlog(doc->page_label, PageBottom, PageTop, PageWidth);
++ write_label_prolog(doc, doc->page_label, PageBottom, PageTop, PageWidth);
+ }
+
+
+@@ -3063,6 +3114,123 @@
+
+
+ /*
++ * 'write_label_prolog()' - Write the prolog with the classification
++ * and page label.
++ */
++
++static void
++write_label_prolog(pstops_doc_t *doc, /* I - Document info */
++ const char *label, /* I - Page label */
++ float bottom, /* I - Bottom position in points */
++ float top, /* I - Top position in points */
++ float width) /* I - Width in points */
++{
++ const char *classification; /* CLASSIFICATION environment variable */
++ const char *ptr; /* Temporary string pointer */
++
++
++ /*
++ * First get the current classification...
++ */
++
++ if ((classification = getenv("CLASSIFICATION")) == NULL)
++ classification = "";
++ if (strcmp(classification, "none") == 0)
++ classification = "";
++
++ /*
++ * If there is nothing to show, bind an empty 'write labels' procedure
++ * and return...
++ */
++
++ if (!classification[0] && (label == NULL || !label[0]))
++ {
++ doc_puts(doc, "userdict/ESPwl{}bind put\n");
++ return;
++ }
++
++ /*
++ * Set the classification + page label string...
++ */
++
++ doc_puts(doc, "userdict");
++ if (!strcmp(classification, "confidential"))
++ doc_puts(doc, "/ESPpl(CONFIDENTIAL");
++ else if (!strcmp(classification, "classified"))
++ doc_puts(doc, "/ESPpl(CLASSIFIED");
++ else if (!strcmp(classification, "secret"))
++ doc_puts(doc, "/ESPpl(SECRET");
++ else if (!strcmp(classification, "topsecret"))
++ doc_puts(doc, "/ESPpl(TOP SECRET");
++ else if (!strcmp(classification, "unclassified"))
++ doc_puts(doc, "/ESPpl(UNCLASSIFIED");
++ else
++ {
++ doc_puts(doc, "/ESPpl(");
++
++ for (ptr = classification; *ptr; ptr ++)
++ {
++ if (*ptr < 32 || *ptr > 126)
++ doc_printf(doc, "\\%03o", *ptr);
++ else if (*ptr == '_')
++ doc_puts(doc, " ");
++ else if (*ptr == '(' || *ptr == ')' || *ptr == '\\')
++ doc_printf(doc, "\\%c", *ptr);
++ else
++ doc_printf(doc, "%c", *ptr);
++ }
++ }
++
++ if (label)
++ {
++ if (classification[0])
++ doc_puts(doc, " - ");
++
++ /*
++ * Quote the label string as needed...
++ */
++
++ for (ptr = label; *ptr; ptr ++)
++ {
++ if (*ptr < 32 || *ptr > 126)
++ doc_printf(doc, "\\%03o", *ptr);
++ else if (*ptr == '(' || *ptr == ')' || *ptr == '\\')
++ doc_printf(doc, "\\%c", *ptr);
++ else
++ doc_printf(doc, "%c", *ptr);
++ }
++ }
++
++ doc_puts(doc, ")put\n");
++
++ /*
++ * Then get a 14 point Helvetica-Bold font...
++ */
++
++ doc_puts(doc, "userdict/ESPpf /Helvetica-Bold findfont 14 scalefont put\n");
++
++ /*
++ * Finally, the procedure to write the labels on the page...
++ */
++
++ doc_puts(doc, "userdict/ESPwl{\n");
++ doc_puts(doc, " ESPpf setfont\n");
++ doc_printf(doc, " ESPpl stringwidth pop dup 12 add exch -0.5 mul %.0f add\n",
++ width * 0.5f);
++ doc_puts(doc, " 1 setgray\n");
++ doc_printf(doc, " dup 6 sub %.0f 3 index 20 ESPrf\n", bottom - 2.0);
++ doc_printf(doc, " dup 6 sub %.0f 3 index 20 ESPrf\n", top - 18.0);
++ doc_puts(doc, " 0 setgray\n");
++ doc_printf(doc, " dup 6 sub %.0f 3 index 20 ESPrs\n", bottom - 2.0);
++ doc_printf(doc, " dup 6 sub %.0f 3 index 20 ESPrs\n", top - 18.0);
++ doc_printf(doc, " dup %.0f moveto ESPpl show\n", bottom + 2.0);
++ doc_printf(doc, " %.0f moveto ESPpl show\n", top - 14.0);
++ doc_puts(doc, "pop\n");
++ doc_puts(doc, "}bind put\n");
++}
++
++
++/*
+ * 'write_labels()' - Write the actual page labels.
+ *
+ * This function is a copy of the one in common.c since we need to
Added: cupsys/branches/cups-1.2/debian/patches/00_02str2144.dpatch
==============================================================================
--- (empty file)
+++ cupsys/branches/cups-1.2/debian/patches/00_02str2144.dpatch Thu Dec 28 14:48:31 2006
@@ -0,0 +1,19 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 00_02str2144.dpatch by Kenshi Muto <kmuto at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad cupsys-1.2.7~/scheduler/job.c cupsys-1.2.7/scheduler/job.c
+--- cupsys-1.2.7~/scheduler/job.c 2006-10-23 00:26:52.000000000 +0000
++++ cupsys-1.2.7/scheduler/job.c 2006-12-28 13:00:34.000000000 +0000
+@@ -1497,7 +1497,7 @@
+ */
+
+ if (job->hold_until < curtime)
+- job->hold_until += 24 * 60 * 60 * 60;
++ job->hold_until += 24 * 60 * 60;
+ }
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2, "cupsdSetJobHoldUntil: hold_until = %d",
Added: cupsys/branches/cups-1.2/debian/patches/00_03str2106.dpatch
==============================================================================
--- (empty file)
+++ cupsys/branches/cups-1.2/debian/patches/00_03str2106.dpatch Thu Dec 28 14:48:31 2006
@@ -0,0 +1,19 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 00_03str2106.dpatch by Kenshi Muto <kmuto at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad cupsys-1.2.7~/filter/image-pnm.c cupsys-1.2.7/filter/image-pnm.c
+--- cupsys-1.2.7~/filter/image-pnm.c 2006-12-28 12:00:51.000000000 +0000
++++ cupsys-1.2.7/filter/image-pnm.c 2006-12-28 13:02:55.000000000 +0000
+@@ -202,7 +202,7 @@
+ else
+ {
+ bit = 128;
+- inptr ++;
++ outptr ++;
+ }
+ }
+ break;
Added: cupsys/branches/cups-1.2/debian/patches/00_04str2117.dpatch
==============================================================================
--- (empty file)
+++ cupsys/branches/cups-1.2/debian/patches/00_04str2117.dpatch Thu Dec 28 14:48:31 2006
@@ -0,0 +1,28 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 00_04str2117.dpatch by Kenshi Muto <kmuto at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad cupsys-1.2.7~/scheduler/conf.c cupsys-1.2.7/scheduler/conf.c
+--- cupsys-1.2.7~/scheduler/conf.c 2006-12-28 12:00:51.000000000 +0000
++++ cupsys-1.2.7/scheduler/conf.c 2006-12-28 13:06:05.000000000 +0000
+@@ -1316,7 +1316,7 @@
+ * Get the address...
+ */
+
+- ip[0] = ip[1] = ip[2] = ip[2] = 0x00000000;
++ ip[0] = ip[1] = ip[2] = ip[3] = 0x00000000;
+ mask[0] = mask[1] = mask[2] = mask[3] = 0xffffffff;
+
+ if ((maskval = strchr(value, '/')) != NULL)
+@@ -1501,7 +1501,7 @@
+
+ cupsdLogMessage(CUPSD_LOG_DEBUG2,
+ "get_addr_and_mask(value=\"%s\", "
+- "ip=[%08x:%08x:%08x:%08x], mask=[%08x:%08x:%08x:%08x]",
++ "ip=[%08x:%08x:%08x:%08x], mask=[%08x:%08x:%08x:%08x])",
+ value, ip[0], ip[1], ip[2], ip[3], mask[0], mask[1], mask[2],
+ mask[3]);
+
Added: cupsys/branches/cups-1.2/debian/patches/00_05str2133.dpatch
==============================================================================
--- (empty file)
+++ cupsys/branches/cups-1.2/debian/patches/00_05str2133.dpatch Thu Dec 28 14:48:31 2006
@@ -0,0 +1,3127 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 00_05str2133.dpatch by Kenshi Muto <kmuto at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad cupsys-1.2.7~/cups/http.c cupsys-1.2.7/cups/http.c
+--- cupsys-1.2.7~/cups/http.c 2006-12-28 12:00:51.000000000 +0000
++++ cupsys-1.2.7/cups/http.c 2006-12-28 13:09:06.000000000 +0000
+@@ -694,8 +694,18 @@
+ * after the transfer is complete...
+ */
+
+- if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0')
+- http->data_remaining = 2147483647;
++ if (!http->fields[HTTP_FIELD_CONTENT_LENGTH][0])
++ {
++ /*
++ * Default content length is 0 for errors and 2^31-1 for other
++ * successful requests...
++ */
++
++ if (http->status >= HTTP_MULTIPLE_CHOICES)
++ http->data_remaining = 0;
++ else
++ http->data_remaining = 2147483647;
++ }
+ else
+ http->data_remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
+ NULL, 10);
+diff -urNad cupsys-1.2.7~/cups/http.c.orig cupsys-1.2.7/cups/http.c.orig
+--- cupsys-1.2.7~/cups/http.c.orig 1970-01-01 00:00:00.000000000 +0000
++++ cupsys-1.2.7/cups/http.c.orig 2006-12-28 12:00:51.000000000 +0000
+@@ -0,0 +1,3092 @@
++/*
++ * "$Id: http.c 6111 2006-11-15 20:28:39Z mike $"
++ *
++ * HTTP routines for the Common UNIX Printing System (CUPS).
++ *
++ * Copyright 1997-2006 by Easy Software Products, all rights reserved.
++ *
++ * These coded instructions, statements, and computer programs are the
++ * property of Easy Software Products and are protected by Federal
++ * copyright law. Distribution and use rights are outlined in the file
++ * "LICENSE.txt" which should have been included with this file. If this
++ * file is missing or damaged please contact Easy Software Products
++ * at:
++ *
++ * Attn: CUPS Licensing Information
++ * Easy Software Products
++ * 44141 Airport View Drive, Suite 204
++ * Hollywood, Maryland 20636 USA
++ *
++ * Voice: (301) 373-9600
++ * EMail: cups-info at cups.org
++ * WWW: http://www.cups.org
++ *
++ * This file is subject to the Apple OS-Developed Software exception.
++ *
++ * Contents:
++ *
++ * _httpBIOMethods() - Get the OpenSSL BIO methods for HTTP connections.
++ * httpBlocking() - Set blocking/non-blocking behavior on a connection.
++ * httpCheck() - Check to see if there is a pending response from
++ * the server.
++ * httpClearCookie() - Clear the cookie value(s).
++ * httpClearFields() - Clear HTTP request fields.
++ * httpClose() - Close an HTTP connection...
++ * httpConnect() - Connect to a HTTP server.
++ * httpConnectEncrypt() - Connect to a HTTP server using encryption.
++ * httpDelete() - Send a DELETE request to the server.
++ * httpEncryption() - Set the required encryption on the link.
++ * httpError() - Get the last error on a connection.
++ * httpFlush() - Flush data from a HTTP connection.
++ * httpFlushWrite() - Flush data in write buffer.
++ * httpGet() - Send a GET request to the server.
++ * httpGetBlocking() - Get the blocking/non-block state of a connection.
++ * httpGetCookie() - Get any cookie data from the response.
++ * httpGetFd() - Get the file descriptor associated with a
++ * connection.
++ * httpGetField() - Get a field value from a request/response.
++ * httpGetLength() - Get the amount of data remaining from the
++ * content-length or transfer-encoding fields.
++ * httpGetLength2() - Get the amount of data remaining from the
++ * content-length or transfer-encoding fields.
++ * httpGetStatus() - Get the status of the last HTTP request.
++ * httpGetSubField() - Get a sub-field value.
++ * httpGets() - Get a line of text from a HTTP connection.
++ * httpHead() - Send a HEAD request to the server.
++ * httpInitialize() - Initialize the HTTP interface library and set the
++ * default HTTP proxy (if any).
++ * httpOptions() - Send an OPTIONS request to the server.
++ * httpPost() - Send a POST request to the server.
++ * httpPrintf() - Print a formatted string to a HTTP connection.
++ * httpPut() - Send a PUT request to the server.
++ * httpRead() - Read data from a HTTP connection.
++ * httpRead2() - Read data from a HTTP connection.
++ * _httpReadCDSA() - Read function for the CDSA library.
++ * _httpReadGNUTLS() - Read function for the GNU TLS library.
++ * httpReconnect() - Reconnect to a HTTP server...
++ * httpSetCookie() - Set the cookie value(s)...
++ * httpSetExpect() - Set the Expect: header in a request.
++ * httpSetField() - Set the value of an HTTP header.
++ * httpSetLength() - Set the content-length and transfer-encoding.
++ * httpTrace() - Send an TRACE request to the server.
++ * httpUpdate() - Update the current HTTP state for incoming data.
++ * httpWait() - Wait for data available on a connection.
++ * httpWrite() - Write data to a HTTP connection.
++ * httpWrite2() - Write data to a HTTP connection.
++ * _httpWriteCDSA() - Write function for the CDSA library.
++ * _httpWriteGNUTLS() - Write function for the GNU TLS library.
++ * http_bio_ctrl() - Control the HTTP connection.
++ * http_bio_free() - Free OpenSSL data.
++ * http_bio_new() - Initialize an OpenSSL BIO structure.
++ * http_bio_puts() - Send a string for OpenSSL.
++ * http_bio_read() - Read data for OpenSSL.
++ * http_bio_write() - Write data for OpenSSL.
++ * http_field() - Return the field index for a field name.
++ * http_read_ssl() - Read from a SSL/TLS connection.
++ * http_send() - Send a request with all fields and the trailing
++ * blank line.
++ * http_setup_ssl() - Set up SSL/TLS on a connection.
++ * http_shutdown_ssl() - Shut down SSL/TLS on a connection.
++ * http_upgrade() - Force upgrade to TLS encryption.
++ * http_wait() - Wait for data available on a connection.
++ * http_write() - Write data to a connection.
++ * http_write_ssl() - Write to a SSL/TLS connection.
++ */
++
++/*
++ * Include necessary headers...
++ */
++
++#include "http-private.h"
++#include "globals.h"
++#include "debug.h"
++#include <stdlib.h>
++#include <fcntl.h>
++#include <errno.h>
++#ifndef WIN32
++# include <signal.h>
++# include <sys/time.h>
++# include <sys/resource.h>
++#endif /* !WIN32 */
++
++
++/*
++ * Some operating systems have done away with the Fxxxx constants for
++ * the fcntl() call; this works around that "feature"...
++ */
++
++#ifndef FNONBLK
++# define FNONBLK O_NONBLOCK
++#endif /* !FNONBLK */
++
++
++/*
++ * Local functions...
++ */
++
++static http_field_t http_field(const char *name);
++static int http_send(http_t *http, http_state_t request,
++ const char *uri);
++static int http_wait(http_t *http, int msec, int usessl);
++static int http_write(http_t *http, const char *buffer,
++ int length);
++static int http_write_chunk(http_t *http, const char *buffer,
++ int length);
++#ifdef HAVE_SSL
++static int http_read_ssl(http_t *http, char *buf, int len);
++static int http_setup_ssl(http_t *http);
++static void http_shutdown_ssl(http_t *http);
++static int http_upgrade(http_t *http);
++static int http_write_ssl(http_t *http, const char *buf, int len);
++#endif /* HAVE_SSL */
++
++
++/*
++ * Local globals...
++ */
++
++static const char * const http_fields[] =
++ {
++ "Accept-Language",
++ "Accept-Ranges",
++ "Authorization",
++ "Connection",
++ "Content-Encoding",
++ "Content-Language",
++ "Content-Length",
++ "Content-Location",
++ "Content-MD5",
++ "Content-Range",
++ "Content-Type",
++ "Content-Version",
++ "Date",
++ "Host",
++ "If-Modified-Since",
++ "If-Unmodified-since",
++ "Keep-Alive",
++ "Last-Modified",
++ "Link",
++ "Location",
++ "Range",
++ "Referer",
++ "Retry-After",
++ "Transfer-Encoding",
++ "Upgrade",
++ "User-Agent",
++ "WWW-Authenticate"
++ };
++
++
++#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
++/*
++ * BIO methods for OpenSSL...
++ */
++
++static int http_bio_write(BIO *h, const char *buf, int num);
++static int http_bio_read(BIO *h, char *buf, int size);
++static int http_bio_puts(BIO *h, const char *str);
++static long http_bio_ctrl(BIO *h, int cmd, long arg1, void *arg2);
++static int http_bio_new(BIO *h);
++static int http_bio_free(BIO *data);
++
++static BIO_METHOD http_bio_methods =
++ {
++ BIO_TYPE_SOCKET,
++ "http",
++ http_bio_write,
++ http_bio_read,
++ http_bio_puts,
++ NULL, /* http_bio_gets, */
++ http_bio_ctrl,
++ http_bio_new,
++ http_bio_free,
++ NULL,
++ };
++
++
++/*
++ * '_httpBIOMethods()' - Get the OpenSSL BIO methods for HTTP connections.
++ */
++
++BIO_METHOD * /* O - BIO methods for OpenSSL */
++_httpBIOMethods(void)
++{
++ return (&http_bio_methods);
++}
++#endif /* HAVE_SSL && HAVE_LIBSSL */
++
++
++/*
++ * 'httpBlocking()' - Set blocking/non-blocking behavior on a connection.
++ */
++
++void
++httpBlocking(http_t *http, /* I - HTTP connection */
++ int b) /* I - 1 = blocking, 0 = non-blocking */
++{
++ if (http)
++ http->blocking = b;
++}
++
++
++/*
++ * 'httpCheck()' - Check to see if there is a pending response from the server.
++ */
++
++int /* O - 0 = no data, 1 = data available */
++httpCheck(http_t *http) /* I - HTTP connection */
++{
++ return (httpWait(http, 0));
++}
++
++
++/*
++ * 'httpClearCookie()' - Clear the cookie value(s).
++ *
++ * @since CUPS 1.1.19@
++ */
++
++void
++httpClearCookie(http_t *http) /* I - HTTP connection */
++{
++ if (!http)
++ return;
++
++ if (http->cookie)
++ {
++ free(http->cookie);
++ http->cookie = NULL;
++ }
++}
++
++
++/*
++ * 'httpClearFields()' - Clear HTTP request fields.
++ */
++
++void
++httpClearFields(http_t *http) /* I - HTTP connection */
++{
++ if (http)
++ {
++ memset(http->fields, 0, sizeof(http->fields));
++ if (http->hostname[0] == '/')
++ httpSetField(http, HTTP_FIELD_HOST, "localhost");
++ else
++ httpSetField(http, HTTP_FIELD_HOST, http->hostname);
++
++ http->expect = (http_status_t)0;
++ }
++}
++
++
++/*
++ * 'httpClose()' - Close an HTTP connection...
++ */
++
++void
++httpClose(http_t *http) /* I - HTTP connection */
++{
++ DEBUG_printf(("httpClose(http=%p)\n", http));
++
++ if (!http)
++ return;
++
++ httpAddrFreeList(http->addrlist);
++
++ if (http->input_set)
++ free(http->input_set);
++
++ if (http->cookie)
++ free(http->cookie);
++
++#ifdef HAVE_SSL
++ if (http->tls)
++ http_shutdown_ssl(http);
++#endif /* HAVE_SSL */
++
++#ifdef WIN32
++ closesocket(http->fd);
++#else
++ close(http->fd);
++#endif /* WIN32 */
++
++ free(http);
++}
++
++
++/*
++ * 'httpConnect()' - Connect to a HTTP server.
++ */
++
++http_t * /* O - New HTTP connection */
++httpConnect(const char *host, /* I - Host to connect to */
++ int port) /* I - Port number */
++{
++ http_encryption_t encryption; /* Type of encryption to use */
++
++
++ /*
++ * Set the default encryption status...
++ */
++
++ if (port == 443)
++ encryption = HTTP_ENCRYPT_ALWAYS;
++ else
++ encryption = HTTP_ENCRYPT_IF_REQUESTED;
++
++ return (httpConnectEncrypt(host, port, encryption));
++}
++
++
++/*
++ * 'httpConnectEncrypt()' - Connect to a HTTP server using encryption.
++ */
++
++http_t * /* O - New HTTP connection */
++httpConnectEncrypt(
++ const char *host, /* I - Host to connect to */
++ int port, /* I - Port number */
++ http_encryption_t encryption) /* I - Type of encryption to use */
++{
++ http_t *http; /* New HTTP connection */
++ http_addrlist_t *addrlist; /* Host address data */
++ char service[255]; /* Service name */
++
++
++ DEBUG_printf(("httpConnectEncrypt(host=\"%s\", port=%d, encryption=%d)\n",
++ host ? host : "(null)", port, encryption));
++
++ if (!host)
++ return (NULL);
++
++ httpInitialize();
++
++ /*
++ * Lookup the host...
++ */
++
++ sprintf(service, "%d", port);
++
++ if ((addrlist = httpAddrGetList(host, AF_UNSPEC, service)) == NULL)
++ return (NULL);
++
++ /*
++ * Allocate memory for the structure...
++ */
++
++ http = calloc(sizeof(http_t), 1);
++ if (http == NULL)
++ return (NULL);
++
++ http->version = HTTP_1_1;
++ http->blocking = 1;
++ http->activity = time(NULL);
++ http->fd = -1;
++
++ /*
++ * Set the encryption status...
++ */
++
++ if (port == 443) /* Always use encryption for https */
++ http->encryption = HTTP_ENCRYPT_ALWAYS;
++ else
++ http->encryption = encryption;
++
++ /*
++ * Loop through the addresses we have until one of them connects...
++ */
++
++ strlcpy(http->hostname, host, sizeof(http->hostname));
++
++ /*
++ * Connect to the remote system...
++ */
++
++ http->addrlist = addrlist;
++
++ if (!httpReconnect(http))
++ return (http);
++
++ /*
++ * Could not connect to any known address - bail out!
++ */
++
++ httpAddrFreeList(addrlist);
++
++ free(http);
++
++ return (NULL);
++}
++
++
++/*
++ * 'httpDelete()' - Send a DELETE request to the server.
++ */
++
++int /* O - Status of call (0 = success) */
++httpDelete(http_t *http, /* I - HTTP connection */
++ const char *uri) /* I - URI to delete */
++{
++ return (http_send(http, HTTP_DELETE, uri));
++}
++
++
++/*
++ * 'httpEncryption()' - Set the required encryption on the link.
++ */
++
++int /* O - -1 on error, 0 on success */
++httpEncryption(http_t *http, /* I - HTTP connection */
++ http_encryption_t e) /* I - New encryption preference */
++{
++ DEBUG_printf(("httpEncryption(http=%p, e=%d)\n", http, e));
++
++#ifdef HAVE_SSL
++ if (!http)
++ return (0);
++
++ http->encryption = e;
++
++ if ((http->encryption == HTTP_ENCRYPT_ALWAYS && !http->tls) ||
++ (http->encryption == HTTP_ENCRYPT_NEVER && http->tls))
++ return (httpReconnect(http));
++ else if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
++ return (http_upgrade(http));
++ else
++ return (0);
++#else
++ if (e == HTTP_ENCRYPT_ALWAYS || e == HTTP_ENCRYPT_REQUIRED)
++ return (-1);
++ else
++ return (0);
++#endif /* HAVE_SSL */
++}
++
++
++/*
++ * 'httpError()' - Get the last error on a connection.
++ */
++
++int /* O - Error code (errno) value */
++httpError(http_t *http) /* I - HTTP connection */
++{
++ if (http)
++ return (http->error);
++ else
++ return (EINVAL);
++}
++
++
++/*
++ * 'httpFlush()' - Flush data from a HTTP connection.
++ */
++
++void
++httpFlush(http_t *http) /* I - HTTP connection */
++{
++ char buffer[8192]; /* Junk buffer */
++ int blocking; /* To block or not to block */
++
++
++ DEBUG_printf(("httpFlush(http=%p), state=%d\n", http, http->state));
++
++ /*
++ * Temporarily set non-blocking mode so we don't get stuck in httpRead()...
++ */
++
++ blocking = http->blocking;
++ http->blocking = 0;
++
++ /*
++ * Read any data we can...
++ */
++
++ while (httpRead2(http, buffer, sizeof(buffer)) > 0);
++
++ /*
++ * Restore blocking and reset the connection if we didn't get all of
++ * the remaining data...
++ */
++
++ http->blocking = blocking;
++
++ if (http->state != HTTP_WAITING && http->fd >= 0)
++ {
++ /*
++ * Didn't get the data back, so close the current connection.
++ */
++
++ http->state = HTTP_WAITING;
++
++#ifdef HAVE_SSL
++ if (http->tls)
++ http_shutdown_ssl(http);
++#endif /* HAVE_SSL */
++
++#ifdef WIN32
++ closesocket(http->fd);
++#else
++ close(http->fd);
++#endif /* WIN32 */
++
++ http->fd = -1;
++ }
++}
++
++
++/*
++ * 'httpFlushWrite()' - Flush data in write buffer.
++ *
++ * @since CUPS 1.2@
++ */
++
++int /* O - Bytes written or -1 on error */
++httpFlushWrite(http_t *http) /* I - HTTP connection */
++{
++ int bytes; /* Bytes written */
++
++
++ DEBUG_printf(("httpFlushWrite(http=%p)\n", http));
++
++ if (!http || !http->wused)
++ return (0);
++
++ if (http->data_encoding == HTTP_ENCODE_CHUNKED)
++ bytes = http_write_chunk(http, http->wbuffer, http->wused);
++ else
++ bytes = http_write(http, http->wbuffer, http->wused);
++
++ http->wused = 0;
++
++ return (bytes);
++}
++
++
++/*
++ * 'httpGet()' - Send a GET request to the server.
++ */
++
++int /* O - Status of call (0 = success) */
++httpGet(http_t *http, /* I - HTTP connection */
++ const char *uri) /* I - URI to get */
++{
++ return (http_send(http, HTTP_GET, uri));
++}
++
++
++/*
++ * 'httpGetBlocking()' - Get the blocking/non-block state of a connection.
++ *
++ * @since CUPS 1.2@
++ */
++
++int /* O - 1 if blocking, 0 if non-blocking */
++httpGetBlocking(http_t *http) /* I - HTTP connection */
++{
++ return (http ? http->blocking : 0);
++}
++
++
++/*
++ * 'httpGetCookie()' - Get any cookie data from the response.
++ *
++ * @since CUPS 1.1.19@
++ */
++
++const char * /* O - Cookie data or NULL */
++httpGetCookie(http_t *http) /* I - HTTP connecion */
++{
++ return (http ? http->cookie : NULL);
++}
++
++
++/*
++ * 'httpGetFd()' - Get the file descriptor associated with a connection.
++ *
++ * @since CUPS 1.2@
++ */
++
++int /* O - File descriptor or -1 if none */
++httpGetFd(http_t *http) /* I - HTTP connection */
++{
++ return (http ? http->fd : -1);
++}
++
++
++/*
++ * 'httpGetField()' - Get a field value from a request/response.
++ */
++
++const char * /* O - Field value */
++httpGetField(http_t *http, /* I - HTTP connection */
++ http_field_t field) /* I - Field to get */
++{
++ if (!http || field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
++ return (NULL);
++ else
++ return (http->fields[field]);
++}
++
++
++/*
++ * 'httpGetLength()' - Get the amount of data remaining from the
++ * content-length or transfer-encoding fields.
++ *
++ * This function is deprecated and will not return lengths larger than
++ * 2^31 - 1; use httpGetLength2() instead.
++ *
++ * @deprecated@
++ */
++
++int /* O - Content length */
++httpGetLength(http_t *http) /* I - HTTP connection */
++{
++ /*
++ * Get the read content length and return the 32-bit value.
++ */
++
++ if (http)
++ {
++ httpGetLength2(http);
++
++ return (http->_data_remaining);
++ }
++ else
++ return (-1);
++}
++
++
++/*
++ * 'httpGetLength2()' - Get the amount of data remaining from the
++ * content-length or transfer-encoding fields.
++ *
++ * This function returns the complete content length, even for
++ * content larger than 2^31 - 1.
++ *
++ * @since CUPS 1.2@
++ */
++
++off_t /* O - Content length */
++httpGetLength2(http_t *http) /* I - HTTP connection */
++{
++ DEBUG_printf(("httpGetLength2(http=%p), state=%d\n", http, http->state));
++
++ if (!http)
++ return (-1);
++
++ if (!strcasecmp(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked"))
++ {
++ DEBUG_puts("httpGetLength2: chunked request!");
++
++ http->data_encoding = HTTP_ENCODE_CHUNKED;
++ http->data_remaining = 0;
++ }
++ else
++ {
++ http->data_encoding = HTTP_ENCODE_LENGTH;
++
++ /*
++ * The following is a hack for HTTP servers that don't send a
++ * content-length or transfer-encoding field...
++ *
++ * If there is no content-length then the connection must close
++ * after the transfer is complete...
++ */
++
++ if (http->fields[HTTP_FIELD_CONTENT_LENGTH][0] == '\0')
++ http->data_remaining = 2147483647;
++ else
++ http->data_remaining = strtoll(http->fields[HTTP_FIELD_CONTENT_LENGTH],
++ NULL, 10);
++
++ DEBUG_printf(("httpGetLength2: content_length=" CUPS_LLFMT "\n",
++ CUPS_LLCAST http->data_remaining));
++ }
++
++ if (http->data_remaining <= INT_MAX)
++ http->_data_remaining = (int)http->data_remaining;
++ else
++ http->_data_remaining = INT_MAX;
++
++ return (http->data_remaining);
++}
++
++
++/*
++ * 'httpGetStatus()' - Get the status of the last HTTP request.
++ *
++ * @since CUPS 1.2@
++ */
++
++http_status_t /* O - HTTP status */
++httpGetStatus(http_t *http) /* I - HTTP connection */
++{
++ return (http ? http->status : HTTP_ERROR);
++}
++
++
++/*
++ * 'httpGetSubField()' - Get a sub-field value.
++ *
++ * @deprecated@
++ */
++
++char * /* O - Value or NULL */
++httpGetSubField(http_t *http, /* I - HTTP connection */
++ http_field_t field, /* I - Field index */
++ const char *name, /* I - Name of sub-field */
++ char *value) /* O - Value string */
++{
++ return (httpGetSubField2(http, field, name, value, HTTP_MAX_VALUE));
++}
++
++
++/*
++ * 'httpGetSubField2()' - Get a sub-field value.
++ *
++ * @since CUPS 1.2@
++ */
++
++char * /* O - Value or NULL */
++httpGetSubField2(http_t *http, /* I - HTTP connection */
++ http_field_t field, /* I - Field index */
++ const char *name, /* I - Name of sub-field */
++ char *value, /* O - Value string */
++ int valuelen) /* I - Size of value buffer */
++{
++ const char *fptr; /* Pointer into field */
++ char temp[HTTP_MAX_VALUE], /* Temporary buffer for name */
++ *ptr, /* Pointer into string buffer */
++ *end; /* End of value buffer */
++
++ DEBUG_printf(("httpGetSubField2(http=%p, field=%d, name=\"%s\", value=%p, valuelen=%d)\n",
++ http, field, name, value, valuelen));
++
++ if (!http || !name || !value || valuelen < 2 ||
++ field <= HTTP_FIELD_UNKNOWN || field >= HTTP_FIELD_MAX)
++ return (NULL);
++
++ end = value + valuelen - 1;
++
++ for (fptr = http->fields[field]; *fptr;)
++ {
++ /*
++ * Skip leading whitespace...
++ */
++
++ while (isspace(*fptr & 255))
++ fptr ++;
++
++ if (*fptr == ',')
++ {
++ fptr ++;
++ continue;
++ }
++
++ /*
++ * Get the sub-field name...
++ */
++
++ for (ptr = temp;
++ *fptr && *fptr != '=' && !isspace(*fptr & 255) &&
++ ptr < (temp + sizeof(temp) - 1);
++ *ptr++ = *fptr++);
++
++ *ptr = '\0';
++
++ DEBUG_printf(("httpGetSubField: name=\"%s\"\n", temp));
++
++ /*
++ * Skip trailing chars up to the '='...
++ */
++
++ while (isspace(*fptr & 255))
++ fptr ++;
++
++ if (!*fptr)
++ break;
++
++ if (*fptr != '=')
++ continue;
++
++ /*
++ * Skip = and leading whitespace...
++ */
++
++ fptr ++;
++
++ while (isspace(*fptr & 255))
++ fptr ++;
++
++ if (*fptr == '\"')
++ {
++ /*
++ * Read quoted string...
++ */
++
++ for (ptr = value, fptr ++;
++ *fptr && *fptr != '\"' && ptr < end;
++ *ptr++ = *fptr++);
++
++ *ptr = '\0';
++
++ while (*fptr && *fptr != '\"')
++ fptr ++;
++
++ if (*fptr)
++ fptr ++;
++ }
++ else
++ {
++ /*
++ * Read unquoted string...
++ */
++
++ for (ptr = value;
++ *fptr && !isspace(*fptr & 255) && *fptr != ',' && ptr < end;
++ *ptr++ = *fptr++);
++
++ *ptr = '\0';
++
++ while (*fptr && !isspace(*fptr & 255) && *fptr != ',')
++ fptr ++;
++ }
++
++ DEBUG_printf(("httpGetSubField: value=\"%s\"\n", value));
++
++ /*
++ * See if this is the one...
++ */
++
++ if (!strcmp(name, temp))
++ return (value);
++ }
++
++ value[0] = '\0';
++
++ return (NULL);
++}
++
++
++/*
++ * 'httpGets()' - Get a line of text from a HTTP connection.
++ */
++
++char * /* O - Line or NULL */
++httpGets(char *line, /* I - Line to read into */
++ int length, /* I - Max length of buffer */
++ http_t *http) /* I - HTTP connection */
++{
++ char *lineptr, /* Pointer into line */
++ *lineend, /* End of line */
++ *bufptr, /* Pointer into input buffer */
++ *bufend; /* Pointer to end of buffer */
++ int bytes, /* Number of bytes read */
++ eol; /* End-of-line? */
++
++
++ DEBUG_printf(("httpGets(line=%p, length=%d, http=%p)\n", line, length, http));
++
++ if (http == NULL || line == NULL)
++ return (NULL);
++
++ /*
++ * Read a line from the buffer...
++ */
++
++ lineptr = line;
++ lineend = line + length - 1;
++ eol = 0;
++
++ while (lineptr < lineend)
++ {
++ /*
++ * Pre-load the buffer as needed...
++ */
++
++#ifdef WIN32
++ WSASetLastError(0);
++#else
++ errno = 0;
++#endif /* WIN32 */
++
++ while (http->used == 0)
++ {
++ /*
++ * No newline; see if there is more data to be read...
++ */
++
++ if (!http->blocking && !http_wait(http, 10000, 1))
++ {
++ DEBUG_puts("httpGets: Timed out!");
++ http->error = ETIMEDOUT;
++ return (NULL);
++ }
++
++#ifdef HAVE_SSL
++ if (http->tls)
++ bytes = http_read_ssl(http, http->buffer + http->used,
++ HTTP_MAX_BUFFER - http->used);
++ else
++#endif /* HAVE_SSL */
++ bytes = recv(http->fd, http->buffer + http->used,
++ HTTP_MAX_BUFFER - http->used, 0);
++
++ DEBUG_printf(("httpGets: read %d bytes...\n", bytes));
++
++ if (bytes < 0)
++ {
++ /*
++ * Nope, can't get a line this time...
++ */
++
++#ifdef WIN32
++ if (WSAGetLastError() != http->error)
++ {
++ http->error = WSAGetLastError();
++ continue;
++ }
++
++ DEBUG_printf(("httpGets: recv() error %d!\n", WSAGetLastError()));
++#else
++ DEBUG_printf(("httpGets: recv() error %d!\n", errno));
++
++ if (errno == EINTR)
++ continue;
++ else if (errno != http->error)
++ {
++ http->error = errno;
++ continue;
++ }
++#endif /* WIN32 */
++
++ return (NULL);
++ }
++ else if (bytes == 0)
++ {
++ http->error = EPIPE;
++
++ return (NULL);
++ }
++
++ /*
++ * Yup, update the amount used...
++ */
++
++ http->used += bytes;
++ }
++
++ /*
++ * Now copy as much of the current line as possible...
++ */
++
++ for (bufptr = http->buffer, bufend = http->buffer + http->used;
++ lineptr < lineend && bufptr < bufend;)
++ {
++ if (*bufptr == 0x0a)
++ {
++ eol = 1;
++ bufptr ++;
++ break;
++ }
++ else if (*bufptr == 0x0d)
++ bufptr ++;
++ else
++ *lineptr++ = *bufptr++;
++ }
++
++ http->used -= bufptr - http->buffer;
++ if (http->used > 0)
++ memmove(http->buffer, bufptr, http->used);
++
++ if (eol)
++ {
++ /*
++ * End of line...
++ */
++
++ http->activity = time(NULL);
++
++ *lineptr = '\0';
++
++ DEBUG_printf(("httpGets: Returning \"%s\"\n", line));
++
++ return (line);
++ }
++ }
++
++ DEBUG_puts("httpGets: No new line available!");
++
++ return (NULL);
++}
++
++
++/*
++ * 'httpHead()' - Send a HEAD request to the server.
++ */
++
++int /* O - Status of call (0 = success) */
++httpHead(http_t *http, /* I - HTTP connection */
++ const char *uri) /* I - URI for head */
++{
++ return (http_send(http, HTTP_HEAD, uri));
++}
++
++
++/*
++ * 'httpInitialize()' - Initialize the HTTP interface library and set the
++ * default HTTP proxy (if any).
++ */
++
++void
++httpInitialize(void)
++{
++#ifdef HAVE_LIBSSL
++# ifndef WIN32
++ struct timeval curtime; /* Current time in microseconds */
++# endif /* !WIN32 */
++ int i; /* Looping var */
++ unsigned char data[1024]; /* Seed data */
++#endif /* HAVE_LIBSSL */
++
++#ifdef WIN32
++ WSADATA winsockdata; /* WinSock data */
++ static int initialized = 0; /* Has WinSock been initialized? */
++
++
++ if (!initialized)
++ WSAStartup(MAKEWORD(1,1), &winsockdata);
++#elif !defined(SO_NOSIGPIPE)
++ /*
++ * Ignore SIGPIPE signals...
++ */
++
++# ifdef HAVE_SIGSET
++ sigset(SIGPIPE, SIG_IGN);
++# elif defined(HAVE_SIGACTION)
++ struct sigaction action; /* POSIX sigaction data */
++
++
++ memset(&action, 0, sizeof(action));
++ action.sa_handler = SIG_IGN;
++ sigaction(SIGPIPE, &action, NULL);
++# else
++ signal(SIGPIPE, SIG_IGN);
++# endif /* !SO_NOSIGPIPE */
++#endif /* WIN32 */
++
++#ifdef HAVE_GNUTLS
++ gnutls_global_init();
++#endif /* HAVE_GNUTLS */
++
++#ifdef HAVE_LIBSSL
++ SSL_load_error_strings();
++ SSL_library_init();
++
++ /*
++ * Using the current time is a dubious random seed, but on some systems
++ * it is the best we can do (on others, this seed isn't even used...)
++ */
++
++#ifdef WIN32
++#else
++ gettimeofday(&curtime, NULL);
++ srand(curtime.tv_sec + curtime.tv_usec);
++#endif /* WIN32 */
++
++ for (i = 0; i < sizeof(data); i ++)
++ data[i] = rand(); /* Yes, this is a poor source of random data... */
++
++ RAND_seed(&data, sizeof(data));
++#endif /* HAVE_LIBSSL */
++}
++
++
++/*
++ * 'httpOptions()' - Send an OPTIONS request to the server.
++ */
++
++int /* O - Status of call (0 = success) */
++httpOptions(http_t *http, /* I - HTTP connection */
++ const char *uri) /* I - URI for options */
++{
++ return (http_send(http, HTTP_OPTIONS, uri));
++}
++
++
++/*
++ * 'httpPost()' - Send a POST request to the server.
++ */
++
++int /* O - Status of call (0 = success) */
++httpPost(http_t *http, /* I - HTTP connection */
++ const char *uri) /* I - URI for post */
++{
++ return (http_send(http, HTTP_POST, uri));
++}
++
++
++/*
++ * 'httpPrintf()' - Print a formatted string to a HTTP connection.
++ *
++ * @private@
++ */
++
++int /* O - Number of bytes written */
++httpPrintf(http_t *http, /* I - HTTP connection */
++ const char *format, /* I - printf-style format string */
++ ...) /* I - Additional args as needed */
++{
++ int bytes; /* Number of bytes to write */
++ char buf[16384]; /* Buffer for formatted string */
++ va_list ap; /* Variable argument pointer */
++
++
++ DEBUG_printf(("httpPrintf(http=%p, format=\"%s\", ...)\n", http, format));
++
++ va_start(ap, format);
++ bytes = vsnprintf(buf, sizeof(buf), format, ap);
++ va_end(ap);
++
++ DEBUG_printf(("httpPrintf: %s", buf));
++
++ if (http->data_encoding == HTTP_ENCODE_FIELDS)
++ return (httpWrite2(http, buf, bytes));
++ else
++ {
++ if (http->wused)
++ {
++ DEBUG_puts(" flushing existing data...");
++
++ if (httpFlushWrite(http) < 0)
++ return (-1);
++ }
++
++ return (http_write(http, buf, bytes));
++ }
++}
++
++
++/*
++ * 'httpPut()' - Send a PUT request to the server.
++ */
++
++int /* O - Status of call (0 = success) */
++httpPut(http_t *http, /* I - HTTP connection */
++ const char *uri) /* I - URI to put */
++{
++ return (http_send(http, HTTP_PUT, uri));
++}
++
++
++/*
++ * 'httpRead()' - Read data from a HTTP connection.
++ *
++ * This function is deprecated. Use the httpRead2() function which can
++ * read more than 2GB of data.
++ *
++ * @deprecated@
++ */
++
++int /* O - Number of bytes read */
++httpRead(http_t *http, /* I - HTTP connection */
++ char *buffer, /* I - Buffer for data */
++ int length) /* I - Maximum number of bytes */
++{
++ return ((int)httpRead2(http, buffer, length));
++}
++
++
++/*
++ * 'httpRead2()' - Read data from a HTTP connection.
++ *
++ * @since CUPS 1.2@
++ */
++
++ssize_t /* O - Number of bytes read */
++httpRead2(http_t *http, /* I - HTTP connection */
++ char *buffer, /* I - Buffer for data */
++ size_t length) /* I - Maximum number of bytes */
++{
++ ssize_t bytes; /* Bytes read */
++ char len[32]; /* Length string */
++
++
++ DEBUG_printf(("httpRead(http=%p, buffer=%p, length=%d)\n",
++ http, buffer, length));
++
++ if (http == NULL || buffer == NULL)
++ return (-1);
++
++ http->activity = time(NULL);
++
++ if (length <= 0)
++ return (0);
++
++ if (http->data_encoding == HTTP_ENCODE_CHUNKED &&
++ http->data_remaining <= 0)
++ {
++ DEBUG_puts("httpRead2: Getting chunk length...");
++
++ if (httpGets(len, sizeof(len), http) == NULL)
++ {
++ DEBUG_puts("httpRead2: Could not get length!");
++ return (0);
++ }
++
++ http->data_remaining = strtoll(len, NULL, 16);
++ if (http->data_remaining < 0)
++ {
++ DEBUG_puts("httpRead2: Negative chunk length!");
++ return (0);
++ }
++ }
++
++ DEBUG_printf(("httpRead2: data_remaining=" CUPS_LLFMT "\n",
++ CUPS_LLCAST http->data_remaining));
++
++ if (http->data_remaining <= 0)
++ {
++ /*
++ * A zero-length chunk ends a transfer; unless we are reading POST
++ * data, go idle...
++ */
++
++ if (http->data_encoding == HTTP_ENCODE_CHUNKED)
++ httpGets(len, sizeof(len), http);
++
++ if (http->state == HTTP_POST_RECV)
++ http->state ++;
++ else
++ http->state = HTTP_WAITING;
++
++ /*
++ * Prevent future reads for this request...
++ */
++
++ http->data_encoding = HTTP_ENCODE_LENGTH;
++
++ return (0);
++ }
++ else if (length > http->data_remaining)
++ length = http->data_remaining;
++
++ if (http->used == 0 && length <= 256)
++ {
++ /*
++ * Buffer small reads for better performance...
++ */
++
++ if (!http->blocking && !httpWait(http, 10000))
++ return (0);
++
++ if (http->data_remaining > sizeof(http->buffer))
++ bytes = sizeof(http->buffer);
++ else
++ bytes = http->data_remaining;
++
++#ifdef HAVE_SSL
++ if (http->tls)
++ bytes = http_read_ssl(http, http->buffer, bytes);
++ else
++#endif /* HAVE_SSL */
++ {
++ DEBUG_printf(("httpRead2: reading %d bytes from socket into buffer...\n",
++ bytes));
++
++ bytes = recv(http->fd, http->buffer, bytes, 0);
++
++ DEBUG_printf(("httpRead2: read %d bytes from socket into buffer...\n",
++ bytes));
++ }
++
++ if (bytes > 0)
++ http->used = bytes;
++ else if (bytes < 0)
++ {
++#ifdef WIN32
++ http->error = WSAGetLastError();
++ return (-1);
++#else
++ if (errno != EINTR)
++ {
++ http->error = errno;
++ return (-1);
++ }
++#endif /* WIN32 */
++ }
++ else
++ {
++ http->error = EPIPE;
++ return (0);
++ }
++ }
++
++ if (http->used > 0)
++ {
++ if (length > http->used)
++ length = http->used;
++
++ bytes = length;
++
++ DEBUG_printf(("httpRead2: grabbing %d bytes from input buffer...\n", bytes));
++
++ memcpy(buffer, http->buffer, length);
++ http->used -= length;
++
++ if (http->used > 0)
++ memmove(http->buffer, http->buffer + length, http->used);
++ }
++#ifdef HAVE_SSL
++ else if (http->tls)
++ {
++ if (!http->blocking && !httpWait(http, 10000))
++ return (0);
++
++ bytes = http_read_ssl(http, buffer, length);
++ }
++#endif /* HAVE_SSL */
++ else
++ {
++ if (!http->blocking && !httpWait(http, 10000))
++ return (0);
++
++ DEBUG_printf(("httpRead2: reading %d bytes from socket...\n", length));
++
++ while ((bytes = recv(http->fd, buffer, length, 0)) < 0)
++ if (errno != EINTR)
++ break;
++
++ DEBUG_printf(("httpRead2: read %d bytes from socket...\n", bytes));
++ }
++
++ if (bytes > 0)
++ {
++ http->data_remaining -= bytes;
++
++ if (http->data_remaining <= INT_MAX)
++ http->_data_remaining = (int)http->data_remaining;
++ else
++ http->_data_remaining = INT_MAX;
++ }
++ else if (bytes < 0)
++ {
++#ifdef WIN32
++ http->error = WSAGetLastError();
++#else
++ if (errno == EINTR)
++ bytes = 0;
++ else
++ http->error = errno;
++#endif /* WIN32 */
++ }
++ else
++ {
++ http->error = EPIPE;
++ return (0);
++ }
++
++ if (http->data_remaining == 0)
++ {
++ if (http->data_encoding == HTTP_ENCODE_CHUNKED)
++ httpGets(len, sizeof(len), http);
++
++ if (http->data_encoding != HTTP_ENCODE_CHUNKED)
++ {
++ if (http->state == HTTP_POST_RECV)
++ http->state ++;
++ else
++ http->state = HTTP_WAITING;
++ }
++ }
++
++#ifdef DEBUG
++ {
++ int i, j, ch;
++ printf("httpRead2: Read %d bytes:\n", bytes);
++ for (i = 0; i < bytes; i += 16)
++ {
++ printf(" ");
++
++ for (j = 0; j < 16 && (i + j) < bytes; j ++)
++ printf(" %02X", buffer[i + j] & 255);
++
++ while (j < 16)
++ {
++ printf(" ");
++ j ++;
++ }
++
++ printf(" ");
++ for (j = 0; j < 16 && (i + j) < bytes; j ++)
++ {
++ ch = buffer[i + j] & 255;
++
++ if (ch < ' ' || ch >= 127)
++ ch = '.';
++
++ putchar(ch);
++ }
++ putchar('\n');
++ }
++ }
++#endif /* DEBUG */
++
++ return (bytes);
++}
++
++
++#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
++/*
++ * '_httpReadCDSA()' - Read function for the CDSA library.
++ */
++
++OSStatus /* O - -1 on error, 0 on success */
++_httpReadCDSA(
++ SSLConnectionRef connection, /* I - SSL/TLS connection */
++ void *data, /* I - Data buffer */
++ size_t *dataLength) /* IO - Number of bytes */
++{
++ OSStatus result; /* Return value */
++ ssize_t bytes; /* Number of bytes read */
++ http_t *http; /* HTTP connection */
++
++
++ http = (http_t *)connection;
++
++ if (!http->blocking)
++ {
++ /*
++ * Make sure we have data before we read...
++ */
++
++ if (!http_wait(http, 10000, 0))
++ {
++ http->error = ETIMEDOUT;
++ return (-1);
++ }
++ }
++
++ do
++ {
++ bytes = recv(http->fd, data, *dataLength, 0);
++ }
++ while (bytes == -1 && errno == EINTR);
++
++ if (bytes == *dataLength)
++ {
++ result = 0;
++ }
++ else if (bytes > 0)
++ {
++ *dataLength = bytes;
++ result = errSSLWouldBlock;
++ }
++ else
++ {
++ *dataLength = 0;
++
++ if (bytes == 0)
++ result = errSSLClosedGraceful;
++ else if (errno == EAGAIN)
++ result = errSSLWouldBlock;
++ else
++ result = errSSLClosedAbort;
++ }
++
++ return (result);
++}
++#endif /* HAVE_SSL && HAVE_CDSASSL */
++
++
++#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
++/*
++ * '_httpReadGNUTLS()' - Read function for the GNU TLS library.
++ */
++
++ssize_t /* O - Number of bytes read or -1 on error */
++_httpReadGNUTLS(
++ gnutls_transport_ptr ptr, /* I - HTTP connection */
++ void *data, /* I - Buffer */
++ size_t length) /* I - Number of bytes to read */
++{
++ http_t *http; /* HTTP connection */
++
++
++ http = (http_t *)ptr;
++
++ if (!http->blocking)
++ {
++ /*
++ * Make sure we have data before we read...
++ */
++
++ if (!http_wait(http, 10000, 0))
++ {
++ http->error = ETIMEDOUT;
++ return (-1);
++ }
++ }
++
++ return (recv(http->fd, data, length, 0));
++}
++#endif /* HAVE_SSL && HAVE_GNUTLS */
++
++
++/*
++ * 'httpReconnect()' - Reconnect to a HTTP server.
++ */
++
++int /* O - 0 on success, non-zero on failure */
++httpReconnect(http_t *http) /* I - HTTP connection */
++{
++ http_addrlist_t *addr; /* Connected address */
++
++
++ DEBUG_printf(("httpReconnect(http=%p)\n", http));
++
++ if (!http)
++ return (-1);
++
++#ifdef HAVE_SSL
++ if (http->tls)
++ http_shutdown_ssl(http);
++#endif /* HAVE_SSL */
++
++ /*
++ * Close any previously open socket...
++ */
++
++ if (http->fd >= 0)
++ {
++#ifdef WIN32
++ closesocket(http->fd);
++#else
++ close(http->fd);
++#endif /* WIN32 */
++
++ http->fd = -1;
++ }
++
++ /*
++ * Connect to the server...
++ */
++
++ if ((addr = httpAddrConnect(http->addrlist, &(http->fd))) == NULL)
++ {
++ /*
++ * Unable to connect...
++ */
++
++#ifdef WIN32
++ http->error = WSAGetLastError();
++#else
++ http->error = errno;
++#endif /* WIN32 */
++ http->status = HTTP_ERROR;
++
++ return (-1);
++ }
++
++ http->hostaddr = &(addr->addr);
++ http->error = 0;
++ http->status = HTTP_CONTINUE;
++
++#ifdef HAVE_SSL
++ if (http->encryption == HTTP_ENCRYPT_ALWAYS)
++ {
++ /*
++ * Always do encryption via SSL.
++ */
++
++ if (http_setup_ssl(http) != 0)
++ {
++#ifdef WIN32
++ closesocket(http->fd);
++#else
++ close(http->fd);
++#endif /* WIN32 */
++
++ return (-1);
++ }
++ }
++ else if (http->encryption == HTTP_ENCRYPT_REQUIRED)
++ return (http_upgrade(http));
++#endif /* HAVE_SSL */
++
++ return (0);
++}
++
++
++/*
++ * 'httpSetCookie()' - Set the cookie value(s)...
++ *
++ * @since CUPS 1.1.19@
++ */
++
++void
++httpSetCookie(http_t *http, /* I - Connection */
++ const char *cookie) /* I - Cookie string */
++{
++ if (!http)
++ return;
++
++ if (http->cookie)
++ free(http->cookie);
++
++ if (cookie)
++ http->cookie = strdup(cookie);
++ else
++ http->cookie = NULL;
++}
++
++
++/*
++ * 'httpSetExpect()' - Set the Expect: header in a request.
++ *
++ * Currently only HTTP_CONTINUE is supported for the "expect" argument.
++ *
++ * @since CUPS 1.2@
++ */
++
++void
++httpSetExpect(http_t *http, /* I - HTTP connection */
++ http_status_t expect) /* I - HTTP status to expect (HTTP_CONTINUE) */
++{
++ if (http)
++ http->expect = expect;
++}
++
++
++/*
++ * 'httpSetField()' - Set the value of an HTTP header.
++ */
++
++void
++httpSetField(http_t *http, /* I - HTTP connection */
++ http_field_t field, /* I - Field index */
++ const char *value) /* I - Value */
++{
++ if (http == NULL ||
++ field < HTTP_FIELD_ACCEPT_LANGUAGE ||
++ field > HTTP_FIELD_WWW_AUTHENTICATE ||
++ value == NULL)
++ return;
++
++ strlcpy(http->fields[field], value, HTTP_MAX_VALUE);
++}
++
++
++/*
++ * 'httpSetLength()' - Set the content-length and content-encoding.
++ *
++ * @since CUPS 1.2@
++ */
++
++void
++httpSetLength(http_t *http, /* I - HTTP connection */
++ size_t length) /* I - Length (0 for chunked) */
++{
++ if (!http)
++ return;
++
++ if (!length)
++ {
++ strcpy(http->fields[HTTP_FIELD_TRANSFER_ENCODING], "chunked");
++ http->fields[HTTP_FIELD_CONTENT_LENGTH][0] = '\0';
++ }
++ else
++ {
++ http->fields[HTTP_FIELD_TRANSFER_ENCODING][0] = '\0';
++ snprintf(http->fields[HTTP_FIELD_CONTENT_LENGTH], HTTP_MAX_VALUE,
++ CUPS_LLFMT, CUPS_LLCAST length);
++ }
++}
++
++
++/*
++ * 'httpTrace()' - Send an TRACE request to the server.
++ */
++
++int /* O - Status of call (0 = success) */
++httpTrace(http_t *http, /* I - HTTP connection */
++ const char *uri) /* I - URI for trace */
++{
++ return (http_send(http, HTTP_TRACE, uri));
++}
++
++
++/*
++ * 'httpUpdate()' - Update the current HTTP state for incoming data.
++ */
++
++http_status_t /* O - HTTP status */
++httpUpdate(http_t *http) /* I - HTTP connection */
++{
++ char line[32768], /* Line from connection... */
++ *value; /* Pointer to value on line */
++ http_field_t field; /* Field index */
++ int major, minor, /* HTTP version numbers */
++ status; /* Request status */
++
++
++ DEBUG_printf(("httpUpdate(http=%p), state=%d\n", http, http->state));
++
++ /*
++ * Flush pending data, if any...
++ */
++
++ if (http->wused)
++ {
++ DEBUG_puts(" flushing buffer...");
++
++ if (httpFlushWrite(http) < 0)
++ return (HTTP_ERROR);
++ }
++
++ /*
++ * If we haven't issued any commands, then there is nothing to "update"...
++ */
++
++ if (http->state == HTTP_WAITING)
++ return (HTTP_CONTINUE);
++
++ /*
++ * Grab all of the lines we can from the connection...
++ */
++
++ while (httpGets(line, sizeof(line), http) != NULL)
++ {
++ DEBUG_printf(("httpUpdate: Got \"%s\"\n", line));
++
++ if (line[0] == '\0')
++ {
++ /*
++ * Blank line means the start of the data section (if any). Return
++ * the result code, too...
++ *
++ * If we get status 100 (HTTP_CONTINUE), then we *don't* change states.
++ * Instead, we just return HTTP_CONTINUE to the caller and keep on
++ * tryin'...
++ */
++
++ if (http->status == HTTP_CONTINUE)
++ return (http->status);
++
++ if (http->status < HTTP_BAD_REQUEST)
++ http->digest_tries = 0;
++
++#ifdef HAVE_SSL
++ if (http->status == HTTP_SWITCHING_PROTOCOLS && !http->tls)
++ {
++ if (http_setup_ssl(http) != 0)
++ {
++# ifdef WIN32
++ closesocket(http->fd);
++# else
++ close(http->fd);
++# endif /* WIN32 */
++
++ return (HTTP_ERROR);
++ }
++
++ return (HTTP_CONTINUE);
++ }
++#endif /* HAVE_SSL */
++
++ httpGetLength2(http);
++
++ switch (http->state)
++ {
++ case HTTP_GET :
++ case HTTP_POST :
++ case HTTP_POST_RECV :
++ case HTTP_PUT :
++ http->state ++;
++ case HTTP_POST_SEND :
++ case HTTP_HEAD :
++ break;
++
++ default :
++ http->state = HTTP_WAITING;
++ break;
++ }
++
++ return (http->status);
++ }
++ else if (strncmp(line, "HTTP/", 5) == 0)
++ {
++ /*
++ * Got the beginning of a response...
++ */
++
++ if (sscanf(line, "HTTP/%d.%d%d", &major, &minor, &status) != 3)
++ return (HTTP_ERROR);
++
++ http->version = (http_version_t)(major * 100 + minor);
++ http->status = (http_status_t)status;
++ }
++ else if ((value = strchr(line, ':')) != NULL)
++ {
++ /*
++ * Got a value...
++ */
++
++ *value++ = '\0';
++ while (isspace(*value & 255))
++ value ++;
++
++ /*
++ * Be tolerants of servers that send unknown attribute fields...
++ */
++
++ if (!strcasecmp(line, "expect"))
++ {
++ /*
++ * "Expect: 100-continue" or similar...
++ */
++
++ http->expect = (http_status_t)atoi(value);
++ }
++ else if (!strcasecmp(line, "cookie"))
++ {
++ /*
++ * "Cookie: name=value[; name=value ...]" - replaces previous cookies...
++ */
++
++ httpSetCookie(http, value);
++ }
++ else if ((field = http_field(line)) == HTTP_FIELD_UNKNOWN)
++ {
++ DEBUG_printf(("httpUpdate: unknown field %s seen!\n", line));
++ continue;
++ }
++ else
++ httpSetField(http, field, value);
++ }
++ else
++ {
++ http->status = HTTP_ERROR;
++ return (HTTP_ERROR);
++ }
++ }
++
++ /*
++ * See if there was an error...
++ */
++
++ if (http->error == EPIPE && http->status > HTTP_CONTINUE)
++ return (http->status);
++
++ if (http->error)
++ {
++ DEBUG_printf(("httpUpdate: socket error %d - %s\n", http->error,
++ strerror(http->error)));
++ http->status = HTTP_ERROR;
++ return (HTTP_ERROR);
++ }
++
++ /*
++ * If we haven't already returned, then there is nothing new...
++ */
++
++ return (HTTP_CONTINUE);
++}
++
++
++/*
++ * 'httpWait()' - Wait for data available on a connection.
++ *
++ * @since CUPS 1.1.19@
++ */
++
++int /* O - 1 if data is available, 0 otherwise */
++httpWait(http_t *http, /* I - HTTP connection */
++ int msec) /* I - Milliseconds to wait */
++{
++ /*
++ * First see if there is data in the buffer...
++ */
++
++ if (http == NULL)
++ return (0);
++
++ if (http->used)
++ return (1);
++
++ /*
++ * Flush pending data, if any...
++ */
++
++ if (http->wused)
++ {
++ if (httpFlushWrite(http) < 0)
++ return (0);
++ }
++
++ /*
++ * If not, check the SSL/TLS buffers and do a select() on the connection...
++ */
++
++ return (http_wait(http, msec, 1));
++}
++
++
++/*
++ * 'httpWrite()' - Write data to a HTTP connection.
++ *
++ * This function is deprecated. Use the httpWrite2() function which can
++ * write more than 2GB of data.
++ *
++ * @deprecated@
++ */
++
++int /* O - Number of bytes written */
++httpWrite(http_t *http, /* I - HTTP connection */
++ const char *buffer, /* I - Buffer for data */
++ int length) /* I - Number of bytes to write */
++{
++ return ((int)httpWrite2(http, buffer, length));
++}
++
++
++/*
++ * 'httpWrite2()' - Write data to a HTTP connection.
++ *
++ * @since CUPS 1.2@
++ */
++
++ssize_t /* O - Number of bytes written */
++httpWrite2(http_t *http, /* I - HTTP connection */
++ const char *buffer, /* I - Buffer for data */
++ size_t length) /* I - Number of bytes to write */
++{
++ ssize_t bytes; /* Bytes written */
++
++
++ DEBUG_printf(("httpWrite(http=%p, buffer=%p, length=%d)\n", http,
++ buffer, length));
++
++ /*
++ * Range check input...
++ */
++
++ if (http == NULL || buffer == NULL)
++ return (-1);
++
++ /*
++ * Mark activity on the connection...
++ */
++
++ http->activity = time(NULL);
++
++ /*
++ * Buffer small writes for better performance...
++ */
++
++ if (length > 0)
++ {
++ if (http->wused && (length + http->wused) > sizeof(http->wbuffer))
++ {
++ DEBUG_printf((" flushing buffer (wused=%d, length=%d)\n",
++ http->wused, length));
++
++ httpFlushWrite(http);
++ }
++
++ if ((length + http->wused) <= sizeof(http->wbuffer))
++ {
++ /*
++ * Write to buffer...
++ */
++
++ DEBUG_printf((" copying %d bytes to wbuffer...\n", length));
++
++ memcpy(http->wbuffer + http->wused, buffer, length);
++ http->wused += length;
++ bytes = length;
++ }
++ else
++ {
++ /*
++ * Otherwise write the data directly...
++ */
++
++ DEBUG_printf((" writing %d bytes to socket...\n", length));
++
++ if (http->data_encoding == HTTP_ENCODE_CHUNKED)
++ bytes = http_write_chunk(http, buffer, length);
++ else
++ bytes = http_write(http, buffer, length);
++
++ DEBUG_printf((" wrote %d bytes...\n", bytes));
++ }
++
++ if (http->data_encoding == HTTP_ENCODE_LENGTH)
++ http->data_remaining -= bytes;
++ }
++ else
++ bytes = 0;
++
++ /*
++ * Handle end-of-request processing...
++ */
++
++ if ((http->data_encoding == HTTP_ENCODE_CHUNKED && length == 0) ||
++ (http->data_encoding == HTTP_ENCODE_LENGTH && http->data_remaining == 0))
++ {
++ /*
++ * Finished with the transfer; unless we are sending POST or PUT
++ * data, go idle...
++ */
++
++ DEBUG_puts("httpWrite: changing states...");
++
++ if (http->wused)
++ httpFlushWrite(http);
++
++ if (http->data_encoding == HTTP_ENCODE_CHUNKED)
++ {
++ /*
++ * Send a 0-length chunk at the end of the request...
++ */
++
++ http_write(http, "0\r\n\r\n", 5);
++
++ /*
++ * Reset the data state...
++ */
++
++ http->data_encoding = HTTP_ENCODE_LENGTH;
++ http->data_remaining = 0;
++ }
++
++ if (http->state == HTTP_POST_RECV)
++ http->state ++;
++ else if (http->state == HTTP_PUT_RECV)
++ http->state = HTTP_STATUS;
++ else
++ http->state = HTTP_WAITING;
++ }
++
++ return (bytes);
++}
++
++
++#if defined(HAVE_SSL) && defined(HAVE_CDSASSL)
++/*
++ * '_httpWriteCDSA()' - Write function for the CDSA library.
++ */
++
++OSStatus /* O - -1 on error, 0 on success */
++_httpWriteCDSA(
++ SSLConnectionRef connection, /* I - SSL/TLS connection */
++ const void *data, /* I - Data buffer */
++ size_t *dataLength) /* IO - Number of bytes */
++{
++ OSStatus result; /* Return value */
++ ssize_t bytes; /* Number of bytes read */
++ http_t *http; /* HTTP connection */
++
++
++ http = (http_t *)connection;
++
++ do
++ {
++ bytes = write(http->fd, data, *dataLength);
++ }
++ while (bytes == -1 && errno == EINTR);
++
++ if (bytes == *dataLength)
++ {
++ result = 0;
++ }
++ else if (bytes >= 0)
++ {
++ *dataLength = bytes;
++ result = errSSLWouldBlock;
++ }
++ else
++ {
++ *dataLength = 0;
++
++ if (errno == EAGAIN)
++ result = errSSLWouldBlock;
++ else
++ result = errSSLClosedAbort;
++ }
++
++ return (result);
++}
++#endif /* HAVE_SSL && HAVE_CDSASSL */
++
++
++#if defined(HAVE_SSL) && defined(HAVE_GNUTLS)
++/*
++ * '_httpWriteGNUTLS()' - Write function for the GNU TLS library.
++ */
++
++ssize_t /* O - Number of bytes written or -1 on error */
++_httpWriteGNUTLS(
++ gnutls_transport_ptr ptr, /* I - HTTP connection */
++ const void *data, /* I - Data buffer */
++ size_t length) /* I - Number of bytes to write */
++{
++ return (send(((http_t *)ptr)->fd, data, length, 0));
++}
++#endif /* HAVE_SSL && HAVE_GNUTLS */
++
++
++#if defined(HAVE_SSL) && defined(HAVE_LIBSSL)
++/*
++ * 'http_bio_ctrl()' - Control the HTTP connection.
++ */
++
++static long /* O - Result/data */
++http_bio_ctrl(BIO *h, /* I - BIO data */
++ int cmd, /* I - Control command */
++ long arg1, /* I - First argument */
++ void *arg2) /* I - Second argument */
++{
++ switch (cmd)
++ {
++ default :
++ return (0);
++
++ case BIO_CTRL_RESET :
++ h->ptr = NULL;
++ return (0);
++
++ case BIO_C_SET_FILE_PTR :
++ h->ptr = arg2;
++ h->init = 1;
++ return (1);
++
++ case BIO_C_GET_FILE_PTR :
++ if (arg2)
++ {
++ *((void **)arg2) = h->ptr;
++ return (1);
++ }
++ else
++ return (0);
++
++ case BIO_CTRL_DUP :
++ case BIO_CTRL_FLUSH :
++ return (1);
++ }
++}
++
++
++/*
++ * 'http_bio_free()' - Free OpenSSL data.
++ */
++
++static int /* O - 1 on success, 0 on failure */
++http_bio_free(BIO *h) /* I - BIO data */
++{
++ if (!h)
++ return (0);
++
++ if (h->shutdown)
++ {
++ h->init = 0;
++ h->flags = 0;
++ }
++
++ return (1);
++}
++
++
++/*
++ * 'http_bio_new()' - Initialize an OpenSSL BIO structure.
++ */
++
++static int /* O - 1 on success, 0 on failure */
++http_bio_new(BIO *h) /* I - BIO data */
++{
++ if (!h)
++ return (0);
++
++ h->init = 0;
++ h->num = 0;
++ h->ptr = NULL;
++ h->flags = 0;
++
++ return (1);
++}
++
++
++/*
++ * 'http_bio_puts()' - Send a string for OpenSSL.
++ */
++
++static int /* O - Bytes written */
++http_bio_puts(BIO *h, /* I - BIO data */
++ const char *str) /* I - String to write */
++{
++ return (send(((http_t *)h->ptr)->fd, str, strlen(str), 0));
++}
++
++
++/*
++ * 'http_bio_read()' - Read data for OpenSSL.
++ */
++
++static int /* O - Bytes read */
++http_bio_read(BIO *h, /* I - BIO data */
++ char *buf, /* I - Buffer */
++ int size) /* I - Number of bytes to read */
++{
++ http_t *http; /* HTTP connection */
++
++
++ http = (http_t *)h->ptr;
++
++ if (!http->blocking)
++ {
++ /*
++ * Make sure we have data before we read...
++ */
++
++ if (!http_wait(http, 10000, 0))
++ {
++ http->error = ETIMEDOUT;
++ return (-1);
++ }
++ }
++
++ return (recv(http->fd, buf, size, 0));
++}
++
++
++/*
++ * 'http_bio_write()' - Write data for OpenSSL.
++ */
++
++static int /* O - Bytes written */
++http_bio_write(BIO *h, /* I - BIO data */
++ const char *buf, /* I - Buffer to write */
++ int num) /* I - Number of bytes to write */
++{
++ return (send(((http_t *)h->ptr)->fd, buf, num, 0));
++}
++#endif /* HAVE_SSL && HAVE_LIBSSL */
++
++
++/*
++ * 'http_field()' - Return the field index for a field name.
++ */
++
++static http_field_t /* O - Field index */
++http_field(const char *name) /* I - String name */
++{
++ int i; /* Looping var */
++
++
++ for (i = 0; i < HTTP_FIELD_MAX; i ++)
++ if (strcasecmp(name, http_fields[i]) == 0)
++ return ((http_field_t)i);
++
++ return (HTTP_FIELD_UNKNOWN);
++}
++
++
++#ifdef HAVE_SSL
++/*
++ * 'http_read_ssl()' - Read from a SSL/TLS connection.
++ */
++
++static int /* O - Bytes read */
++http_read_ssl(http_t *http, /* I - HTTP connection */
++ char *buf, /* I - Buffer to store data */
++ int len) /* I - Length of buffer */
++{
++# if defined(HAVE_LIBSSL)
++ return (SSL_read((SSL *)(http->tls), buf, len));
++
++# elif defined(HAVE_GNUTLS)
++ return (gnutls_record_recv(((http_tls_t *)(http->tls))->session, buf, len));
++
++# elif defined(HAVE_CDSASSL)
++ int result; /* Return value */
++ OSStatus error; /* Error info */
++ size_t processed; /* Number of bytes processed */
++
++
++ error = SSLRead(((http_tls_t *)http->tls)->session, buf, len, &processed);
++
++ switch (error)
++ {
++ case 0 :
++ result = (int)processed;
++ break;
++ case errSSLClosedGraceful :
++ result = 0;
++ break;
++ case errSSLWouldBlock :
++ if (processed)
++ result = (int)processed;
++ else
++ {
++ result = -1;
++ errno = EINTR;
++ }
++ break;
++ default :
++ errno = EPIPE;
++ result = -1;
++ break;
++ }
++
++ return (result);
++# endif /* HAVE_LIBSSL */
++}
++#endif /* HAVE_SSL */
++
++
++/*
++ * 'http_send()' - Send a request with all fields and the trailing blank line.
++ */
++
++static int /* O - 0 on success, non-zero on error */
++http_send(http_t *http, /* I - HTTP connection */
++ http_state_t request, /* I - Request code */
++ const char *uri) /* I - URI */
++{
++ int i; /* Looping var */
++ char *ptr, /* Pointer in buffer */
++ buf[1024]; /* Encoded URI buffer */
++ static const char * const codes[] =
++ { /* Request code strings */
++ NULL,
++ "OPTIONS",
++ "GET",
++ NULL,
++ "HEAD",
++ "POST",
++ NULL,
++ NULL,
++ "PUT",
++ NULL,
++ "DELETE",
++ "TRACE",
++ "CLOSE"
++ };
++ static const char hex[] = "0123456789ABCDEF";
++ /* Hex digits */
++
++
++ DEBUG_printf(("http_send(http=%p, request=HTTP_%s, uri=\"%s\")\n",
++ http, codes[request], uri));
++
++ if (http == NULL || uri == NULL)
++ return (-1);
++
++ /*
++ * Set the User-Agent field if it isn't already...
++ */
++
++ if (!http->fields[HTTP_FIELD_USER_AGENT][0])
++ httpSetField(http, HTTP_FIELD_USER_AGENT, CUPS_MINIMAL);
++
++ /*
++ * Encode the URI as needed...
++ */
++
++ for (ptr = buf; *uri != '\0' && ptr < (buf + sizeof(buf) - 1); uri ++)
++ if (*uri <= ' ' || *uri >= 127)
++ {
++ if (ptr < (buf + sizeof(buf) - 1))
++ *ptr ++ = '%';
++ if (ptr < (buf + sizeof(buf) - 1))
++ *ptr ++ = hex[(*uri >> 4) & 15];
++ if (ptr < (buf + sizeof(buf) - 1))
++ *ptr ++ = hex[*uri & 15];
++ }
++ else
++ *ptr ++ = *uri;
++
++ *ptr = '\0';
++
++ /*
++ * See if we had an error the last time around; if so, reconnect...
++ */
++
++ if (http->status == HTTP_ERROR || http->status >= HTTP_BAD_REQUEST)
++ if (httpReconnect(http))
++ return (-1);
++
++ /*
++ * Flush any written data that is pending...
++ */
++
++ if (http->wused)
++ httpFlushWrite(http);
++
++ /*
++ * Send the request header...
++ */
++
++ http->state = request;
++ http->data_encoding = HTTP_ENCODE_FIELDS;
++
++ if (request == HTTP_POST || request == HTTP_PUT)
++ http->state ++;
++
++ http->status = HTTP_CONTINUE;
++
++#ifdef HAVE_SSL
++ if (http->encryption == HTTP_ENCRYPT_REQUIRED && !http->tls)
++ {
++ httpSetField(http, HTTP_FIELD_CONNECTION, "Upgrade");
++ httpSetField(http, HTTP_FIELD_UPGRADE, "TLS/1.0,SSL/2.0,SSL/3.0");
++ }
++#endif /* HAVE_SSL */
++
++ if (httpPrintf(http, "%s %s HTTP/1.1\r\n", codes[request], buf) < 1)
++ {
++ http->status = HTTP_ERROR;
++ return (-1);
++ }
++
++ for (i = 0; i < HTTP_FIELD_MAX; i ++)
++ if (http->fields[i][0] != '\0')
++ {
++ DEBUG_printf(("%s: %s\n", http_fields[i], http->fields[i]));
++
++ if (httpPrintf(http, "%s: %s\r\n", http_fields[i], http->fields[i]) < 1)
++ {
++ http->status = HTTP_ERROR;
++ return (-1);
++ }
++ }
++
++ if (http->cookie)
++ if (httpPrintf(http, "Cookie: $Version=0; %s\r\n", http->cookie) < 1)
++ {
++ http->status = HTTP_ERROR;
++ return (-1);
++ }
++
++ if (http->expect == HTTP_CONTINUE &&
++ (http->state == HTTP_POST_RECV || http->state == HTTP_PUT_RECV))
++ if (httpPrintf(http, "Expect: 100-continue\r\n") < 1)
++ {
++ http->status = HTTP_ERROR;
++ return (-1);
++ }
++
++ if (httpPrintf(http, "\r\n") < 1)
++ {
++ http->status = HTTP_ERROR;
++ return (-1);
++ }
++
++ httpFlushWrite(http);
++ httpGetLength2(http);
++ httpClearFields(http);
++
++ return (0);
++}
++
++
++#ifdef HAVE_SSL
++/*
++ * 'http_setup_ssl()' - Set up SSL/TLS support on a connection.
++ */
++
++static int /* O - Status of connection */
++http_setup_ssl(http_t *http) /* I - HTTP connection */
++{
++# ifdef HAVE_LIBSSL
++ SSL_CTX *context; /* Context for encryption */
++ SSL *conn; /* Connection for encryption */
++ BIO *bio; /* BIO data */
++# elif defined(HAVE_GNUTLS)
++ http_tls_t *conn; /* TLS session object */
++ gnutls_certificate_client_credentials *credentials;
++ /* TLS credentials */
++# elif defined(HAVE_CDSASSL)
++ OSStatus error; /* Error code */
++ http_tls_t *conn; /* CDSA connection information */
++# endif /* HAVE_LIBSSL */
++
++
++ DEBUG_printf(("http_setup_ssl(http=%p)\n", http));
++
++# ifdef HAVE_LIBSSL
++ context = SSL_CTX_new(SSLv23_client_method());
++
++ SSL_CTX_set_options(context, SSL_OP_NO_SSLv2); /* Only use SSLv3 or TLS */
++
++ bio = BIO_new(_httpBIOMethods());
++ BIO_ctrl(bio, BIO_C_SET_FILE_PTR, 0, (char *)http);
++
++ conn = SSL_new(context);
++ SSL_set_bio(conn, bio, bio);
++
++ if (SSL_connect(conn) != 1)
++ {
++# ifdef DEBUG
++ unsigned long error; /* Error code */
++
++ while ((error = ERR_get_error()) != 0)
++ printf("http_setup_ssl: %s\n", ERR_error_string(error, NULL));
++# endif /* DEBUG */
++
++ SSL_CTX_free(context);
++ SSL_free(conn);
++
++# ifdef WIN32
++ http->error = WSAGetLastError();
++# else
++ http->error = errno;
++# endif /* WIN32 */
++ http->status = HTTP_ERROR;
++
++ return (HTTP_ERROR);
++ }
++
++# elif defined(HAVE_GNUTLS)
++ if ((conn = (http_tls_t *)malloc(sizeof(http_tls_t))) == NULL)
++ {
++ http->error = errno;
++ http->status = HTTP_ERROR;
++
++ return (-1);
++ }
++
++ credentials = (gnutls_certificate_client_credentials *)
++ malloc(sizeof(gnutls_certificate_client_credentials));
++ if (credentials == NULL)
++ {
++ free(conn);
++
++ http->error = errno;
++ http->status = HTTP_ERROR;
++
++ return (-1);
++ }
++
++ gnutls_certificate_allocate_credentials(credentials);
++
++ gnutls_init(&(conn->session), GNUTLS_CLIENT);
++ gnutls_set_default_priority(conn->session);
++ gnutls_credentials_set(conn->session, GNUTLS_CRD_CERTIFICATE, *credentials);
++ gnutls_transport_set_ptr(conn->session, (gnutls_transport_ptr)http);
++ gnutls_transport_set_pull_function(conn->session, _httpReadGNUTLS);
++ gnutls_transport_set_push_function(conn->session, _httpWriteGNUTLS);
++
++ if ((gnutls_handshake(conn->session)) != GNUTLS_E_SUCCESS)
++ {
++ http->error = errno;
++ http->status = HTTP_ERROR;
++
++ return (-1);
++ }
++
++ conn->credentials = credentials;
++
++# elif defined(HAVE_CDSASSL)
++ conn = (http_tls_t *)calloc(1, sizeof(http_tls_t));
++
++ if (conn == NULL)
++ return (-1);
++
++ if ((error = SSLNewContext(false, &conn->session)))
++ {
++ http->error = error;
++ http->status = HTTP_ERROR;
++
++ free(conn);
++ return (-1);
++ }
++
++ /*
++ * Use a union to resolve warnings about int/pointer size mismatches...
++ */
++
++ error = SSLSetConnection(conn->session, http);
++
++ if (!error)
++ error = SSLSetIOFuncs(conn->session, _httpReadCDSA, _httpWriteCDSA);
++
++ if (!error)
++ error = SSLSetAllowsExpiredCerts(conn->session, true);
++
++ if (!error)
++ error = SSLSetAllowsAnyRoot(conn->session, true);
++
++ if (!error)
++ error = SSLSetProtocolVersionEnabled(conn->session, kSSLProtocol2, false);
++
++ if (!error)
++ {
++ while ((error = SSLHandshake(conn->session)) == errSSLWouldBlock)
++ usleep(1000);
++ }
++
++ if (error)
++ {
++ http->error = error;
++ http->status = HTTP_ERROR;
++
++ SSLDisposeContext(conn->session);
++
++ free(conn);
++
++ return (-1);
++ }
++# endif /* HAVE_CDSASSL */
++
++ http->tls = conn;
++ return (0);
++}
++#endif /* HAVE_SSL */
++
++
++#ifdef HAVE_SSL
++/*
++ * 'http_shutdown_ssl()' - Shut down SSL/TLS on a connection.
++ */
++
++static void
++http_shutdown_ssl(http_t *http) /* I - HTTP connection */
++{
++# ifdef HAVE_LIBSSL
++ SSL_CTX *context; /* Context for encryption */
++ SSL *conn; /* Connection for encryption */
++
++
++ conn = (SSL *)(http->tls);
++ context = SSL_get_SSL_CTX(conn);
++
++ SSL_shutdown(conn);
++ SSL_CTX_free(context);
++ SSL_free(conn);
++
++# elif defined(HAVE_GNUTLS)
++ http_tls_t *conn; /* Encryption session */
++ gnutls_certificate_client_credentials *credentials;
++ /* TLS credentials */
++
++
++ conn = (http_tls_t *)(http->tls);
++ credentials = (gnutls_certificate_client_credentials *)(conn->credentials);
++
++ gnutls_bye(conn->session, GNUTLS_SHUT_RDWR);
++ gnutls_deinit(conn->session);
++ gnutls_certificate_free_credentials(*credentials);
++ free(credentials);
++ free(conn);
++
++# elif defined(HAVE_CDSASSL)
++ http_tls_t *conn; /* CDSA connection information */
++
++
++ conn = (http_tls_t *)(http->tls);
++
++ while (SSLClose(conn->session) == errSSLWouldBlock)
++ usleep(1000);
++
++ SSLDisposeContext(conn->session);
++
++ if (conn->certsArray)
++ CFRelease(conn->certsArray);
++
++ free(conn);
++# endif /* HAVE_LIBSSL */
++
++ http->tls = NULL;
++}
++#endif /* HAVE_SSL */
++
++
++#ifdef HAVE_SSL
++/*
++ * 'http_upgrade()' - Force upgrade to TLS encryption.
++ */
++
++static int /* O - Status of connection */
++http_upgrade(http_t *http) /* I - HTTP connection */
++{
++ int ret; /* Return value */
++ http_t myhttp; /* Local copy of HTTP data */
++
++
++ DEBUG_printf(("http_upgrade(%p)\n", http));
++
++ /*
++ * Copy the HTTP data to a local variable so we can do the OPTIONS
++ * request without interfering with the existing request data...
++ */
++
++ memcpy(&myhttp, http, sizeof(myhttp));
++
++ /*
++ * Send an OPTIONS request to the server, requiring SSL or TLS
++ * encryption on the link...
++ */
++
++ httpClearFields(&myhttp);
++ httpSetField(&myhttp, HTTP_FIELD_CONNECTION, "upgrade");
++ httpSetField(&myhttp, HTTP_FIELD_UPGRADE, "TLS/1.0, SSL/2.0, SSL/3.0");
++
++ if ((ret = httpOptions(&myhttp, "*")) == 0)
++ {
++ /*
++ * Wait for the secure connection...
++ */
++
++ while (httpUpdate(&myhttp) == HTTP_CONTINUE);
++ }
++
++ httpFlush(&myhttp);
++
++ /*
++ * Copy the HTTP data back over, if any...
++ */
++
++ http->fd = myhttp.fd;
++ http->error = myhttp.error;
++ http->activity = myhttp.activity;
++ http->status = myhttp.status;
++ http->version = myhttp.version;
++ http->keep_alive = myhttp.keep_alive;
++ http->used = myhttp.used;
++
++ if (http->used)
++ memcpy(http->buffer, myhttp.buffer, http->used);
++
++ http->auth_type = myhttp.auth_type;
++ http->nonce_count = myhttp.nonce_count;
++
++ memcpy(http->nonce, myhttp.nonce, sizeof(http->nonce));
++
++ http->tls = myhttp.tls;
++ http->encryption = myhttp.encryption;
++
++ /*
++ * See if we actually went secure...
++ */
++
++ if (!http->tls)
++ {
++ /*
++ * Server does not support HTTP upgrade...
++ */
++
++ DEBUG_puts("Server does not support HTTP upgrade!");
++
++# ifdef WIN32
++ closesocket(http->fd);
++# else
++ close(http->fd);
++# endif
++
++ http->fd = -1;
++
++ return (-1);
++ }
++ else
++ return (ret);
++}
++#endif /* HAVE_SSL */
++
++
++/*
++ * 'http_wait()' - Wait for data available on a connection.
++ */
++
++static int /* O - 1 if data is available, 0 otherwise */
++http_wait(http_t *http, /* I - HTTP connection */
++ int msec, /* I - Milliseconds to wait */
++ int usessl) /* I - Use SSL context? */
++{
++#ifndef WIN32
++ struct rlimit limit; /* Runtime limit */
++ int set_size; /* Size of select set */
++#endif /* !WIN32 */
++ struct timeval timeout; /* Timeout */
++ int nfds; /* Result from select() */
++
++
++ DEBUG_printf(("http_wait(http=%p, msec=%d)\n", http, msec));
++
++ if (http->fd < 0)
++ return (0);
++
++ /*
++ * Check the SSL/TLS buffers for data first...
++ */
++
++#ifdef HAVE_SSL
++ if (http->tls && usessl)
++ {
++# ifdef HAVE_LIBSSL
++ if (SSL_pending((SSL *)(http->tls)))
++ return (1);
++# elif defined(HAVE_GNUTLS)
++ if (gnutls_record_check_pending(((http_tls_t *)(http->tls))->session))
++ return (1);
++# elif defined(HAVE_CDSASSL)
++ size_t bytes; /* Bytes that are available */
++
++ if (!SSLGetBufferedReadSize(((http_tls_t *)http->tls)->session, &bytes) && bytes > 0)
++ return (1);
++# endif /* HAVE_LIBSSL */
++ }
++#endif /* HAVE_SSL */
++
++ /*
++ * Then try doing a select() to poll the socket...
++ */
++
++ if (!http->input_set)
++ {
++#ifdef WIN32
++ /*
++ * Windows has a fixed-size select() structure, different (surprise,
++ * surprise!) from all UNIX implementations. Just allocate this
++ * fixed structure...
++ */
++
++ http->input_set = calloc(1, sizeof(fd_set));
++#else
++ /*
++ * Allocate the select() input set based upon the max number of file
++ * descriptors available for this process...
++ */
++
++ getrlimit(RLIMIT_NOFILE, &limit);
++
++ set_size = (limit.rlim_cur + 31) / 8 + 4;
++ if (set_size < sizeof(fd_set))
++ set_size = sizeof(fd_set);
++
++ http->input_set = calloc(1, set_size);
++#endif /* WIN32 */
++
++ if (!http->input_set)
++ return (0);
++ }
++
++ do
++ {
++ FD_SET(http->fd, http->input_set);
++
++ DEBUG_printf(("http_wait: msec=%d, http->fd=%d\n", msec, http->fd));
++
++ if (msec >= 0)
++ {
++ timeout.tv_sec = msec / 1000;
++ timeout.tv_usec = (msec % 1000) * 1000;
++
++ nfds = select(http->fd + 1, http->input_set, NULL, NULL, &timeout);
++ }
++ else
++ nfds = select(http->fd + 1, http->input_set, NULL, NULL, NULL);
++
++ DEBUG_printf(("http_wait: select() returned %d...\n", nfds));
++ }
++#ifdef WIN32
++ while (nfds < 0 && WSAGetLastError() == WSAEINTR);
++#else
++ while (nfds < 0 && errno == EINTR);
++#endif /* WIN32 */
++
++ FD_CLR(http->fd, http->input_set);
++
++ DEBUG_printf(("http_wait: returning with nfds=%d...\n", nfds));
++
++ return (nfds > 0);
++}
++
++
++/*
++ * 'http_write()' - Write a buffer to a HTTP connection.
++ */
++
++static int /* O - Number of bytes written */
++http_write(http_t *http, /* I - HTTP connection */
++ const char *buffer, /* I - Buffer for data */
++ int length) /* I - Number of bytes to write */
++{
++ int tbytes, /* Total bytes sent */
++ bytes; /* Bytes sent */
++
++
++ tbytes = 0;
++
++ while (length > 0)
++ {
++#ifdef HAVE_SSL
++ if (http->tls)
++ bytes = http_write_ssl(http, buffer, length);
++ else
++#endif /* HAVE_SSL */
++ bytes = send(http->fd, buffer, length, 0);
++
++ if (bytes < 0)
++ {
++#ifdef WIN32
++ if (WSAGetLastError() != http->error)
++ {
++ http->error = WSAGetLastError();
++ continue;
++ }
++#else
++ if (errno == EINTR)
++ continue;
++ else if (errno != http->error && errno != ECONNRESET)
++ {
++ http->error = errno;
++ continue;
++ }
++#endif /* WIN32 */
++
++ DEBUG_puts("http_write: error writing data...\n");
++
++ return (-1);
++ }
++
++ buffer += bytes;
++ tbytes += bytes;
++ length -= bytes;
++ }
++
++#ifdef DEBUG
++ {
++ int i, j, ch;
++ printf("http_write: wrote %d bytes: \n", tbytes);
++ for (i = 0, buffer -= tbytes; i < tbytes; i += 16)
++ {
++ printf(" ");
++
++ for (j = 0; j < 16 && (i + j) < tbytes; j ++)
++ printf(" %02X", buffer[i + j] & 255);
++
++ while (j < 16)
++ {
++ printf(" ");
++ j ++;
++ }
++
++ printf(" ");
++ for (j = 0; j < 16 && (i + j) < tbytes; j ++)
++ {
++ ch = buffer[i + j] & 255;
++
++ if (ch < ' ' || ch == 127)
++ ch = '.';
++
++ putchar(ch);
++ }
++ putchar('\n');
++ }
++ }
++#endif /* DEBUG */
++
++ return (tbytes);
++}
++
++
++/*
++ * 'http_write_chunk()' - Write a chunked buffer.
++ */
++
++static int /* O - Number bytes written */
++http_write_chunk(http_t *http, /* I - HTTP connection */
++ const char *buffer, /* I - Buffer to write */
++ int length) /* I - Length of buffer */
++{
++ char header[255]; /* Chunk header */
++ int bytes; /* Bytes written */
++
++ DEBUG_printf(("http_write_chunk(http=%p, buffer=%p, length=%d)\n",
++ http, buffer, length));
++
++ /*
++ * Write the chunk header, data, and trailer.
++ */
++
++ sprintf(header, "%x\r\n", length);
++ if (http_write(http, header, strlen(header)) < 0)
++ {
++ DEBUG_puts(" http_write of length failed!");
++ return (-1);
++ }
++
++ if ((bytes = http_write(http, buffer, length)) < 0)
++ {
++ DEBUG_puts(" http_write of buffer failed!");
++ return (-1);
++ }
++
++ if (http_write(http, "\r\n", 2) < 0)
++ {
++ DEBUG_puts(" http_write of CR LF failed!");
++ return (-1);
++ }
++
++ return (bytes);
++}
++
++
++#ifdef HAVE_SSL
++/*
++ * 'http_write_ssl()' - Write to a SSL/TLS connection.
++ */
++
++static int /* O - Bytes written */
++http_write_ssl(http_t *http, /* I - HTTP connection */
++ const char *buf, /* I - Buffer holding data */
++ int len) /* I - Length of buffer */
++{
++# if defined(HAVE_LIBSSL)
++ return (SSL_write((SSL *)(http->tls), buf, len));
++
++# elif defined(HAVE_GNUTLS)
++ return (gnutls_record_send(((http_tls_t *)(http->tls))->session, buf, len));
++# elif defined(HAVE_CDSASSL)
++ int result; /* Return value */
++ OSStatus error; /* Error info */
++ size_t processed; /* Number of bytes processed */
++
++
++ error = SSLWrite(((http_tls_t *)http->tls)->session, buf, len, &processed);
++
++ switch (error)
++ {
++ case 0 :
++ result = (int)processed;
++ break;
++ case errSSLClosedGraceful :
++ result = 0;
++ break;
++ case errSSLWouldBlock :
++ if (processed)
++ result = (int)processed;
++ else
++ {
++ result = -1;
++ errno = EINTR;
++ }
++ break;
++ default :
++ errno = EPIPE;
++ result = -1;
++ break;
++ }
++
++ return (result);
++# endif /* HAVE_LIBSSL */
++}
++#endif /* HAVE_SSL */
++
++
++/*
++ * End of "$Id: http.c 6111 2006-11-15 20:28:39Z mike $".
++ */
Added: cupsys/branches/cups-1.2/debian/patches/00_06str2121.dpatch
==============================================================================
--- (empty file)
+++ cupsys/branches/cups-1.2/debian/patches/00_06str2121.dpatch Thu Dec 28 14:48:31 2006
@@ -0,0 +1,32 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 00_06str2121.dpatch by Kenshi Muto <kmuto at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad cupsys-1.2.7~/cups/auth.c cupsys-1.2.7/cups/auth.c
+--- cupsys-1.2.7~/cups/auth.c 2006-12-28 12:00:51.000000000 +0000
++++ cupsys-1.2.7/cups/auth.c 2006-12-28 13:13:54.000000000 +0000
+@@ -75,6 +75,7 @@
+ realm[HTTP_MAX_VALUE], /* realm="xyz" string */
+ nonce[HTTP_MAX_VALUE], /* nonce="xyz" string */
+ encode[512]; /* Encoded username:password */
++ _cups_globals_t *cg; /* Global data */
+
+
+ DEBUG_printf(("cupsDoAuthentication(http=%p, method=\"%s\", resource=\"%s\")\n",
+@@ -114,7 +115,12 @@
+ * Nope - get a new password from the user...
+ */
+
+- snprintf(prompt, sizeof(prompt), _("Password for %s on %s? "), cupsUser(),
++ cg = _cupsGlobals();
++
++ if (!cg->lang_default)
++ cg->lang_default = cupsLangDefault();
++
++ snprintf(prompt, sizeof(prompt), _cupsLangString(cg->lang_default, _("Password for %s on %s? ")), cupsUser(),
+ http->hostname[0] == '/' ? "localhost" : http->hostname);
+
+ http->digest_tries = strncasecmp(http->fields[HTTP_FIELD_WWW_AUTHENTICATE],
Added: cupsys/branches/cups-1.2/debian/patches/00_07str2123.dpatch
==============================================================================
--- (empty file)
+++ cupsys/branches/cups-1.2/debian/patches/00_07str2123.dpatch Thu Dec 28 14:48:31 2006
@@ -0,0 +1,28 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 00_07str2123.dpatch by Kenshi Muto <kmuto at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad cupsys-1.2.7~/backend/runloop.c cupsys-1.2.7/backend/runloop.c
+--- cupsys-1.2.7~/backend/runloop.c 2006-12-28 12:00:51.000000000 +0000
++++ cupsys-1.2.7/backend/runloop.c 2006-12-28 13:18:23.000000000 +0000
+@@ -206,7 +206,7 @@
+ if (!paperout)
+ {
+ fputs("ERROR: Out of paper!\n", stderr);
+- fputs("STATUS: +media-tray-empty-error\n", stderr);
++ fputs("STATE: +media-empty-error\n", stderr);
+ paperout = 1;
+ }
+ }
+@@ -229,7 +229,7 @@
+ {
+ if (paperout)
+ {
+- fputs("STATUS: -media-tray-empty-error\n", stderr);
++ fputs("STATE: -media-empty-error\n", stderr);
+ paperout = 0;
+ }
+
Added: cupsys/branches/cups-1.2/debian/patches/00_08str2135.dpatch
==============================================================================
--- (empty file)
+++ cupsys/branches/cups-1.2/debian/patches/00_08str2135.dpatch Thu Dec 28 14:48:31 2006
@@ -0,0 +1,39 @@
+#! /bin/sh /usr/share/dpatch/dpatch-run
+## 00_08str2135.dpatch by Kenshi Muto <kmuto at debian.org>
+##
+## All lines beginning with `## DP:' are a description of the patch.
+## DP: No description.
+
+ at DPATCH@
+diff -urNad cupsys-1.2.7~/cups/options.c cupsys-1.2.7/cups/options.c
+--- cupsys-1.2.7~/cups/options.c 2006-02-22 22:43:17.000000000 +0000
++++ cupsys-1.2.7/cups/options.c 2006-12-28 13:22:09.000000000 +0000
+@@ -366,10 +366,27 @@
+ }
+ else if (!strcasecmp(optptr->name, "output-bin"))
+ {
+- if (cupsGetOption("OutputBin", num_options, options) == NULL)
++ if (!cupsGetOption("OutputBin", num_options, options))
+ if (ppdMarkOption(ppd, "OutputBin", optptr->value))
+ conflict = 1;
+ }
++ else if (!strcasecmp(optptr->name, "multiple-document-handling"))
++ {
++ if (!cupsGetOption("Collate", num_options, options) &&
++ ppdFindOption(ppd, "Collate"))
++ {
++ if (strcasecmp(optptr->value, "separate-documents-uncollated-copies"))
++ {
++ if (ppdMarkOption(ppd, "Collate", "True"))
++ conflict = 1;
++ }
++ else
++ {
++ if (ppdMarkOption(ppd, "Collate", "False"))
++ conflict = 1;
++ }
++ }
++ }
+ else if (ppdMarkOption(ppd, optptr->name, optptr->value))
+ conflict = 1;
+
Modified: cupsys/branches/cups-1.2/debian/patches/00list
==============================================================================
--- cupsys/branches/cups-1.2/debian/patches/00list (original)
+++ cupsys/branches/cups-1.2/debian/patches/00list Thu Dec 28 14:48:31 2006
@@ -1,10 +1,18 @@
-00_r6149.dpatch
+00_00str2111.dpatch
+00_01str2137.dpatch
+00_02str2144.dpatch
+00_03str2106.dpatch
+00_04str2117.dpatch
+00_05str2133.dpatch
+00_06str2121.dpatch
+00_07str2123.dpatch
+00_08str2135.dpatch
02_configure.dpatch
#03_manext.dpatch
03_clean.dpatch
04_freebsd.dpatch
#05_avoidunknowngroup.dpatch
-#06_disable_backend_setuid.dpatch
+06_disable_backend_setuid.dpatch
07_removecvstag.dpatch
#08_cupsd.conf.conf.d.dpatch
09_runasuser.dpatch
@@ -28,5 +36,5 @@
62_classes_crash.dpatch
#64_driverfolder.dpatch
65_detect_http_shutdown.dpatch
-66_setegid.dpatch
+#66_setegid.dpatch
67_printcap.dpatch
More information about the Pkg-cups-devel
mailing list