/*
 * <c7q4kq$dm9$1@news.onet.pl>
 *
 * w linii komend podać nazwę grupy (jeśli program uruchomiony jest 
 * z katalogu hamstera) lub ścieżkę do data.dat (jeśli data.dat 
 * w bieżacym katalogu, to ./data.dat). stdout przekierować do pliku 
 * w którym chcemy trzymać batchfile dla innxmit. program do bieżącego 
 * katalogu wypluje kolejno ponumerowane pliki z artykułami, których 
 * nagłówek Path będzie uzupełniony o hamster.converted (do wpisania 
 * do excludelisty feedów w innie).
 *
 * druga część instrukcji: man innxmit
 *
 * uwagi: gophi@linux.net.pl
 *
 */

#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>

extern int errno;

FILE *open_dest (unsigned long int *num)
{
	char name[16];
	FILE *fp;

	sprintf (name, "%lu.msg", *num);
	*num = *num + 1;	/* *num++ zwiększy wskaźnik */
	fp = fopen(name, "wb");
	if (!fp) {
		fprintf (stderr, "Błąd otwierania pliku %s: %m.\n", name);
		_exit (-1);
	}

	fprintf (stdout, "./%s\n", name);

	return fp;
}

char *extract_line (char *buf)
{
	char *line = (char *) NULL;
	int pos = 0;
	char done = 0;
	char ch;

	while (!done) {
		ch = buf[pos];
		if (!ch)
			done = 1;
		else {
			line = (char *) realloc(line, pos + 1);
			if (!line) {
				fputs ("Błąd realokacji bufora linii. Dziwne...\n", stderr);
				_exit (1);
			}
			line[pos] = ch;
			if (ch == 0x0A)
				done = 1;
		}
		pos++;
	}

	line = (char *) realloc(line, pos + 1);
	if (!line) {
		fputs ("Błąd realokacji bufora linii. Dziwne...\n", stderr);
		_exit (1);
	}
	line[pos] = (char) NULL;

	return line;
}

void add_path (char **buf, unsigned long int *len)
{
	char *old_buf, *new_buf;
	char *line;
	unsigned long int old_pos = 0, new_pos = 0, old_len, new_len;
	char added = 0;

	old_len = *len;
	old_buf = *buf;
	new_len = old_len + 18;	/* strlen("hamster.converted!") */
	new_buf = (char *) malloc(new_len);
	if (!new_buf) {
		fputs ("Błąd alokacji pamięci pod artykuł celem przepisania.\n", stderr);
		_exit (-1);
	}

	while (old_pos < old_len) {
		line = extract_line(old_buf + old_pos);
		if (!added && !strncasecmp(line, "path: ", 6)) {	/* to path */
			memcpy (new_buf + new_pos, "Path: hamster.converted!", 24);
			new_pos += 24;
			memcpy (new_buf + new_pos, line + 6, strlen(line) - 6);
			new_pos += strlen(line) - 6;
			added++;
		} else {	/* to nie path, lub już dodano */
			memcpy (new_buf + new_pos, line, strlen(line));
			new_pos += strlen(line);
		}
		old_pos += strlen(line);
		free (line);
	}

	if (added) {
		free (old_buf);
		*buf = new_buf;
		*len = new_len;
	} else {
		fputs ("Ostrzeżenie: Nie znalazłem nagłówka Path.\n", stderr);
		free (new_buf);
	}
}

void extract_articles (FILE *fp)
{
	unsigned long int num = 0;
	unsigned long int len;
	FILE *new_fp;
	char *buf;

	while (!0) {
		/* pobranie długości */
		if (fread(&len, sizeof(len), 1, fp) != 1)
			break;

		/* zaalokowanie bufora pod artykuł */
		buf = (char *) malloc(len);
		if (!buf) {
			fprintf (stderr, "Ostrzeżenie: Nie mogłem zaalokować %lu bajtów pod artykuł.\n", len);
			continue;
		}

		/* wczytanie artykułu z pliku z danymi */
		if (fread(buf, len, 1, fp) != 1) {
			fputs ("Uszkodzony plik z grupą.\n", stderr);
			_exit (-1);
		}

		/* zmiana nagłówka Path */
		add_path (&buf, &len);

		/* otworzenie pliku docelowego i wypisanie jego nazwy */
		new_fp = open_dest(&num);

		/* zapisanie artykułu do pliku docelowego */
		if (fwrite(buf, len, 1, new_fp) != 1) {
			fputs ("Błąd zapisu pliku docelowego?\n", stderr);
			_exit (-1);
		}

		fclose (new_fp);
		free (buf);
	}
}

int main (int argc, char **argv)
{
	char *path;
	FILE *fp;

	if (argc < 2) {
		puts ("Użycie (będąc w katalogu hamstera): hamxtract nazwa grupy");
		puts ("Lub: hamxtract ścieżka do pliku dat");
		return -1;
	}

	if (strchr(argv[1], '/'))	/* podana ścieżka */
		path = argv[1];
	else {				/* podana nazwa grupy */
		path = (char *) malloc(strlen(argv[1]) + 20);
		if (!path) {
			fputs ("Brak pamięci.\n", stderr);
			return -1;
		}
		snprintf (path, strlen(argv[1]) + 20, "groups/%s/data.dat", argv[1]);
	}

	fp = fopen(path, "rb");
	if (!fp) {
		fprintf (stderr, "Błąd otwierania pliku %s: %m.\n", path);
		return -1;
	}

	fprintf (stderr, "Używam pliku %s.\n", path);

	extract_articles (fp);

	fclose (fp);
	if (!strchr(argv[1], '/'))
		free (path);

	return 0;
}
