View Source

[modwtcl]
apreq.h
dist/
libapreq1/
mod_wtcl.c
mod_wtcl.h
setupExclude.txt
util/
win.def
win.mak
wt1.1/
WtAppTable.c
WtAppTable.h
WtBasicCmds.c
WtBasicCmds.h
WtClientRequest.c
WtClientRequest.h
WtCollection.c
WtCollection.h
WtCollectionCmds.c
WtCollectionCmds.h
WtContext.c
WtContext.h
WtContextEvents.c
WtContextEvents.h
WtCookie.c
WtCookie.h
WtDbSession.c
WtDbSession.h
WtExecute.c
WtExecute.h
WtHtmlEntities.c
WtHtmlEntities.h
WtInitCmds.c
WtInitCmds.h
WtMtTable.c
WtMtTable.h
WtMultiTable.c
WtMultiTable.h
WtOS.h
WtProcSession.c
WtProcSession.h
WtResponse.c
WtResponse.h
WtServerCmds.c
WtServerCmds.h
WtSession.c
WtSession.h
WtSettings.c
WtSettings.h
WtTable.c
WtTable.h
WtTableCmds.c
WtTableCmds.h
WtTableUtil.c
WtTableUtil.h
WtUpload.c
WtUpload.h
WtUtil.c
WtUtil.h
WtWebErrors.c
WtWebErrors.h
WtWindows.h
File: / archive / modwtcl / WtContext.c

Lines Size Modified Created Owner MIME Types
861 21,059 2010/06/13 00:28:48 2011/06/13 15:35:15 BUILTIN\Administrators text/x-csrc

0001
/*
0002
 * Copyright 2001 Alexander Boverman and the original authors.
0003
 * 
0004
 * Licensed under the Apache License, Version 2.0 (the "License");
0005
 * you may not use this file except in compliance with the License.
0006
 * You may obtain a copy of the License at
0007
 * 
0008
 *      http://www.apache.org/licenses/LICENSE-2.0
0009
 * 
0010
 * Unless required by applicable law or agreed to in writing, software
0011
 * distributed under the License is distributed on an "AS IS" BASIS,
0012
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0013
 * See the License for the specific language governing permissions and
0014
 * limitations under the License.
0015
 */
0016
0017
#include "httpd.h"
0018
#include "http_config.h"
0019
#include "http_conf_globals.h"
0020
#include "http_main.h"
0021
#include "mod_wtcl.h"
0022
#include "WtContext.h"
0023
#include "WtUtil.h"
0024
#include "WtTable.h"
0025
#include "WtTableUtil.h"
0026
#include "WtMtTable.h"
0027
#include "WtSettings.h"
0028
#include "WtExecute.h"
0029
#include "WtCollection.h"
0030
#include "WtCookie.h"
0031
#include "WtWebErrors.h"
0032
#include "WtClientRequest.h"
0033
#include "WtResponse.h"
0034
#include "WtHtmlEntities.h"
0035
#include "WtDbSession.h"
0036
#include "WtProcSession.h"
0037
#include "WtAppTable.h"
0038
#include "WtTableCmds.h"
0039
#include "WtInitCmds.h"
0040
0041
const char *wtVersion = "1.1";
0042
0043
/* Initialize the server */
0044
0045
void WtInitServer(server_rec *s, pool *p)
0046
{
0047
  WtContext *w;
0048
0049
#ifdef USE_TCL_STUBS
0050
  Tcl_Interp *interp = NULL;
0051
  const char *ver;
0052
#endif
0053
0054
  w = WtGetContext();
0055
  if (!w->serverInit) {
0056
    ap_log_error(HERE, APLOG_DEBUG | APLOG_NOERRNO, s,
0057
      "Wtcl: WtInitServer (pid = %d, tid = %d).",
0058
      os_getpid(), gettid());
0059
0060
#ifdef USE_TCL_STUBS
0061
    if ((ver = Tcl_InitStubs(interp, "8.1", 0)) == NULL) {
0062
      ap_log_error(HERE, APLOG_ERR | APLOG_NOERRNO, s,
0063
        "Wtcl: Tcl_InitStubs failed."); 
0064
    } else {
0065
      ap_log_error(HERE, APLOG_DEBUG | APLOG_NOERRNO, s,
0066
        "Wtcl: Tcl_InitStubs returned version \"%s\".",
0067
        ver);
0068
    }
0069
#endif
0070
0071
    Tcl_FindExecutable(ap_server_argv0);
0072
    /* Tcl_FindExecutable("C:\\Program Files\\Tcl\\bin\\tclsh84.exe"); */
0073
0074
    Tcl_RegisterObjType(&WtTableType);
0075
    Tcl_RegisterObjType(&WtClnType);
0076
    Tcl_RegisterObjType(&WtCookieClnType);
0077
    Tcl_RegisterObjType(&WtTableType);
0078
    Tcl_RegisterObjType(&WtCaselessTableType);
0079
    Tcl_RegisterObjType(&WtMtTableType);
0080
    Tcl_RegisterObjType(&WtDbSessionType);
0081
0082
    Tcl_RegisterObjType(&WtProcSessionType);
0083
    Tcl_RegisterObjType(&WtPSTableType);
0084
    Tcl_InitObjHashTable(&wtPSTables);
0085
0086
    Tcl_RegisterObjType(&WtAppTableType);
0087
    WtInitAppTableSet(&wtAppTables);
0088
0089
    w->serverInit = 1;
0090
  }
0091
}
0092
0093
/* Get the current context */
0094
0095
WtContext *WtGetContext()
0096
{
0097
  WtThreadStorage *ts = WtGetThreadStorage();
0098
  if (!ts->context) {
0099
    ts->context = (WtContext *)ckalloc(sizeof(WtContext));
0100
    memset(ts->context, '\0', sizeof(WtContext));
0101
  }
0102
  return ts->context;
0103
}
0104
0105
/* Process a request */
0106
0107
int WtProcessRequest(request_rec *r)
0108
{
0109
  WtContext *w;
0110
  int ok = 1;
0111
  WtDispatch disp;
0112
0113
  Tcl_GetTime(&disp.startTime);
0114
0115
  ap_soft_timeout("Wtcl request", r);
0116
0117
  disp.status = HTTP_OK;
0118
  disp.moduleStatus = OK;
0119
  disp.terminate = 0;
0120
0121
  ap_log_rerror(HERE, APLOG_DEBUG | APLOG_NOERRNO, r,
0122
    "Wtcl: WtProcessRequest (r = 0x%x, PID = %d, TID = %d).",
0123
    r, os_getpid(), gettid());
0124
0125
  w = WtGetContext();
0126
0127
  if (!w) {
0128
    WtPrintInitError(HERE, APLOG_ERR | APLOG_NOERRNO, r, 1,
0129
      "Failed to create Wtcl context.");
0130
    ok = 0;
0131
  } else {
0132
    if (!WtInitRequest(w, r, &disp)) {
0133
      ok = 0;
0134
    } else {
0135
      ap_chdir_file(r->filename);
0136
      if (r->finfo.st_mode == 0) {
0137
        w->web->clientResponse.status = HTTP_NOT_FOUND;
0138
      } else if (!WtExecuteRequest(w, r->filename)) {
0139
        ok = 0;
0140
      }
0141
    }
0142
0143
    if (!WtEndRequest(w, r, &disp)) {
0144
      ok = 0;
0145
    }
0146
  }
0147
0148
  if (disp.terminate) {
0149
    WtLog(HERE, APLOG_DEBUG | APLOG_NOERRNO, w,
0150
      "Wtcl: WtProcessRequest: Terminating worker process.");
0151
    WtDeleteContext();
0152
#ifndef WIN32
0153
    ap_child_terminate(r);
0154
#endif /* !WIN32 */
0155
  }
0156
0157
  ap_kill_timeout(r);
0158
0159
  return disp.moduleStatus;
0160
}
0161
0162
/* Initialize the request */
0163
0164
int WtInitRequest(WtContext *w, request_rec *r, WtDispatch *disp)
0165
{
0166
  int ok = 1, reuseInterp, boolVal;
0167
  Tcl_Obj *settings, *serverConf, *dirConf, *namesp, *objv[4];
0168
  WtWebContext *web;
0169
0170
  /* Init worker */
0171
0172
  w->apServer = r->server;
0173
  w->apReq = r;
0174
  w->requestCount++;
0175
0176
  if (!w->webChannel) {
0177
    w->webChannel = Tcl_CreateChannel(&WtOutChanType, "web", w, TCL_WRITABLE);
0178
    Tcl_SetStdChannel(w->webChannel, TCL_STDOUT);
0179
    Tcl_RegisterChannel(NULL, w->webChannel);  /* Hold reference */
0180
  }
0181
0182
  /* Request settings */
0183
0184
  settings = WtNewTableObj();
0185
  Tcl_IncrRefCount(settings);
0186
  WtInitDefaultContextSettings(w);
0187
  WtUpdateTable(settings, w->defaultCtxSettings);
0188
0189
  if (serverConf = WtGetServerConf(r->server)) {
0190
    WtUpdateTable(settings, serverConf);
0191
  }
0192
  if (dirConf = WtGetDirConf(r)) {
0193
    WtUpdateTable(settings, dirConf);
0194
  }
0195
0196
  /* Get the web context */
0197
0198
  reuseInterp = WtTableGetBoolFromStr(settings, "server.reuseInterp", 1);
0199
  if (reuseInterp) {
0200
    if (!w->persistentWebContext) {
0201
      w->persistentWebContext = WtCreateWebContext(1);
0202
    }
0203
    web = w->web = w->persistentWebContext;
0204
  } else {
0205
    if (!w->transientWebContext) {
0206
      w->transientWebContext = WtCreateWebContext(0);
0207
    }
0208
    web = w->web = w->transientWebContext;
0209
  }
0210
0211
  if (!web) {
0212
    WtPrintInitError(HERE, APLOG_ERR | APLOG_NOERRNO, r, 1,
0213
      "Failed to create web context.");
0214
    ok = 0;
0215
  }
0216
0217
  /* Init the web context */
0218
0219
  if (ok) {
0220
    web->apReq = r;
0221
    web->ctxRequestCount++;
0222
    web->requestStartTime = disp->startTime;
0223
    web->clientResponse.status = HTTP_OK;
0224
    web->clientResponse.bytesSent = 0;
0225
    WtSetObj(&web->taskSettings, settings);
0226
0227
    namesp = WtTableGetObjFromStr(web->taskSettings,
0228
      "taskNamespace", NULL);
0229
    if (namesp) {
0230
      WtSetObj(&w->web->taskNamespace, namesp);
0231
    }
0232
0233
    if (!WtInitWebContext(w, 1)) {
0234
      ok = 0;
0235
    }
0236
  }
0237
0238
  /* Start the request */
0239
0240
  if (ok) {
0241
    if (!Tcl_CreateObjCommand(w->web->interp,
0242
        "::wt::internal::startRequest",
0243
        WtStartRequestCmd, NULL, NULL)) {
0244
      ok = 0;
0245
    } else {
0246
      objv[0] = WtNewString("namespace");
0247
      objv[1] = WtNewString("eval");
0248
      objv[2] = w->web->taskNamespace;
0249
      objv[3] = WtNewString("::wt::internal::startRequest");
0250
0251
      if (WtEvalIncr(w->web->interp, 4, objv, TCL_EVAL_DIRECT) != TCL_OK ||
0252
          !WtGetBoolResult(w->web->interp, &boolVal)) {
0253
        WtInterpError(HERE, w, w->web->interp);
0254
        ok = 0;
0255
      } else if (!boolVal) {
0256
        ok = 0;
0257
      }
0258
    }
0259
  }
0260
0261
  return ok;
0262
}
0263
0264
/* Create a new web context */
0265
0266
WtWebContext *WtCreateWebContext(int isPersistent)
0267
{
0268
  WtWebContext *wc = (WtWebContext *)ckalloc(sizeof(WtWebContext));
0269
  memset(wc, '\0', sizeof(WtWebContext));
0270
  wc->isPersistent = isPersistent;
0271
  return wc;
0272
}
0273
0274
/* Web context initialization process */
0275
0276
int WtInitWebContext(WtContext *w, int initRequest)
0277
{
0278
  int ok = 1;
0279
  WtWebContext *web = w->web;
0280
0281
  if (!web->aInitDone) {
0282
    web->errorState = 0;
0283
    WtSetObj(&web->notices, Tcl_NewListObj(0, NULL));
0284
    WtSetObj(&web->taskNamespace, WtNewString("::wt::task::"));
0285
    WtSetObj(&web->ctxEventHandlers, WtNewTableObj());
0286
    web->aInitDone = 1;
0287
  }
0288
0289
  if (!web->usedNamespaces) {
0290
    WtSetObj(&web->usedNamespaces, WtNewTableObj());
0291
  }
0292
0293
  if (!WtCreateInterp(w, initRequest) ||
0294
      !WtInitInterp(w, initRequest) ||
0295
      !WtInitPackages(w, initRequest)) {
0296
    ok = 0;
0297
  }
0298
0299
  return ok;
0300
}
0301
0302
/* Create the interpreter */
0303
0304
int WtCreateInterp(WtContext *w, int initRequest)
0305
{
0306
  int ok = 1;
0307
  Tcl_Interp *interp;
0308
0309
  if (w->web->interp) {
0310
    return 1;
0311
  }
0312
0313
  interp = w->web->interp = Tcl_CreateInterp();
0314
0315
  if (!interp) {
0316
    WtLog(HERE, APLOG_ERR | APLOG_NOERRNO, w, "Wtcl: Tcl_CreateInterp failed.");
0317
    ok = 0;
0318
  } else {
0319
    w->web->interpIsNew = 1;
0320
    w->web->interpCreationTime = time(NULL);
0321
    w->web->interpRequestCount = 0;
0322
    Tcl_SetAssocData(interp, "wt::context", NULL, w);
0323
0324
    if (Tcl_SetChannelOption(interp, w->webChannel, "-translation",
0325
        "binary") != TCL_OK) {
0326
      WtInterpError(HERE, w, interp);
0327
    }
0328
0329
    if (Tcl_Init(interp) != TCL_OK) {
0330
      WtInterpError(HERE, w, interp);
0331
      ok = 0;
0332
    }
0333
  }
0334
0335
  if (!ok && interp) {
0336
    Tcl_DeleteInterp(interp);
0337
    w->web->interp = NULL;
0338
  }
0339
0340
  return ok;
0341
}
0342
0343
/* Initialize the interp */
0344
0345
int WtInitInterp(WtContext *w, int initRequest)
0346
{
0347
  int ok, boolVal;
0348
  Tcl_Obj *objv[5];
0349
0350
  if (!Tcl_CreateObjCommand(w->web->interp,
0351
      "::wt::internal::initInterp", WtInitInterpCmd, NULL, NULL)) {
0352
    ok = 0;
0353
  } else {
0354
    objv[0] = WtNewString("namespace");
0355
    objv[1] = WtNewString("eval");
0356
    objv[2] = w->web->taskNamespace;
0357
    objv[3] = WtNewString("::wt::internal::initInterp");
0358
    objv[4] = WtNewBool(initRequest);
0359
0360
    if (WtEvalIncr(w->web->interp, 5, objv, TCL_EVAL_DIRECT) != TCL_OK ||
0361
        !WtGetBoolResult(w->web->interp, &boolVal)) {
0362
      WtInterpError(HERE, w, w->web->interp);
0363
      ok = 0;
0364
    } else if (!boolVal) {
0365
      ok = 0;
0366
    }
0367
  }
0368
0369
  return ok;
0370
}
0371
0372
/* Init packages and imports */
0373
0374
int WtInitPackages(WtContext *w, int initRequest)
0375
{
0376
  int ok, boolVal;
0377
  Tcl_Obj *objv[4];
0378
0379
  if (!Tcl_CreateObjCommand(w->web->interp,
0380
      "::wt::internal::initPackages", WtInitPackagesCmd, NULL, NULL)) {
0381
    ok = 0;
0382
  } else {
0383
    objv[0] = WtNewString("namespace");
0384
    objv[1] = WtNewString("eval");
0385
    objv[2] = w->web->taskNamespace;
0386
    objv[3] = WtNewString("::wt::internal::initPackages");
0387
0388
    if (WtEvalIncr(w->web->interp, 4, objv, TCL_EVAL_DIRECT) != TCL_OK ||
0389
        !WtGetBoolResult(w->web->interp, &boolVal)) {
0390
      WtInterpError(HERE, w, w->web->interp);
0391
      ok = 0;
0392
    } else if (!boolVal) {
0393
      ok = 0;
0394
    }
0395
  }
0396
0397
  return ok;
0398
}
0399
0400
int WtInitTaskObjectsB(WtContext *w)
0401
{
0402
  int ok = 1;
0403
  WtWebContext *web = w->web;
0404
  Tcl_Obj *str;
0405
0406
  if (w->web->bInitDone) {
0407
    return 1;
0408
  }
0409
0410
  web->importCommands = 1;
0411
  web->pageIsStarted = 0;
0412
  web->readEnvStatus = WT_STATUS_NONE;
0413
0414
  WtSetObj(&web->serverVars, WtNewTableObj());
0415
0416
  /* Page loader settings */
0417
0418
  str = WtNewString(".");
0419
  WtSetObj(&web->loader.includeSearchPath, Tcl_NewListObj(1, &str));
0420
  WtSetObj(&web->loader.includeNamespace, WtNewString(NULL));
0421
  web->loader.addHeaderTrailer = 0;
0422
  WtSetObj(&web->loader.includeHeader, WtNewString(NULL));
0423
  WtSetObj(&web->loader.includeTrailer, WtNewString(NULL));
0424
  WtSetObj(&web->loader.scriptStartString, WtNewString("<?"));
0425
  WtSetObj(&web->loader.scriptEndString, WtNewString("?>"));
0426
  web->loader.interpolateText = 1;
0427
  WtSetObj(&web->loader.textHandler, WtNewString(NULL));
0428
  WtSetObj(&web->loader.exprHandler, WtNewString(NULL));
0429
  web->loader.pageIndex = -1;
0430
  WtSetObj(&web->loader.pageStack, Tcl_NewListObj(0, NULL));
0431
0432
  /* Client request */
0433
0434
  WtSetObj(&web->clientRequest.headers, WtNewCaselessTableObj());
0435
  web->clientRequest.parseStatus = WT_STATUS_NONE;
0436
  web->clientRequest.readRequestStatus = WT_STATUS_NONE;
0437
  web->clientRequest.apWeb = NULL;
0438
  WtSetObj(&web->clientRequest.queryParams, WtNewTableObj());
0439
  WtSetObj(&web->clientRequest.postParams, WtNewTableObj());
0440
  web->clientRequest.readCookiesStatus = WT_STATUS_NONE;
0441
  web->clientRequest.apCookies = NULL;
0442
  WtSetObj(&web->clientRequest.cookies, WtNewTableObj());
0443
  WtSetObj(&web->clientRequest.uploads, WtNewTableObj());
0444
  WtSetObj(&web->clientRequest.uploadHandler, WtNewString(NULL));
0445
  WtSetObj(&web->clientRequest.params, WtNewTableObj());
0446
0447
  /* Client response */
0448
0449
  WtSetObj(&web->clientResponse.contentType, WtNewString(NULL));
0450
  WtSetObj(&web->clientResponse.headers, WtNewCaselessTableObj());
0451
  WtSetObj(&web->clientResponse.successHeaders, WtNewCaselessTableObj());
0452
  web->clientResponse.headersStatus = WT_STATUS_NONE;
0453
  WtSetObj(&web->clientResponse.cookies, WtNewCookieClnObj(NULL));
0454
  web->clientResponse.status = HTTP_OK;
0455
  web->clientResponse.bytesSent = 0;
0456
0457
  web->deleteInterp = 0;
0458
  WtInitSession(&web->session);
0459
  WtSetObj(&web->dataSourceHandler, WtNewString(NULL));
0460
0461
  if (ok) {
0462
    web->bInitDone = 1;
0463
  }
0464
0465
  return ok;
0466
}
0467
0468
/* End the request */
0469
0470
int WtEndRequest(WtContext *w, request_rec *r, WtDispatch *disp)
0471
{
0472
  int ok = 1, boolVal;
0473
  Tcl_Obj *objv[4];
0474
0475
  /* Run the exit handlers */
0476
0477
  if (w->web && w->web->interp) {
0478
    if (!Tcl_CreateObjCommand(w->web->interp,
0479
        "::wt::internal::endRequest", WtEndRequestCmd, NULL, NULL)) {
0480
      ok = 0;
0481
    } else {
0482
      objv[0] = WtNewString("namespace");
0483
      objv[1] = WtNewString("eval");
0484
      objv[2] = w->web->taskNamespace;
0485
      objv[3] = WtNewString("::wt::internal::endRequest");
0486
0487
      if (WtEvalIncr(w->web->interp, 4, objv, 0) != TCL_OK ||
0488
          !WtGetBoolResult(w->web->interp, &boolVal)) {
0489
        WtInterpError(HERE, w, w->web->interp);
0490
        w->web->terminate = 1;
0491
        ok = 0;
0492
      } else if (!boolVal) {
0493
        ok = 0;
0494
      }
0495
    }
0496
  }
0497
0498
  /* Flush response */
0499
0500
  if (w->web) {
0501
    if (!w->webChannel || Tcl_Flush(w->webChannel) != TCL_OK) {
0502
      WtLog(HERE, APLOG_ERR | APLOG_NOERRNO, w, "Tcl_Flush failed.");
0503
      ok = 0;
0504
    }
0505
  }
0506
0507
  /* Prepare the next task */
0508
0509
  if (w->web) {
0510
    if (disp->terminate) {
0511
      w->web->terminate = disp->terminate;
0512
    }
0513
0514
    if (!w->web->terminate) {
0515
      w->web->interpIsNew = 0;
0516
0517
      /* Recycle the interp */
0518
0519
      if (!w->web->isPersistent || w->web->deleteInterp) {
0520
        if (!WtRecreateInterp(w, disp)) {
0521
          ok = 0;
0522
        }
0523
      } else if (!WtReuseInterp(w)) {
0524
        ok = 0;
0525
      }
0526
    }
0527
0528
    /* Print errors */
0529
0530
    if (!ok || w->web->errorState) {
0531
      WtHandleErrorsNs(w);
0532
    }
0533
0534
    /* Send headers */
0535
0536
    if (!w->webChannel || Tcl_Flush(w->webChannel) != TCL_OK) {
0537
      WtLog(HERE, APLOG_ERR | APLOG_NOERRNO, w, "Tcl_Flush failed.");
0538
      ok = 0;
0539
    }
0540
0541
    if (w->web->clientResponse.headersStatus == WT_STATUS_NONE) {
0542
      if (w->web->clientResponse.status == HTTP_OK) {
0543
        if (!WtSendHeaders(w, w->web->apReq, w->web->interp)) {
0544
          ok = 0;
0545
        }
0546
      } else if (!WtSetApHeaders(w, w->web->interp)) {
0547
        ok = 0;
0548
      }
0549
    } else if (w->web->clientResponse.headersStatus == WT_STATUS_ERROR) {
0550
      WtSetApHeaders(w, w->web->interp);
0551
      ok = 0;
0552
    }
0553
0554
    disp->status = w->web->clientResponse.status;
0555
0556
    if (w->web->clientResponse.headersStatus != WT_STATUS_OK) {
0557
      disp->moduleStatus = w->web->clientResponse.status == HTTP_OK ?
0558
        OK : w->web->clientResponse.status;
0559
    } else {
0560
      disp->moduleStatus = OK;
0561
    }
0562
0563
    if (w->web->terminate) {
0564
      disp->terminate = w->web->terminate;
0565
    }
0566
0567
    /* Clear the internal task state */
0568
0569
    if (!disp->terminate && !WtClearTaskObjects(w)) {
0570
      ok = 0;
0571
    }
0572
  } else {
0573
    ap_rflush(r);
0574
  }
0575
0576
  return ok;
0577
}
0578
0579
/* Re-create the interp */
0580
0581
int WtRecreateInterp(WtContext *w, WtDispatch *disp)
0582
{
0583
  int ok = 1;
0584
0585
  if (w->web && w->web->interp && !WtDeleteInterp(w)) {
0586
    ok = 0;
0587
  }
0588
0589
  if (ok && !WtInitWebContext(w, 0)) {
0590
    ok = 0;
0591
  }
0592
0593
  return ok;
0594
}
0595
0596
/* Delete any state dependent on the interp */
0597
0598
int WtDeleteInterp(WtContext *w)
0599
{
0600
  if (w->web) {
0601
    if (w->web->interp) {
0602
      if (!Tcl_InterpDeleted(w->web->interp)) {
0603
        Tcl_DeleteInterp(w->web->interp);
0604
      }
0605
      w->web->interp = NULL;
0606
    }
0607
0608
    WtDecr(w->web->usedNamespaces);
0609
    w->web->usedNamespaces = NULL;
0610
  }
0611
0612
  return 1;
0613
}
0614
0615
/* Post-request cleanup */
0616
0617
int WtReuseInterp(WtContext *w)
0618
{
0619
  int ok = 1, deleteNs = 0;
0620
  Tcl_Obj *exists, *cond, *del, *ifCmd[3];
0621
  Tcl_Interp *interp;
0622
  char *nsStr, *p;
0623
0624
  if (w->web->interp) {
0625
    interp = w->web->interp;
0626
0627
    /* Make sure the namespace isn't empty */
0628
0629
    if (Tcl_GetCharLength(w->web->taskNamespace)) {
0630
      nsStr = Tcl_GetString(w->web->taskNamespace);
0631
      for (p = nsStr; *p == ':'; p++) ;
0632
      deleteNs = *p != '\0';
0633
    }
0634
0635
    if (deleteNs) {
0636
      /* XXX: Use assertion checking append functions */
0637
0638
      exists = Tcl_NewListObj(0, NULL);
0639
      Tcl_ListObjAppendElement(interp, exists, WtNewString("namespace"));
0640
      Tcl_ListObjAppendElement(interp, exists, WtNewString("exists"));
0641
      Tcl_ListObjAppendElement(interp, exists, w->web->taskNamespace);
0642
0643
      cond = WtNewString("[");
0644
      Tcl_AppendObjToObj(cond, exists);
0645
      Tcl_AppendToObj(cond, "]", 1);
0646
0647
      del = Tcl_NewListObj(0, NULL);
0648
      Tcl_ListObjAppendElement(interp, del, WtNewString("namespace"));
0649
      Tcl_ListObjAppendElement(interp, del, WtNewString("delete"));
0650
      Tcl_ListObjAppendElement(interp, del, w->web->taskNamespace);
0651
0652
      ifCmd[0] = WtNewString("if");
0653
      ifCmd[1] = cond;
0654
      ifCmd[2] = del;
0655
0656
      if (WtEvalIncr(w->web->interp, 3, ifCmd, 0) != TCL_OK) {
0657
        WtInterpError(HERE, w, w->web->interp);
0658
        ok = 0;
0659
      } else if (!WtOwnTable(&w->web->usedNamespaces, w->web->interp)) {
0660
        ok = 0;
0661
      } else {
0662
        WtTableRemove(w->web->usedNamespaces, w->web->taskNamespace);
0663
      }
0664
    }
0665
  }
0666
0667
  if (ok && !WtInitWebContext(w, 0)) {
0668
    ok = 0;
0669
  }
0670
0671
  return ok;
0672
}
0673
0674
/* Clear objects used in this request */
0675
0676
int WtClearTaskObjects(WtContext *w)
0677
{
0678
  int ok = 1;
0679
  WtWebContext *web = w->web;
0680
0681
  web->bInitDone = 0;
0682
0683
  web->apReq = NULL;
0684
  web->requestStartTime.sec = 0;
0685
  web->requestStartTime.usec = 0;
0686
  web->errorState = 0;
0687
  WtSetObj(&web->notices, Tcl_NewListObj(0, NULL));
0688
  WtSetObj(&web->taskSettings, WtNewTableObj());
0689
  WtSetObj(&web->taskNamespace, WtNewString("::wt::task::"));
0690
  WtSetObj(&web->ctxEventHandlers, WtNewTableObj());
0691
0692
  if (web->clientRequest.uploadHandlerData) {
0693
    Tcl_DecrRefCount(web->clientRequest.uploadHandlerData);
0694
    web->clientRequest.uploadHandlerData = NULL;
0695
  }
0696
0697
  if (!WtDeleteErrors(w, web->interp)) {
0698
    ok = 0;
0699
  }
0700
0701
  web->terminate = 0;
0702
0703
  WtDeleteSession(&web->session);
0704
0705
  if (!WtInitTaskObjectsB(w)) {
0706
    ok = 0;
0707
  }
0708
0709
  if (web->interp) {
0710
    Tcl_ResetResult(w->web->interp);
0711
  }
0712
0713
  return ok;
0714
}
0715
0716
/* Delete worker state prior to shutdown */
0717
0718
int WtDeleteContext()
0719
{
0720
  int ok = 1;
0721
  WtThreadStorage *ts = WtGetThreadStorage();
0722
  WtContext *w = NULL;
0723
0724
  if (ts->context) {
0725
    w = ts->context;
0726
0727
    if (w->persistentWebContext) {
0728
      w->web = w->persistentWebContext;
0729
      if (!WtDeleteWebContext(w)) {
0730
        ok = 0;
0731
      }
0732
      ckfree((char *)w->web);
0733
      w->persistentWebContext = NULL;
0734
    }
0735
0736
    if (w->transientWebContext) {
0737
      w->web = w->transientWebContext;
0738
      if (WtDeleteWebContext(w)) {
0739
        ok = 0;
0740
      }
0741
      ckfree((char *)w->web);
0742
      w->transientWebContext = NULL;
0743
    }
0744
0745
    if (w->webChannel) {
0746
      Tcl_UnregisterChannel(NULL, w->webChannel);
0747
    }
0748
0749
    w->web = NULL;
0750
0751
    if (w->optionCodes) {
0752
      Tcl_DeleteHashTable(w->optionCodes);
0753
      ckfree((char *)w->optionCodes);
0754
      w->optionCodes = NULL;
0755
    }
0756
0757
    if (w->optionKeys) {
0758
      WtDeleteOptionKeys(w->optionKeys);
0759
      Tcl_DeleteHashTable(w->optionKeys);
0760
      ckfree((char *)w->optionKeys);
0761
      w->optionKeys = NULL;
0762
    }
0763
0764
    if (w->defaultCtxSettings) {
0765
      Tcl_DecrRefCount(w->defaultCtxSettings);
0766
      w->defaultCtxSettings = NULL;
0767
    }
0768
0769
    ckfree((char *)ts->context);
0770
    ts->context = NULL;
0771
  }
0772
0773
  WtDeleteHtmlEntities();
0774
0775
  return ok;
0776
}
0777
0778
/* Delete the web context prior to shutdown */
0779
0780
int WtDeleteWebContext(WtContext *w)
0781
{
0782
  int ok = 1;
0783
  WtWebContext *web;
0784
0785
  if (!WtDeleteInterp(w)) {
0786
    ok = 0;
0787
  }
0788
0789
  if (w->web) {
0790
    web = w->web;
0791
    WtDecr(web->notices);
0792
    WtDecr(web->taskSettings);
0793
    WtDecr(web->taskNamespace);
0794
    WtDecr(web->ctxEventHandlers);
0795
    WtDecr(web->serverVars);
0796
    WtDecr(web->loader.includeSearchPath);
0797
    WtDecr(web->loader.includeNamespace);
0798
    WtDecr(web->loader.includeHeader);
0799
    WtDecr(web->loader.includeTrailer);
0800
    WtDecr(web->loader.scriptStartString);
0801
    WtDecr(web->loader.scriptEndString);
0802
    WtDecr(web->loader.textHandler);
0803
    WtDecr(web->loader.exprHandler);
0804
    WtDecr(web->loader.pageStack);
0805
0806
    WtDecr(web->clientRequest.headers);
0807
    WtDecr(web->clientRequest.queryParams);
0808
    WtDecr(web->clientRequest.postParams);
0809
    WtDecr(web->clientRequest.cookies);
0810
    WtDecr(web->clientRequest.uploads);
0811
    WtDecr(web->clientRequest.uploadHandler);
0812
    WtDecr(web->clientRequest.uploadHandlerData);
0813
0814
    WtDecr(web->clientResponse.headers);
0815
    WtDecr(web->clientResponse.successHeaders);
0816
    WtDecr(web->clientResponse.cookies);
0817
0818
    if (!WtDeleteErrors(w, web->interp)) {
0819
      ok = 0;
0820
    }
0821
0822
    WtDeleteSession(&web->session);
0823
0824
    WtDecr(web->dataSourceHandler);
0825
  }
0826
0827
  return ok;
0828
}
0829
0830
void WtEndServer(server_rec *s, pool *p)
0831
{
0832
  ap_log_error(HERE, APLOG_DEBUG | APLOG_NOERRNO, s,
0833
    "Wtcl: WtEndServer (pid = %d, tid = %d).",
0834
    os_getpid(), gettid());
0835
0836
  Tcl_DeleteHashTable(&wtPSTables);
0837
  Tcl_MutexFinalize(&wtPSTablesLock);
0838
}
0839
0840
Tcl_Obj *WtGetServerConf(server_rec *s)
0841
{
0842
  Tcl_Obj *conf = (Tcl_Obj *)ap_get_module_config(s->module_config, &wtcl_module);
0843
  if (conf && !WtConvertToTable(conf, NULL)) {
0844
    conf = NULL;
0845
  }
0846
  return conf;
0847
}
0848
0849
Tcl_Obj *WtGetDirConf(request_rec *r)
0850
{
0851
  Tcl_Obj *conf = (Tcl_Obj *)ap_get_module_config(r->per_dir_config, &wtcl_module);
0852
  if (conf && !WtConvertToTable(conf, NULL)) {
0853
    conf = NULL;
0854
  }
0855
  return conf;
0856
}
0857
0858
WtContext *WtGetAssocContext(Tcl_Interp *interp)
0859
{
0860
  return (WtContext *)Tcl_GetAssocData(interp, "wt::context", NULL);
0861
}