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