4 * Get/put file functions for CUPS.
6 * Copyright 2007-2014 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * This file is subject to the Apple OS-Developed Software exception.
19 * Include necessary headers...
22 #include "cups-private.h"
25 #if defined(WIN32) || defined(__EMX__)
29 #endif /* WIN32 || __EMX__ */
33 * 'cupsGetFd()' - Get a file from the server.
35 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
37 * @since CUPS 1.1.20/OS X 10.4@
40 http_status_t
/* O - HTTP status */
41 cupsGetFd(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
42 const char *resource
, /* I - Resource name */
43 int fd
) /* I - File descriptor */
45 ssize_t bytes
; /* Number of bytes read */
46 char buffer
[8192]; /* Buffer for file */
47 http_status_t status
; /* HTTP status from server */
48 char if_modified_since
[HTTP_MAX_VALUE
];
49 /* If-Modified-Since header */
53 * Range check input...
56 DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", http
,
59 if (!resource
|| fd
< 0)
64 return (HTTP_STATUS_ERROR
);
68 if ((http
= _cupsConnect()) == NULL
)
69 return (HTTP_STATUS_SERVICE_UNAVAILABLE
);
72 * Then send GET requests to the HTTP server...
75 strlcpy(if_modified_since
, httpGetField(http
, HTTP_FIELD_IF_MODIFIED_SINCE
),
76 sizeof(if_modified_since
));
80 if (!_cups_strcasecmp(httpGetField(http
, HTTP_FIELD_CONNECTION
), "close"))
82 httpClearFields(http
);
83 if (httpReconnect2(http
, 30000, NULL
))
85 status
= HTTP_STATUS_ERROR
;
90 httpClearFields(http
);
91 httpSetField(http
, HTTP_FIELD_AUTHORIZATION
, http
->authstring
);
92 httpSetField(http
, HTTP_FIELD_IF_MODIFIED_SINCE
, if_modified_since
);
94 if (httpGet(http
, resource
))
96 if (httpReconnect2(http
, 30000, NULL
))
98 status
= HTTP_STATUS_ERROR
;
103 status
= HTTP_STATUS_UNAUTHORIZED
;
108 while ((status
= httpUpdate(http
)) == HTTP_STATUS_CONTINUE
);
110 if (status
== HTTP_STATUS_UNAUTHORIZED
)
113 * Flush any error message...
119 * See if we can do authentication...
122 if (cupsDoAuthentication(http
, "GET", resource
))
124 status
= HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED
;
128 if (httpReconnect2(http
, 30000, NULL
))
130 status
= HTTP_STATUS_ERROR
;
137 else if (status
== HTTP_STATUS_UPGRADE_REQUIRED
)
139 /* Flush any error message... */
143 if (httpReconnect2(http
, 30000, NULL
))
145 status
= HTTP_STATUS_ERROR
;
149 /* Upgrade with encryption... */
150 httpEncryption(http
, HTTP_ENCRYPTION_REQUIRED
);
152 /* Try again, this time with encryption enabled... */
155 #endif /* HAVE_SSL */
157 while (status
== HTTP_STATUS_UNAUTHORIZED
|| status
== HTTP_STATUS_UPGRADE_REQUIRED
);
160 * See if we actually got the file or an error...
163 if (status
== HTTP_STATUS_OK
)
166 * Yes, copy the file...
169 while ((bytes
= httpRead2(http
, buffer
, sizeof(buffer
))) > 0)
170 write(fd
, buffer
, (size_t)bytes
);
174 _cupsSetHTTPError(status
);
179 * Return the request status...
182 DEBUG_printf(("1cupsGetFd: Returning %d...", status
));
189 * 'cupsGetFile()' - Get a file from the server.
191 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
193 * @since CUPS 1.1.20/OS X 10.4@
196 http_status_t
/* O - HTTP status */
197 cupsGetFile(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
198 const char *resource
, /* I - Resource name */
199 const char *filename
) /* I - Filename */
201 int fd
; /* File descriptor */
202 http_status_t status
; /* Status */
206 * Range check input...
209 if (!http
|| !resource
|| !filename
)
212 http
->error
= EINVAL
;
214 return (HTTP_STATUS_ERROR
);
221 if ((fd
= open(filename
, O_WRONLY
| O_EXCL
| O_TRUNC
)) < 0)
224 * Couldn't open the file!
229 return (HTTP_STATUS_ERROR
);
236 status
= cupsGetFd(http
, resource
, fd
);
239 * If the file couldn't be gotten, then remove the file...
244 if (status
!= HTTP_STATUS_OK
)
248 * Return the HTTP status code...
256 * 'cupsPutFd()' - Put a file on the server.
258 * This function returns @code HTTP_STATUS_CREATED@ when the file is stored
261 * @since CUPS 1.1.20/OS X 10.4@
264 http_status_t
/* O - HTTP status */
265 cupsPutFd(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
266 const char *resource
, /* I - Resource name */
267 int fd
) /* I - File descriptor */
269 ssize_t bytes
; /* Number of bytes read */
270 int retries
; /* Number of retries */
271 char buffer
[8192]; /* Buffer for file */
272 http_status_t status
; /* HTTP status from server */
276 * Range check input...
279 DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", http
,
282 if (!resource
|| fd
< 0)
285 http
->error
= EINVAL
;
287 return (HTTP_STATUS_ERROR
);
291 if ((http
= _cupsConnect()) == NULL
)
292 return (HTTP_STATUS_SERVICE_UNAVAILABLE
);
295 * Then send PUT requests to the HTTP server...
302 if (!_cups_strcasecmp(httpGetField(http
, HTTP_FIELD_CONNECTION
), "close"))
304 httpClearFields(http
);
305 if (httpReconnect2(http
, 30000, NULL
))
307 status
= HTTP_STATUS_ERROR
;
312 DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
315 httpClearFields(http
);
316 httpSetField(http
, HTTP_FIELD_AUTHORIZATION
, http
->authstring
);
317 httpSetField(http
, HTTP_FIELD_TRANSFER_ENCODING
, "chunked");
318 httpSetExpect(http
, HTTP_STATUS_CONTINUE
);
320 if (httpPut(http
, resource
))
322 if (httpReconnect2(http
, 30000, NULL
))
324 status
= HTTP_STATUS_ERROR
;
329 status
= HTTP_STATUS_UNAUTHORIZED
;
335 * Wait up to 1 second for a 100-continue response...
338 if (httpWait(http
, 1000))
339 status
= httpUpdate(http
);
341 status
= HTTP_STATUS_CONTINUE
;
343 if (status
== HTTP_STATUS_CONTINUE
)
349 lseek(fd
, 0, SEEK_SET
);
351 while ((bytes
= read(fd
, buffer
, sizeof(buffer
))) > 0)
354 if ((status
= httpUpdate(http
)) != HTTP_STATUS_CONTINUE
)
358 httpWrite2(http
, buffer
, (size_t)bytes
);
361 if (status
== HTTP_STATUS_CONTINUE
)
363 httpWrite2(http
, buffer
, 0);
365 while ((status
= httpUpdate(http
)) == HTTP_STATUS_CONTINUE
);
368 if (status
== HTTP_STATUS_ERROR
&& !retries
)
370 DEBUG_printf(("2cupsPutFd: retry on status %d", status
));
374 /* Flush any error message... */
378 if (httpReconnect2(http
, 30000, NULL
))
380 status
= HTTP_STATUS_ERROR
;
388 DEBUG_printf(("2cupsPutFd: status=%d", status
));
390 if (status
== HTTP_STATUS_UNAUTHORIZED
)
393 * Flush any error message...
399 * See if we can do authentication...
402 if (cupsDoAuthentication(http
, "PUT", resource
))
404 status
= HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED
;
408 if (httpReconnect2(http
, 30000, NULL
))
410 status
= HTTP_STATUS_ERROR
;
417 else if (status
== HTTP_STATUS_UPGRADE_REQUIRED
)
419 /* Flush any error message... */
423 if (httpReconnect2(http
, 30000, NULL
))
425 status
= HTTP_STATUS_ERROR
;
429 /* Upgrade with encryption... */
430 httpEncryption(http
, HTTP_ENCRYPTION_REQUIRED
);
432 /* Try again, this time with encryption enabled... */
435 #endif /* HAVE_SSL */
437 while (status
== HTTP_STATUS_UNAUTHORIZED
|| status
== HTTP_STATUS_UPGRADE_REQUIRED
||
438 (status
== HTTP_STATUS_ERROR
&& retries
< 2));
441 * See if we actually put the file or an error...
444 if (status
!= HTTP_STATUS_CREATED
)
446 _cupsSetHTTPError(status
);
450 DEBUG_printf(("1cupsPutFd: Returning %d...", status
));
457 * 'cupsPutFile()' - Put a file on the server.
459 * This function returns @code HTTP_CREATED@ when the file is stored
462 * @since CUPS 1.1.20/OS X 10.4@
465 http_status_t
/* O - HTTP status */
466 cupsPutFile(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
467 const char *resource
, /* I - Resource name */
468 const char *filename
) /* I - Filename */
470 int fd
; /* File descriptor */
471 http_status_t status
; /* Status */
475 * Range check input...
478 if (!http
|| !resource
|| !filename
)
481 http
->error
= EINVAL
;
483 return (HTTP_STATUS_ERROR
);
487 * Open the local file...
490 if ((fd
= open(filename
, O_RDONLY
)) < 0)
493 * Couldn't open the file!
498 return (HTTP_STATUS_ERROR
);
505 status
= cupsPutFd(http
, resource
, fd
);