2 * Get/put file functions for CUPS.
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products.
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
11 * Include necessary headers...
14 #include "cups-private.h"
17 #if defined(WIN32) || defined(__EMX__)
21 #endif /* WIN32 || __EMX__ */
25 * 'cupsGetFd()' - Get a file from the server.
27 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
29 * @since CUPS 1.1.20/macOS 10.4@
32 http_status_t
/* O - HTTP status */
33 cupsGetFd(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
34 const char *resource
, /* I - Resource name */
35 int fd
) /* I - File descriptor */
37 ssize_t bytes
; /* Number of bytes read */
38 char buffer
[8192]; /* Buffer for file */
39 http_status_t status
; /* HTTP status from server */
40 char if_modified_since
[HTTP_MAX_VALUE
];
41 /* If-Modified-Since header */
45 * Range check input...
48 DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)", (void *)http
, resource
, fd
));
50 if (!resource
|| fd
< 0)
55 return (HTTP_STATUS_ERROR
);
59 if ((http
= _cupsConnect()) == NULL
)
60 return (HTTP_STATUS_SERVICE_UNAVAILABLE
);
63 * Then send GET requests to the HTTP server...
66 strlcpy(if_modified_since
, httpGetField(http
, HTTP_FIELD_IF_MODIFIED_SINCE
),
67 sizeof(if_modified_since
));
71 if (!_cups_strcasecmp(httpGetField(http
, HTTP_FIELD_CONNECTION
), "close"))
73 httpClearFields(http
);
74 if (httpReconnect2(http
, 30000, NULL
))
76 status
= HTTP_STATUS_ERROR
;
81 httpClearFields(http
);
82 httpSetField(http
, HTTP_FIELD_AUTHORIZATION
, http
->authstring
);
83 httpSetField(http
, HTTP_FIELD_IF_MODIFIED_SINCE
, if_modified_since
);
85 if (httpGet(http
, resource
))
87 if (httpReconnect2(http
, 30000, NULL
))
89 status
= HTTP_STATUS_ERROR
;
94 status
= HTTP_STATUS_UNAUTHORIZED
;
99 while ((status
= httpUpdate(http
)) == HTTP_STATUS_CONTINUE
);
101 if (status
== HTTP_STATUS_UNAUTHORIZED
)
104 * Flush any error message...
110 * See if we can do authentication...
113 if (cupsDoAuthentication(http
, "GET", resource
))
115 status
= HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED
;
119 if (httpReconnect2(http
, 30000, NULL
))
121 status
= HTTP_STATUS_ERROR
;
128 else if (status
== HTTP_STATUS_UPGRADE_REQUIRED
)
130 /* Flush any error message... */
134 if (httpReconnect2(http
, 30000, NULL
))
136 status
= HTTP_STATUS_ERROR
;
140 /* Upgrade with encryption... */
141 httpEncryption(http
, HTTP_ENCRYPTION_REQUIRED
);
143 /* Try again, this time with encryption enabled... */
146 #endif /* HAVE_SSL */
148 while (status
== HTTP_STATUS_UNAUTHORIZED
|| status
== HTTP_STATUS_UPGRADE_REQUIRED
);
151 * See if we actually got the file or an error...
154 if (status
== HTTP_STATUS_OK
)
157 * Yes, copy the file...
160 while ((bytes
= httpRead2(http
, buffer
, sizeof(buffer
))) > 0)
161 write(fd
, buffer
, (size_t)bytes
);
165 _cupsSetHTTPError(status
);
170 * Return the request status...
173 DEBUG_printf(("1cupsGetFd: Returning %d...", status
));
180 * 'cupsGetFile()' - Get a file from the server.
182 * This function returns @code HTTP_STATUS_OK@ when the file is successfully retrieved.
184 * @since CUPS 1.1.20/macOS 10.4@
187 http_status_t
/* O - HTTP status */
188 cupsGetFile(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
189 const char *resource
, /* I - Resource name */
190 const char *filename
) /* I - Filename */
192 int fd
; /* File descriptor */
193 http_status_t status
; /* Status */
197 * Range check input...
200 if (!http
|| !resource
|| !filename
)
203 http
->error
= EINVAL
;
205 return (HTTP_STATUS_ERROR
);
212 if ((fd
= open(filename
, O_WRONLY
| O_EXCL
| O_TRUNC
)) < 0)
215 * Couldn't open the file!
220 return (HTTP_STATUS_ERROR
);
227 status
= cupsGetFd(http
, resource
, fd
);
230 * If the file couldn't be gotten, then remove the file...
235 if (status
!= HTTP_STATUS_OK
)
239 * Return the HTTP status code...
247 * 'cupsPutFd()' - Put a file on the server.
249 * This function returns @code HTTP_STATUS_CREATED@ when the file is stored
252 * @since CUPS 1.1.20/macOS 10.4@
255 http_status_t
/* O - HTTP status */
256 cupsPutFd(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
257 const char *resource
, /* I - Resource name */
258 int fd
) /* I - File descriptor */
260 ssize_t bytes
; /* Number of bytes read */
261 int retries
; /* Number of retries */
262 char buffer
[8192]; /* Buffer for file */
263 http_status_t status
; /* HTTP status from server */
267 * Range check input...
270 DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)", (void *)http
, resource
, fd
));
272 if (!resource
|| fd
< 0)
275 http
->error
= EINVAL
;
277 return (HTTP_STATUS_ERROR
);
281 if ((http
= _cupsConnect()) == NULL
)
282 return (HTTP_STATUS_SERVICE_UNAVAILABLE
);
285 * Then send PUT requests to the HTTP server...
292 if (!_cups_strcasecmp(httpGetField(http
, HTTP_FIELD_CONNECTION
), "close"))
294 httpClearFields(http
);
295 if (httpReconnect2(http
, 30000, NULL
))
297 status
= HTTP_STATUS_ERROR
;
302 DEBUG_printf(("2cupsPutFd: starting attempt, authstring=\"%s\"...",
305 httpClearFields(http
);
306 httpSetField(http
, HTTP_FIELD_AUTHORIZATION
, http
->authstring
);
307 httpSetField(http
, HTTP_FIELD_TRANSFER_ENCODING
, "chunked");
308 httpSetExpect(http
, HTTP_STATUS_CONTINUE
);
310 if (httpPut(http
, resource
))
312 if (httpReconnect2(http
, 30000, NULL
))
314 status
= HTTP_STATUS_ERROR
;
319 status
= HTTP_STATUS_UNAUTHORIZED
;
325 * Wait up to 1 second for a 100-continue response...
328 if (httpWait(http
, 1000))
329 status
= httpUpdate(http
);
331 status
= HTTP_STATUS_CONTINUE
;
333 if (status
== HTTP_STATUS_CONTINUE
)
339 lseek(fd
, 0, SEEK_SET
);
341 while ((bytes
= read(fd
, buffer
, sizeof(buffer
))) > 0)
344 if ((status
= httpUpdate(http
)) != HTTP_STATUS_CONTINUE
)
348 httpWrite2(http
, buffer
, (size_t)bytes
);
351 if (status
== HTTP_STATUS_CONTINUE
)
353 httpWrite2(http
, buffer
, 0);
355 while ((status
= httpUpdate(http
)) == HTTP_STATUS_CONTINUE
);
358 if (status
== HTTP_STATUS_ERROR
&& !retries
)
360 DEBUG_printf(("2cupsPutFd: retry on status %d", status
));
364 /* Flush any error message... */
368 if (httpReconnect2(http
, 30000, NULL
))
370 status
= HTTP_STATUS_ERROR
;
378 DEBUG_printf(("2cupsPutFd: status=%d", status
));
380 if (status
== HTTP_STATUS_UNAUTHORIZED
)
383 * Flush any error message...
389 * See if we can do authentication...
392 if (cupsDoAuthentication(http
, "PUT", resource
))
394 status
= HTTP_STATUS_CUPS_AUTHORIZATION_CANCELED
;
398 if (httpReconnect2(http
, 30000, NULL
))
400 status
= HTTP_STATUS_ERROR
;
407 else if (status
== HTTP_STATUS_UPGRADE_REQUIRED
)
409 /* Flush any error message... */
413 if (httpReconnect2(http
, 30000, NULL
))
415 status
= HTTP_STATUS_ERROR
;
419 /* Upgrade with encryption... */
420 httpEncryption(http
, HTTP_ENCRYPTION_REQUIRED
);
422 /* Try again, this time with encryption enabled... */
425 #endif /* HAVE_SSL */
427 while (status
== HTTP_STATUS_UNAUTHORIZED
|| status
== HTTP_STATUS_UPGRADE_REQUIRED
||
428 (status
== HTTP_STATUS_ERROR
&& retries
< 2));
431 * See if we actually put the file or an error...
434 if (status
!= HTTP_STATUS_CREATED
)
436 _cupsSetHTTPError(status
);
440 DEBUG_printf(("1cupsPutFd: Returning %d...", status
));
447 * 'cupsPutFile()' - Put a file on the server.
449 * This function returns @code HTTP_CREATED@ when the file is stored
452 * @since CUPS 1.1.20/macOS 10.4@
455 http_status_t
/* O - HTTP status */
456 cupsPutFile(http_t
*http
, /* I - Connection to server or @code CUPS_HTTP_DEFAULT@ */
457 const char *resource
, /* I - Resource name */
458 const char *filename
) /* I - Filename */
460 int fd
; /* File descriptor */
461 http_status_t status
; /* Status */
465 * Range check input...
468 if (!http
|| !resource
|| !filename
)
471 http
->error
= EINVAL
;
473 return (HTTP_STATUS_ERROR
);
477 * Open the local file...
480 if ((fd
= open(filename
, O_RDONLY
)) < 0)
483 * Couldn't open the file!
488 return (HTTP_STATUS_ERROR
);
495 status
= cupsPutFd(http
, resource
, fd
);