Example #1
0
static void
setup_request_object(sl_vm_t* vm, request_rec* r)
{
    struct iter_args ia;
    
    sl_request_opts_t opts;
    opts.method       = (char*)r->method;
    opts.uri          = r->uri;
    opts.path_info    = r->path_info;
    opts.query_string = r->args;
    opts.remote_addr  = r->connection->remote_ip;
    opts.content_type = (char*)apr_table_get(r->headers_in, "content-type");
    
    ia.count = 0;
    ia.capacity = 4;
    ia.kvs = sl_alloc(vm->arena, sizeof(sl_request_key_value_t) * ia.capacity);
    ia.vm = vm;
    apr_table_do(iterate_apr_table, &ia, r->headers_in, NULL);
    opts.header_count = ia.count;
    opts.headers = ia.kvs;
    
    ap_add_common_vars(r);
    ap_add_cgi_vars(r);
    ia.count = 0;
    ia.capacity = 4;
    ia.kvs = sl_alloc(vm->arena, sizeof(sl_request_key_value_t) * ia.capacity);
    ia.vm = vm;
    apr_table_do(iterate_apr_table, &ia, r->subprocess_env, NULL);
    opts.env_count = ia.count;
    opts.env = ia.kvs;
    
    read_post_data(vm, &opts, r);
    
    sl_request_set_opts(vm, &opts);
}
Example #2
0
static bool
setup_request_object(sl_vm_t* vm, slash_request_info_t* info)
{
    bool result = true;
    sl_request_opts_t opts;

    opts.method       =
        info->request_method ? info->request_method->value : "GET";

    opts.uri          = info->real_uri ? info->real_uri : "";
    opts.path_info    = info->real_path_info ? info->real_path_info : "";
    opts.query_string = info->query_string ? info->query_string->value : "";
    opts.remote_addr  = info->remote_addr ? info->remote_addr->value : "";
    opts.content_type = info->content_type ? info->content_type->value : NULL;

    opts.header_count = info->http_headers->count;
    opts.headers      = info->http_headers->kvs;
    
    opts.env_count    = info->environment->count;
    opts.env          = info->environment->kvs;
    
    result = read_post_data(vm, &opts, info);

    sl_request_set_opts(vm, &opts);

    return result;
}
Example #3
0
void do_post(int fd, char *uri)
{
    int is_static;
    struct stat sbuf;
    char filename[MAXLINE], cgiargs[MAXLINE];
    
    read_post_data(fd);

    /* 从POST request 中解析 URI  */
    is_static = parse_uri(uri, filename, cgiargs);
    if (stat(filename, &sbuf) < 0) {
        send_error(fd, filename, "404", "Not Found");
        return;
    }
    send_error(fd, filename, "403", "Forbidden");
    close(fd);
    return;
}
Example #4
0
/***************************************************************************
 * Function Name: cfe_web_bg_process
 * Description  : This function processes an HTTP request on a socket.
 * Returns      : None.
 ***************************************************************************/
static void cfe_web_bg_process(PSOCKET_INFO si)
{
    char post_subst[] = {UPLOAD_FATAL, '\0'};
    char *post_substs[] = {post_subst};
    int close_tcp = 0;

    switch( si->state )
    {
    case HTTP_READ_FIRST_HDR:
        if( read_first_hdr( si->s, si->web_first_buf,
            sizeof(si->web_first_buf), &si->web_buf_idx, &close_tcp ) == 0 )
        {
            /* Not all of the first header has been read yet. Try again later.*/
            break;
        }

        /* The first header has been read. */
        si->state = HTTP_READ_REMAINING_HDRS;

        /* fall thru */

    case HTTP_READ_REMAINING_HDRS:
        if( read_remaining_hdrs( si->s, si->web_buf, sizeof(si->web_buf),
            &si->web_buf_idx, &close_tcp, &si->post_content_length ) )
        {
            if( g_processing_cmd == 0 )
            {
                char *method = NULL;
                char *path = NULL;
                char *ptr = (char *) si->web_first_buf;

                method = gettoken(&ptr);
                if( method )
                    path = gettoken(&ptr);

                /* Process the HTTP request. Only GET and POST are supported. */
                if( method && path )
                {
                    if( !strcmpi( method, "get" ) )
                    {
                        send_page( si->s, path, 1, NULL, 0 );
                        close_tcp = 1;
                    }
                    else
                    {
                        if( !strcmpi( method, "post" ) )
                        {
                            if( g_post_data_in_progress == 0 )
                            {
                                g_post_data_in_progress = 1;
                                si->state = HTTP_READ_POST_DATA;
                            }
                            else
                            {
                                send_error( si->s, 501, "Upload Busy",
                                    (char*) 0,
                                    "An image is already being uploaded." );
                                close_tcp = 1;
                            }
                        }
                        else
                        {
                            send_error( si->s, 501, "Not Implemented",
                                (char*) 0,
                                "That method is not implemented." );
                            close_tcp  = 1;
                        }
                    }
                }
                else
                {
                    send_error( si->s, 400, "Bad Request", (char *) 0,
                        "Can't parse request." );
                    close_tcp  = 1;
                }
            }
            else
            {
                /* A download and flash image command is being executed from
                 * the serial port console.
                 */
                send_error( si->s, 400, "Bad Request", (char *) 0,
                    "Console command is in progress." );
                close_tcp  = 1;
            }
        }

        if( si->state != HTTP_READ_POST_DATA )
            break;

    case HTTP_READ_POST_DATA:
        /* Read the post data, which contains an image to flash, into low
         * memory.
         */
        if( (post_subst[0] = read_post_data( si->s, POST_DATA_START,
            si->post_content_length, &g_post_data_idx )) == UPLOAD_OK )
        {
            /* Verify that the post data is a valid image to flash. */
            post_subst[0] = parse_post_data( si->s, POST_DATA_START,
                g_post_data_idx, (unsigned char **) &g_image_start, &g_image_len,
                &g_image_format );
        }

        switch( post_subst[0] )
        {
        case UPLOAD_PENDING:
            break;

        case UPLOAD_TCP_ERROR:
            close_tcp = 1;
            g_post_data_in_progress = 0;
            g_post_data_idx = 0;
            break;

        case UPLOAD_OK:
            /* Notify foreground to abort the console input so it can
             * write the image to flash memory.
             */
            g_console_abort = 1;

            send_page(si->s, "/uploadinfo.html", 0, post_substs, 1);
            close_tcp = 1;
            g_post_data_idx = 0;
            break;

        default:
            /* The image was downloaded OK but there was a problem with it
             * so it could not be written to flash memory.
             */
            send_page(si->s, "/uploadinfo.html", 0, post_substs, 1);
            close_tcp = 1;
            g_post_data_in_progress = 0;
            g_post_data_idx = 0;
            break;
        }
        break;
    }

    /* Close the socket if the HTTP transaction is done. */
    if( close_tcp )
    {
        POLL();
        tcp_close(si->s);
        si->s = SOCKET_CLOSED;
        si->state = HTTP_READ_FIRST_HDR;
        si->web_buf_idx = 0;
        si->post_content_length = 0;
    }
} /* cfe_web_poll */
Example #5
0
int main(int argc, char *argv[]) 
{
    fd_set rfds, wfds;
    struct connstruct *tp, *to;
    struct serverstruct *sp;
    int rnum, wnum, active;
    int i = 1;
    time_t currtime;
    char *httpAddress = NULL;
    int httpPort = CONFIG_HTTP_PORT;
    char *httpsAddress = NULL;
    int httpsPort = CONFIG_HTTP_HTTPS_PORT;
    uint32_t options = CONFIG_HTTP_DEFAULT_SSL_OPTIONS;
    char *portStr;
    char *private_key = NULL;
    char *cert = NULL;

#ifdef WIN32
    WORD wVersionRequested = MAKEWORD(2, 2);
    WSADATA wsaData;
    WSAStartup(wVersionRequested,&wsaData);
#else
    signal(SIGPIPE, SIG_IGN);
#if defined(CONFIG_HTTP_HAS_CGI)
    signal(SIGCHLD, reaper);
#endif
#ifdef CONFIG_HTTP_VERBOSE
    signal(SIGQUIT, die);
#endif
#endif

#ifdef CONFIG_HTTP_VERBOSE
    signal(SIGTERM, die);
    signal(SIGINT, sigint_cleanup);
#endif
    tdate_init();

    /* get some command-line parameters */
    while (argv[i] != NULL)
    {
        if (strcmp(argv[i], "-p") == 0 && argv[i+1] != NULL)
        {
            if ((portStr = strchr(argv[i+1], ':')) != NULL)
            {
                httpAddress = argv[i+1];
                *portStr = 0;
                httpPort = atoi(portStr + 1);
            }
            else
                httpPort = atoi(argv[i+1]);

            i += 2;
            continue;
        }

        if (strcmp(argv[i], "-s") == 0 && argv[i+1] != NULL)
        {
            if ((portStr = strchr(argv[i+1], ':')) != NULL)
            {
                httpsAddress = argv[i+1];
                *portStr = 0;
                httpsPort = atoi(portStr + 1);
            }
            else
                httpsPort = atoi(argv[i+1]);

            i += 2;
            continue;
        }

        if (strcmp(argv[i], "-w") == 0 && argv[i+1] != NULL)
        {
            webroot = argv[i+1];
            i += 2;
            continue;
        }

        if (strcmp(argv[i], "-cert") == 0 && argv[i+1] != NULL)
        {
            cert = argv[i+1];
            i += 2;
            continue;
        }

        if (strcmp(argv[i], "-key") == 0 && argv[i+1] != NULL)
        {
            private_key = argv[i+1];
            i += 2;
            continue;
        }
        printf("%s:\n"
               "    [-p [address:]httpport]\n"
               "    [-s [address:]httpsport]\n"
               "    [-key private_key]\n"
               "    [-cert cert]\n"
               "    [-w webroot]\n", argv[0]);
        exit(1);
    }

    for (i = 0; i < INITIAL_CONNECTION_SLOTS; i++) 
    {
        tp = freeconns;
        freeconns = (struct connstruct *)calloc(1, sizeof(struct connstruct));
        freeconns->next = tp;
    }

    if ((active = openlistener(httpAddress, httpPort)) == -1) 
    {
#ifdef CONFIG_HTTP_VERBOSE
        fprintf(stderr, "ERR: Couldn't bind to port %d\n", httpPort);
#endif
        exit(1);
    }

    addtoservers(active);

    if ((active = openlistener(httpsAddress, httpsPort)) == -1) 
    {
#ifdef CONFIG_HTTP_VERBOSE
        fprintf(stderr, "ERR: Couldn't bind to port %d\n", httpsPort);
#endif
        exit(1);
    }

    addtoservers(active);

    if (cert != NULL && private_key != NULL)
        options |=  SSL_NO_DEFAULT_KEY;

    servers->ssl_ctx = ssl_ctx_new(options, CONFIG_HTTP_SESSION_CACHE_SIZE);
    servers->is_ssl = 1;

    if (cert != NULL && private_key != NULL)
    {
        printf("YEAH\n");
        if (ssl_obj_load(servers->ssl_ctx, SSL_OBJ_RSA_KEY, private_key,
                    NULL))
        {
#ifdef CONFIG_HTTP_VERBOSE
            fprintf(stderr, "ERR: Couldn't load private key %s\n", private_key);
#endif
            exit(1);
        }

        if (ssl_obj_load(servers->ssl_ctx, SSL_OBJ_X509_CERT, cert,
                    NULL))
        {
#ifdef CONFIG_HTTP_VERBOSE
            fprintf(stderr, "ERR: Couldn't load cert %s\n", cert);
#endif
            exit(1);
        }
    }

#if defined(CONFIG_HTTP_HAS_CGI)
    addcgiext(CONFIG_HTTP_CGI_EXTENSIONS);
#endif

#if defined(CONFIG_HTTP_VERBOSE)
#if defined(CONFIG_HTTP_HAS_CGI)
    printf("addcgiext %s\n", CONFIG_HTTP_CGI_EXTENSIONS); 
#endif
    printf("%s: listening on ports %d (http) and %d (https)\n", 
            server_version, httpPort, httpsPort);
    TTY_FLUSH();
#endif

    ax_chdir();

#ifdef CONFIG_HTTP_ENABLE_DIFFERENT_USER
    {
        struct passwd *pd = getpwnam(CONFIG_HTTP_USER);

        if (pd != NULL)
        {
            int res = setuid(pd->pw_uid);
            res |= setgid(pd->pw_gid);

#if defined(CONFIG_HTTP_VERBOSE)
            if (res == 0)
            {
                printf("change to '%s' successful\n", CONFIG_HTTP_USER); 
                TTY_FLUSH();
            }
#endif
        }

    }
#endif

#ifndef WIN32 
#ifdef CONFIG_HTTP_IS_DAEMON
    if (fork() > 0)  /* parent will die */
        exit(0);

    setsid();
#endif
#endif

    /* main loop */
    while (1)
    {
        struct timeval tv = { 10, 0 };
        FD_ZERO(&rfds);
        FD_ZERO(&wfds);
        rnum = wnum = -1;
        sp = servers;

        while (sp != NULL)  /* read each server port */
        {
            FD_SET(sp->sd, &rfds);

            if (sp->sd > rnum) 
                rnum = sp->sd;
            sp = sp->next;
        }

        /* Add the established sockets */
        tp = usedconns;
        currtime = time(NULL);

        while (tp != NULL) 
        {
            if (currtime > tp->timeout)     /* timed out? Kill it. */
            {
                to = tp;
                tp = tp->next;
                removeconnection(to);
                continue;
            }

            if (tp->state == STATE_WANT_TO_READ_HEAD) 
            {
                FD_SET(tp->networkdesc, &rfds);
                if (tp->networkdesc > rnum) 
                    rnum = tp->networkdesc;
            }

            if (tp->state == STATE_WANT_TO_SEND_HEAD) 
            {
                FD_SET(tp->networkdesc, &wfds);
                if (tp->networkdesc > wnum) 
                    wnum = tp->networkdesc;
            }

            if (tp->state == STATE_WANT_TO_READ_FILE) 
            {
                FD_SET(tp->filedesc, &rfds);
                if (tp->filedesc > rnum) 
                    rnum = tp->filedesc;
            }

            if (tp->state == STATE_WANT_TO_SEND_FILE) 
            {
                FD_SET(tp->networkdesc, &wfds);
                if (tp->networkdesc > wnum) 
                    wnum = tp->networkdesc;
            }

#if defined(CONFIG_HTTP_DIRECTORIES)
            if (tp->state == STATE_DOING_DIR) 
            {
                FD_SET(tp->networkdesc, &wfds);
                if (tp->networkdesc > wnum) 
                    wnum = tp->networkdesc;
            }
#endif
            tp = tp->next;
        }

        active = select(wnum > rnum ? wnum+1 : rnum+1,
                rnum != -1 ? &rfds : NULL, 
                wnum != -1 ? &wfds : NULL,
                NULL, usedconns ? &tv : NULL);

        /* timeout? */
        if (active == 0)
            continue;

        /* New connection? */
        sp = servers;
        while (active > 0 && sp != NULL) 
        {
            if (FD_ISSET(sp->sd, &rfds)) 
            {
                handlenewconnection(sp->sd, sp->is_ssl);
                active--;
            }

            sp = sp->next;
        }

        /* Handle the established sockets */
        tp = usedconns;

        while (active > 0 && tp != NULL) 
        {
            to = tp;
            tp = tp->next;

            if (to->state == STATE_WANT_TO_READ_HEAD &&
                        FD_ISSET(to->networkdesc, &rfds)) 
            {
                active--;
#if defined(CONFIG_HTTP_HAS_CGI)
                if (to->post_state)
                    read_post_data(to);
                else
#endif
                    procreadhead(to);
            } 

            if (to->state == STATE_WANT_TO_SEND_HEAD &&
                        FD_ISSET(to->networkdesc, &wfds)) 
            {
                active--;
                procsendhead(to);
            } 

            if (to->state == STATE_WANT_TO_READ_FILE && 
                        FD_ISSET(to->filedesc, &rfds)) 
            {
                active--;
                procreadfile(to);
            } 

            if (to->state == STATE_WANT_TO_SEND_FILE && 
                        FD_ISSET(to->networkdesc, &wfds)) 
            {
                active--;
                procsendfile(to);
            }

#if defined(CONFIG_HTTP_DIRECTORIES)
            if (to->state == STATE_DOING_DIR &&
                        FD_ISSET(to->networkdesc, &wfds)) 
            {
                active--;
                procdodir(to);
            }
#endif
        }
    }

    return 0;
}
Example #6
0
int oversight_main(int argc,char **argv,int send_content_type_header)
{
    int result=0;
    int done=0;

    g_start_clock = time(NULL);
    assert(sizeof(long long) >= 8);

    init_view();
    adjust_path();

    char *q=getenv("QUERY_STRING");
    char *sp=getenv("SCRIPT_NAME");

    char *p;
    char *req;
    if (q && (p = delimited_substring(q,"&",REMOTE_VOD_PREFIX2,"=",1,0)) != NULL) {

        gaya_auto_load(p+strlen(REMOTE_VOD_PREFIX2)+1);
        done=1;

    } else if (q && strstr(q,YAMJ_PREFIX2)) {

        g_query=parse_query_string(q,g_query);
        //req = url_decode(q+strlen(YAMJ_PREFIX2));
        req = url_decode(query_val("yamj"));
        yamj_xml(req);
        FREE(req);
        done=1;
    } else if (sp && (req=strstr(sp,YAMJ_PREFIX)) != NULL) {
        // If oversight script is launched as /oversight/yamj/xxxxx.xml
        // then use xxxxxx.xml as a yamj xml request.
        // This is to allow for Apache ModAlias to serve static images whilst calling oversight for CGI
        // The rewrite rules should be 
        //    ScriptAliasMatch ^/oversight/yamj/(.*).xml  /share/Apps/oversight/oversight.cgi
        //    AliasMatch ^/oversight/yamj/banner_(.*jpg) /oversight/db/global/_b/ovs_$1
        //    AliasMatch ^/oversight/yamj/fanart_(.*jpg) /oversight/db/global/_fa/ovs_$1
        //    AliasMatch ^/oversight/yamj/poster_(.*jpg) /oversight/db/global/_J/ovs_$1
        //    AliasMatch ^/oversight/yamj/thumb_(.*).jpg  /oversight/db/global/_J/ovs_$1.thumb.jpg
        //    AliasMatch ^/oversight/yamj/boxset_(.*).jpg  /oversight/db/global/_J/ovs_$1.thumb.boxset.jpg`
        //
        req += strlen(YAMJ_PREFIX);
        yamj_xml(req);
        done=1;

    } else if (q == NULL || strchr(q,'=') == NULL ) {

        if (argc > 1 ) {

            if ( argv[1] && *argv[1] && argv[2] == NULL && util_starts_with(argv[1],YAMJ_PREFIX) ) {
                char *req = url_decode(argv[1]+strlen(YAMJ_PREFIX));
                yamj_xml(req);
                FREE(req);
                done=1;

            } else if ( argv[1] && *argv[1] && argv[2] == NULL && strchr(argv[1],'=') == NULL) {
                // Single argument passed.
                //
                char *path = url_decode(argv[1]);
                char *dot = strrchr(path,'.');
                if (dot < path) dot = strchr(path,'\0');
                int result = 0;

                fprintf(stderr,"path=[%s]",path);

                // should really use file command or magic number to determine file type

                if (dot && STRCMP(dot,".png") == 0 ) {

                    result = cat(CONTENT_TYPE"image/png",path);

                } else if (dot &&  STRCMP(dot,".jpg") == 0 ) {

                    result = cat(CONTENT_TYPE"image/jpeg",path);

                } else if (dot &&  STRCMP(dot,".gif") == 0) {

                    result = cat(CONTENT_TYPE"image/gif",path);

                } else if (dot &&  (STRCMP(dot,".swf") == 0 || STRCMP(dot,".phf" ) == 0) ) {

                    result = cat(CONTENT_TYPE"application/x-shockwave-flash",path);

                } else if (browsing_from_lan() ) {

                    if (is_dir(path)) {

                        // load_configs(); // load configs so we can use file_to_url() functions 
                        result = ls(path);
                    } else {
                        int exists = is_file(path);

                        char *all_headers = NULL;
                        char *content_headers = NULL;

                        if (exists) {
                            if (strstr(path,".tar.gz") || strcmp(dot,".tgz") == 0) {

                                ovs_asprintf(&content_headers,"%s%s\n%s%s",
                                        CONTENT_TYPE,"application/x-tar",CONTENT_ENC,"gzip");

                            } else if (strcmp(dot,".gz") == 0 ) {

                                ovs_asprintf(&content_headers,"%s%s\n%s%s",
                                        CONTENT_TYPE,"application/x-gzip",CONTENT_ENC,"identity");

                            } else if (strcmp(dot,".html") == 0 ) {

                                ovs_asprintf(&content_headers,"%s%s",
                                        CONTENT_TYPE,"text/html;charset=utf-8");

                            } else {
                                ovs_asprintf(&content_headers,"%s%s",
                                        CONTENT_TYPE,"text/plain;charset=utf-8");
                            }
                        } else {
                            // .gz.txt is a fake extension added by the ls command to view log.gz inline without browser downloading.
                            if (strstr(path,".gz.txt")) {
                                ovs_asprintf(&content_headers,"%s%s\n%s%s",
                                        CONTENT_TYPE,"text/plain;charset=utf-8", CONTENT_ENC,"gzip");
                                // remove .txt to get real zip file.
                                // .txt is needed so a certain browser displays inline. (might be other ways)
                                *dot = '\0';
                            } else {
                                // 404 error would be here
                            }
                        }
                        ovs_asprintf(&all_headers,"%s\n%s%ld",content_headers,CONTENT_LENGTH,file_size(path));
                        FREE(content_headers);
                        result = cat(all_headers,path);
                        FREE(all_headers);

                    }
                }
                FREE(path);
                fflush(stdout);
                done=1;
            }
        }
    }



    if (!done) {
        if (send_content_type_header) {
            printf("Content-Type: text/html; charset=utf-8\n\n");

            start_page("CGI");
        } else {
            start_page("WGET");
        }

        html_log_level_set(2);

        load_configs();
        //html_hashtable_dump(0,"settings",g_nmt_settings);

        long log_level;
        if (config_check_long(g_oversight_config,"ovs_log_level",&log_level)) {
            html_log_level_set(log_level);
        }

        html_comment("Appdir= [%s]",appDir());

        //array_unittest();
        //util_unittest();
        //config_unittest();

        g_query = string_string_hashtable("g_query2",16);

        html_comment("default query ... ");
        add_default_html_parameters(g_query);
        html_hashtable_dump(0,"prequery",g_query);

        html_comment("read query ... ");
        g_query=parse_query_string(getenv("QUERY_STRING"),g_query);
        html_hashtable_dump(0,"query",g_query);

        html_comment("read post ... ");

        struct hashtable *post=read_post_data(getenv("TEMP_FILE"));
        html_hashtable_dump(0,"post",g_query);
        
        html_comment("merge query and post data");
        merge_hashtables(g_query,post,1); // post is destroyed

        html_hashtable_dump(0,"query final",g_query);


#if 0
        html_comment("utf8len expect 2 = %d",utf8len("a"));
        html_comment("utf8len expect 2 = %d",utf8len("à€€a"));
        html_comment("utf8len expect 2 = %d",utf8len("ü€€€€€a"));
        html_comment("utf8cmp_char 0 = %d",utf8cmp_char("ü€€€€€a","ü€€€€€b"));
        html_comment("utf8cmp_char !0 = %d",utf8cmp_char("ü€€€€€a","ü€€€€€a"));
        html_comment("utf8cmp_char 0 = %d",utf8cmp_char("a","a"));
        html_comment("utf8cmp_char !0 = %d",utf8cmp_char("a","b"));
        html_comment("utf8cmp_char !0 = %d",utf8cmp_char("ü€€€€€a","üa"));
        html_comment("utf8cmp_char !0 = %d",utf8cmp_char("a","ü€€€€€a"));
        Abet *a = abet_create("abcdefghijklmnopqrstuvwxyz");
        html_comment("inc a %d",abet_letter_inc_or_add(a,"a",1));
        html_comment("inc a %d",abet_letter_inc_or_add(a,"a",1));
        html_comment("inc z %d",abet_letter_inc_or_add(a,"z",1));
        html_comment("inc 4 %d",abet_letter_inc_or_add(a,"4",1));
        html_comment("inc 5 %d",abet_letter_inc_or_add(a,"5",1));
        html_comment("inc 5 %d",abet_letter_inc_or_add(a,"5",1));
        html_comment("inc 6* %d",abet_letter_inc_or_add(a,"6",0));
        html_comment("inc 7* %d",abet_letter_inc_or_add(a,"7",0));
        html_comment("inc a %d",abet_letter_inc_or_add(a,"a",1));
        abet_free(a);
#endif


        config_read_dimensions(1);

        HTML_LOG(0,"Begin Actions");
        do_actions();
       
        ViewMode *view;

        DbSortedRows *sortedRows = NULL;


        while(1) {
            view=get_view_mode(1);  
            HTML_LOG(0,"view mode = [%s]",view->name);

            // If movie view but all ids have been removed , then move up
            if (view == VIEW_MOVIE && !*query_val(QUERY_PARAM_IDLIST)) {
                query_pop();
                view=get_view_mode(1);  
            }

            sortedRows = get_sorted_rows_from_params();
            dump_all_rows("sorted",sortedRows->num_rows,sortedRows->rows);

            // If it's not a tv/movie detail or boxset view then break
            if (view == VIEW_MENU ||  view == VIEW_ADMIN ) {
                break;
            }

            // Found some data - as we are on a smaller view - filter it
            if (sortedRows->num_rows && sortedRows->num_rows < 50 ) {
                int new_num = sortedRows->num_rows;
                int max_new = sortedRows->num_rows;
                DbItem **new_list = filter_page_items(0,sortedRows->num_rows,sortedRows->rows,max_new,&new_num);
                FREE(sortedRows->rows);
                sortedRows->rows = new_list;
                sortedRows->num_rows=new_num;
            }
            if (sortedRows->num_rows) break;

            // No data found in this view - try to return to the previous view.
            query_pop();
            // Adjust config - 
            // TODO Change the config structure to reload more efficiently.
            //reload_configs();

            config_read_dimensions(1);

            // Now refetch all data again with new parameters.
            sorted_rows_free_all(sortedRows);
            HTML_LOG(0,"reparsing database");
        }

        // Remove and store the last navigation cell. eg if user clicked on cell 12 this is passed in 
        // the URL as @i=12. The url that returns to this page then has i=12. If we have returned to this
        // page we must remove i=12 from the query so that it is not passed to the new urls created for this 
        // page.
        set_selected_item();

        char *skin_name=get_skin_name();


        if (strchr(skin_name,'/') || *skin_name == '.' || !*skin_name ) {

            html_error("Invalid skin name[%s]",skin_name);

        } else {

            playlist_open();
            //exp_test();

            if (view->view_class == VIEW_CLASS_ADMIN) {

                setPermissions();
                display_admin(sortedRows);

            } else {

                char *template = query_val(QUERY_PARAM_TEMPLATE_NAME);
                if (EMPTY_STR(template)) {