Example #1
0
/**
*	_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;
}
Example #2
0
/**
*	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;
}
Example #3
0
    Inst::Inst(
      RC::ConstHandle<IO::Dir> const &extensionDir,
      std::string const &extensionName,
      std::string const &jsonDesc,
      std::vector<std::string> const &pluginDirs,
      RC::Handle<CG::Manager> const &cgManager,
      EDK::Callbacks const &callbacks,
      std::map< std::string, void (*)( void * ) > &implNameToDestructorMap
      )
      : m_name( extensionName )
      , m_jsonDesc( jsonDesc )
    {
      try
      {
        JSON::Decoder jsonDecode( jsonDesc.data(), jsonDesc.length() );
        JSON::Entity jsonEntity;
        if ( !jsonDecode.getNext( jsonEntity ) )
          throw Exception( "missing JSON entity" );
        jsonEntity.requireObject();
        m_desc = parseDesc( jsonEntity );
        if ( jsonDecode.getNext( jsonEntity ) )
          throw Exception( "extra JSON entity" );
      }
      catch ( Exception e )
      {
        throw "JSON description: " + e;
      }
      
      /*
      m_fabricLIBObject = LIB::NakedObject::Create();
      m_fabricLIBObject->set( "hostTriple", LIB::ReferencedString::Create( Util::getHostTriple() ) );
      m_fabricLIBObject->set( "DependencyGraph", LIBDG::Namespace::Create( dgContext ) );
      */
      std::vector< std::string > libs;
      m_desc.libs.appendMatching( Util::getHostTriple(), libs );
      std::string libSuffix = "-" + std::string(buildOS) + "-" + std::string(buildArch);
      
      for ( size_t i=0; i<libs.size(); ++i )
      {
        std::string resolvedName;
        SOLibHandle soLibHandle = SOLibOpen( libs[i]+libSuffix, resolvedName, false, pluginDirs );
        m_resolvedNameToSOLibHandleMap.insert( ResolvedNameToSOLibHandleMap::value_type( resolvedName, soLibHandle ) );
        m_orderedSOLibHandles.push_back( soLibHandle );
      }

      if ( !m_orderedSOLibHandles.empty() )
      {
        void *resolvedFabricEDKInitFunction = 0;
        for ( size_t i=0; i<m_orderedSOLibHandles.size(); ++i )
        {
          resolvedFabricEDKInitFunction = SOLibResolve( m_orderedSOLibHandles[i], "FabricEDKInit" );
          if ( resolvedFabricEDKInitFunction )
            break;
        }
        if ( !resolvedFabricEDKInitFunction )
          throw Exception( "error: extension doesn't implement function FabricEDKInit through macro IMPLEMENT_FABRIC_EDK_ENTRIES" );

        ( *( FabricEDKInitPtr )resolvedFabricEDKInitFunction )( callbacks );
      }
      
      for ( size_t i=0; i<m_orderedSOLibHandles.size(); ++i )
      {
        /*
        OnLoadFn onLoadFn = (OnLoadFn)SOLibResolve( m_orderedSOLibHandles[i], "FabricOnLoad" );
        if ( onLoadFn )
          onLoadFn( SDK::Value::Bind( m_fabricLIBObject ) );
        */
      }
      
      /*
      for ( size_t i=0; i<m_desc.interface.methods.size(); ++i )
      {
        std::string const &methodName = m_desc.interface.methods[i];
        Method method = 0;
        for ( size_t j=0; j<m_orderedSOLibHandles.size(); ++j )
        {
          SOLibHandle soLibHandle = m_orderedSOLibHandles[j];
          method = (Method)SOLibResolve( soLibHandle, methodName );
          if ( method )
            break;
        }
        if ( !method )
          throw Exception( "method "+_(methodName)+" not found" );
        m_methodMap.insert( MethodMap::value_type( methodName, method ) );
      }
      */
      
      
      std::vector<std::string> codeFiles;
      m_desc.code.appendMatching( Util::getHostTriple(), codeFiles );
      std::string filename;
      m_code = "";
      for ( std::vector<std::string>::const_iterator it=codeFiles.begin(); it!=codeFiles.end(); ++it )
      {
        std::string const &codeEntry = *it;
        
        if ( filename.empty() )
          filename = codeEntry;
          
        std::string code;
        try
        {
          code = extensionDir->getFileContents( codeEntry );
        }
        catch ( Exception e )
        {
          throw _(codeEntry) + ": " + e;
        }
        m_code += code + "\n";
      }
      
      RC::ConstHandle<KL::Source> source = KL::StringSource::Create( filename, m_code );
      RC::Handle<KL::Scanner> scanner = KL::Scanner::Create( source );
      m_ast = KL::Parse( scanner, m_diagnostics );
      if ( !m_diagnostics.containsError() )
        m_ast->registerTypes( cgManager, m_diagnostics );
      for ( CG::Diagnostics::const_iterator it=m_diagnostics.begin(); it!=m_diagnostics.end(); ++it )
      {
        CG::Location const &location = it->first;
        CG::Diagnostic const &diagnostic = it->second;
        FABRIC_LOG( "[%s] %s:%u:%u: %s: %s", extensionName.c_str(), location.getFilename()->c_str(), (unsigned)location.getLine(), (unsigned)location.getColumn(), diagnostic.getLevelDesc(), diagnostic.getDesc().c_str() );
      }
      if ( m_diagnostics.containsError() )
        throw Exception( "KL compile failed" );
      
      std::vector< RC::ConstHandle<AST::FunctionBase> > functionBases;
      m_ast->collectFunctionBases( functionBases );
      for ( std::vector< RC::ConstHandle<AST::FunctionBase> >::const_iterator it=functionBases.begin(); it!=functionBases.end(); ++it )
      {
        RC::ConstHandle<AST::FunctionBase> const &functionBase = *it;
        
        if ( !functionBase->getBody() )
        {
          std::string symbolName = functionBase->getSymbolName( cgManager );
          void *resolvedFunction = 0;
          for ( size_t i=0; i<m_orderedSOLibHandles.size(); ++i )
          {
            resolvedFunction = SOLibResolve( m_orderedSOLibHandles[i], symbolName );
            if ( resolvedFunction )
              break;
          }
          if ( !resolvedFunction )
            throw Exception( "error: symbol " + _(symbolName) + ", prototyped in KL, not found in native code" );
          m_externalFunctionMap.insert( ExternalFunctionMap::value_type( symbolName, resolvedFunction ) );
          
          if ( functionBase->isDestructor() )
          {
            RC::ConstHandle<AST::Destructor> destructor = RC::ConstHandle<AST::Destructor>::StaticCast( functionBase );
            std::string thisTypeName = destructor->getThisTypeName();
            implNameToDestructorMap[thisTypeName] = (void (*)( void * )) resolvedFunction;
          }
        }
      }

      m_jsConstants = m_desc.jsConstants.concatMatching( Util::getHostTriple() );
    }