Annotation of libwww/Library/src/HTFSave.c, revision 2.3
2.1 frystyk 1: /*
2: ** VARIOUS FILE WRITER STREAMS
3: **
4: ** (c) COPYRIGHT MIT 1995.
5: ** Please first read the full copyright statement in the file COPYRIGH.
2.3 ! frystyk 6: ** @(#) $Id: HTFSave.c,v 2.2 1999/02/22 22:10:11 frystyk Exp $
2.1 frystyk 7: **
8: ** This version of the stream object just writes to a C file.
9: ** The file is assumed open and left open.
10: **
11: ** Bugs:
12: ** strings written must be less than buffer size.
13: **
14: ** History:
15: ** HFN: wrote it
16: ** HWL: converted the caching scheme to be hierachical by taking
17: ** AL code from Deamon
18: ** HFN: moved cache code to HTCache module
19: **
20: */
21:
22: /* Library include files */
23: #include "wwwsys.h"
24: #include "WWWUtil.h"
25: #include "WWWCore.h"
26: #include "HTBind.h"
27: #include "HTFWrite.h"
28: #include "HTFSave.h" /* Implemented here */
29:
30: struct _HTStream {
31: const HTStreamClass *isa;
32: HTStream * target;
33: char * end_command; /* Command to execute */
34: BOOL remove_on_close; /* Remove file? */
35: char * filename; /* Name of file */
36: HTRequest * request; /* Saved for callback */
37: HTRequestCallback * callback;
38: };
39:
40: #define DEFAULT_LAST_SEGMENT "index"
41:
42: /* ------------------------------------------------------------------------- */
43:
44: PRIVATE int HTFileSave_flush (HTStream * me)
45: {
46: return (*me->target->isa->flush)(me->target);
47: }
48:
49: PRIVATE int HTFileSave_put_character (HTStream * me, char c)
50: {
51: return (*me->target->isa->put_character)(me->target, c);
52: }
53:
54: PRIVATE int HTFileSave_put_string (HTStream * me, const char * s)
55: {
56: return (*me->target->isa->put_string)(me->target, s);
57: }
58:
59: PRIVATE int HTFileSave_write (HTStream * me, const char * b, int l)
60: {
61: return (*me->target->isa->put_block)(me->target, b, l);
62: }
63:
64: PRIVATE int HTFileSave_free (HTStream * me)
65: {
66: if (me) {
67: (*me->target->isa->_free)(me->target);
68: #ifdef HAVE_SYSTEM
69: if (me->end_command) system(me->end_command); /* SECURITY HOLE!!! */
70: #endif
71: if (me->callback) (*me->callback)(me->request, me->filename);
72: if (me->remove_on_close) REMOVE(me->filename);
73: HT_FREE(me->end_command);
74: HT_FREE(me->filename);
75: HT_FREE(me);
76: }
77: return HT_OK;
78: }
79:
80: PRIVATE int HTFileSave_abort (HTStream * me, HTList * e)
81: {
2.2 frystyk 82: HTTRACE(STREAM_TRACE, "Save File.. ABORTING...\n");
2.1 frystyk 83: if (me) {
84: (*me->target->isa->abort)(me->target, e);
85: if (me->remove_on_close) REMOVE(me->filename);
86: HT_FREE(me->end_command);
87: HT_FREE(me->filename);
88: HT_FREE(me);
89: }
90: return HT_ERROR;
91: }
92:
93: PRIVATE const HTStreamClass HTFileSave =
94: {
95: "FileSave",
96: HTFileSave_flush,
97: HTFileSave_free,
98: HTFileSave_abort,
99: HTFileSave_put_character,
100: HTFileSave_put_string,
101: HTFileSave_write
102: };
103:
104: PUBLIC HTStream * HTFileSave_new (HTRequest * request, FILE * fp,
105: BOOL leave_open)
106: {
107: HTStream * me = NULL;
108: if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
109: HT_OUTOFMEM("HTFileSave_new");
110: me->isa = &HTFileSave;
111: me->target = HTFWriter_new(request, fp, leave_open);
112: me->request = request;
113: return me;
114: }
115:
116: /* ------------------------------------------------------------------------- */
117:
118: /*
119: ** This function tries really hard to find a non-existent filename relative
120: ** to the path given. Returns a string that must be freed by the caller or
121: ** NULL on error.
122: */
123: PRIVATE char * get_filename (char * base, const char * uri,
124: const char * suffix, BOOL use_last_segment)
125: {
126: char * path = NULL;
127: if (use_last_segment) {
128: char * uri_path = NULL;
129: if (uri && (uri_path = HTParse(uri, "", PARSE_PATH|PARSE_PUNCTUATION))) {
130: char * last_segment = strrchr(uri_path, '/');
131: BOOL slash = (base && *(base+strlen(base)-1)=='/');
132: if (last_segment && *(last_segment+1)) {
133: StrAllocMCopy(&path, base ? base : "",
2.3 ! frystyk 134: slash ? "" : DIR_SEPARATOR_STR, ++last_segment, NULL);
2.1 frystyk 135: } else {
136: StrAllocMCopy(&path, base ? base : "",
2.3 ! frystyk 137: slash ? "" : DIR_SEPARATOR_STR, DEFAULT_LAST_SEGMENT,
2.1 frystyk 138: suffix ? suffix : "", NULL);
139: }
140: }
141: } else {
142: path = HTGetTmpFileName(base);
143: if (path && suffix) StrAllocCat(path, suffix);
144: }
145:
2.2 frystyk 146: HTTRACE(STREAM_TRACE, "Save file... Temporaray file `%s\'\n" _ path ? path : "<null>");
2.1 frystyk 147: return path;
148: }
149:
150: /* Save Locally
151: ** ------------
152: ** Saves a file to local disk. This can for example be used to dump
153: ** data objects of unknown media types to local disk. The stream prompts
154: ** for a file name for the temporary file.
155: */
156: PUBLIC HTStream* HTSaveLocally (HTRequest * request,
157: void * param,
158: HTFormat input_format,
159: HTFormat output_format,
160: HTStream * output_stream)
161: {
162: FILE * fp = NULL;
163: char * filename = NULL;
164: HTUserProfile * up = HTRequest_userProfile(request);
165: char * tmproot = HTUserProfile_tmp(up);
166: if (HTLib_secure()) {
167: HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_UNAUTHORIZED,
168: NULL, 0, "HTSaveLocally");
169: return HTErrorStream();
170: }
171: if (!tmproot) {
2.2 frystyk 172: HTTRACE(STREAM_TRACE, "Save File... turned off\n");
2.1 frystyk 173: return HTErrorStream();
174: }
175:
176: /* Let's prompt the user for a file name for this file */
177: {
178: HTAlertCallback *cbf = HTAlert_find(HT_A_PROMPT);
179: HTParentAnchor *anchor = (HTParentAnchor *) HTRequest_anchor(request);
180:
181: /*
182: ** If we found an alert handler for prompting the user then call it.
183: ** If not then either we are in non-interactive mode or no handler
184: ** has been registered. For now we then return a blackhole which may
185: ** not be the best thing to do.
186: */
187: if (cbf) {
188: HTAlertPar * reply = HTAlert_newReply();
189: char * suffix = HTBind_getSuffix(anchor);
190: char * deflt = get_filename(tmproot, HTAnchor_physical(anchor), suffix, YES);
191: if ((*cbf)(request, HT_A_PROMPT, HT_MSG_FILENAME,deflt,NULL,reply))
192: filename = HTAlert_replyMessage(reply);
193: HTAlert_deleteReply(reply);
194: HT_FREE(suffix);
195: HT_FREE(deflt);
196: }
197: if (filename) {
198: if ((fp = fopen(filename, "wb")) == NULL) {
199: HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_NO_FILE,
200: filename, strlen(filename),"HTSaveLocally");
201: HT_FREE(filename);
202: return HTErrorStream();
203: }
204: } else if (cbf) {
2.2 frystyk 205: HTTRACE(STREAM_TRACE, "Save File... No file name - error stream\n");
2.1 frystyk 206: return HTErrorStream();
207: } else {
2.2 frystyk 208: HTTRACE(STREAM_TRACE, "Save File... No file name - black hole\n");
2.1 frystyk 209: return HTBlackHole();
210: }
211: }
212:
213: /* Now we are ready for creating the file writer stream */
214: if (fp) {
215: HTStream * me = HTFileSave_new(request, fp, NO);
216: me->filename = filename;
217: return me;
218: }
219: HT_FREE(filename);
220: return HTErrorStream();
221: }
222:
223: /* Take action using a system command
224: ** ----------------------------------
225: ** Creates temporary file, writes to it and then executes system
226: ** command (maybe an external viewer) when EOF has been reached. The
227: ** stream finds a suitable name of the temporary file which preserves the
228: ** suffix. This way, the system command can find out the file type from
229: ** the name of the temporary file name.
230: */
231: PUBLIC HTStream* HTSaveAndExecute (HTRequest * request,
232: void * param,
233: HTFormat input_format,
234: HTFormat output_format,
235: HTStream * output_stream)
236: {
237: FILE * fp = NULL;
238: char * filename = NULL;
239: HTUserProfile * up = HTRequest_userProfile(request);
240: char * tmproot = HTUserProfile_tmp(up);
241: if (HTLib_secure()) {
242: HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_UNAUTHORIZED,
243: NULL, 0, "HTSaveLocally");
244: return HTErrorStream();
245: }
246: if (!tmproot) {
2.2 frystyk 247: HTTRACE(STREAM_TRACE, "Save File... turned off");
2.1 frystyk 248: return HTErrorStream();
249: }
250:
251: /* Let's find a hash name for this file without asking user */
252: {
253: HTParentAnchor *anchor = (HTParentAnchor *) HTRequest_anchor(request);
254: char *suffix = HTBind_getSuffix(anchor);
255: filename = get_filename(tmproot, HTAnchor_physical(anchor), suffix, NO);
256: HT_FREE(suffix);
257: if (filename) {
258: if ((fp = fopen(filename, "wb")) == NULL) {
259: HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_NO_FILE,
260: filename, strlen(filename),"HTSaveAndExecute");
261: HT_FREE(filename);
262: return HTErrorStream();
263: }
264: } else {
2.2 frystyk 265: HTTRACE(STREAM_TRACE, "Save File... No file name\n");
2.1 frystyk 266: return HTErrorStream();
267: }
268: }
269:
270: /* Now we are ready for creating the file writer stream */
271: if (fp) {
272: HTStream * me = HTFileSave_new(request, fp, NO);
273: me->filename = filename;
274: if (param) {
275: if ((me->end_command = (char *) HT_MALLOC((strlen((char *) param) + 10 + 3*strlen(filename)))) == NULL)
276: HT_OUTOFMEM("SaveAndExecute");
277: sprintf (me->end_command,
278: (char *)param, filename, filename, filename);
279: }
280: return me;
281: }
282: HT_FREE(filename);
283: return HTErrorStream();
284: }
285:
286: /* Save and Call Back
287: ** ------------------
288: ** This stream works exactly like the HTSaveAndExecute
289: ** stream but in addition when EOF has been reached, it checks whether a
290: ** callback function has been associated with the request object in which
291: ** case, this callback is being called. This can be use by the
292: ** application to do some processing after the system command
293: ** has terminated. The callback function is called with the file name of
294: ** the temporary file as parameter.
295: */
296: PUBLIC HTStream* HTSaveAndCallback (HTRequest * request,
297: void * param,
298: HTFormat input_format,
299: HTFormat output_format,
300: HTStream * output_stream)
301: {
302: HTStream * me = HTSaveAndExecute(request, param, input_format,
303: output_format, output_stream);
304: if (me) {
305: me->callback = HTRequest_callback(request);
306: return me;
307: }
308: return HTErrorStream();
309: }
Webmaster