bool getConfigDoubleValue(char * buf,char *key,double &val) { int bufLen = (int)strlen(buf); int keyLen = (int)strlen(key); int start = findStr(buf,key,bufLen,keyLen); int valueStart = start+keyLen; int end = findStr(buf,"\n",bufLen,1,valueStart); if(start == -1 || end == -1) { return false; } char str[500] = {0}; int i,j; if(end - valueStart >= 500) { return false; } for(i = valueStart,j = 0; i < end; i++,j++) { str[j] = buf[i]; } str[end] = 0; val = atof(str); return true; }
static void doWork(Crew *crew, Work *work) { int status; struct stat filestat; struct dirent *dirbuf; status = lstat(work->path, &filestat); if (status != 0) return; if (S_ISDIR(filestat.st_mode)) { DIR *pDir = opendir(work->path); if (pDir == NULL) { return; } while ((dirbuf = readdir(pDir)) != NULL) { if (strcmp(dirbuf->d_name, ".") == 0 || strcmp(dirbuf->d_name, "..") == 0) { continue; } status = pthread_mutex_lock(&crew->mutex); if (status != 0) return; addWork(crew, work->path, dirbuf->d_name, work->string); status = pthread_cond_signal(&crew->go); if (status != 0) return; status = pthread_mutex_unlock(&crew->mutex); if (status != 0) return; } } else if (S_ISREG(filestat.st_mode)) { findStr(work); } }
bool getConfigMapTable(char * buf,char *key,int *dstTable,int dstLen) { int bufLen = (int)strlen(buf); int keyLen = (int)strlen(key); int start = findStr(buf,key,bufLen,keyLen); int valueStart = start+keyLen; int end = findStr(buf,"\n",bufLen,1,valueStart); if(start == -1 || end == -1) { return false; } char str[500]; if(end - valueStart >= 500) { return false; } int i,j; int idx = 0; int x = 0; for(i = valueStart,j = 0; i <= end; i++,j++) { if(buf[i] == ',' || buf[i] == '\n') { str[x] = 0; x = -1; if(idx >= dstLen) { return false; } dstTable[idx++] = atoi(str); } else { str[x] = buf[i]; } x++; } return true; }
bool getConfigStrValue(char * buf,char *key,char *dstStr,int dstLen) { int bufLen = (int)strlen(buf); int keyLen = (int)strlen(key); int start = findStr(buf,key,bufLen,keyLen); int valueStart = start+keyLen; int end = findStr(buf,"\n",bufLen,1,valueStart); if(start == -1 || end == -1) { return false; } if(end - valueStart >= dstLen) { return false; } int i,j; for(i = valueStart,j = 0; i < end; i++,j++) { dstStr[j] = buf[i]; } dstStr[end] = 0; return true; }
void IniFile::parseText(BufInputStream& txtFile) { //txtFile.seek(0, skBegin); clearList(); const char notesFlag = ';'; String strLine; while (txtFile.readLine(strLine)) { trimTo(strLine); String& strTmp=strLine; long strTmp_size=(long)strTmp.size(); //Notes if ((strTmp_size > 0) && (notesFlag != strTmp[0])) { //Section if (strTmp_size >= 2) { if ((sectionStart == strTmp[0]) && (sectionEnd == strTmp[strTmp_size - 1])) { String strSection; trim(strTmp.c_str()+1,strTmp_size-2,strSection); m_sctList.push_back(Section(strSection)); } else { long nIdxSpace = findStr(strTmp, valSpace); if (nIdxSpace >= 0) { String strKey; trim(strTmp.c_str(),nIdxSpace,strKey); String strVal; if ((nIdxSpace + 1) < strTmp_size) trim(strTmp.c_str()+nIdxSpace + 1,strTmp_size - nIdxSpace - 1,strVal); getBackSection()->list.push_back(IniValue(strKey, strVal)); } //else getBackSection()->list.push_back(IniValue(strLine)); } } //else getBackSection()->list.push_back(IniValue(strLine)); } else { getBackSection()->list.push_back(IniValue(strLine)); } } }
SearchData FindInFilesDialog::DoGetSearchData() { SearchData data; wxString findStr(m_data.GetFindString()); if(m_findString->GetValue().IsEmpty() == false) { findStr = m_findString->GetValue(); } data.SetFindString(findStr); m_data.SetFlags(GetSearchFlags()); size_t flags = m_data.GetFlags(); // If the 'Skip comments' is ON, remove the // 'colour comments' flag if(flags & wxFRD_SKIP_COMMENTS) { flags &= ~wxFRD_COLOUR_COMMENTS; } data.SetMatchCase((flags & wxFRD_MATCHCASE) != 0); data.SetMatchWholeWord((flags & wxFRD_MATCHWHOLEWORD) != 0); data.SetRegularExpression((flags & wxFRD_REGULAREXPRESSION) != 0); data.SetDisplayScope((flags & wxFRD_DISPLAYSCOPE) != 0); data.SetEncoding(m_choiceEncoding->GetStringSelection()); data.SetSkipComments(flags & wxFRD_SKIP_COMMENTS); data.SetSkipStrings(flags & wxFRD_SKIP_STRINGS); data.SetColourComments(flags & wxFRD_COLOUR_COMMENTS); wxArrayString rootDirs; for(size_t i = 0; i < m_listPaths->GetCount(); ++i) { rootDirs.push_back(m_listPaths->GetString(i)); } if(rootDirs.IsEmpty()) { wxString dir = m_dirPicker->GetPath(); if(dir.IsEmpty() == false) { rootDirs.push_back(dir); } } data.SetRootDirs(rootDirs); wxArrayString files; for(size_t i = 0; i < rootDirs.GetCount(); ++i) { const wxString& rootDir = rootDirs.Item(i); // Check both translations and otherwise: the history may contain either if((rootDir == wxGetTranslation(SEARCH_IN_WORKSPACE)) || (rootDir == SEARCH_IN_WORKSPACE)) { ManagerST::Get()->GetWorkspaceFiles(files); } else if((rootDir == wxGetTranslation(SEARCH_IN_PROJECT)) || (rootDir == SEARCH_IN_PROJECT)) { ManagerST::Get()->GetActiveProjectFiles(files); } else if((rootDir == wxGetTranslation(SEARCH_IN_CURR_FILE_PROJECT)) || (rootDir == SEARCH_IN_CURR_FILE_PROJECT)) { ManagerST::Get()->GetActiveFileProjectFiles(files); } else if((rootDir == wxGetTranslation(SEARCH_IN_CURRENT_FILE)) || (rootDir == SEARCH_IN_CURRENT_FILE)) { LEditor* editor = clMainFrame::Get()->GetMainBook()->GetActiveEditor(); if(editor) { files.Add(editor->GetFileName().GetFullPath()); } } else if((rootDir == wxGetTranslation(SEARCH_IN_OPEN_FILES)) || (rootDir == SEARCH_IN_OPEN_FILES)) { std::vector<LEditor*> editors; clMainFrame::Get()->GetMainBook()->GetAllEditors(editors, MainBook::kGetAll_IncludeDetached); for(size_t n = 0; n < editors.size(); ++n) { LEditor* editor = dynamic_cast<LEditor*>(*(editors.begin() + n)); if(editor) { files.Add(editor->GetFileName().GetFullPath()); } } } } data.SetFiles(files); data.UseNewTab(m_checkBoxSeparateTab->IsChecked()); data.SetExtensions(m_fileTypes->GetValue()); return data; }
SearchData FindInFilesDialog::DoGetSearchData() { SearchData data; wxString findStr(m_data.GetFindString()); if(!m_findString->GetValue().IsEmpty()) { findStr = m_findString->GetValue(); } data.SetFindString(findStr); data.SetReplaceWith(m_replaceString->GetValue()); m_data.SetFlags(GetSearchFlags()); size_t flags = m_data.GetFlags(); // If the 'Skip comments' is ON, remove the // 'colour comments' flag if(flags & wxFRD_SKIP_COMMENTS) { flags &= ~wxFRD_COLOUR_COMMENTS; } data.SetMatchCase((flags & wxFRD_MATCHCASE) != 0); data.SetMatchWholeWord((flags & wxFRD_MATCHWHOLEWORD) != 0); data.SetRegularExpression((flags & wxFRD_REGULAREXPRESSION) != 0); data.SetDisplayScope((flags & wxFRD_DISPLAYSCOPE) != 0); data.SetEncoding(m_choiceEncoding->GetStringSelection()); data.SetSkipComments(flags & wxFRD_SKIP_COMMENTS); data.SetSkipStrings(flags & wxFRD_SKIP_STRINGS); data.SetColourComments(flags & wxFRD_COLOUR_COMMENTS); data.SetEnablePipeSupport(flags & wxFRD_ENABLE_PIPE_SUPPORT); wxArrayString searchWhere = m_listPaths->GetStrings(); wxArrayString files; wxArrayString rootDirs; for(size_t i = 0; i < searchWhere.GetCount(); ++i) { const wxString& rootDir = searchWhere.Item(i); // Check both translations and otherwise: the history may contain either if((rootDir == wxGetTranslation(SEARCH_IN_WORKSPACE)) || (rootDir == SEARCH_IN_WORKSPACE)) { if(!clWorkspaceManager::Get().IsWorkspaceOpened()) continue; clWorkspaceManager::Get().GetWorkspace()->GetWorkspaceFiles(files); } else if((rootDir == wxGetTranslation(SEARCH_IN_PROJECT)) || (rootDir == SEARCH_IN_PROJECT)) { if(!clWorkspaceManager::Get().IsWorkspaceOpened()) continue; if(clWorkspaceManager::Get().GetWorkspace()->IsProjectSupported()) { // get the active project files clWorkspaceManager::Get().GetWorkspace()->GetProjectFiles("", files); } else { // search the entire workspace clWorkspaceManager::Get().GetWorkspace()->GetWorkspaceFiles(files); } } else if((rootDir == wxGetTranslation(SEARCH_IN_CURR_FILE_PROJECT)) || (rootDir == SEARCH_IN_CURR_FILE_PROJECT)) { if(!clWorkspaceManager::Get().IsWorkspaceOpened()) continue; IEditor* editor = clGetManager()->GetActiveEditor(); if(!editor) continue; if(clWorkspaceManager::Get().GetWorkspace()->IsProjectSupported()) { wxString projectName = clWorkspaceManager::Get().GetWorkspace()->GetProjectFromFile(editor->GetFileName()); clWorkspaceManager::Get().GetWorkspace()->GetProjectFiles(projectName, files); } else { // search the entire workspace clWorkspaceManager::Get().GetWorkspace()->GetWorkspaceFiles(files); } } else if((rootDir == wxGetTranslation(SEARCH_IN_CURRENT_FILE)) || (rootDir == SEARCH_IN_CURRENT_FILE)) { LEditor* editor = clMainFrame::Get()->GetMainBook()->GetActiveEditor(); if(editor) { files.Add(editor->GetFileName().GetFullPath()); } } else if((rootDir == wxGetTranslation(SEARCH_IN_OPEN_FILES)) || (rootDir == SEARCH_IN_OPEN_FILES)) { std::vector<LEditor*> editors; clMainFrame::Get()->GetMainBook()->GetAllEditors(editors, MainBook::kGetAll_IncludeDetached); for(size_t n = 0; n < editors.size(); ++n) { LEditor* editor = dynamic_cast<LEditor*>(*(editors.begin() + n)); if(editor) { files.Add(editor->GetFileName().GetFullPath()); } } } else if(wxFileName::DirExists(searchWhere.Item(i))) { rootDirs.Add(searchWhere.Item(i)); } } // Remove duplicates wxStringSet_t filesSet; wxArrayString uniqueFiles; std::for_each(files.begin(), files.end(), [&](const wxString& file) { if(filesSet.count(file) == 0) { filesSet.insert(file); uniqueFiles.Add(file); } }); files.swap(uniqueFiles); data.SetFiles(files); // list of files data.SetRootDirs(rootDirs); // folders data.UseNewTab(false); data.SetExtensions(m_fileTypes->GetValue()); return data; }
// Smooth Streaming On Demand Publisher int smoothstreamingSSP(con_t *con, const char *uriData, int uriLen, \ const ssp_config_t *ssp_cfg, \ off_t contentLen, const char *dataBuf, int bufLen) { const char *uri; char *p_qpos, *p_fpos, *p_cmpos; char *manifest_uri, *media_uri; const char *video_qparam_name, *audio_qparam_name; uint8_t track_type, mfro[16]; uint16_t pos=0, track_id; uint32_t manifest_uri_size=0; uint32_t bit_rate; uint64_t time_offset=0; uint32_t box_size; size_t mfra_off=0, moof_size=0, moof_offset=0, moof_time=0; xml_read_ctx_t *ism; ism_bitrate_map_t *map; ismv_parser_ctx_t *ctx; int remap_len=0, rv, err; const char *tmpData; int tmpLen=0, tmpCnt=0; unsigned int tmpAttrs=0; http_cb_t *phttp = &con->http; // Obtain the relative URL length stripped of all query params if ( (remap_len = findStr(uriData, "?", uriLen)) == -1 ) { remap_len = uriLen; } if ( ssp_cfg->smoothstream_pub.quality_tag == NULL || \ ssp_cfg->smoothstream_pub.fragment_tag == NULL ) { DBG_LOG(ERROR, MOD_SSP, "Required Quality/Frag tags unspecified in CLI, exiting..."); return -NKN_SSP_CLI_PARAM_UNSPECIFIED; } // If request is for client manifest (.ismc is requested as .ism/Manifest) // Rebase URI and return p_cmpos = strcasestr(uriData, ".ism/Manifest"); if ( p_cmpos != NULL ) { manifest_uri_size = p_cmpos - uriData + strlen(".ismc") + SSP_MAX_EXTENSION_SZ; manifest_uri = (char *)alloca(manifest_uri_size); memset(manifest_uri, 0, manifest_uri_size); manifest_uri[0]='\0'; strncat(manifest_uri, uriData, (p_cmpos-uriData) ); strncat(manifest_uri, ".ismc", strlen(".ismc")); add_known_header(&phttp->hdr, MIME_HDR_X_NKN_DECODED_URI, manifest_uri, strlen(manifest_uri)); add_known_header(&phttp->hdr, MIME_HDR_X_NKN_URI, manifest_uri, strlen(manifest_uri)); phttp->p_ssp_cb->ssp_streamtype = NKN_SSP_SMOOTHSTREAM_STREAMTYPE_MANIFEST; // text/xml DBG_LOG(MSG, MOD_SSP, "SmoothStream Pub: Client manifest file request %s", manifest_uri); rv = SSP_SEND_DATA_OTW; goto exit; } /************************************************************* * State Flow for Smooth Stream Publishing * State 0: * Remap URI to fetch .ISM Server Manifest, SEND_DATA_BACK_TO_SSP * State 10: * Parse the XML .ism buffer, extract track id, quality, source name, etc * Remap URI to source name, SEND_DATA_BACK_TO_SSP * State 20: * Read the content length, Trigger a byte range fetch from EOF-16 * This is to get the MFRO box (Assuming that it is the last box) * SEND_DATA_BACK_TO_SSP * State 30: * Parse the MFRO box, find the MFRA offset. * Trigger a byte range fetch to MFRA * SEND_DATA_BACK_TO_SSP * State 40: * Allocate buffer for MFRA box, loop and copy the data in chunked fashion * Return code will be SSP_WAIT_FOR_DATA till all chunked data is read. * Fall through to State 50 * Parse the MFRA box using the time offset provided * Determine the moof offset and size. * State 50: * To determine the size of the fragment first do a internal 4 byte fetch * to find the box size for the moof header, then go to next state * State 60: * Again perform a 4-byte fetch to find the size of the mdat box. The sum * of both the sizes, gives the moof length. Now set the actual byte range * fetch and send over the wire SEND_DATA_OTW */ switch(con->ssp.seek_state) { case 0: // Reset all previous stateful variables to 0 // (Helpful when GET requests are pipelined in the same keep alive conn) con->ssp.ss_seek_offset = 0; con->ssp.ss_track_type = 0; con->ssp.ss_bit_rate = 0; con->ssp.ssp_br_offset = 0; con->ssp.ssp_br_length = 0; CLEAR_HTTP_FLAG(phttp, HRF_BYTE_RANGE); CLEAR_HTTP_FLAG(phttp, HRF_SSP_NO_AM_HITS); con->ssp.header_size = 0; if ( con->ssp.header ) { free(con->ssp.header); con->ssp.header = NULL; } con->ssp.ssp_partial_content_len = 0; con->ssp.ssp_streamtype = 0; // Remap .ism file uri and request to send to ssp p_qpos = strstr(uriData, ssp_cfg->smoothstream_pub.quality_tag); p_fpos = strstr(uriData, ssp_cfg->smoothstream_pub.fragment_tag); if (p_qpos && p_fpos) { // Process only if uri is a valid ss uri // Extract/Create the server manifest uri (*.ism) manifest_uri_size = p_qpos - uriData; manifest_uri = (char *)alloca(manifest_uri_size + SSP_MAX_EXTENSION_SZ); memset(manifest_uri, 0, manifest_uri_size + SSP_MAX_EXTENSION_SZ); manifest_uri[0] = '\0'; strncat(manifest_uri, uriData, manifest_uri_size-1); #if 0 parse_smoothstream_uri(uriData, ssp_cfg->smoothstream_pub.quality_tag, \ ssp_cfg->smoothstream_pub.fragment_tag, \ "video", "audio", \ &track_type, &bit_rate, &time_offset); con->ssp.ss_track_type = track_type; con->ssp.ss_bit_rate = bit_rate; con->ssp.ss_seek_offset = time_offset; snprintf(con->ssp.ss_orig_uri, uriLen, "%s", uriData); if(time_offset > 0) //BZ 6541 SET_HTTP_FLAG(phttp, HRF_SSP_NO_AM_HITS); DBG_LOG(MSG, MOD_SSP, "SmoothStream Pub (State: 0):" "Parsed Quality: %d, Time: %ld", con->ssp.ss_bit_rate, con->ssp.ss_seek_offset); #endif DBG_LOG(MSG, MOD_SSP, "SmoothStream Pub (State: 0): Fetch .ism file %s", manifest_uri); add_known_header(&phttp->hdr, MIME_HDR_X_NKN_REMAPPED_URI, manifest_uri, strlen(manifest_uri)); add_known_header(&phttp->hdr, MIME_HDR_X_NKN_SEEK_URI, manifest_uri, strlen(manifest_uri)); con->ssp.seek_state = 10; rv = SSP_SEND_DATA_BACK; goto exit; } else { // just allow to pass through DBG_LOG(MSG, MOD_SSP, "SmoothStream Pub (State: 0): Original URI not SS compliant: %s", uriData); rv = SSP_SEND_DATA_OTW; goto exit; } break; case 10: // Obtain .ism file, parse the XML context and extract track/src data if (contentLen == OM_STAT_SIG_TOT_CONTENT_LEN || contentLen == 0) { // File not found DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 10): Server Manifest not found. Cannot proceed"); rv = -NKN_SSP_SS_SVR_MANIFEST_ISM_NOT_FOUND; goto exit; } // Manifest found, initiate xml parser (chunked fetch for .ISM files not supported) if (dataBuf != NULL && contentLen <= bufLen) { //const char *orig_uri = uriData;//con->ssp.ss_orig_uri; [BZ 10387] /* delete the known MIME headers set in state 0 */ delete_known_header(&phttp->hdr, MIME_HDR_X_NKN_SEEK_URI); delete_known_header(&phttp->hdr, MIME_HDR_X_NKN_REMAPPED_URI); // Obtain the original restful URL [BZ 10387] if (get_known_header(&phttp->hdr, MIME_HDR_X_NKN_DECODED_URI, &tmpData, &tmpLen, &tmpAttrs, &tmpCnt)) { if (get_known_header(&phttp->hdr , MIME_HDR_X_NKN_URI, &tmpData, &tmpLen, &tmpAttrs, &tmpCnt)) { DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 10): Failed to extract url from NKN_URI"); return -NKN_SSP_BAD_URL; } } /* read the server manifest ism file into an XML context */ ism = init_xml_read_ctx( (uint8_t *)dataBuf, bufLen); /* read the [trackid, bitrate] map from the ism file context */ map = ism_read_bitrate_map(ism); /* read the bitrate from the uri, this is necessary to * query the "trackName" attribute from the ism bitrate * map */ rv = smoothstream_uri_get_ql(tmpData, ssp_cfg->smoothstream_pub.quality_tag, &bit_rate); if (rv!=0){ DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 10): Tags positions not found. Exiting"); rv = SSP_SEND_DATA_OTW; goto exit; } /* retrieve the query param name for the A/V track * for the given bitrate. if the "trackName" attribute * is not present the we fallback to defaults */ err = ism_get_video_qparam_name(map, bit_rate, &video_qparam_name); if (err == ISM_USE_DEF_QPARAM) { video_qparam_name = \ smoothstream_def_av_qparam_name[0]; } err = ism_get_audio_qparam_name(map, bit_rate, &audio_qparam_name); if (err == ISM_USE_DEF_QPARAM) { audio_qparam_name = \ smoothstream_def_av_qparam_name[1]; } /* now parse with the audio and video query param tag * parsed from the ism bitrate map */ rv = parse_smoothstream_uri(tmpData, ssp_cfg->smoothstream_pub.quality_tag, \ ssp_cfg->smoothstream_pub.fragment_tag, \ video_qparam_name, audio_qparam_name, \ &track_type, &bit_rate, &time_offset); if (rv!=0){ DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 10): Tags positions not found. Exiting"); rv = SSP_SEND_DATA_OTW; goto exit; } con->ssp.ss_track_type = track_type; con->ssp.ss_bit_rate = bit_rate; con->ssp.ss_seek_offset = time_offset; if(time_offset > 0) //BZ 6541 SET_HTTP_FLAG(phttp, HRF_SSP_NO_AM_HITS); /* find the trackid for a given track type and bitrate */ track_id = ism_get_track_id(map, con->ssp.ss_bit_rate, con->ssp.ss_track_type); if (track_id == 0) { DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 10):" "Unable to find a track corresponding to bit rate %d kbps. Close conn ", con->ssp.ss_bit_rate); rv = -NKN_SSP_SS_TRACK_NOT_FOUND; goto exit; } /* Use track id to find the source file name */ uri = ism_get_video_name(map, con->ssp.ss_track_type, track_id, con->ssp.ss_bit_rate, NULL, NULL, 0); if (con->ssp.ss_track_type == 0) { phttp->p_ssp_cb->ssp_streamtype = NKN_SSP_SMOOTHSTREAM_STREAMTYPE_VIDEO; //video/mp4 } else if (con->ssp.ss_track_type == 1) { phttp->p_ssp_cb->ssp_streamtype = NKN_SSP_SMOOTHSTREAM_STREAMTYPE_AUDIO; //audio/mp4 } con->ssp.ss_track_id = track_id; //con->ssp.ss_seek_offset = time_offset; // Create the source file URI for the .ISMV or .ISMA // file p_qpos = strstr(tmpData, ssp_cfg->smoothstream_pub.quality_tag); p_fpos = strstr(tmpData, ssp_cfg->smoothstream_pub.fragment_tag); if (p_qpos == NULL || p_fpos == NULL) { // [BZ 10387] DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 10): Tags positions not found. Exiting"); rv = SSP_SEND_DATA_OTW; goto exit; } // Extract/Create the server manifest uri (*.ism) manifest_uri_size = p_qpos - tmpData; if (manifest_uri_size > strlen(tmpData)) { // [BZ 10387] DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 10): uri size gone out of bounds. Exiting"); rv = SSP_SEND_DATA_OTW; goto exit; } manifest_uri = (char *)alloca(manifest_uri_size + SSP_MAX_EXTENSION_SZ); memset(manifest_uri, 0, manifest_uri_size + SSP_MAX_EXTENSION_SZ); manifest_uri[0] = '\0'; strncat(manifest_uri, tmpData, manifest_uri_size-1); pos = find_base_uri_endpos(manifest_uri, ssp_cfg->smoothstream_pub.quality_tag); media_uri = (char *)alloca(pos + strlen(uri) + SSP_MAX_EXTENSION_SZ); memset(media_uri, 0, pos + strlen(uri) + SSP_MAX_EXTENSION_SZ); media_uri[0] = '\0'; strncat(media_uri, manifest_uri, pos); strncat(media_uri, uri, strlen(uri)); // Uri for the media asset (Could be an ISMV or ISMA or a packaged ISMV file) add_known_header(&phttp->hdr, MIME_HDR_X_NKN_DECODED_URI, media_uri, strlen(media_uri)); add_known_header(&phttp->hdr, MIME_HDR_X_NKN_URI, media_uri, strlen(media_uri)); SET_HTTP_FLAG(phttp, HRF_SSP_NO_AM_HITS); // BZ 6541 DBG_LOG(MSG, MOD_SSP, "SmoothStream Pub (State 10):" "Got .ism file, fetching .ismv file %s [QL: %d, Time: %ld]", media_uri, con->ssp.ss_bit_rate, con->ssp.ss_seek_offset); ism_cleanup_map(map); xml_cleanup_ctx(ism); con->ssp.seek_state = 20; rv = SSP_SEND_DATA_BACK; goto exit; } else { DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 10): NULL dataBuf returned for Server Manifest"); rv = -NKN_SSP_SS_NULL_BUF_INT_FETCH; goto exit; } break; case 20: // Find the content length of the media file, set a byte range request for mfro box if (contentLen == OM_STAT_SIG_TOT_CONTENT_LEN || contentLen == 0) { // File not found DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 20): .ISMV Media file not found. Cannot proceed"); rv = -NKN_SSP_SS_ISMV_ISMA_NOT_FOUND; goto exit; } if (dataBuf != NULL) { con->ssp.ssp_content_length = contentLen; // Fixed offset from EOF phttp->brstart = contentLen - 16; phttp->brstop = 0; SET_HTTP_FLAG(phttp, HRF_BYTE_RANGE); DBG_LOG(MSG, MOD_SSP, "SmoothStream Pub (State 20): Requesting mfro box (Off/Size: %ld/%ld) [Time: %ld]", phttp->brstart, con->ssp.ssp_content_length, con->ssp.ss_seek_offset); con->ssp.seek_state = 30; rv = SSP_SEND_DATA_BACK; goto exit; } else { DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 20): NULL dataBuf returned for ISMV media file"); rv = -NKN_SSP_SS_NULL_BUF_INT_FETCH; goto exit; } break; case 30: /* For fragmented ISMV files, the mfro box is usually the last box * in the file and is of fixed size. * The mfro box gives the offset in the file for the mfra box. * The mfra box in turn has information about the timestamp & offset of each moof fragment */ if (contentLen == OM_STAT_SIG_TOT_CONTENT_LEN || contentLen == 0) { // File not found DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 30): Byte range fetch for MFRO failed. Cannot proceed"); rv = -NKN_SSP_SS_ISMV_ISMA_NOT_FOUND; goto exit; } if (dataBuf != NULL) { memset(mfro, 0, 16); memcpy(mfro, dataBuf, 16); /* read the mfra offset from the mfro box */ mfra_off = con->ssp.ssp_content_length - mp4_get_mfra_offset(mfro, 16); if(mfra_off == con->ssp.ssp_content_length) { DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 30): MFRO box offset read failed"); rv = -NKN_SSP_SS_MFRO_OFF_FAIL; goto exit; } phttp->brstart = mfra_off; phttp->brstop = 0; SET_HTTP_FLAG(phttp, HRF_BYTE_RANGE); con->ssp.header_size = con->ssp.ssp_content_length - mfra_off; // Size of MFRA box till the end DBG_LOG(MSG, MOD_SSP, "SmoothStream Pub (State: 30): Requesting the MFRA box (Off/Size: %ld/%ld) [Time: %ld]", phttp->brstart, con->ssp.ssp_content_length, con->ssp.ss_seek_offset); con->ssp.seek_state = 40; rv = SSP_SEND_DATA_BACK; goto exit; } else { DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 30): NULL dataBuf returned for MFRO offset"); rv = -NKN_SSP_SS_NULL_BUF_INT_FETCH; goto exit; } break; case 40: // Buffered loopback read to copy the entire MFRA box if (contentLen == OM_STAT_SIG_TOT_CONTENT_LEN || contentLen == 0) { // File not found DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 40): Byte range fetch for MFRA failed"); rv = -NKN_SSP_SS_ISMV_ISMA_NOT_FOUND; goto exit; } if ( !con->ssp.header ) { // Buffer for MFRA box con->ssp.header = (uint8_t *)nkn_calloc_type(con->ssp.header_size, sizeof(char), mod_ssp_smoothstream_pub_t); if (con->ssp.header == NULL) { DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 40): Failed to allocate space for copy MFRA box"); CLEAR_HTTP_FLAG(phttp, HRF_BYTE_RANGE); rv = -NKN_SSP_SS_MEM_ALLOC_HDR_FAIL; // error case goto exit; } con->ssp.ssp_partial_content_len = 0; } if (dataBuf != NULL) { memcpy(con->ssp.header + con->ssp.ssp_partial_content_len, dataBuf, bufLen); con->ssp.ssp_partial_content_len += bufLen; if (con->ssp.ssp_partial_content_len < con->ssp.header_size) { DBG_LOG(MSG, MOD_SSP, "SmoothStream Pub (State: 40): Chunked read for MFRA box, read %d of %ld [Time: %ld]", con->ssp.ssp_partial_content_len, con->ssp.header_size, con->ssp.ss_seek_offset); rv = SSP_WAIT_FOR_DATA; goto exit; } } // Parse the populated MFRA box to glean the offset and length for the MOOF fragment /* initialize the ismv context */ ctx = mp4_init_ismv_parser_ctx(con->ssp.header, con->ssp.header_size, NULL); /* seek to a timestamp in a track id, returns the correct moof * offset and its length; track id determined by call to 'ism_get_track_id' */ mp4_frag_seek(ctx, con->ssp.ss_track_id, 0, con->ssp.ss_seek_offset, &moof_offset, &moof_size, &moof_time); if (moof_offset == 0) { DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 40): Invalid fragment offset(Off: %ld)", moof_time); con->ssp.seek_state = 0; rv = -NKN_SSP_SS_ISMV_ISMA_NOT_FOUND; goto exit; } con->ssp.ssp_br_offset = moof_offset; phttp->brstart = moof_offset; phttp->brstop = moof_offset + 4 - 1; SET_HTTP_FLAG(phttp, HRF_BYTE_RANGE); DBG_LOG(MSG, MOD_SSP, "SmoothStream Pub (State: 40): Refetch to parse the moof size value (Off: %ld)", phttp->brstart); mp4_cleanup_ismv_ctx(ctx); con->ssp.seek_state = 50; rv = SSP_SEND_DATA_BACK; goto exit; break; case 50: if (dataBuf != NULL) { box_size = get_mp4_boxsize((uint8_t *)dataBuf, 4); phttp->brstart += box_size; phttp->brstop = phttp->brstart + 4 - 1; SET_HTTP_FLAG(phttp, HRF_BYTE_RANGE); DBG_LOG(MSG, MOD_SSP, "SmoothStream Pub (State: 60): Refetch to parse the moof size value (Off: %ld)", phttp->brstart); con->ssp.seek_state = 60; rv = SSP_SEND_DATA_BACK; goto exit; } else { DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 50): NULL dataBuf returned for ISMV media file"); rv = -NKN_SSP_SS_NULL_BUF_INT_FETCH; goto exit; } break; case 60: if (dataBuf != NULL) { box_size = get_mp4_boxsize((uint8_t *)dataBuf, 4); phttp->brstart = con->ssp.ssp_br_offset; phttp->brstop += box_size - 4 + 1; SET_HTTP_FLAG(phttp, HRF_BYTE_RANGE); SET_HTTP_FLAG(phttp, HRF_BYTE_SEEK); // To override the 206 response to 200 CLEAR_HTTP_FLAG(phttp, HRF_SSP_NO_AM_HITS); // BZ 6541 DBG_LOG(MSG, MOD_SSP, "SmoothStream Pub (State: 60): Found MOOF offset,size = %ld, %ld [Time: %ld]", phttp->brstart, phttp->brstop - phttp->brstart, con->ssp.ss_seek_offset); con->ssp.seek_state = 0; rv = SSP_SEND_DATA_OTW; goto exit; } else { DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: 20): NULL dataBuf returned for ISMV media file"); con->ssp.seek_state = 0; rv = -NKN_SSP_SS_NULL_BUF_INT_FETCH; goto exit; } break; default: DBG_LOG(WARNING, MOD_SSP, "SmoothStream Pub (State: Default): Not supported state = %d", con->ssp.seek_state); rv = SSP_SEND_DATA_OTW; goto exit; break; } //switch(con->ssp.seek_state) exit: return rv; }
/* * PEM decode incoming data, appending SecImportRep's to specified array. * Returned SecImportReps may or may not have a known type and format and * (if they are keys) algorithm. */ OSStatus impExpParsePemToImportRefs( CFDataRef importedData, CFMutableArrayRef importReps, // output appended here bool *isPem) // true means we think it was PEM regardless of // final return code { /* * First task: is this PEM or at least base64 encoded? */ const char *currCp = (const char *)CFDataGetBytePtr(importedData); const char *cp = currCp; unsigned lenToGo = (unsigned)CFDataGetLength(importedData); OSStatus ortn; *isPem = false; unsigned dex; bool allBlanks = true; for(dex=0; dex<lenToGo; dex++, cp++) { if (!isspace(*cp)) { // it's not a space. Is it a non-ascii character? if (!isascii(*cp)) { return errSecSuccess; } // is it a control character? if (iscntrl(*cp)) { return errSecSuccess; } // no, mark that an acceptable character was encountered and keep going allBlanks = false; } } if (allBlanks) { return errSecSuccess; } /* search for START line */ const char *startLine = findStr(currCp, lenToGo, "-----BEGIN"); if(startLine == NULL) { /* Assume one item, raw base64 */ SecImpInferDbg("impExpParsePemToImportRefs no PEM headers, assuming raw base64"); ortn = impExpImportSinglePEM(currCp, lenToGo, importReps); if(ortn == errSecSuccess) { *isPem = true; } return ortn; } /* break up input into chunks between START and END lines */ ortn = errSecSuccess; bool gotSomePem = false; do { /* get to beginning of START line */ startLine = findStr(currCp, lenToGo, "-----BEGIN"); if(startLine == NULL) { break; } unsigned consumed = (unsigned)(startLine - currCp); assert(consumed <= lenToGo); lenToGo -= consumed; currCp += consumed; /* get to beginning of END line */ const char *endLine = findStr(currCp+10, lenToGo, "-----END"); unsigned toDecode = lenToGo; if(endLine) { consumed = (unsigned)(endLine - startLine); assert(consumed <= lenToGo); currCp += consumed; lenToGo -= consumed; /* find end of END line */ const char *tmpLine = getLine(endLine, lenToGo, &consumed); assert((tmpLine != NULL) && (tmpLine[0] != 0)); /* don't decode the terminators */ toDecode = (unsigned)(endLine - startLine + strlen(tmpLine)); free((void *)tmpLine); /* skip past END line and newlines */ assert(consumed <= lenToGo); currCp += consumed; lenToGo -= consumed; } else { /* no END line, we'll allow that - decode to end of file */ lenToGo = 0; } ortn = impExpImportSinglePEM(startLine, toDecode, importReps); if(ortn) { break; } gotSomePem = true; } while(lenToGo != 0); if(ortn == errSecSuccess) { if(gotSomePem) { *isPem = true; } else { SecImpInferDbg("impExpParsePemToImportRefs empty at EOF, no PEM found"); ortn = kSecFormatUnknown; } } return ortn; }
/* * PEM decode incoming data which we've previously determined to contain * exactly one reasonably well formed PEM blob (it has no more than one * START and END line - though it may have none - and is all ASCII). * * Returned SecImportRep may or may not have a known type and format and * (if it is a key) algorithm. */ static OSStatus impExpImportSinglePEM( const char *currCp, unsigned lenToGo, CFMutableArrayRef importReps) // output appended here { unsigned consumed; const char *currLine = NULL; // mallocd by getLine() const char *lastCp = currCp; CFMutableArrayRef pemParamLines = NULL; OSStatus ortn = errSecSuccess; CFDataRef cdata = NULL; Security::KeychainCore::SecImportRep *rep = NULL; const char *start64; unsigned base64Len; const char *end64; unsigned char *decData; unsigned decDataLen; /* we try to glean these from the header, but it's not fatal if we can not */ SecExternalFormat format = kSecFormatUnknown; SecExternalItemType itemType = kSecItemTypeUnknown; CSSM_ALGORITHMS keyAlg = CSSM_ALGID_NONE; /* search to START line, parse it to get type/format/alg */ const char *startLine = findStr(currCp, lenToGo, "-----BEGIN"); if(startLine != NULL) { /* possibly skip over leading garbage */ consumed = (unsigned)(startLine - currCp); lenToGo -= consumed; currCp = startLine; /* get C string of START line */ currLine = getLine(startLine, lenToGo, &consumed); if(currLine == NULL) { /* somehow got here with no data */ assert(lenToGo == 0); SecImpInferDbg("impExpImportSinglePEM empty data"); ortn = errSecUnsupportedFormat; goto errOut; } assert(consumed <= lenToGo); currCp += consumed; lenToGo -= consumed; /* * Search currLine for known PEM header strings. * It is not an error if we don't recognize this * header. */ for(unsigned dex=0; dex<NUM_PEM_HEADERS; dex++) { const PemHeader *ph = &PemHeaders[dex]; if(!strstr(currLine, ph->pemStr)) { continue; } /* found one! */ format = ph->format; itemType = ph->itemType; keyAlg = ph->keyAlg; break; } free((void *)currLine); } /* * Skip empty lines. Save all lines containing ':' (used by openssl * to specify key wrapping parameters). These will be saved in * outgoing SecImportReps' pemParamLines. */ for( ; ; ) { currLine = getLine(currCp, lenToGo, &consumed); if(currLine == NULL || currCp == lastCp) { /* out of data (unable to advance to next line) */ SecImpInferDbg("impExpImportSinglePEM out of data"); if (currLine) free((void *)currLine); ortn = errSecUnsupportedFormat; goto errOut; } lastCp = currCp; bool skipThis = false; unsigned lineLen = (unsigned)strlen(currLine); if(lineLen == 0) { /* empty line */ skipThis = true; } if(strchr(currLine, ':')) { /* * Save this PEM header info. Used for traditional openssl * wrapped keys to indicate IV. */ SecImpInferDbg("import PEM: param line %s", currLine); CFStringRef cfStr = CFStringCreateWithCString(NULL, currLine, kCFStringEncodingASCII); if(pemParamLines == NULL) { /* first param line */ pemParamLines = CFArrayCreateMutable(NULL, 0, &kCFTypeArrayCallBacks); /* * If it says "ENCRYPTED" and this is a private key, * flag the fact that it's wrapped in openssl format */ if(strstr(currLine, "ENCRYPTED")) { if((format == kSecFormatOpenSSL) && (itemType == kSecItemTypePrivateKey)) { format = kSecFormatWrappedOpenSSL; } } } CFArrayAppendValue(pemParamLines, cfStr); CFRelease(cfStr); // array owns it skipThis = true; } free((void *)currLine); if(!skipThis) { /* looks like good stuff; process */ break; } /* skip this line */ assert(consumed <= lenToGo); currCp += consumed; lenToGo -= consumed; } if(lenToGo <= 2) { SecImpInferDbg("impExpImportSinglePEM no valid base64 data"); ortn = errSecUnsupportedFormat; goto errOut; } /* * currCP points to start of base64 data - mark it and search for end line. * We skip everything after the end line. */ start64 = currCp; base64Len = lenToGo; // if no END end64 = findStr(currCp, lenToGo, "-----END"); if(end64 != NULL) { if(end64 == start64) { /* Empty, nothing between START and END */ SecImpInferDbg("impExpImportSinglePEM no base64 between terminators"); ortn = errSecUnsupportedFormat; goto errOut; } base64Len = (unsigned)(end64 - start64); } /* else no END, no reason to complain about that as long as base64 decode works OK */ /* Base 64 decode */ decData = cuDec64((const unsigned char *)start64, base64Len, &decDataLen); if(decData == NULL) { SecImpInferDbg("impExpImportSinglePEM bad base64 data"); ortn = errSecUnsupportedFormat; goto errOut; } cdata = CFDataCreate(NULL, decData, decDataLen); free((void *)decData); rep = new Security::KeychainCore::SecImportRep(cdata, itemType, format, keyAlg, pemParamLines); CFArrayAppendValue(importReps, rep); CFRelease(cdata); // SecImportRep holds ref return errSecSuccess; errOut: if(pemParamLines != NULL) { CFRelease(pemParamLines); } return ortn; }