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