/* I wrote this to be more generalized... pho's does the same thing
 * and it's much shorter.  So I'm keeping this around as a lesson to
 * myself to keep things simple!  (168 lines vs. 46)
 * -jer 20000204.2130
 */  

void SLForumUser::loadPrefs()  /* new jer ver */
{
  const int MAX_FILE_LINES = 8;  /* 5 params currently, plus blank lines? 
				  * This maximum is to prevent denial-of-
				  * service attacks from a really long file,
				  * since nothing else goes on in the forum
				  * while this is being read in.
				  */
  const size_t MAX_FILE_CHARS = MAX_FILE_LINES * (16+64+20);

  char   filebuf[MAX_FILE_CHARS + 1];
  size_t bufleft;    // how much of filebuf left to read?

  // reading in the file
  {
    FILE *f;
    {
      char fname[80];
      sprintf(fname,"/tmp/.slforum-%s",name);  // array's long enough
      f=fopen(fname,"r");
    }
    if (f==NULL) {
      return;
    }
    
    // read the entire file into a buffer; check its size and complain/stop
    // if it's too long.

    bufleft = fread (&filebuf, sizeof(char), MAX_FILE_CHARS, f);
    filebuf[bufleft] = '\0';

    if ((MAX_FILE_CHARS <= bufleft) && ! feof(f)) {
      Send("Prefs file is too long; has it been tampered with?", 0, true);
      fclose(f);
      return;
    }
    // we're done with the file.
    fclose(f); 
  }


  // now parse that buffer.
  {
    char *paramname=NULL, *paramval=NULL;
    		/* holds where these are found in buffer
		 * (we null-terminate 'em and pass these
		 *  two pointers to c_zebra).
		 */
    char *pc;       // pointer to curr char
    char c = '\0';  // curr char being read
    char lastc;     // prev char read
    enum {STATE_LINE_START, STATE_PARAMNAME, STATE_TWEENNAMEVAL,
	  STATE_PARAMVAL, STATE_EOL} stayte = STATE_LINE_START;

    /*  int stayte=0; */
    int lineno = 1;


    /* file format: <whitespace>paramname<whitespace>value\n
       <whitespace>paramname<whitespace>value\n
       ...
    */

    // STATE STATE STATE here! got states, just gotta write code in switch.
    // when we get a syntax error on a line, announce it and ignore that line.
    pc = filebuf;
    while (bufleft > 0)
      {
	lastc = c;  // save prev char
	c = *pc;    // get this one from buf
	++pc;       // move pointer to next one
	--bufleft;  // decr count of how many left
	
	switch (stayte) {
	case STATE_LINE_START: /* whitespace at start of line,
				* looking for paramname */
	  {
	    if (isalpha(c)) {  // letter: start of a param
	      stayte = STATE_PARAMNAME;
	      paramname = pc;           // save this location
	    }
	    else if ((c == '\n') || (c == '\r')) {  // newline
	      if ((lastc != c) && (lastc != '\n') && (lastc != '\r'))
		++lineno;
	    }
	    else if (c <= ' ') { // whitespace
	      // do nothing, just wait for next char
	    } else {
	      char buf[64];
	      snprintf (buf, 63, "Invalid param name charcter on line %d, ignoring line", lineno);
	      Send (buf, 0, true);
	      stayte = STATE_EOL;
	    }
	    break;
	  }
	case STATE_PARAMNAME: /* reading paramname */
	  { 
	    if (c <= ' ') {  // whitespace
	      *pc = '\0';  // mark end of paramname properly
	      stayte = STATE_TWEENNAMEVAL;
	    } else if isalnum(c) {  // part of paramname
	      // don't need to do anything
	    } else {	// not whitespace or part of paramname?
	      char buf[64];
	      snprintf (buf, 63, "Param name has invalid char on line %d, skipping line", lineno);
	      Send (buf, 0, true);
	      stayte = STATE_EOL;
	    }
	    break;
	  }
	case STATE_TWEENNAMEVAL: /* whitespace tween paramname and value */
	  {
	    if ((c == '\r') || (c == '\n')) {	// end of line :-(
	      char buf[64];
	      snprintf (buf, 63, "No value given for param on line %d, ignoring line", lineno);
	      Send (buf, 0, true);
	      // now count line, and set state to start of new line
	      if ((lastc != c) && (lastc != '\n') && (lastc != '\r'))
		++lineno;
	      stayte = STATE_LINE_START;
	    }
	    else if (c  <= ' ') {  // whitespace
	      // this is expected.
	    } else {	// start of param val
	      stayte = STATE_PARAMVAL;
	      paramname = pc;
	    }
	    break;
	  }
	case STATE_PARAMVAL:  /* reading param val */
	  {	
	    if (c <= ' ') {  // whitespace
	      *pc = '\0';  // mark end of paramval properly

	      // Run the !set command!!
	      slfparam params[2];
	      params[0].strval = paramname;
	      params[1].strval = paramval;
	      SLForumCmd::c_zebra ( room, this, 2, params );

	      stayte = STATE_EOL;   	      // now skip to end-of-line.
	    } else {  // part of paramval
		// no need to do anything, it's part of it.
	    } 
	    break;
	  }
	case STATE_EOL:  /* reading whitespace after val (or rest of a badly
			  * formed line), looking for \n */
	  {
	    if ((c != '\n') && (c != '\r')) {
	      // that's ok, keep going
	    } else {
	      // found newline.
	      // now move along in the file.
	      if ((lastc != c) && (lastc != '\n') && (lastc != '\r'))
		++lineno;
	      stayte = STATE_LINE_START;
	    }
	    break;
	  }  // end STATE_EOL
	}  // endsw
      }  // end while-reading-file
    
    if ((stayte == STATE_PARAMNAME) || (stayte == STATE_TWEENNAMEVAL)
	|| (stayte == STATE_PARAMVAL)) {
      Send ("** Encountered EOF in middle of line **", 0, true);
    }
  }  // end parse-buffer
}  // end loadPrefs



void SLForumUser::loadPrefs()  /* old pho ver */
{
  FILE *fp;
  int c;
  char fname[80];
  char prefBuf[128];
  char *p=prefBuf;      // pointer to place in prefBuf
  char field[15],val[30];
  
  if (is_guest)
    return;

  room->logprintf("Loading values...\n");
  sprintf(fname,"/tmp/.slforum-%s",this->name);

  fp=fopen(fname,"r");
  if (fp==NULL)
    return;
  
  room->logprintf("Opened file %s\n",fname);
  // Move to own fxn?
  fgets(prefBuf,128,fp);     // Buffer one line
  // room->logprintf("  read from config file: %s\n",prefBuf);
  c=0;
    // read in the field
    while(*p!='\t'){
      ++c;
      ++p;
    }
    strncpy(field,prefBuf,c);
    field[c]='\0';
    ++p;
    strncpy(val,p,29);  val[29] = '\0';
    //  room->logprintf("read in %d bytes to field: %s\n",c,field);
    //  room->logprintf("read in value: %s\n",val);

  if(strncmp(field,"command", 6)==0)
    cmd_char=val[0];

  //  room->logprintf("%s set to %c  (var == %c)\n",field,cmd_char,val[0]);
  fclose(fp);
  //  room->logprintf("Calling buildHelp()\n");
  buildHelp(SLF_CMD_ESC_CHAR,cmd_char);
}


int SLForumUser::savePrefs() const {
  FILE *outp;
  char fn[80];

  if(is_guest)
    return 0;
  sprintf(fn,"/tmp/.slforum-%s",name);
  room->logprintf("Opening %s and saving...\n",fn);
  outp= fopen(fn,"w");
  if(outp==NULL)
    return 0;
  fprintf(outp,"%s\t%c\n","command",cmd_char);
  fclose(outp);
  return 1;
}


