View | Details | Raw Unified | Return to bug 57501
Collapse All | Expand All

(-)src/apache-2/mod_rivet.c (-30 / +127 lines)
Lines 101-106 Link Here
101
101
102
mod_rivet_globals* rivet_module_globals = NULL;
102
mod_rivet_globals* rivet_module_globals = NULL;
103
103
104
/* -- Rivet_PrintErrorMessage
105
 *
106
 * Utility function to print the error message stored in errorInfo
107
 * with a custom header. This procedure is called to print standard
108
 * errors when one of Tcl scripts fails
109
 * 
110
 * Arguments:
111
 *
112
 *   - Tcl_Interp* interp: the Tcl interpreter that was running the script
113
 *                         (and therefore the built-in variable errorInfo
114
 *                          keeps the message)
115
 *   - const char* error: Custom error header
116
 */
117
118
static void 
119
Rivet_PrintErrorMessage (Tcl_Interp* interp,const char* error_header)
120
{
121
    Tcl_Obj* errormsg  = Tcl_NewObj();
122
123
    Tcl_IncrRefCount(errormsg);
124
    Tcl_AppendStringsToObj(errormsg,"puts \"",error_header,"<br />\"\n",NULL);
125
    Tcl_AppendStringsToObj(errormsg,"puts \"<pre>$errorInfo</pre>\"\n",NULL);
126
    Tcl_EvalObjEx(interp,errormsg,0);
127
    Tcl_DecrRefCount(errormsg);
128
}
129
104
/*
130
/*
105
 * -- Rivet_chdir_file (const char* filename)
131
 * -- Rivet_chdir_file (const char* filename)
106
 * 
132
 * 
Lines 299-304 Link Here
299
    }
325
    }
300
}
326
}
301
327
328
/* -- Rivet_ExecuteErrorHandler
329
 *
330
 * Invoking either the default error handler or the ErrorScript.
331
 * In case the error handler fails a standard error message is printed
332
 * (you're better off if you make your error handlers fail save)
333
 *
334
 * Arguments:
335
 *
336
 *  - Tcl_Interp* interp: the Tcl interpreter
337
 *  - Tcl_Obj*    tcl_script_obj: the script that failed (to retrieve error
338
 *                info from it
339
 *  - request_rec* req: current request obj pointer
340
 * 
341
 * Returned value:
342
 *
343
 *  - A Tcl status
344
 */
345
346
static int 
347
Rivet_ExecuteErrorHandler (Tcl_Interp* interp,Tcl_Obj* tcl_script_obj, request_rec* req)
348
{
349
    int                     result;
350
    rivet_server_conf*      conf = Rivet_GetConf(req);
351
    Tcl_Obj*                errscript;
352
353
    /* We extract information from the errorOutbuf variable. Notice that tcl_script_obj
354
     * can either be the request processing script or conf->rivet_abort_script
355
     */
356
357
    Tcl_SetVar( interp, "errorOutbuf",Tcl_GetStringFromObj( tcl_script_obj, NULL ),TCL_GLOBAL_ONLY );
358
359
    /* If we don't have an error script, use the default error handler. */
360
    if (conf->rivet_error_script) {
361
        errscript = conf->rivet_error_script;
362
    } else {
363
        errscript = conf->rivet_default_error_script;
364
    }
365
366
    Tcl_IncrRefCount(errscript);
367
    result = Tcl_EvalObjEx(interp, errscript, 0);
368
    if (result == TCL_ERROR) {
369
        Rivet_PrintErrorMessage(interp,"<b>Rivet ErrorScript failed</b>");
370
    }
371
372
    /* This shouldn't make the default_error_script go away,
373
     * because it gets a Tcl_IncrRefCount when it is created.
374
     */
375
    Tcl_DecrRefCount(errscript);
376
377
    return result;
378
}
379
380
302
/* -- Rivet_ExecuteAndCheck
381
/* -- Rivet_ExecuteAndCheck
303
 * 
382
 * 
304
 * Tcl script execution central procedure. The script stored
383
 * Tcl script execution central procedure. The script stored
Lines 316-322 Link Here
316
 *
395
 *
317
 *   Returned value:
396
 *   Returned value:
318
 *
397
 *
319
 *      - invariably TCL_OK
398
 *      - One of the Tcl defined returned value of Tcl_EvelObjExe (TCL_OK, 
399
 *        TCL_ERROR, TCL_BREAK etc.)
320
 *
400
 *
321
 *   Side effects:
401
 *   Side effects:
322
 *
402
 *
Lines 330-336 Link Here
330
{
410
{
331
    int                     result;
411
    int                     result;
332
    rivet_server_conf*      conf = Rivet_GetConf(req);
412
    rivet_server_conf*      conf = Rivet_GetConf(req);
333
    rivet_interp_globals*   globals = Tcl_GetAssocData(interp, "rivet", NULL);
334
413
335
    Tcl_Preserve (interp);
414
    Tcl_Preserve (interp);
336
    result = Tcl_EvalObjEx(interp, tcl_script_obj, 0);
415
    result = Tcl_EvalObjEx(interp, tcl_script_obj, 0);
Lines 337-343 Link Here
337
416
338
    if (result == TCL_ERROR) {
417
    if (result == TCL_ERROR) {
339
418
340
        Tcl_Obj*    errscript;
341
        Tcl_Obj*    errorCodeListObj;
419
        Tcl_Obj*    errorCodeListObj;
342
        Tcl_Obj*    errorCodeElementObj;
420
        Tcl_Obj*    errorCodeElementObj;
343
        char*       errorCodeSubString;
421
        char*       errorCodeSubString;
Lines 376-414 Link Here
376
            {
454
            {
377
                if (conf->rivet_abort_script) 
455
                if (conf->rivet_abort_script) 
378
                {
456
                {
379
                    if (Tcl_EvalObjEx(interp,conf->rivet_abort_script,0) == TCL_ERROR)
457
458
                    /* Ideally an AbortScript should be fail safe, but in case
459
                     * it fails we give a chance to the subsequent ErrorScript
460
                     * to catch this error.
461
                     */
462
463
                    result = Tcl_EvalObjEx(interp,conf->rivet_abort_script,0);
464
                    if (result == TCL_ERROR)
380
                    {
465
                    {
381
                        CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 );
466
382
                        TclWeb_PrintError("<b>Rivet AbortScript failed!</b>",1,globals->req);
467
                        /* This is not elegant, but we want to avoid to print
383
                        TclWeb_PrintError(errorinfo,0,globals->req);
468
                         * this error message if an ErrorScript will handle this error.
469
                         * Thus we print the usual error message only if we are running the
470
                         * default error handler
471
                         */
472
473
                        if (conf->rivet_error_script == NULL) {
474
475
                            Rivet_PrintErrorMessage(interp,"<b>Rivet AbortScript failed</b>");
476
                        }
477
                        else
478
                        {
479
                            result = Rivet_ExecuteErrorHandler(interp,conf->rivet_abort_script,req);
480
                        }
384
                    }
481
                    }
385
                }
482
                }
386
                goto good;
483
                else
484
                {
485
486
                    /* If the script issued a ::rivet::abort_page but no AbortScript was
487
                     * defined we return a TCL_OK anyway
488
                     */
489
490
                    result = TCL_OK;
491
492
                }
387
            }
493
            }
388
        }
494
        }
495
        else
496
        {
497
            /* Invoke Rivet error handler */
389
498
390
        Tcl_SetVar( interp, "errorOutbuf",Tcl_GetStringFromObj( tcl_script_obj, NULL ),TCL_GLOBAL_ONLY );
499
            result = Rivet_ExecuteErrorHandler(interp,tcl_script_obj,req);
391
500
392
        /* If we don't have an error script, use the default error handler. */
393
        if (conf->rivet_error_script) {
394
            errscript = conf->rivet_error_script;
395
        } else {
396
            errscript = conf->rivet_default_error_script;
397
        }
501
        }
398
502
399
        Tcl_IncrRefCount(errscript);
400
        if (Tcl_EvalObjEx(interp, errscript, 0) == TCL_ERROR) {
401
            CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 );
402
            TclWeb_PrintError("<b>Rivet ErrorScript failed!</b>",1,globals->req);
403
            TclWeb_PrintError( errorinfo, 0, globals->req );
404
        }
405
503
406
        /* This shouldn't make the default_error_script go away,
407
         * because it gets a Tcl_IncrRefCount when it is created. */
408
        Tcl_DecrRefCount(errscript);
409
    }
504
    }
410
411
good:
412
    
505
    
413
    /* Tcl_Flush moved to the end of Rivet_SendContent */
506
    /* Tcl_Flush moved to the end of Rivet_SendContent */
414
507
Lines 425-431 Link Here
425
 * if a Tcl script.
518
 * if a Tcl script.
426
 *
519
 *
427
 * This is a separate function so that it may be called from command 'parse'
520
 * This is a separate function so that it may be called from command 'parse'
521
 * 
522
 * Returned value:
428
 *
523
 *
524
 *   - One of the Tcl defined values returned by Rivet_ExecuteAndCheck (TCL_OK, 
525
 *     TCL_ERROR, TCL_BREAK etc.)
526
 *
429
 * Arguments:
527
 * Arguments:
430
 *
528
 *
431
 *   - TclWebRequest: pointer to the structure collecting Tcl and Apache data
529
 *   - TclWebRequest: pointer to the structure collecting Tcl and Apache data
Lines 434-439 Link Here
434
 *   - toplevel:      integer to be interpreted as a boolean meaning the
532
 *   - toplevel:      integer to be interpreted as a boolean meaning the
435
 *                    file is pointed by the request. When 0 that's a subtemplate
533
 *                    file is pointed by the request. When 0 that's a subtemplate
436
 *                    to be parsed and executed from another template
534
 *                    to be parsed and executed from another template
535
 *
437
 */
536
 */
438
537
439
int
538
int
Lines 443-449 Link Here
443
    int isNew = 0;
542
    int isNew = 0;
444
    int result = 0;
543
    int result = 0;
445
544
446
    Tcl_Obj *outbuf = NULL;
545
    Tcl_Obj *outbuf      = NULL;
447
    Tcl_HashEntry *entry = NULL;
546
    Tcl_HashEntry *entry = NULL;
448
547
449
    time_t ctime;
548
    time_t ctime;
Lines 1477-1483 Link Here
1477
    if (Rivet_ParseExecFile(globals->req, r->filename, 1) != TCL_OK)
1576
    if (Rivet_ParseExecFile(globals->req, r->filename, 1) != TCL_OK)
1478
    {
1577
    {
1479
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r->server, 
1578
        ap_log_error(APLOG_MARK, APLOG_ERR, APR_EGENERAL, r->server, 
1480
                     MODNAME ": Error parsing exec file '%s': %s",
1579
                     MODNAME ": Error in Rivet_ParseExecFile exec file '%s': %s",
1481
                     r->filename,
1580
                     r->filename,
1482
                     Tcl_GetVar(interp, "errorInfo", 0));
1581
                     Tcl_GetVar(interp, "errorInfo", 0));
1483
    }
1582
    }
Lines 1488-1496 Link Here
1488
    {
1587
    {
1489
        if (Rivet_ExecuteAndCheck(interp, rsc->after_every_script,r) == TCL_ERROR)
1588
        if (Rivet_ExecuteAndCheck(interp, rsc->after_every_script,r) == TCL_ERROR)
1490
        {
1589
        {
1491
            CONST84 char *errorinfo = Tcl_GetVar( interp, "errorInfo", 0 );
1590
            Rivet_PrintErrorMessage(interp,"<b>Rivet AfterEveryScript failed</b>");
1492
            TclWeb_PrintError("<b>Rivet AfterEveryScript failed!</b>",1,globals->req);
1493
            TclWeb_PrintError( errorinfo, 0, globals->req );
1494
        }
1591
        }
1495
    }
1592
    }
1496
1593

Return to bug 57501