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

cfgfile.c

/* cfgfile.c
 * Part of ziproxy package.
 * 
 * Copyright (c)2003-2004 Juraj Variny<variny@naex.sk>
 * Copyright (c)2005-2009 Daniel Mealha Cabrita
 *
 * Released subject to GNU General Public License v2 or later version.
 * 
 * Configuration file parsing functions.
 */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/nameser.h>
#include <arpa/inet.h>
#include <resolv.h>

#include "qparser.h"
#include "image.h"
#include "jp2tools.h"
#include "cfgfile.h"
#include "urltables.h"
#include "simplelist.h"

t_qp_bool MSIETest, DoGzip, UseContentLength, AllowLookCh, ProcessJPG, ProcessPNG, ProcessGIF, PreemptNameRes, PreemptNameResBC, TransparentProxy, ConventionalProxy, ProcessHTML, ProcessCSS, ProcessJS, ProcessHTML_CSS, ProcessHTML_JS, ProcessHTML_tags, ProcessHTML_text, ProcessHTML_PRE, ProcessHTML_NoComments, ProcessHTML_TEXTAREA, AllowMethodCONNECT, OverrideAcceptEncoding, DecompressIncomingGzipData, WA_MSIE_FriendlyErrMsgs, AccessLogUserPOV, InterceptCrashes;

int Port, NextPort, NetdTimeout, ZTimeout, MaxSize, PreemptNameResMax, MaxUncompressedGzipRatio, MinUncompressedGzipStreamEval, MaxUncompressedImageRatio;
int ImageQuality[4];
int JP2ImageQuality[4];
int RestrictOutPortHTTP [MAX_RESTRICTOUTPORTHTTP_LEN];
int RestrictOutPortCONNECT [MAX_RESTRICTOUTPORTCONNECT_LEN];
int RestrictOutPortHTTP_len;
int RestrictOutPortCONNECT_len;
char *WhereZiproxy, *ServHost, *OnlyFrom, *LogFileName, *NextProxy, *ServUrl;
char **LogPipe, **Compressible;
char *CustomError400, *CustomError403, *CustomError404, *CustomError407, *CustomError408, *CustomError409, *CustomError500, *CustomError503;
char *Address;
char *AccessLogFileName;
char *PasswdFile;
char *RedefineUserAgent;
char *URLNoProcessing;
char *URLReplaceData;
char *URLReplaceDataCT;
char *URLDeny;
char *tmpBindOutgoingExList;
char *tmpBindOutgoingExAddr;
t_st_strtable *BindOutgoingExList;
in_addr_t *BindOutgoingExAddr;
in_addr_t *BindOutgoing;
int BindOutgoing_entries;

#ifdef JP2K
t_qp_bool ProcessJP2, ForceOutputNoJP2, ProcessToJP2, AnnounceJP2Capability, JP2OutRequiresExpCap;
int JP2Colorspace_cfg;
t_color_space JP2Colorspace;  // 0=RGB 1=YUV
int JP2Upsampler_cfg;
t_upsampler JP2Upsampler;     // upsampler method: 0-linear, 1-lanczos
int JP2BitResYA[8];     // 4x qualities 2 components: YA YA YA YA
int JP2BitResRGBA[16];  // 4x qualities 4 components: RGBA RGBA RGBA RGBA
int JP2BitResYUVA[16];  // 4x qualities 4 components: YUVA YUVA YUVA YUVA
int JP2CSamplingYA[32]; // 4x qualities 2 components 4 settings: YxYyYwYh AxAyAwAh YxYyYwYh AxAyAwAh YxYyYwYh AxAyAwAh YxYyYwYh AxAyAwAh
int JP2CSamplingRGBA[64];     // 4x qualities 4 components 4 settings: RxRyRwRh GxGyGwGh BxByBwBh AxAyAwAh ... (4 times)
int JP2CSamplingYUVA[64];     // 4x qualities 4 components 4 settings: YxYyYwYh UxUyUwUh VxVyVwVh AxAyAwAh ... (4 times)
#endif

#ifndef DefaultCfgLocation
char DefaultCfgLocation[] = "/etc/ziproxy/ziproxy.conf";
#endif

int LoadParmMatrix(int *destarray, t_qp_configfile *conf_handler, const char *conf_key, const int *dvalues, const int min_entries, const int max_entries, const int min_value, const int max_value);
const t_st_strtable *LoadParmMatrixStr(t_qp_configfile *conf_handler, const char *conf_key, const char **dvalues, int dvalues_len, const int min_entries, const int max_entries);
const t_ut_urltable *load_URLtable (const char *urltable_filename);
int check_int_ranges (const char *conf_key, const int inval, const int vlow, const int vhigh);

const t_ut_urltable *urltable_noprocessing;
const t_ut_urltable *urltable_replacedata;
const t_ut_urltable *urltable_replacedatact;
const t_st_strtable *urltable_replacedatactlist;
const t_ut_urltable *urltable_deny;
const t_st_strtable *passwd_table;

/* dump parsing errors (if any) to stderr
 * returns: ==0: no errors, !=0 errors */
int dump_errors (t_qp_configfile *conf_handler)
{
      int counter = 0;
      const char *conf_key;
      t_qp_error error_code;
      int has_errors = 0;
      int display_conf_key = 1;
      
      while (qp_get_error (conf_handler, counter++, &conf_key, &error_code)) {
            fprintf (stderr, "ERROR: ");
            switch (error_code) {
            case QP_ERROR_SYNTAX:
                  fprintf (stderr, "Incorrect syntax of parameter");
                  break;
            case QP_ERROR_MISSING_CONFKEY:
                  fprintf (stderr, "Required parameter missing");
                  break;
            case QP_ERROR_INVALID_PARM:
                  fprintf (stderr, "Invalid parameter");
                  break;
            case QP_ERROR_DUPLICATED:
                  fprintf (stderr, "Parameter defined twice or more");
                  break;
            case QP_ERROR_MORE_ERRORS:
                  fprintf (stderr, "More errors present, but not displayed.");
                  display_conf_key = 0;
                  break;
            default:
                  fprintf (stderr, "Parser bug.\n");
                  display_conf_key = 0;
            }
            if (display_conf_key)
                  fprintf (stderr, " --> %s\n", conf_key);
            else
                  fprintf (stderr, "\n");

            has_errors = 1;
      }

      return (has_errors);
}

int ReadCfgFile(char * cfg_file)
{
      t_qp_configfile *conf_handler;
      int i, n;
#ifdef JP2K
      const int DefaultJP2ImageQuality[] = { 30, 25, 25, 20 };
      const int DefaultJP2BitResYA[] = { 6, 4, 7, 5, 8, 6, 8, 6 };
      const int DefaultJP2BitResRGBA[] = { 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8 };
      const int DefaultJP2BitResYUVA[] = { 6, 5, 5, 4, 7, 6, 6, 5, 8, 7, 7, 6, 8, 8, 8, 6 };
      const int DefaultJP2CSamplingYA[] = {     0, 0, 1, 1,  0, 0, 1, 1, \
                                    0, 0, 1, 1,  0, 0, 1, 1, \
                                    0, 0, 1, 1,  0, 0, 2, 2, \
                                    0, 0, 1, 1,  0, 0, 2, 2 };
      const int DefaultJP2CSamplingRGBA[] = {   0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1, \
                                    0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1, \
                                    0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1, \
                                    0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1 };
      const int DefaultJP2CSamplingYUVA[] = {   0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1,  0, 0, 1, 1, \
                                    0, 0, 1, 1,  0, 0, 1, 2,  0, 0, 2, 1,  0, 0, 1, 1, \
                                    0, 0, 1, 1,  0, 0, 2, 2,  0, 0, 2, 1,  0, 0, 2, 2, \
                                    0, 0, 1, 1,  0, 0, 2, 2,  0, 0, 2, 2,  0, 0, 2, 2 };

      
#endif
      const int DefaultImageQuality[] = { 30, 25, 25, 20 };
      
      Port = NextPort = 8080;
      NetdTimeout = 0;
      ZTimeout = 90;
      MaxSize = 1048576;
      PreemptNameResMax = 50;
      MaxUncompressedGzipRatio = 2000;
      MinUncompressedGzipStreamEval = 250000;
      MaxUncompressedImageRatio = 500;
      MSIETest = PreemptNameRes = QP_FALSE;
      DoGzip = UseContentLength = ProcessJPG = ProcessPNG = ProcessGIF = QP_TRUE;
      ProcessHTML = ProcessCSS = ProcessJS = QP_FALSE;
      WA_MSIE_FriendlyErrMsgs = QP_TRUE;
      AccessLogUserPOV = QP_FALSE;
      ProcessHTML_CSS = ProcessHTML_JS = ProcessHTML_tags = ProcessHTML_text = ProcessHTML_PRE = ProcessHTML_NoComments = ProcessHTML_TEXTAREA = QP_TRUE;
      AllowLookCh = PreemptNameResBC = TransparentProxy = QP_FALSE;
      ConventionalProxy = QP_TRUE;
      WhereZiproxy = ServHost = ServUrl = OnlyFrom = LogFileName = NextProxy = NULL;
      LogPipe = Compressible = NULL;
      CustomError400 = CustomError403 = CustomError404 = CustomError407 = CustomError408 = CustomError409 = CustomError500 = CustomError503 = NULL;
      Address = NULL;
      AccessLogFileName = NULL;
      PasswdFile = NULL;
      AllowMethodCONNECT = QP_TRUE;
      OverrideAcceptEncoding = QP_TRUE;
      RedefineUserAgent = NULL;
      DecompressIncomingGzipData = QP_TRUE;
      BindOutgoing = NULL;
      BindOutgoing_entries = 0;
      tmpBindOutgoingExAddr = NULL;
      tmpBindOutgoingExList = NULL;
      BindOutgoingExAddr = NULL;
      BindOutgoingExList = NULL;
      URLNoProcessing = NULL;
      URLReplaceData = NULL;
      URLReplaceDataCT = NULL;
      URLDeny = NULL;
      urltable_noprocessing = NULL;
      urltable_replacedata = NULL;
      urltable_replacedatact = NULL;
      urltable_replacedatactlist = NULL;
      passwd_table = NULL;
      InterceptCrashes = QP_FALSE;
#ifdef JP2K
      ProcessJP2 = QP_FALSE;
      ForceOutputNoJP2 = QP_FALSE;
      ProcessToJP2 = QP_FALSE;
      AnnounceJP2Capability = QP_FALSE;
      JP2OutRequiresExpCap = QP_FALSE;
      JP2Colorspace_cfg = 1;  // defaults to YUV
      JP2Upsampler = 0; // defaults to linear
#endif

      if ((conf_handler = qp_init (cfg_file, QP_INITFLAG_IGNORECASE)) == NULL) {
            fprintf (stderr, "Unable to open config file '%s'\n", cfg_file);
            return (1);
      }

      qp_getconf_str (conf_handler, "WhereZiproxy", &WhereZiproxy, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "ViaServer", &ServHost, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "ServerUrl", &ServUrl, QP_FLAG_NONE);
        qp_getconf_int (conf_handler, "Port", &Port, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "OnlyFrom", &OnlyFrom, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "LogFile", &LogFileName, QP_FLAG_NONE);
      qp_getconf_array_str (conf_handler, "LogPipe", 0, NULL, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "NextProxy", &NextProxy, QP_FLAG_NONE);
      qp_getconf_int (conf_handler, "NextPort", &NextPort, QP_FLAG_NONE);
      qp_getconf_int (conf_handler, "NetdTimeout", &NetdTimeout, QP_FLAG_NONE);
      qp_getconf_int (conf_handler, "ZiproxyTimeout", &ZTimeout, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "MSIETest", &MSIETest, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "Gzip", &DoGzip, QP_FLAG_NONE);
      qp_getconf_array_str (conf_handler, "Compressible", 0, NULL, QP_FLAG_NONE);
      qp_getconf_int (conf_handler, "MaxSize", &MaxSize, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "UseContentLength", &UseContentLength, QP_FLAG_NONE);
      qp_getconf_array_int (conf_handler, "ImageQuality", 0, NULL, QP_FLAG_NONE);
      qp_getconf_array_int (conf_handler, "JP2ImageQuality", 0, NULL, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "AllowLookChange", &AllowLookCh, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessJPG", &ProcessJPG, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessPNG", &ProcessPNG, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessGIF", &ProcessGIF, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "PreemptNameRes", &PreemptNameRes, QP_FLAG_NONE);
      qp_getconf_int (conf_handler, "PreemptNameResMax", &PreemptNameResMax, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "PreemptNameResBC", &PreemptNameResBC, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "TransparentProxy", &TransparentProxy, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ConventionalProxy", &ConventionalProxy, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "CustomError400", &CustomError400, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "CustomError403", &CustomError403, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "CustomError404", &CustomError404, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "CustomError407", &CustomError407, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "CustomError408", &CustomError408, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "CustomError409", &CustomError409, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "CustomError500", &CustomError500, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "CustomError503", &CustomError503, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "Address", &Address, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "AccessLogFileName", &AccessLogFileName, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "PasswdFile", &PasswdFile, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessHTML", &ProcessHTML, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessCSS", &ProcessCSS, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessJS", &ProcessJS, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessHTML_CSS", &ProcessHTML_CSS, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessHTML_JS", &ProcessHTML_JS, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessHTML_tags", &ProcessHTML_tags, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessHTML_text", &ProcessHTML_text, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessHTML_PRE", &ProcessHTML_PRE, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessHTML_NoComments", &ProcessHTML_NoComments, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessHTML_TEXTAREA", &ProcessHTML_TEXTAREA, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "AllowMethodCONNECT", &AllowMethodCONNECT, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "OverrideAcceptEncoding", &OverrideAcceptEncoding, QP_FLAG_NONE);
      qp_getconf_int (conf_handler, "MaxUncompressedGzipRatio", &MaxUncompressedGzipRatio, QP_FLAG_NONE);
      qp_getconf_int (conf_handler, "MaxUncompressedImageRatio", &MaxUncompressedImageRatio, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "RedefineUserAgent", &RedefineUserAgent, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "DecompressIncomingGzipData", &DecompressIncomingGzipData, QP_FLAG_NONE);
      qp_getconf_array_str (conf_handler, "Nameservers", 0, NULL, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "WA_MSIE_FriendlyErrMsgs", &WA_MSIE_FriendlyErrMsgs, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "InterceptCrashes", &InterceptCrashes, QP_FLAG_NONE);
      qp_getconf_int (conf_handler, "MinUncompressedGzipStreamEval", &MinUncompressedGzipStreamEval, QP_FLAG_NONE);
      qp_getconf_array_str (conf_handler, "BindOutgoing", 0, NULL, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "BindOutgoingExAddr", &tmpBindOutgoingExAddr, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "BindOutgoingExList", &tmpBindOutgoingExList, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "AccessLogUserPOV", &AccessLogUserPOV, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "URLNoProcessing", &URLNoProcessing, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "URLReplaceData", &URLReplaceData, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "URLReplaceDataCT", &URLReplaceDataCT, QP_FLAG_NONE);
      qp_getconf_array_str (conf_handler, "URLReplaceDataCTList", 0, NULL, QP_FLAG_NONE);
      qp_getconf_str (conf_handler, "URLDeny", &URLDeny, QP_FLAG_NONE);
      qp_getconf_array_int (conf_handler, "RestrictOutPortHTTP", 0, NULL, QP_FLAG_NONE);
      qp_getconf_array_int (conf_handler, "RestrictOutPortCONNECT", 0, NULL, QP_FLAG_NONE);
#ifdef JP2K
      qp_getconf_bool (conf_handler, "ProcessJP2", &ProcessJP2, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ForceOutputNoJP2", &ForceOutputNoJP2, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "ProcessToJP2", &ProcessToJP2, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "AnnounceJP2Capability", &AnnounceJP2Capability, QP_FLAG_NONE);
      qp_getconf_bool (conf_handler, "JP2OutRequiresExpCap", &JP2OutRequiresExpCap, QP_FLAG_NONE);
      qp_getconf_int (conf_handler, "JP2Colorspace", &JP2Colorspace_cfg, QP_FLAG_NONE);
      qp_getconf_int (conf_handler, "JP2Upsampler", &JP2Upsampler_cfg, QP_FLAG_NONE);
      qp_getconf_array_int (conf_handler, "JP2BitResYA", 0, NULL, QP_FLAG_NONE);
      qp_getconf_array_int (conf_handler, "JP2BitResRGBA", 0, NULL, QP_FLAG_NONE);
      qp_getconf_array_int (conf_handler, "JP2BitResYUVA", 0, NULL, QP_FLAG_NONE);
      qp_getconf_array_int (conf_handler, "JP2CSamplingYA", 0, NULL, QP_FLAG_NONE);
      qp_getconf_array_int (conf_handler, "JP2CSamplingRGBA", 0, NULL, QP_FLAG_NONE);
      qp_getconf_array_int (conf_handler, "JP2CSamplingYUVA", 0, NULL, QP_FLAG_NONE);
#endif

      qp_fail_unrecognized_conf (conf_handler);
      if (dump_errors (conf_handler))
            return (1);

      if (URLNoProcessing != NULL) {
            if ((urltable_noprocessing = load_URLtable (URLNoProcessing)) == NULL)
                  return (1);
      }

      if (URLReplaceData != NULL) {
            if ((urltable_replacedata = load_URLtable (URLReplaceData)) == NULL)
                  return (1);
      }

      if (URLReplaceDataCT != NULL) {
            if (qp_get_array_size (conf_handler, "URLReplaceDataCTList") <= 0) {
                  fprintf(stderr, "Configuration error: URLReplaceDataCT requires non-empty URLReplaceDataCTList.\n");
                  return (1);
            }
            if ((urltable_replacedatact = load_URLtable (URLReplaceDataCT)) == NULL)
                  return (1);

            urltable_replacedatactlist = LoadParmMatrixStr(conf_handler, "URLReplaceDataCTList", NULL, 0, 1, -1);
            if (urltable_replacedatactlist == NULL)
                  return (1);
      }

      if (URLDeny != NULL) {
            if ((urltable_deny = load_URLtable (URLDeny)) == NULL)
                  return (1);
      }

      if (PasswdFile != NULL) {
            // FIXME: this table is not manually deallocated later, thus it is not zero'ed
            // when ziproxy daemon/process finishes. That's a security vulnerability.
            if ((passwd_table = auth_create_populate_from_file (PasswdFile)) == NULL)
                  return (1);
      }

      n = qp_get_array_size (conf_handler, "BindOutgoing");
      if(n){
            char *ip_str;
            
            BindOutgoing_entries = n;
            BindOutgoing = calloc (n, sizeof (in_addr_t));
            while (n--) { 
                  qp_getconf_array_str (conf_handler, "BindOutgoing", n, &ip_str, QP_FLAG_NONE);
                  BindOutgoing [n] = inet_addr (ip_str);
                  free (ip_str);
            }
      }

      if (tmpBindOutgoingExList != NULL) {
            if ((BindOutgoingExList = slist_create (tmpBindOutgoingExList)) == NULL) {
                  fprintf(stderr, "Configuration error: Problem while processing BindOutgoingExList\n");
                  return (1);
            }
      }

      if (tmpBindOutgoingExAddr != NULL) {
            BindOutgoingExAddr = calloc (1, sizeof (in_addr_t));
            *BindOutgoingExAddr = inet_addr (tmpBindOutgoingExAddr);
      } else {
            if (BindOutgoing_entries > 0) {
                  BindOutgoingExAddr = &(BindOutgoing [0]);
            }
      }
      
      n = qp_get_array_size (conf_handler, "LogPipe");
      if(n){
            LogPipe = malloc((n + 1)*sizeof(char*));
            for(i = 0; i < n; i++)
                  qp_getconf_array_str (conf_handler, "LogPipe", i, &LogPipe[i], QP_FLAG_NONE);
                  
            LogPipe[i] = NULL;
      }
            
      n = qp_get_array_size (conf_handler, "Compressible");
      if(n){
            Compressible = malloc((n + 1)*sizeof(char*));
            for(i = 0; i < n; i++)
                  qp_getconf_array_str (conf_handler, "Compressible", i, &Compressible[i], QP_FLAG_NONE);
                  
            Compressible[i] = NULL;
      }

      RestrictOutPortHTTP_len = LoadParmMatrix (RestrictOutPortHTTP, conf_handler, "RestrictOutPortHTTP", NULL, 1, MAX_RESTRICTOUTPORTHTTP_LEN, 1, 65535);
      if (RestrictOutPortHTTP_len < 0)
            return (1);

      RestrictOutPortCONNECT_len = LoadParmMatrix (RestrictOutPortCONNECT, conf_handler, "RestrictOutPortCONNECT", NULL, 1, MAX_RESTRICTOUTPORTCONNECT_LEN, 1, 65535);
      if (RestrictOutPortCONNECT_len < 0)
            return (1);

      if (LoadParmMatrix(ImageQuality, conf_handler, "ImageQuality", DefaultImageQuality, 4, 4, -100, 100) < 0)
                  return (1);
            
      n = qp_get_array_size (conf_handler, "Nameservers");
      if (n) {
            struct sockaddr_in nsaddr;

            if (n > MAXNS)
                  fprintf(stderr, "Configuration error: "
                              "You can not specify more than %d Nameservers. "
                              "Using nameserver 1-%d.\n", MAXNS, MAXNS);

            nsaddr.sin_family = AF_INET;
            nsaddr.sin_port = htons(53);

            res_init();
            _res.nscount = 0;

            for (i = 0; i < n && i < MAXNS; i++) {
                  char *nserver_str;
                  
                  qp_getconf_array_str (conf_handler, "Nameservers", i, &nserver_str, QP_FLAG_NONE);
                  inet_aton(nserver_str, &nsaddr.sin_addr);
                  _res.nsaddr_list[_res.nscount++] = nsaddr;
            }
      }

      if (check_int_ranges ("MaxUncompressedImageRatio", MaxUncompressedImageRatio, 0, 100000))
            return (1);

#ifdef JP2K
      switch (JP2Colorspace_cfg) {
            case 1:
                  JP2Colorspace = CENC_YUV;
                  break;
            case 0:
                  JP2Colorspace = CENC_RGB;
                  break;
            default:
                  fprintf(stderr,"Configuration error: Invalid JP2Colorspace value: %d\n", JP2Colorspace_cfg);
                  return (1);
                  break;
      }

      switch (JP2Upsampler_cfg) {
            case 0:
                  JP2Upsampler = UPS_LINEAR;
                  break;
            case 1:
                  JP2Upsampler = UPS_LANCZOS;
                  break;
            default:
                  fprintf(stderr,"Configuration error: Invalid JP2Upsampler value: %d\n", JP2Upsampler_cfg);
                  break;
      }

      if (LoadParmMatrix(JP2ImageQuality, conf_handler, "JP2ImageQuality", DefaultJP2ImageQuality, 4, 4, 1, 100) < 0)
            return (1);
      
      if (LoadParmMatrix(JP2BitResYA, conf_handler, "JP2BitResYA", DefaultJP2BitResYA, 8, 8, 1, 8) < 0)
            return (1);
      
      if (LoadParmMatrix(JP2BitResRGBA, conf_handler, "JP2BitResRGBA", DefaultJP2BitResRGBA, 16, 16, 1, 8) < 0)
            return (1);

      if (LoadParmMatrix(JP2BitResYUVA, conf_handler, "JP2BitResYUVA", DefaultJP2BitResYUVA, 16, 16, 1, 8) < 0)
            return (1);

      if (LoadParmMatrix(JP2CSamplingYA, conf_handler, "JP2CSamplingYA", DefaultJP2CSamplingYA, 32, 32, 0, 256) < 0)
            return (1);

      if (LoadParmMatrix(JP2CSamplingRGBA, conf_handler, "JP2CSamplingRGBA", DefaultJP2CSamplingRGBA, 64, 64, 0, 256) < 0)
            return (1);

      if (LoadParmMatrix(JP2CSamplingYUVA, conf_handler, "JP2CSamplingYUVA", DefaultJP2CSamplingYUVA, 64, 64, 0, 256) < 0)
            return (1);
#endif
      
      qp_end (conf_handler);
      return (0);
}

/* create strtable from parameters
 * dvalues = array of strings with default values (if any)
 * dvalues_len = size of dvalues (in elements)
 * returns: <pointer to t_st_strtable structure>, or NULL (fail) -- array length may be collected using strtable functions */
const t_st_strtable *LoadParmMatrixStr(t_qp_configfile *conf_handler, const char *conf_key, const char **dvalues, int dvalues_len, const int min_entries, const int max_entries)
{
      int entries;
      int position;
      char *indata;
      t_st_strtable *outdata;

      if ((outdata = st_create ()) == NULL)
            return (NULL);

      entries = qp_get_array_size (conf_handler, conf_key);

      // checks whether array is defined or not (an empty array will be considered 'undefined')
      // fill with default values if undefined
      if (entries == 0) {
            if (dvalues != NULL) {
                  for (position = 0; position < dvalues_len; position++)
                        st_insert (outdata, dvalues [position]);
                  return (outdata);
            } else {
                  st_destroy (outdata);
                  return (NULL);
            }
      }
      
      if (((entries > max_entries) && (max_entries >= 0)) || ((entries < min_entries) && (min_entries >= 0))) {
            fprintf (stderr, "Configuration error: invalid number of entries in %s\n", conf_key);
            if (min_entries == max_entries)
                  fprintf (stderr, "The number of entries must be exactly: %d\n", min_entries);
            else
                  fprintf (stderr, "The number of entries must be between: %d - %d\n", min_entries, max_entries);
            st_destroy (outdata);
            return (NULL);
      }
      
      for (position = 0; position < entries; position++) {
            qp_getconf_array_str (conf_handler, conf_key, position, &indata, QP_FLAG_NONE);
            st_insert (outdata, indata);
      }

      return (outdata);
}

/* load url table from file
 * returns: <pointer to t_ut_urltable structure>, or NULL (table not loaded) */
const t_ut_urltable *load_URLtable (const char *urltable_filename)
{
      t_ut_urltable *urltable;
      
      if ((urltable = ut_create_populate_from_file (urltable_filename)) == NULL) {
            fprintf (stderr, "Configuration error: Unable to load %s\n", urltable_filename);
            return (NULL);
      }

      return (urltable);
}

/* get position in quality tables according to the image size */
int getImgSizeCategory (int width, int height)
{
      int imgcat;
      long i = width * height;
      
      if (i < 5000)
            imgcat = 0;
      else if ((i < 50000)|| (width < 150) || (height < 150))
            imgcat = 1;
      else if (i < 250000)
            imgcat = 2;
      else imgcat = 3;

      return (imgcat);
}

#ifdef JP2K

/* return a pointer to a array[4] with the bit lenght for JP2K YA components */
const int *getJP2KBitLenYA (int width, int height)
{
      int imgcat;

      imgcat = getImgSizeCategory (width, height);

      return (JP2BitResYA + (2 * imgcat));
}

/* return a pointer to a array[4] with the bit lenght for JP2K RGBA components */
const int *getJP2KBitLenRGBA (int width, int height)
{
      int imgcat;

      imgcat = getImgSizeCategory (width, height);

      return (JP2BitResRGBA + (4 * imgcat));
}

/* return a pointer to a array[4] with the bit lenght for JP2K YUVA components */
const int *getJP2KBitLenYUVA (int width, int height)
{
      int imgcat;

      imgcat = getImgSizeCategory (width, height);

      return (JP2BitResYUVA + (4 * imgcat));
}

/* return a pointer to a array[8] with the components' sampling parameters JP2K YA components */
const int *getJP2KCSamplingYA (int width, int height)
{
      int imgcat;

      imgcat = getImgSizeCategory (width, height);

      return (JP2CSamplingYA + (8 * imgcat));
}

/* return a pointer to a array[16] with the components' sampling parameters JP2K RGBA components */
const int *getJP2KCSamplingRGBA (int width, int height)
{
      int imgcat;

      imgcat = getImgSizeCategory (width, height);

      return (JP2CSamplingRGBA + (16 * imgcat));
}

/* return a pointer to a array[16] with the components' sampling parameters JP2K YUVA components */
const int *getJP2KCSamplingYUVA (int width, int height)
{
      int imgcat;

      imgcat = getImgSizeCategory (width, height);

      return (JP2CSamplingYUVA + (16 * imgcat));
}

/*
 * Fills in the values of JP2ImageQuality according to image dimensions. 
 * Returns index used to get the values ranging from 0 (smallest images)
 * to 3 (largest images).
 */
int getJP2ImageQuality (int width, int height)
{
      int imgcat;
      
      imgcat = getImgSizeCategory (width, height);
      return (JP2ImageQuality [imgcat]);
}

#endif

/*
 * Fills in the values of ImageQuality according to image dimensions. 
 * Returns index used to get the values ranging from 0 (smallest images)
 * to 3 (largest images).
 */
int getImageQuality (int width, int height)
{
      int imgcat;
      
      imgcat = getImgSizeCategory (width, height);
      return (ImageQuality [imgcat]);
}

/* returns:
 * lenght of array OR
 * < 0 if error */
int LoadParmMatrix(int *destarray, t_qp_configfile *conf_handler, const char *conf_key, const int *dvalues, const int min_entries, const int max_entries, const int min_value, const int max_value)
{
      int entries;
      int position;
      int indata;

      entries = qp_get_array_size (conf_handler, conf_key);

      // checks whether array is defined or not (an empty array will be considered 'undefined')
      // if no data available, use internal default values instead.
      if (entries == 0) {
            if (dvalues != NULL) {
                  for (position = 0; position < max_entries; position++)
                        destarray [position] = dvalues [position];
                  return (max_entries);
            } else {
                  return (0);
            }
      }

      if ((entries > max_entries) || (entries < min_entries)) {
            fprintf (stderr, "Configuration error: invalid number of entries in %s\n", conf_key);
            if (min_entries == max_entries)
                  fprintf (stderr, "The number of entries must be exactly: %d\n", min_entries);
            else
                  fprintf (stderr, "The number of entries must be between: %d - %d\n", min_entries, max_entries);
            return (-1);
      }
      
      for (position = 0; position < entries; position++) {
            qp_getconf_array_int (conf_handler, conf_key, position, &indata, QP_FLAG_NONE);
            if ((indata < min_value) || (indata > max_value)) {
                  fprintf (stderr, "Configuration error: out of range values in %s\n", conf_key);
                  return (-1);
            }
            destarray [position] = indata;
      }

      return (entries);
}

int check_int_ranges (const char *conf_key, const int inval, const int vlow, const int vhigh)
{
      if ((inval < vlow) || (inval > vhigh)) {
            fprintf (stderr, "Configuration error: out of range value for %s (Acceptable: %d to %d)\n", conf_key, vlow, vhigh);
            return (1);
      }
      return (0);
}


Generated by  Doxygen 1.6.0   Back to index