]> git.ipfire.org Git - thirdparty/cups.git/blob - cups/getputfile.c
Merge changes from CUPS trunk, r6739.
[thirdparty/cups.git] / cups / getputfile.c
1 /*
2 * "$Id: getputfile.c 6720 2007-07-25 00:40:03Z mike $"
3 *
4 * Get/put file functions for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2007 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
8 *
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/".
14 *
15 * This file is subject to the Apple OS-Developed Software exception.
16 *
17 * Contents:
18 *
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.
23 */
24
25 /*
26 * Include necessary headers...
27 */
28
29 #include "globals.h"
30 #include "cups.h"
31 #include "language.h"
32 #include "debug.h"
33 #include <stdlib.h>
34 #include <ctype.h>
35 #include <errno.h>
36 #include <fcntl.h>
37 #include <sys/stat.h>
38 #if defined(WIN32) || defined(__EMX__)
39 # include <io.h>
40 #else
41 # include <unistd.h>
42 #endif /* WIN32 || __EMX__ */
43
44
45 /*
46 * 'cupsGetFd()' - Get a file from the server.
47 *
48 * This function returns HTTP_OK when the file is successfully retrieved.
49 *
50 * @since CUPS 1.1.20@
51 */
52
53 http_status_t /* O - HTTP status */
54 cupsGetFd(http_t *http, /* I - HTTP connection to server */
55 const char *resource, /* I - Resource name */
56 int fd) /* I - File descriptor */
57 {
58 int bytes; /* Number of bytes read */
59 char buffer[8192]; /* Buffer for file */
60 http_status_t status; /* HTTP status from server */
61 char if_modified_since[HTTP_MAX_VALUE];
62 /* If-Modified-Since header */
63
64
65 /*
66 * Range check input...
67 */
68
69 DEBUG_printf(("cupsGetFd(http=%p, resource=\"%s\", fd=%d)\n", http,
70 resource, fd));
71
72 if (!http || !resource || fd < 0)
73 {
74 if (http)
75 http->error = EINVAL;
76
77 return (HTTP_ERROR);
78 }
79
80 /*
81 * Then send GET requests to the HTTP server...
82 */
83
84 strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE),
85 sizeof(if_modified_since));
86
87 do
88 {
89 httpClearFields(http);
90 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
91 httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since);
92
93 if (httpGet(http, resource))
94 {
95 if (httpReconnect(http))
96 {
97 status = HTTP_ERROR;
98 break;
99 }
100 else
101 {
102 status = HTTP_UNAUTHORIZED;
103 continue;
104 }
105 }
106
107 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
108
109 if (status == HTTP_UNAUTHORIZED)
110 {
111 /*
112 * Flush any error message...
113 */
114
115 httpFlush(http);
116
117 /*
118 * See if we can do authentication...
119 */
120
121 if (cupsDoAuthentication(http, "GET", resource))
122 break;
123
124 if (httpReconnect(http))
125 {
126 status = HTTP_ERROR;
127 break;
128 }
129
130 continue;
131 }
132 #ifdef HAVE_SSL
133 else if (status == HTTP_UPGRADE_REQUIRED)
134 {
135 /* Flush any error message... */
136 httpFlush(http);
137
138 /* Reconnect... */
139 if (httpReconnect(http))
140 {
141 status = HTTP_ERROR;
142 break;
143 }
144
145 /* Upgrade with encryption... */
146 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
147
148 /* Try again, this time with encryption enabled... */
149 continue;
150 }
151 #endif /* HAVE_SSL */
152 }
153 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED);
154
155 /*
156 * See if we actually got the file or an error...
157 */
158
159 if (status == HTTP_OK)
160 {
161 /*
162 * Yes, copy the file...
163 */
164
165 while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
166 write(fd, buffer, bytes);
167 }
168 else
169 {
170 _cupsSetHTTPError(status);
171 httpFlush(http);
172 }
173
174 /*
175 * Return the request status...
176 */
177
178 return (status);
179 }
180
181
182 /*
183 * 'cupsGetFile()' - Get a file from the server.
184 *
185 * This function returns HTTP_OK when the file is successfully retrieved.
186 *
187 * @since CUPS 1.1.20@
188 */
189
190 http_status_t /* O - HTTP status */
191 cupsGetFile(http_t *http, /* I - HTTP connection to server */
192 const char *resource, /* I - Resource name */
193 const char *filename) /* I - Filename */
194 {
195 int fd; /* File descriptor */
196 http_status_t status; /* Status */
197
198
199 /*
200 * Range check input...
201 */
202
203 if (!http || !resource || !filename)
204 {
205 if (http)
206 http->error = EINVAL;
207
208 return (HTTP_ERROR);
209 }
210
211 /*
212 * Create the file...
213 */
214
215 if ((fd = open(filename, O_WRONLY | O_EXCL | O_TRUNC)) < 0)
216 {
217 /*
218 * Couldn't open the file!
219 */
220
221 http->error = errno;
222
223 return (HTTP_ERROR);
224 }
225
226 /*
227 * Get the file...
228 */
229
230 status = cupsGetFd(http, resource, fd);
231
232 /*
233 * If the file couldn't be gotten, then remove the file...
234 */
235
236 close(fd);
237
238 if (status != HTTP_OK)
239 unlink(filename);
240
241 /*
242 * Return the HTTP status code...
243 */
244
245 return (status);
246 }
247
248
249 /*
250 * 'cupsPutFd()' - Put a file on the server.
251 *
252 * This function returns HTTP_CREATED when the file is stored successfully.
253 *
254 * @since CUPS 1.1.20@
255 */
256
257 http_status_t /* O - HTTP status */
258 cupsPutFd(http_t *http, /* I - HTTP connection to server */
259 const char *resource, /* I - Resource name */
260 int fd) /* I - File descriptor */
261 {
262 int bytes, /* Number of bytes read */
263 retries; /* Number of retries */
264 char buffer[8192]; /* Buffer for file */
265 http_status_t status; /* HTTP status from server */
266
267
268 /*
269 * Range check input...
270 */
271
272 DEBUG_printf(("cupsPutFd(http=%p, resource=\"%s\", fd=%d)\n", http,
273 resource, fd));
274
275 if (!http || !resource || fd < 0)
276 {
277 if (http)
278 http->error = EINVAL;
279
280 return (HTTP_ERROR);
281 }
282
283 /*
284 * Then send PUT requests to the HTTP server...
285 */
286
287 retries = 0;
288
289 do
290 {
291 DEBUG_printf(("cupsPutFd: starting attempt, authstring=\"%s\"...\n",
292 http->authstring));
293
294 httpClearFields(http);
295 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
296 httpSetField(http, HTTP_FIELD_TRANSFER_ENCODING, "chunked");
297 httpSetExpect(http, HTTP_CONTINUE);
298
299 if (httpPut(http, resource))
300 {
301 if (httpReconnect(http))
302 {
303 status = HTTP_ERROR;
304 break;
305 }
306 else
307 {
308 status = HTTP_UNAUTHORIZED;
309 continue;
310 }
311 }
312
313 /*
314 * Wait up to 1 second for a 100-continue response...
315 */
316
317 if (httpWait(http, 1000))
318 status = httpUpdate(http);
319 else
320 status = HTTP_CONTINUE;
321
322 if (status == HTTP_CONTINUE)
323 {
324 /*
325 * Copy the file...
326 */
327
328 lseek(fd, 0, SEEK_SET);
329
330 while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
331 if (httpCheck(http))
332 {
333 if ((status = httpUpdate(http)) != HTTP_CONTINUE)
334 break;
335 }
336 else
337 httpWrite2(http, buffer, bytes);
338 }
339
340 if (status == HTTP_CONTINUE)
341 {
342 httpWrite2(http, buffer, 0);
343
344 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
345 }
346
347 if (status == HTTP_ERROR && !retries)
348 {
349 DEBUG_printf(("cupsPutFd: retry on status %d\n", status));
350
351 retries ++;
352
353 /* Flush any error message... */
354 httpFlush(http);
355
356 /* Reconnect... */
357 if (httpReconnect(http))
358 {
359 status = HTTP_ERROR;
360 break;
361 }
362
363 /* Try again... */
364 continue;
365 }
366
367 DEBUG_printf(("cupsPutFd: status=%d\n", status));
368
369 if (status == HTTP_UNAUTHORIZED)
370 {
371 /*
372 * Flush any error message...
373 */
374
375 httpFlush(http);
376
377 /*
378 * See if we can do authentication...
379 */
380
381 if (cupsDoAuthentication(http, "PUT", resource))
382 break;
383
384 if (httpReconnect(http))
385 {
386 status = HTTP_ERROR;
387 break;
388 }
389
390 continue;
391 }
392 #ifdef HAVE_SSL
393 else if (status == HTTP_UPGRADE_REQUIRED)
394 {
395 /* Flush any error message... */
396 httpFlush(http);
397
398 /* Reconnect... */
399 if (httpReconnect(http))
400 {
401 status = HTTP_ERROR;
402 break;
403 }
404
405 /* Upgrade with encryption... */
406 httpEncryption(http, HTTP_ENCRYPT_REQUIRED);
407
408 /* Try again, this time with encryption enabled... */
409 continue;
410 }
411 #endif /* HAVE_SSL */
412 }
413 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED ||
414 (status == HTTP_ERROR && retries < 2));
415
416 /*
417 * See if we actually put the file or an error...
418 */
419
420 if (status != HTTP_CREATED)
421 {
422 _cupsSetHTTPError(status);
423 httpFlush(http);
424 }
425
426 return (status);
427 }
428
429
430 /*
431 * 'cupsPutFile()' - Put a file on the server.
432 *
433 * This function returns HTTP_CREATED when the file is stored successfully.
434 *
435 * @since CUPS 1.1.20@
436 */
437
438 http_status_t /* O - HTTP status */
439 cupsPutFile(http_t *http, /* I - HTTP connection to server */
440 const char *resource, /* I - Resource name */
441 const char *filename) /* I - Filename */
442 {
443 int fd; /* File descriptor */
444 http_status_t status; /* Status */
445
446
447 /*
448 * Range check input...
449 */
450
451 if (!http || !resource || !filename)
452 {
453 if (http)
454 http->error = EINVAL;
455
456 return (HTTP_ERROR);
457 }
458
459 /*
460 * Open the local file...
461 */
462
463 if ((fd = open(filename, O_RDONLY)) < 0)
464 {
465 /*
466 * Couldn't open the file!
467 */
468
469 http->error = errno;
470
471 return (HTTP_ERROR);
472 }
473
474 /*
475 * Put the file...
476 */
477
478 status = cupsPutFd(http, resource, fd);
479
480 close(fd);
481
482 return (status);
483 }
484
485
486 /*
487 * End of "$Id: getputfile.c 6720 2007-07-25 00:40:03Z mike $".
488 */