in src/generic/dispatch.c [28:408]
int parsePostData(Tcl_Interp * interp, Tcl_Obj * name,
Tcl_Obj * type, Tcl_Obj * len, RequestData * requestData);
/* ----------------------------------------------------------------------------
* Web_Dispatch
* ------------------------------------------------------------------------- */
int Web_Dispatch(ClientData clientData,
Tcl_Interp * interp, int objc, Tcl_Obj * CONST objv[])
{
RequestData *requestData = NULL;
TCLCONST char *params[] = { "-track",
"-querystring",
"-postdata",
"-cmd",
"-hook",
NULL
};
enum params
{ TRACK,
QUERYSTRING,
POSTDATA,
CMD,
HOOK
};
int idx = 0;
Tcl_Obj *post_data;
Tcl_Obj *query_string;
/* --------------------------------------------------------------------------
* check for private data
* ----------------------------------------------------------------------- */
WebAssertData(interp, clientData, "Web_Dispatch", TCL_ERROR)
requestData = (RequestData *) clientData;
/* --------------------------------------------------------------------------
* check for not-accepted options
* ----------------------------------------------------------------------- */
WebAssertArgs(interp, objc, objv, params, idx, -1);
/* make sure we have values */
if (requestFillRequestValues(interp, requestData) == TCL_ERROR)
return TCL_ERROR;
/* ==========================================================================
* query_string
* ======================================================================= */
query_string = argValueOfKey(objc, objv, (char *)params[QUERYSTRING]);
if (query_string == NULL) {
/* ------------------------------------------------------------------------
* not on command line. try to get from response object
* --------------------------------------------------------------------- */
query_string =
paramListGetObjectByString(interp, requestData->request,
"QUERY_STRING");
}
/* --------------------------------------------------------------------------
* did we find any query_string ?
* ----------------------------------------------------------------------- */
if (query_string != NULL) {
Tcl_IncrRefCount(query_string);
/* ------------------------------------------------------------------------
* empty string means: skip
* --------------------------------------------------------------------- */
if (Tcl_GetCharLength(query_string) > 0) {
if (parseQueryString(requestData, interp, query_string) ==
TCL_ERROR) {
Tcl_DecrRefCount(query_string);
return TCL_ERROR;
}
}
Tcl_DecrRefCount(query_string);
}
/* ==========================================================================
* post_data
* ======================================================================= */
post_data = argValueOfKey(objc, objv, (char *)params[POSTDATA]);
if (post_data != NULL) {
/* ------------------------------------------------------------------------
* on command line; empty string means: skip
* --------------------------------------------------------------------- */
if (Tcl_GetCharLength(post_data) > 0) {
/* ----------------------------------------------------------------------
* parse -postdata input
* ------------------------------------------------------------------- */
int idx1 = 0;
int idx2 = 0;
if ((idx1 = argIndexOfKey(objc, objv, (char *)params[POSTDATA])) > 0) {
idx2 = argIndexOfNextKey(objc, objv, idx1);
/* for( i = idx1; i < objc; i++) { */
/* fprintf(stdout,"DBG %d (%d) %s\n",i,(i == idx2),Tcl_GetString(objv[i])); fflush(stdout); */
/* } */
switch ((idx2 - idx1)) {
case 2:
/* ------------------------------------------------------------------
* -postdata channel
* --------------------------------------------------------------- */
if (parsePostData(interp, objv[idx1 + 1], NULL, NULL,
requestData) == TCL_ERROR) {
return TCL_ERROR;
}
break;
case 3:
/* ------------------------------------------------------------------
* -postdata channel length
* --------------------------------------------------------------- */
/* log is handled by parsePostData */
if (parsePostData(interp, objv[idx1 + 1], objv[idx1 + 2],
NULL, requestData) == TCL_ERROR) {
return TCL_ERROR;
}
break;
case 4:
/* ------------------------------------------------------------------
* -postdata channel length type
* --------------------------------------------------------------- */
/* log is handled by parsePostData */
if (parsePostData(interp, objv[idx1 + 1], objv[idx1 + 2],
objv[idx1 + 3], requestData) == TCL_ERROR) {
return TCL_ERROR;
}
break;
default:
Tcl_WrongNumArgs(interp, 1, objv,
"-postdata ?#?channel ?content_length? ?content_type?");
return TCL_ERROR;
break;
}
}
}
}
else {
/* ------------------------------------------------------------------------
* get postdata from default input
* --------------------------------------------------------------------- */
Tcl_Obj *content_type = NULL;
Tcl_Obj *content_length = NULL;
content_type =
paramListGetObjectByString(interp, requestData->request,
"CONTENT_TYPE");
content_length =
paramListGetObjectByString(interp, requestData->request,
"CONTENT_LENGTH");
if ((content_type != NULL) && (content_length != NULL)) {
Tcl_Obj *tmp = NULL;
Tcl_IncrRefCount(content_type);
Tcl_IncrRefCount(content_length);
tmp = requestGetDefaultChannelName(interp);
Tcl_IncrRefCount(tmp);
parsePostData(interp, tmp, content_length, content_type,
requestData);
Tcl_DecrRefCount(tmp);
}
WebDecrRefCountIfNotNull(content_type);
WebDecrRefCountIfNotNull(content_length);
}
/* ==========================================================================
* track
* ======================================================================= */
{
Tcl_Obj *trackList = NULL;
int listLen = -1;
int i = -1;
Tcl_Obj *key = NULL;
Tcl_Obj *val = NULL;
trackList = argValueOfKey(objc, objv, (char *)params[TRACK]);
if ((trackList != NULL) &&
(listLen = tclGetListLength(interp, trackList)) != -1) {
/* ----------------------------------------------------------------------
* loop over list and add these parameters to "static"
* ------------------------------------------------------------------- */
for (i = 0; i < listLen; i++) {
key = NULL;
val = NULL;
Tcl_ListObjIndex(interp, trackList, i, &key);
/* Tcl_ListObjIndex: The reference count for the list element
* is not incremented; the caller must do that if it needs to
* retain a pointer to the element. */
if (key != NULL) {
/* ------------------------------------------------------------------
* get value from params
* --------------------------------------------------------------- */
val = (Tcl_Obj *) getFromHashTable(requestData->paramList,
Tcl_GetString(key));
if (val != NULL) {
/* this obj now belongs to two lists */
val = Tcl_DuplicateObj(val);
if (paramListSetAsWhole(requestData->staticList,
Tcl_GetString(key),
val) == TCL_ERROR) {
LOG_MSG(interp, WRITE_LOG, __FILE__, __LINE__,
"web::dispatch -track", WEBLOG_INFO,
"error adding \"", Tcl_GetString(key),
", ", Tcl_GetString(val),
"\" to static params", NULL);
}
}
}
}
}
}
/* ==========================================================================
* dispatch
* ======================================================================= */
{
Tcl_Obj *cmdName = NULL;
Tcl_Obj *cmdCode = NULL;
char *cmdNameStr = NULL;
int res;
/* ------------------------------------------------------------------------
* reset interp result
* --------------------------------------------------------------------- */
Tcl_ResetResult(interp);
cmdName = argValueOfKey(objc, objv, (char *)params[CMD]);
if (cmdName != NULL) {
/* ----------------------------------------------------------------------
* call command (from command-line); empty string means: no dispatch
* ------------------------------------------------------------------- */
if (Tcl_GetCharLength(cmdName) < 1)
return TCL_OK;
}
else {
/* ----------------------------------------------------------------------
* get command name from default source
* ------------------------------------------------------------------- */
cmdName = (Tcl_Obj *) getFromHashTable(requestData->paramList,
Tcl_GetString(requestData->
cmdTag));
}
/* ------------------------------------------------------------------------
* cmd: "",NULL --> default
* --------------------------------------------------------------------- */
if (cmdName == NULL) {
cmdName = Tcl_NewStringObj(WEB_REQ_DEFAULT, -1);
}
else if (Tcl_GetCharLength(cmdName) == 0) {
cmdName = Tcl_NewStringObj(WEB_REQ_DEFAULT, -1);
}
else {
cmdName = Tcl_DuplicateObj(cmdName);
}
cmdNameStr = Tcl_GetString(cmdName);
LOG_MSG(interp, WRITE_LOG,
__FILE__, __LINE__,
"web::dispatch", WEBLOG_INFO,
"Handling command \"", cmdNameStr, "\"", NULL);
/* ------------------------------------------------------------------------
* get command code
* --------------------------------------------------------------------- */
cmdCode =
(Tcl_Obj *) getFromHashTable(requestData->cmdList, cmdNameStr);
/* ------------------------------------------------------------------------
* command found ?
* --------------------------------------------------------------------- */
if (cmdCode == NULL) {
LOG_MSG(interp, WRITE_LOG,
__FILE__, __LINE__,
"web::dispatch", WEBLOG_INFO,
"command \"", cmdNameStr, "\" not found.",
" Switching to command \"default\"", NULL);
cmdNameStr = WEB_REQ_DEFAULT;
cmdCode =
(Tcl_Obj *) getFromHashTable(requestData->cmdList,
cmdNameStr);
}
/* ------------------------------------------------------------------------
* eval command, if any
* --------------------------------------------------------------------- */
if (cmdCode == NULL) {
LOG_MSG(interp, WRITE_LOG | SET_RESULT, __FILE__, __LINE__,
"web::dispatch", WEBLOG_ERROR,
"command \"", cmdNameStr, "\" not found", NULL);
WebDecrRefCountIfNotNull(cmdName);
return TCL_ERROR;
}
else {
Tcl_Obj *hook = NULL;
/* first eval hook, if any */
hook = argValueOfKey(objc, objv, (char *)params[HOOK]);
if (hook != NULL) {
Tcl_IncrRefCount(hook);
res = Tcl_EvalObjEx(interp, hook, TCL_EVAL_DIRECT);
Tcl_DecrRefCount(hook);
if (res == TCL_ERROR) {
LOG_MSG(interp, WRITE_LOG | INTERP_ERRORINFO,
__FILE__, __LINE__,
"web::dispatch", WEBLOG_ERROR,
"error evaluating hook \"", Tcl_GetString(hook),
"\"", NULL);
WebDecrRefCountIfNotNull(cmdName);
return TCL_ERROR;
}
}
/* reuse var hook */
Tcl_ListObjIndex(interp, cmdCode, 0, &hook);
Tcl_IncrRefCount(hook);
res = Tcl_EvalObjEx(interp, hook, TCL_EVAL_DIRECT);
Tcl_DecrRefCount(hook);
if (res == TCL_ERROR) {
LOG_MSG(interp, WRITE_LOG | SET_RESULT | INTERP_ERRORINFO,
__FILE__, __LINE__,
"web::dispatch", WEBLOG_ERROR,
"error evaluating command \"", cmdNameStr,
"\"", NULL);
WebDecrRefCountIfNotNull(cmdName);
return TCL_ERROR;
}
}
WebDecrRefCountIfNotNull(cmdName);
}
return TCL_OK;
}