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