configedit.c
上传用户:seven77cht
上传日期:2007-01-04
资源大小:486k
文件大小:13k
- /***************************************
- $Header: /home/amb/wwwoffle/RCS/configedit.c 2.19 1999/09/11 14:00:01 amb Exp $
- WWWOFFLE - World Wide Web Offline Explorer - Version 2.5.
- Configuration file management via a web-page.
- ******************/ /******************
- Written by Andrew M. Bishop
- This file Copyright 1997,98,99 Andrew M. Bishop
- It may be distributed under the GNU Public License, version 2, or
- any higher version. See section COPYING of the GNU Public license
- for conditions under which this file may be redistributed.
- ***************************************/
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <ctype.h>
- #include <sys/stat.h>
- #include <unistd.h>
- #include "wwwoffle.h"
- #include "misc.h"
- #include "config.h"
- #include "errors.h"
- typedef struct _ConfigSection
- {
- char *comment; /*+ The comment outside the section. +*/
- char *name; /*+ The name of the section. +*/
- char *file; /*+ The filename of an included section. +*/
- char *content; /*+ The content of the section. +*/
- }
- *ConfigSection;
- static void ConfigEditForms(int fd,ConfigSection *sections);
- static void ConfigEditUpdate(int fd,char *section,ConfigSection *sections);
- static ConfigSection *read_config_file(void);
- static int write_config_file(ConfigSection *sections);
- static void free_sections(ConfigSection *sections);
- /*++++++++++++++++++++++++++++++++++++++
- The control page that allows editing of the configuration file.
- int fd The file descriptor to write the file to.
- char *args The arguments to the page.
- Body *request_body The body of the HTTP request for the page.
- ++++++++++++++++++++++++++++++++++++++*/
- void ConfigEditPage(int fd,char *args,Body *request_body)
- {
- char *newargs=NULL;
- ConfigSection *sections;
- if(args)
- {
- if(*args=='!' && strchr(args+1,'!'))
- {
- char *pling;
- newargs=(char*)malloc(strlen(args)+1);
- strcpy(newargs,args+1);
- pling=strchr(newargs,'!');
- *pling=0;
- }
- else if(*args!='!')
- {
- newargs=(char*)malloc(strlen(args)+1);
- strcpy(newargs,args);
- }
- }
- sections=read_config_file();
- if(!sections)
- HTMLMessage(fd,404,"WWWOFFLE Configuration Error",NULL,"ConfigError",
- "section",NULL,
- "reason","ReadError",
- NULL);
- else if(newargs && *newargs)
- {
- int i=0;
- char *section=NULL;
- while(sections[i])
- {
- if(sections[i]->name && !strcmp(sections[i]->name,newargs))
- {section=newargs;break;}
- i++;
- }
- if(!section)
- HTMLMessage(fd,404,"WWWOFFLE Configuration Error",NULL,"ConfigError",
- "section",newargs,
- "reason","BadSection",
- NULL);
- else if(!request_body || strncmp(request_body->content,"value=",6))
- HTMLMessage(fd,404,"WWWOFFLE Configuration Error",NULL,"ConfigError",
- "section",newargs,
- "reason","BadBody",
- NULL);
- else
- {
- char *old=sections[i]->content;
- char *new=URLDecode(request_body->content+6,1);
- #if !defined(__CYGWIN__)
- char *p,*q;
- for(p=q=new;*p;p++)
- if(*p!='r')
- *q++=*p;
- *q=0;
- #endif
- sections[i]->content=new;
- free(old);
- ConfigEditUpdate(fd,section,sections);
- }
- }
- else
- ConfigEditForms(fd,sections);
- if(sections)
- free_sections(sections);
- if(newargs)
- free(newargs);
- }
- /*++++++++++++++++++++++++++++++++++++++
- The page that contains the forms making up the config file.
- int fd The file descriptor to write to.
- ConfigSection *sections The sections of the file.
- ++++++++++++++++++++++++++++++++++++++*/
- static void ConfigEditForms(int fd,ConfigSection *sections)
- {
- int i=0;
- HTMLMessageHead(fd,200,"WWWOFFLE Configuration Edit Page",
- NULL);
- HTMLMessageBody(fd,"ConfigEditPage-Head",
- NULL);
- while(sections[i])
- {
- char *htmlcomment=NULL,*htmlcontent=NULL;
- if(sections[i]->comment)
- htmlcomment=HTMLString(sections[i]->comment);
- if(sections[i]->content)
- htmlcontent=HTMLString(sections[i]->content);
- HTMLMessageBody(fd,"ConfigEditPage-Body",
- "section",sections[i]->name,
- "comment",htmlcomment,
- "content",htmlcontent,
- NULL);
- if(htmlcomment)
- free(htmlcomment);
- if(htmlcontent)
- free(htmlcontent);
- i++;
- }
- HTMLMessageBody(fd,"ConfigEditPage-Tail",
- NULL);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Update the configuration file.
- int fd The file descriptor to write the message to.
- char *section The section that was updated.
- ConfigSection *sections The sections including the updated one.
- ++++++++++++++++++++++++++++++++++++++*/
- static void ConfigEditUpdate(int fd,char *section,ConfigSection *sections)
- {
- if(write_config_file(sections))
- HTMLMessage(fd,404,"WWWOFFLE Configuration Error",NULL,"ConfigError",
- "section",section,
- "reason","WriteError",
- NULL);
- else
- HTMLMessage(fd,200,"WWWOFFLE Configuration Update",NULL,"ConfigUpdate",
- "section",section,
- NULL);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Read in the config file into a set of sections.
- ConfigSection *read_config_file Returns the sections of the file as a NULL terminated list.
- ++++++++++++++++++++++++++++++++++++++*/
- static ConfigSection *read_config_file(void)
- {
- int sec_num=0,state=0;
- FILE *conf;
- ConfigSection *sections;
- char *line=NULL;
- int line_num=0;
- conf=fopen(ConfigFile,"r");
- if(!conf)
- {PrintMessage(Warning,"Cannot open the config file '%s' for reading.",ConfigFile); return(NULL);}
- sections=(ConfigSection*)calloc(1,sizeof(ConfigSection));
- while((line=fgets_realloc(line,conf)))
- {
- char *l=line;
- char *r=line+strlen(line)-1;
- line_num++;
- while(isspace(*l))
- l++;
- if(state==0 && *l=='#')
- {
- state=1;
- sections=(ConfigSection*)realloc((void*)sections,sizeof(ConfigSection)*(sec_num+2));
- sections[sec_num]=(ConfigSection)calloc(1,sizeof(struct _ConfigSection));
- sections[++sec_num]=NULL;
- sections[sec_num-1]->comment=(char*)malloc(strlen(l)+1);
- strcpy(sections[sec_num-1]->comment,l);
- }
- else if((state==1 || state==2) && *l=='#')
- {
- sections[sec_num-1]->comment=(char*)realloc((void*)sections[sec_num-1]->comment,strlen(sections[sec_num-1]->comment)+strlen(l)+1);
- strcat(sections[sec_num-1]->comment,l);
- }
- else if(state==0 && !*l)
- ;
- else if(state==1 && !*l)
- state=0;
- else if((state==0 || state==1) && *l)
- {
- state=2;
- while(r>l && isspace(*r))
- *r--=0;
- if(sec_num==0 || sections[sec_num-1]->name)
- {
- sections=(ConfigSection*)realloc((void*)sections,sizeof(ConfigSection)*(sec_num+2));
- sections[sec_num]=(ConfigSection)calloc(1,sizeof(struct _ConfigSection));
- sections[++sec_num]=NULL;
- }
- sections[sec_num-1]->name=(char*)malloc(strlen(l)+1);
- strcpy(sections[sec_num-1]->name,l);
- }
- else if(state==2 && !*l)
- ;
- else if(state==2 && *l=='{')
- {
- state=3;
- sections[sec_num-1]->content=(char*)malloc(1);
- strcpy(sections[sec_num-1]->content,"");
- }
- else if(state==2 && *l=='[')
- {
- state=4;
- }
- else if(state==3 && *l=='}')
- state=0;
- else if(state==3)
- {
- sections[sec_num-1]->content=(char*)realloc((void*)sections[sec_num-1]->content,strlen(sections[sec_num-1]->content)+strlen(line)+1);
- strcat(sections[sec_num-1]->content,line);
- }
- else if(state==4 && *l)
- {
- state=5;
- while(r>l && isspace(*r))
- *r--=0;
- sections[sec_num-1]->file=(char*)malloc(strlen(l)+1);
- strcpy(sections[sec_num-1]->file,l);
- }
- else if(state==5 && *l==']')
- state=0;
- else
- {
- line[strlen(line)-1]=0;
- PrintMessage(Warning,"Error parsing config file, line %d = '%s' [state=%d]",line_num,line,state);
- free_sections(sections);
- return(NULL);
- }
- }
- fclose(conf);
- for(sec_num=0;sections[sec_num];sec_num++)
- if(sections[sec_num]->name && sections[sec_num]->file)
- {
- char *name,*r,*old;
- sections[sec_num]->content=(char*)malloc(1);
- strcpy(sections[sec_num]->content,"");
- name=(char*)malloc(strlen(ConfigFile)+strlen(sections[sec_num]->file)+1);
- strcpy(name,ConfigFile);
- r=name+strlen(name)-1;
- while(r>name && *r!='/')
- r--;
- strcpy(r+1,sections[sec_num]->file);
- conf=fopen(name,"r");
- if(!conf)
- {PrintMessage(Warning,"Cannot open the config file '%s' for reading.",name); free_sections(sections); return(NULL);}
- old=sections[sec_num]->file;
- sections[sec_num]->file=name;
- free(old);
- while((line=fgets_realloc(line,conf)))
- {
- sections[sec_num]->content=(char*)realloc((void*)sections[sec_num]->content,strlen(sections[sec_num]->content)+strlen(line)+1);
- strcat(sections[sec_num]->content,line);
- }
- fclose(conf);
- }
- return(sections);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Write out a set of sections to the config file.
- int write_config_file Returns 1 if in error.
- ConfigSection *sections The sections to write out.
- ++++++++++++++++++++++++++++++++++++++*/
- static int write_config_file(ConfigSection *sections)
- {
- char *conf_file_backup;
- int renamed=0,i;
- struct stat buf;
- FILE *conf;
- /* Rename the old file as a backup. */
- conf_file_backup=(char*)malloc(strlen(ConfigFile)+5);
- strcpy(conf_file_backup,ConfigFile);
- strcat(conf_file_backup,".bak");
- if(rename(ConfigFile,conf_file_backup))
- PrintMessage(Warning,"Cannot rename the config file '%s' to '%s'.",ConfigFile,conf_file_backup);
- else
- {
- renamed=1;
- if(stat(conf_file_backup,&buf))
- PrintMessage(Warning,"Cannot stat the config file '%s'.",ConfigFile);
- }
- conf=fopen(ConfigFile,"w");
- if(!conf)
- {PrintMessage(Warning,"Cannot open the config file '%s' for writing.",ConfigFile); return(1);}
- if(renamed)
- {
- chown(ConfigFile,buf.st_uid,buf.st_gid);
- chmod(ConfigFile,buf.st_mode&(~S_IFMT));
- }
- for(i=0;sections[i];i++)
- {
- if(sections[i]->comment)
- {
- fprintf(conf,sections[i]->comment);
- fprintf(conf,"n");
- }
- if(sections[i]->name)
- {
- fprintf(conf,"%sn",sections[i]->name);
- if(sections[i]->file)
- {
- char *p=sections[i]->file+strlen(sections[i]->file)-1;
- while(p>sections[i]->file && *p!='/')
- p--;
- fprintf(conf,"[n");
- fprintf(conf,"%sn",p+1);
- fprintf(conf,"]nnn");
- }
- else
- {
- fprintf(conf,"{n");
- if(sections[i]->content)
- fputs(sections[i]->content,conf);
- if(sections[i]->content[strlen(sections[i]->content)-1]!='n')
- fputs("n",conf);
- fprintf(conf,"}nnn");
- }
- }
- }
- fclose(conf);
- free(conf_file_backup);
- for(i=0;sections[i];i++)
- if(sections[i]->name && sections[i]->file)
- {
- conf_file_backup=(char*)malloc(strlen(sections[i]->file)+5);
- strcpy(conf_file_backup,sections[i]->file);
- strcat(conf_file_backup,".bak");
- if(rename(sections[i]->file,conf_file_backup))
- PrintMessage(Warning,"Cannot rename the config file '%s' to '%s'.",sections[i]->file,conf_file_backup);
- else
- {
- renamed=1;
- if(stat(conf_file_backup,&buf))
- PrintMessage(Warning,"Cannot stat the config file '%s'.",sections[i]->file);
- }
- conf=fopen(sections[i]->file,"w");
- if(!conf)
- {PrintMessage(Warning,"Cannot open the config file '%s' for writing.",sections[i]->file); return(1);}
- if(renamed)
- {
- chown(sections[i]->file,buf.st_uid,buf.st_gid);
- chmod(sections[i]->file,buf.st_mode&(~S_IFMT));
- }
- fputs(sections[i]->content,conf);
- fclose(conf);
- free(conf_file_backup);
- }
- return(0);
- }
- /*++++++++++++++++++++++++++++++++++++++
- Free up a set of sections.
- ConfigSection *sections The sections that are to be freed up.
- ++++++++++++++++++++++++++++++++++++++*/
- static void free_sections(ConfigSection *sections)
- {
- int i=0;
- while(sections[i])
- {
- if(sections[i]->comment)
- free(sections[i]->comment);
- if(sections[i]->name)
- free(sections[i]->name);
- if(sections[i]->file)
- free(sections[i]->file);
- if(sections[i]->content)
- free(sections[i]->content);
- free(sections[i]);
- i++;
- }
- free(sections);
- }