Logo Search packages:      
Sourcecode: rapple version File versions  Download package

mod_xslt.c

Go to the documentation of this file.
/*
   Name: $RCSfile: mod_xslt.c,v $
   Author: Alan Moran
   $Date: 2005/11/26 15:04:17 $
   $Revision: 1.10 $
   $Id: mod_xslt.c,v 1.10 2005/11/26 15:04:17 a_j_moran Exp $

   Legal Notice:

   This program is free software; you can redistribute it and/or
   modify it under the terms of the license contained in the
   COPYING file that comes with this distribution.

 */

/**
   @file

   @brief Functions to support the xslt module.

 */

#include "globals.h"
/* these conditionals must appear after the inclusion of the globals header */
#if SUPPORT_XSLT_PROC == 1
#include <sablot.h>
#elif SUPPORT_XSLT_PROC == 2
#include <libxml/xmlmemory.h>
#include <libxml/debugXML.h>
#include <libxml/HTMLtree.h>
#include <libxml/xmlIO.h>
/* #include <libxml/DOCBparser.h> */
#include <libxml/xinclude.h>
#include <libxml/catalog.h>
#include <libxslt/xslt.h>
#include <libxslt/xsltInternals.h>
#include <libxslt/transform.h>
#include <libxslt/xsltutils.h>
#endif
#include "mod_xslt.h"

static rpl_str_t rpl_xslt_base_dir;
static rpl_str_t host_param, out_dir, xsl_filename;

#if SUPPORT_XSLT_PROC == 1
static SablotSituation situation;
static SablotHandle proc;
/* Sablot code samples often use (void *) for a preparsed variable - in fact this
   is the typedef of SDOM_Document (sablot.h) */
static SDOM_Document preparsed; 
#elif SUPPORT_XSLT_PROC == 2
static rpl_str_t params[3];
xsltStylesheetPtr cur;
#endif

/**
   Configure the xslt module.

   @param fns pointer to module interface to be configured.
 */
void
00062 rpl_mod_xslt_configure(rpl_mod_fns *fns)
{
      fns->init = rpl_mod_xslt_init;
      fns->process = rpl_mod_xslt_process;
      fns->cleanup = rpl_mod_xslt_cleanup;
      rpl_xslt_base_dir = rpl_str_concat(rpl_cfg_get_ds_basedir(), "/", RPL_DS_PARSE_DIR, RPL_STR_EOC);
      fns->basedir = rpl_xslt_base_dir;
}

/**
   Parse the XSLT stylesheet.
 */
rpl_wk_status 
00075 rpl_mod_xslt_init()
{
      rpl_wk_status status = RPL_WK_OK;
      rpl_str_t msg;
#if SUPPORT_XSLT_PROC == 1
    int sablotronFlags;
      int rc;
#elif SUPPORT_XSLT_PROC == 2
      rpl_str_t catalog_loc;
#endif

      /* acquire the XSLT filename from the config */
      xsl_filename = rpl_cfg_get_trf_tpl_xslt();

      /* define output directory */
      out_dir = rpl_wk_get_webdir();

#if SUPPORT_XSLT_PROC == 1

      /* create and configure Sablot sitation */
    rc = SablotCreateSituation(&situation);
      if(rc != 0)
      {
            msg = rpl_message_get("XSLT_UNABLE_TO_CREATE_SIT", RPL_EOM);
            rpl_log_error(msg);
            rpl_me_free(msg);
            return RPL_WK_ERR;
      }
    sablotronFlags = SablotGetOptions (situation);
    sablotronFlags |= SAB_PARSE_PUBLIC_ENTITIES;
    SablotSetOptions (situation, sablotronFlags);

      /* parse and configure XSLT processor */
    if((rc = SablotCreateProcessorForSituation(situation,&proc)))
      {
            msg = rpl_message_get("XSLT_UNABLE_TO_CREATE_PROC", RPL_EOM);
            rpl_log_error(msg);
            rpl_me_free(msg);
            return RPL_WK_ERR;
      } else {
            host_param = rpl_wk_get_domain();
            SablotParseStylesheet(situation, xsl_filename, &preparsed);
      }

#elif SUPPORT_XSLT_PROC == 2

      /* attempt to locate catalog */
      catalog_loc = (rpl_cfg_get_trf_catalog()) ? rpl_cfg_get_trf_catalog() : getenv("XML_CATALOG_FILES");
      if(catalog_loc == NULL)
      {
            msg = rpl_message_get("XML_CATALOG_DEFAULT", RPL_EOM);
            rpl_log_warn(msg);
            rpl_me_free(msg);
      } else {
            xmlLoadCatalogs(catalog_loc);
      }

      xmlSubstituteEntitiesDefault(1);
      xmlLoadExtDtdDefaultValue = 1;      

      if((cur = xsltParseStylesheetFile((const xmlChar *)xsl_filename)) == NULL)
            rpl_log_fatal(rpl_message_get("XSLT_STYLESHEET_PARSE_FAILED", xsl_filename, RPL_EOM));

      host_param = rpl_str_concat("'", rpl_wk_get_domain(), "'", RPL_STR_EOC);
      params[0] = "host";
      params[1] = host_param;
      params[2] = NULL;

#endif

      return status; 
}

/**
   Performs xslt operations on web asset.

   @param filename name of file to be transformed relative to website base directory.
   @param st_buf stat of file.
 */
rpl_wk_status 
00155 rpl_mod_xslt_process(rpl_c_str_t filename, struct stat statbuf)
{
      rpl_str_t msg, rdp, fp, key, outfp;
      rpl_wk_status status = RPL_WK_OK;
#if SUPPORT_XSLT_PROC == 1
    SDOM_Document xml = NULL;
#elif SUPPORT_XSLT_PROC == 2
      xmlDocPtr doc, res;
      FILE *ofp;
#endif
      rpl_reg_item item;
      /* static for reasons stated below - not a very elegant solution :( */
      static int rc = 0;

    assert(filename != NULL);

      msg = rpl_str_concat(rpl_message_get("WK_PROCESSING", RPL_EOM), "xslt ", filename, RPL_STR_EOC);
      rpl_log_info(msg);
      rpl_me_free(msg);

      /* extract key information */
      if(rpl_fs_resolve_paths(filename, rpl_xslt_base_dir, &rdp, &fp))
            return RPL_WK_ERR;
      key = rpl_reg_create_key(rdp, fp);

      /* use relative path to resolve directories for errors and output */
      outfp = (rpl_str_t)rpl_me_malloc(strlen(out_dir) + strlen(rdp) + strlen(fp) + 2);
      sprintf(outfp, "%s/%s/%s", out_dir, rdp, fp);

      if(S_ISREG(statbuf.st_mode))
      {
            /* retrieve asset from registry */
            item = rpl_reg_search(key);
            if(item == &RPL_REG_WA_NULL)
            {
                  msg = rpl_message_get("REG_ASSET_NOT_FOUND", key, RPL_EOM);
                  rpl_log_error(msg);
                  rpl_me_free(msg);
                  status = RPL_WK_ERR;
            } else if(rpl_wa_is_transformable(*item)) {
                  /* either transform the asset or simply copy it */    
#if SUPPORT_XSLT_PROC == 1
                  /* yes the parameter really must be bound on each processing pass ;) */
                  /* if for some reason parsing fails (e.g., unknown entity etc.) then on
                     the next pass of the processor a "conflicting variable bindings" error
                     is thrown when the host parameter is added - rc therefore records the
                     last known return code of the processor and only adds if necessary */
                  if(rc == 0)
                  SablotAddParam(situation, proc, "host", host_param);
            /* perform transformation */
                  SablotAddArgBuffer(situation, proc, RPL_TRF_SABLOT_ARG_DATA, xml);
            SablotAddArgTree(situation, proc, RPL_TRF_SABLOT_XSLT, preparsed);

            rc = SablotRunProcessorGen(situation, proc, RPL_TRF_SABLOT_ARG_XSLT, filename, outfp); 
#elif SUPPORT_XSLT_PROC == 2
                  if((doc = xmlParseFile(filename)) == NULL)
                  {     
                        msg = rpl_message_get("XSLT_INPUT_PARSE_FAILED", filename, RPL_EOM);
                        rpl_log_error(msg);
                        rpl_me_free(msg);
                        status RPL_WK_ERR;
                  } else {
                        res = xsltApplyStylesheet(cur, doc, (const char **)params);
                        if(!res) {
                              rc = RPL_WK_ERR;
                        } else {
                              errno = 0;
                              if((ofp=fopen(outfp, "w")) == NULL)
                                    rpl_log_fatal(rpl_message_get("FS_OPEN_FAILED", filename, " (", strerror(errno), ")", RPL_EOM));
                              xsltSaveResultToFile(ofp, res, cur);
                              fclose(ofp);
                        }
                  }

                  xmlFreeDoc(doc);
                  xmlFreeDoc(res);
#endif
                  rpl_wa_set_tmpl_stat_desc(rpl_wa_get_trf_status_desc(((rc == 1) ? RPL_WA_TRF_ST_SUCCESS : RPL_WA_TRF_ST_FAILURE)), item);
                  rpl_reg_insert(item);
                  
            /* SablotDestroyDocument(situation, xml); */
            } else {
                  rpl_fs_cp(filename, outfp);
            }
      }

      /* free resources */
      if(strlen(rdp) > 0)
            rpl_me_free(rdp); 
      if(strlen(fp) > 0)
            rpl_me_free(fp); 
      if(strlen(key) > 0)
            rpl_me_free(key);
      rpl_me_free(outfp);

      return status; 
}

/**
   Release resources held during processing. 
 */
rpl_wk_status 
00257 rpl_mod_xslt_cleanup()
{
      rpl_wk_status status = RPL_WK_OK;

      /* release string resources */
      rpl_me_free(rpl_xslt_base_dir);
      rpl_me_free(host_param);
      /* do not free
      rpl_me_free(out_dir);
      */

#if SUPPORT_XSLT_PROC == 1
      /* release Sablotron structures */
    SablotDestroyProcessor(proc); 
    SablotDestroySituation(situation); 
    SablotDestroyDocument(situation, preparsed); 
#elif SUPPORT_XSLT_PROC == 2
      xsltFreeStylesheet(cur);
      xsltCleanupGlobals();
      xmlCleanupParser();
#endif

      return status;
}


Generated by  Doxygen 1.6.0   Back to index