Annotation of libwww/Library/src/HTFSave.c, revision 2.1
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.
! 6: ** @(#) $Id: HTFWrite.c,v 2.44 1998/10/20 13:11:59 frystyk Exp $
! 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: {
! 82: if (STREAM_TRACE) HTTrace("Save File.. ABORTING...\n");
! 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 : "",
! 134: slash ? "" : "/", ++last_segment, NULL);
! 135: } else {
! 136: StrAllocMCopy(&path, base ? base : "",
! 137: slash ? "" : "/", DEFAULT_LAST_SEGMENT,
! 138: suffix ? suffix : "", NULL);
! 139: }
! 140: }
! 141: } else {
! 142: path = HTGetTmpFileName(base);
! 143: if (path && suffix) StrAllocCat(path, suffix);
! 144: }
! 145:
! 146: if (STREAM_TRACE)
! 147: HTTrace("Save file... Temporaray file `%s\'\n", path ? path : "<null>");
! 148: return path;
! 149: }
! 150:
! 151: /* Save Locally
! 152: ** ------------
! 153: ** Saves a file to local disk. This can for example be used to dump
! 154: ** data objects of unknown media types to local disk. The stream prompts
! 155: ** for a file name for the temporary file.
! 156: */
! 157: PUBLIC HTStream* HTSaveLocally (HTRequest * request,
! 158: void * param,
! 159: HTFormat input_format,
! 160: HTFormat output_format,
! 161: HTStream * output_stream)
! 162: {
! 163: FILE * fp = NULL;
! 164: char * filename = NULL;
! 165: HTUserProfile * up = HTRequest_userProfile(request);
! 166: char * tmproot = HTUserProfile_tmp(up);
! 167: if (HTLib_secure()) {
! 168: HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_UNAUTHORIZED,
! 169: NULL, 0, "HTSaveLocally");
! 170: return HTErrorStream();
! 171: }
! 172: if (!tmproot) {
! 173: if (STREAM_TRACE) HTTrace("Save File... turned off\n");
! 174: return HTErrorStream();
! 175: }
! 176:
! 177: /* Let's prompt the user for a file name for this file */
! 178: {
! 179: HTAlertCallback *cbf = HTAlert_find(HT_A_PROMPT);
! 180: HTParentAnchor *anchor = (HTParentAnchor *) HTRequest_anchor(request);
! 181:
! 182: /*
! 183: ** If we found an alert handler for prompting the user then call it.
! 184: ** If not then either we are in non-interactive mode or no handler
! 185: ** has been registered. For now we then return a blackhole which may
! 186: ** not be the best thing to do.
! 187: */
! 188: if (cbf) {
! 189: HTAlertPar * reply = HTAlert_newReply();
! 190: char * suffix = HTBind_getSuffix(anchor);
! 191: char * deflt = get_filename(tmproot, HTAnchor_physical(anchor), suffix, YES);
! 192: if ((*cbf)(request, HT_A_PROMPT, HT_MSG_FILENAME,deflt,NULL,reply))
! 193: filename = HTAlert_replyMessage(reply);
! 194: HTAlert_deleteReply(reply);
! 195: HT_FREE(suffix);
! 196: HT_FREE(deflt);
! 197: }
! 198: if (filename) {
! 199: if ((fp = fopen(filename, "wb")) == NULL) {
! 200: HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_NO_FILE,
! 201: filename, strlen(filename),"HTSaveLocally");
! 202: HT_FREE(filename);
! 203: return HTErrorStream();
! 204: }
! 205: } else if (cbf) {
! 206: if (STREAM_TRACE) HTTrace("Save File... No file name - error stream\n");
! 207: return HTErrorStream();
! 208: } else {
! 209: if (STREAM_TRACE) HTTrace("Save File... No file name - black hole\n");
! 210: return HTBlackHole();
! 211: }
! 212: }
! 213:
! 214: /* Now we are ready for creating the file writer stream */
! 215: if (fp) {
! 216: HTStream * me = HTFileSave_new(request, fp, NO);
! 217: me->filename = filename;
! 218: return me;
! 219: }
! 220: HT_FREE(filename);
! 221: return HTErrorStream();
! 222: }
! 223:
! 224: /* Take action using a system command
! 225: ** ----------------------------------
! 226: ** Creates temporary file, writes to it and then executes system
! 227: ** command (maybe an external viewer) when EOF has been reached. The
! 228: ** stream finds a suitable name of the temporary file which preserves the
! 229: ** suffix. This way, the system command can find out the file type from
! 230: ** the name of the temporary file name.
! 231: */
! 232: PUBLIC HTStream* HTSaveAndExecute (HTRequest * request,
! 233: void * param,
! 234: HTFormat input_format,
! 235: HTFormat output_format,
! 236: HTStream * output_stream)
! 237: {
! 238: FILE * fp = NULL;
! 239: char * filename = NULL;
! 240: HTUserProfile * up = HTRequest_userProfile(request);
! 241: char * tmproot = HTUserProfile_tmp(up);
! 242: if (HTLib_secure()) {
! 243: HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_UNAUTHORIZED,
! 244: NULL, 0, "HTSaveLocally");
! 245: return HTErrorStream();
! 246: }
! 247: if (!tmproot) {
! 248: if (STREAM_TRACE) HTTrace("Save File... turned off");
! 249: return HTErrorStream();
! 250: }
! 251:
! 252: /* Let's find a hash name for this file without asking user */
! 253: {
! 254: HTParentAnchor *anchor = (HTParentAnchor *) HTRequest_anchor(request);
! 255: char *suffix = HTBind_getSuffix(anchor);
! 256: filename = get_filename(tmproot, HTAnchor_physical(anchor), suffix, NO);
! 257: HT_FREE(suffix);
! 258: if (filename) {
! 259: if ((fp = fopen(filename, "wb")) == NULL) {
! 260: HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_NO_FILE,
! 261: filename, strlen(filename),"HTSaveAndExecute");
! 262: HT_FREE(filename);
! 263: return HTErrorStream();
! 264: }
! 265: } else {
! 266: if (STREAM_TRACE) HTTrace("Save File... No file name\n");
! 267: return HTErrorStream();
! 268: }
! 269: }
! 270:
! 271: /* Now we are ready for creating the file writer stream */
! 272: if (fp) {
! 273: HTStream * me = HTFileSave_new(request, fp, NO);
! 274: me->filename = filename;
! 275: if (param) {
! 276: if ((me->end_command = (char *) HT_MALLOC((strlen((char *) param) + 10 + 3*strlen(filename)))) == NULL)
! 277: HT_OUTOFMEM("SaveAndExecute");
! 278: sprintf (me->end_command,
! 279: (char *)param, filename, filename, filename);
! 280: }
! 281: return me;
! 282: }
! 283: HT_FREE(filename);
! 284: return HTErrorStream();
! 285: }
! 286:
! 287: /* Save and Call Back
! 288: ** ------------------
! 289: ** This stream works exactly like the HTSaveAndExecute
! 290: ** stream but in addition when EOF has been reached, it checks whether a
! 291: ** callback function has been associated with the request object in which
! 292: ** case, this callback is being called. This can be use by the
! 293: ** application to do some processing after the system command
! 294: ** has terminated. The callback function is called with the file name of
! 295: ** the temporary file as parameter.
! 296: */
! 297: PUBLIC HTStream* HTSaveAndCallback (HTRequest * request,
! 298: void * param,
! 299: HTFormat input_format,
! 300: HTFormat output_format,
! 301: HTStream * output_stream)
! 302: {
! 303: HTStream * me = HTSaveAndExecute(request, param, input_format,
! 304: output_format, output_stream);
! 305: if (me) {
! 306: me->callback = HTRequest_callback(request);
! 307: return me;
! 308: }
! 309: return HTErrorStream();
! 310: }
Webmaster