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 / mod_wtcl.c

Lines Size Modified Created Owner MIME Types
524 14,542 2010/06/12 23:53:32 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 <stdio.h>
0018
#include <tcl.h>
0019
#include "mod_wtcl.h"
0020
#include "WtContext.h"
0021
#include "WtUtil.h"
0022
#include "WtTable.h"
0023
#include "WtTableUtil.h"
0024
#include "WtSettings.h"
0025
0026
module MODULE_VAR_EXPORT wtcl_module;
0027
0028
static const char *wtEventsKey = "server.ctxEventHandlers";
0029
0030
static int wtcl_handler(request_rec *r)
0031
{
0032
  return WtProcessRequest(r);
0033
}
0034
0035
static void wtcl_init(server_rec *s, pool *p)
0036
{
0037
  ap_log_error(HERE, APLOG_DEBUG | APLOG_NOERRNO, s, "Wtcl: wtcl_init");
0038
}
0039
0040
static int WtCfgMergeEvents(Tcl_Obj *conf, Tcl_Obj *base, Tcl_Obj *overrides)
0041
{
0042
  int ok = 1;
0043
  Tcl_Obj *confEvt = WtTableGetObjFromStr(conf, wtEventsKey, NULL);
0044
  Tcl_Obj *baseEvt = WtTableGetObjFromStr(base, wtEventsKey, NULL);
0045
  Tcl_Obj *overridesEvt = WtTableGetObjFromStr(overrides, wtEventsKey, NULL);
0046
  Tcl_Obj *name, *item;
0047
  Tcl_HashTable *hashTable;
0048
  Tcl_HashEntry *ent;
0049
  Tcl_HashSearch search;
0050
0051
  if (baseEvt && !overridesEvt) {
0052
    WtTableSetStrToObj(conf, wtEventsKey, baseEvt);
0053
  } else if (!baseEvt && overridesEvt) {
0054
    WtTableSetStrToObj(conf, wtEventsKey, overridesEvt);
0055
  } else {
0056
    if (!confEvt) {
0057
      confEvt = WtNewTableObj();
0058
      WtTableSetStrToObj(conf, wtEventsKey, confEvt);
0059
    }
0060
0061
    hashTable = WtGetTableMap(confEvt);
0062
    ent = Tcl_FirstHashEntry(hashTable, &search);
0063
0064
    while (ent) {
0065
      name = (Tcl_Obj *)Tcl_GetHashKey(hashTable, ent);
0066
      item = (Tcl_Obj *)Tcl_GetHashValue(ent);
0067
      if (!WtTableGetIntFromStr(item, "add", 0)) {
0068
        WtTableRemove(confEvt, name);
0069
      }
0070
      if (!WtTableAppendToList(confEvt, name, item, NULL, NULL)) {
0071
        ok = 0;
0072
        break;
0073
      }
0074
      ent = Tcl_NextHashEntry(&search);
0075
    }
0076
  }
0077
0078
  return ok;
0079
}
0080
0081
static void *wtcl_create_dir_config(pool *p, char *path)
0082
{
0083
  WtInitServer(NULL, p);
0084
  return WtNewTableObj();
0085
}
0086
0087
static void *wtcl_merge_dir_config(pool *p, void *basev, void *overridesv)
0088
{
0089
  int ok = 1;
0090
  Tcl_Obj *conf = WtNewTableObj();
0091
  Tcl_Obj *base = (Tcl_Obj *)basev;
0092
  Tcl_Obj *overrides = (Tcl_Obj *)overridesv;
0093
0094
  WtUpdateTable(conf, base);
0095
  WtUpdateTable(conf, overrides);
0096
0097
  if (!WtCfgMergeEvents(conf, base, overrides)) {
0098
    ok = 0;
0099
    Tcl_DecrRefCount(conf);
0100
    conf = NULL;
0101
  }
0102
0103
  return conf;
0104
}
0105
0106
static void *wtcl_create_server_config(pool *p, server_rec *s)
0107
{
0108
  ap_log_error(HERE, APLOG_DEBUG | APLOG_NOERRNO, s,
0109
    "Wtcl: wtcl_create_server_config: pid = %d, tid = %d.",
0110
    os_getpid(), gettid());
0111
0112
  WtInitServer(s, p);
0113
  return WtNewTableObj();
0114
}
0115
0116
static void *wtcl_merge_server_config(pool *p, void *basev, void *overridesv)
0117
{
0118
  int ok = 1;
0119
  Tcl_Obj *conf = WtNewTableObj();
0120
  Tcl_Obj *base = (Tcl_Obj *)basev;
0121
  Tcl_Obj *overrides = (Tcl_Obj *)overridesv;
0122
0123
  WtUpdateTable(conf, base);
0124
  WtUpdateTable(conf, overrides);
0125
0126
  if (!WtCfgMergeEvents(conf, base, overrides)) {
0127
    ok = 0;
0128
    Tcl_DecrRefCount(conf);
0129
    conf = NULL;
0130
  }
0131
0132
  return conf;
0133
}
0134
0135
static void wtcl_child_init(server_rec *s, pool *p)
0136
{
0137
  ap_log_error(HERE, APLOG_DEBUG | APLOG_NOERRNO, s,
0138
    "Wtcl: wtcl_child_init: pid = %d, tid = %d.",
0139
    os_getpid(), gettid());
0140
0141
  WtInitServer(s, p);
0142
}
0143
0144
static void wtcl_child_exit(server_rec *s, pool *p)
0145
{
0146
  ap_log_error(HERE, APLOG_DEBUG | APLOG_NOERRNO, s, "Wtcl: wtcl_child_exit"); 
0147
  WtEndServer(s, p);
0148
}
0149
0150
Tcl_Obj *WtGetTargetConf(cmd_parms *cmd, void *dirConf)
0151
{
0152
  return cmd->path ? dirConf : ap_get_module_config(
0153
    cmd->server->module_config, &wtcl_module);
0154
}
0155
0156
static const char *WtReuseInterpCfg(cmd_parms *cmd, void *dirConf, int flag)
0157
{
0158
  WtTableSetStrToBool(WtGetTargetConf(cmd, dirConf),
0159
    "server.reuseInterp", flag);
0160
  return NULL;
0161
}
0162
0163
static const char *WtDeleteInterpCfg(cmd_parms *cmd, void *dirConf, int flag)
0164
{
0165
  WtTableSetStrToBool(WtGetTargetConf(cmd, dirConf),
0166
    "server.deleteInterp", flag);
0167
  return NULL;
0168
}
0169
0170
static const char *WtTaskNamespaceCfg(cmd_parms *cmd, void *dirConf, char *script)
0171
{
0172
  WtTableSetStrToStr(WtGetTargetConf(cmd, dirConf),
0173
    "server.taskNamespace", script);
0174
  return NULL;
0175
}
0176
0177
static Tcl_Obj *WtCfgGetEvents(Tcl_Obj *tbl)
0178
{
0179
  Tcl_Obj *events = WtTableGetObjFromStr(tbl, wtEventsKey, NULL);
0180
  if (!events) {
0181
    events = WtNewTableObj();
0182
    WtTableSetStrToObj(tbl, wtEventsKey, events);
0183
  }
0184
  return events;
0185
}
0186
0187
static const char *WtEventHandlerCfg(cmd_parms *cmd, void *dirConf,
0188
    char *a, char *b, char *c)
0189
{
0190
  char *ret = NULL, *mode, *name, *script;
0191
  Tcl_Obj *nameObj, *scriptObj, *tbl, *events, *item;
0192
  int doAdd = 0;
0193
0194
  mode = c ? a : NULL;
0195
  name = c ? b : a;
0196
  nameObj = WtNewString(name);
0197
  Tcl_IncrRefCount(nameObj);
0198
  script = c ? c : b;
0199
  scriptObj = WtNewString(script);
0200
  Tcl_IncrRefCount(scriptObj);
0201
0202
  tbl = WtGetTargetConf(cmd, dirConf);
0203
0204
  if (mode) {
0205
    if (!strcmp(mode, "add")) {
0206
      doAdd = 1;
0207
    } else {
0208
      ret = "WtEventHandler: Invalid option.";
0209
    }
0210
  }
0211
0212
  if (!mode || doAdd) {
0213
    events = WtCfgGetEvents(tbl);
0214
    if (!doAdd) {
0215
      WtTableRemove(events, nameObj);
0216
    }
0217
    item = WtNewTableObj();
0218
    WtTableSetStrToInt(item, "add", doAdd);
0219
    WtTableSetStrToObj(item, "script", scriptObj);
0220
    if (!WtTableAppendToList(events, nameObj, item, NULL, NULL)) {
0221
      ret = "WtEventHandler: Failed to set configuration value.";
0222
      Tcl_DecrRefCount(item);
0223
    }
0224
  }
0225
0226
  Tcl_DecrRefCount(nameObj);
0227
  Tcl_DecrRefCount(scriptObj);
0228
0229
  return ret;
0230
}
0231
0232
static const char *WtIncludeNamespaceCfg(cmd_parms *cmd, void *dirConf,
0233
    char *arg1)
0234
{
0235
  WtTableSetStrToStr(WtGetTargetConf(cmd, dirConf),
0236
    "server.includeNamespace", arg1);
0237
  return NULL;
0238
}
0239
0240
static const char *WtAddHeaderTrailerCfg(cmd_parms *cmd, void *dirConf,
0241
    int flag)
0242
{
0243
  WtTableSetStrToBool(WtGetTargetConf(cmd, dirConf),
0244
    "server.addHeaderTrailer", flag);
0245
  return NULL;
0246
}
0247
0248
static const char *WtIncludeHeaderCfg(cmd_parms *cmd, void *dirConf,
0249
    char *arg1)
0250
{
0251
  WtTableSetStrToStr(WtGetTargetConf(cmd, dirConf),
0252
    "server.includeHeader", arg1);
0253
  return NULL;
0254
}
0255
0256
static const char *WtIncludeTrailerCfg(cmd_parms *cmd, void *dirConf,
0257
    char *arg1)
0258
{
0259
  WtTableSetStrToStr(WtGetTargetConf(cmd, dirConf),
0260
    "server.includeTrailer", arg1);
0261
  return NULL;
0262
}
0263
0264
static const char *WtScriptStartStringCfg(cmd_parms *cmd, void *dirConf,
0265
    char *arg1)
0266
{
0267
  WtTableSetStrToStr(WtGetTargetConf(cmd, dirConf),
0268
    "server.scriptStartString", arg1);
0269
  return NULL;
0270
}
0271
0272
static const char *WtScriptEndStringCfg(cmd_parms *cmd, void *dirConf,
0273
    char *arg1)
0274
{
0275
  WtTableSetStrToStr(WtGetTargetConf(cmd, dirConf),
0276
    "server.scriptEndString", arg1);
0277
  return NULL;
0278
}
0279
0280
static const char *WtInterpolateTextCfg(cmd_parms *cmd, void *dirConf,
0281
    int flag)
0282
{
0283
  WtTableSetStrToBool(WtGetTargetConf(cmd, dirConf),
0284
    "server.interpolateText", flag);
0285
  return NULL;
0286
}
0287
0288
static const char *WtPageTextHandlerCfg(cmd_parms *cmd, void *dirConf,
0289
    char *arg1)
0290
{
0291
  WtTableSetStrToStr(WtGetTargetConf(cmd, dirConf),
0292
    "server.pageTextHandler", arg1);
0293
  return NULL;
0294
}
0295
0296
static const char *WtPageExprHandlerCfg(cmd_parms *cmd, void *dirConf,
0297
    char *arg1)
0298
{
0299
  WtTableSetStrToStr(WtGetTargetConf(cmd, dirConf),
0300
    "server.pageExprHandler", arg1);
0301
  return NULL;
0302
}
0303
0304
static const char *WtSessionHandlerCfg(cmd_parms *cmd, void *dirConf,
0305
    char *arg1)
0306
{
0307
  WtTableSetStrToStr(WtGetTargetConf(cmd, dirConf),
0308
    "session.handler", arg1);
0309
  return NULL;
0310
}
0311
0312
static const char *WtSessionHandlerTypeCfg(cmd_parms *cmd, void *dirConf,
0313
    char *arg1)
0314
{
0315
  WtTableSetStrToStr(WtGetTargetConf(cmd, dirConf),
0316
    "session.handlerType", arg1);
0317
  return NULL;
0318
}
0319
0320
static const char *WtSessionCookieNameCfg(cmd_parms *cmd, void *dirConf,
0321
    char *arg1)
0322
{
0323
  WtTableSetStrToStr(WtGetTargetConf(cmd, dirConf),
0324
    "session.cookieName", arg1);
0325
  return NULL;
0326
}
0327
0328
static const char *WtSessionMaxIdleTimeCfg(cmd_parms *cmd, void *dirConf,
0329
    char *arg1)
0330
{
0331
  char *err = NULL;
0332
  Tcl_Obj *numStr;
0333
  int intVal;
0334
0335
  numStr = WtNewString(arg1);
0336
  Tcl_IncrRefCount(numStr);
0337
0338
  if (Tcl_GetIntFromObj(NULL, numStr, &intVal) != TCL_OK) {
0339
    err = "WtSessionMaxIdleTime: Number of seconds must be an integer.";
0340
  } else {
0341
    WtTableSetStrToInt(WtGetTargetConf(cmd, dirConf),
0342
      "session.maxIdleTime", intVal);
0343
  }
0344
0345
  return err;
0346
}
0347
0348
static const char *WtSessionSweepFrequencyCfg(cmd_parms *cmd,
0349
    void *dirConf, char *arg1)
0350
{
0351
  char *err = NULL;
0352
  Tcl_Obj *numStr;
0353
  double dblVal;
0354
0355
  numStr = WtNewString(arg1);
0356
  Tcl_IncrRefCount(numStr);
0357
0358
  if (Tcl_GetDoubleFromObj(NULL, numStr, &dblVal) != TCL_OK) {
0359
    err = "WtSessionSweepFrequency: Value must be a decimal number.";
0360
  } else {
0361
    WtTableSetStrToDouble(WtGetTargetConf(cmd, dirConf),
0362
      "session.sweepFrequency", dblVal);
0363
  }
0364
0365
  return err;
0366
}
0367
0368
static const char *WtDbSessionHandlerCfg(cmd_parms *cmd, void *dirConf,
0369
    char *arg1)
0370
{
0371
  WtTableSetStrToStr(WtGetTargetConf(cmd, dirConf),
0372
    "session.dbSession.dbHandlerNamespace", arg1);
0373
  return NULL;
0374
}
0375
0376
static const handler_rec wtcl_handlers[] =
0377
{
0378
  {"application/x-httpd-wtcl", wtcl_handler},
0379
  {NULL}
0380
};
0381
0382
static const command_rec wtcl_cmds[] =
0383
{
0384
  {"WtReuseInterp", WtReuseInterpCfg, NULL, OR_FILEINFO, FLAG,
0385
    "Reuse the same interpreter for each request. Usage: WtReuseInterp flag"},
0386
0387
  {"WtDeleteInterp", WtDeleteInterpCfg, NULL, OR_FILEINFO, FLAG,
0388
    "Delete the interpreter when the request ends. "
0389
    "Usage: WtDeleteInterp flag"},
0390
0391
  {"WtTaskNamespace", WtTaskNamespaceCfg, NULL, OR_FILEINFO, FLAG,
0392
    "Evaluate the request in this namespace. Usage: WtTaskNamespace namespace"},
0393
0394
  {"WtEventHandler", WtEventHandlerCfg, NULL, OR_FILEINFO, TAKE23,
0395
    "Script to evaluate when a context event is triggered. "
0396
    "The script will replace any previously defined handlers unless "
0397
    "the \"add\" option is specified. "
0398
    "Usage: WtEventHandler [add] eventName script"},
0399
0400
  {"WtIncludeNamespace", WtIncludeNamespaceCfg, NULL, ACCESS_CONF, TAKE1,
0401
    "Evaluate includes in this namespace. "
0402
    "Usage: WtIncludeNamespace namespace"},
0403
0404
  {"WtAddHeaderTrailer", WtAddHeaderTrailerCfg, NULL, ACCESS_CONF, FLAG,
0405
    "Add header and trailer strings to includes. "
0406
    "Usage: WtAddHeaderTrailer flag"},
0407
0408
  {"WtIncludeHeader", WtIncludeHeaderCfg, NULL, ACCESS_CONF, TAKE1,
0409
    "Header to prepend to includes. Usage: WtIncludeHeader string"},
0410
0411
  {"WtIncludeTrailer", WtIncludeTrailerCfg, NULL, ACCESS_CONF, TAKE1,
0412
    "Trailer to append to includes. Usage: WtIncludeTrailer string"},
0413
0414
  {"WtScriptStartString", WtScriptStartStringCfg, NULL, ACCESS_CONF, TAKE1,
0415
    "Token marking the beginning of a script section. "
0416
    "Usage: WtScriptStartString string"},
0417
0418
  {"WtScriptEndString", WtScriptEndStringCfg, NULL, ACCESS_CONF, TAKE1,
0419
    "Token marking the end of a script section. "
0420
    "Usage: WtScriptEndString string"},
0421
0422
  {"WtInterpolateText", WtInterpolateTextCfg, NULL, ACCESS_CONF, FLAG,
0423
    "Interpolate text sections with subst prior to printing. "
0424
    "Usage: WtInterpolateText flag."},
0425
0426
  {"WtPageTextHandlerString", WtPageTextHandlerCfg, NULL, ACCESS_CONF, TAKE1,
0427
    "Handler for text sections. Usage: WtPageTextHandler proc"},
0428
0429
  {"WtPageExprHandlerString", WtPageExprHandlerCfg, NULL, ACCESS_CONF,
0430
    TAKE1, "Handler for page expressions. "
0431
    "Usage: WtPageExprResultHandler proc"},
0432
0433
  {"WtSessionHandler", WtSessionHandlerCfg, NULL, ACCESS_CONF, TAKE1,
0434
    "Session handler. Usage: WtSessionHandler script"},
0435
0436
  {"WtSessionHandlerType", WtSessionHandlerTypeCfg, NULL, ACCESS_CONF, TAKE1,
0437
    "Session handler type. Usage: WtSessionHandlerType type"},
0438
0439
  {"WtSessionCookieName", WtSessionCookieNameCfg, NULL, ACCESS_CONF, TAKE1,
0440
    "Session handler cookie name. Usage: WtSessionCookieName name"},
0441
0442
  {"WtSessionMaxIdleTime", WtSessionMaxIdleTimeCfg, NULL, ACCESS_CONF, TAKE1,
0443
    "Maximum idle time in seconds. Usage: WtSessionMaxIdleTime seconds"},
0444
0445
  {"WtSessionSweepFrequency", WtSessionSweepFrequencyCfg, NULL,
0446
    ACCESS_CONF, TAKE1,
0447
    "Value between 0 and 1. The probability that expired sessions "
0448
    " will be expunged at the end of a request. "
0449
    "Usage: WtSessionSweepFrequency frequency"},
0450
0451
  {"WtDbSessionHandler", WtDbSessionHandlerCfg, NULL, ACCESS_CONF, TAKE1,
0452
    "Database session storage handler. "
0453
    "Usage: WtDbSessionHandler handler"},
0454
0455
  {NULL}
0456
};
0457
0458
#ifdef WIN32
0459
0460
static DWORD tls_index;
0461
0462
BOOL WINAPI DllMain(HINSTANCE dllhandle, DWORD reason, LPVOID reserved)
0463
{
0464
  switch (reason) {
0465
    case DLL_PROCESS_ATTACH:
0466
      tls_index = TlsAlloc();
0467
      if (tls_index == TLS_OUT_OF_INDEXES) {
0468
        return FALSE;
0469
      }
0470
    case DLL_THREAD_ATTACH:
0471
      TlsSetValue(tls_index, (LPVOID)0);
0472
      break;
0473
    case DLL_THREAD_DETACH:
0474
      break;
0475
    case DLL_PROCESS_DETACH:
0476
      TlsFree(tls_index);
0477
      break;
0478
  }
0479
0480
  return TRUE;
0481
}
0482
0483
WtThreadStorage *WtGetThreadStorage()
0484
{
0485
  WtThreadStorage *p = (WtThreadStorage *)TlsGetValue(tls_index);
0486
  if (!p) {
0487
    p = (WtThreadStorage *)calloc(1, sizeof(WtThreadStorage));
0488
    TlsSetValue(tls_index, p);
0489
  }
0490
  return p;
0491
}
0492
0493
#endif /* WIN32 */
0494
0495
module MODULE_VAR_EXPORT wtcl_module =
0496
{
0497
  STANDARD_MODULE_STUFF,
0498
  wtcl_init,                 /* module initializer */
0499
  wtcl_create_dir_config,
0500
  wtcl_merge_dir_config,
0501
  wtcl_create_server_config,
0502
  wtcl_merge_server_config,
0503
  wtcl_cmds,
0504
  wtcl_handlers,
0505
  NULL,
0506
  NULL,
0507
  NULL,
0508
  NULL,
0509
  NULL,
0510
  NULL,
0511
  NULL,
0512
#if MODULE_MAGIC_NUMBER >= 19970103
0513
  NULL,
0514
#endif
0515
#if MODULE_MAGIC_NUMBER >= 19970719
0516
  wtcl_child_init,         /* process initializer */
0517
#endif
0518
#if MODULE_MAGIC_NUMBER >= 19970728
0519
  wtcl_child_exit,         /* process exit/cleanup */
0520
#endif
0521
#if MODULE_MAGIC_NUMBER >= 19970902
0522
  NULL
0523
#endif
0524
};