module.cpp

来自「Shorthand是一个强大的脚本语言」· C++ 代码 · 共 655 行 · 第 1/2 页

CPP
655
字号
 */
void ShhModule::parse_posted_data()
{
    string s;
    const char* v = safe_getenv("CONTENT_LENGTH", s);
    int content_length = (v != NULL) ? atoi(v) : 0;
    TRACE((3, "reading posted data: CONTENT_LENGTH = %d (\"%s\")\n", content_length, v));
    if (content_length <= 0) return;
    
    int bytes_left = content_length;

    string input;
    char buffer[1024]; int count;
    
    while(bytes_left > 0 && (count = m_http_stream->http_read(buffer, sizeof(buffer))) > 0)
    {
        input.append(buffer, count);
        bytes_left -= count;
    }
    //input.save_to_file("c://tmp//shorthand.post.txt");
    TRACE((3, "got posted data...\n"));
    parse_vars_into_map((char*) input.cstr(), m_context->m_put_fields);

}


/**
 * Parses a list of URL-encoded variables into string map.
 */
void ShhModule::parse_vars_into_map(char* source, cchar_map& target)
{

    char* token = strtok(source, "&");
    while(token != NULL )
    {
        char* q = strchr(token, '=');
        if (q != NULL)
        {
            char* name = token;
            while(*name && isspace(*name)) name++;
            *q = '\0';
            char* value = q+1;
            while(q > name && isspace(q[-1])) *(--q) = '\0';
            
            string raw_value(value);
            string raw_name(name);
            string real_name, real_value;

            raw_name.urldecode(real_name);
            raw_value.urldecode(real_value);

            target.put(m_context->m_memory.strdup(real_name), 
                       m_context->m_memory.strdup(real_value));
        }
        token = strtok( NULL, "&" );
    }
}



/**
 * Executes the body of parsed script.
 */
void ShhModule::execute_body()
{
    if (m_parent == NULL)
    {
        parse_query_string();
        parse_posted_data();
        
        
        m_http_stream->http_add_header("Cache-Control", "no-cache");
        m_http_stream->http_add_header("Pragma", "no-cache");
        
        datetime dt; dt.import_ydm(1980, 1, 1);
        string exp;  dt.export_rfc(exp);
        m_http_stream->http_add_header("Expires", exp);

    
        var("script")->value() =  m_own_context.m_memory.strdup(getenv("PATH_INFO"));
        var("ip")->value()     =  m_own_context.m_memory.strdup(getenv("REMOTE_ADDR"));
    }

    try
    {
        if (m_entry != NULL)
        {
            m_entry->execute();
        }
    }
    catch(ShhExitException* exex)
    {
        // call to exit()
        delete exex;
    }
    
    m_own_context.m_memory.purge();
    if (m_parent == NULL) 
    {
	m_http_stream->http_finalize();
    }
}


#ifdef WIN32
#define PATH_SEPARATOR ";"
#else
#define PATH_SEPARATOR ":"
#endif

/**
 * Executes another module in the current context.
 *
 * parameters:
 *     location:  location where another module was mentioned
 *     name:      name of the module to include
 *     do_return: indicates whether or not we should return 
 *                after finishing with another module
 *     flags:     reserved
 */
void ShhModule::switch_module(ShhNode& location, const char* name, bool do_return, int flags)
{
    ShhModule* topm = this->top();
    
    bool is_full_name;
    string full_name;

#ifdef WIN32
    is_full_name = strlen(name) > 1 && (name[1] == ':' || name[0] == '\\' && name[1] == '\\');
#else
    is_full_name = name[0] == '\0';
#endif

    struct stat stinfo;

    const char* path_translated = getenv("PATH_TRANSLATED");
    /*
    this->printf("path_translated = %s; m_script_name = %s\n", 
        path_translated != NULL ? path_translated : "NULL", m_script_name.cstr());
    return;*/

    if (is_full_name)
    {
        full_name = name;
        if (stat(full_name, &stinfo) != 0)
        {
            throw location.mkexception(1270, "file %s was not found", name);
        }
    }
    else
    {   
        string local_dir, include_path;
        bool found = false;
        string candidate;

        string this_script_name;
        
        if (path_translated != NULL)
        {
            this_script_name = path_translated;
        }
        else
        {
            this_script_name = m_script_name;
        }
        //TRACE((1, "path_translated = %s\n", getenv("PATH_TRANSLATED")));
        TRACE((1, "script_name = %s\n", this_script_name.cstr()));
        
        include_path = getenv("SHH_INCLUDE_PATH");

        // first, try to find it in the same dir as original script:
        const char* last_slash = strrchr(this_script_name, '/');

#ifdef WIN32
        const char* last_backslash = strrchr(this_script_name, '\\');
        if (last_slash == NULL || last_backslash > last_slash)
            last_slash = last_backslash;
#endif
        if (last_slash != NULL)
        {
            string path; path.set(this_script_name, last_slash - (const char*)this_script_name);
            path.chop("/\\");
            string local_attempt;
            local_dir = path;
            TRACE((1, "local_dir = %s\n", path.cstr()));
        }
        else
        {
            char buf[512];
            local_dir = getcwd(buf, 512);
            local_dir.chop("/\\");
        }

        candidate.printf("%s"SLASH"%s", local_dir.cstr(), name);
        if (stat(candidate, &stinfo) == 0)
            found = true;
    
        if (!found)
        {
            // first, find another module source file    
            string_array paths; string::split(include_path, paths, PATH_SEPARATOR);
            for(int i=0,n=paths.size(); i<n; i++)
            {
                string* path = paths.get(i);
                path->chop("/\\");
                candidate.printf("%s"SLASH"%s", path->cstr(), name);
                if (stat(candidate, &stinfo) == 0)
                {
                    found = true;
                    break;
                }
            }
        }
        if (!found)
        {
            throw location.mkexception(1271, "file \"%s\" cannot be not found in the local directory (\"%s\") or include path (\"%s\")", name, local_dir.cstr(), include_path.cstr());
        }
        full_name = candidate;
    }


    for(int i=0,n=topm->m_modules.size(); i<n; i++)
    {
        int diff;
#ifdef WIN32
        diff = stricmp(topm->m_modules.get(i)->getName(), full_name);
#else
        diff = strcmp(topm->m_modules.get(i)->getName(), full_name);
#endif
        if (diff == 0)
            return;
    }
    
    ShhModule* module = new ShhModule(full_name, this);
    topm->m_modules.add(module);

    
    string content; 
    try
    {
        content.load_from_file(full_name);
    }
    catch(ShhException*)
    {
        throw location.mkexception(1274, "Cannot open file %s", full_name.cstr());
    }

    try
    {
        module->execute_script(content, m_http_stream);
    }
    catch(ShhException* ex)
    {
        string msg = ex->message();
        msg.chop("\r\n");
        if (msg.ends_with("<br>")) msg.set_length(msg.length() - 4);

        ShhException* wrapper = new ShhException(1272, 
            "%s<BR>\nin file included from <B>%s</B> at line <b>%d</b>", 
            msg.cstr(), m_script_name.cstr(), location.lineno());
        delete ex;
        throw wrapper;
    }

    if (!do_return) throw new ShhExitException();

}


ShhModule* ShhModule::top() 
{
    if (m_parent != NULL) return m_parent->top();
    else return this;
}


/**
 * Returns a reference to the global list of user-defined functions.
 */
ShhDefunList& ShhModule::getFunctionList()
{
    if (m_parent == NULL) 
        return m_ufds;
    else
        return m_parent->getFunctionList();
}

/** 
 * Tries to execute named function
 */
ShhValue ShhModule::executeFunction(const char* name, const ShhValueList& args)
{
    const ShhDefun* udf;

    // lock for user-defined function
    ShhDefunList& udfs = getFunctionList();
    udf = udfs.find(name);
    ShhModule* topModule = top();

    if (udf != NULL)
    {
        ShhValue returnValue;
        ShhValue* oldReturnValue = m_return_value;
        topModule->m_return_value = &returnValue;
        try
        {
            udf->execute(this, args);
        }
        catch(ShhReturnException*)
        {
        }
        topModule->m_return_value = oldReturnValue;
        return returnValue;
    }
    else 
    {
        // look for built-in function
        const ShhBuiltin* bi = g_builtins.find(name);
        if (bi == NULL)
            throw new ShhObjectException(1050, "call to undefined function '%s'", name);
        return bi->execute(this, args);
    }


}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?