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

Lines Size Modified Created Owner MIME Types
928 22,846 2010/05/08 18:46:41 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 <util_md5.h>
0019
#include "WtSession.h"
0020
#include "WtUtil.h"
0021
#include "WtDbSession.h"
0022
#include "WtProcSession.h"
0023
#include "WtContext.h"
0024
#include "WtTable.h"
0025
#include "WtTableUtil.h"
0026
#include "WtCookie.h"
0027
#include "WtClientRequest.h"
0028
0029
const char *wtSessionStatusNames[] =
0030
{
0031
  "new",
0032
  "active",
0033
  "expired",
0034
  "invalid"
0035
};
0036
0037
/* Initialize the session */
0038
0039
void WtInitSession(WtSession *s)
0040
{
0041
  s->clientId = NULL;
0042
  s->clientValue = WtNewString(NULL);
0043
  s->clientTimeStamp = -1;
0044
  s->cookieName = WtNewString("WtSessionId");
0045
  Tcl_IncrRefCount(s->cookieName);
0046
  s->cookie = NULL;
0047
  s->cookieSendMode = WtNewString("default");
0048
  Tcl_IncrRefCount(s->cookieSendMode);
0049
  s->maxIdleTime = 86400;
0050
  s->sweepFrequency = 0.001;
0051
#ifdef WIN32
0052
  s->handler = WtNewString("::wt::session::procSession::procSessionHandler");
0053
#else
0054
  s->handler = WtNewString("::wt::session::dbSession::dbSessionHandler");
0055
#endif /* WIN32 */
0056
  Tcl_IncrRefCount(s->handler);
0057
  s->handlerType = WtNewString("proc");
0058
  Tcl_IncrRefCount(s->handlerType);
0059
  s->handlerLoaded = 0;
0060
  s->dbSession = NULL;
0061
  s->procSession = NULL;
0062
  s->isInitialized = 1;
0063
}
0064
0065
/* Delete the session */
0066
0067
void WtDeleteSession(WtSession *s)
0068
{
0069
  s->isInitialized = 0;
0070
0071
  WtDecr(s->clientId);
0072
  s->clientId = NULL;
0073
0074
  WtDecr(s->clientValue);
0075
  s->clientValue = NULL;
0076
0077
  WtDecr(s->cookieName);
0078
  s->cookieName = NULL;
0079
0080
  WtDecr(s->cookie);
0081
  s->cookie = NULL;
0082
0083
  WtDecr(s->cookieSendMode);
0084
  s->cookieSendMode = NULL;
0085
0086
  WtDecr(s->handler);
0087
  s->handler = NULL;
0088
0089
  WtDecr(s->handlerType);
0090
  s->handlerType = NULL;
0091
0092
  WtDecr(s->dbSession);
0093
  s->dbSession = NULL;
0094
0095
  WtDecr(s->procSession);
0096
  s->procSession = NULL;
0097
}
0098
0099
/* Get the initial session ID */
0100
0101
Tcl_Obj *WtGetInitialSessionId(WtSession *s, int *isAutoIdPtr, Tcl_Interp *interp)
0102
{
0103
  Tcl_Obj *id = NULL;
0104
  int isAutoId = 0;
0105
0106
  if (WtGetClientSessionId(s, interp)) {
0107
    if (Tcl_GetCharLength(s->clientId)) {
0108
      id = s->clientId;
0109
      isAutoId = 0;
0110
    } else if (id = WtGenerateSessionId(s, interp)) {
0111
      isAutoId = 1;
0112
    }
0113
  }
0114
0115
  if (id && isAutoIdPtr) {
0116
    *isAutoIdPtr = isAutoId;
0117
  }
0118
0119
  return id;
0120
}
0121
0122
/* Get the client-supplied session ID */
0123
0124
Tcl_Obj *WtGetClientSessionId(WtSession *s, Tcl_Interp *interp)
0125
{
0126
  int ok = 1;
0127
  long tsVal;
0128
  WtContext *w = WtGetAssocContext(interp);
0129
  Tcl_Obj *obj = NULL, *ts;
0130
  char *val, *p;
0131
0132
  if (!s->clientId) {
0133
    if (Tcl_GetCharLength(s->cookieName)) {
0134
      if (!WtReadRequestCookies(w, interp)) {
0135
        ok = 0;
0136
      } else if (!WtConvertToTable(w->web->clientRequest.cookies,
0137
          interp)) {
0138
        ok = 0;
0139
      } else if (obj = WtTableGet(w->web->clientRequest.cookies,
0140
          s->cookieName)) {
0141
        s->clientValue = obj;
0142
        Tcl_IncrRefCount(s->clientValue);
0143
0144
        val = WtToString(obj);
0145
        if (p = strchr(val, '.')) {
0146
          s->clientId = Tcl_NewStringObj(val, p - val);
0147
          Tcl_IncrRefCount(s->clientId);
0148
0149
          ts = Tcl_NewStringObj(p + 1, -1);
0150
          Tcl_IncrRefCount(ts);
0151
0152
          if (Tcl_GetLongFromObj(interp, ts, &tsVal) == TCL_OK) {
0153
            if (tsVal > 0) {
0154
              s->clientTimeStamp = (time_t)tsVal;
0155
            }
0156
          }
0157
0158
          Tcl_DecrRefCount(ts);
0159
        } else {
0160
          s->clientId = obj;
0161
          Tcl_IncrRefCount(s->clientId);
0162
        }
0163
      }
0164
    }
0165
0166
    if (ok && !s->clientId) {
0167
      s->clientValue = WtNewString(NULL);
0168
      Tcl_IncrRefCount(s->clientValue);
0169
      s->clientId = WtNewString(NULL);
0170
      Tcl_IncrRefCount(s->clientId);
0171
    }
0172
  }
0173
0174
  return ok ? s->clientId : NULL;
0175
}
0176
0177
/* Generate a new session ID */
0178
0179
Tcl_Obj *WtGenerateSessionId(WtSession *s, Tcl_Interp *interp)
0180
{
0181
  Tcl_Obj *ret = NULL, *src, *obj;
0182
  char *bytes;
0183
  int len;
0184
  WtContext *w = WtGetAssocContext(interp);
0185
0186
  if (WtConvertToTable(w->web->serverVars, interp)) {
0187
    src = Tcl_NewStringObj(NULL, 0);
0188
0189
    /* Use mod_unique_id */
0190
0191
    if ((obj = WtTableGetObjFromStr(w->web->serverVars,
0192
        "UNIQUE_ID", NULL)) && Tcl_GetCharLength(obj)) {
0193
      Tcl_AppendObjToObj(src, obj);
0194
    }
0195
0196
    /* Use environment (weak) */
0197
0198
    WtSessionAddEnvironment(src);
0199
    if ((obj = WtTableGetObjFromStr(w->web->serverVars,
0200
        "REMOTE_ADDR", NULL)) && Tcl_GetCharLength(obj)) {
0201
      Tcl_AppendObjToObj(src, obj);
0202
    }
0203
    if (w->apServer->server_hostname) {
0204
      Tcl_AppendToObj(src, w->apServer->server_hostname, -1);
0205
    }
0206
    Tcl_AppendStringsToObj(src, __FILE__, __TIME__, "baboo", NULL);
0207
0208
    bytes = Tcl_GetStringFromObj(src, &len);
0209
    ret = Tcl_NewStringObj(ap_md5_binary(w->apReq->pool, bytes, len), -1);
0210
0211
    Tcl_DecrRefCount(src);
0212
  }
0213
0214
  return ret;
0215
}
0216
0217
void WtSessionAddEnvironment(Tcl_Obj *str)
0218
{
0219
  char buf[512];
0220
0221
#ifdef WIN32
0222
0223
  FILETIME st, ct, et, kt, ut;
0224
  HANDLE process;
0225
0226
  GetSystemTimeAsFileTime(&st);
0227
0228
  if (process = GetCurrentProcess()) {
0229
    GetProcessTimes(process, &ct, &et, &kt, &ut);
0230
  }
0231
0232
  ap_snprintf(buf, sizeof(buf), "%d%d%d%d%d%d%d%d%d%d%d%d%c",
0233
    GetCurrentProcessId(), GetCurrentThreadId(),
0234
    st.dwLowDateTime, st.dwHighDateTime,
0235
    ct.dwLowDateTime, ct.dwHighDateTime,
0236
    et.dwLowDateTime, et.dwHighDateTime,
0237
    kt.dwLowDateTime, kt.dwHighDateTime,
0238
    ut.dwLowDateTime, ut.dwHighDateTime,
0239
    buf[ut.dwLowDateTime % sizeof(buf)]);
0240
0241
#else
0242
0243
  struct timeval tv;
0244
0245
  gettimeofday(&tv, NULL);
0246
0247
  ap_snprintf(buf, sizeof(buf), "%ld%ld%ld%ld%c", src, buf,
0248
    getpid(), gettid(), tv.tv_sec, tv.tv_usec,
0249
    buf[tv.tv_usec % sizeof(buf)]);
0250
0251
#endif /* WIN32 */
0252
0253
  Tcl_AppendToObj(str, buf, -1);
0254
}
0255
0256
/* Get the output cookie */
0257
0258
Tcl_Obj *WtGetSessionCookie(WtSession *s, Tcl_Interp *interp)
0259
{
0260
  if (!s->cookie) {
0261
    s->cookie = WtNewCookieObj();
0262
    Tcl_IncrRefCount(s->cookie);
0263
    if (Tcl_GetCharLength(s->cookieName)) {
0264
      if (!WtCookieSetName(s->cookie, s->cookieName, interp)) {
0265
        Tcl_DecrRefCount(s->cookie);
0266
        s->cookie = NULL;
0267
      }
0268
    }
0269
  }
0270
0271
  return s->cookie;
0272
}
0273
0274
/* Set the cookie name */
0275
0276
int WtSetSessionCookieName(WtSession *s, Tcl_Obj *name, Tcl_Interp *interp)
0277
{
0278
  /* Client cookie name */
0279
0280
  Tcl_DecrRefCount(s->cookieName);
0281
  s->cookieName = name;
0282
  Tcl_IncrRefCount(s->cookieName);
0283
0284
  /* Output cookie */
0285
0286
  if (WtGetSessionCookie(s, interp)) {
0287
    WtCopyOnWrite(&s->cookie);
0288
    return WtCookieSetName(s->cookie, name, interp);
0289
  }
0290
0291
  return 0;
0292
}
0293
0294
/* Send the cookie */
0295
0296
int WtSetSessionCookie(WtSession *s, Tcl_Obj *id, Tcl_Interp *interp,
0297
    time_t timeStamp)
0298
{
0299
  int ok = 1, doSend = 0;
0300
  WtContext *w;
0301
  Tcl_Obj *val, *atimeObj;
0302
0303
  if (id && Tcl_GetCharLength(id)) {
0304
    if (!strcmp(WtToString(s->cookieSendMode), "default")) {
0305
      if (!s->clientId || !Tcl_GetCharLength(s->clientId) ||
0306
          strcmp(WtToString(s->clientId), WtToString(id)) ||
0307
          timeStamp != s->clientTimeStamp) {
0308
        doSend = 1;
0309
      }
0310
    } else if (Tcl_GetBooleanFromObj(interp, s->cookieSendMode,
0311
        &doSend) != TCL_OK) {
0312
      ok = 0;
0313
    }
0314
0315
    if (ok && doSend) {
0316
      if (!WtGetSessionCookie(s, interp)) {
0317
        ok = 0;
0318
      } else {
0319
        WtCopyOnWrite(&s->cookie);
0320
0321
        if (timeStamp == -1) {
0322
          WtCookieSetValue(s->cookie, id, interp);
0323
        } else {
0324
          val = Tcl_DuplicateObj(id);
0325
          Tcl_IncrRefCount(val);
0326
          Tcl_AppendToObj(val, ".", 1);
0327
0328
          atimeObj = Tcl_NewLongObj((long)timeStamp);
0329
          Tcl_IncrRefCount(atimeObj);
0330
          Tcl_AppendObjToObj(val, atimeObj);
0331
          Tcl_DecrRefCount(atimeObj);
0332
0333
          WtCookieSetValue(s->cookie, val, interp);
0334
0335
          Tcl_DecrRefCount(val);
0336
        }
0337
0338
        /* Store in the cookie jar */
0339
0340
        w = WtGetAssocContext(interp);
0341
0342
        if (!WtRemoveFromCln(w->web->clientResponse.cookies,
0343
              s->cookieName, -1, interp) ||
0344
            !WtAppendClnItem(w->web->clientResponse.cookies,
0345
              s->cookie, interp)) {
0346
          ok = 0;
0347
        }
0348
      }
0349
    }
0350
  }
0351
0352
  return ok;
0353
}
0354
0355
/* Set the handler */
0356
0357
int WtSetSessionHandler(WtSession *s, Tcl_Obj *handler, Tcl_Interp *interp)
0358
{
0359
  int ok = 0;
0360
  if (!Tcl_GetCharLength(handler)) {
0361
    Tcl_AppendResult(interp, "Session handler string is invalid.");
0362
  } else if (!strcmp(WtToString(s->handler), WtToString(handler))) {
0363
    ok = 1;
0364
  } else if (!s->handlerLoaded || WtUnloadSessionHandler(s, interp)) {
0365
    Tcl_DecrRefCount(s->handler);
0366
    s->handler = handler;
0367
    Tcl_IncrRefCount(s->handler);
0368
    ok = 1;
0369
  }
0370
0371
  return ok;
0372
}
0373
0374
/* Load the handler */
0375
0376
int WtLoadSessionHandler(WtSession *s, Tcl_Interp *interp)
0377
{
0378
  int ok = 0;
0379
0380
  if (s->handlerLoaded) {
0381
    ok = 1;
0382
  } else if (WtSessionHandlerStr(s, s->handler, "loadModule",
0383
      interp, 0, NULL) == TCL_OK) {
0384
    s->handlerLoaded = 1;
0385
    ok = 1;
0386
  }
0387
0388
  return ok;
0389
}
0390
0391
/* Unload the handler */
0392
0393
int WtUnloadSessionHandler(WtSession *s, Tcl_Interp *interp)
0394
{
0395
  int ok = 0;
0396
0397
  if (!s->handlerLoaded) {
0398
    ok = 1;
0399
  } else if (WtSessionHandlerStr(s, s->handler,
0400
      "unloadModule", interp, 0, NULL) == TCL_OK) {
0401
    s->handlerLoaded = 0;
0402
    ok = 1;
0403
  }
0404
0405
  return ok;
0406
}
0407
0408
/* Check if we need to sweep the sessions */
0409
0410
int WtShouldSweepSessions(WtSession *s, Tcl_Interp *interp)
0411
{
0412
  if (s->sweepFrequency > 0 &&
0413
      ((rand() * 1.0) / (RAND_MAX * 1.0)) <= s->sweepFrequency) {
0414
    return 1;
0415
  }
0416
  return 0;
0417
}
0418
0419
/* Finalize the request */
0420
0421
int WtSessionEndRequest(WtSession *s, Tcl_Interp *interp)
0422
{
0423
  int ok = 1;
0424
  Tcl_Obj *err, *msg;
0425
0426
  msg = WtNewString(NULL);
0427
  Tcl_IncrRefCount(msg);
0428
0429
  if (s->handlerLoaded) {
0430
    if (WtSessionHandlerStr(s, s->handler, "finalizeRequest",
0431
        interp, 0, NULL) != TCL_OK) {
0432
      err = Tcl_GetVar2Ex(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY);
0433
      Tcl_AppendObjToObj(msg, err);
0434
      ok = 0;
0435
    }
0436
  }
0437
0438
  if (!WtUnloadSession(s, interp)) {
0439
    err = Tcl_GetVar2Ex(interp, "errorInfo", NULL, TCL_GLOBAL_ONLY);
0440
    if (Tcl_GetCharLength(msg)) {
0441
      Tcl_AppendToObj(msg, "\n    and\n", -1);
0442
    }
0443
    Tcl_AppendObjToObj(msg, err);
0444
    ok = 0;
0445
  }
0446
0447
  if (!ok) {
0448
    Tcl_ResetResult(interp);
0449
    Tcl_AddObjErrorInfo(interp, WtToString(msg), -1);
0450
  }
0451
0452
  Tcl_DecrRefCount(msg);
0453
0454
  return ok;
0455
}
0456
0457
/* Unload the session module */
0458
0459
int WtUnloadSession(WtSession *s, Tcl_Interp *interp)
0460
{
0461
  int ok = 1;
0462
0463
  if (s->handlerLoaded && !WtUnloadSessionHandler(s, interp)) {
0464
    ok = 0;
0465
  }
0466
0467
  return ok;
0468
}
0469
0470
/* session command */
0471
0472
int WtSessionCmd(ClientData clientData, Tcl_Interp *interp,
0473
    int objc, Tcl_Obj *const objv[])
0474
{
0475
  int ret = TCL_ERROR;
0476
  char *subCmd;
0477
  WtSession *s = WtGetAssocSession(interp);
0478
0479
  if (objc == 1) {
0480
0481
    WtSessionCmdUsage(interp, objv[0]);
0482
0483
  } else if (objc >= 2) {
0484
0485
    subCmd = Tcl_GetString(objv[1]);
0486
0487
    if (!strcmp(subCmd, "clientId")) {
0488
      ret = WtSessionClientIdCmd(clientData, interp, s, objc, objv);
0489
    } else if (!strcmp(subCmd, "newId")) {
0490
      ret = WtSessionNewIdCmd(clientData, interp, s, objc, objv);
0491
    } else if (!strcmp(subCmd, "cookie")) {
0492
      ret = WtSessionCookieCmd(clientData, interp, s, objc, objv);
0493
    } else if (!strcmp(subCmd, "cookieName")) {
0494
      ret = WtSessionCookieNameCmd(clientData, interp, s, objc, objv);
0495
    } else if (!strcmp(subCmd, "cookieSendMode")) {
0496
      ret = WtSessionCookieSendModeCmd(clientData, interp, s, objc, objv);
0497
    } else if (!strcmp(subCmd, "maxIdleTime")) {
0498
      ret = WtSessionMaxIdleTimeCmd(clientData, interp, s, objc, objv);
0499
    } else if (!strcmp(subCmd, "sweepFrequency")) {
0500
      ret = WtSessionSweepFrequencyCmd(clientData, interp, s, objc, objv);
0501
    } else if (!strcmp(subCmd, "handler")) {
0502
      ret = WtSessionHandlerCmd(clientData, interp, s, objc, objv);
0503
    } else if (!strcmp(subCmd, "handlerType")) {
0504
      ret = WtSessionHandlerTypeCmd(clientData, interp, s, objc, objv);
0505
    } else {
0506
      ret = WtSessionHandler(s, s->handler, objv[1], interp,
0507
        objc - 2, objv + 2);
0508
    }
0509
  }
0510
0511
  return ret;
0512
}
0513
0514
/* clientId comand */
0515
0516
int WtSessionClientIdCmd(ClientData clientData, Tcl_Interp *interp,
0517
    WtSession *s, int objc, Tcl_Obj *const objv[])
0518
{
0519
  int ret = TCL_ERROR;
0520
  Tcl_Obj *id;
0521
0522
  if (objc != 2) {
0523
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0524
      WtToString(objv[0]), " ", WtToString(objv[1]));
0525
  } else if (id = WtGetClientSessionId(s, interp)) {
0526
    Tcl_SetObjResult(interp, id);
0527
    ret = TCL_OK;
0528
  }
0529
0530
  return ret;
0531
}
0532
0533
/* newId comand */
0534
0535
int WtSessionNewIdCmd(ClientData clientData, Tcl_Interp *interp,
0536
    WtSession *s, int objc, Tcl_Obj *const objv[])
0537
{
0538
  int ret = TCL_ERROR;
0539
  Tcl_Obj *id;
0540
0541
  if (objc != 2) {
0542
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0543
      WtToString(objv[0]), " ", WtToString(objv[1]));
0544
  } else if (id = WtGenerateSessionId(s, interp)) {
0545
    Tcl_SetObjResult(interp, id);
0546
    ret = TCL_OK;
0547
  }
0548
0549
  return ret;
0550
}
0551
0552
/* cookieName command */
0553
0554
int WtSessionCookieNameCmd(ClientData clientData, Tcl_Interp *interp,
0555
    WtSession *s, int objc, Tcl_Obj *const objv[])
0556
{
0557
  int ret = TCL_ERROR;
0558
0559
  if (objc != 2 && objc != 3) {
0560
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0561
      WtToString(objv[0]), " ", WtToString(objv[1]),
0562
      " ?cookieName?", NULL);
0563
  } else if (objc == 2) {
0564
    Tcl_SetObjResult(interp, s->cookieName);
0565
    ret = TCL_OK;
0566
  } else if (objc == 3) {
0567
    if (WtSetSessionCookieName(s, objv[2], interp)) {
0568
      Tcl_SetObjResult(interp, s->cookieName);
0569
      ret = TCL_OK;
0570
    }
0571
  }
0572
0573
  return ret;
0574
}
0575
0576
/* cookie command */
0577
0578
int WtSessionCookieCmd(ClientData clientData, Tcl_Interp *interp,
0579
    WtSession *s, int objc, Tcl_Obj *const objv[])
0580
{
0581
  int ret = TCL_ERROR;
0582
  Tcl_Obj *cookie;
0583
0584
  if (objc != 2 && objc != 3) {
0585
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0586
      WtToString(objv[0]), " ", WtToString(objv[1]),
0587
      " ?cookie?", NULL);
0588
  } else {
0589
    if (objc == 2) {
0590
      if (cookie = WtGetSessionCookie(s, interp)) {
0591
        Tcl_SetObjResult(interp, cookie);
0592
        ret = TCL_OK;
0593
      }
0594
    } else if (objc == 3) {
0595
      if (s->cookie != objv[2]) {
0596
        if (s->cookie) {
0597
          Tcl_DecrRefCount(s->cookie);
0598
        }
0599
        s->cookie = objv[2];
0600
        Tcl_IncrRefCount(s->cookie);
0601
      }
0602
      Tcl_SetObjResult(interp, s->cookie);
0603
      ret = TCL_OK;
0604
    }
0605
  }
0606
0607
  return ret;
0608
}
0609
0610
/* cookieSendMode command */
0611
0612
int WtSessionCookieSendModeCmd(ClientData clientData, Tcl_Interp *interp,
0613
    WtSession *s, int objc, Tcl_Obj *const objv[])
0614
{
0615
  int ret = TCL_ERROR, intVal;
0616
  const char *str;
0617
0618
  if (objc != 2 && objc != 3) {
0619
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0620
      WtToString(objv[0]), " ", WtToString(objv[1]),
0621
      " ?cookieSendMode?", NULL);
0622
  } else if (objc == 2) {
0623
    Tcl_SetObjResult(interp, s->cookieSendMode);
0624
    ret = TCL_OK;
0625
  } else if (objc == 3) {
0626
    str = WtToString(objv[2]);
0627
    if (!strcmp(str, "default") ||
0628
        Tcl_GetBooleanFromObj(interp, objv[2], &intVal) == TCL_OK) {
0629
      Tcl_DecrRefCount(s->cookieSendMode);
0630
      s->cookieSendMode = objv[2];
0631
      Tcl_IncrRefCount(s->cookieSendMode);
0632
      Tcl_SetObjResult(interp, s->cookieSendMode);
0633
      ret = TCL_OK;
0634
    }
0635
  }
0636
0637
  return ret;
0638
}
0639
0640
/* maxIdleTime comand */
0641
0642
int WtSessionMaxIdleTimeCmd(ClientData clientData, Tcl_Interp *interp,
0643
    WtSession *s, int objc, Tcl_Obj *const objv[])
0644
{
0645
  int ret = TCL_ERROR, intVal;
0646
0647
  if (objc != 2 && objc != 3) {
0648
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0649
      WtToString(objv[0]), " ", WtToString(objv[1]),
0650
      " ?maxIdleTime?", NULL);
0651
  } else if (objc == 2) {
0652
    Tcl_SetObjResult(interp, Tcl_NewIntObj(s->maxIdleTime));
0653
    ret = TCL_OK;
0654
  } else if (objc == 3) {
0655
    if (Tcl_GetIntFromObj(interp, objv[2], &intVal) == TCL_OK) {
0656
      s->maxIdleTime = intVal;
0657
      ret = TCL_OK;
0658
    }
0659
  }
0660
0661
  return ret;
0662
}
0663
0664
/* sweepFrequency comand */
0665
0666
int WtSessionSweepFrequencyCmd(ClientData clientData, Tcl_Interp *interp,
0667
    WtSession *s, int objc, Tcl_Obj *const objv[])
0668
{
0669
  int ret = TCL_ERROR;
0670
  double dblVal;
0671
0672
  if (objc != 2 && objc != 3) {
0673
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0674
      WtToString(objv[0]), " ", WtToString(objv[1]),
0675
      " ?sweepFrequency", NULL);
0676
  } else if (objc == 2) {
0677
    Tcl_SetObjResult(interp, Tcl_NewDoubleObj(s->sweepFrequency));
0678
    ret = TCL_OK;
0679
  } else if (objc == 3) {
0680
    if (Tcl_GetDoubleFromObj(interp, objv[2], &dblVal) == TCL_OK) {
0681
      s->sweepFrequency = dblVal;
0682
      ret = TCL_OK;
0683
    }
0684
  }
0685
0686
  return ret;
0687
}
0688
0689
/* handler command */
0690
0691
int WtSessionHandlerCmd(ClientData clientData, Tcl_Interp *interp,
0692
    WtSession *s, int objc, Tcl_Obj *const objv[])
0693
{
0694
  int ret = TCL_ERROR;
0695
0696
  if (objc != 2 && objc != 3) {
0697
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0698
    WtToString(objv[0]), " ", WtToString(objv[1]), " ?handler?");
0699
  } else if (objc == 2) {
0700
    Tcl_SetObjResult(interp, s->handler);
0701
    ret = TCL_OK;
0702
  } else if (WtSetSessionHandler(s, objv[2], interp)) {
0703
    Tcl_SetObjResult(interp, s->handler);
0704
    ret = TCL_OK;
0705
  }
0706
0707
  return ret;
0708
}
0709
0710
/* handlerType command */
0711
0712
int WtSessionHandlerTypeCmd(ClientData clientData, Tcl_Interp *interp,
0713
    WtSession *s, int objc, Tcl_Obj *const objv[])
0714
{
0715
  int ret = TCL_ERROR;
0716
  const char *typeStr;
0717
0718
  if (objc != 2 && objc != 3) {
0719
    Tcl_AppendResult(interp, wtBadUsagePrefix,
0720
    WtToString(objv[0]), " ", WtToString(objv[1]), " ?type?");
0721
  } else if (objc == 2) {
0722
    Tcl_SetObjResult(interp, s->handlerType);
0723
    ret = TCL_OK;
0724
  } else {
0725
    typeStr = WtToString(objv[2]);
0726
    if (strcmp(typeStr, "proc") && strcmp(typeStr, "namespace") &&
0727
        strcmp(typeStr, "")) {
0728
      Tcl_AppendResult(interp, "Invalid session handler type: \"",
0729
        typeStr, "\".");
0730
    } else {
0731
      Tcl_DecrRefCount(s->handlerType);
0732
      s->handlerType = objv[2];
0733
      Tcl_IncrRefCount(s->handlerType);
0734
      Tcl_SetObjResult(interp, s->handlerType);
0735
      ret = TCL_OK;
0736
    }
0737
  }
0738
0739
  return ret;
0740
}
0741
0742
/* Get the session associated with an interp */
0743
0744
WtSession *WtGetAssocSession(Tcl_Interp *interp)
0745
{
0746
  WtContext *w = WtGetAssocContext(interp);
0747
  return w && w->web ? &w->web->session : NULL;
0748
}
0749
0750
/* Create the interp commands */
0751
0752
void WtInitSessionCommands(Tcl_Interp *interp)
0753
{
0754
  WtContext *w = Tcl_GetAssocData(interp, "wt::context", NULL);
0755
0756
  WtLog(HERE, APLOG_DEBUG | APLOG_NOERRNO, w,
0757
    "Wtcl: WtInitSessionCommands.");
0758
0759
  Tcl_CreateObjCommand(interp, "::wt::session::session",
0760
                       WtSessionCmd, NULL, NULL);
0761
}
0762
0763
/* Invoke handler */
0764
0765
int WtSessionHandler(WtSession *s, Tcl_Obj *handler,
0766
    Tcl_Obj *method, Tcl_Interp *interp, int objc,
0767
    Tcl_Obj *const objv[])
0768
{
0769
  return WtSessionHandlerInternal(s, handler, method,
0770
    interp, objc, objv);
0771
}
0772
0773
/* Using a C string */
0774
0775
int WtSessionHandlerStr(WtSession *s, Tcl_Obj *handler,
0776
    const char *methodStr, Tcl_Interp *interp, int objc, 
0777
    Tcl_Obj *const objv[])
0778
{
0779
  int ret;
0780
  Tcl_Obj *method = WtNewString(methodStr);
0781
  Tcl_IncrRefCount(method);
0782
  ret = WtSessionHandlerInternal(s, handler, method,
0783
    interp, objc, objv);
0784
  Tcl_DecrRefCount(method);
0785
  return ret;
0786
}
0787
0788
/* All options */
0789
0790
int WtSessionHandlerInternal(WtSession *s,
0791
    Tcl_Obj *handler, Tcl_Obj *method, Tcl_Interp *interp,
0792
    int objc, Tcl_Obj *const objv[])
0793
{
0794
  int ret = TCL_ERROR, i, len, cmdObjc, cmdOffset, n;
0795
  Tcl_Obj *cmd, **argv, *err, *res;
0796
  const char *handlerStr, *handlerTypeStr = NULL;
0797
  WtContext *w = WtGetAssocContext(interp);
0798
0799
  if (WtPrepareSessionHandler(s, method, interp)) {
0800
0801
    /* Build the command */
0802
0803
    cmd = Tcl_NewStringObj(NULL, 0);
0804
    Tcl_IncrRefCount(cmd);
0805
0806
    if (s->handlerType) {
0807
      handlerTypeStr = WtToString(s->handlerType);
0808
    }
0809
0810
    if (handlerTypeStr && !strcmp(handlerTypeStr, "namespace")) {
0811
      len = Tcl_GetCharLength(s->handler);
0812
      if (len >= 2) {
0813
        handlerStr = WtToString(s->handler);
0814
        if (!(handlerStr[len - 1] == ':' && handlerStr[len - 2] == ':')) {
0815
          Tcl_AppendToObj(cmd, "::", 2);
0816
        }
0817
      }
0818
      Tcl_AppendObjToObj(cmd, method);
0819
0820
      cmdObjc = objc + 1;
0821
      n = sizeof(Tcl_Obj *) * cmdObjc;
0822
      argv = (Tcl_Obj **)ckalloc(n);
0823
      argv[0] = cmd;
0824
    } else {
0825
      Tcl_AppendObjToObj(cmd, s->handler);
0826
0827
      cmdObjc = objc + 2;
0828
      n = sizeof(Tcl_Obj *) * cmdObjc;
0829
      argv = (Tcl_Obj **)ckalloc(n);
0830
      argv[0] = cmd;
0831
      argv[1] = method;
0832
    }
0833
0834
    cmdOffset = cmdObjc - objc;
0835
0836
    n = objc * sizeof(Tcl_Obj *);
0837
    memcpy(argv + (cmdObjc - objc), objv, n);
0838
0839
    for (i = 0; i < cmdObjc; i++) {
0840
      Tcl_IncrRefCount(argv[i]);
0841
    }
0842
0843
    /* Evaluate the command */
0844
0845
    ret = Tcl_EvalObjv(interp, cmdObjc, argv, TCL_EVAL_DIRECT);
0846
0847
    err = Tcl_GetVar2Ex(interp, "errorInfo", NULL,
0848
     TCL_GLOBAL_ONLY);
0849
    res = Tcl_GetObjResult(interp);
0850
0851
    WtLog(HERE, APLOG_DEBUG | APLOG_NOERRNO, w,
0852
      "Wtcl: WtSessionHandlerInternal: cmdObjc = %d, ret = %d.",
0853
      cmdObjc, ret);
0854
0855
    for (i = 0; i < cmdObjc; i++) {
0856
      Tcl_DecrRefCount(argv[i]);
0857
    }
0858
0859
    ckfree((char *)argv);
0860
    Tcl_DecrRefCount(cmd);
0861
  }
0862
0863
  return ret;
0864
}
0865
0866
/* Prepare the handler before passing along any commands */
0867
0868
int WtPrepareSessionHandler(WtSession *s, Tcl_Obj *method,
0869
    Tcl_Interp *interp)
0870
{
0871
  int ok = 1;
0872
  const char *methodStr = WtToString(method);
0873
0874
  if (!Tcl_GetCharLength(s->handler)) {
0875
    Tcl_AppendResult(interp, "No session handler defined.", NULL);
0876
    ok = 0;
0877
  } else {
0878
    /* Load the handler */
0879
0880
    if (!s->handlerLoaded && strcmp(methodStr, "loadModule") &&
0881
        strcmp(methodStr, "unloadModule")) {
0882
      ok = WtLoadSessionHandler(s, interp);
0883
    }
0884
  }
0885
0886
  return ok;
0887
}
0888
0889
/* Session usage */
0890
0891
void WtSessionCmdUsage(Tcl_Interp *interp, Tcl_Obj *cmd)
0892
{
0893
  char *cmdStr = WtToString(cmd);
0894
0895
  Tcl_AppendResult(interp,
0896
    wtBadUsagePrefix2,
0897
    cmdStr, " id\n",
0898
    cmdStr, " count\n",
0899
    cmdStr, " has key\n",
0900
    cmdStr, " get key ?defaultValue?\n",
0901
    cmdStr, " set key value\n",
0902
    cmdStr, " setDefault key value\n",
0903
    cmdStr, " add key value\n",
0904
    cmdStr, " addList key list\n",
0905
    cmdStr, " keys\n",
0906
    cmdStr, " values\n",
0907
    cmdStr, " remove key\n",
0908
    cmdStr, " removeList keys\n",
0909
    cmdStr, " array arrayName\n",
0910
    cmdStr, " table\n",
0911
    cmdStr, " copy\n",
0912
    cmdStr, " clear\n",
0913
    cmdStr, " isModified\n",
0914
    cmdStr, " commit\n",
0915
    cmdStr, " clearCache\n",
0916
    cmdStr, " status ?id?\n",
0917
    cmdStr, " delete ?id?\n",
0918
    cmdStr, " clientId\n",
0919
    cmdStr, " newId\n",
0920
    cmdStr, " cookie ?cookie?\n",
0921
    cmdStr, " cookieName ?name?\n",
0922
    cmdStr, " cookieSendMode ?mode?\n",
0923
    cmdStr, " maxIdleTime ?time?\n",
0924
    cmdStr, " sweepFrequency ?frequency?\n",
0925
    cmdStr, " handler ?handler?\n",
0926
    cmdStr, " handlerType ?type?\n",
0927
    NULL);
0928
}