/*
* Copyright (c) 2004-2005, Doug Harple. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are
* met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* 3. Neither the name of author nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $Id: detox.c,v 1.22 2005/03/05 01:54:56 purgedhalo Exp $
*
*/
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "detox.h"
#include "file.h"
#include "config.h"
#include "clean_string.h"
#include "detox_path.h"
#include "config_file.h"
#include "parse_table.h"
#ifndef HAVE_LIBPOPT
#include "parse_options_getopt.h"
#else
#include "parse_options_popt.h"
#endif
int main(int argc, char **argv)
{
struct stat stat_info;
int err;
struct detox_sequence_list *sequences = NULL;
struct detox_sequence_list *list_work = NULL;
struct detox_sequence *which_sequence = NULL;
struct detox_sequence *work = NULL;
char *check_config_file = NULL;
struct detox_options *main_options;
char **file_walk;
#ifndef HAVE_LIBPOPT
main_options = parse_options_getopt(argc, argv);
#else
main_options = parse_options_popt(argc, argv);
#endif
if (main_options == NULL) {
return -1;
}
if (main_options->check_config_file) {
check_config_file = strdup(main_options->check_config_file);
}
if (check_config_file != NULL) {
sequences = parse_config_file(check_config_file, NULL, main_options);
if (sequences == NULL) {
fprintf(stderr, "detox: unable to open: %s\n", check_config_file);
exit(-1);
}
}
else {
check_config_file = malloc(256);
snprintf(check_config_file, 256, "%s/detoxrc", default_etc_dir);
sequences = parse_config_file(check_config_file, NULL, main_options);
if (sequences == NULL) {
sequences = parse_config_file("/etc/detoxrc", NULL, main_options);
}
if (sequences == NULL) {
sequences = parse_config_file("/usr/local/etc/detoxrc", NULL, main_options);
}
snprintf(check_config_file, 256, "%s/.detoxrc", getenv("HOME"));
sequences = parse_config_file(check_config_file, sequences, main_options);
if (sequences == NULL) {
/*
* Head
*/
sequences = malloc(sizeof(struct detox_sequence_list));
memset(sequences, 0, sizeof(struct detox_sequence_list));
sequences->name = strdup("default");
sequences->source_filename = strdup("inside the beast");
/*
* Step 1 - ISO8859_1
*/
sequences->head = malloc(sizeof(struct detox_sequence));
work = sequences->head;
memset(work, 0, sizeof(struct detox_sequence));
work->cleaner = &clean_iso8859_1;
/*
* Step 2 - Safe
*/
work->next = malloc(sizeof(struct detox_sequence));
work = work->next;
memset(work, 0, sizeof(struct detox_sequence));
work->cleaner = &clean_safe;
/*
* Step 3 - Wipe Up
*/
work->next = malloc(sizeof(struct detox_sequence));
work = work->next;
memset(work, 0, sizeof(struct detox_sequence));
work->cleaner = &clean_wipeup;
/*
* Deprecated
*/
if (main_options->remove_trailing) {
static struct clean_string_options *csopts;
csopts = malloc(sizeof(struct clean_string_options));
memset(csopts, 0, sizeof(struct clean_string_options));
csopts->remove_trailing = 1;
work->options = csopts;
}
}
free(check_config_file);
}
/*
* Determine which sequence to use
*/
which_sequence = NULL;
list_work = sequences;
while (list_work != NULL) {
if (strcmp(list_work->name, (main_options->sequence_name == NULL) ? "default" : main_options->sequence_name) == 0) {
which_sequence = list_work->head;
break;
}
list_work = list_work->next;
}
/*
* If no sequence was found, and the user didn't specify a sequence
* to use, just use the first sequence.
*/
if (which_sequence == NULL && main_options->sequence_name == NULL) {
if (sequences != NULL) {
which_sequence = sequences->head;
}
}
main_options->sequence = which_sequence;
/*
* List sequences
*/
if (main_options->list_sequences) {
if (!main_options->verbose) {
printf("available sequences:\n");
}
list_work = sequences;
while (list_work != NULL) {
if (main_options->verbose) {
printf("sequence name: ");
}
else {
printf("\t");
}
printf("%s%s\n", list_work->name, (main_options->sequence == list_work->head) ? " (*)" : "");
if (main_options->verbose) {
printf("\tsource file: %s\n", list_work->source_filename);
work = list_work->head;
while (work != NULL) {
if (work->cleaner == &clean_uncgi) {
printf("\tcleaner: uncgi\n");
}
else if (work->cleaner == &clean_safe) {
printf("\tcleaner: safe\n");
}
else if (work->cleaner == &clean_wipeup) {
printf("\tcleaner: wipeup\n");
if (work->options != NULL) {
struct clean_string_options *opts = work->options;
printf("\t\tremove trailing: %s\n", opts->remove_trailing ? "yes" : "no");
}
}
else if (work->cleaner == &clean_iso8859_1) {
printf("\tcleaner: iso8859_1\n");
if (work->options != NULL) {
struct clean_string_options *opts = work->options;
if (opts->filename != NULL) {
printf("\t\ttranslation table: %s\n", opts->filename);
}
}
}
else if (work->cleaner == &clean_utf_8) {
printf("\tcleaner: utf_8\n");
if (work->options != NULL) {
struct clean_string_options *opts = work->options;
if (opts->filename != NULL) {
printf("\t\ttranslation table: %s\n", opts->filename);
}
}
}
else if (work->cleaner == &clean_max_length) {
printf("\tcleaner: max length\n");
if (work->options != NULL) {
struct clean_string_options *opts = work->options;
printf("\t\tlength: %d\n", opts->max_length);
}
}
if (work->cleaner == &clean_lower) {
printf("\tcleaner: lower\n");
}
work = work->next;
}
}
list_work = list_work->next;
}
exit(0);
}
/*
* Fail if no sequence is available
*/
if (main_options->sequence == NULL) {
/*
* XXX - Explain this better
*/
fprintf(stderr, "detox: no sequence to work with\n");
exit(-1);
}
/*
* Check translation tables
*/
work = main_options->sequence;
while (work != NULL) {
char *check_filename = NULL;
int do_search = 0;
struct translation_table *table = NULL;
struct clean_string_options *opts;
if (work->cleaner == &clean_iso8859_1) {
if (work->options != NULL) {
opts = work->options;
if (opts->filename != NULL) {
check_filename = opts->filename;
}
}
if (!check_filename) {
check_filename = "iso8859_1.tbl";
do_search = 1;
}
}
else if (work->cleaner == &clean_utf_8) {
if (work->options != NULL) {
opts = work->options;
if (opts->filename != NULL) {
check_filename = opts->filename;
}
}
if (!check_filename) {
check_filename = "unicode.tbl";
do_search = 1;
}
}
if (check_filename || do_search) {
table = NULL;
if (do_search) {
check_config_file = malloc(256);
snprintf(check_config_file, 256, "%s/%s", default_data_dir, check_filename);
table = parse_table(check_config_file);
if (table == NULL) {
snprintf(check_config_file, 256, "/usr/share/detox/%s", check_filename);
table = parse_table(check_config_file);
}
if (table == NULL) {
snprintf(check_config_file, 256, "/usr/local/share/detox/%s", check_filename);
table = parse_table(check_config_file);
}
if (table == NULL) {
/*
* Fall back to the non-file based
* cleaner
*/
if (work->cleaner == &clean_iso8859_1) {
work->cleaner = &clean_iso8859_1_basic;
}
else if (work->cleaner == &clean_utf_8) {
work->cleaner = &clean_utf_8_basic;
}
else {
fprintf(stderr, "detox: unable to locate translation table or fall back\n");
exit(-1);
}
}
else {
/*
* Allocate an options
*/
opts = malloc(sizeof(struct clean_string_options));
memset(opts, 0, sizeof(struct clean_string_options));
opts->translation_table = table;
work->options = opts;
}
free(check_config_file);
}
else {
table = parse_table(check_filename);
if (table == NULL) {
fprintf(stderr, "detox: unable to parse file: %s\n", check_filename);
exit(-1);
}
opts = work->options;
opts->translation_table = table;
}
}
work = work->next;
}
/*
* Do some actual work
*/
file_walk = main_options->files;
while (*file_walk) {
if (main_options->verbose) {
printf("Scanning: %s\n", *file_walk);
}
err = lstat(*file_walk, &stat_info);
if (err == -1) {
fprintf(stderr, "%s: %s\n", *file_walk, strerror(errno));
}
else {
if (S_ISDIR(stat_info.st_mode)) {
parse_dir(*file_walk, main_options);
}
else if (S_ISREG(stat_info.st_mode)) {
parse_file(*file_walk, main_options);
}
else if (main_options->special) {
parse_special(*file_walk, main_options);
}
}
file_walk++;
}
return 0;
}
syntax highlighted by Code2HTML, v. 0.9.1