]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/getputfile.c
Merge changes from CUPS trunk, r6739.
[thirdparty/cups.git] / cups / getputfile.c
CommitLineData
ef416fc2 1/*
355e94dc 2 * "$Id: getputfile.c 6720 2007-07-25 00:40:03Z mike $"
ef416fc2 3 *
4 * Get/put file functions for the Common UNIX Printing System (CUPS).
5 *
bc44d920 6 * Copyright 2007 by Apple Inc.
ef416fc2 7 * Copyright 1997-2006 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
bc44d920 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/".
ef416fc2 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
355e94dc 29#include "globals.h"
ef416fc2 30#include "cups.h"
ef416fc2 31#include "language.h"
ef416fc2 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
ecdc0628 53http_status_t /* O - HTTP status */
ef416fc2 54cupsGetFd(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 */
757d2cad 61 char if_modified_since[HTTP_MAX_VALUE];
62 /* If-Modified-Since header */
ef416fc2 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
757d2cad 84 strlcpy(if_modified_since, httpGetField(http, HTTP_FIELD_IF_MODIFIED_SINCE),
85 sizeof(if_modified_since));
86
ef416fc2 87 do
88 {
89 httpClearFields(http);
90 httpSetField(http, HTTP_FIELD_AUTHORIZATION, http->authstring);
757d2cad 91 httpSetField(http, HTTP_FIELD_IF_MODIFIED_SINCE, if_modified_since);
ef416fc2 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
fa73b229 124 if (httpReconnect(http))
125 {
126 status = HTTP_ERROR;
127 break;
128 }
ef416fc2 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... */
fa73b229 139 if (httpReconnect(http))
140 {
141 status = HTTP_ERROR;
142 break;
143 }
ef416fc2 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
a4d04587 165 while ((bytes = httpRead2(http, buffer, sizeof(buffer))) > 0)
ef416fc2 166 write(fd, buffer, bytes);
167 }
168 else
355e94dc
MS
169 {
170 _cupsSetHTTPError(status);
ef416fc2 171 httpFlush(http);
355e94dc 172 }
ef416fc2 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
ecdc0628 190http_status_t /* O - HTTP status */
ef416fc2 191cupsGetFile(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
ecdc0628 257http_status_t /* O - HTTP status */
ef416fc2 258cupsPutFd(http_t *http, /* I - HTTP connection to server */
259 const char *resource, /* I - Resource name */
260 int fd) /* I - File descriptor */
261{
bd7854cb 262 int bytes, /* Number of bytes read */
263 retries; /* Number of retries */
ef416fc2 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
bd7854cb 287 retries = 0;
288
ef416fc2 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");
b423cd4c 297 httpSetExpect(http, HTTP_CONTINUE);
ef416fc2 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 /*
b423cd4c 314 * Wait up to 1 second for a 100-continue response...
ef416fc2 315 */
316
b423cd4c 317 if (httpWait(http, 1000))
318 status = httpUpdate(http);
319 else
320 status = HTTP_CONTINUE;
ef416fc2 321
b423cd4c 322 if (status == HTTP_CONTINUE)
323 {
324 /*
325 * Copy the file...
326 */
ef416fc2 327
b423cd4c 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 }
ef416fc2 339
340 if (status == HTTP_CONTINUE)
341 {
a4d04587 342 httpWrite2(http, buffer, 0);
ef416fc2 343
344 while ((status = httpUpdate(http)) == HTTP_CONTINUE);
345 }
346
bd7854cb 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
ef416fc2 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
fa73b229 384 if (httpReconnect(http))
385 {
386 status = HTTP_ERROR;
387 break;
388 }
ef416fc2 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... */
fa73b229 399 if (httpReconnect(http))
400 {
401 status = HTTP_ERROR;
402 break;
403 }
ef416fc2 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 }
bd7854cb 413 while (status == HTTP_UNAUTHORIZED || status == HTTP_UPGRADE_REQUIRED ||
414 (status == HTTP_ERROR && retries < 2));
ef416fc2 415
416 /*
417 * See if we actually put the file or an error...
418 */
419
420 if (status != HTTP_CREATED)
355e94dc
MS
421 {
422 _cupsSetHTTPError(status);
ef416fc2 423 httpFlush(http);
355e94dc 424 }
ef416fc2 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
ecdc0628 438http_status_t /* O - HTTP status */
ef416fc2 439cupsPutFile(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/*
355e94dc 487 * End of "$Id: getputfile.c 6720 2007-07-25 00:40:03Z mike $".
ef416fc2 488 */