configedit.c
上传用户:seven77cht
上传日期:2007-01-04
资源大小:486k
文件大小:13k
源码类别:

浏览器

开发平台:

Unix_Linux

  1. /***************************************
  2.   $Header: /home/amb/wwwoffle/RCS/configedit.c 2.19 1999/09/11 14:00:01 amb Exp $
  3.   WWWOFFLE - World Wide Web Offline Explorer - Version 2.5.
  4.   Configuration file management via a web-page.
  5.   ******************/ /******************
  6.   Written by Andrew M. Bishop
  7.   This file Copyright 1997,98,99 Andrew M. Bishop
  8.   It may be distributed under the GNU Public License, version 2, or
  9.   any higher version.  See section COPYING of the GNU Public license
  10.   for conditions under which this file may be redistributed.
  11.   ***************************************/
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <ctype.h>
  16. #include <sys/stat.h>
  17. #include <unistd.h>
  18. #include "wwwoffle.h"
  19. #include "misc.h"
  20. #include "config.h"
  21. #include "errors.h"
  22. typedef struct _ConfigSection
  23. {
  24.  char *comment;                 /*+ The comment outside the section. +*/
  25.  char *name;                    /*+ The name of the section. +*/
  26.  char *file;                    /*+ The filename of an included section. +*/
  27.  char *content;                 /*+ The content of the section. +*/
  28. }
  29. *ConfigSection;
  30. static void ConfigEditForms(int fd,ConfigSection *sections);
  31. static void ConfigEditUpdate(int fd,char *section,ConfigSection *sections);
  32. static ConfigSection *read_config_file(void);
  33. static int write_config_file(ConfigSection *sections);
  34. static void free_sections(ConfigSection *sections);
  35. /*++++++++++++++++++++++++++++++++++++++
  36.   The control page that allows editing of the configuration file.
  37.   int fd The file descriptor to write the file to.
  38.   char *args The arguments to the page.
  39.   Body *request_body The body of the HTTP request for the page.
  40.   ++++++++++++++++++++++++++++++++++++++*/
  41. void ConfigEditPage(int fd,char *args,Body *request_body)
  42. {
  43.  char *newargs=NULL;
  44.  ConfigSection *sections;
  45.  if(args)
  46.    {
  47.     if(*args=='!' && strchr(args+1,'!'))
  48.       {
  49.        char *pling;
  50.        newargs=(char*)malloc(strlen(args)+1);
  51.        strcpy(newargs,args+1);
  52.        pling=strchr(newargs,'!');
  53.        *pling=0;
  54.       }
  55.     else if(*args!='!')
  56.       {
  57.        newargs=(char*)malloc(strlen(args)+1);
  58.        strcpy(newargs,args);
  59.       }
  60.    }
  61.  sections=read_config_file();
  62.  if(!sections)
  63.     HTMLMessage(fd,404,"WWWOFFLE Configuration Error",NULL,"ConfigError",
  64.                 "section",NULL,
  65.                 "reason","ReadError",
  66.                 NULL);
  67.  else if(newargs && *newargs)
  68.    {
  69.     int i=0;
  70.     char *section=NULL;
  71.     while(sections[i])
  72.       {
  73.        if(sections[i]->name && !strcmp(sections[i]->name,newargs))
  74.          {section=newargs;break;}
  75.        i++;
  76.       }
  77.     if(!section)
  78.        HTMLMessage(fd,404,"WWWOFFLE Configuration Error",NULL,"ConfigError",
  79.                    "section",newargs,
  80.                    "reason","BadSection",
  81.                    NULL);
  82.     else if(!request_body || strncmp(request_body->content,"value=",6))
  83.        HTMLMessage(fd,404,"WWWOFFLE Configuration Error",NULL,"ConfigError",
  84.                    "section",newargs,
  85.                    "reason","BadBody",
  86.                    NULL);
  87.     else
  88.       {
  89.        char *old=sections[i]->content;
  90.        char *new=URLDecode(request_body->content+6,1);
  91. #if !defined(__CYGWIN__)
  92.        char *p,*q;
  93.        for(p=q=new;*p;p++)
  94.           if(*p!='r')
  95.              *q++=*p;
  96.        *q=0;
  97. #endif
  98.        sections[i]->content=new;
  99.        free(old);
  100.        ConfigEditUpdate(fd,section,sections);
  101.       }
  102.    }
  103.  else
  104.     ConfigEditForms(fd,sections);
  105.  if(sections)
  106.     free_sections(sections);
  107.  if(newargs)
  108.     free(newargs);
  109. }
  110. /*++++++++++++++++++++++++++++++++++++++
  111.   The page that contains the forms making up the config file.
  112.   int fd The file descriptor to write to.
  113.   ConfigSection *sections The sections of the file.
  114.   ++++++++++++++++++++++++++++++++++++++*/
  115. static void ConfigEditForms(int fd,ConfigSection *sections)
  116. {
  117.  int i=0;
  118.  HTMLMessageHead(fd,200,"WWWOFFLE Configuration Edit Page",
  119.                  NULL);
  120.  HTMLMessageBody(fd,"ConfigEditPage-Head",
  121.                  NULL);
  122.  while(sections[i])
  123.    {
  124.     char *htmlcomment=NULL,*htmlcontent=NULL;
  125.     if(sections[i]->comment)
  126.        htmlcomment=HTMLString(sections[i]->comment);
  127.     if(sections[i]->content)
  128.        htmlcontent=HTMLString(sections[i]->content);
  129.     HTMLMessageBody(fd,"ConfigEditPage-Body",
  130.                     "section",sections[i]->name,
  131.                     "comment",htmlcomment,
  132.                     "content",htmlcontent,
  133.                     NULL);
  134.     if(htmlcomment)
  135.        free(htmlcomment);
  136.     if(htmlcontent)
  137.        free(htmlcontent);
  138.     i++;
  139.    }
  140.  HTMLMessageBody(fd,"ConfigEditPage-Tail",
  141.                  NULL);
  142. }
  143. /*++++++++++++++++++++++++++++++++++++++
  144.   Update the configuration file.
  145.   int fd The file descriptor to write the message to.
  146.   char *section The section that was updated.
  147.   ConfigSection *sections The sections including the updated one.
  148.   ++++++++++++++++++++++++++++++++++++++*/
  149. static void ConfigEditUpdate(int fd,char *section,ConfigSection *sections)
  150. {
  151.  if(write_config_file(sections))
  152.     HTMLMessage(fd,404,"WWWOFFLE Configuration Error",NULL,"ConfigError",
  153.                 "section",section,
  154.                 "reason","WriteError",
  155.                 NULL);
  156.  else
  157.     HTMLMessage(fd,200,"WWWOFFLE Configuration Update",NULL,"ConfigUpdate",
  158.                 "section",section,
  159.                 NULL);
  160. }
  161. /*++++++++++++++++++++++++++++++++++++++
  162.   Read in the config file into a set of sections.
  163.   ConfigSection *read_config_file Returns the sections of the file as a NULL terminated list.
  164.   ++++++++++++++++++++++++++++++++++++++*/
  165. static ConfigSection *read_config_file(void)
  166. {
  167.  int sec_num=0,state=0;
  168.  FILE *conf;
  169.  ConfigSection *sections;
  170.  char *line=NULL;
  171.  int line_num=0;
  172.  conf=fopen(ConfigFile,"r");
  173.  if(!conf)
  174.    {PrintMessage(Warning,"Cannot open the config file '%s' for reading.",ConfigFile); return(NULL);}
  175.  sections=(ConfigSection*)calloc(1,sizeof(ConfigSection));
  176.  while((line=fgets_realloc(line,conf)))
  177.    {
  178.     char *l=line;
  179.     char *r=line+strlen(line)-1;
  180.     line_num++;
  181.     while(isspace(*l))
  182.        l++;
  183.     if(state==0 && *l=='#')
  184.       {
  185.        state=1;
  186.        sections=(ConfigSection*)realloc((void*)sections,sizeof(ConfigSection)*(sec_num+2));
  187.        sections[sec_num]=(ConfigSection)calloc(1,sizeof(struct _ConfigSection));
  188.        sections[++sec_num]=NULL;
  189.        sections[sec_num-1]->comment=(char*)malloc(strlen(l)+1);
  190.        strcpy(sections[sec_num-1]->comment,l);
  191.       }
  192.     else if((state==1 || state==2) && *l=='#')
  193.       {
  194.        sections[sec_num-1]->comment=(char*)realloc((void*)sections[sec_num-1]->comment,strlen(sections[sec_num-1]->comment)+strlen(l)+1);
  195.        strcat(sections[sec_num-1]->comment,l);
  196.       }
  197.     else if(state==0 && !*l)
  198.       ;
  199.     else if(state==1 && !*l)
  200.        state=0;
  201.     else if((state==0 || state==1) && *l)
  202.       {
  203.        state=2;
  204.        while(r>l && isspace(*r))
  205.           *r--=0;
  206.        if(sec_num==0 || sections[sec_num-1]->name)
  207.          {
  208.           sections=(ConfigSection*)realloc((void*)sections,sizeof(ConfigSection)*(sec_num+2));
  209.           sections[sec_num]=(ConfigSection)calloc(1,sizeof(struct _ConfigSection));
  210.           sections[++sec_num]=NULL;
  211.          }
  212.        sections[sec_num-1]->name=(char*)malloc(strlen(l)+1);
  213.        strcpy(sections[sec_num-1]->name,l);
  214.       }
  215.     else if(state==2 && !*l)
  216.       ;
  217.     else if(state==2 && *l=='{')
  218.       {
  219.        state=3;
  220.        sections[sec_num-1]->content=(char*)malloc(1);
  221.        strcpy(sections[sec_num-1]->content,"");
  222.       }
  223.     else if(state==2 && *l=='[')
  224.       {
  225.        state=4;
  226.       }
  227.     else if(state==3 && *l=='}')
  228.        state=0;
  229.     else if(state==3)
  230.       {
  231.        sections[sec_num-1]->content=(char*)realloc((void*)sections[sec_num-1]->content,strlen(sections[sec_num-1]->content)+strlen(line)+1);
  232.        strcat(sections[sec_num-1]->content,line);
  233.       }
  234.     else if(state==4 && *l)
  235.       {
  236.        state=5;
  237.        while(r>l && isspace(*r))
  238.           *r--=0;
  239.        sections[sec_num-1]->file=(char*)malloc(strlen(l)+1);
  240.        strcpy(sections[sec_num-1]->file,l);
  241.       }
  242.     else if(state==5 && *l==']')
  243.        state=0;
  244.     else
  245.       {
  246.        line[strlen(line)-1]=0;
  247.        PrintMessage(Warning,"Error parsing config file, line %d = '%s' [state=%d]",line_num,line,state);
  248.        free_sections(sections);
  249.        return(NULL);
  250.       }
  251.    }
  252.  fclose(conf);
  253.  for(sec_num=0;sections[sec_num];sec_num++)
  254.     if(sections[sec_num]->name && sections[sec_num]->file)
  255.       {
  256.        char *name,*r,*old;
  257.        sections[sec_num]->content=(char*)malloc(1);
  258.        strcpy(sections[sec_num]->content,"");
  259.        name=(char*)malloc(strlen(ConfigFile)+strlen(sections[sec_num]->file)+1);
  260.        strcpy(name,ConfigFile);
  261.        r=name+strlen(name)-1;
  262.        while(r>name && *r!='/')
  263.           r--;
  264.        strcpy(r+1,sections[sec_num]->file);
  265.        conf=fopen(name,"r");
  266.        if(!conf)
  267.          {PrintMessage(Warning,"Cannot open the config file '%s' for reading.",name); free_sections(sections); return(NULL);}
  268.        old=sections[sec_num]->file;
  269.        sections[sec_num]->file=name;
  270.        free(old);
  271.        while((line=fgets_realloc(line,conf)))
  272.          {
  273.           sections[sec_num]->content=(char*)realloc((void*)sections[sec_num]->content,strlen(sections[sec_num]->content)+strlen(line)+1);
  274.           strcat(sections[sec_num]->content,line);
  275.          }
  276.        fclose(conf);
  277.       }
  278.  return(sections);
  279. }
  280. /*++++++++++++++++++++++++++++++++++++++
  281.   Write out a set of sections to the config file.
  282.   int write_config_file Returns 1 if in error.
  283.   ConfigSection *sections The sections to write out.
  284.   ++++++++++++++++++++++++++++++++++++++*/
  285. static int write_config_file(ConfigSection *sections)
  286. {
  287.  char *conf_file_backup;
  288.  int renamed=0,i;
  289.  struct stat buf;
  290.  FILE *conf;
  291.  /* Rename the old file as a backup. */
  292.  conf_file_backup=(char*)malloc(strlen(ConfigFile)+5);
  293.  strcpy(conf_file_backup,ConfigFile);
  294.  strcat(conf_file_backup,".bak");
  295.  if(rename(ConfigFile,conf_file_backup))
  296.     PrintMessage(Warning,"Cannot rename the config file '%s' to '%s'.",ConfigFile,conf_file_backup);
  297.  else
  298.    {
  299.     renamed=1;
  300.     if(stat(conf_file_backup,&buf))
  301.        PrintMessage(Warning,"Cannot stat the config file '%s'.",ConfigFile);
  302.    }
  303.  conf=fopen(ConfigFile,"w");
  304.  if(!conf)
  305.    {PrintMessage(Warning,"Cannot open the config file '%s' for writing.",ConfigFile); return(1);}
  306.  if(renamed)
  307.    {
  308.     chown(ConfigFile,buf.st_uid,buf.st_gid);
  309.     chmod(ConfigFile,buf.st_mode&(~S_IFMT));
  310.    }
  311.  for(i=0;sections[i];i++)
  312.    {
  313.     if(sections[i]->comment)
  314.       {
  315.        fprintf(conf,sections[i]->comment);
  316.        fprintf(conf,"n");
  317.       }
  318.     if(sections[i]->name)
  319.       {
  320.        fprintf(conf,"%sn",sections[i]->name);
  321.        if(sections[i]->file)
  322.          {
  323.           char *p=sections[i]->file+strlen(sections[i]->file)-1;
  324.           while(p>sections[i]->file && *p!='/')
  325.              p--;
  326.           fprintf(conf,"[n");
  327.           fprintf(conf,"%sn",p+1);
  328.           fprintf(conf,"]nnn");
  329.          }
  330.        else
  331.          {
  332.           fprintf(conf,"{n");
  333.           if(sections[i]->content)
  334.              fputs(sections[i]->content,conf);
  335.           if(sections[i]->content[strlen(sections[i]->content)-1]!='n')
  336.              fputs("n",conf);
  337.           fprintf(conf,"}nnn");
  338.          }
  339.       }
  340.    }
  341.  fclose(conf);
  342.  free(conf_file_backup);
  343.  for(i=0;sections[i];i++)
  344.     if(sections[i]->name && sections[i]->file)
  345.       {
  346.        conf_file_backup=(char*)malloc(strlen(sections[i]->file)+5);
  347.        strcpy(conf_file_backup,sections[i]->file);
  348.        strcat(conf_file_backup,".bak");
  349.        if(rename(sections[i]->file,conf_file_backup))
  350.           PrintMessage(Warning,"Cannot rename the config file '%s' to '%s'.",sections[i]->file,conf_file_backup);
  351.        else
  352.          {
  353.           renamed=1;
  354.           if(stat(conf_file_backup,&buf))
  355.              PrintMessage(Warning,"Cannot stat the config file '%s'.",sections[i]->file);
  356.          }
  357.        conf=fopen(sections[i]->file,"w");
  358.        if(!conf)
  359.          {PrintMessage(Warning,"Cannot open the config file '%s' for writing.",sections[i]->file); return(1);}
  360.        if(renamed)
  361.          {
  362.           chown(sections[i]->file,buf.st_uid,buf.st_gid);
  363.           chmod(sections[i]->file,buf.st_mode&(~S_IFMT));
  364.          }
  365.        fputs(sections[i]->content,conf);
  366.        fclose(conf);
  367.        free(conf_file_backup);
  368.       }
  369.  return(0);
  370. }
  371. /*++++++++++++++++++++++++++++++++++++++
  372.   Free up a set of sections.
  373.   ConfigSection *sections The sections that are to be freed up.
  374.   ++++++++++++++++++++++++++++++++++++++*/
  375. static void free_sections(ConfigSection *sections)
  376. {
  377.  int i=0;
  378.  while(sections[i])
  379.    {
  380.     if(sections[i]->comment)
  381.        free(sections[i]->comment);
  382.     if(sections[i]->name)
  383.        free(sections[i]->name);
  384.     if(sections[i]->file)
  385.        free(sections[i]->file);
  386.     if(sections[i]->content)
  387.        free(sections[i]->content);
  388.     free(sections[i]);
  389.     i++;
  390.    }
  391.  free(sections);
  392. }