/* ** Copyright (c) 2002 D. Richard Hipp ** ** This program is free software; you can redistribute it and/or ** modify it under the terms of the GNU General Public ** License as published by the Free Software Foundation; either ** version 2 of the License, or (at your option) any later version. ** ** This program is distributed in the hope that it will be useful, ** but WITHOUT ANY WARRANTY; without even the implied warranty of ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ** General Public License for more details. ** ** You should have received a copy of the GNU General Public ** License along with this library; if not, write to the ** Free Software Foundation, Inc., 59 Temple Place - Suite 330, ** Boston, MA 02111-1307, USA. ** ** Author contact information: ** drh@hwaci.com ** http://www.hwaci.com/drh/ ** ******************************************************************************* ** ** Routines shared by many pages */ #include "config.h" #include "common.h" /* ** Output a string with the following substitutions: ** ** %T The title of the current page. ** %N Project name ** %V CVSTrac version number ** %B Base URL ** %% The character '%' */ static void output_with_subst(const char *zText, const char *zTitle){ int i; while( zText[0] ){ for(i=0; zText[i] && zText[i]!='%'; i++){} if( i>0 ) cgi_append_content(zText, i); if( zText[i]==0 ) break; switch( zText[i+1] ){ case 'T': zText += i+2; cgi_printf("%h", zTitle); break; case 'N': zText += i+2; cgi_printf("%h", g.zName); break; case 'V': zText += i+2; cgi_printf("%h", "2.0.0"); break; case 'B': zText += i+2; cgi_printf("%h", g.zBaseURL); break; case '%': zText += i+2; cgi_printf("%%"); break; default: zText += i+1; cgi_printf("%%"); break; } } } /* ** Read the whole contents of a file into memory obtained from ** malloc(). Return a pointer to the file contents. Be sure ** the string is null terminated. ** ** A NULL pointer is returned if the file could not be read ** for any reason. */ char *common_readfile(const char *zFilename) { FILE *fp; char *zContent = NULL; size_t n; if ((fp = fopen(zFilename, "r")) != NULL) { fseek(fp, 0, SEEK_END); if ((n = ftell(fp)) > 0) { if ((zContent = (char *)malloc(n+1)) == NULL) { fclose(fp); return NULL; } fseek(fp, 0, SEEK_SET); if ((n = fread(zContent, 1, n, fp)) == 0) { free(zContent); fclose(fp); return NULL; } zContent[n] = '\0'; } else { zContent = strdup(""); } fclose(fp); } return zContent; } /* ** Read the whole contents of a file pointer into memory obtained from ** malloc(). Return a pointer to the file contents. Be sure ** the string is null terminated. ** ** A NULL pointer is returned if the file could not be read ** for any reason. The caller is responsible for closing the file. */ char *common_readfp(FILE* fp) { char *zContent = NULL; char *z; size_t n = 0, m = 0; size_t rc; while( fp && !feof(fp) && !ferror(fp) ) { if( (n+1)>=m ){ m = m ? (m*2) : 1024; z = realloc(zContent, m); if( z==NULL ){ if( zContent!=NULL ) free(zContent); return NULL; } zContent = z; } rc = fread(&zContent[n], 1, m-(n+1), fp); if( rc>0 ){ n += rc; } zContent[n] = 0; } return zContent; } /* ** Generate an error message screen. */ void common_err(const char *zFormat, ...){ char *zMsg; va_list ap; va_start(ap, zFormat); zMsg = vmprintf(zFormat, ap); va_end(ap); cgi_reset_content(); common_standard_menu(0,0); common_header("Oops!"); cgi_printf("
The following error has occurred:
\n" "%h\n",zMsg); if( g.okSetup ){ cgi_printf("
Query parameters:
\n");
cgi_print_all();
}
common_footer();
cgi_append_header("Pragma: no-cache\r\n");
cgi_reply();
exit(0);
}
/*
** The menu on the top bar of every page is defined by the following
** variables. Links are navigation links to other pages. Actions are
** links which apply to the current page.
*/
static const char *azLink[50];
static int nLink = 0;
static const char *azAction[50];
static int nAction = 0;
const char *default_browse_url(void){
if( !strncmp(g.zPath,"dir",3) ) {
/* If the _current_ path is already a browse path, go with it */
return g.zPath;
}else{
/* If cookie is set, it overrides default setting */
char *zBrowseUrlCookieName = mprintf("%t_browse_url",g.zName);
const char *zCookieValue = P(zBrowseUrlCookieName);
free(zBrowseUrlCookieName);
if( zCookieValue ) {
if( !strcmp("dir",zCookieValue) ){
return "dir";
}else if( !strcmp("dirview",zCookieValue) ){
return "dirview";
}
}
}
return db_config("default_browse_url","dir");
}
/*
** Prepopulate the set of navigation items with a standard set that includes
** links to all top-level pages except for zOmit. If zOmit is NULL then
** include all items.
**
** If zSrchUrl is not NULL then use it as the URL for the "Search" menu
** option.
*/
void common_standard_menu(const char *zOmit, const char *zSrchUrl){
const char *zLimit;
if( g.okNewTkt ){
azLink[nLink++] = "tktnew";
azLink[nLink++] = "Ticket";
}
if( g.okCheckout ){
azLink[nLink++] = default_browse_url();
azLink[nLink++] = "Browse";
}
if( g.okRead ){
azLink[nLink++] = "reportlist";
azLink[nLink++] = "Reports";
}
if( g.okRdWiki || g.okRead || g.okCheckout ){
azLink[nLink++] = "timeline";
azLink[nLink++] = "Timeline";
}
if( g.okRdWiki ){
azLink[nLink++] = "wiki";
azLink[nLink++] = "Wiki";
}
if( g.okRdWiki || g.okRead || g.okCheckout ){
azLink[nLink++] = zSrchUrl ? zSrchUrl : "search";
azLink[nLink++] = "Search";
}
if( g.okCheckin ){
azLink[nLink++] = "msnew";
azLink[nLink++] = "Milestone";
}
if( g.okWrite && !g.isAnon ){
azLink[nLink++] = "userlist";
azLink[nLink++] = "Users";
}
if( g.okAdmin ){
azLink[nLink++] = "setup";
azLink[nLink++] = "Setup";
}
azLink[nLink++] = "login";
if( g.isAnon ){
azLink[nLink++] = "Login";
}else{
azLink[nLink++] = "Logout";
}
if( g.isAnon && (zLimit = db_config("throttle",0))!=0 && atof(zLimit)>0.0 ){
azLink[nLink++] = "honeypot";
azLink[nLink++] = "0Honeypot";
}
if( nLink>2 ){
azLink[nLink++] = "index";
azLink[nLink++] = "Home";
}
if( zOmit ){
int j;
for(j=0; j This website is implemented using CVSTrac version 2.0.0. CVSTrac implements a patch-set and\n"
"bug tracking system for %h.\n"
"For additional information, visit the CVSTrac homepage at Copyright © 2002-2006 \n"
"D. Richard Hipp.\n"
"The CVSTrac server is released under the terms of the GNU\n"
"\n"
"General Public License. \n"
"\n"
" \n"
"
\n"
"\n"
" \n");
if( nAction && azAction ){
int j;
int nChar;
cgi_printf("\n",BORDER1,BG1);
if( zUrl ){
cgi_printf("%h -\n"
"%h \n"
"
\n",g.zName,zUrl,zTitleTxt);
}else{
cgi_printf("%h - %h
\n",g.zName,zTitleTxt);
}
if( !g.isAnon ){
cgi_printf("Logged in as\n",g.zUser);
if( !strcmp(g.zUser,"setup") ){
cgi_printf("setup\n");
}else{
cgi_printf("%h\n",g.zUser,g.zUser);
}
cgi_printf("\n");
}else{
const char *zUri = getenv("REQUEST_URI");
cgi_printf("\n");
if( nLink && azLink ){
int j;
int nChar;
nLink /= 2;
qsort(azLink, nLink, 2*sizeof(azLink[0]), link_compare);
nChar = 0;
for(i=0; azLink[i]; i+=2){
nChar += strlen(azLink[i+1]) + 3;
}
if( nChar<=60 ){
brk = nChar;
}else if( nChar<=120 ){
brk = nChar/2;
}else{
brk = nChar/3;
}
nChar = 0;
cgi_printf(" \n"
" \n");
}
cgi_printf(" \n"
"\n",BG4);
nAction /= 2;
qsort(azAction, nAction, 2*sizeof(azAction[0]), link_compare);
nChar = 0;
for(i=0; azAction[i]; i+=2){
nChar += strlen(azAction[i+1]) + 3;
}
if( nChar<=60 ){
brk = nChar;
}else if( nChar<=120 ){
brk = nChar/2;
}else{
brk = nChar/3;
}
nChar = 0;
cgi_printf(" \n"
"http://www.cvstrac.org/\n"
"
\n"
"\n"
"