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

Lines Size Modified Created Owner MIME Types
491 10,063 2010/05/08 18:46:41 2011/06/13 15:35:16 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 "WtUtil.h"
0018
#include "WtTable.h"
0019
0020
const char *wtBadUsagePrefix = "Usage: ";
0021
const char *wtBadUsagePrefix2 = "Usage:\n\n";
0022
0023
char *WtToString(Tcl_Obj *obj)
0024
{
0025
  return Tcl_GetString(obj);
0026
}
0027
0028
Tcl_Obj *WtNewString(const char *val)
0029
{
0030
  return Tcl_NewStringObj(val ? val : NULL, val ? -1 : 0);
0031
}
0032
0033
Tcl_Obj *WtNewBool(int val)
0034
{
0035
  return Tcl_NewBooleanObj(val);
0036
}
0037
0038
/* Update a WtTable from an apache table */
0039
0040
int WtUpdateTableFromAp(Tcl_Obj *tbl, table *apTable,
0041
    Tcl_Interp *interp)
0042
{
0043
  return WtUpdateTableObjFromAp(tbl, apTable, interp, 1);
0044
}
0045
0046
int WtUpdateTableFromApNoMulti(Tcl_Obj *tbl, table *apTable,
0047
    Tcl_Interp *interp)
0048
{
0049
  return WtUpdateTableObjFromAp(tbl, apTable, interp, 0);
0050
}
0051
0052
int WtUpdateTableObjFromAp(Tcl_Obj *tbl, table *apTable,
0053
    Tcl_Interp *interp, int doMulti)
0054
{
0055
  int ok = 1, i;
0056
  array_header *arr;
0057
  table_entry *elts;
0058
  char *key, *val;
0059
  Tcl_Obj *keyObj, *valObj;
0060
0061
  arr = ap_table_elts(apTable);
0062
  elts = (table_entry *)arr->elts;
0063
0064
  for (i = 0; i < arr->nelts; i++) {
0065
    key = elts[i].key ? elts[i].key : "";
0066
    val = elts[i].val ? elts[i].val : "";
0067
0068
    keyObj = Tcl_NewStringObj(key, -1);
0069
    Tcl_IncrRefCount(keyObj);
0070
0071
    valObj = Tcl_NewStringObj(val, -1);
0072
    Tcl_IncrRefCount(valObj);
0073
0074
    if (doMulti) {
0075
      ok = WtTableAppendToList(tbl, keyObj, valObj, NULL, interp);
0076
    } else {
0077
      WtTableSet(tbl, keyObj, valObj);
0078
    }
0079
0080
    Tcl_DecrRefCount(keyObj);
0081
    Tcl_DecrRefCount(valObj);
0082
0083
    if (!ok) {
0084
      break;
0085
    }
0086
  }
0087
0088
  return ok;
0089
}
0090
0091
/* Update an apache table from a WtTable */
0092
0093
int WtUpdateApFromLVTable(table *apTable, Tcl_Obj *tbl,
0094
    Tcl_Interp *interp)
0095
{
0096
  Tcl_HashTable *hashTable;
0097
  Tcl_HashEntry *ent;
0098
  Tcl_HashSearch search;
0099
  Tcl_Obj *list, *obj;
0100
  char *key;
0101
  int ok = 1, i, len;
0102
0103
  hashTable = WtGetTableMap(tbl);
0104
0105
  ent = Tcl_FirstHashEntry(hashTable, &search);
0106
0107
  while (ent && ok) {
0108
    list = (Tcl_Obj *)Tcl_GetHashValue(ent);
0109
    if (list) {
0110
      if (Tcl_ListObjLength(interp, list, &len) != TCL_OK) {
0111
        ok = 0;
0112
        break;
0113
      }
0114
0115
      key = WtToString((Tcl_Obj *)Tcl_GetHashKey(hashTable, ent));
0116
      ap_table_unset(apTable, key);
0117
0118
      for (i = 0; i < len; i++) {
0119
        if (Tcl_ListObjIndex(interp, list, 0, &obj) != TCL_OK) {
0120
          ok = 0;
0121
          break;
0122
        } else {
0123
          ap_table_add(apTable, key, WtToString(obj));
0124
        }
0125
      }
0126
    }
0127
    ent = Tcl_NextHashEntry(&search);
0128
  }
0129
0130
  return ok;
0131
}
0132
0133
int WtLog(const char *file, int line, int mask, WtContext *w,
0134
    const char *fmt, ...)
0135
{
0136
  va_list args;
0137
  int ok = 0;
0138
  char buf[MAX_STRING_LEN];
0139
0140
  va_start(args, fmt);
0141
  if (ap_vsnprintf(buf, sizeof(buf), fmt, args)) {
0142
    ok = WtLogInternal(file, line, mask, w, buf, 1);
0143
  }
0144
  va_end(args);
0145
0146
  return ok;
0147
}
0148
0149
int WtLogInternal(const char *file, int line, int mask, WtContext *w,
0150
    const char *str, int addNotice)
0151
{
0152
  int ok = 1;
0153
  char buf[MAX_STRING_LEN];
0154
0155
  memcpy(buf, str, MAX_STRING_LEN);
0156
  // XXX: Convert newlines to spaces
0157
0158
  if (w->apReq) {
0159
    ap_log_rerror(file, line, mask, w->apReq, "%s", buf);
0160
  } else {
0161
    ap_log_error(file, line, mask, w->apServer, "%s", buf);
0162
  }
0163
0164
  if ((mask & APLOG_LEVELMASK) <= APLOG_ERR) {
0165
    w->web->errorState = 1;
0166
  }
0167
0168
  if (addNotice && w->web && w->web->interp && w->web->notices &&
0169
      !WtAddNotice(w, buf, mask & APLOG_LEVELMASK, w->web->interp)) {
0170
    ok = 0;
0171
  }
0172
0173
  return ok;
0174
}
0175
0176
int WtAddNotice(WtContext *w, char *notice, int mask, Tcl_Interp *interp)
0177
{
0178
  int ok = 1, level = mask & APLOG_LEVELMASK;
0179
  Tcl_Obj *objv[2], *item;
0180
0181
  objv[0] = Tcl_NewIntObj(level);
0182
  objv[1] = WtNewString(notice);
0183
  item = Tcl_NewListObj(2, objv);
0184
  Tcl_IncrRefCount(item);
0185
0186
  WtCopyOnWrite(&w->web->notices);
0187
0188
  if (Tcl_ListObjAppendElement(interp, w->web->notices, item) != TCL_OK) {
0189
    if (interp) {
0190
      WtLogInternal(HERE, APLOG_ERR | APLOG_NOERRNO, w,
0191
        (interp ? Tcl_GetStringResult(interp) : "Failed to add notice."), 0);
0192
    }
0193
    ok = 0;
0194
  }
0195
0196
  Tcl_DecrRefCount(item);
0197
0198
  return ok;
0199
}
0200
0201
int WtCopyOnWrite(Tcl_Obj **objPtr)
0202
{
0203
  Tcl_Obj *t;
0204
0205
  if (*objPtr && Tcl_IsShared(*objPtr)) {
0206
    t = Tcl_DuplicateObj(*objPtr);
0207
    Tcl_IncrRefCount(t);
0208
    Tcl_DecrRefCount(*objPtr);
0209
    *objPtr = t;
0210
    return 1;
0211
  }
0212
  return 0;
0213
}
0214
0215
int WtEvalIncr(Tcl_Interp *interp, int objc, Tcl_Obj **objv, int flags)
0216
{
0217
  int i, rc;
0218
  for (i = 0; i < objc; i++) {
0219
    Tcl_IncrRefCount(objv[i]);
0220
  }
0221
  rc = Tcl_EvalObjv(interp, objc, objv, flags);
0222
  for (i = 0; i < objc; i++) {
0223
    Tcl_DecrRefCount(objv[i]);
0224
  }
0225
  return rc;
0226
}
0227
0228
Tcl_Obj *WtIncr(Tcl_Obj *obj)
0229
{
0230
  if (obj) {
0231
    Tcl_IncrRefCount(obj);
0232
  }
0233
  return obj;
0234
}
0235
0236
Tcl_Obj *WtDecr(Tcl_Obj *obj)
0237
{
0238
  if (obj) {
0239
    Tcl_DecrRefCount(obj);
0240
  }
0241
  return obj;
0242
}
0243
0244
Tcl_Obj **WtIncrList(Tcl_Obj **objv, int n)
0245
{
0246
  int i;
0247
  for (i = 0; i < n; i++) {
0248
    Tcl_IncrRefCount(objv[i]);
0249
  }
0250
  return objv;
0251
}
0252
0253
Tcl_Obj **WtDecrList(Tcl_Obj **objv, int n)
0254
{
0255
  int i;
0256
  for (i = 0; i < n; i++) {
0257
    Tcl_DecrRefCount(objv[i]);
0258
  }
0259
  return objv;
0260
}
0261
0262
Tcl_Obj *WtSetObj(Tcl_Obj **objPtr, Tcl_Obj *val)
0263
{
0264
  if (*objPtr) {
0265
    Tcl_DecrRefCount(*objPtr);
0266
  }
0267
  if (*objPtr = val) {
0268
    Tcl_IncrRefCount(*objPtr);
0269
  }
0270
  return *objPtr;
0271
}
0272
0273
int WtGetBoolResult(Tcl_Interp *interp, int *boolVal)
0274
{
0275
  int ok = 1;
0276
  Tcl_Obj *result = Tcl_GetObjResult(interp);
0277
0278
  if (!result) {
0279
    Tcl_AppendResult(interp, "Failed to get result.");
0280
    ok = 0;
0281
  } else {
0282
    Tcl_IncrRefCount(result);
0283
    Tcl_ResetResult(interp);
0284
    if (Tcl_GetBooleanFromObj(interp, result, boolVal) != TCL_OK) {
0285
      ok = 0;
0286
    }
0287
    Tcl_DecrRefCount(result);
0288
  }
0289
0290
  return ok;
0291
}
0292
0293
int WtCommandExists(Tcl_Interp *interp, const char *name)
0294
{
0295
  Tcl_CmdInfo info;
0296
  return Tcl_GetCommandInfo(interp, name, &info) != 0;
0297
}
0298
0299
char *WtSafeStr(const char *str)
0300
{
0301
  return str ? (char *)str : "";
0302
}
0303
0304
/* Get a typed value pass to a command */
0305
0306
Tcl_Obj *WtCmdGetVal(Tcl_Obj *val, Tcl_ObjType *type,
0307
    Tcl_Interp *interp)
0308
{
0309
  if (Tcl_ConvertToType(interp, val, type) == TCL_OK) {
0310
    return val;
0311
  }
0312
  return NULL;
0313
}
0314
0315
/* Get a variable passed to a command */
0316
0317
int WtCmdGetVar(Tcl_Obj *var, Tcl_Obj **val, Tcl_ObjType *type,
0318
    Tcl_Interp *interp)
0319
{
0320
  int ok = 0;
0321
  *val = Tcl_ObjGetVar2(interp, var, NULL, 0);
0322
  if (*val) {
0323
    if ((*val)->typePtr == type ||
0324
        Tcl_ConvertToType(interp, *val, type)) {
0325
      ok = 1;
0326
    }
0327
  }
0328
  return ok;
0329
}
0330
0331
/* Get and unshare a variable passed to a command */
0332
0333
int WtCmdOwnVar(Tcl_Obj *var, Tcl_Obj **val, Tcl_ObjType *type,
0334
    int *created, Tcl_Interp *interp)
0335
{
0336
  int ok = 1;
0337
  Tcl_Obj *obj;
0338
0339
  *val = NULL;
0340
  *created = 0;
0341
0342
  obj = Tcl_ObjGetVar2(interp, var, NULL, 0);
0343
0344
  if (obj) {
0345
    if (Tcl_IsShared(obj)) {
0346
      if (!(obj = Tcl_DuplicateObj(obj))) {
0347
        ok = 0;
0348
      } else {
0349
        Tcl_IncrRefCount(obj);
0350
        if (Tcl_ConvertToType(interp, obj, type) != TCL_OK) {
0351
          Tcl_DecrRefCount(obj);
0352
          ok = 0;
0353
        } else {
0354
          *val = obj;
0355
          *created = 1;
0356
        }
0357
      }
0358
    } else if (Tcl_ConvertToType(interp, obj, type) != TCL_OK) {
0359
      ok = 0;
0360
    } else {
0361
      *val = obj;
0362
    }
0363
  }
0364
0365
  return ok;
0366
}
0367
0368
/* Reset a var */
0369
0370
Tcl_Obj *WtCmdSetVar(Tcl_Obj *var, Tcl_Obj *val, Tcl_Interp *interp)
0371
{
0372
  Tcl_Obj *ret;
0373
  Tcl_IncrRefCount(val);
0374
  ret = Tcl_ObjSetVar2(interp, var, NULL, val, TCL_LEAVE_ERR_MSG);
0375
  Tcl_DecrRefCount(val);
0376
  return ret;
0377
}
0378
0379
void WtUpdateProtectedObjString(Tcl_Obj *obj)
0380
{
0381
  /* Empty string. Do not attempt to serialize. */
0382
  obj->bytes = Tcl_Alloc(1);
0383
  obj->bytes[0] = '\0';
0384
  obj->length = 1;
0385
}
0386
0387
int WtSetProtectedObjFromAny(Tcl_Interp *interp, Tcl_Obj *obj,
0388
    Tcl_ObjType *type)
0389
{
0390
  if (obj->typePtr != type) {
0391
    Tcl_AppendResult(interp, "Conversion to object is not permitted.");
0392
    return TCL_ERROR;
0393
  }
0394
  return TCL_OK;
0395
}
0396
0397
unsigned int WtHashString(const char *str, int len)
0398
{
0399
  int i;
0400
  unsigned int result = 0;
0401
  const char *p;
0402
0403
  if (len != -1) {
0404
    for (i = 0; i < len; i++) {
0405
      result += (result << 3) + str[i];
0406
    }
0407
  } else {
0408
    for (p = str; *p; p++) {
0409
      result += (result << 3) + *p;
0410
    }
0411
  }
0412
0413
  return result;
0414
}
0415
0416
/* Code bits for URL encoding taken from PHP source */
0417
0418
static const char *hexDigits = "0123456789ABCDEF";
0419
0420
char *WtEncodeUrl(const char *str, int stringLen, int *resultLen)
0421
{
0422
  const char *p, *end = str + stringLen;
0423
  char *q, *dest = ckalloc(stringLen * 3 + 1);
0424
  char c;
0425
0426
  q = dest;
0427
0428
  for (p = str; p < end; p++) {
0429
    c = *p;
0430
    if (c == ' ') {
0431
      *q++ = '+';
0432
    } else if ((c < '0' && c != '-' && c != '.') ||
0433
        (c < 'A' && c > '9') ||
0434
        (c > 'Z' && c < 'a' && c != '_') || (c > 'z')) {
0435
      *q = '%';
0436
      q[1] = hexDigits[c >> 4];
0437
      q[2] = hexDigits[c & 0x0f];
0438
      q += 3;
0439
    } else {
0440
      *q++ = c;
0441
    }
0442
  }
0443
0444
  *q = '\0';
0445
  if (resultLen) {
0446
    *resultLen = q - dest;
0447
  }
0448
0449
  return dest;
0450
}
0451
0452
int WtHexToChar(char *p)
0453
{
0454
  int val, c;
0455
0456
  c = ((unsigned char *)p)[0];
0457
  if (isupper(c)) {
0458
    c = tolower(c);
0459
  }
0460
  val = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16;
0461
  c = ((unsigned char *)p)[1];
0462
  if (isupper(c)) {
0463
    c = tolower(c);
0464
  }
0465
  val += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10;
0466
  return val;
0467
}
0468
0469
int WtDecodeUrlInPlace(char *str, int len)
0470
{
0471
  char *p = str;
0472
  char *q = str;
0473
0474
  while (len--) {
0475
    if (*p == '+') {
0476
      *q++ = ' ';
0477
      ++p;
0478
    } else if (*p == '%' && len >= 2 && isxdigit(p[1]) &&
0479
        isxdigit(p[2])) {
0480
      *q = (char)WtHexToChar(p + 1);
0481
      p += 3;
0482
      len -= 2;
0483
    } else {
0484
      *q++ = *p++;
0485
    }
0486
  }
0487
0488
  *q = '\0';
0489
0490
  return q - str;
0491
}