Fossil SCM
Add a "logo" image to the local server state. Return this image on all requests to the "/logo" URL. All the administrator to setup that image. Include the image in the default header.
Commit
43481115ed929aec6c2694cd918221bea542da25
Parent
7100babda6b4484…
5 files changed
+2
+89
+58
+4
-3
+38
-13
+2
| --- src/configure.c | ||
| +++ src/configure.c | ||
| @@ -76,10 +76,12 @@ | ||
| 76 | 76 | int groupMask; /* Which config groups is it part of */ |
| 77 | 77 | } aConfig[] = { |
| 78 | 78 | { "css", CONFIGSET_SKIN }, |
| 79 | 79 | { "header", CONFIGSET_SKIN }, |
| 80 | 80 | { "footer", CONFIGSET_SKIN }, |
| 81 | + { "logo-mimetype", CONFIGSET_SKIN }, | |
| 82 | + { "logo-image", CONFIGSET_SKIN }, | |
| 81 | 83 | { "project-name", CONFIGSET_PROJ }, |
| 82 | 84 | { "project-description", CONFIGSET_PROJ }, |
| 83 | 85 | { "index-page", CONFIGSET_SKIN }, |
| 84 | 86 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 85 | 87 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 86 | 88 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -76,10 +76,12 @@ | |
| 76 | int groupMask; /* Which config groups is it part of */ |
| 77 | } aConfig[] = { |
| 78 | { "css", CONFIGSET_SKIN }, |
| 79 | { "header", CONFIGSET_SKIN }, |
| 80 | { "footer", CONFIGSET_SKIN }, |
| 81 | { "project-name", CONFIGSET_PROJ }, |
| 82 | { "project-description", CONFIGSET_PROJ }, |
| 83 | { "index-page", CONFIGSET_SKIN }, |
| 84 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 85 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 86 |
| --- src/configure.c | |
| +++ src/configure.c | |
| @@ -76,10 +76,12 @@ | |
| 76 | int groupMask; /* Which config groups is it part of */ |
| 77 | } aConfig[] = { |
| 78 | { "css", CONFIGSET_SKIN }, |
| 79 | { "header", CONFIGSET_SKIN }, |
| 80 | { "footer", CONFIGSET_SKIN }, |
| 81 | { "logo-mimetype", CONFIGSET_SKIN }, |
| 82 | { "logo-image", CONFIGSET_SKIN }, |
| 83 | { "project-name", CONFIGSET_PROJ }, |
| 84 | { "project-description", CONFIGSET_PROJ }, |
| 85 | { "index-page", CONFIGSET_SKIN }, |
| 86 | { "timeline-block-markup", CONFIGSET_SKIN }, |
| 87 | { "timeline-max-comment", CONFIGSET_SKIN }, |
| 88 |
+89
| --- src/doc.c | ||
| +++ src/doc.c | ||
| @@ -469,5 +469,94 @@ | ||
| 469 | 469 | style_header("Document Not Found"); |
| 470 | 470 | @ <p>No such document: %h(PD("name","tip/index.wiki"))</p> |
| 471 | 471 | style_footer(); |
| 472 | 472 | return; |
| 473 | 473 | } |
| 474 | + | |
| 475 | +/* | |
| 476 | +** The default logo. | |
| 477 | +*/ | |
| 478 | +static const unsigned char aLogo[] = { | |
| 479 | + 71, 73, 70, 56, 55, 97, 62, 0, 71, 0, 244, 0, 0, 85, | |
| 480 | + 129, 149, 95, 136, 155, 99, 139, 157, 106, 144, 162, 113, 150, 166, | |
| 481 | + 116, 152, 168, 127, 160, 175, 138, 168, 182, 148, 176, 188, 159, 184, | |
| 482 | + 195, 170, 192, 202, 180, 199, 208, 184, 202, 210, 191, 207, 215, 201, | |
| 483 | + 215, 221, 212, 223, 228, 223, 231, 235, 226, 227, 226, 226, 234, 237, | |
| 484 | + 233, 239, 241, 240, 244, 246, 244, 247, 248, 255, 255, 255, 0, 0, | |
| 485 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, | |
| 486 | + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, | |
| 487 | + 0, 0, 62, 0, 71, 0, 0, 5, 255, 96, 100, 141, 100, 105, | |
| 488 | + 158, 168, 37, 41, 132, 192, 164, 112, 44, 207, 102, 99, 0, 56, | |
| 489 | + 16, 84, 116, 239, 199, 141, 65, 110, 232, 248, 25, 141, 193, 161, | |
| 490 | + 82, 113, 108, 202, 32, 55, 229, 210, 73, 61, 41, 164, 88, 102, | |
| 491 | + 181, 10, 41, 96, 179, 91, 106, 35, 240, 5, 135, 143, 137, 242, | |
| 492 | + 87, 123, 246, 33, 190, 81, 108, 163, 237, 198, 14, 30, 113, 233, | |
| 493 | + 131, 78, 115, 72, 11, 115, 87, 101, 19, 124, 51, 66, 74, 8, | |
| 494 | + 19, 16, 67, 100, 74, 133, 50, 15, 101, 135, 56, 11, 74, 6, | |
| 495 | + 143, 49, 126, 106, 56, 8, 145, 67, 9, 152, 48, 139, 155, 5, | |
| 496 | + 22, 13, 74, 115, 161, 41, 147, 101, 13, 130, 57, 132, 170, 40, | |
| 497 | + 167, 155, 0, 94, 57, 3, 178, 48, 183, 181, 57, 160, 186, 40, | |
| 498 | + 19, 141, 189, 0, 69, 192, 40, 16, 195, 155, 185, 199, 41, 201, | |
| 499 | + 189, 191, 205, 193, 188, 131, 210, 49, 175, 88, 209, 214, 38, 19, | |
| 500 | + 3, 11, 19, 111, 127, 60, 219, 39, 55, 204, 19, 11, 6, 100, | |
| 501 | + 5, 10, 227, 228, 37, 163, 0, 239, 117, 56, 238, 243, 49, 195, | |
| 502 | + 177, 247, 48, 158, 56, 251, 50, 216, 254, 197, 56, 128, 107, 158, | |
| 503 | + 2, 125, 171, 114, 92, 218, 246, 96, 66, 3, 4, 50, 134, 176, | |
| 504 | + 145, 6, 97, 64, 144, 24, 19, 136, 108, 91, 177, 160, 0, 194, | |
| 505 | + 19, 253, 0, 216, 107, 214, 224, 192, 129, 5, 16, 83, 255, 244, | |
| 506 | + 43, 213, 195, 24, 159, 27, 169, 64, 230, 88, 208, 227, 129, 182, | |
| 507 | + 54, 4, 89, 158, 24, 181, 163, 199, 1, 155, 52, 233, 8, 130, | |
| 508 | + 176, 83, 24, 128, 137, 50, 18, 32, 48, 48, 114, 11, 173, 137, | |
| 509 | + 19, 110, 4, 64, 105, 1, 194, 30, 140, 68, 15, 24, 24, 224, | |
| 510 | + 50, 76, 70, 0, 11, 171, 54, 26, 160, 181, 194, 149, 148, 40, | |
| 511 | + 174, 148, 122, 64, 180, 208, 161, 17, 207, 112, 164, 1, 128, 96, | |
| 512 | + 148, 78, 18, 21, 194, 33, 229, 51, 247, 65, 133, 97, 5, 250, | |
| 513 | + 69, 229, 100, 34, 220, 128, 166, 116, 190, 62, 8, 167, 195, 170, | |
| 514 | + 47, 163, 0, 130, 90, 152, 11, 160, 173, 170, 27, 154, 26, 91, | |
| 515 | + 232, 151, 171, 18, 14, 162, 253, 98, 170, 18, 70, 171, 64, 219, | |
| 516 | + 10, 67, 136, 134, 187, 116, 75, 180, 46, 179, 174, 135, 4, 189, | |
| 517 | + 229, 231, 78, 40, 10, 62, 226, 164, 172, 64, 240, 167, 170, 10, | |
| 518 | + 18, 124, 188, 10, 107, 65, 193, 94, 11, 93, 171, 28, 248, 17, | |
| 519 | + 239, 46, 140, 78, 97, 34, 25, 153, 36, 99, 65, 130, 7, 203, | |
| 520 | + 183, 168, 51, 34, 136, 25, 140, 10, 6, 16, 28, 255, 145, 241, | |
| 521 | + 230, 140, 10, 66, 178, 167, 112, 48, 192, 128, 129, 9, 31, 141, | |
| 522 | + 84, 138, 63, 163, 162, 2, 203, 206, 240, 56, 55, 98, 192, 188, | |
| 523 | + 15, 185, 50, 160, 6, 0, 125, 62, 33, 214, 195, 33, 5, 24, | |
| 524 | + 184, 25, 231, 14, 201, 245, 144, 23, 126, 104, 228, 0, 145, 2, | |
| 525 | + 13, 140, 244, 212, 17, 21, 20, 176, 159, 17, 95, 225, 160, 128, | |
| 526 | + 16, 1, 32, 224, 142, 32, 227, 125, 87, 64, 0, 16, 54, 129, | |
| 527 | + 205, 2, 141, 76, 53, 130, 103, 37, 166, 64, 144, 107, 78, 196, | |
| 528 | + 5, 192, 0, 54, 50, 229, 9, 141, 49, 84, 194, 35, 12, 196, | |
| 529 | + 153, 48, 192, 137, 57, 84, 24, 7, 87, 159, 249, 240, 215, 143, | |
| 530 | + 105, 241, 118, 149, 9, 139, 4, 64, 203, 141, 35, 140, 129, 131, | |
| 531 | + 16, 222, 125, 231, 128, 2, 238, 17, 152, 66, 3, 5, 56, 224, | |
| 532 | + 159, 103, 16, 76, 25, 75, 5, 11, 164, 215, 96, 9, 14, 16, | |
| 533 | + 36, 225, 15, 11, 40, 144, 192, 156, 41, 10, 178, 199, 3, 66, | |
| 534 | + 64, 80, 193, 3, 124, 90, 48, 129, 129, 102, 177, 18, 192, 154, | |
| 535 | + 49, 84, 240, 208, 92, 22, 149, 96, 39, 9, 31, 74, 17, 94, | |
| 536 | + 3, 8, 177, 199, 72, 59, 85, 76, 25, 216, 8, 139, 194, 197, | |
| 537 | + 138, 163, 69, 96, 115, 0, 147, 72, 72, 84, 28, 14, 79, 86, | |
| 538 | + 233, 230, 23, 113, 26, 160, 128, 3, 10, 58, 129, 103, 14, 159, | |
| 539 | + 214, 163, 146, 117, 238, 213, 154, 128, 151, 109, 84, 64, 217, 13, | |
| 540 | + 27, 10, 228, 39, 2, 235, 164, 168, 74, 8, 0, 59, | |
| 541 | +}; | |
| 542 | + | |
| 543 | +/* | |
| 544 | +** WEBPAGE: logo | |
| 545 | +** | |
| 546 | +** Return the logo image. This image is available to anybody who can see | |
| 547 | +** the login page. It is designed for use in the upper left-hand corner | |
| 548 | +** of the header. | |
| 549 | +*/ | |
| 550 | +void logo_page(void){ | |
| 551 | + Blob logo; | |
| 552 | + char *zMime; | |
| 553 | + | |
| 554 | + zMime = db_get("logo-mimetype", "image/gif"); | |
| 555 | + blob_zero(&logo); | |
| 556 | + db_blob(&logo, "SELECT value FROM config WHERE name='logo-image'"); | |
| 557 | + if( blob_size(&logo)==0 ){ | |
| 558 | + blob_init(&logo, (char*)aLogo, sizeof(aLogo)); | |
| 559 | + } | |
| 560 | + cgi_set_content_type(zMime); | |
| 561 | + cgi_set_content(&logo); | |
| 562 | +} | |
| 474 | 563 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -469,5 +469,94 @@ | |
| 469 | style_header("Document Not Found"); |
| 470 | @ <p>No such document: %h(PD("name","tip/index.wiki"))</p> |
| 471 | style_footer(); |
| 472 | return; |
| 473 | } |
| 474 |
| --- src/doc.c | |
| +++ src/doc.c | |
| @@ -469,5 +469,94 @@ | |
| 469 | style_header("Document Not Found"); |
| 470 | @ <p>No such document: %h(PD("name","tip/index.wiki"))</p> |
| 471 | style_footer(); |
| 472 | return; |
| 473 | } |
| 474 | |
| 475 | /* |
| 476 | ** The default logo. |
| 477 | */ |
| 478 | static const unsigned char aLogo[] = { |
| 479 | 71, 73, 70, 56, 55, 97, 62, 0, 71, 0, 244, 0, 0, 85, |
| 480 | 129, 149, 95, 136, 155, 99, 139, 157, 106, 144, 162, 113, 150, 166, |
| 481 | 116, 152, 168, 127, 160, 175, 138, 168, 182, 148, 176, 188, 159, 184, |
| 482 | 195, 170, 192, 202, 180, 199, 208, 184, 202, 210, 191, 207, 215, 201, |
| 483 | 215, 221, 212, 223, 228, 223, 231, 235, 226, 227, 226, 226, 234, 237, |
| 484 | 233, 239, 241, 240, 244, 246, 244, 247, 248, 255, 255, 255, 0, 0, |
| 485 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, |
| 486 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 44, 0, 0, |
| 487 | 0, 0, 62, 0, 71, 0, 0, 5, 255, 96, 100, 141, 100, 105, |
| 488 | 158, 168, 37, 41, 132, 192, 164, 112, 44, 207, 102, 99, 0, 56, |
| 489 | 16, 84, 116, 239, 199, 141, 65, 110, 232, 248, 25, 141, 193, 161, |
| 490 | 82, 113, 108, 202, 32, 55, 229, 210, 73, 61, 41, 164, 88, 102, |
| 491 | 181, 10, 41, 96, 179, 91, 106, 35, 240, 5, 135, 143, 137, 242, |
| 492 | 87, 123, 246, 33, 190, 81, 108, 163, 237, 198, 14, 30, 113, 233, |
| 493 | 131, 78, 115, 72, 11, 115, 87, 101, 19, 124, 51, 66, 74, 8, |
| 494 | 19, 16, 67, 100, 74, 133, 50, 15, 101, 135, 56, 11, 74, 6, |
| 495 | 143, 49, 126, 106, 56, 8, 145, 67, 9, 152, 48, 139, 155, 5, |
| 496 | 22, 13, 74, 115, 161, 41, 147, 101, 13, 130, 57, 132, 170, 40, |
| 497 | 167, 155, 0, 94, 57, 3, 178, 48, 183, 181, 57, 160, 186, 40, |
| 498 | 19, 141, 189, 0, 69, 192, 40, 16, 195, 155, 185, 199, 41, 201, |
| 499 | 189, 191, 205, 193, 188, 131, 210, 49, 175, 88, 209, 214, 38, 19, |
| 500 | 3, 11, 19, 111, 127, 60, 219, 39, 55, 204, 19, 11, 6, 100, |
| 501 | 5, 10, 227, 228, 37, 163, 0, 239, 117, 56, 238, 243, 49, 195, |
| 502 | 177, 247, 48, 158, 56, 251, 50, 216, 254, 197, 56, 128, 107, 158, |
| 503 | 2, 125, 171, 114, 92, 218, 246, 96, 66, 3, 4, 50, 134, 176, |
| 504 | 145, 6, 97, 64, 144, 24, 19, 136, 108, 91, 177, 160, 0, 194, |
| 505 | 19, 253, 0, 216, 107, 214, 224, 192, 129, 5, 16, 83, 255, 244, |
| 506 | 43, 213, 195, 24, 159, 27, 169, 64, 230, 88, 208, 227, 129, 182, |
| 507 | 54, 4, 89, 158, 24, 181, 163, 199, 1, 155, 52, 233, 8, 130, |
| 508 | 176, 83, 24, 128, 137, 50, 18, 32, 48, 48, 114, 11, 173, 137, |
| 509 | 19, 110, 4, 64, 105, 1, 194, 30, 140, 68, 15, 24, 24, 224, |
| 510 | 50, 76, 70, 0, 11, 171, 54, 26, 160, 181, 194, 149, 148, 40, |
| 511 | 174, 148, 122, 64, 180, 208, 161, 17, 207, 112, 164, 1, 128, 96, |
| 512 | 148, 78, 18, 21, 194, 33, 229, 51, 247, 65, 133, 97, 5, 250, |
| 513 | 69, 229, 100, 34, 220, 128, 166, 116, 190, 62, 8, 167, 195, 170, |
| 514 | 47, 163, 0, 130, 90, 152, 11, 160, 173, 170, 27, 154, 26, 91, |
| 515 | 232, 151, 171, 18, 14, 162, 253, 98, 170, 18, 70, 171, 64, 219, |
| 516 | 10, 67, 136, 134, 187, 116, 75, 180, 46, 179, 174, 135, 4, 189, |
| 517 | 229, 231, 78, 40, 10, 62, 226, 164, 172, 64, 240, 167, 170, 10, |
| 518 | 18, 124, 188, 10, 107, 65, 193, 94, 11, 93, 171, 28, 248, 17, |
| 519 | 239, 46, 140, 78, 97, 34, 25, 153, 36, 99, 65, 130, 7, 203, |
| 520 | 183, 168, 51, 34, 136, 25, 140, 10, 6, 16, 28, 255, 145, 241, |
| 521 | 230, 140, 10, 66, 178, 167, 112, 48, 192, 128, 129, 9, 31, 141, |
| 522 | 84, 138, 63, 163, 162, 2, 203, 206, 240, 56, 55, 98, 192, 188, |
| 523 | 15, 185, 50, 160, 6, 0, 125, 62, 33, 214, 195, 33, 5, 24, |
| 524 | 184, 25, 231, 14, 201, 245, 144, 23, 126, 104, 228, 0, 145, 2, |
| 525 | 13, 140, 244, 212, 17, 21, 20, 176, 159, 17, 95, 225, 160, 128, |
| 526 | 16, 1, 32, 224, 142, 32, 227, 125, 87, 64, 0, 16, 54, 129, |
| 527 | 205, 2, 141, 76, 53, 130, 103, 37, 166, 64, 144, 107, 78, 196, |
| 528 | 5, 192, 0, 54, 50, 229, 9, 141, 49, 84, 194, 35, 12, 196, |
| 529 | 153, 48, 192, 137, 57, 84, 24, 7, 87, 159, 249, 240, 215, 143, |
| 530 | 105, 241, 118, 149, 9, 139, 4, 64, 203, 141, 35, 140, 129, 131, |
| 531 | 16, 222, 125, 231, 128, 2, 238, 17, 152, 66, 3, 5, 56, 224, |
| 532 | 159, 103, 16, 76, 25, 75, 5, 11, 164, 215, 96, 9, 14, 16, |
| 533 | 36, 225, 15, 11, 40, 144, 192, 156, 41, 10, 178, 199, 3, 66, |
| 534 | 64, 80, 193, 3, 124, 90, 48, 129, 129, 102, 177, 18, 192, 154, |
| 535 | 49, 84, 240, 208, 92, 22, 149, 96, 39, 9, 31, 74, 17, 94, |
| 536 | 3, 8, 177, 199, 72, 59, 85, 76, 25, 216, 8, 139, 194, 197, |
| 537 | 138, 163, 69, 96, 115, 0, 147, 72, 72, 84, 28, 14, 79, 86, |
| 538 | 233, 230, 23, 113, 26, 160, 128, 3, 10, 58, 129, 103, 14, 159, |
| 539 | 214, 163, 146, 117, 238, 213, 154, 128, 151, 109, 84, 64, 217, 13, |
| 540 | 27, 10, 228, 39, 2, 235, 164, 168, 74, 8, 0, 59, |
| 541 | }; |
| 542 | |
| 543 | /* |
| 544 | ** WEBPAGE: logo |
| 545 | ** |
| 546 | ** Return the logo image. This image is available to anybody who can see |
| 547 | ** the login page. It is designed for use in the upper left-hand corner |
| 548 | ** of the header. |
| 549 | */ |
| 550 | void logo_page(void){ |
| 551 | Blob logo; |
| 552 | char *zMime; |
| 553 | |
| 554 | zMime = db_get("logo-mimetype", "image/gif"); |
| 555 | blob_zero(&logo); |
| 556 | db_blob(&logo, "SELECT value FROM config WHERE name='logo-image'"); |
| 557 | if( blob_size(&logo)==0 ){ |
| 558 | blob_init(&logo, (char*)aLogo, sizeof(aLogo)); |
| 559 | } |
| 560 | cgi_set_content_type(zMime); |
| 561 | cgi_set_content(&logo); |
| 562 | } |
| 563 |
+58
| --- src/setup.c | ||
| +++ src/setup.c | ||
| @@ -76,10 +76,12 @@ | ||
| 76 | 76 | "Edit the Cascading Style Sheet used by all pages of this repository"); |
| 77 | 77 | setup_menu_entry("Header", "setup_header", |
| 78 | 78 | "Edit HTML text inserted at the top of every page"); |
| 79 | 79 | setup_menu_entry("Footer", "setup_footer", |
| 80 | 80 | "Edit HTML text inserted at the bottom of every page"); |
| 81 | + setup_menu_entry("Logo", "setup_logo", | |
| 82 | + "Change the logo image for the server"); | |
| 81 | 83 | setup_menu_entry("Shunned", "shun", |
| 82 | 84 | "Show artifacts that are shunned by this repository"); |
| 83 | 85 | setup_menu_entry("Log", "rcvfromlist", |
| 84 | 86 | "A record of received artifacts and their sources"); |
| 85 | 87 | setup_menu_entry("Stats", "stat", |
| @@ -1012,8 +1014,64 @@ | ||
| 1012 | 1014 | @ <hr> |
| 1013 | 1015 | @ Here is the default page footer: |
| 1014 | 1016 | @ <blockquote><pre> |
| 1015 | 1017 | @ %h(zDefaultFooter) |
| 1016 | 1018 | @ </pre></blockquote> |
| 1019 | + style_footer(); | |
| 1020 | + db_end_transaction(0); | |
| 1021 | +} | |
| 1022 | + | |
| 1023 | +/* | |
| 1024 | +** WEBPAGE: setup_logo | |
| 1025 | +*/ | |
| 1026 | +void setup_logo(void){ | |
| 1027 | + const char *zMime = "image/gif"; | |
| 1028 | + const char *aImg = P("im"); | |
| 1029 | + int szImg = atoi(PD("im:bytes","0")); | |
| 1030 | + if( szImg>0 ){ | |
| 1031 | + zMime = PD("im:mimetype","image/gif"); | |
| 1032 | + } | |
| 1033 | + login_check_credentials(); | |
| 1034 | + if( !g.okSetup ){ | |
| 1035 | + login_needed(); | |
| 1036 | + } | |
| 1037 | + db_begin_transaction(); | |
| 1038 | + if( P("set")!=0 && zMime && zMime[0] && szImg>0 ){ | |
| 1039 | + Blob img; | |
| 1040 | + Stmt ins; | |
| 1041 | + blob_init(&img, aImg, szImg); | |
| 1042 | + db_prepare(&ins, | |
| 1043 | + "REPLACE INTO config(name, value)" | |
| 1044 | + " VALUES('logo-image',:bytes)" | |
| 1045 | + ); | |
| 1046 | + db_bind_blob(&ins, ":bytes", &img); | |
| 1047 | + db_step(&ins); | |
| 1048 | + db_finalize(&ins); | |
| 1049 | + db_multi_exec( | |
| 1050 | + "REPLACE INTO config(name, value) VALUES('logo-mimetype',%Q)", | |
| 1051 | + zMime | |
| 1052 | + ); | |
| 1053 | + }else if( P("clr")!=0 ){ | |
| 1054 | + db_multi_exec( | |
| 1055 | + "DELETE FROM config WHERE name GLOB 'logo-*'" | |
| 1056 | + ); | |
| 1057 | + } | |
| 1058 | + style_header("Edit Project Logo"); | |
| 1059 | + @ <p>The current project logo has a MIME-Type of <b>%h(zMime)</b> and looks | |
| 1060 | + @ like this:</p> | |
| 1061 | + @ <blockquote><img src="/logo" alt="logo"></blockquote> | |
| 1062 | + @ | |
| 1063 | + @ <form action="%s(g.zBaseURL)/setup_logo" method="POST" | |
| 1064 | + @ enctype="multipart/form-data"> | |
| 1065 | + @ <p>The logo is accessible to all users at this URL: | |
| 1066 | + @ <a href="%s(g.zBaseURL)/logo">%s(g.zBaseURL)/logo</a>. | |
| 1067 | + @ To set a new logo image, select a file to use as the logo using | |
| 1068 | + @ the entry box below and then press the "Change Logo" button.</p> | |
| 1069 | + login_insert_csrf_secret(); | |
| 1070 | + @ Logo Image file: | |
| 1071 | + @ <input type="file" name="im" size="60" accepts="image/*"><br> | |
| 1072 | + @ <input type="submit" name="set" value="Change Logo"> | |
| 1073 | + @ <input type="submit" name="clr" value="Revert To Default"> | |
| 1074 | + @ </form> | |
| 1017 | 1075 | style_footer(); |
| 1018 | 1076 | db_end_transaction(0); |
| 1019 | 1077 | } |
| 1020 | 1078 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -76,10 +76,12 @@ | |
| 76 | "Edit the Cascading Style Sheet used by all pages of this repository"); |
| 77 | setup_menu_entry("Header", "setup_header", |
| 78 | "Edit HTML text inserted at the top of every page"); |
| 79 | setup_menu_entry("Footer", "setup_footer", |
| 80 | "Edit HTML text inserted at the bottom of every page"); |
| 81 | setup_menu_entry("Shunned", "shun", |
| 82 | "Show artifacts that are shunned by this repository"); |
| 83 | setup_menu_entry("Log", "rcvfromlist", |
| 84 | "A record of received artifacts and their sources"); |
| 85 | setup_menu_entry("Stats", "stat", |
| @@ -1012,8 +1014,64 @@ | |
| 1012 | @ <hr> |
| 1013 | @ Here is the default page footer: |
| 1014 | @ <blockquote><pre> |
| 1015 | @ %h(zDefaultFooter) |
| 1016 | @ </pre></blockquote> |
| 1017 | style_footer(); |
| 1018 | db_end_transaction(0); |
| 1019 | } |
| 1020 |
| --- src/setup.c | |
| +++ src/setup.c | |
| @@ -76,10 +76,12 @@ | |
| 76 | "Edit the Cascading Style Sheet used by all pages of this repository"); |
| 77 | setup_menu_entry("Header", "setup_header", |
| 78 | "Edit HTML text inserted at the top of every page"); |
| 79 | setup_menu_entry("Footer", "setup_footer", |
| 80 | "Edit HTML text inserted at the bottom of every page"); |
| 81 | setup_menu_entry("Logo", "setup_logo", |
| 82 | "Change the logo image for the server"); |
| 83 | setup_menu_entry("Shunned", "shun", |
| 84 | "Show artifacts that are shunned by this repository"); |
| 85 | setup_menu_entry("Log", "rcvfromlist", |
| 86 | "A record of received artifacts and their sources"); |
| 87 | setup_menu_entry("Stats", "stat", |
| @@ -1012,8 +1014,64 @@ | |
| 1014 | @ <hr> |
| 1015 | @ Here is the default page footer: |
| 1016 | @ <blockquote><pre> |
| 1017 | @ %h(zDefaultFooter) |
| 1018 | @ </pre></blockquote> |
| 1019 | style_footer(); |
| 1020 | db_end_transaction(0); |
| 1021 | } |
| 1022 | |
| 1023 | /* |
| 1024 | ** WEBPAGE: setup_logo |
| 1025 | */ |
| 1026 | void setup_logo(void){ |
| 1027 | const char *zMime = "image/gif"; |
| 1028 | const char *aImg = P("im"); |
| 1029 | int szImg = atoi(PD("im:bytes","0")); |
| 1030 | if( szImg>0 ){ |
| 1031 | zMime = PD("im:mimetype","image/gif"); |
| 1032 | } |
| 1033 | login_check_credentials(); |
| 1034 | if( !g.okSetup ){ |
| 1035 | login_needed(); |
| 1036 | } |
| 1037 | db_begin_transaction(); |
| 1038 | if( P("set")!=0 && zMime && zMime[0] && szImg>0 ){ |
| 1039 | Blob img; |
| 1040 | Stmt ins; |
| 1041 | blob_init(&img, aImg, szImg); |
| 1042 | db_prepare(&ins, |
| 1043 | "REPLACE INTO config(name, value)" |
| 1044 | " VALUES('logo-image',:bytes)" |
| 1045 | ); |
| 1046 | db_bind_blob(&ins, ":bytes", &img); |
| 1047 | db_step(&ins); |
| 1048 | db_finalize(&ins); |
| 1049 | db_multi_exec( |
| 1050 | "REPLACE INTO config(name, value) VALUES('logo-mimetype',%Q)", |
| 1051 | zMime |
| 1052 | ); |
| 1053 | }else if( P("clr")!=0 ){ |
| 1054 | db_multi_exec( |
| 1055 | "DELETE FROM config WHERE name GLOB 'logo-*'" |
| 1056 | ); |
| 1057 | } |
| 1058 | style_header("Edit Project Logo"); |
| 1059 | @ <p>The current project logo has a MIME-Type of <b>%h(zMime)</b> and looks |
| 1060 | @ like this:</p> |
| 1061 | @ <blockquote><img src="/logo" alt="logo"></blockquote> |
| 1062 | @ |
| 1063 | @ <form action="%s(g.zBaseURL)/setup_logo" method="POST" |
| 1064 | @ enctype="multipart/form-data"> |
| 1065 | @ <p>The logo is accessible to all users at this URL: |
| 1066 | @ <a href="%s(g.zBaseURL)/logo">%s(g.zBaseURL)/logo</a>. |
| 1067 | @ To set a new logo image, select a file to use as the logo using |
| 1068 | @ the entry box below and then press the "Change Logo" button.</p> |
| 1069 | login_insert_csrf_secret(); |
| 1070 | @ Logo Image file: |
| 1071 | @ <input type="file" name="im" size="60" accepts="image/*"><br> |
| 1072 | @ <input type="submit" name="set" value="Change Logo"> |
| 1073 | @ <input type="submit" name="clr" value="Revert To Default"> |
| 1074 | @ </form> |
| 1075 | style_footer(); |
| 1076 | db_end_transaction(0); |
| 1077 | } |
| 1078 |
+4
-3
| --- src/style.c | ||
| +++ src/style.c | ||
| @@ -191,12 +191,12 @@ | ||
| 191 | 191 | @ media="screen"> |
| 192 | 192 | @ </head> |
| 193 | 193 | @ <body> |
| 194 | 194 | @ <div class="header"> |
| 195 | 195 | @ <div class="logo"> |
| 196 | -@ <!-- <img src="logo.gif" alt="logo"><br></br> --> | |
| 197 | -@ <nobr>$<project_name></nobr> | |
| 196 | +@ <img src="/logo" alt="logo"> | |
| 197 | +@ <br><nobr>$<project_name></nobr> | |
| 198 | 198 | @ </div> |
| 199 | 199 | @ <div class="title">$<title></div> |
| 200 | 200 | @ <div class="status"><nobr><th1> |
| 201 | 201 | @ if {[info exists login]} { |
| 202 | 202 | @ puts "Logged in as $login" |
| @@ -269,11 +269,12 @@ | ||
| 269 | 269 | @ /* The page title centered at the top of each page */ |
| 270 | 270 | @ div.title { |
| 271 | 271 | @ display: table-cell; |
| 272 | 272 | @ font-size: 2em; |
| 273 | 273 | @ font-weight: bold; |
| 274 | -@ text-align: center; | |
| 274 | +@ text-align: left; | |
| 275 | +@ padding: 0 0 0 1em; | |
| 275 | 276 | @ color: #558195; |
| 276 | 277 | @ vertical-align: bottom; |
| 277 | 278 | @ width: 100%; |
| 278 | 279 | @ } |
| 279 | 280 | @ |
| 280 | 281 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -191,12 +191,12 @@ | |
| 191 | @ media="screen"> |
| 192 | @ </head> |
| 193 | @ <body> |
| 194 | @ <div class="header"> |
| 195 | @ <div class="logo"> |
| 196 | @ <!-- <img src="logo.gif" alt="logo"><br></br> --> |
| 197 | @ <nobr>$<project_name></nobr> |
| 198 | @ </div> |
| 199 | @ <div class="title">$<title></div> |
| 200 | @ <div class="status"><nobr><th1> |
| 201 | @ if {[info exists login]} { |
| 202 | @ puts "Logged in as $login" |
| @@ -269,11 +269,12 @@ | |
| 269 | @ /* The page title centered at the top of each page */ |
| 270 | @ div.title { |
| 271 | @ display: table-cell; |
| 272 | @ font-size: 2em; |
| 273 | @ font-weight: bold; |
| 274 | @ text-align: center; |
| 275 | @ color: #558195; |
| 276 | @ vertical-align: bottom; |
| 277 | @ width: 100%; |
| 278 | @ } |
| 279 | @ |
| 280 |
| --- src/style.c | |
| +++ src/style.c | |
| @@ -191,12 +191,12 @@ | |
| 191 | @ media="screen"> |
| 192 | @ </head> |
| 193 | @ <body> |
| 194 | @ <div class="header"> |
| 195 | @ <div class="logo"> |
| 196 | @ <img src="/logo" alt="logo"> |
| 197 | @ <br><nobr>$<project_name></nobr> |
| 198 | @ </div> |
| 199 | @ <div class="title">$<title></div> |
| 200 | @ <div class="status"><nobr><th1> |
| 201 | @ if {[info exists login]} { |
| 202 | @ puts "Logged in as $login" |
| @@ -269,11 +269,12 @@ | |
| 269 | @ /* The page title centered at the top of each page */ |
| 270 | @ div.title { |
| 271 | @ display: table-cell; |
| 272 | @ font-size: 2em; |
| 273 | @ font-weight: bold; |
| 274 | @ text-align: left; |
| 275 | @ padding: 0 0 0 1em; |
| 276 | @ color: #558195; |
| 277 | @ vertical-align: bottom; |
| 278 | @ width: 100%; |
| 279 | @ } |
| 280 | @ |
| 281 |
+38
-13
| --- src/xfer.c | ||
| +++ src/xfer.c | ||
| @@ -523,15 +523,18 @@ | ||
| 523 | 523 | /* |
| 524 | 524 | ** Send a single config card for configuration item zName |
| 525 | 525 | */ |
| 526 | 526 | static void send_config_card(Xfer *pXfer, const char *zName){ |
| 527 | 527 | if( zName[0]!='@' ){ |
| 528 | - char *zValue = db_get(zName, 0); | |
| 529 | - if( zValue ){ | |
| 530 | - blob_appendf(pXfer->pOut, "config %s %d\n%s\n", | |
| 531 | - zName, strlen(zValue), zValue); | |
| 532 | - free(zValue); | |
| 528 | + Blob val; | |
| 529 | + blob_zero(&val); | |
| 530 | + db_blob(&val, "SELECT value FROM config WHERE name=%Q", zName); | |
| 531 | + if( blob_size(&val)>0 ){ | |
| 532 | + blob_appendf(pXfer->pOut, "config %s %d\n", zName, blob_size(&val)); | |
| 533 | + blob_append(pXfer->pOut, blob_buffer(&val), blob_size(&val)); | |
| 534 | + blob_reset(&val); | |
| 535 | + blob_append(pXfer->pOut, "\n", 1); | |
| 533 | 536 | } |
| 534 | 537 | }else{ |
| 535 | 538 | Blob content; |
| 536 | 539 | blob_zero(&content); |
| 537 | 540 | configure_render_special_name(zName, &content); |
| @@ -768,14 +771,25 @@ | ||
| 768 | 771 | @ error not\sauthorized\sto\spush\sconfiguration |
| 769 | 772 | nErr++; |
| 770 | 773 | break; |
| 771 | 774 | } |
| 772 | 775 | if( zName[0]!='@' ){ |
| 773 | - db_multi_exec( | |
| 774 | - "REPLACE INTO config(name,value) VALUES(%Q,%Q)", | |
| 775 | - zName, blob_str(&content) | |
| 776 | - ); | |
| 776 | + if( strcmp(zName, "logo-image")==0 ){ | |
| 777 | + Stmt ins; | |
| 778 | + db_prepare(&ins, | |
| 779 | + "REPLACE INTO config(name, value) VALUES(:name, :value)" | |
| 780 | + ); | |
| 781 | + db_bind_text(&ins, ":name", zName); | |
| 782 | + db_bind_blob(&ins, ":value", &content); | |
| 783 | + db_step(&ins); | |
| 784 | + db_finalize(&ins); | |
| 785 | + }else{ | |
| 786 | + db_multi_exec( | |
| 787 | + "REPLACE INTO config(name,value) VALUES(%Q,%Q)", | |
| 788 | + zName, blob_str(&content) | |
| 789 | + ); | |
| 790 | + } | |
| 777 | 791 | }else{ |
| 778 | 792 | /* Notice that we are evaluating arbitrary SQL received from the |
| 779 | 793 | ** client. But this can only happen if the client has authenticated |
| 780 | 794 | ** as an administrator, so presumably we trust the client at this |
| 781 | 795 | ** point. |
| @@ -1130,14 +1144,25 @@ | ||
| 1130 | 1144 | blob_zero(&content); |
| 1131 | 1145 | blob_extract(xfer.pIn, size, &content); |
| 1132 | 1146 | g.okAdmin = g.okRdAddr = 1; |
| 1133 | 1147 | if( configure_is_exportable(zName) & origConfigRcvMask ){ |
| 1134 | 1148 | if( zName[0]!='@' ){ |
| 1135 | - db_multi_exec( | |
| 1136 | - "REPLACE INTO config(name,value) VALUES(%Q,%Q)", | |
| 1137 | - zName, blob_str(&content) | |
| 1138 | - ); | |
| 1149 | + if( strcmp(zName, "logo-image")==0 ){ | |
| 1150 | + Stmt ins; | |
| 1151 | + db_prepare(&ins, | |
| 1152 | + "REPLACE INTO config(name, value) VALUES(:name, :value)" | |
| 1153 | + ); | |
| 1154 | + db_bind_text(&ins, ":name", zName); | |
| 1155 | + db_bind_blob(&ins, ":value", &content); | |
| 1156 | + db_step(&ins); | |
| 1157 | + db_finalize(&ins); | |
| 1158 | + }else{ | |
| 1159 | + db_multi_exec( | |
| 1160 | + "REPLACE INTO config(name,value) VALUES(%Q,%Q)", | |
| 1161 | + zName, blob_str(&content) | |
| 1162 | + ); | |
| 1163 | + } | |
| 1139 | 1164 | }else{ |
| 1140 | 1165 | /* Notice that we are evaluating arbitrary SQL received from the |
| 1141 | 1166 | ** server. But this can only happen if we have specifically |
| 1142 | 1167 | ** requested configuration information from the server, so |
| 1143 | 1168 | ** presumably the operator trusts the server. |
| 1144 | 1169 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -523,15 +523,18 @@ | |
| 523 | /* |
| 524 | ** Send a single config card for configuration item zName |
| 525 | */ |
| 526 | static void send_config_card(Xfer *pXfer, const char *zName){ |
| 527 | if( zName[0]!='@' ){ |
| 528 | char *zValue = db_get(zName, 0); |
| 529 | if( zValue ){ |
| 530 | blob_appendf(pXfer->pOut, "config %s %d\n%s\n", |
| 531 | zName, strlen(zValue), zValue); |
| 532 | free(zValue); |
| 533 | } |
| 534 | }else{ |
| 535 | Blob content; |
| 536 | blob_zero(&content); |
| 537 | configure_render_special_name(zName, &content); |
| @@ -768,14 +771,25 @@ | |
| 768 | @ error not\sauthorized\sto\spush\sconfiguration |
| 769 | nErr++; |
| 770 | break; |
| 771 | } |
| 772 | if( zName[0]!='@' ){ |
| 773 | db_multi_exec( |
| 774 | "REPLACE INTO config(name,value) VALUES(%Q,%Q)", |
| 775 | zName, blob_str(&content) |
| 776 | ); |
| 777 | }else{ |
| 778 | /* Notice that we are evaluating arbitrary SQL received from the |
| 779 | ** client. But this can only happen if the client has authenticated |
| 780 | ** as an administrator, so presumably we trust the client at this |
| 781 | ** point. |
| @@ -1130,14 +1144,25 @@ | |
| 1130 | blob_zero(&content); |
| 1131 | blob_extract(xfer.pIn, size, &content); |
| 1132 | g.okAdmin = g.okRdAddr = 1; |
| 1133 | if( configure_is_exportable(zName) & origConfigRcvMask ){ |
| 1134 | if( zName[0]!='@' ){ |
| 1135 | db_multi_exec( |
| 1136 | "REPLACE INTO config(name,value) VALUES(%Q,%Q)", |
| 1137 | zName, blob_str(&content) |
| 1138 | ); |
| 1139 | }else{ |
| 1140 | /* Notice that we are evaluating arbitrary SQL received from the |
| 1141 | ** server. But this can only happen if we have specifically |
| 1142 | ** requested configuration information from the server, so |
| 1143 | ** presumably the operator trusts the server. |
| 1144 |
| --- src/xfer.c | |
| +++ src/xfer.c | |
| @@ -523,15 +523,18 @@ | |
| 523 | /* |
| 524 | ** Send a single config card for configuration item zName |
| 525 | */ |
| 526 | static void send_config_card(Xfer *pXfer, const char *zName){ |
| 527 | if( zName[0]!='@' ){ |
| 528 | Blob val; |
| 529 | blob_zero(&val); |
| 530 | db_blob(&val, "SELECT value FROM config WHERE name=%Q", zName); |
| 531 | if( blob_size(&val)>0 ){ |
| 532 | blob_appendf(pXfer->pOut, "config %s %d\n", zName, blob_size(&val)); |
| 533 | blob_append(pXfer->pOut, blob_buffer(&val), blob_size(&val)); |
| 534 | blob_reset(&val); |
| 535 | blob_append(pXfer->pOut, "\n", 1); |
| 536 | } |
| 537 | }else{ |
| 538 | Blob content; |
| 539 | blob_zero(&content); |
| 540 | configure_render_special_name(zName, &content); |
| @@ -768,14 +771,25 @@ | |
| 771 | @ error not\sauthorized\sto\spush\sconfiguration |
| 772 | nErr++; |
| 773 | break; |
| 774 | } |
| 775 | if( zName[0]!='@' ){ |
| 776 | if( strcmp(zName, "logo-image")==0 ){ |
| 777 | Stmt ins; |
| 778 | db_prepare(&ins, |
| 779 | "REPLACE INTO config(name, value) VALUES(:name, :value)" |
| 780 | ); |
| 781 | db_bind_text(&ins, ":name", zName); |
| 782 | db_bind_blob(&ins, ":value", &content); |
| 783 | db_step(&ins); |
| 784 | db_finalize(&ins); |
| 785 | }else{ |
| 786 | db_multi_exec( |
| 787 | "REPLACE INTO config(name,value) VALUES(%Q,%Q)", |
| 788 | zName, blob_str(&content) |
| 789 | ); |
| 790 | } |
| 791 | }else{ |
| 792 | /* Notice that we are evaluating arbitrary SQL received from the |
| 793 | ** client. But this can only happen if the client has authenticated |
| 794 | ** as an administrator, so presumably we trust the client at this |
| 795 | ** point. |
| @@ -1130,14 +1144,25 @@ | |
| 1144 | blob_zero(&content); |
| 1145 | blob_extract(xfer.pIn, size, &content); |
| 1146 | g.okAdmin = g.okRdAddr = 1; |
| 1147 | if( configure_is_exportable(zName) & origConfigRcvMask ){ |
| 1148 | if( zName[0]!='@' ){ |
| 1149 | if( strcmp(zName, "logo-image")==0 ){ |
| 1150 | Stmt ins; |
| 1151 | db_prepare(&ins, |
| 1152 | "REPLACE INTO config(name, value) VALUES(:name, :value)" |
| 1153 | ); |
| 1154 | db_bind_text(&ins, ":name", zName); |
| 1155 | db_bind_blob(&ins, ":value", &content); |
| 1156 | db_step(&ins); |
| 1157 | db_finalize(&ins); |
| 1158 | }else{ |
| 1159 | db_multi_exec( |
| 1160 | "REPLACE INTO config(name,value) VALUES(%Q,%Q)", |
| 1161 | zName, blob_str(&content) |
| 1162 | ); |
| 1163 | } |
| 1164 | }else{ |
| 1165 | /* Notice that we are evaluating arbitrary SQL received from the |
| 1166 | ** server. But this can only happen if we have specifically |
| 1167 | ** requested configuration information from the server, so |
| 1168 | ** presumably the operator trusts the server. |
| 1169 |