@@ -43,7 +43,7 @@ using namespace httpsserver;
43
43
44
44
static const char *const HTML_ENTITY_FAILED_CROSS = " ❌" ;
45
45
static const char *const HTML_ENTITY_OK_MARK = " ✅" ;
46
-
46
+ static const char * const HTML_ENTITY_WASTEBASKED = " 🗑 " ;
47
47
static const char *const HTTP_GET = " GET" ;
48
48
static const char *const HTTP_POST = " POST" ;
49
49
@@ -70,6 +70,7 @@ static const char* const header =
70
70
// STYLE
71
71
" <style>"
72
72
" #file-input,input, button {width:100%;height:44px;border-radius:4px;margin:10px auto;font-size:15px;}"
73
+ " .small {height:12px;width:12px;margin:2px}"
73
74
" input, button, a.back {background:#f1f1f1;border:0;padding:0;text-align:center;}"
74
75
" body {background:#3498db;font-family:sans-serif;font-size:12px;color:#777}"
75
76
" #file-input {padding:0 5px;border:1px solid #ddd;line-height:44px;text-align:left;display:block;cursor:pointer}"
@@ -437,6 +438,7 @@ static void handleMakeCurrentLocationPrivate(HTTPRequest * req, HTTPResponse * r
437
438
static void handlePrivacy (HTTPRequest *req, HTTPResponse *res);
438
439
static void handlePrivacyDeleteAction (HTTPRequest *req, HTTPResponse *res);
439
440
static void handleSd (HTTPRequest *req, HTTPResponse *res);
441
+ static void handleDeleteFiles (HTTPRequest *req, HTTPResponse *res);
440
442
static void handleDelete (HTTPRequest *req, HTTPResponse *res);
441
443
static void handleDeleteAction (HTTPRequest *req, HTTPResponse *res);
442
444
@@ -481,6 +483,7 @@ void beginPages() {
481
483
server->registerNode (new ResourceNode (" /settings/privacy" , HTTP_GET, handlePrivacy));
482
484
server->registerNode (new ResourceNode (" /privacy_delete" , HTTP_GET, handlePrivacyDeleteAction));
483
485
server->registerNode (new ResourceNode (" /sd" , HTTP_GET, handleSd));
486
+ server->registerNode (new ResourceNode (" /deleteFiles" , HTTP_POST, handleDeleteFiles));
484
487
485
488
server->addMiddleware (&accessFilter);
486
489
server->setDefaultHeader (" Server" , std::string (" OBS/" ) + OBSVersion);
@@ -491,8 +494,8 @@ void beginPages() {
491
494
492
495
493
496
void createHttpServer () {
494
- server = new HTTPSServer (&obsCert);
495
- insecureServer = new HTTPServer ();
497
+ server = new HTTPSServer (&obsCert, 443 , 2 );
498
+ insecureServer = new HTTPServer (80 , 1 );
496
499
497
500
log_i (" About to create pages." );
498
501
beginPages ();
@@ -1442,6 +1445,57 @@ static void handleFlashFileUpdateAction(HTTPRequest *req, HTTPResponse *res) {
1442
1445
sensorManager->attachInterrupts ();
1443
1446
}
1444
1447
1448
+ static void handleDeleteFiles (HTTPRequest *req, HTTPResponse * res) {
1449
+ const auto params = extractParameters (req);
1450
+ String path = getParameter (params, " path" );
1451
+ if (path != " trash" ) {
1452
+ SD.mkdir (" /trash" );
1453
+ }
1454
+
1455
+ String html = replaceDefault (header, " Delete Files" );
1456
+ html += " <h3>Deleting files</h3>" ;
1457
+ html += " <div>In: " + ObsUtils::encodeForXmlText (path);
1458
+ html += " </div><br /><div>" ;
1459
+ sendHtml (res, html);
1460
+ html.clear ();
1461
+
1462
+ for (auto param : params) {
1463
+ if (param.first == " delete" ) {
1464
+ String file = param.second ;
1465
+
1466
+ String fullName = path + (path.length () > 1 ? " /" : " " ) + file;
1467
+
1468
+ html += ObsUtils::encodeForXmlText (file) + " ➜ " ;
1469
+ if (path != " trash" ) {
1470
+ if (SD.rename (fullName, " /trash/" + file)) {
1471
+ log_i (" Moved '%s'." , fullName.c_str ());
1472
+ html += HTML_ENTITY_WASTEBASKED;
1473
+ } else {
1474
+ log_w (" Failed to move '%s'." , fullName.c_str ());
1475
+ html += HTML_ENTITY_FAILED_CROSS;
1476
+ }
1477
+ } else {
1478
+ if (SD.remove (fullName)) {
1479
+ log_i (" Deleted '%s'." , fullName.c_str ());
1480
+ html += HTML_ENTITY_WASTEBASKED;
1481
+ } else {
1482
+ log_w (" Failed to delete '%s'." , fullName.c_str ());
1483
+ html += HTML_ENTITY_FAILED_CROSS;
1484
+ }
1485
+ }
1486
+ html += " <br />\n " ;
1487
+ res->print (html);
1488
+ html.clear ();
1489
+ }
1490
+ }
1491
+ html += " </div>" ;
1492
+ html += " <input type=button onclick=\" window.location.href='/sd?path="
1493
+ + ObsUtils::encodeForUrl (path) + " '\" class='btn' value='Back' />" ;
1494
+ html += footer;
1495
+ res->print (html);
1496
+ }
1497
+
1498
+
1445
1499
static void handleSd (HTTPRequest *req, HTTPResponse *res) {
1446
1500
String path = getParameter (req, " path" , " /" );
1447
1501
@@ -1454,7 +1508,9 @@ static void handleSd(HTTPRequest *req, HTTPResponse *res) {
1454
1508
1455
1509
if (file.isDirectory ()) {
1456
1510
String html = header;
1457
- html = replaceDefault (html, " SD Card Contents " + String (file.name ()));
1511
+ html = replaceDefault (html, " SD Card Contents " + String (file.name ()), " /deleteFiles" );
1512
+
1513
+ html += " <input type='hidden' name='path' value='" + ObsUtils::encodeForXmlAttribute (path) + " '/>" ;
1458
1514
html += " <ul class=\" directory-listing\" >" ;
1459
1515
sendHtml (res, html);
1460
1516
html.clear ();
@@ -1468,12 +1524,20 @@ static void handleSd(HTTPRequest *req, HTTPResponse *res) {
1468
1524
displayTest->drawWaitBar (5 , counter++);
1469
1525
1470
1526
auto fileName = String (child.name ());
1527
+ auto fileTip = ObsUtils::encodeForXmlAttribute (
1528
+ ObsUtils::dateTimeToString (child.getLastWrite ())
1529
+ + " - " + ObsUtils::toScaledByteString (child.size ()));
1530
+
1471
1531
fileName = fileName.substring (int (fileName.lastIndexOf (" /" ) + 1 ));
1532
+ fileName = ObsUtils::encodeForXmlAttribute (fileName);
1472
1533
bool isDirectory = child.isDirectory ();
1473
1534
html +=
1474
1535
(" <li class=\" "
1475
1536
+ String (isDirectory ? " directory" : " file" )
1476
- + " \" ><a href=\" /sd?path="
1537
+ + " \" title='" + fileTip + " '>"
1538
+ + " <input class='small' type='checkbox' value='" + fileName + " ' name='delete'"
1539
+ + String (isDirectory ? " disabled" : " " )
1540
+ + " ><a href=\" /sd?path="
1477
1541
+ String (child.name ())
1478
1542
+ " \" >"
1479
1543
+ String (isDirectory ? " 📁" : " 📄" )
@@ -1491,6 +1555,26 @@ static void handleSd(HTTPRequest *req, HTTPResponse *res) {
1491
1555
}
1492
1556
file.close ();
1493
1557
html += " </ul>" ;
1558
+
1559
+ if (path != " /" ) {
1560
+ String back = path.substring (0 , path.lastIndexOf (' /' ));
1561
+ if (back.isEmpty ()) {
1562
+ back = " /" ;
1563
+ }
1564
+ html += " <input type=button onclick=\" window.location.href='/sd?path="
1565
+ + ObsUtils::encodeForUrl (back) + " '\" class='btn' value='Up' />" ;
1566
+ } else {
1567
+ html += " <input type=button onclick=\" window.location.href='/'\" "
1568
+ " class='btn' value='Menu' />" ;
1569
+ }
1570
+
1571
+ if (counter > 0 ) {
1572
+ if (path == " /trash" ) {
1573
+ html += " <hr /><input type='submit' class='btn' value='Delete Selected' />" ;
1574
+ } else {
1575
+ html += " <hr /><input type='submit' class='btn' value='Move to Trash' />" ;
1576
+ }
1577
+ }
1494
1578
html += footer;
1495
1579
res->print (html);
1496
1580
displayTest->clearProgressBar (5 );
0 commit comments