/*! * \brief getLocalPath * get path that works for both ffmpeg and QFile * Windows: ffmpeg does not supports file:///C:/xx.mov, only supports file:C:/xx.mov or C:/xx.mov * QFile: does not support file: scheme * fullPath can be file:///path from QUrl. QUrl.toLocalFile will remove file:// */ QString getLocalPath(const QString& fullPath) { #ifdef Q_OS_MAC if (fullPath.startsWith(QLatin1String("file:///.file/id=")) || fullPath.startsWith(QLatin1String("/.file/id="))) return absolutePathFromOSX(fullPath); #endif int pos = fullPath.indexOf(QLatin1String(kFileScheme)); if (pos >= 0) { pos += CHAR_COUNT(kFileScheme); bool has_slash = false; while (fullPath.at(pos) == QLatin1Char('/')) { has_slash = true; ++pos; } // win: ffmpeg does not supports file:///C:/xx.mov, only supports file:C:/xx.mov or C:/xx.mov #ifndef Q_OS_WIN // for QUrl if (has_slash) --pos; #endif } // always remove "file:" even thought it works for ffmpeg.but fileName() may be used for QFile which does not file: if (pos > 0) return fullPath.mid(pos); return fullPath; }
//Note: This function assumes that "Host:" and "Content-Length:" headers are setup // by the caller of HTTPAPI_ExecuteRequest() (which is true for httptransport.c). HTTPAPI_RESULT HTTPAPI_ExecuteRequest(HTTP_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, HTTP_HEADERS_HANDLE httpHeadersHandle, const unsigned char* content, size_t contentLength, unsigned int* statusCode, HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent) { LogInfo("HTTPAPI_ExecuteRequest::Start\r\n"); HTTPAPI_RESULT result; size_t headersCount; char buf[TEMP_BUFFER_SIZE]; int ret; TLSConnection* con = NULL; size_t bodyLength = 0; bool chunked = false; const unsigned char* receivedContent; const char* method = (requestType == HTTPAPI_REQUEST_GET) ? "GET" : (requestType == HTTPAPI_REQUEST_POST) ? "POST" : (requestType == HTTPAPI_REQUEST_PUT) ? "PUT" : (requestType == HTTPAPI_REQUEST_DELETE) ? "DELETE" : (requestType == HTTPAPI_REQUEST_PATCH) ? "PATCH" : NULL; if (handle == NULL || relativePath == NULL || httpHeadersHandle == NULL || method == NULL || HTTPHeaders_GetHeaderCount(httpHeadersHandle, &headersCount) != HTTP_HEADERS_OK) { result = HTTPAPI_INVALID_ARG; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } con = &(((HTTP_HANDLE_DATA*)handle)->con); //Send request if ((ret = snprintf(buf, sizeof(buf), "%s %s HTTP/1.1\r\n", method, relativePath)) < 0 || ret >= sizeof(buf)) { result = HTTPAPI_STRING_PROCESSING_ERROR; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } LogInfo("HTTPAPI_ExecuteRequest::Sending=%*.*s\r\n", strlen(buf), strlen(buf), buf); if (con->send_all(buf, strlen(buf)) < 0) { result = HTTPAPI_SEND_REQUEST_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } //Send default headers for (int i = 0; i < (int)headersCount; i++) { if (HTTPHeaders_GetHeader(httpHeadersHandle, i, buf, sizeof(buf)) != HTTP_HEADERS_OK) { result = HTTPAPI_HTTP_HEADERS_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } LogInfo("HTTPAPI_ExecuteRequest::Sending=%*.*s\r\n", strlen(buf), strlen(buf), buf); if (con->send_all(buf, strlen(buf)) < 0) { result = HTTPAPI_SEND_REQUEST_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } if (con->send_all("\r\n", 2) < 0) { result = HTTPAPI_SEND_REQUEST_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } } //Close headers if (con->send_all("\r\n", 2) < 0) { result = HTTPAPI_SEND_REQUEST_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } //Send data (if available) if (content && contentLength > 0) { LogInfo("HTTPAPI_ExecuteRequest::Sending data=%*.*s\r\n", contentLength, contentLength, content); if (con->send_all((char*)content, contentLength) < 0) { result = HTTPAPI_SEND_REQUEST_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } } //Receive response if (readLine(con, buf, sizeof(buf)) < 0) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } //Parse HTTP response if (sscanf(buf, "HTTP/%*d.%*d %d %*[^\r\n]", &ret) != 1) { //Cannot match string, error LogInfo("HTTPAPI_ExecuteRequest::Not a correct HTTP answer=%s\r\n", buf); result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } if (statusCode) *statusCode = ret; LogInfo("HTTPAPI_ExecuteRequest::Received response=%*.*s\r\n", strlen(buf), strlen(buf), buf); //Read HTTP response headers if (readLine(con, buf, sizeof(buf)) < 0) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } while (buf[0]) { const char ContentLength[] = "content-length:"; const char TransferEncoding[] = "transfer-encoding:"; LogInfo("Receiving header=%*.*s\r\n", strlen(buf), strlen(buf), buf); if (strncasecmp(buf, ContentLength, CHAR_COUNT(ContentLength)) == 0) { if (sscanf(buf + CHAR_COUNT(ContentLength), " %d", &bodyLength) != 1) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } } else if (strncasecmp(buf, TransferEncoding, CHAR_COUNT(TransferEncoding)) == 0) { const char* p = buf + CHAR_COUNT(TransferEncoding); while (isspace(*p)) p++; if (strcasecmp(p, "chunked") == 0) chunked = true; } char* whereIsColon = strchr((char*)buf, ':'); if (whereIsColon && responseHeadersHandle != NULL) { *whereIsColon = '\0'; HTTPHeaders_AddHeaderNameValuePair(responseHeadersHandle, buf, whereIsColon + 1); } if (readLine(con, buf, sizeof(buf)) < 0) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } } //Read HTTP response body LogInfo("HTTPAPI_ExecuteRequest::Receiving body=%d,%x\r\n", bodyLength, responseContent); if (!chunked) { if (bodyLength) { if (responseContent != NULL) { if (BUFFER_pre_build(responseContent, bodyLength) != 0) { result = HTTPAPI_ALLOC_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else if (BUFFER_content(responseContent, &receivedContent) != 0) { (void)BUFFER_unbuild(responseContent); result = HTTPAPI_ALLOC_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } if (readChunk(con, (char*)receivedContent, bodyLength) < 0) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } else { LogInfo("HTTPAPI_ExecuteRequest::Received response body=%*.*s\r\n", bodyLength, bodyLength, receivedContent); result = HTTPAPI_OK; } } else { (void)skipN(con, bodyLength, buf, sizeof(buf)); result = HTTPAPI_OK; } } else { result = HTTPAPI_OK; } } else { size_t size = 0; result = HTTPAPI_OK; for (;;) { int chunkSize; if (readLine(con, buf, sizeof(buf)) < 0) // read [length in hex]/r/n { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } if (sscanf(buf, "%x", &chunkSize) != 1) // chunkSize is length of next line (/r/n is not counted) { //Cannot match string, error result = HTTPAPI_RECEIVE_RESPONSE_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } if (chunkSize == 0) { // 0 length means next line is just '\r\n' and end of chunks if (readChunk(con, (char*)buf, 2) < 0 || buf[0] != '\r' || buf[1] != '\n') // skip /r/n { (void)BUFFER_unbuild(responseContent); result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } break; } else { if (responseContent != NULL) { if (BUFFER_enlarge(responseContent, chunkSize) != 0) { (void)BUFFER_unbuild(responseContent); result = HTTPAPI_ALLOC_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } else if (BUFFER_content(responseContent, &receivedContent) != 0) { (void)BUFFER_unbuild(responseContent); result = HTTPAPI_ALLOC_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); } if (readChunk(con, (char*)receivedContent + size, chunkSize) < 0) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } } else { if (skipN(con, chunkSize, buf, sizeof(buf)) < 0) { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } } if (readChunk(con, (char*)buf, 2) < 0 || buf[0] != '\r' || buf[1] != '\n') // skip /r/n { result = HTTPAPI_READ_DATA_FAILED; LogError("(result = %s)\r\n", ENUM_TO_STRING(HTTPAPI_RESULT, result)); goto exit; } size += chunkSize; } } if (size > 0) { LogInfo("HTTPAPI_ExecuteRequest::Received chunk body=%*.*s\r\n", size, size, responseContent); } } exit: LogInfo("HTTPAPI_ExecuteRequest::End=%d\r\n", result); return result; }