Fossil

Check-in [5ea6e15bf1]
Login

Check-in [5ea6e15bf1]

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Initialize the $title and $login variable for TH1 used during header/footer generation to a similar string that has characters that are special to HTML escaped to similar-looking unicode characters. This is an defense against XSS attacks that might otherwise result due to errors in a custom skin where the $title variable is misused.
Downloads: Tarball | ZIP archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA3-256: 5ea6e15bf1fc942d67d53d085b4a67fedaafc13f45a6d1028a8bd637e9d513a3
User & Date: drh 2025-03-29 16:00:08.197
Context
2025-03-30
09:51
Update documentation for the /test_env to /test-env change. ... (check-in: 5df726ab25 user: drh tags: trunk)
2025-03-29
16:00
Initialize the $title and $login variable for TH1 used during header/footer generation to a similar string that has characters that are special to HTML escaped to similar-looking unicode characters. This is an defense against XSS attacks that might otherwise result due to errors in a custom skin where the $title variable is misused. ... (check-in: 5ea6e15bf1 user: drh tags: trunk)
15:10
Change the name of the /test_env page to /test-env for consistency. The old name is retained as an alias for backwards compatibility. ... (check-in: caf286d748 user: drh tags: trunk)
Changes
Unified Diff Ignore Whitespace Patch
Changes to src/encode.c.
139
140
141
142
143
144
145








































































146
147
148
149
150
151
152
        blob_append(p, " ", 1);
        j = i+1;
        break;
    }
  }
  if( j<i ) blob_append(p, zIn+j, i-j);
}










































































/*
** Encode a string for HTTP.  This means converting lots of
** characters into the "%HH" where H is a hex digit.  It also
** means converting spaces to "+".
**







>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>







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
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
        blob_append(p, " ", 1);
        j = i+1;
        break;
    }
  }
  if( j<i ) blob_append(p, zIn+j, i-j);
}

/*
** Make the given string safe for HTML by converting syntax characters
** into alternatives that do not have the special syntactic meaning.
**
**     <     -->     U+227a
**     >     -->     U+227b
**     &     -->     +
**     "     -->     U+201d
**     '     -->     U+2019
**
** Return a pointer to a new string obtained from fossil_malloc().
*/
char *html_lookalike(const char *z, int n){
  unsigned char c;
  int i = 0;
  int count = 0;
  unsigned char *zOut;
  const unsigned char *zIn = (const unsigned char*)z;

  if( n<0 ) n = strlen(z);
  while( i<n ){
    switch( zIn[i] ){
      case '<':   count += 3;       break;
      case '>':   count += 3;       break;
      case '"':   count += 3;       break;
      case '\'':  count += 3;       break;
      case 0:     n = i;            break;
    }
    i++;
  }
  i = 0;
  zOut = fossil_malloc( count+n+1 );
  if( count==0 ){
    memcpy(zOut, zIn, n);
    zOut[n] = 0;
    return (char*)zOut;
  }
  while( n-->0 ){
    c = *(zIn++);
    switch( c ){
      case '<':
        zOut[i++] = 0xe2;
        zOut[i++] = 0x89;
        zOut[i++] = 0xba;
        break;
      case '>':
        zOut[i++] = 0xe2;
        zOut[i++] = 0x89;
        zOut[i++] = 0xbb;
        break;
      case '&':
        zOut[i++] = '+';
        break;
      case '"':
        zOut[i++] = 0xe2;
        zOut[i++] = 0x80;
        zOut[i++] = 0x9d;
        break;
      case '\'':
        zOut[i++] = 0xe2;
        zOut[i++] = 0x80;
        zOut[i++] = 0x99;
        break;
      default:
        zOut[i++] = c;
        break;
    }
  }
  zOut[i] = 0;
  return (char*)zOut;
}


/*
** Encode a string for HTTP.  This means converting lots of
** characters into the "%HH" where H is a hex digit.  It also
** means converting spaces to "+".
**
Changes to src/style.c.
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
  ** is evaluated before the header is rendered).
  */
  Th_MaybeStore("default_csp", zDfltCsp);
  fossil_free(zDfltCsp);
  Th_Store("nonce", zNonce);
  Th_Store("project_name", db_get("project-name","Unnamed Fossil Project"));
  Th_Store("project_description", db_get("project-description",""));
  if( zTitle ) Th_Store("title", zTitle);
  Th_Store("baseurl", g.zBaseURL);
  Th_Store("secureurl", fossil_wants_https(1)? g.zHttpsURL: g.zBaseURL);
  Th_Store("home", g.zTop);
  Th_Store("index_page", db_get("index-page","/home"));
  if( local_zCurrentPage==0 ) style_set_current_page("%T", g.zPath);
  Th_Store("current_page", local_zCurrentPage);
  if( g.zPath ){                /* store the first segment of a path; */







|







744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
  ** is evaluated before the header is rendered).
  */
  Th_MaybeStore("default_csp", zDfltCsp);
  fossil_free(zDfltCsp);
  Th_Store("nonce", zNonce);
  Th_Store("project_name", db_get("project-name","Unnamed Fossil Project"));
  Th_Store("project_description", db_get("project-description",""));
  if( zTitle ) Th_Store("title", html_lookalike(zTitle,-1));
  Th_Store("baseurl", g.zBaseURL);
  Th_Store("secureurl", fossil_wants_https(1)? g.zHttpsURL: g.zBaseURL);
  Th_Store("home", g.zTop);
  Th_Store("index_page", db_get("index-page","/home"));
  if( local_zCurrentPage==0 ) style_set_current_page("%T", g.zPath);
  Th_Store("current_page", local_zCurrentPage);
  if( g.zPath ){                /* store the first segment of a path; */
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
  Th_Store("manifest_date", MANIFEST_DATE);
  Th_Store("compiler_name", COMPILER_NAME);
  Th_Store("mainmenu", style_get_mainmenu());
  stylesheet_url_var();
  image_url_var("logo");
  image_url_var("background");
  if( !login_is_nobody() ){
    Th_Store("login", g.zLogin);
  }
  Th_MaybeStore("current_feature", feature_from_page_path(local_zCurrentPage) );
  if( g.ftntsIssues[0] || g.ftntsIssues[1] ||
      g.ftntsIssues[2] || g.ftntsIssues[3] ){
    char buf[80];
    sqlite3_snprintf(sizeof(buf), buf, "%i %i %i %i", g.ftntsIssues[0],
                     g.ftntsIssues[1], g.ftntsIssues[2], g.ftntsIssues[3]);







|







770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
  Th_Store("manifest_date", MANIFEST_DATE);
  Th_Store("compiler_name", COMPILER_NAME);
  Th_Store("mainmenu", style_get_mainmenu());
  stylesheet_url_var();
  image_url_var("logo");
  image_url_var("background");
  if( !login_is_nobody() ){
    Th_Store("login", html_lookalike(g.zLogin,-1));
  }
  Th_MaybeStore("current_feature", feature_from_page_path(local_zCurrentPage) );
  if( g.ftntsIssues[0] || g.ftntsIssues[1] ||
      g.ftntsIssues[2] || g.ftntsIssues[3] ){
    char buf[80];
    sqlite3_snprintf(sizeof(buf), buf, "%i %i %i %i", g.ftntsIssues[0],
                     g.ftntsIssues[1], g.ftntsIssues[2], g.ftntsIssues[3]);