static int vlclua_httpd_file_new( lua_State *L )
{
    httpd_host_t **pp_host = (httpd_host_t **)luaL_checkudata( L, 1, "httpd_host" );
    const char *psz_url = luaL_checkstring( L, 2 );
    const char *psz_mime = luaL_nilorcheckstring( L, 3 );
    const char *psz_user = luaL_nilorcheckstring( L, 4 );
    const char *psz_password = luaL_nilorcheckstring( L, 5 );
    const vlc_acl_t **pp_acl = lua_isnil( L, 6 ) ? NULL : luaL_checkudata( L, 6, "acl" );
    /* Stack item 7 is the callback function */
    luaL_argcheck( L, lua_isfunction( L, 7 ), 7, "Should be a function" );
    /* Stack item 8 is the callback data */
    httpd_file_sys_t *p_sys = (httpd_file_sys_t *)
                              malloc( sizeof( httpd_file_sys_t ) );
    if( !p_sys )
        return luaL_error( L, "Failed to allocate private buffer." );
    p_sys->L = lua_newthread( L );
    p_sys->ref = luaL_ref( L, LUA_REGISTRYINDEX ); /* pops the object too */
    lua_xmove( L, p_sys->L, 2 );
    httpd_file_t *p_file = httpd_FileNew( *pp_host, psz_url, psz_mime,
                                          psz_user, psz_password,
                                          pp_acl?*pp_acl:NULL,
                                          vlclua_httpd_file_callback, p_sys );
    if( !p_file )
    {
        free( p_sys );
        return luaL_error( L, "Failed to create HTTPd file." );
    }

    httpd_file_t **pp_file = lua_newuserdata( L, sizeof( httpd_file_t * ) );
    *pp_file = p_file;

    if( luaL_newmetatable( L, "httpd_file" ) )
    {
        lua_pushcfunction( L, vlclua_httpd_file_delete );
        lua_setfield( L, -2, "__gc" );
    }

    lua_setmetatable( L, -2 );
    return 1;
}
Exemple #2
0
/*****************************************************************************
 * HTTPOpen: Start the internal HTTP server
 *****************************************************************************/
int E_(HTTPOpen)( access_t *p_access )
{
#define FREE( x )                                                           \
    if ( (x) != NULL )                                                      \
        free( x );

    access_sys_t *p_sys = p_access->p_sys;
    char          *psz_address, *psz_cert = NULL, *psz_key = NULL,
                                 *psz_ca = NULL, *psz_crl = NULL, *psz_user = NULL,
                                  *psz_password = NULL, *psz_acl = NULL;
    int           i_port       = 0;
    char          psz_tmp[10];
    vlc_acl_t     *p_acl = NULL;
    httpd_file_sys_t *f;

    vlc_mutex_init( p_access, &p_sys->httpd_mutex );
    vlc_cond_init( p_access, &p_sys->httpd_cond );
    p_sys->b_request_frontend_info = p_sys->b_request_mmi_info = VLC_FALSE;
    p_sys->i_httpd_timeout = 0;

    psz_address = var_GetString( p_access, "dvb-http-host" );
    if( psz_address != NULL && *psz_address )
    {
        char *psz_parser = strchr( psz_address, ':' );
        if( psz_parser )
        {
            *psz_parser++ = '\0';
            i_port = atoi( psz_parser );
        }
    }
    else
    {
        if ( psz_address != NULL ) free( psz_address );
        return VLC_SUCCESS;
    }

    /* determine SSL configuration */
    psz_cert = var_GetString( p_access, "dvb-http-intf-cert" );
    if ( psz_cert != NULL && *psz_cert )
    {
        msg_Dbg( p_access, "enabling TLS for HTTP interface (cert file: %s)",
                 psz_cert );
        psz_key = config_GetPsz( p_access, "dvb-http-intf-key" );
        psz_ca = config_GetPsz( p_access, "dvb-http-intf-ca" );
        psz_crl = config_GetPsz( p_access, "dvb-http-intf-crl" );

        if ( i_port <= 0 )
            i_port = 8443;
    }
    else
    {
        if ( !*psz_cert )
        {
            free( psz_cert );
            psz_cert = NULL;
        }
        if ( i_port <= 0 )
            i_port= 8082;
    }

    /* Ugly hack to allow to run several HTTP servers on different ports. */
    sprintf( psz_tmp, ":%d", i_port + 1 );
    config_PutPsz( p_access, "dvb-http-host", psz_tmp );

    msg_Dbg( p_access, "base %s:%d", psz_address, i_port );

    p_sys->p_httpd_host = httpd_TLSHostNew( VLC_OBJECT(p_access), psz_address,
                                            i_port, psz_cert, psz_key, psz_ca,
                                            psz_crl );
    FREE( psz_cert );
    FREE( psz_key );
    FREE( psz_ca );
    FREE( psz_crl );

    if ( p_sys->p_httpd_host == NULL )
    {
        msg_Err( p_access, "cannot listen on %s:%d", psz_address, i_port );
        free( psz_address );
        return VLC_EGENERIC;
    }
    free( psz_address );

    psz_user = var_GetString( p_access, "dvb-http-user" );
    psz_password = var_GetString( p_access, "dvb-http-password" );
    psz_acl = var_GetString( p_access, "dvb-http-acl" );

    if ( psz_acl != NULL )
    {
        p_acl = ACL_Create( p_access, VLC_FALSE );
        if( ACL_LoadFile( p_acl, psz_acl ) )
        {
            ACL_Destroy( p_acl );
            p_acl = NULL;
        }
    }

    /* Declare an index.html file. */
    f = malloc( sizeof(httpd_file_sys_t) );
    f->p_access = p_access;
    f->p_file = httpd_FileNew( p_sys->p_httpd_host, "/index.html",
                               "text/html; charset=UTF-8",
                               psz_user, psz_password, p_acl,
                               HttpCallback, f );

    FREE( psz_user );
    FREE( psz_password );
    FREE( psz_acl );
    if ( p_acl != NULL )
        ACL_Destroy( p_acl );

    if ( f->p_file == NULL )
    {
        free( f );
        p_sys->p_httpd_file = NULL;
        return VLC_EGENERIC;
    }

    p_sys->p_httpd_file = f;
    p_sys->p_httpd_redir = httpd_RedirectNew( p_sys->p_httpd_host,
                           "/index.html", "/" );

#undef FREE

    return VLC_SUCCESS;
}
Exemple #3
0
/* Parse a directory and recursively add files */
int ParseDirectory( intf_thread_t *p_intf, char *psz_root,
                        char *psz_dir )
{
    intf_sys_t     *p_sys = p_intf->p_sys;
    char           dir[MAX_DIR_SIZE];
    DIR           *p_dir;
    vlc_acl_t     *p_acl;
    FILE          *file;

    char          *user = NULL;
    char          *password = NULL;

    int           i_dirlen;

    if( ( p_dir = utf8_opendir( psz_dir ) ) == NULL )
    {
        if( errno != ENOENT && errno != ENOTDIR )
            msg_Err( p_intf, "cannot open directory (%s)", psz_dir );
        return VLC_EGENERIC;
    }

    i_dirlen = strlen( psz_dir );
    if( i_dirlen + 10 > MAX_DIR_SIZE )
    {
        msg_Warn( p_intf, "skipping too deep directory (%s)", psz_dir );
        closedir( p_dir );
        return 0;
    }

    msg_Dbg( p_intf, "dir=%s", psz_dir );

    snprintf( dir, sizeof( dir ), "%s"DIR_SEP".access", psz_dir );
    if( ( file = utf8_fopen( dir, "r" ) ) != NULL )
    {
        char line[1024];
        int  i_size;

        msg_Dbg( p_intf, "find .access in dir=%s", psz_dir );

        i_size = fread( line, 1, 1023, file );
        if( i_size > 0 )
        {
            char *p;
            while( i_size > 0 && ( line[i_size-1] == '\n' ||
                   line[i_size-1] == '\r' ) )
            {
                i_size--;
            }

            line[i_size] = '\0';

            p = strchr( line, ':' );
            if( p )
            {
                *p++ = '\0';
                user = strdup( line );
                password = strdup( p );
            }
        }
        msg_Dbg( p_intf, "using user=%s (read=%d)", user, i_size );

        fclose( file );
    }

    snprintf( dir, sizeof( dir ), "%s"DIR_SEP".hosts", psz_dir );
    p_acl = ACL_Create( p_intf, false );
    if( ACL_LoadFile( p_acl, dir ) )
    {
        ACL_Destroy( p_acl );

        struct stat st;
        if( utf8_stat( dir, &st ) == 0 )
        {
            free( user );
            free( password );
            closedir( p_dir );
            return VLC_EGENERIC;
        }
        p_acl = NULL;
    }

    for( ;; )
    {
        char *psz_filename;
        /* parse psz_src dir */
        if( ( psz_filename = utf8_readdir( p_dir ) ) == NULL )
        {
            break;
        }

        if( ( psz_filename[0] == '.' )
         || ( i_dirlen + strlen( psz_filename ) > MAX_DIR_SIZE ) )
        {
            free( psz_filename );
            continue;
        }

        snprintf( dir, sizeof( dir ), "%s"DIR_SEP"%s", psz_dir, psz_filename );
        free( psz_filename );

        if( ParseDirectory( p_intf, psz_root, dir ) )
        {
            httpd_file_sys_t *f = NULL;
            httpd_handler_sys_t *h = NULL;
            bool b_index;
            char *psz_name, *psz_ext;

            psz_name = FileToUrl( &dir[strlen( psz_root )], &b_index );
            psz_ext = strrchr( dir, '.' );
            if( psz_ext != NULL )
            {
                int i;
                psz_ext++;
                for( i = 0; i < p_sys->i_handlers; i++ )
                    if( !strcmp( p_sys->pp_handlers[i]->psz_ext, psz_ext ) )
                        break;
                if( i < p_sys->i_handlers )
                {
                    f = malloc( sizeof( httpd_handler_sys_t ) );
                    h = (httpd_handler_sys_t *)f;
                    f->b_handler = true;
                    h->p_association = p_sys->pp_handlers[i];
                }
            }
            if( f == NULL )
            {
                f = malloc( sizeof( httpd_file_sys_t ) );
                f->b_handler = false;
            }

            f->p_intf  = p_intf;
            f->p_file = NULL;
            f->p_redir = NULL;
            f->p_redir2 = NULL;
            f->file = strdup (dir);
            f->name = psz_name;
            f->b_html = strstr( &dir[strlen( psz_root )], ".htm" ) || strstr( &dir[strlen( psz_root )], ".xml" ) ? true : false;

            if( !f->name )
            {
                msg_Err( p_intf , "unable to parse directory" );
                closedir( p_dir );
                free( f );
                return( VLC_ENOMEM );
            }
            msg_Dbg( p_intf, "file=%s (url=%s)",
                     f->file, f->name );

            if( !f->b_handler )
            {
                char *psz_type = strdup( "text/html; charset=UTF-8" );
                if( strstr( &dir[strlen( psz_root )], ".xml" ) )
                {
                    char *psz = strstr( psz_type, "html;" );
                    if( psz )
                    {
                        psz[0] = 'x';
                        psz[1] = 'm';
                        psz[2] = 'l';
                        psz[3] = ';';
                        psz[4] = ' ';
                    }
                }
                f->p_file = httpd_FileNew( p_sys->p_httpd_host,
                                           f->name,
                                           f->b_html ? psz_type : NULL,
                                           user, password, p_acl,
                                           HttpCallback, f );
                free( psz_type );
                if( f->p_file != NULL )
                {
                    TAB_APPEND( p_sys->i_files, p_sys->pp_files, f );
                }
            }
            else
            {
                h->p_handler = httpd_HandlerNew( p_sys->p_httpd_host,
                                                 f->name,
                                                 user, password, p_acl,
                                                 HandlerCallback, h );
                if( h->p_handler != NULL )
                {
                    TAB_APPEND( p_sys->i_files, p_sys->pp_files,
                                (httpd_file_sys_t *)h );
                }
            }

            /* for url that ends by / add
             *  - a redirect from rep to rep/
             *  - in case of index.* rep/index.html to rep/ */
            if( f && f->name[strlen(f->name) - 1] == '/' )
            {
                char *psz_redir = strdup( f->name );
                char *p;
                psz_redir[strlen( psz_redir ) - 1] = '\0';

                msg_Dbg( p_intf, "redir=%s -> %s", psz_redir, f->name );
                f->p_redir = httpd_RedirectNew( p_sys->p_httpd_host, f->name, psz_redir );
                free( psz_redir );

                if( b_index && ( p = strstr( f->file, "index." ) ) )
                {
                    if( asprintf( &psz_redir, "%s%s", f->name, p ) != -1 )
                    {
                        msg_Dbg( p_intf, "redir=%s -> %s", psz_redir, f->name );
                        f->p_redir2 = httpd_RedirectNew( p_sys->p_httpd_host,
                                                         f->name, psz_redir );

                        free( psz_redir );
                    }
                }
            }
        }
    }

    free( user );
    free( password );

    ACL_Destroy( p_acl );
    closedir( p_dir );

    return VLC_SUCCESS;
}