4 * Get/put file functions for CUPS.
6 * Copyright 2007-2013 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 * cupsGetFd() - Get a file from the server.
20 * cupsGetFile() - Get a file from the server.
21 * cupsPutFd() - Put a file on the server.
22 * cupsPutFile() - Put a file on the server.
26 * Include necessary headers...
29 #include "cups-private.h"
32 #if defined(WIN32) || defined(__EMX__)
36 #endif /* WIN32 || __EMX__ */
40 * 'cupsGetFd()' - Get a file from the server.
42 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
44 * @since CUPS 1.1.20/OS X 10.4@
47 http_status_t
/* O - HTTP status */
48 cupsGetFd(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
49 const char *resource
, /* I - Resource name */
50 int fd
) /* I - File descriptor */
52 int bytes
; /* Number of bytes read */
53 char buffer
[8192]; /* Buffer for file */
54 http_status_t status
; /* HTTP status from server */
55 char if_modified_since
[HTTP_MAX_VALUE
];
56 /* If-Modified-Since header */
60 * Range check input...
63 DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", http
,
66 if (!resource
|| fd
< 0)
71 return (HTTP_STATUS_ERROR
);
75 if ((http
= _cupsConnect()) == NULL
)
76 return (HTTP_STATUS_SERVICE_UNAVAILABLE
);
79 * Then send GET requests to the HTTP server...
82 strlcpy(if_modified_since
, httpGetField(http
, HTTP_FIELD_IF_MODIFIED_SINCE
),
83 sizeof(if_modified_since
));
87 if (!_cups_strcasecmp(httpGetField(http
, HTTP_FIELD_CONNECTION
), "close"))
89 httpClearFields(http
);
90 if (httpReconnect2(http
, 30000, NULL
))
92 status
= HTTP_STATUS_ERROR
;
97 httpClearFields(http
);
98 httpSetField(http
, HTTP_FIELD_AUTHORIZATION
, http
->authstring
);
99 httpSetField(http
, HTTP_FIELD_IF_MODIFIED_SINCE
, if_modified_since
);
101 if (httpGet(http
, resource
))
103 if (httpReconnect2(http
, 30000, NULL
))
105 status
= HTTP_STATUS_ERROR
;
110 status
= HTTP_STATUS_UNAUTHORIZED
;
115 while ((status
= httpUpdate(http
)) == HTTP_STATUS_CONTINUE
);
117 if (status
== HTTP_STATUS_UNAUTHORIZED
)
120 * Flush any error message...
126 * See if we can do authentication...
129 if (cupsDoAuthentication(http
, "GET", resource
))
131 status
= HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED
;
135 if (httpReconnect2(http
, 30000, NULL
))
137 status
= HTTP_STATUS_ERROR
;
144 else if (status
== HTTP_STATUS_UPGRADE_REQUIRED
)
146 /* Flush any error message... */
150 if (httpReconnect2(http
, 30000, NULL
))
152 status
= HTTP_STATUS_ERROR
;
156 /* Upgrade with encryption... */
157 httpEncryption(http
, HTTP_ENCRYPTION_REQUIRED
);
159 /* Try again, this time with encryption enabled... */
162 #endif /* HAVE_SSL */
164 while (status
== HTTP_STATUS_UNAUTHORIZED
|| status
== HTTP_STATUS_UPGRADE_REQUIRED
);
167 * See if we actually got the file or an error...
170 if (status
== HTTP_STATUS_OK
)
173 * Yes, copy the file...
176 while ((bytes
= httpRead2(http
, buffer
, sizeof(buffer
))) > 0)
177 write(fd
, buffer
, bytes
);
181 _cupsSetHTTPError(status
);
186 * Return the request status...
189 DEBUG_printf(("1cupsGetFd: Returning %d...", status
));
196 * 'cupsGetFile()' - Get a file from the server.
198 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
200 * @since CUPS 1.1.20/OS X 10.4@
203 http_status_t
/* O - HTTP status */
204 cupsGetFile(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
205 const char *resource
, /* I - Resource name */
206 const char *filename
) /* I - Filename */
208 int fd
; /* File descriptor */
209 http_status_t status
; /* Status */
213 * Range check input...
216 if (!http
|| !resource
|| !filename
)
219 http
->error
= EINVAL
;
221 return (HTTP_STATUS_ERROR
);
228 if ((fd
= open(filename
, O_WRONLY
| O_EXCL
| O_TRUNC
)) < 0)
231 * Couldn't open the file!
236 return (HTTP_STATUS_ERROR
);
243 status
= cupsGetFd(http
, resource
, fd
);
246 * If the file couldn't be gotten, then remove the file...
251 if (status
!= HTTP_STATUS_OK
)
255 * Return the HTTP status code...
263 * 'cupsPutFd()' - Put a file on the server.
265 * This function returns @code HTTP_STATUS_CREATED@ when the file is stored
268 * @since CUPS 1.1.20/OS X 10.4@
271 http_status_t
/* O - HTTP status */
272 cupsPutFd(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
273 const char *resource
, /* I - Resource name */
274 int fd
) /* I - File descriptor */
276 int bytes
, /* Number of bytes read */
277 retries
; /* Number of retries */
278 char buffer
[8192]; /* Buffer for file */
279 http_status_t status
; /* HTTP status from server */
283 * Range check input...
286 DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", http
,
289 if (!resource
|| fd
< 0)
292 http
->error
= EINVAL
;
294 return (HTTP_STATUS_ERROR
);
298 if ((http
= _cupsConnect()) == NULL
)
299 return (HTTP_STATUS_SERVICE_UNAVAILABLE
);
302 * Then send PUT requests to the HTTP server...
309 if (!_cups_strcasecmp(httpGetField(http
, HTTP_FIELD_CONNECTION
), "close"))
311 httpClearFields(http
);
312 if (httpReconnect2(http
, 30000, NULL
))
314 status
= HTTP_STATUS_ERROR
;
319 DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
322 httpClearFields(http
);
323 httpSetField(http
, HTTP_FIELD_AUTHORIZATION
, http
->authstring
);
324 httpSetField(http
, HTTP_FIELD_TRANSFER_ENCODING
, "chunked");
325 httpSetExpect(http
, HTTP_STATUS_CONTINUE
);
327 if (httpPut(http
, resource
))
329 if (httpReconnect2(http
, 30000, NULL
))
331 status
= HTTP_STATUS_ERROR
;
336 status
= HTTP_STATUS_UNAUTHORIZED
;
342 * Wait up to 1 second for a 100-continue response...
345 if (httpWait(http
, 1000))
346 status
= httpUpdate(http
);
348 status
= HTTP_STATUS_CONTINUE
;
350 if (status
== HTTP_STATUS_CONTINUE
)
356 lseek(fd
, 0, SEEK_SET
);
358 while ((bytes
= read(fd
, buffer
, sizeof(buffer
))) > 0)
361 if ((status
= httpUpdate(http
)) != HTTP_STATUS_CONTINUE
)
365 httpWrite2(http
, buffer
, bytes
);
368 if (status
== HTTP_STATUS_CONTINUE
)
370 httpWrite2(http
, buffer
, 0);
372 while ((status
= httpUpdate(http
)) == HTTP_STATUS_CONTINUE
);
375 if (status
== HTTP_STATUS_ERROR
&& !retries
)
377 DEBUG_printf(("2cupsPutFd: retry on status %d", status
));
381 /* Flush any error message... */
385 if (httpReconnect2(http
, 30000, NULL
))
387 status
= HTTP_STATUS_ERROR
;
395 DEBUG_printf(("2cupsPutFd: status=%d", status
));
397 if (status
== HTTP_STATUS_UNAUTHORIZED
)
400 * Flush any error message...
406 * See if we can do authentication...
409 if (cupsDoAuthentication(http
, "PUT", resource
))
411 status
= HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED
;
415 if (httpReconnect2(http
, 30000, NULL
))
417 status
= HTTP_STATUS_ERROR
;
424 else if (status
== HTTP_STATUS_UPGRADE_REQUIRED
)
426 /* Flush any error message... */
430 if (httpReconnect2(http
, 30000, NULL
))
432 status
= HTTP_STATUS_ERROR
;
436 /* Upgrade with encryption... */
437 httpEncryption(http
, HTTP_ENCRYPTION_REQUIRED
);
439 /* Try again, this time with encryption enabled... */
442 #endif /* HAVE_SSL */
444 while (status
== HTTP_STATUS_UNAUTHORIZED
|| status
== HTTP_STATUS_UPGRADE_REQUIRED
||
445 (status
== HTTP_STATUS_ERROR
&& retries
< 2));
448 * See if we actually put the file or an error...
451 if (status
!= HTTP_STATUS_CREATED
)
453 _cupsSetHTTPError(status
);
457 DEBUG_printf(("1cupsPutFd: Returning %d...", status
));
464 * 'cupsPutFile()' - Put a file on the server.
466 * This function returns @code HTTP_CREATED@ when the file is stored
469 * @since CUPS 1.1.20/OS X 10.4@
472 http_status_t
/* O - HTTP status */
473 cupsPutFile(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
474 const char *resource
, /* I - Resource name */
475 const char *filename
) /* I - Filename */
477 int fd
; /* File descriptor */
478 http_status_t status
; /* Status */
482 * Range check input...
485 if (!http
|| !resource
|| !filename
)
488 http
->error
= EINVAL
;
490 return (HTTP_STATUS_ERROR
);
494 * Open the local file...
497 if ((fd
= open(filename
, O_RDONLY
)) < 0)
500 * Couldn't open the file!
505 return (HTTP_STATUS_ERROR
);
512 status
= cupsPutFd(http
, resource
, fd
);