Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
| Comment: | The URL parser now understands the /draftN/ prefix. Draft skins can now be initialized from built-ins. Another incremental check-in. |
|---|---|
| Downloads: | Tarball | ZIP archive |
| Timelines: | family | ancestors | descendants | both | skin-setup-refactor |
| Files: | files | file ages | folders |
| SHA3-256: |
0cba37ec1aae0f52c49b354589df6f0b |
| User & Date: | drh 2017-12-02 16:22:14.960 |
Context
|
2017-12-02
| ||
| 21:24 | The new skin editing is working, minimally. Still needs lots of work, though. check-in: 5840fdd732 user: drh tags: skin-setup-refactor | |
| 16:22 | The URL parser now understands the /draftN/ prefix. Draft skins can now be initialized from built-ins. Another incremental check-in. check-in: 0cba37ec1a user: drh tags: skin-setup-refactor | |
| 14:39 | Rework the Setup/Skin page so that all edits are done on a draft, then tested, then the draft is published to become the default skin. This specific check-in is just the beginning. Must code needs to be added. This is just an incremental check-in. check-in: 9bafe6cb60 user: drh tags: skin-setup-refactor | |
Changes
Changes to src/db.c.
| ︙ | ︙ | |||
2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 |
}
int db_lget_int(const char *zName, int dflt){
return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
}
void db_lset_int(const char *zName, int value){
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
}
#if INTERFACE
/* Manifest generation flags */
#define MFESTFLG_RAW 0x01
#define MFESTFLG_UUID 0x02
#define MFESTFLG_TAGS 0x04
#endif /* INTERFACE */
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512 2513 2514 2515 2516 2517 |
}
int db_lget_int(const char *zName, int dflt){
return db_int(dflt, "SELECT value FROM vvar WHERE name=%Q", zName);
}
void db_lset_int(const char *zName, int value){
db_multi_exec("REPLACE INTO vvar(name,value) VALUES(%Q,%d)", zName, value);
}
/* Va-args versions of db_get(), db_set(), and db_unset()
*/
char *db_get_mprintf(const char *zFormat, const char *zDefault, ...){
va_list ap;
char *zName;
char *zResult;
va_start(ap, zDefault);
zName = vmprintf(zFormat, ap);
va_end(ap);
zResult = db_get(zName, zDefault);
fossil_free(zName);
return zResult;
}
void db_set_mprintf(const char *zFormat, const char *zNew, int iGlobal, ...){
va_list ap;
char *zName;
va_start(ap, iGlobal);
zName = vmprintf(zFormat, ap);
va_end(ap);
db_set(zName, zNew, iGlobal);
fossil_free(zName);
}
void db_unset_mprintf(const char *zFormat, int iGlobal, ...){
va_list ap;
char *zName;
va_start(ap, iGlobal);
zName = vmprintf(zFormat, ap);
va_end(ap);
db_unset(zName, iGlobal);
fossil_free(zName);
}
#if INTERFACE
/* Manifest generation flags */
#define MFESTFLG_RAW 0x01
#define MFESTFLG_UUID 0x02
#define MFESTFLG_TAGS 0x04
#endif /* INTERFACE */
|
| ︙ | ︙ |
Changes to src/main.c.
| ︙ | ︙ | |||
1540 1541 1542 1543 1544 1545 1546 |
@ <!-- translated g.zBaseURL: "%h(g.zBaseURL)" -->
fprintf(stderr, "# translated g.zBaseURL = [%s]\n", g.zBaseURL);
}
}
}
/* At this point, the appropriate repository database file will have
| | > > > > > > > > > > > > > > > > > > | > > > > > > > | 1540 1541 1542 1543 1544 1545 1546 1547 1548 1549 1550 1551 1552 1553 1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564 1565 1566 1567 1568 1569 1570 1571 1572 1573 1574 1575 1576 1577 1578 1579 1580 1581 1582 1583 1584 1585 1586 1587 1588 |
@ <!-- translated g.zBaseURL: "%h(g.zBaseURL)" -->
fprintf(stderr, "# translated g.zBaseURL = [%s]\n", g.zBaseURL);
}
}
}
/* At this point, the appropriate repository database file will have
** been opened.
**
** Check to see if the the PATH_INFO begins with "draft[1-9]" and if
** so activate the special handling for draft skins
*/
if( zPathInfo && strncmp(zPathInfo,"/draft",6)==0
&& zPathInfo[6]>='1' && zPathInfo[6]<='9'
&& (zPathInfo[7]=='/' || zPathInfo[7]==0)
){
int iSkin = zPathInfo[6] - '0';
char *zNewScript;
skin_use_draft(iSkin);
zNewScript = mprintf("%s/draft%d", P("SCRIPT_NAME"), iSkin);
if( g.zTop ) g.zTop = mprintf("%s/draft%d", g.zTop, iSkin);
if( g.zBaseURL ) g.zBaseURL = mprintf("%s/draft%d", g.zBaseURL, iSkin);
zPathInfo += 7;
cgi_replace_parameter("PATH_INFO", zPathInfo);
cgi_replace_parameter("SCRIPT_NAME", zNewScript);
}
/* If the content type is application/x-fossil or
** application/x-fossil-debug, then a sync/push/pull/clone is
** desired, so default the PATH_INFO to /xfer
*/
if( g.zContentType &&
strncmp(g.zContentType, "application/x-fossil", 20)==0 ){
/* Special case: If the content mimetype shows that it is "fossil sync"
** payload, then pretend that the PATH_INFO is /xfer so that we always
** invoke the sync page. */
zPathInfo = "/xfer";
}
/* Use the first element of PATH_INFO as the page name
** and deliver the appropriate page back to the user.
*/
set_base_url(0);
if( zPathInfo==0 || zPathInfo[0]==0
|| (zPathInfo[0]=='/' && zPathInfo[1]==0) ){
/* Second special case: If the PATH_INFO is blank, issue a redirect to
** the home page identified by the "index-page" setting in the repository
** CONFIG table, to "/index" if there no "index-page" setting. */
#ifdef FOSSIL_ENABLE_JSON
|
| ︙ | ︙ |
Changes to src/skins.c.
| ︙ | ︙ | |||
62 63 64 65 66 67 68 69 70 71 72 73 74 75 | ** a match, that alternative is used. ** ** The following static variable holds the name of the alternative skin, ** or NULL if the skin should be as configured. */ static struct BuiltinSkin *pAltSkin = 0; static char *zAltSkinDir = 0; /* ** Skin details are a set of key/value pairs that define display ** attributes of the skin that cannot be easily specified using CSS ** or that need to be known on the server-side. ** ** The following array holds the value for all known skin details. | > | 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 | ** a match, that alternative is used. ** ** The following static variable holds the name of the alternative skin, ** or NULL if the skin should be as configured. */ static struct BuiltinSkin *pAltSkin = 0; static char *zAltSkinDir = 0; static int iDraftSkin = 0; /* ** Skin details are a set of key/value pairs that define display ** attributes of the skin that cannot be easily specified using CSS ** or that need to be known on the server-side. ** ** The following array holds the value for all known skin details. |
| ︙ | ︙ | |||
98 99 100 101 102 103 104 105 106 107 108 109 110 111 |
*/
char *skin_use_alternative(const char *zName){
int i;
Blob err = BLOB_INITIALIZER;
if( strchr(zName, '/')!=0 ){
zAltSkinDir = fossil_strdup(zName);
return 0;
}
for(i=0; i<count(aBuiltinSkin); i++){
if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){
pAltSkin = &aBuiltinSkin[i];
return 0;
}
}
| > > > > | 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 |
*/
char *skin_use_alternative(const char *zName){
int i;
Blob err = BLOB_INITIALIZER;
if( strchr(zName, '/')!=0 ){
zAltSkinDir = fossil_strdup(zName);
return 0;
}
if( sqlite3_strglob("draft[1-9]", zName)==0 ){
skin_use_draft(zName[5] - '0');
return 0;
}
for(i=0; i<count(aBuiltinSkin); i++){
if( fossil_strcmp(aBuiltinSkin[i].zLabel, zName)==0 ){
pAltSkin = &aBuiltinSkin[i];
return 0;
}
}
|
| ︙ | ︙ | |||
124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 |
void skin_override(void){
const char *zSkin = find_option("skin",0,1);
if( zSkin ){
char *zErr = skin_use_alternative(zSkin);
if( zErr ) fossil_fatal("%s", zErr);
}
}
/*
** The following routines return the various components of the skin
** that should be used for the current run.
*/
const char *skin_get(const char *zWhat){
const char *zOut;
char *z;
if( zAltSkinDir ){
char *z = mprintf("%s/%s.txt", zAltSkinDir, zWhat);
if( file_isfile(z) ){
Blob x;
blob_read_from_file(&x, z);
fossil_free(z);
return blob_str(&x);
| > > > > > > > > > > > > > > > | 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 |
void skin_override(void){
const char *zSkin = find_option("skin",0,1);
if( zSkin ){
char *zErr = skin_use_alternative(zSkin);
if( zErr ) fossil_fatal("%s", zErr);
}
}
/*
** Use one of the draft skins.
*/
void skin_use_draft(int i){
iDraftSkin = i;
}
/*
** The following routines return the various components of the skin
** that should be used for the current run.
**
** zWhat is one of: "css", "header", "footer", "details".
*/
const char *skin_get(const char *zWhat){
const char *zOut;
char *z;
if( iDraftSkin ){
z = mprintf("draft%d-%s", iDraftSkin, zWhat);
zOut = db_get(z, 0);
fossil_free(z);
if( zOut ) return zOut;
}
if( zAltSkinDir ){
char *z = mprintf("%s/%s.txt", zAltSkinDir, zWhat);
if( file_isfile(z) ){
Blob x;
blob_read_from_file(&x, z);
fossil_free(z);
return blob_str(&x);
|
| ︙ | ︙ | |||
666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 |
blob_reset(&to);
blob_reset(&out);
}
@ </div></form>
style_footer();
db_end_transaction(0);
}
/*
** WEBPAGE: setup_skin
**
** Generate a page showing the steps needed to customize a skin.
*/
void setup_skin(void){
int i; /* Loop counter */
int iSkin; /* Which draft skin is being edited */
static const char *azTestPages[] = {
"home",
"timeline",
"dir?ci=tip",
"dir?ci=tip&type=tree",
"brlist",
"info/trunk",
};
| > > > > > > > > > > > > > > > > > > > > > > > > > > > | > > > > > > > > > > > > > > > > > | > > > | | < < < < > | 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 |
blob_reset(&to);
blob_reset(&out);
}
@ </div></form>
style_footer();
db_end_transaction(0);
}
/*
** Try to initialize draft skin iSkin to the built-in or preexisting
** skin named by zTemplate.
*/
static void skin_initialize_draft(int iSkin, const char *zTemplate){
int i;
const char *azWhat[] = { "css", "header", "footer", "detail" };
if( zTemplate==0 ) return;
if( strcmp(zTemplate, "current")==0 ){
for(i=0; i<count(azWhat); i++){
db_unset_mprintf("draft%d-%s", 0, iSkin, azWhat[i]);
}
}else{
for(i=0; i<count(aBuiltinSkin); i++){
if( strcmp(zTemplate, aBuiltinSkin[i].zLabel)==0 ){
for(i=0; i<count(azWhat); i++){
char *zKey = mprintf("skins/%s/%s.txt", zTemplate, azWhat[i]);
db_set_mprintf("draft%d-%s", builtin_text(zKey), 0, iSkin, azWhat[i]);
}
break;
}
}
}
}
/*
** WEBPAGE: setup_skin
**
** Generate a page showing the steps needed to customize a skin.
*/
void setup_skin(void){
int i; /* Loop counter */
int iSkin; /* Which draft skin is being edited */
int isAdmin; /* True for an administrator */
int isEditor; /* Others authorized to make edits */
static const char *azTestPages[] = {
"home",
"timeline",
"dir?ci=tip",
"dir?ci=tip&type=tree",
"brlist",
"info/trunk",
};
/* Figure out which skin we are editing */
iSkin = atoi(PD("sk","1"));
if( iSkin<1 || iSkin>9 ) iSkin = 1;
/* Figure out if the current user is allowed to make administrative
** changes and/or edits
*/
login_check_credentials();
if( g.perm.Admin ){
isAdmin = isEditor = 1;
}else{
char *zAllowedEditors;
Glob *pAllowedEditors;
isAdmin = isEditor = 0;
zAllowedEditors = db_get_mprintf("draft%d-users", 0, iSkin);
if( zAllowedEditors ){
pAllowedEditors = glob_create(zAllowedEditors);
isEditor = glob_match(pAllowedEditors, zAllowedEditors);
glob_free(pAllowedEditors);
}
}
/* Initialize the skin, if requested and authorized. */
if( P("init3")!=0 && isEditor ){
skin_initialize_draft(iSkin, P("initskin"));
}
style_header("Customize Skin");
@ <p>Customize the look of this Fossil repository by making changes
@ to the CSS, Header, Footer, and Detail Settings in one of nine "draft"
@ configurations. Then, after verifying that all is working correctly,
@ publish the draft to become the new main Skin.<p>
@
@ <a name='step1'></a>
|
| ︙ | ︙ | |||
727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 | @ </p> @ @ <a name='step2'></a> @ <h1>Step 2: Authenticate @ @ <a name='step3'></a> @ <h1>Step 3: Initialize The Draft</h1> @ @ <a name='step4'></a> @ <h1>Step 4: Make Edits</h1> @ @ <a name='step5'></a> @ <h1>Step 5: Verify The Draft Skin</h1> @ @ <p>To test this draft skin, insert text "/draft%d(iSkin)/" just before the @ operation name in the URL. Here are a few links to try: @ <ul> | > > > > > > > > > > > > > > > > > > > > > | > > > > | 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 |
@ </p>
@
@ <a name='step2'></a>
@ <h1>Step 2: Authenticate
@
@ <a name='step3'></a>
@ <h1>Step 3: Initialize The Draft</h1>
@
if( !isEditor ){
@ <p>You are not allowed to initialize draft%(iSkin). Contact
@ the administrator for this repository for more information.
}else{
@ <p>Initialize the draft%d(iSkin) skin to one of the built-in skins
@ or a preexisting skin, to use as a baseline.</p>
@
@ <p><form method='POST' action='%R/setup_skin#stop4' id='f03'>
@ <input type='hidden' name='sk' value='%d(iSkin)'>
@ Initialize <b>draft%d(iSkin)</b> to
@ <select size='1' name='initskin'>
@ <option value='current'>Currently In Use</option>
for(i=0; i<count(aBuiltinSkin); i++){
@ <option value='%s(aBuiltinSkin[i].zLabel)'>\
@ %h(aBuiltinSkin[i].zDesc) (built-in)</option>
}
@ </select>
@ <input type='submit' name='init3' value='Go'>
@ </p>
}
@
@ <a name='step4'></a>
@ <h1>Step 4: Make Edits</h1>
@
@ <a name='step5'></a>
@ <h1>Step 5: Verify The Draft Skin</h1>
@
@ <p>To test this draft skin, insert text "/draft%d(iSkin)/" just before the
@ operation name in the URL. Here are a few links to try:
@ <ul>
for(i=0; i<count(azTestPages); i++){
@ <li><a href='%s(g.zBaseURL)/draft%d(iSkin)/%s(azTestPages[i])'>\
@ %s(g.zBaseURL)/draft%d(iSkin)/%s(azTestPages[i])</a>
}
@ </ul>
@
@ <p><b>Important:</b> After CSS changes, you will probably need to
@ press the "Reload" button on your browser for those changes
@ to take effect.</p>
@
@ <a name='step6'></a>
@ <h1>Step 6: Publish The Draft</h1>
if( !g.perm.Setup ){
@ <p>Only administrators are allowed to publish draft skins. Contact
@ an administrator to get this "draft%d(iSkin)" skin published.</p>
}else{
|
| ︙ | ︙ |