Changeset 87032 in vbox
- Timestamp:
- Dec 2, 2020 4:33:29 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 141673
- Location:
- trunk
- Files:
-
- 6 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/http-common.h
r87010 r87032 48 48 RTHTTPMETHOD_OPTIONS, 49 49 RTHTTPMETHOD_TRACE, 50 #ifdef RTHTTP_WITH_WEBDAV 51 RTHTTPMETHOD_PROPFIND, 52 #endif 50 53 RTHTTPMETHOD_END, 51 54 RTHTTPMETHOD_32BIT_HACK = 0x7fffffff -
trunk/include/iprt/http-server.h
r87016 r87032 125 125 * @returns VBox status code. 126 126 * @param pData Pointer to HTTP callback data. 127 * @param p szUrl URLto handle.127 * @param pReq Pointer to request to handle. 128 128 * @param ppvHandle Where to return the pointer to the opaque handle used for object identification. 129 129 */ 130 DECLCALLBACKMEMBER(int, pfnOpen,(PRTHTTPCALLBACKDATA pData, const char *pszUrl, void **ppvHandle));130 DECLCALLBACKMEMBER(int, pfnOpen,(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, void **ppvHandle)); 131 131 /** 132 132 * Called when a given URL will be retrieved by the GET method. … … 137 137 * @returns VBox status code. 138 138 * @param pData Pointer to HTTP callback data. 139 * @param pvHandle Opaque handle for object identification. 140 * @param pvBuf Pointer to buffer where to store the read data. 141 * @param cbBuf Size (in bytes) of the buffer where to store the read data. 142 * @param pcbRead Where to return the amount (in bytes) of read data. Optional and can be NULL. 143 */ 144 DECLCALLBACKMEMBER(int, pfnRead,(PRTHTTPCALLBACKDATA pData, void *pvHandle, void *pvBuf, size_t cbBuf, size_t *pcbRead)); 145 /** 146 * Called when a given URL is done retrieving by the GET method. 147 * 148 * Note: High level function, not being called when pfnOnGetRequest is implemented. 149 * 150 * @returns VBox status code. 151 * @param pData Pointer to HTTP callback data. 139 152 * @param pszUrl URL to handle. 140 153 * @param pvHandle Opaque handle for object identification. 141 154 */ 142 DECLCALLBACKMEMBER(int, pfnRead,(PRTHTTPCALLBACKDATA pData, void *pvHandle, void *pvBuf, size_t cbBuf, size_t *pcbRead));143 /**144 * Called when a given URL is done retrieving by the GET method.145 *146 * Note: High level function, not being called when pfnOnGetRequest is implemented.147 *148 * @returns VBox status code.149 * @param pData Pointer to HTTP callback data.150 * @param pszUrl URL to handle.151 * @param pvHandle Opaque handle for object identification.152 */153 155 DECLCALLBACKMEMBER(int, pfnClose,(PRTHTTPCALLBACKDATA pData, void *pvHandle)); 154 156 /** … … 159 161 * @returns VBox status code. 160 162 * @param pData Pointer to HTTP callback data. 161 * @param p szUrl URL to query information for.163 * @param pReq Pointer to request to handle. 162 164 * @param pObjInfo Where to store the queried file information on success. 163 165 * @param ppszMIMEHint Where to return an allocated MIME type hint on success. 164 166 * Must be free'd by the caller using RTStrFree(). 165 167 */ 166 DECLCALLBACKMEMBER(int, pfnQueryInfo,(PRTHTTPCALLBACKDATA pData, const char *pszUrl, PRTFSOBJINFO pObjInfo, char **ppszMIMEHint));168 DECLCALLBACKMEMBER(int, pfnQueryInfo,(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, PRTFSOBJINFO pObjInfo, char **ppszMIMEHint)); 167 169 /** 168 170 * Low-level handler for a GET method request. … … 181 183 */ 182 184 DECLCALLBACKMEMBER(int, pfnOnHeadRequest,(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq)); 185 /** 186 * Called before the HTTP server will be destroyed. 187 * 188 * @returns VBox status code. 189 * @param pData Pointer to HTTP callback data. 190 */ 191 DECLCALLBACKMEMBER(int, pfnDestroy,(PRTHTTPCALLBACKDATA pData)); 183 192 } RTHTTPSERVERCALLBACKS; 184 193 /** Pointer to a HTTP server callback data table. */ 185 194 typedef RTHTTPSERVERCALLBACKS *PRTHTTPSERVERCALLBACKS; 186 195 187 /** Maximum length (in bytes) a client request can have. */196 /** Maximum length (in bytes) a single client request can have. */ 188 197 #define RTHTTPSERVER_MAX_REQ_LEN _8K 189 198 -
trunk/src/VBox/Runtime/generic/http-curl.cpp
r87004 r87032 2396 2396 case RTHTTPMETHOD_OPTIONS: pszMethodSp = "options "; break; 2397 2397 case RTHTTPMETHOD_TRACE: pszMethodSp = "trace "; break; 2398 #ifdef RTHTTP_WITH_WEBDAV 2399 case RTHTTPMETHOD_PROPFIND: pszMethodSp = "propfind "; break; 2400 #endif 2398 2401 /* no default! */ 2399 2402 case RTHTTPMETHOD_INVALID: … … 3734 3737 rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_CUSTOMREQUEST, "TRACE"); 3735 3738 break; 3739 #ifdef RTHTTP_WITH_WEBDAV 3740 case RTHTTPMETHOD_PROPFIND: 3741 RT_FALL_THROUGH(); 3742 #endif 3736 3743 case RTHTTPMETHOD_END: 3737 3744 case RTHTTPMETHOD_INVALID: -
trunk/src/VBox/Runtime/generic/http.cpp
r87010 r87032 104 104 case RTHTTPMETHOD_OPTIONS: return "OPTIONS"; 105 105 case RTHTTPMETHOD_TRACE: return "TRACE"; 106 106 #ifdef RTHTTP_WITH_WEBDAV 107 case RTHTTPMETHOD_PROPFIND: return "PROPFIND"; 108 #endif 107 109 case RTHTTPMETHOD_END: 108 110 RT_FALL_THROUGH(); -
trunk/src/VBox/Runtime/r3/http-server.cpp
r87029 r87032 14 14 * - No IPv6 support. 15 15 * - No multi-threading. 16 * 17 * For WebDAV (optional via RTHTTP_WITH_WEBDAV): 18 * - Only OPTIONS + PROPLIST methods are implemented (e.g. simple read-only support). 19 * - No pagination support for directory listings. 16 20 */ 17 21 … … 132 136 rc = pCallbacks->a_Name(&Data); \ 133 137 } \ 134 else \135 rc = VERR_NOT_IMPLEMENTED; \136 138 } while (0) 137 139 … … 146 148 rc = pCallbacks->a_Name(&Data, __VA_ARGS__); \ 147 149 } \ 148 else \149 rc = VERR_NOT_IMPLEMENTED; \150 150 } while (0) 151 151 … … 256 256 * @{ 257 257 */ 258 static FNRTHTTPSERVERMETHOD rtHttpServerHandleGET; 259 static FNRTHTTPSERVERMETHOD rtHttpServerHandleHEAD; 258 static FNRTHTTPSERVERMETHOD rtHttpServerHandleGET; 259 static FNRTHTTPSERVERMETHOD rtHttpServerHandleHEAD; 260 #ifdef RTHTTP_WITH_WEBDAV 261 static FNRTHTTPSERVERMETHOD rtHttpServerHandleOPTIONS; 262 static FNRTHTTPSERVERMETHOD rtHttpServerHandlePROPFIND; 263 #endif 260 264 /** @} */ 261 265 … … 283 287 static const RTHTTPSERVERMETHOD_ENTRY g_aMethodMap[] = 284 288 { 285 { RTHTTPMETHOD_GET, rtHttpServerHandleGET }, 286 { RTHTTPMETHOD_HEAD, rtHttpServerHandleHEAD }, 289 { RTHTTPMETHOD_GET, rtHttpServerHandleGET }, 290 { RTHTTPMETHOD_HEAD, rtHttpServerHandleHEAD }, 291 #ifdef RTHTTP_WITH_WEBDAV 292 { RTHTTPMETHOD_OPTIONS, rtHttpServerHandleOPTIONS }, 293 { RTHTTPMETHOD_PROPFIND, rtHttpServerHandlePROPFIND }, 294 #endif 287 295 { RTHTTPMETHOD_END, NULL } 288 296 }; … … 518 526 AssertRCReturn(rc, rc); 519 527 528 #ifdef RTHTTP_WITH_WEBDAV 529 rc = RTHttpHeaderListAdd(HdrLst, "Allow", "GET, HEAD, PROPFIND", strlen("GET, HEAD, PROPFIND"), RTHTTPHEADERLISTADD_F_BACK); 530 AssertRCReturn(rc, rc); 531 rc = RTHttpHeaderListAdd(HdrLst, "DAV", "1", strlen("1"), RTHTTPHEADERLISTADD_F_BACK); /* Note: v1 is sufficient for read-only access. */ 532 AssertRCReturn(rc, rc); 533 #endif 534 520 535 char *pszHdr = NULL; 521 536 … … 621 636 case VERR_INVALID_POINTER: return RTHTTPSTATUS_BADREQUEST; 622 637 case VERR_NOT_IMPLEMENTED: return RTHTTPSTATUS_NOTIMPLEMENTED; 638 case VERR_NOT_SUPPORTED: return RTHTTPSTATUS_NOTIMPLEMENTED; 623 639 case VERR_PATH_NOT_FOUND: return RTHTTPSTATUS_NOTFOUND; 624 640 case VERR_FILE_NOT_FOUND: return RTHTTPSTATUS_NOTFOUND; … … 649 665 LogFlowFuncEnter(); 650 666 651 int rc ;667 int rc = VINF_SUCCESS; 652 668 653 669 /* If a low-level GET request handler is defined, call it and return. */ … … 659 675 char *pszMIMEHint = NULL; 660 676 661 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnQueryInfo, pReq ->pszUrl, &fsObj, &pszMIMEHint);677 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnQueryInfo, pReq, &fsObj, &pszMIMEHint); 662 678 if (RT_FAILURE(rc)) 663 679 return rc; 664 680 665 681 void *pvHandle = NULL; 666 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnOpen, pReq ->pszUrl, &pvHandle);682 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnOpen, pReq, &pvHandle); 667 683 668 684 if (RT_SUCCESS(rc)) … … 761 777 RTHTTPSERVER_HANDLE_CALLBACK_VA_RET(pfnOnHeadRequest, pReq); 762 778 763 int rc ;779 int rc = VINF_SUCCESS; 764 780 765 781 RTFSOBJINFO fsObj; 766 782 RT_ZERO(fsObj); /* Shut up MSVC. */ 767 783 768 char *pszMIMEHint = NULL; 769 770 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnQueryInfo, pReq->pszUrl, &fsObj, &pszMIMEHint); 784 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnQueryInfo, pReq, &fsObj, NULL /* pszMIMEHint */); 771 785 if (RT_SUCCESS(rc)) 772 786 { … … 805 819 return rc; 806 820 } 821 822 #ifdef RTHTTP_WITH_WEBDAV 823 /** 824 * Handler for the OPTIONS method. 825 * 826 * @returns VBox status code. 827 * @param pClient Client to handle OPTIONS method for. 828 * @param pReq Client request to handle. 829 */ 830 static DECLCALLBACK(int) rtHttpServerHandleOPTIONS(PRTHTTPSERVERCLIENT pClient, PRTHTTPSERVERREQ pReq) 831 { 832 LogFlowFuncEnter(); 833 834 RT_NOREF(pReq); 835 836 int rc = rtHttpServerSendResponseEx(pClient, RTHTTPSTATUS_OK, NULL /* pHdrLst */); 837 838 LogFlowFuncLeaveRC(rc); 839 return rc; 840 } 841 842 /** 843 * Handler for the PROPFIND (WebDAV) method. 844 * 845 * @returns VBox status code. 846 * @param pClient Client to handle PROPFIND method for. 847 * @param pReq Client request to handle. 848 */ 849 static DECLCALLBACK(int) rtHttpServerHandlePROPFIND(PRTHTTPSERVERCLIENT pClient, PRTHTTPSERVERREQ pReq) 850 { 851 LogFlowFuncEnter(); 852 853 int rc = VINF_SUCCESS; 854 855 /* If a low-level GET request handler is defined, call it and return. */ 856 RTHTTPSERVER_HANDLE_CALLBACK_VA_RET(pfnOnGetRequest, pReq); 857 858 RTFSOBJINFO fsObj; 859 RT_ZERO(fsObj); /* Shut up MSVC. */ 860 861 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnQueryInfo, pReq, &fsObj, NULL /* pszMIMEHint */); 862 if (RT_FAILURE(rc)) 863 return rc; 864 865 void *pvHandle = NULL; 866 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnOpen, pReq, &pvHandle); 867 868 if (RT_SUCCESS(rc)) 869 { 870 size_t cbBuf = _64K; 871 void *pvBuf = RTMemAlloc(cbBuf); 872 AssertPtrReturn(pvBuf, VERR_NO_MEMORY); 873 874 for (;;) 875 { 876 RTHTTPHEADERLIST HdrLst; 877 rc = RTHttpHeaderListInit(&HdrLst); 878 AssertRCReturn(rc, rc); 879 880 char szVal[16]; 881 882 rc = RTHttpHeaderListAdd(HdrLst, "Content-Type", "text/xml; charset=utf-8", strlen("text/xml; charset=utf-8"), RTHTTPHEADERLISTADD_F_BACK); 883 AssertRCBreak(rc); 884 885 /* Note: For directories fsObj.cbObject contains the actual size (in bytes) 886 * of the body data for the directory listing. */ 887 888 ssize_t cch = RTStrPrintf2(szVal, sizeof(szVal), "%RU64", fsObj.cbObject); 889 AssertBreakStmt(cch, VERR_BUFFER_OVERFLOW); 890 rc = RTHttpHeaderListAdd(HdrLst, "Content-Length", szVal, strlen(szVal), RTHTTPHEADERLISTADD_F_BACK); 891 AssertRCBreak(rc); 892 893 rc = rtHttpServerSendResponseEx(pClient, RTHTTPSTATUS_MULTISTATUS, &HdrLst); 894 AssertRCReturn(rc, rc); 895 896 RTHttpHeaderListDestroy(HdrLst); 897 898 size_t cbToRead = fsObj.cbObject; 899 size_t cbRead = 0; /* Shut up GCC. */ 900 size_t cbWritten = 0; /* Ditto. */ 901 while (cbToRead) 902 { 903 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnRead, pvHandle, pvBuf, RT_MIN(cbBuf, cbToRead), &cbRead); 904 if (RT_FAILURE(rc)) 905 break; 906 rtHttpServerLogProto(pClient, true /* fWrite */, (const char *)pvBuf); 907 rc = rtHttpServerSendResponseBody(pClient, pvBuf, cbRead, &cbWritten); 908 AssertBreak(cbToRead >= cbWritten); 909 cbToRead -= cbWritten; 910 if (rc == VERR_NET_CONNECTION_RESET_BY_PEER) /* Clients often apruptly abort the connection when done. */ 911 { 912 rc = VINF_SUCCESS; 913 break; 914 } 915 AssertRCBreak(rc); 916 } 917 918 break; 919 } /* for (;;) */ 920 921 RTMemFree(pvBuf); 922 923 int rc2 = rc; /* Save rc. */ 924 925 RTHTTPSERVER_HANDLE_CALLBACK_VA(pfnClose, pvHandle); 926 927 if (RT_FAILURE(rc2)) /* Restore original rc on failure. */ 928 rc = rc2; 929 } 930 931 LogFlowFuncLeaveRC(rc); 932 return rc; 933 } 934 #endif /* RTHTTP_WITH_WEBDAV */ 807 935 808 936 /** … … 912 1040 913 1041 /* Note: Method names are case sensitive. */ 914 if (!RTStrCmp(pszReq, "GET")) pReq->enmMethod = RTHTTPMETHOD_GET; 915 else if (!RTStrCmp(pszReq, "HEAD")) pReq->enmMethod = RTHTTPMETHOD_HEAD; 1042 if (!RTStrCmp(pszReq, "GET")) pReq->enmMethod = RTHTTPMETHOD_GET; 1043 else if (!RTStrCmp(pszReq, "HEAD")) pReq->enmMethod = RTHTTPMETHOD_HEAD; 1044 #ifdef RTHTTP_WITH_WEBDAV 1045 else if (!RTStrCmp(pszReq, "OPTIONS")) pReq->enmMethod = RTHTTPMETHOD_OPTIONS; 1046 else if (!RTStrCmp(pszReq, "PROPFIND")) pReq->enmMethod = RTHTTPMETHOD_PROPFIND; 1047 #endif 916 1048 else 917 1049 return VERR_NOT_SUPPORTED; … … 1122 1254 AssertPtr(pThis->pTCPServer); 1123 1255 1124 int rc = RTTcpServerDestroy(pThis->pTCPServer); 1256 int rc = VINF_SUCCESS; 1257 1258 PRTHTTPSERVERCALLBACKS pCallbacks = &pThis->Callbacks; 1259 if (pCallbacks->pfnDestroy) 1260 { 1261 RTHTTPCALLBACKDATA Data = { NULL /* pClient */, pThis->pvUser, pThis->cbUser }; 1262 rc = pCallbacks->pfnDestroy(&Data); 1263 } 1264 1125 1265 if (RT_SUCCESS(rc)) 1126 1266 { 1127 pThis->u32Magic = RTHTTPSERVER_MAGIC_DEAD; 1128 1129 RTMemFree(pThis); 1130 } 1131 1132 return rc; 1133 } 1267 rc = RTTcpServerDestroy(pThis->pTCPServer); 1268 if (RT_SUCCESS(rc)) 1269 { 1270 pThis->u32Magic = RTHTTPSERVER_MAGIC_DEAD; 1271 1272 RTMemFree(pThis); 1273 } 1274 } 1275 1276 return rc; 1277 } -
trunk/src/VBox/Runtime/tools/RTHttpServer.cpp
r87018 r87032 49 49 #include <iprt/getopt.h> 50 50 #include <iprt/initterm.h> 51 #define LOG_GROUP RTLOGGROUP_HTTP 52 #include <iprt/log.h> 51 53 #include <iprt/mem.h> 52 54 #include <iprt/message.h> … … 286 288 continue; 287 289 } 288 else if (rc != VERR_NO_MORE_FILES)290 else 289 291 break; 290 292 } … … 309 311 } 310 312 311 static int dirEntryWrite(char *pszBuf, size_t cbBuf, 312 const char *pszEntry, const PRTFSOBJINFO pObjInfo, size_t *pcbWritten) 313 { 313 #ifdef RTHTTP_WITH_WEBDAV 314 static int dirEntryWriteDAV(char *pszBuf, size_t cbBuf, 315 const char *pszEntry, const PRTFSOBJINFO pObjInfo, size_t *pcbWritten) 316 { 317 char szBirthTime[32]; 318 if (RTTimeSpecToString(&pObjInfo->BirthTime, szBirthTime, sizeof(szBirthTime)) == NULL) 319 return VERR_BUFFER_UNDERFLOW; 320 314 321 char szModTime[32]; 315 322 if (RTTimeSpecToString(&pObjInfo->ModificationTime, szModTime, sizeof(szModTime)) == NULL) … … 318 325 int rc = VINF_SUCCESS; 319 326 320 ssize_t cch = RTStrPrintf2(pszBuf, cbBuf, "201: %s %RU64 %s %s\r\n", 321 pszEntry, pObjInfo->cbObject, szModTime, 322 /** @todo Very crude; only files and directories are supported for now. */ 323 RTFS_IS_FILE(pObjInfo->Attr.fMode) ? "FILE" : "DIRECTORY"); 327 /** 328 * !!! HACK ALERT !!! 329 ** @todo Build up and use a real XML DOM here. Works with Gnome / Gvfs-compatible apps though. 330 */ 331 ssize_t cch = RTStrPrintf(pszBuf, cbBuf, 332 "<d:response>" 333 "<d:href>%s</d:href>" 334 "<d:propstat>" 335 "<d:status>HTTP/1.1 200 OK</d:status>" 336 "<d:prop>" 337 "<d:displayname>%s</d:displayname>" 338 "<d:getcontentlength>%RU64</d:getcontentlength>" 339 "<d:getcontenttype>%s</d:getcontenttype>" 340 "<d:creationdate>%s</d:creationdate>" 341 "<d:getlastmodified>%s</d:getlastmodified>" 342 "<d:getetag/>" 343 "<d:resourcetype><d:collection/></d:resourcetype>" 344 "</d:prop>" 345 "</d:propstat>" 346 "</d:response>", 347 pszEntry, pszEntry, pObjInfo->cbObject, "application/octet-stream", szBirthTime, szModTime); 348 324 349 if (cch <= 0) 325 350 rc = VERR_BUFFER_OVERFLOW; 351 352 *pcbWritten = cch; 353 354 return rc; 355 } 356 #endif /* RTHTTP_WITH_WEBDAV */ 357 358 static int dirEntryWrite(RTHTTPMETHOD enmMethod, char *pszBuf, size_t cbBuf, 359 const char *pszEntry, const PRTFSOBJINFO pObjInfo, size_t *pcbWritten) 360 { 361 char szModTime[32]; 362 if (RTTimeSpecToString(&pObjInfo->ModificationTime, szModTime, sizeof(szModTime)) == NULL) 363 return VERR_BUFFER_UNDERFLOW; 364 365 int rc = VINF_SUCCESS; 366 367 ssize_t cch = 0; 368 369 if (enmMethod == RTHTTPMETHOD_GET) 370 { 371 cch = RTStrPrintf2(pszBuf, cbBuf, "201: %s %RU64 %s %s\r\n", 372 pszEntry, pObjInfo->cbObject, szModTime, 373 /** @todo Very crude; only files and directories are supported for now. */ 374 RTFS_IS_FILE(pObjInfo->Attr.fMode) ? "FILE" : "DIRECTORY"); 375 if (cch <= 0) 376 rc = VERR_BUFFER_OVERFLOW; 377 } 378 #ifdef RTHTTP_WITH_WEBDAV 379 else if (enmMethod == RTHTTPMETHOD_PROPFIND) 380 { 381 char szBuf[RTPATH_MAX + _4K]; /** @todo Just a rough guesstimate. */ 382 rc = dirEntryWriteDAV(szBuf, sizeof(szBuf), pszEntry, pObjInfo, (size_t *)&cch); 383 if (RT_SUCCESS(rc)) 384 rc = RTStrCat(pszBuf, cbBuf, szBuf); 385 AssertRC(rc); 386 } 387 #endif /* RTHTTP_WITH_WEBDAV */ 388 else 389 rc = VERR_NOT_SUPPORTED; 326 390 327 391 if (RT_SUCCESS(rc)) … … 361 425 } 362 426 363 DECLCALLBACK(int) onOpen(PRTHTTPCALLBACKDATA pData, const char *pszUrl, void **ppvHandle)427 DECLCALLBACK(int) onOpen(PRTHTTPCALLBACKDATA pData, PRTHTTPSERVERREQ pReq, void **ppvHandle) 364 428 { 365 429 PHTTPSERVERDATA pThis = (PHTTPSERVERDATA)pData->pvUser; … … 367 431 368 432 char *pszPathAbs = NULL; 369 int rc = pathResolve(pThis, p szUrl, &pszPathAbs);433 int rc = pathResolve(pThis, pReq->pszUrl, &pszPathAbs); 370 434 if (RT_SUCCESS(rc)) 371 435 { … … 395 459 RTStrFree(pszPathAbs); 396 460 } 461 462 LogFlowFuncLeaveRC(rc); 397 463 return rc; 398 464 } … … 404 470 405 471 AssertReturn(*(uint64_t *)pvHandle == 42 /** @todo Fudge. */, VERR_NOT_FOUND); 472 473 int rc; 406 474 407 475 if (RTFS_IS_DIRECTORY(pThis->fMode)) … … 416 484 *pcbRead = cbToCopy; 417 485 418 r eturnVINF_SUCCESS;486 rc = VINF_SUCCESS; 419 487 } 420 488 else if (RTFS_IS_FILE(pThis->fMode)) 421 return RTFileRead(pThis->h.File, pvBuf, cbBuf, pcbRead); 422 423 return VERR_NOT_IMPLEMENTED; /* Never reached. */ 489 { 490 rc = RTFileRead(pThis->h.File, pvBuf, cbBuf, pcbRead); 491 } 492 else 493 rc = VERR_NOT_SUPPORTED; 494 495 LogFlowFuncLeaveRC(rc); 496 return rc; 424 497 } 425 498 … … 445 518 pvHandle = NULL; 446 519 520 LogFlowFuncLeaveRC(rc); 447 521 return rc; 448 522 } 449 523 450 524 DECLCALLBACK(int) onQueryInfo(PRTHTTPCALLBACKDATA pData, 451 const char *pszUrl, PRTFSOBJINFO pObjInfo, char **ppszMIMEHint)525 PRTHTTPSERVERREQ pReq, PRTFSOBJINFO pObjInfo, char **ppszMIMEHint) 452 526 { 453 527 PHTTPSERVERDATA pThis = (PHTTPSERVERDATA)pData->pvUser; 454 528 Assert(pData->cbUser == sizeof(HTTPSERVERDATA)); 455 529 530 /** !!!! WARNING !!! 531 ** 532 ** Not production-ready code below! 533 ** @todo Use something like bodyAdd() instead of the RTStrPrintf2() hacks. 534 ** 535 ** !!!! WARNING !!! */ 536 456 537 char *pszPathAbs = NULL; 457 int rc = pathResolve(pThis, p szUrl, &pszPathAbs);538 int rc = pathResolve(pThis, pReq->pszUrl, &pszPathAbs); 458 539 if (RT_SUCCESS(rc)) 459 540 { … … 471 552 { 472 553 RTHttpServerResponseDestroy(pResp); 473 RTHttpServerResponseInitEx(pResp, _4K); 554 RTHttpServerResponseInitEx(pResp, _64K); /** @todo Make this more dynamic. */ 555 556 char *pszBody = (char *)pResp->pvBody; 557 size_t cbBodyLeft = pResp->cbBodyAlloc; 474 558 475 559 /* 476 560 * Write body header. 477 561 */ 478 ssize_t cch = RTStrPrintf2((char *)pResp->pvBody, pResp->cbBodyAlloc, 479 "300: file://%s\r\n" 480 "200: filename content-length last-modified file-type\r\n", 481 pszUrl); 482 RT_NOREF(cch); 483 Assert(cch); 484 485 pResp->cbBodyUsed = strlen((char *)pResp->pvBody); 486 562 if (pReq->enmMethod == RTHTTPMETHOD_GET) 563 { 564 ssize_t cch = RTStrPrintf2(pszBody, cbBodyLeft, 565 "300: file://%s\r\n" 566 "200: filename content-length last-modified file-type\r\n", 567 pReq->pszUrl); 568 Assert(cch); 569 pszBody += cch; 570 cbBodyLeft -= cch; 571 } 572 #ifdef RTHTTP_WITH_WEBDAV 573 else if (pReq->enmMethod == RTHTTPMETHOD_PROPFIND) 574 { 575 ssize_t cch = RTStrPrintf2(pszBody, cbBodyLeft, "<?xml version=\"1.0\" encoding=\"utf-8\"?>\r\n"); 576 Assert(cch); 577 pszBody += cch; 578 cbBodyLeft -= cch; 579 580 cch = RTStrPrintf2(pszBody, cbBodyLeft, "<d:multistatus xmlns:d=\"DAV:\">\r\n"); 581 Assert(cch); 582 pszBody += cch; 583 cbBodyLeft -= cch; 584 585 rc = dirEntryWriteDAV(pszBody, cbBodyLeft, "/", &objInfo, (size_t *)&cch); 586 AssertRC(rc); 587 pszBody += cch; 588 cbBodyLeft -= cch; 589 } 590 #endif /* RTHTTP_WITH_WEBDAV */ 487 591 /* 488 592 * Write body entries. … … 492 596 while (RT_SUCCESS(rc = dirRead(hVfsDir, &pszEntry, &fsObjInfo))) 493 597 { 494 char *pszBody = (char *)pResp->pvBody; 495 496 size_t cbWritten; 497 rc = dirEntryWrite(&pszBody[pResp->cbBodyUsed], pResp->cbBodyAlloc - pResp->cbBodyUsed, pszEntry, &fsObjInfo, &cbWritten); 598 size_t cbWritten = 0; 599 rc = dirEntryWrite(pReq->enmMethod, pszBody, cbBodyLeft, pszEntry, &fsObjInfo, &cbWritten); 498 600 if (rc == VERR_BUFFER_OVERFLOW) 499 601 { 500 pResp->cbBodyAlloc *= 2; /** @todo Improve this. */602 pResp->cbBodyAlloc += _4K; /** @todo Improve this. */ 501 603 pResp->pvBody = RTMemRealloc(pResp->pvBody, pResp->cbBodyAlloc); 502 604 AssertPtrBreakStmt(pResp->pvBody, rc = VERR_NO_MEMORY); 503 605 504 606 pszBody = (char *)pResp->pvBody; 505 506 rc = dirEntryWrite(&pszBody[pResp->cbBodyUsed], pResp->cbBodyAlloc - pResp->cbBodyUsed, pszEntry, &fsObjInfo, &cbWritten); 607 cbBodyLeft += _4K; /** @todo Ditto. */ 608 609 rc = dirEntryWrite(pReq->enmMethod, pszBody, cbBodyLeft, pszEntry, &fsObjInfo, &cbWritten); 507 610 } 508 611 509 if (RT_SUCCESS(rc)) 510 pResp->cbBodyUsed += cbWritten; 612 if ( RT_SUCCESS(rc) 613 && cbWritten) 614 { 615 pszBody += cbWritten; 616 Assert(cbBodyLeft > cbWritten); 617 cbBodyLeft -= cbWritten; 618 } 511 619 512 620 RTStrFree(pszEntry); … … 521 629 dirClose(hVfsDir); 522 630 631 /* 632 * Write footers, if any. 633 */ 523 634 if (RT_SUCCESS(rc)) 524 635 { 525 rc = RTStrAPrintf(ppszMIMEHint, "text/plain"); 526 if (RT_SUCCESS(rc)) 527 pObjInfo->cbObject = pResp->cbBodyUsed; 636 if (pReq->enmMethod == RTHTTPMETHOD_GET) 637 { 638 if (ppszMIMEHint) 639 rc = RTStrAPrintf(ppszMIMEHint, "text/plain"); 640 } 641 #ifdef RTHTTP_WITH_WEBDAV 642 else if (pReq->enmMethod == RTHTTPMETHOD_PROPFIND) 643 { 644 /** 645 * !!! HACK ALERT !!! 646 ** @todo Build up and use a real XML DOM here. Works with Gnome / Gvfs-compatible apps though. 647 */ 648 ssize_t cch = RTStrPrintf2(pszBody, cbBodyLeft, "</d:multistatus>\r\n"); 649 Assert(cch); 650 RT_NOREF(cch); 651 } 652 #endif /* RTHTTP_WITH_WEBDAV */ 653 654 pResp->cbBodyUsed = strlen((char *)pResp->pvBody); 655 656 pObjInfo->cbObject = pResp->cbBodyUsed; 528 657 } 529 658 } … … 541 670 } 542 671 } 672 else 673 rc = VERR_NOT_SUPPORTED; 543 674 } 544 675 … … 546 677 } 547 678 679 LogFlowFuncLeaveRC(rc); 548 680 return rc; 681 } 682 683 DECLCALLBACK(int) onDestroy(PRTHTTPCALLBACKDATA pData) 684 { 685 PHTTPSERVERDATA pThis = (PHTTPSERVERDATA)pData->pvUser; 686 Assert(pData->cbUser == sizeof(HTTPSERVERDATA)); 687 688 RTHttpServerResponseDestroy(&pThis->Resp); 689 690 return VINF_SUCCESS; 549 691 } 550 692 … … 650 792 Callbacks.pfnClose = onClose; 651 793 Callbacks.pfnQueryInfo = onQueryInfo; 794 Callbacks.pfnDestroy = onDestroy; 652 795 653 796 g_HttpServerData.h.File = NIL_RTFILE;
Note:
See TracChangeset
for help on using the changeset viewer.