Statistics
| Revision:

root / trunk / base / nzb.c @ 1857

History | View | Annotate | Download (6.9 KB)

1
/* 
2
    Copyright (C) 2005-2010  Erik van Pienbroek
3

                
4
    This program is free software; you can redistribute it and/or modify
5
    it under the terms of the GNU General Public License as published by
6
    the Free Software Foundation; either version 2 of the License, or
7
    (at your option) any later version.
8

                
9
    This program is distributed in the hope that it will be useful,
10
    but WITHOUT ANY WARRANTY; without even the implied warranty of
11
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
    GNU General Public License for more details.
13

                
14
    You should have received a copy of the GNU General Public License
15
    along with this program; if not, write to the Free Software
16
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
17
*/
18

                
19
#include 
20
#include 
21
#include 
22
#include "nntpgrab_utils.h"
23

                
24
struct _parse_data {
25
    NNTPGrabNZB *nzb;
26
    NNTPGrabNZBFile *current_file;
27
    NNTPGrabPart *current_segment;
28
};
29

                
30
static void
31
start_element_handler  (GMarkupParseContext *context,
32
                        const gchar         *element_name,
33
                        const gchar        **attribute_names,
34
                        const gchar        **attribute_values,
35
                        gpointer             user_data,
36
                        GError             **error)
37
{
38
    struct _parse_data *data = (struct _parse_data*) user_data;
39
    int i;
40

                
41
    if (!strcmp(element_name, "file")) {
42
        NNTPGrabNZBFile *file = g_slice_new0(NNTPGrabNZBFile);
43

                
44
        g_return_if_fail(data->current_file == NULL);
45

                
46
        data->nzb->files = ng_list_append(data->nzb->files, file);
47
        data->current_file = file;
48

                
49
        i = 0;
50
        while (attribute_names[i] != NULL) {
51
            if (!strcmp(attribute_names[i], "subject")) {
52
                strncpy((char *) file->subject, attribute_values[i], (size_t) sizeof(file->subject));
53
            } else if (!strcmp(attribute_names[i], "poster")) {
54
                strncpy((char *) file->poster, attribute_values[i], (size_t) sizeof(file->poster));
55
            } else if (!strcmp(attribute_names[i], "date")) {
56
                file->stamp = atoi(attribute_values[i]);
57
            }
58

                
59
            i++;
60
        }
61
    } else if (!strcmp(element_name, "segment")) {
62
        NNTPGrabPart *segment = g_slice_new0(NNTPGrabPart);
63

                
64
        g_return_if_fail(data->current_file != NULL);
65

                
66
        data->current_file->segments = ng_list_append(data->current_file->segments, segment);
67
        data->current_segment = segment;
68

                
69
        i = 0;
70
        while (attribute_names[i] != NULL) {
71
            if (!strcmp(attribute_names[i], "bytes")) {
72
                segment->size = atol(attribute_values[i]);
73
                data->current_file->filesize += segment->size;
74
            } else if (!strcmp(attribute_names[i], "number")) {
75
                segment->part_num = atoi(attribute_values[i]);
76
            }
77

                
78
            i++;
79
        }
80
    }
81
}
82

                
83
static void
84
end_element_handler    (GMarkupParseContext *context,
85
                        const gchar         *element_name,
86
                        gpointer             user_data,
87
                        GError             **error)
88
{
89
    struct _parse_data *data = (struct _parse_data*) user_data;
90

                
91
    if (!strcmp(element_name, "file")) {
92
        data->current_file = NULL;
93
    } else if (!strcmp(element_name, "segment")) {
94
        data->current_segment = NULL;
95
    }
96
}
97

                
98
static void
99
text_handler           (GMarkupParseContext *context,
100
                        const gchar         *text,
101
                        gsize                text_len,
102
                        gpointer             user_data,
103
                        GError             **error)
104
{
105
    struct _parse_data *data = (struct _parse_data*) user_data;
106
    const char *element_name = g_markup_parse_context_get_element(context);
107

                
108
    if (!strcmp(element_name, "segment")) {
109
        char *message_id;
110

                
111
        g_return_if_fail(data->current_segment != NULL);
112

                
113
        /* NZB files contain a message-id without the brackets. Add them manually */
114
        message_id = g_strdup_printf("<%s>", text);
115
        strncpy((char*) data->current_segment->message_id, message_id, (size_t) sizeof(data->current_segment->message_id) - 1);
116
        g_free(message_id);
117
    } else if (!strcmp(element_name, "group")) {
118
        g_return_if_fail(data->current_file != NULL);
119

                
120
        data->current_file->groups = ng_list_append(data->current_file->groups, g_strdup(text));
121
    }
122
}
123

                
124
static const GMarkupParser parser = {
125
  start_element_handler,
126
  end_element_handler,
127
  text_handler,
128
  NULL,
129
  NULL
130
};
131

                
132
NNTPGrabNZB *
133
nntpgrab_utils_parse_nzb_file(const char *contents, char **errmsg)
134
{
135
    GMarkupParseContext *context;
136
    GError              *error = NULL;
137
    struct _parse_data   parse_data;
138

                
139
    parse_data.nzb = g_slice_new0(NNTPGrabNZB);
140
    parse_data.current_file = NULL;
141
    parse_data.current_segment = NULL;
142

                
143
    context = g_markup_parse_context_new (&parser, 0, &parse_data, NULL);
144

                
145
    if (!g_markup_parse_context_parse (context, contents, -1, &error) ||
146
        !g_markup_parse_context_end_parse (context, &error)) {
147

                
148
        if (g_error_matches(error, G_MARKUP_ERROR, G_MARKUP_ERROR_BAD_UTF8)) {
149
            /* Encoding error. Try converting the file from iso-8859-1 to utf-8 first */
150
            char *contents2 = g_convert(contents, -1, "utf-8", "iso-8859-1", NULL, NULL, NULL);
151

                
152
            g_error_free(error);
153
            error = NULL;
154

                
155
            nntpgrab_utils_nzb_file_free(parse_data.nzb);
156
            parse_data.nzb = g_slice_new0(NNTPGrabNZB);
157
            parse_data.current_file = NULL;
158
            parse_data.current_segment = NULL;
159

                
160
            g_markup_parse_context_free (context);
161
            context = g_markup_parse_context_new (&parser, 0, &parse_data, NULL);
162

                
163
            if (g_markup_parse_context_parse (context, contents2, -1, &error)) {
164
                g_markup_parse_context_end_parse (context, &error);
165
            }
166

                
167
            g_free(contents2);
168
        }
169

                
170
        if (error) {
171
            if (errmsg) {
172
                *errmsg = g_strdup(error->message);
173
            }
174
            g_error_free(error);
175
            g_markup_parse_context_free (context);
176
            nntpgrab_utils_nzb_file_free(parse_data.nzb);
177

                
178
            return NULL;
179
        }
180
    }
181

                
182
    g_markup_parse_context_free (context);
183

                
184
    return parse_data.nzb;
185
}
186

                
187
void
188
nntpgrab_utils_nzb_file_free(NNTPGrabNZB *nzbfile)
189
{
190
    NGList *list;
191

                
192
    list = nzbfile->files;
193
    while (list) {
194
        NNTPGrabNZBFile *file = (NNTPGrabNZBFile *) list->data;
195
        NGList *list2;
196

                
197
        list2 = file->groups;
198
        while (list2) {
199
            g_free(list2->data);
200
            list2 = ng_list_next(list2);
201
        }
202

                
203
        ng_list_free(file->groups);
204

                
205
        list2 = file->segments;
206
        while (list2) {
207
            g_slice_free(NNTPGrabPart, list2->data);
208
            list2 = ng_list_next(list2);
209
        }
210

                
211
        ng_list_free(file->segments);
212

                
213
        g_slice_free(NNTPGrabNZBFile, file);
214

                
215
        list = ng_list_next(list);
216
    }
217

                
218
    g_slice_free(NNTPGrabNZB, nzbfile);
219
}