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