Changeset 87032 in vbox for trunk/src/VBox/Runtime/tools
- Timestamp:
- Dec 2, 2020 4:33:29 PM (4 years ago)
- svn:sync-xref-src-repo-rev:
- 141673
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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.