in src/generic/url.c [480:817]
int Web_CmdUrl(ClientData clientData,
Tcl_Interp * interp, int objc, Tcl_Obj * CONST objv[])
{
static TCLCONST char *params[] = { "-urlformat",
"-notimestamp", NULL
};
enum params
{ URLFORMAT,
NOTIMESTAMP
};
int Nparams[] = { 1, 0 };
int iCurArg = 0;
UrlData *urlData = NULL;
Tcl_Obj *plist = NULL;
Tcl_Obj *cmd = NULL;
Tcl_Obj *qStrList = NULL;
int plistLen = 0;
int i = 0;
int flag = 0;
int bool = 1;
int urlformat = 0;
Tcl_Obj *urlFmt = NULL;
Tcl_Obj *res = NULL;
/* --------------------------------------------------------------------------
* internal data ?
* ----------------------------------------------------------------------- */
WebAssertData(interp, clientData, "Web_CmdUrl", TCL_ERROR)
urlData = (UrlData *) clientData;
/* make sure we have request data */
if (requestFillRequestValues(interp, urlData->requestData) == TCL_ERROR)
return TCL_ERROR;
/* --------------------------------------------------------------------------
* first arg is cmd
* ----------------------------------------------------------------------- */
iCurArg = argIndexOfFirstArg(objc, objv, params, Nparams);
if ((objc - iCurArg) < 1) {
Tcl_WrongNumArgs(interp, 1, objv, "cmdName");
return TCL_ERROR;
}
if (Tcl_GetCharLength(objv[iCurArg]) > 0) {
cmd = objv[iCurArg];
}
iCurArg++;
/* --------------------------------------------------------------------------
* any params we don't accept ?
* ----------------------------------------------------------------------- */
WebAssertArgs(interp, objc, objv, params, i, -1);
/* --------------------------------------------------------------------------
* check for flags
* ----------------------------------------------------------------------- */
urlformat = urlData->urlformat;
if ((urlFmt = argValueOfKey(objc, objv, (char *)params[URLFORMAT])) != NULL) {
urlformat = parseUrlFormat(interp, urlFmt);
if (urlformat == 0)
return TCL_ERROR;
}
if (argIndexOfKey(objc, objv, (char *)params[NOTIMESTAMP]) > 0)
flag = (flag | WEB_URL_NOTIMESTAMP);
Tcl_GetBooleanFromObj(interp, urlData->requestData->cmdUrlTimestamp, &bool);
if (bool == 0)
flag = (flag | WEB_URL_NOTIMESTAMP);
/* --------------------------------------------------------------------------
* do we need to create a querystring ?
* ----------------------------------------------------------------------- */
if ((urlformat & WEB_URL_WITH_QUERYSTRING) != 0) {
if (urlData->querystring != NULL) {
/* take the one which was configured in web::cmdurlcfg */
qStrList = Tcl_DuplicateObj(urlData->querystring);
Tcl_IncrRefCount(qStrList);
}
else {
/* create a new one */
/* ---------------------------------------------------------------------
* create query_string
* ------------------------------------------------------------------ */
switch (objc - iCurArg) {
case 0:
/* ...................................................................
* web::cmdurl [options] cmd
* ................................................................ */
qStrList = createQueryList(interp, cmd, NULL, urlData, flag);
break;
case 1:
/* ...................................................................
* web::cmdurl [options] cmd list
* ................................................................ */
if ((plistLen =
tclGetListLength(interp, objv[iCurArg])) == -1)
return TCL_ERROR;
if ((plistLen % 2) != 0) {
LOG_MSG(interp, WRITE_LOG | SET_RESULT, __FILE__,
__LINE__, "web::cmdurl", WEBLOG_INFO,
"key-value list \"", Tcl_GetString(objv[iCurArg]),
"\" must be even-numbered", NULL);
return TCL_ERROR;
}
qStrList =
createQueryList(interp, cmd, objv[iCurArg], urlData,
flag);
break;
default:
/* ................................................................
* web::cmdurl [options] "" k1 v1 ... kn vn
* ................................................................ */
if (((objc - iCurArg) % 2) != 0) {
LOG_MSG(interp, WRITE_LOG | SET_RESULT, __FILE__,
__LINE__, "web::cmdurl", WEBLOG_INFO,
"key without the matching value (uneven list), starting at \"",
Tcl_GetString(objv[iCurArg]), "\"", NULL);
return TCL_ERROR;
}
plist = Tcl_NewObj();
if (plist == NULL)
return TCL_ERROR;
Tcl_IncrRefCount(plist);
for (i = iCurArg; i < objc; i += 2) {
if (Tcl_ListObjAppendElement(interp, plist, objv[i]) ==
TCL_ERROR) {
Tcl_DecrRefCount(plist);
return TCL_ERROR;
}
if (Tcl_ListObjAppendElement(interp, plist, objv[i + 1])
== TCL_ERROR) {
Tcl_DecrRefCount(plist);
return TCL_ERROR;
}
}
qStrList = createQueryList(interp, cmd, plist, urlData, flag);
Tcl_DecrRefCount(plist);
}
/* ------------------------------------------------------------------
* crypt
* ------------------------------------------------------------------ */
if (doencrypt(interp, qStrList, 1) != TCL_OK) {
LOG_MSG(interp, WRITE_LOG, __FILE__, __LINE__,
"web::cmdurl", WEBLOG_ERROR,
"error encrypting \"", Tcl_GetString(qStrList), "\"",
NULL);
if (qStrList != NULL)
Tcl_DecrRefCount(qStrList);
return TCL_ERROR;
} else {
if (qStrList != NULL)
Tcl_DecrRefCount(qStrList);
qStrList = Tcl_DuplicateObj(Tcl_GetObjResult(interp));
Tcl_IncrRefCount(qStrList);
Tcl_ResetResult(interp);
}
}
}
/* ==========================================================================
* url (stuff before query_string)
* ======================================================================= */
res = Tcl_NewObj();
Tcl_IncrRefCount(res);
if ((urlformat & WEB_URL_WITH_SCHEME) != 0) {
if (urlData->defaultscheme != NULL) {
Tcl_AppendObjToObj(res, urlData->defaultscheme);
Tcl_AppendToObj(res, WEBURL_SCHEME_SEP, -1);
} else {
Tcl_Obj *schemeObj = NULL;
char *scheme = NULL;
if( urlData->requestData != NULL ) {
schemeObj = paramListGetObjectByString(interp, urlData->requestData->request, "HTTPS");
if (schemeObj != NULL) {
Tcl_IncrRefCount(schemeObj);
scheme = Tcl_GetString(schemeObj);
}
}
/* scheme detection: HTTPS variable can be upper case too
(e.g. on Sunone) */
if (scheme != NULL && !STRCASECMP(scheme, "on")) {
Tcl_AppendToObj(res, WEB_SECURE_SCHEME, -1);
Tcl_AppendToObj(res, WEBURL_SCHEME_SEP, -1);
} else {
Tcl_AppendToObj(res,WEB_DEFAULT_SCHEME, -1);
Tcl_AppendToObj(res, WEBURL_SCHEME_SEP, -1);
}
if (schemeObj != NULL)
Tcl_DecrRefCount(schemeObj);
}
}
if ((urlformat & WEB_URL_WITH_HOST) != 0) {
Tcl_Obj *host = NULL;
/* try to get requested host */
WEB_URL_GETFROMREQDATA(host, "HTTP_HOST", 0);
if (host == NULL) {
/* fall back use server name */
WEB_URL_GETFROMREQDATA(host, "SERVER_NAME", 0);
}
if (host != NULL) {
char *hostname = Tcl_GetString(host);
char *colon = hostname;
size_t pos = 0;
size_t len = strlen(hostname);
Tcl_IncrRefCount(host);
for (; pos < len; pos++) {
if (*colon++ == ':') {
break;
}
}
Tcl_AppendToObj(res, WEBURL_HOST_SEP, -1);
if (pos < len) {
/* only insert up to colon */
Tcl_AppendToObj(res, hostname, pos);
} else {
Tcl_AppendObjToObj(res, host);
/* reset colon */
}
Tcl_DecrRefCount(host);
}
}
if ((urlformat & WEB_URL_WITH_PORT) != 0) {
Tcl_Obj *port = NULL;
/* To get the Port, try the following:
1. Take port explicitly configured in Websh if available
2. Take port from HTTP_HOST or SERVER_NAME if available
3. Take port from SERVER_PORT if available
4. Take default port (fallback)
*/
if (urlData->port != NULL) {
port = urlData->port;
Tcl_IncrRefCount(port);
}
if (port == NULL) {
/* nothign found yet */
/* try to get requested host */
Tcl_Obj *host = NULL;
WEB_URL_GETFROMREQDATA(host, "HTTP_HOST", 1);
if (host == NULL) {
/* fall back use server name */
WEB_URL_GETFROMREQDATA(host, "SERVER_NAME", 1);
}
if (host != NULL) {
char *hostname = Tcl_GetString(host);
char *colon = hostname;
size_t pos = 0;
size_t len = strlen(hostname);
Tcl_IncrRefCount(host);
for (; pos < len; pos++) {
if (*colon++ == ':') {
break;
}
}
if (pos < len) {
/* colon points to port */
port = Tcl_NewStringObj(colon, -1);
Tcl_IncrRefCount(port);
}
Tcl_DecrRefCount(host);
}
}
if (port == NULL) {
/* still nothing found */
WEB_URL_GETFROMREQDATA(port, "SERVER_PORT", 0);
if (port != NULL) {
Tcl_IncrRefCount(port);
}
}
Tcl_AppendToObj(res, WEBURL_PORT_SEP, -1);
if (port != NULL) {
/* found one */
Tcl_AppendObjToObj(res, port);
Tcl_DecrRefCount(port);
} else {
/* output the default port */
Tcl_AppendToObj(res, WEB_DEFAULT_PORT, -1);
}
}
if ((urlformat & WEB_URL_WITH_SCRIPTNAME) != 0) {
Tcl_Obj *scriptname = NULL;
WEB_URL_GETFROMREQDATA(scriptname, "SCRIPT_NAME", 0);
if (scriptname != NULL) {
Tcl_IncrRefCount(scriptname);
Tcl_AppendObjToObj(res, scriptname);
Tcl_DecrRefCount(scriptname);
}
}
if ((urlformat & WEB_URL_WITH_PATHINFO) != 0) {
Tcl_Obj *pathinfo = NULL;
WEB_URL_GETFROMREQDATA(pathinfo, "PATH_INFO", 0);
if (pathinfo != NULL) {
Tcl_IncrRefCount(pathinfo);
Tcl_AppendObjToObj(res, pathinfo);
Tcl_DecrRefCount(pathinfo);
}
}
if ((urlformat & WEB_URL_WITH_QUERYSTRING) != 0) {
if (qStrList != NULL) {
Tcl_AppendToObj(res, WEBURL_QUERY_STRING_SEP, -1);
Tcl_AppendObjToObj(res, qStrList);
}
}
if (qStrList != NULL) {
Tcl_DecrRefCount(qStrList);
}
Tcl_SetObjResult(interp, res);
Tcl_DecrRefCount(res);
return TCL_OK;
}