/***************************************************************************** * DirRead: *****************************************************************************/ static input_item_t* DirRead (access_t *p_access ) { access_sys_t *p_sys = p_access->p_sys; struct smbc_dirent *p_entry; input_item_t *p_item = NULL; while( !p_item && ( p_entry = smbc_readdir( p_sys->i_smb ) ) ) { char *psz_uri; const char *psz_server = p_sys->url.psz_host; const char *psz_path = p_sys->url.psz_path; const char *psz_name = p_entry->name; int i_type; switch( p_entry->smbc_type ) { case SMBC_SERVER: case SMBC_WORKGROUP: psz_server = p_sys->url.psz_host; psz_path = NULL; psz_name = NULL; case SMBC_FILE_SHARE: case SMBC_DIR: i_type = ITEM_TYPE_DIRECTORY; break; case SMBC_FILE: i_type = ITEM_TYPE_FILE; break; default: case SMBC_PRINTER_SHARE: case SMBC_COMMS_SHARE: case SMBC_IPC_SHARE: case SMBC_LINK: continue; } char *psz_encoded_name = NULL; if( psz_name != NULL && ( psz_encoded_name = vlc_uri_encode( psz_name ) ) == NULL ) return NULL; if( smb_get_uri( p_access, &psz_uri, NULL, NULL, NULL, psz_server, psz_path, psz_encoded_name ) < 0 ) { free(psz_encoded_name); return NULL; } free(psz_encoded_name); p_item = input_item_NewExt( psz_uri, p_entry->name, -1, i_type, ITEM_NET ); free( psz_uri ); if( !p_item ) return NULL; } return p_item; }
/***************************************************************************** * DirRead: *****************************************************************************/ static int DirRead (stream_t *p_access, input_item_node_t *p_node ) { access_sys_t *p_sys = p_access->p_sys; int i_ret = VLC_SUCCESS; struct vlc_readdir_helper rdh; vlc_readdir_helper_init( &rdh, p_access, p_node ); #ifndef _WIN32 struct smbc_dirent *p_entry; while( i_ret == VLC_SUCCESS && ( p_entry = smbc_readdir( p_sys->i_smb ) ) ) { char *psz_uri; const char *psz_server = p_sys->url.psz_host; const char *psz_path = p_sys->url.psz_path; const char *psz_name = p_entry->name; int i_type; switch( p_entry->smbc_type ) { case SMBC_SERVER: case SMBC_WORKGROUP: psz_server = p_sys->url.psz_host; psz_path = NULL; psz_name = NULL; case SMBC_FILE_SHARE: case SMBC_DIR: i_type = ITEM_TYPE_DIRECTORY; break; case SMBC_FILE: i_type = ITEM_TYPE_FILE; break; default: case SMBC_PRINTER_SHARE: case SMBC_COMMS_SHARE: case SMBC_IPC_SHARE: case SMBC_LINK: continue; } char *psz_encoded_name = NULL; if( psz_name != NULL && ( psz_encoded_name = vlc_uri_encode( psz_name ) ) == NULL ) { i_ret = VLC_ENOMEM; break; } if( smb_get_uri( p_access, &psz_uri, NULL, NULL, NULL, psz_server, psz_path, psz_encoded_name ) < 0 ) { free(psz_encoded_name); i_ret = VLC_ENOMEM; break; } free(psz_encoded_name); i_ret = vlc_readdir_helper_additem( &rdh, psz_uri, NULL, p_entry->name, i_type, ITEM_NET ); free( psz_uri ); } #else // Handle share listing from here. Directory browsing is handled by the // usual filesystem module. SHARE_INFO_1 *p_info; DWORD i_share_enum_res; DWORD i_nb_elem; DWORD i_resume_handle = 0; DWORD i_total_elements; // Unused, but needs to be passed wchar_t *wpsz_host = ToWide( p_sys->url.psz_host ); if( wpsz_host == NULL ) return VLC_ENOMEM; do { i_share_enum_res = NetShareEnum( wpsz_host, 1, (LPBYTE*)&p_info, MAX_PREFERRED_LENGTH, &i_nb_elem, &i_total_elements, &i_resume_handle ); if( i_share_enum_res == ERROR_SUCCESS || i_share_enum_res == ERROR_MORE_DATA ) { for ( DWORD i = 0; i < i_nb_elem; ++i ) { SHARE_INFO_1 *p_current = p_info + i; if( p_current->shi1_type & STYPE_SPECIAL ) continue; char* psz_name = FromWide( p_current->shi1_netname ); if( psz_name == NULL ) { i_ret = VLC_ENOMEM; break; } char* psz_path; if( smb_get_uri( p_access, &psz_path, NULL, NULL, NULL, p_sys->url.psz_host, p_sys->url.psz_path, psz_name ) < 0 ) { free( psz_name ); i_ret = VLC_ENOMEM; break; } free( psz_name ); // We need to concatenate the scheme before, as the window version // of smb_get_uri generates a path (and the other call site needs // a path). The path is already prefixed by "//" so we just need // to add "file:" char* psz_uri; if( asprintf( &psz_uri, "file:%s", psz_path ) < 0 ) { free( psz_path ); i_ret = VLC_ENOMEM; break; } free( psz_path ); i_ret = vlc_readdir_helper_additem( &rdh, psz_uri, NULL, psz_name, ITEM_TYPE_DIRECTORY, ITEM_NET ); free( psz_uri ); } } NetApiBufferFree( p_info ); } while( i_share_enum_res == ERROR_MORE_DATA && i_ret == VLC_SUCCESS ); free( wpsz_host ); #endif vlc_readdir_helper_finish( &rdh, i_ret == VLC_SUCCESS ); return i_ret; }
/**************************************************************************** * Open: connect to smb server and ask for file ****************************************************************************/ static int Open( vlc_object_t *p_this ) { stream_t *p_access = (stream_t*)p_this; access_sys_t *p_sys; struct stat filestat; vlc_url_t url; vlc_credential credential; char *psz_decoded_path = NULL, *psz_uri = NULL, *psz_var_domain = NULL; int i_ret; int i_smb; uint64_t i_size; bool b_is_dir = false; #ifndef _WIN32 if( smbc_init( smb_auth, 0 ) ) return VLC_EGENERIC; #endif /* ** some version of glibc defines open as a macro, causing havoc ** with other macros using 'open' under the hood, such as the ** following one: */ #if defined(smbc_open) && defined(open) # undef open #endif vlc_UrlParse( &url, p_access->psz_url ); if( url.psz_path ) { psz_decoded_path = vlc_uri_decode_duplicate( url.psz_path ); if( !psz_decoded_path ) { vlc_UrlClean( &url ); return VLC_EGENERIC; } } vlc_credential_init( &credential, &url ); psz_var_domain = var_InheritString( p_access, "smb-domain" ); credential.psz_realm = psz_var_domain; vlc_credential_get( &credential, p_access, "smb-user", "smb-pwd", NULL, NULL ); for (;;) { if( smb_get_uri( p_access, &psz_uri, credential.psz_realm, credential.psz_username, credential.psz_password, url.psz_host, psz_decoded_path, NULL ) == -1 ) { vlc_credential_clean( &credential ); free(psz_var_domain); free( psz_decoded_path ); vlc_UrlClean( &url ); return VLC_ENOMEM; } if( ( i_ret = smbc_stat( psz_uri, &filestat ) ) && errno == EACCES ) { errno = 0; if( vlc_credential_get( &credential, p_access, "smb-user", "smb-pwd", SMB_LOGIN_DIALOG_TITLE, SMB_LOGIN_DIALOG_TEXT, url.psz_host) ) continue; } /* smbc_stat fails with servers or shares. Assume they are directory */ if( i_ret || S_ISDIR( filestat.st_mode ) ) b_is_dir = true; break; } vlc_credential_store( &credential, p_access ); vlc_credential_clean( &credential ); free(psz_var_domain); free( psz_decoded_path ); /* Init p_access */ p_sys = p_access->p_sys = vlc_calloc( p_this, 1, sizeof( access_sys_t ) ); if( !p_sys ) { free( psz_uri ); vlc_UrlClean( &url ); return VLC_ENOMEM; } if( b_is_dir ) { p_sys->url = url; p_access->pf_readdir = DirRead; p_access->pf_control = access_vaDirectoryControlHelper; i_size = 0; #ifndef _WIN32 i_smb = smbc_opendir( psz_uri ); if( i_smb < 0 ) vlc_UrlClean( &p_sys->url ); #endif } else { ACCESS_SET_CALLBACKS( Read, NULL, Control, Seek ); i_smb = smbc_open( psz_uri, O_RDONLY, 0 ); i_size = filestat.st_size; vlc_UrlClean( &url ); } free( psz_uri ); #ifndef _WIN32 if( i_smb < 0 ) { msg_Err( p_access, "open failed for '%s' (%s)", p_access->psz_location, vlc_strerror_c(errno) ); return VLC_EGENERIC; } #endif p_sys->size = i_size; p_sys->i_smb = i_smb; return VLC_SUCCESS; }
static int Open(vlc_object_t *obj) { stream_t *access = (stream_t *)obj; vlc_url_t url; vlc_credential credential; char *psz_decoded_path = NULL, *psz_uri = NULL, *psz_var_domain = NULL; int fd; uint64_t size; bool is_dir; if (vlc_UrlParseFixup(&url, access->psz_url) != 0) { vlc_UrlClean(&url); return VLC_EGENERIC; } if (url.psz_path != NULL) { psz_decoded_path = vlc_uri_decode_duplicate(url.psz_path); if (psz_decoded_path == NULL) { vlc_UrlClean(&url); return VLC_EGENERIC; } } vlc_credential_init(&credential, &url); psz_var_domain = var_InheritString(access, "smb-domain"); credential.psz_realm = psz_var_domain; vlc_credential_get(&credential, access, "smb-user", "smb-pwd", NULL, NULL); for (;;) { struct stat st; if (smb_get_uri(access, &psz_uri, credential.psz_realm, credential.psz_username, credential.psz_password, url.psz_host, psz_decoded_path, NULL ) == -1 ) { vlc_credential_clean(&credential); free(psz_var_domain); free(psz_decoded_path); vlc_UrlClean(&url); return VLC_ENOMEM; } if (stat(psz_uri, &st) == 0) { is_dir = S_ISDIR(st.st_mode) != 0; size = st.st_size; break; } /* stat() fails with servers or shares. Assume directory. */ is_dir = true; size = 0; if (errno != EACCES) break; errno = 0; if (!vlc_credential_get(&credential, access, "smb-user", "smb-pwd", SMB_LOGIN_DIALOG_TITLE, SMB_LOGIN_DIALOG_TEXT, url.psz_host)) break; } vlc_credential_store(&credential, access); vlc_credential_clean(&credential); free(psz_var_domain); free(psz_decoded_path); /* Init access */ access_sys_t *sys = vlc_obj_calloc(obj, 1, sizeof (*sys)); if (unlikely(sys == NULL)) { free(psz_uri); vlc_UrlClean(&url); return VLC_ENOMEM; } access->p_sys = sys; if (is_dir) { sys->url = url; access->pf_readdir = DirRead; access->pf_control = access_vaDirectoryControlHelper; } else { access->pf_read = Read; access->pf_control = Control; access->pf_seek = Seek; fd = open(psz_uri, O_RDONLY, 0); vlc_UrlClean(&url); } free(psz_uri); sys->size = size; sys->i_smb = fd; return VLC_SUCCESS; }
static int DirRead(stream_t *p_access, input_item_node_t *p_node) { access_sys_t *p_sys = p_access->p_sys; int i_ret = VLC_SUCCESS; struct vlc_readdir_helper rdh; vlc_readdir_helper_init( &rdh, p_access, p_node ); // Handle share listing from here. Directory browsing is handled by the // usual filesystem module. SHARE_INFO_1 *p_info; DWORD i_share_enum_res; DWORD i_nb_elem; DWORD i_resume_handle = 0; DWORD i_total_elements; // Unused, but needs to be passed wchar_t *wpsz_host = ToWide( p_sys->url.psz_host ); if( wpsz_host == NULL ) return VLC_ENOMEM; do { i_share_enum_res = NetShareEnum( wpsz_host, 1, (LPBYTE*)&p_info, MAX_PREFERRED_LENGTH, &i_nb_elem, &i_total_elements, &i_resume_handle ); if( i_share_enum_res == ERROR_SUCCESS || i_share_enum_res == ERROR_MORE_DATA ) { for ( DWORD i = 0; i < i_nb_elem; ++i ) { SHARE_INFO_1 *p_current = p_info + i; if( p_current->shi1_type & STYPE_SPECIAL ) continue; char* psz_name = FromWide( p_current->shi1_netname ); if( psz_name == NULL ) { i_ret = VLC_ENOMEM; break; } char* psz_path; if( smb_get_uri( p_access, &psz_path, NULL, NULL, NULL, p_sys->url.psz_host, p_sys->url.psz_path, psz_name ) < 0 ) { free( psz_name ); i_ret = VLC_ENOMEM; break; } // We need to concatenate the scheme before, as the window version // of smb_get_uri generates a path (and the other call site needs // a path). The path is already prefixed by "//" so we just need // to add "file:" char* psz_uri; if( asprintf( &psz_uri, "file:%s", psz_path ) < 0 ) { free( psz_name ); free( psz_path ); i_ret = VLC_ENOMEM; break; } free( psz_path ); i_ret = vlc_readdir_helper_additem( &rdh, psz_uri, NULL, psz_name, ITEM_TYPE_DIRECTORY, ITEM_NET ); free( psz_name ); free( psz_uri ); } } NetApiBufferFree( p_info ); } while( i_share_enum_res == ERROR_MORE_DATA && i_ret == VLC_SUCCESS ); free( wpsz_host ); vlc_readdir_helper_finish( &rdh, i_ret == VLC_SUCCESS ); return i_ret; }