/** * _getOptionArgs * * Returns the address of an OPTIONS struct with all supported options decoded. * Two types of optional parameters are supported, that is, 'queryOptions' and * 'options'. * * query-options :== 'queryOptions' '=' '{' (object (',' object)*))? '}' * options :== 'options' '=' '[' (string (',' string)*)? ']' * object :== '{' (property (',' property)*)? '}' * property :== string ':' value * array :== '[' (value (',' value)*)? ']' * value :== string | number | object | array | 'true' | 'false' * string :== '"' char* '"' * * Example: * * queryOptions={"deep":true, "ignoreCase":false} * options=["dirsOnly", "showHiddenFiles"] * * @note: Strict JSON encoding rules are enforced when decoding parameters. * * @param pGET Address of a variable data type. (php style $_GET variable) * @param piResult Address integer receiving the final result code: * HTTP_V_OK, HTTP_V_BAD_REQUEST or HTTP_V_SERVER_ERROR * * @return On success the address of an OPTIONS struct otherwise NULL **/ static OPTIONS * _getOptionArgs( DATA *pGET, int *piResult ) { OPTIONS *pOptions; DATA *ptQueryOptions, *ptOptions; if( (pOptions = (OPTIONS *)calloc(1, sizeof(OPTIONS))) ) { if( hasProperty( "options", pGET ) ) { if( (ptOptions = jsonDecode( varGetProperty("options", pGET))) ) { pOptions->bShowHiddenFiles = varInArray("showHiddenFiles", ptOptions); pOptions->bDebug = varInArray("debug", ptOptions); destroy( ptOptions ); } else // Ill formatted JSON array { cbtDebug( "options parameter is not a valid JSON object." ); *piResult = HTTP_V_BAD_REQUEST; destroy( pOptions ); return NULL; } } if( hasProperty( "queryOptions", pGET ) ) { if( (ptQueryOptions = jsonDecode( varGetProperty("queryOptions", pGET))) ) { pOptions->bIgnoreCase = (bool)varGet( varGetProperty("ignoreCase", ptQueryOptions) ); pOptions->bDeep = (bool)varGet( varGetProperty("deep", ptQueryOptions) ); destroy( ptQueryOptions ); } else // Ill formatted JSON object { cbtDebug( "queryOptions parameter is not a valid JSON object." ); *piResult = HTTP_V_BAD_REQUEST; destroy( pOptions ); return NULL; } } *piResult = HTTP_V_OK; // Success } else // Out of memory... { *piResult = HTTP_V_SERVER_ERROR; } return pOptions; }
bool Debugger::Cmd_Var(int argc, const char **argv) { switch (argc) { case 2: varGet(atoi(argv[1])); break; case 3: varSet(atoi(argv[1]), atoi(argv[2])); break; default: DebugPrintf("Usage: %s number value\n", argv[0]); break; } return true; }
/** * cgiInit * * Load the available CGI variables and create the PHP style _SERVER and _GET * dynamic variables. Both variables are created as associative arrays. **/ int cgiInit() { METHOD *pMethod; DATA *ptContent, *ptQuery, *ptArgs, *ptSERVER, *ptCBTREE, *ptGET, *ptPOST; char cProperty[MAX_BUF_SIZE], cValue[MAX_BUF_SIZE], cArgm[MAX_BUF_SIZE], *pcAllowed, *pcSrc, *pcArgm; int iArgCount, iSep, i; phResp = stdout; cgiEnvironment = newArray(NULL); // Setup a PHP style '$_SERVER' variable. if( (ptSERVER = newArray( "_SERVER" )) ) { for( i=0; cgiVarNames[i]; i++) { varNewProperty( cgiVarNames[i], getenv(cgiVarNames[i]), ptSERVER ); } varPush( cgiEnvironment, ptSERVER ); } /** * Setup a PHP style '$_CBTREE' variable. * * NOTE: On Apache HTTP servers any non CGI variables must be passed explicitly * using the 'SetEnv' or 'PassEnv' directive. For example in httpd.conf * add: * * PassEnv CBTREE_METHODS **/ if( (ptCBTREE = newArray( "_CBTREE" )) ) { for( i=0; cgiCbtreeNames[i]; i++) { varNewProperty( cgiCbtreeNames[i], getenv(cgiCbtreeNames[i]), ptCBTREE ); } varPush( cgiEnvironment, ptCBTREE ); } #ifdef _DEBUG varSet( cgiGetProperty("QUERY_STRING"), cDbgQS ); #endif switch( cgiGetMethodId() ) { case HTTP_V_DELETE: case HTTP_V_GET: if( (ptGET = newArray( "_GET" )) ) { if( (ptQuery = cgiGetProperty("QUERY_STRING")) ) { // Get the list of HTTP query arguments as a new array. ptArgs = varSplit( ptQuery, "&", false ); ptGET = newArray( "_GET" ); if( (iArgCount = varCount( ptArgs )) ) { for( i=0; i < iArgCount; i++ ) { if( (pcArgm = varGet(varGetByIndex( i, ptArgs ))) ) { // Decode special characters and treat each argument as a new property. pcSrc = decodeURI( pcArgm, cArgm, sizeof(cArgm)-1 ); iSep = strcspn( pcSrc, "=" ); strncpyz( cProperty, pcSrc, iSep ); pcSrc += pcSrc[iSep] ? iSep + 1: iSep; strcpy( cValue, pcSrc ); varNewProperty( cProperty, cValue, ptGET ); } } } destroy( ptArgs ); } varPush( cgiEnvironment, ptGET ); } break; case HTTP_V_POST: if( (ptPOST = newArray( "_POST" )) ) { // Read the content from stdin if( fgets(cArgm, sizeof(cArgm)-1, stdin) ) { ptContent = newString( "CONTENT", cArgm ); ptArgs = varSplit( ptContent, "&", false ); if( (iArgCount = varCount( ptArgs )) ) { for( i=0; i < iArgCount; i++ ) { if( (pcArgm = varGet(varGetByIndex( i, ptArgs ))) ) { // Decode special characters and treat each argument as a new property. pcSrc = decodeURI( pcArgm, cArgm, sizeof(cArgm)-1 ); iSep = strcspn( pcSrc, "=" ); strncpyz( cProperty, pcSrc, iSep ); pcSrc += pcSrc[iSep] ? iSep + 1: iSep; strcpy( cValue, pcSrc ); varNewProperty( cProperty, cValue, ptPOST ); } } } destroy( ptArgs ); } varPush( cgiEnvironment, ptPOST ); } break; } // Define which HTTP methods are allowed. if( ptCBTREE ) { pcAllowed = varGet(varGetProperty("CBTREE_METHODS", ptCBTREE)); snprintf( cProperty, sizeof(cProperty)-1,"GET,%s", (pcAllowed ? pcAllowed : "") ); pcArgm = strtok( cProperty, ", " ); while( pcArgm ) { strtrim( pcArgm, TRIM_M_WSP ); if( *pcArgm ) { if( (pMethod = _cgiGetMethodByName( pcArgm )) ) { pMethod->bAllowed = true; } } pcArgm = strtok( NULL, ", " ); } } return 1; }
/** * getArguments * * Returns the address of an ARGS struct with all HTTP query string parameters * extracted and decoded. The query string parameters (args) supported are: * * query-string ::= (qs-param ('&' qs-param)*)? * qs-param ::= authToken | basePath | path | query | queryOptions | options | * start | count |sort * authToken ::= 'authToken' '=' json-object * basePath ::= 'basePath' '=' path-rfc3986 * path ::= 'path' '=' path-rfc3986 * query ::= 'query' '=' object * query-options ::= 'queryOptions' '=' object * options ::= 'options' '=' array * start ::= 'start' '=' number * count ::= 'count' '=' number * sort ::= 'sort' '=' array * * @note: All of the above parameters are optional. * * @param piResult Address integer receiving the final result code: * HTTP_V_OK, HTTP_V_BAD_REQUEST or HTTP_V_SERVER_ERROR * * @return On success the address of an ARGS struct otherwise NULL **/ ARGS *getArguments( int *piResult ) { ARGS *pArgs; DATA *pCBTREE = NULL; DATA *ptARGS = NULL, *ptArg; int iResult = HTTP_V_OK; // Assume success if( (pArgs = (ARGS *)calloc(1, sizeof(ARGS))) ) { pCBTREE = cgiGetProperty("_CBTREE"); // Get CBTREE environment variables. switch( cgiGetMethodId() ) { case HTTP_V_DELETE: if( (ptARGS = cgiGetProperty( "_GET" )) ) { if( !hasProperty("path", ptARGS) ) { iResult = HTTP_V_BAD_REQUEST; } } pArgs->pOptions = _getOptionArgs( NULL, &iResult ); break; case HTTP_V_GET: if( (ptARGS = cgiGetProperty( "_GET" )) ) { // Parse the general options, if any.. if( !(pArgs->pOptions = _getOptionArgs( ptARGS, &iResult )) ) { destroyArguments( &pArgs ); return NULL; } } else // No QUERY-STRING { // We need at least an empty options struct. pArgs->pOptions = _getOptionArgs( NULL, &iResult ); } break; case HTTP_V_POST: if( (ptARGS = cgiGetProperty( "_POST" )) ) { if( hasProperty("newValue", ptARGS) && hasProperty("path", ptARGS) ) { ptArg = varGetProperty("newValue", ptARGS); if( isString(ptArg) ) { pArgs->pcNewValue = varGet( ptArg ); } else { iResult = HTTP_V_BAD_REQUEST; } } else // Missing parameter { iResult = HTTP_V_BAD_REQUEST; } } else // _POST is missing { iResult = HTTP_V_BAD_REQUEST; } pArgs->pOptions = _getOptionArgs( NULL, &iResult ); break; } if( iResult == HTTP_V_OK ) { // Get and validate the basePath if any. pArgs->pcBasePath = varGet(varGetProperty("CBTREE_BASEPATH", pCBTREE)); if( !pArgs->pcBasePath ) { if((ptArg = varGetProperty("basePath", ptARGS)) ) { if( isString(ptArg) ) { pArgs->pcBasePath = varGet( ptArg ); } else { iResult = HTTP_V_BAD_REQUEST; } } } // Validate the path if any. if( (ptArg = varGetProperty("path", ptARGS)) ) { if( isString(ptArg) ) { pArgs->pcPath = varGet( ptArg ); } else { iResult = HTTP_V_BAD_REQUEST; } } if( hasProperty( "authToken", ptARGS ) ) { if( (ptArg = jsonDecode(varGetProperty("authToken", ptARGS))) && isObject(ptArg) ) { pArgs->pAuthToken = ptArg; } else { cbtDebug( "authToken parameter is not a valid JSON object" ); iResult = HTTP_V_BAD_REQUEST; } } } if( iResult != HTTP_V_OK ) { destroyArguments( &pArgs ); *piResult = iResult; return NULL; } *piResult = HTTP_V_OK; } else // Out of memory { *piResult = HTTP_V_SERVER_ERROR; } return pArgs; }