/*
** Copyright (c) 2006 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/
**
*******************************************************************************
**
** This file contains code used to execute external programs on CVSTrac
** objects.
*/
#include "config.h"
#include "tools.h"
#include <sys/times.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <time.h>
#include <string.h>

/*
** Output a file through a crude HTML filter. If the input is HTML and the
** bForce flag zero, it'll be passed through unchanged. Otherwise, it'll be
** wrapped with <pre> tags and marked up as HTML.
** Returns the number of bytes read from the pipe, or less than zero on failure.
*/
int output_tool(FILE *in){
  /* Output the result of the command.  If the first non-whitespace
  ** character is "<" then assume the command is giving us HTML.  In
  ** that case, do no translation.  If the first non-whitespace character
  ** is anything other than "<" then assume the output is plain text.
  ** Convert this text into HTML.
  */
  char zLine[2000];
  char *zFormat = 0;
  int i, n=0;
  while( fgets(zLine, sizeof(zLine), in) ){
    n += strlen(zLine);
    for(i=0; isspace(zLine[i]); i++){}
    if( zLine[i]==0 ) continue;
    if( zLine[i]=='<' ){
      zFormat = "%s";
    }else{
      @ <pre>
      zFormat = "%h";
    }
    cgi_printf(zFormat, zLine);
    break;
  }
  while( fgets(zLine, sizeof(zLine), in) ){
    n += strlen(zLine);
    cgi_printf(zFormat, zLine);
  }
  if( zFormat && zFormat[1]=='h' ){
    @ </pre>
  }
  return n;
}

/*
** Execute the specified tool, handling all the common substitutions and
** putting content into a temporary file.
** Returns number of bytes received from the tool, or less than zero on
** failure.
*/
int execute_tool(
  const char *zTool,
  const char *zAction,
  const char *zContent,
  const char **azTSubst
){
  FILE *in;
  char *zCmd;
  const char *azSubst[32];
  int n = 0;
  char zF[200];

  db_add_functions();
  if( !db_exists("SELECT 1 FROM tool,user "
                 "WHERE tool.name='%q' AND user.id='%q' "
                 "      AND cap_and(user.capabilities,tool.perms)!=''",
                 zTool, g.zUser)){
    return -1;
  }

  while(azTSubst[n]){
    azSubst[n] = azTSubst[n];
    n++;
  }

  azSubst[n++] = "RP";
  azSubst[n++] = db_config("cvsroot", "");
  azSubst[n++] = "B";
  azSubst[n++] = g.zBaseURL;
  azSubst[n++] = "P";
  azSubst[n++] = g.zName;
  azSubst[n++] = "U";
  azSubst[n++] = g.zUser;
  azSubst[n++] = "N";
  azSubst[n++] = mprintf("%d",time(0));
  azSubst[n++] = "T";
  azSubst[n++] = quotable_string(zTool);
  azSubst[n++] = "UC";
  azSubst[n++] = db_short_query("SELECT capabilities FROM user "
                                "WHERE id='%q'",g.zUser);
  zF[0] = 0;
  if( zContent ){
    /* content is special. If provided, we need to write it to a temp file
    ** so that it can be given to the program via the %C subst.
    */
    if( !write_to_temp(zContent,zF,sizeof(zF)) ){
      azSubst[n++] = "C";
      azSubst[n++] = zF;
    }
  }

  azSubst[n] = 0;

  zCmd = subst(zAction, azSubst);

  in = popen(zCmd,"r");
  free(zCmd);
  if( in==0 ) {
    if( zF[0] ) unlink(zF);
    return -1;
  }

  n = output_tool(in);

  pclose(in);
  if( zF[0] ) unlink(zF);

  return n;
}



syntax highlighted by Code2HTML, v. 0.9.1