Annotation of libwww/Library/src/HTFWrite.c, revision 2.34

2.1       frystyk     1: /*                                                                 HTFWrite.c
                      2: **     FILE WRITER
                      3: **
2.6       frystyk     4: **     (c) COPYRIGHT MIT 1995.
2.1       frystyk     5: **     Please first read the full copyright statement in the file COPYRIGH.
2.34    ! frystyk     6: **     @(#) $Id: HTFWrite.c,v 2.33 1996/05/20 15:06:40 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
2.10      frystyk    18: **        HFN: moved cache code to HTCache module
2.1       frystyk    19: **
                     20: */
                     21: 
                     22: /* Library include files */
2.28      frystyk    23: #include "sysdep.h"
2.1       frystyk    24: #include "HTUtils.h"
                     25: #include "HTString.h"
                     26: #include "HTFormat.h"
2.21      frystyk    27: #include "HTError.h"
2.1       frystyk    28: #include "HTAlert.h"
2.19      frystyk    29: #include "HTAccess.h"
2.4       frystyk    30: #include "HTBind.h"
2.1       frystyk    31: #include "HTList.h"
2.3       frystyk    32: #include "HTParse.h"
2.15      frystyk    33: #include "HTReq.h"
2.3       frystyk    34: #include "HTFWrite.h"                                   /* Implemented here */
2.1       frystyk    35: 
2.4       frystyk    36: #define HASH_SIZE 1001         /* Tunable */
                     37: 
2.3       frystyk    38: struct _HTStream {
2.28      frystyk    39:     const HTStreamClass *isa;
2.24      frystyk    40:     
                     41:     FILE *             fp;
2.31      frystyk    42:     BOOL               leave_open;                 /* Close file when free? */
2.24      frystyk    43:     char *             end_command;                   /* Command to execute */
                     44:     BOOL               remove_on_close;                     /* Remove file? */
                     45:     char *             filename;                            /* Name of file */
                     46:     HTRequest *                request;                       /* saved for callback */
                     47:     HTRequestCallback *        callback;
2.3       frystyk    48: };
2.1       frystyk    49: 
2.3       frystyk    50: /* ------------------------------------------------------------------------- */
2.1       frystyk    51: 
2.16      frystyk    52: PRIVATE int HTFWriter_put_character (HTStream * me, char c)
2.3       frystyk    53: {
                     54:     return (fputc(c, me->fp) == EOF) ? HT_ERROR : HT_OK;
                     55: }
                     56: 
2.28      frystyk    57: PRIVATE int HTFWriter_put_string (HTStream * me, const char* s)
2.3       frystyk    58: {
                     59:     if (*s)                                         /* For vms :-( 10/04-94 */
                     60:        return (fputs(s, me->fp) == EOF) ? HT_ERROR : HT_OK;
                     61:     return HT_OK;
                     62: }
                     63: 
2.16      frystyk    64: PRIVATE int HTFWriter_flush (HTStream * me)
2.3       frystyk    65: {
2.7       frystyk    66:     return (fflush(me->fp) == EOF) ? HT_ERROR : HT_OK;
2.3       frystyk    67: }
                     68: 
2.28      frystyk    69: PRIVATE int HTFWriter_write (HTStream * me, const char* s, int l)
2.3       frystyk    70: {
2.7       frystyk    71:     int status ;
                     72:     status = (fwrite(s, 1, l, me->fp) != l) ? HT_ERROR : HT_OK ;
2.24      frystyk    73:     if (l > 1 && status == HT_OK) (void) HTFWriter_flush(me);
2.7       frystyk    74:     return status ;
2.3       frystyk    75: }
2.7       frystyk    76: 
2.30      frystyk    77: PRIVATE int HTFWriter_free (HTStream * me)
2.3       frystyk    78: {
2.24      frystyk    79:     if (me) {
                     80:        if (me->leave_open != YES) fclose(me->fp);
2.28      frystyk    81: #ifdef HAVE_SYSTEM
2.24      frystyk    82:        if (me->end_command) system(me->end_command);    /* SECURITY HOLE!!! */
2.17      frystyk    83: #endif
2.24      frystyk    84:        if (me->remove_on_close) REMOVE(me->filename);
                     85:        if (me->callback) (*me->callback)(me->request, me->filename);
2.26      frystyk    86:        HT_FREE(me->end_command);
                     87:        HT_FREE(me->filename);
                     88:        HT_FREE(me);
2.3       frystyk    89:     }
                     90:     return HT_OK;
                     91: }
                     92: 
2.18      frystyk    93: PRIVATE int HTFWriter_abort (HTStream * me, HTList * e)
2.3       frystyk    94: {
2.27      eric       95:     if (STREAM_TRACE) HTTrace("FileWriter.. ABORTING...\n");
2.24      frystyk    96:     if (me) {
                     97:        if (me->leave_open != YES) fclose(me->fp);
                     98:        if (me->remove_on_close) REMOVE(me->filename);
2.26      frystyk    99:        HT_FREE(me->end_command);
                    100:        HT_FREE(me->filename);
                    101:        HT_FREE(me);
2.3       frystyk   102:     }
                    103:     return HT_ERROR;
                    104: }
                    105: 
2.28      frystyk   106: PRIVATE const HTStreamClass HTFWriter = /* As opposed to print etc */
2.3       frystyk   107: {              
                    108:     "FileWriter",
                    109:     HTFWriter_flush,
2.30      frystyk   110:     HTFWriter_free,
2.3       frystyk   111:     HTFWriter_abort,
                    112:     HTFWriter_put_character,
                    113:     HTFWriter_put_string,
                    114:     HTFWriter_write
                    115: };
                    116: 
2.24      frystyk   117: PUBLIC HTStream * HTFWriter_new (HTRequest * request, FILE * fp,
                    118:                                 BOOL leave_open)
2.3       frystyk   119: {
2.24      frystyk   120:     HTStream * me = NULL;
2.3       frystyk   121:     if (!fp) {
2.27      eric      122:        if (STREAM_TRACE)HTTrace("FileWriter.. Bad file descriptor\n");
2.24      frystyk   123:        return HTErrorStream();
2.3       frystyk   124:     }
2.26      frystyk   125:     if ((me = (HTStream *) HT_CALLOC(1, sizeof(HTStream))) == NULL)
                    126:         HT_OUTOFMEM("HTFWriter_new");
2.3       frystyk   127:     me->isa = &HTFWriter;       
                    128:     me->fp = fp;
2.24      frystyk   129:     me->leave_open = leave_open;
                    130:     me->request = request;
2.3       frystyk   131:     return me;
                    132: }
                    133: 
                    134: /* ------------------------------------------------------------------------- */
                    135: /*                          FILE WRITER ROUTINES                            */
                    136: /* ------------------------------------------------------------------------- */
                    137: 
2.4       frystyk   138: /*
                    139: **   This function tries really hard to find a non-existent filename relative
2.31      frystyk   140: **   to the path given. Returns a string that must be freed by the caller or
2.4       frystyk   141: **   NULL on error. The base must be '/' terminated which!
                    142: */
2.28      frystyk   143: PRIVATE char *get_filename (char * base, const char * url, const char * suffix)
2.4       frystyk   144: {
                    145:     char *path=NULL;
                    146:     char filename[40];
                    147:     int hash=0;
                    148: 
                    149:     /* Do this until we find a name that doesn't exist */
                    150:     while (1)
                    151:     {
2.28      frystyk   152:        const char *ptr=url;
2.4       frystyk   153:        for( ; *ptr; ptr++)
                    154:            hash = (int) ((hash * 31 + (* (unsigned char *) ptr)) % HASH_SIZE);
                    155: 
2.28      frystyk   156: #ifdef HAVE_GETPID
2.4       frystyk   157:        sprintf(filename, "%d-%d", hash, (int) getpid());
                    158: #else
                    159:        sprintf(filename, "%d-%d", hash, time(NULL));
                    160: #endif
                    161:        StrAllocCopy(path, base);
                    162:        StrAllocCat(path, filename);
                    163:        if (suffix) StrAllocCat(path, suffix);
                    164: 
                    165:        {
                    166:            FILE *fp = fopen(path, "r");
                    167:            if (fp)                          /* This file does already exist */
                    168:                fclose(fp);
                    169:            else
                    170:                break;                                  /* Got the file name */
                    171:        }
                    172:     }
2.34    ! frystyk   173:     if (STREAM_TRACE) HTTrace("Save file... Temporaray file `%s\'\n", path);
2.4       frystyk   174:     return path;
                    175: }
                    176: 
                    177: 
2.24      frystyk   178: /*     Save Locally
                    179: **     ------------
                    180: **     Saves a file to local disk. This can for example be used to dump
                    181: **     date objects of unknown media types to local disk. The stream prompts
                    182: **     for a file name for the temporary file.
2.1       frystyk   183: */
2.24      frystyk   184: PUBLIC HTStream* HTSaveLocally (HTRequest *    request,
                    185:                                void *          param,
                    186:                                HTFormat        input_format,
                    187:                                HTFormat        output_format,
                    188:                                HTStream *      output_stream)
2.1       frystyk   189: {
2.24      frystyk   190:     FILE * fp = NULL;
                    191:     char * filename = NULL;
2.33      frystyk   192:     HTUserProfile * up = HTRequest_userProfile(request);
                    193:     char * tmproot = HTUserProfile_tmp(up);
2.19      frystyk   194:     if (HTLib_secure()) {
2.21      frystyk   195:        HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_UNAUTHORIZED,
2.24      frystyk   196:                           NULL, 0, "HTSaveLocally");
                    197:        return HTErrorStream();
2.1       frystyk   198:     }
2.33      frystyk   199:     if (!tmproot) {
2.27      eric      200:        if (STREAM_TRACE) HTTrace("Save File... turned off");
2.24      frystyk   201:        return HTErrorStream();
2.1       frystyk   202:     }
                    203:        
2.24      frystyk   204:     /* Let's prompt the user for a file name for this file */
2.4       frystyk   205:     {
2.24      frystyk   206:        HTAlertCallback *cbf = HTAlert_find(HT_A_PROMPT);
2.13      frystyk   207:        HTParentAnchor *anchor = (HTParentAnchor *) HTRequest_anchor(request);
                    208:        char *suffix = HTBind_getSuffix(anchor);
2.33      frystyk   209:        char *deflt = get_filename(tmproot,HTAnchor_physical(anchor),suffix);
2.24      frystyk   210:        if (cbf) {
                    211:            HTAlertPar * reply = HTAlert_newReply();
                    212:            if ((*cbf)(request, HT_A_PROMPT, HT_MSG_FILENAME,deflt,NULL,reply))
                    213:                filename = HTAlert_replyMessage(reply);
                    214:            HTAlert_deleteReply(reply);
                    215:        }
2.26      frystyk   216:        HT_FREE(suffix);
                    217:        HT_FREE(deflt);
2.24      frystyk   218:        if (filename) {
                    219:            if ((fp = fopen(filename, "wb")) == NULL) {
                    220:                HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_NO_FILE,
                    221:                                   filename, strlen(filename),"HTSaveLocally");
2.26      frystyk   222:                HT_FREE(filename);
2.24      frystyk   223:                return HTErrorStream();
                    224:            }
                    225:        } else {
2.27      eric      226:            if (STREAM_TRACE) HTTrace("Save File... No file name\n");
2.24      frystyk   227:            return HTErrorStream();
2.4       frystyk   228:        }
                    229:     }
2.24      frystyk   230:     
                    231:     /* Now we are ready for creating the file writer stream */
                    232:     if (fp) {
                    233:        HTStream * me = HTFWriter_new(request, fp, NO);
                    234:        me->filename = filename;
                    235:        return me;
2.1       frystyk   236:     }
2.26      frystyk   237:     HT_FREE(filename);
2.24      frystyk   238:     return HTErrorStream();
2.1       frystyk   239: }
                    240: 
                    241: 
2.24      frystyk   242: /*     Take action using a system command
                    243: **     ----------------------------------
                    244: **     Creates temporary file, writes to it and then executes system
                    245: **     command (maybe an external viewer) when EOF has been reached. The
                    246: **     stream finds a suitable name of the temporary file which preserves the
                    247: **     suffix. This way, the system command can find out the file type from
                    248: **     the name of the temporary file name.
2.1       frystyk   249: */
2.24      frystyk   250: PUBLIC HTStream* HTSaveAndExecute (HTRequest * request,
                    251:                                   void *       param,
                    252:                                   HTFormat     input_format,
                    253:                                   HTFormat     output_format,
                    254:                                   HTStream *   output_stream)
2.1       frystyk   255: {
2.24      frystyk   256:     FILE * fp = NULL;
                    257:     char * filename = NULL;
2.33      frystyk   258:     HTUserProfile * up = HTRequest_userProfile(request);
                    259:     char * tmproot = HTUserProfile_tmp(up);
2.19      frystyk   260:     if (HTLib_secure()) {
2.21      frystyk   261:        HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_UNAUTHORIZED,
                    262:                           NULL, 0, "HTSaveLocally");
2.24      frystyk   263:        return HTErrorStream();
2.1       frystyk   264:     }
2.33      frystyk   265:     if (!tmproot) {
2.27      eric      266:        if (STREAM_TRACE) HTTrace("Save File... turned off");
2.24      frystyk   267:        return HTErrorStream();
2.1       frystyk   268:     }
                    269:        
2.24      frystyk   270:     /* Let's find a hash name for this file without asking user */
2.4       frystyk   271:     {
2.13      frystyk   272:        HTParentAnchor *anchor = (HTParentAnchor *) HTRequest_anchor(request);
                    273:        char *suffix = HTBind_getSuffix(anchor);
2.33      frystyk   274:        filename = get_filename(tmproot, HTAnchor_physical(anchor), suffix);
2.26      frystyk   275:        HT_FREE(suffix);
2.25      frystyk   276:        if (filename) {
                    277:            if ((fp = fopen(filename, "wb")) == NULL) {
                    278:                HTRequest_addError(request, ERR_NON_FATAL, NO, HTERR_NO_FILE,
                    279:                                   filename, strlen(filename),"HTSaveAndExecute");
2.26      frystyk   280:                HT_FREE(filename);
2.25      frystyk   281:                return HTErrorStream();
                    282:            }
                    283:        } else {
2.27      eric      284:            if (STREAM_TRACE) HTTrace("Save File... No file name\n");
2.24      frystyk   285:            return HTErrorStream();
2.4       frystyk   286:        }
                    287:     }
                    288:     
2.24      frystyk   289:     /* Now we are ready for creating the file writer stream */
                    290:     if (fp) {
                    291:        HTStream * me = HTFWriter_new(request, fp, NO);
                    292:        me->filename = filename;
2.31      frystyk   293:        if (param) {
                    294:            if ((me->end_command = (char  *) HT_MALLOC((strlen((char *) param) + 10 + 3*strlen(filename)))) == NULL)
                    295:                HT_OUTOFMEM("SaveAndExecute");
                    296:            sprintf (me->end_command,
                    297:                     (char *)param, filename, filename, filename);
                    298:        }
2.24      frystyk   299:        return me;
2.1       frystyk   300:     }
2.26      frystyk   301:     HT_FREE(filename);
2.24      frystyk   302:     return HTErrorStream();
2.1       frystyk   303: }
                    304: 
                    305: 
                    306: /*     Save and Call Back
                    307: **     ------------------
2.32      frystyk   308: **     This stream works exactly like the HTSaveAndExecute
2.24      frystyk   309: **     stream but in addition when EOF has been reached, it checks whether a
                    310: **     callback function has been associated with the request object in which
                    311: **     case, this callback is being called. This can be use by the
                    312: **     application to do some processing after the system command
                    313: **     has terminated. The callback function is called with the file name of
                    314: **     the temporary file as parameter.
2.1       frystyk   315: */
2.16      frystyk   316: PUBLIC HTStream* HTSaveAndCallback (HTRequest *                request,
                    317:                                    void *              param,
                    318:                                    HTFormat            input_format,
                    319:                                    HTFormat            output_format,
                    320:                                    HTStream *          output_stream)
2.1       frystyk   321: {
2.24      frystyk   322:     HTStream * me = HTSaveAndExecute(request, param, input_format,
                    323:                                     output_format, output_stream);
                    324:     if (me) {
                    325:        me->callback = HTRequest_callback(request);
                    326:        return me;
                    327:     }
                    328:     return HTErrorStream();
2.1       frystyk   329: }
                    330: 

Webmaster