~vcs-imports/simias/trunk

« back to all changes in this revision

Viewing changes to simias/tools/gsoap/gsoap-linux-2.7/samples/rss/rss.c

  • Committer: kalidasbala
  • Date: 2007-08-25 12:48:51 UTC
  • Revision ID: vcs-imports@canonical.com-20070825124851-vlfvzun3732ld196
Latest gsoap code update

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 
 
3
RSS 0.91, 0.92, and 2.0
 
4
 
 
5
Retrieve RSS feeds.
 
6
 
 
7
Compile:
 
8
soapcpp2 -c rss.h
 
9
cc rss.c stdsoap2.c soapC.c
 
10
 
 
11
Usage: rss [maxitems] URL
 
12
Prints RSS content in text format.
 
13
 
 
14
Usage: rss.cgi
 
15
Installed as CGI application prints Javascript code to view RSS feeds in Web
 
16
pages. The Javascript code produced by this application is executed with the
 
17
following example script embedded in the Web page, e.g. to display BBC news:
 
18
 
 
19
<script src="http://www.cs.fsu.edu/~engelen/rss.cgi/?rss=http%3A%2F%2Fwww.bbc.co.uk%2Fsyndication%2Ffeeds%2Fnews%2Fukfs_news%2Ffront_page%2Frss091.xml&max=10"></script>
 
20
<noscript><a href="http://www.cs.fsu.edu/~engelen/rss.cgi/?rss=http%3A%2F%2Fwww.bbc.co.uk%2Fsyndication%2Ffeeds%2Fnews%2Fukfs_news%2Ffront_page%2Frss091.xml&max=10">View BBC News | Front Page | UK Edition</a></noscript> 
 
21
 
 
22
To control the appearance with cascading style sheets:
 
23
rss_box         the bounding div for the entire display 
 
24
rss_table       the table with title, image, and items
 
25
rss_title       the title of the feed and link style if displayed
 
26
rss_image       the image
 
27
rss_bar         the dividing bar
 
28
rss_item        the title of the item
 
29
rss_desc        the description of the item
 
30
 
 
31
--------------------------------------------------------------------------------
 
32
gSOAP XML Web services tools
 
33
Copyright (C) 2001-2004, Robert van Engelen, Genivia, Inc. All Rights Reserved.
 
34
This software is released under one of the following two licenses:
 
35
GPL or Genivia's license for commercial use.
 
36
--------------------------------------------------------------------------------
 
37
GPL license.
 
38
 
 
39
This program is free software; you can redistribute it and/or modify it under
 
40
the terms of the GNU General Public License as published by the Free Software
 
41
Foundation; either version 2 of the License, or (at your option) any later
 
42
version.
 
43
 
 
44
This program is distributed in the hope that it will be useful, but WITHOUT ANY
 
45
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
 
46
PARTICULAR PURPOSE. See the GNU General Public License for more details.
 
47
 
 
48
You should have received a copy of the GNU General Public License along with
 
49
this program; if not, write to the Free Software Foundation, Inc., 59 Temple
 
50
Place, Suite 330, Boston, MA 02111-1307 USA
 
51
 
 
52
Author contact information:
 
53
engelen@genivia.com / engelen@acm.org
 
54
--------------------------------------------------------------------------------
 
55
A commercial use license is available from Genivia, Inc., contact@genivia.com
 
56
--------------------------------------------------------------------------------
 
57
*/
 
58
 
 
59
#include "soapH.h"
 
60
 
 
61
#define STR(s) ((s)?(s):"")
 
62
 
 
63
/* Maximum number of HTTP redirects */
 
64
#define MAX_REDIRECTS 10
 
65
 
 
66
static void docwrite0(struct soap *soap, const char *s);
 
67
static void docwrite1(struct soap *soap, const char *s1, const char *s2, const char *s3);
 
68
static void docwrite2(struct soap *soap, const char *s1, const char *s2, const char *s3, const char *s4, const char *s5);
 
69
static void docerror(struct soap *soap, const char *s);
 
70
static void strwrite(struct soap *soop, const char *s);
 
71
static char *query_key(char *buf, size_t len, char **s);
 
72
static char *query_val(char *buf, size_t len, char **s);
 
73
 
 
74
int main(int argc, char **argv)
 
75
{ struct soap *soap = soap_new1(SOAP_C_UTFSTRING); /* preserve UTF8 string content */
 
76
  const char *endpoint = NULL;
 
77
  struct rss *rss;
 
78
  int maxitems = 10; /* max items to show */
 
79
  int show_date = 1; /* show date yes/no */
 
80
  int i;
 
81
  /* RSS has no encoding style */
 
82
  soap->encodingStyle = NULL;
 
83
  /* get URL of RSS feed or run as CGI app */
 
84
  if (argc >= 3)
 
85
  { maxitems = atoi(argv[1]);
 
86
    endpoint = argv[2];
 
87
  }
 
88
  else if (argc >= 2)
 
89
    endpoint = argv[1];
 
90
  else
 
91
  { char *query = getenv("QUERY_STRING"); /* CGI app: get query string */
 
92
    char *keybuf;
 
93
    char *valbuf;
 
94
    int len;
 
95
    if (query)
 
96
    { len = strlen(query);
 
97
      keybuf = (char*)soap_malloc(soap, len + 1);
 
98
      valbuf = (char*)soap_malloc(soap, len + 1);
 
99
      while (query)
 
100
      { char *key = query_key(keybuf, len, &query); /* decode next query string key */
 
101
        char *val = query_val(valbuf, len, &query); /* decode next query string value (if any) */
 
102
        /* get endpoint and max number of items to display */
 
103
        if (key && val)
 
104
        { if (!strcmp(key, "rss"))
 
105
            endpoint = soap_strdup(soap, val);
 
106
          else if (!strcmp(key, "max"))
 
107
            maxitems = atoi(val);
 
108
          else if (!strcmp(key, "date"))
 
109
            show_date = (*val == 'y');
 
110
        }
 
111
      }
 
112
    }
 
113
    if (!endpoint)
 
114
    { docerror(soap, "No RSS URL");
 
115
      exit(0);
 
116
    }
 
117
  }
 
118
  /* connect and parse HTTP header (max HTTP redirects) */
 
119
  for (i = 0; i < MAX_REDIRECTS; i++)
 
120
  { /* HTTP GET and parse HTTP header */
 
121
    if (soap_connect_command(soap, SOAP_GET, endpoint, NULL)
 
122
     || soap_begin_recv(soap))
 
123
    { if ((soap->error >= 301 && soap->error <= 303) || soap->error == 307)
 
124
        endpoint = soap_strdup(soap, soap->endpoint); /* HTTP redirects */
 
125
      else
 
126
      { soap_print_fault(soap, stderr);
 
127
        exit(soap->error);
 
128
      }
 
129
    }
 
130
    else
 
131
      break;
 
132
  }
 
133
  /* parse RSS */
 
134
  rss = soap_get_rss(soap, NULL, "rss", NULL);
 
135
  /* close connection */
 
136
  soap_end_recv(soap);
 
137
  soap_closesock(soap);
 
138
  if (argc < 2)
 
139
  { /* CGI application: produce Javascript */
 
140
    if (rss && (!strcmp(rss->version, "0.91") || !strcmp(rss->version, "0.92") || !strcmp(rss->version, "2.0")))
 
141
    { soap_begin_send(soap);
 
142
      soap->http_content = "application/javascript";
 
143
      soap_response(soap, SOAP_FILE); /* SOAP_FILE specifies http_content should be used */
 
144
      docwrite0(soap, "<div class='rss_box' align='center'>");
 
145
      docwrite0(soap, "<table cellpadding='2' width='100%' class='rss_table'>");
 
146
      if (rss->channel.title)
 
147
      { if (rss->channel.link)
 
148
          docwrite2(soap, "<tr><th class='rss_title'><a href='", rss->channel.link, "' target='_blank'>", rss->channel.title, "</a></th></tr>");
 
149
        else
 
150
          docwrite1(soap, "<tr><th class='rss_title'>", rss->channel.title, "</th></tr>");
 
151
      }
 
152
      if (rss->channel.image && rss->channel.image->url)
 
153
      { struct image *image = rss->channel.image;
 
154
        if (image->link)
 
155
          docwrite2(soap, "<tr><th class='rss_image'><a href='", image->link, "' target='_blank'><img src='", image->url, "' alt='Channel Image' border='0'/></a></th></tr>");
 
156
        else if (rss->channel.link)
 
157
          docwrite2(soap, "<tr><th class='rss_image'><a href='", rss->channel.link, "' target='_blank'><img src='", image->url, "' alt='Channel Image' border='0'/></a></th></tr>");
 
158
        else
 
159
          docwrite1(soap, "<tr><th class='rss_image'><img src='", image->url, "' alt='Channel Image' border='0'</th></tr>");
 
160
        if (!rss->channel.title && image->title)
 
161
          docwrite1(soap, "<tr><td class='rss_title'>", image->title, "</td></tr>");
 
162
        if (!rss->channel.description && image->description)
 
163
          docwrite1(soap, "<tr><td class='rss_desc'>", image->description, "</td></tr>");
 
164
      }
 
165
      if (rss->channel.description)
 
166
        docwrite1(soap, "<tr><th class='rss_desc'>", rss->channel.description, "</th></tr>");
 
167
      if (rss->channel.copyright)
 
168
        docwrite1(soap, "<tr><td class='rss_desc'>", rss->channel.copyright, "</td></tr>");
 
169
      if (rss->channel.__size < maxitems)
 
170
        maxitems = rss->channel.__size;
 
171
      for (i = 0; i < maxitems; i++)
 
172
      { struct item *item = &rss->channel.item[i];
 
173
        docwrite0(soap, "<tr><td class='rss_bar' bgcolor='#bbbbbb'></td></tr>");
 
174
        if (item->title)
 
175
        { if (item->link)
 
176
            docwrite2(soap, "<tr><td class='rss_item' bgcolor='#dddddd'><a href='", item->link, "' target='_blank'>", item->title, "</a></td></tr>");
 
177
          else
 
178
            docwrite1(soap, "<tr><td class='rss_item' bgcolor='#dddddd'>", item->title, "</td></tr>");
 
179
          if (show_date && item->pubDate)
 
180
            docwrite1(soap, "<tr><td class='rss_date' bgcolor='#dddddd'>Posted on ", item->pubDate, "</td></tr>");
 
181
          else if (show_date && item->dc__date)
 
182
            docwrite1(soap, "<tr><td class='rss_date' bgcolor='#dddddd'>Posted on ", ctime(item->dc__date), "</td></tr>");
 
183
          if (item->description)
 
184
            docwrite1(soap, "<tr><td class='rss_desc' bgcolor='#eeeeee'>", item->description, "</td></tr>");
 
185
        }
 
186
      }
 
187
      docwrite0(soap, "</table>");
 
188
      docwrite0(soap, "</div>");
 
189
      soap_end_send(soap);
 
190
    }
 
191
    else
 
192
    { docerror(soap, "No RSS 0.91, 0.92, or 2.0 data");
 
193
      exit(0);
 
194
    }
 
195
  }
 
196
  else if (rss)
 
197
  { /* Interactive: produce text output */
 
198
    if (!strcmp(rss->version, "0.91") || !strcmp(rss->version, "0.92") || !strcmp(rss->version, "2.0"))
 
199
    { printf("Title: %s\n", STR(rss->channel.title));
 
200
      printf("Link: %s\n", STR(rss->channel.link));
 
201
      printf("Language: %s\n", STR(rss->channel.language));
 
202
      printf("Description: %s\n", STR(rss->channel.description));
 
203
      if (rss->channel.image)
 
204
      { printf("Image title: %s\n", STR(rss->channel.image->title));
 
205
        printf("Image url: %s\n", STR(rss->channel.image->url));
 
206
        printf("Image link: %s\n", STR(rss->channel.image->link));
 
207
        printf("Image dimensions: %d x %d\n", rss->channel.image->width, rss->channel.image->height);
 
208
        printf("Image description: %s\n", STR(rss->channel.image->description));
 
209
      }
 
210
      if (rss->channel.__size < maxitems)
 
211
        maxitems = rss->channel.__size;
 
212
      for (i = 0; i < maxitems; i++)
 
213
      { printf("\n%3d Title: %s\n", i+1, STR(rss->channel.item[i].title));
 
214
        printf("    Link: %s\n", STR(rss->channel.item[i].link));
 
215
        printf("    Description: %s\n", STR(rss->channel.item[i].description));
 
216
        if (rss->channel.item[i].pubDate)
 
217
          printf("    Posted: %s\n", rss->channel.item[i].pubDate);
 
218
        else if (rss->channel.item[i].dc__date)
 
219
          printf("    Posted: %s\n", ctime(rss->channel.item[i].dc__date));
 
220
      }
 
221
      printf("\nCopyright: %s\n", STR(rss->channel.copyright));
 
222
    }
 
223
    else
 
224
      fprintf(stderr, "RSS 0.91, 0.92, or 2.0 content expected\n");
 
225
  }
 
226
  else
 
227
    soap_print_fault(soap, stderr);
 
228
  soap_end(soap);
 
229
  soap_done(soap);
 
230
  soap_free(soap);
 
231
  return 0;
 
232
}
 
233
 
 
234
static void docwrite0(struct soap *soap, const char *s)
 
235
{ soap_send3(soap, "document.write(\"", s, "\");\n");
 
236
}
 
237
 
 
238
static void docwrite1(struct soap *soap, const char *s1, const char *s2, const char *s3)
 
239
{ soap_send2(soap, "document.write(\"", s1);
 
240
  strwrite(soap, s2);
 
241
  soap_send2(soap, s3, "\");\n");
 
242
}
 
243
 
 
244
static void docwrite2(struct soap *soap, const char *s1, const char *s2, const char *s3, const char *s4, const char *s5)
 
245
{ soap_send2(soap, "document.write(\"", s1);
 
246
  strwrite(soap, s2);
 
247
  soap_send(soap, s3);
 
248
  strwrite(soap, s4);
 
249
  soap_send2(soap, s5, "\");\n");
 
250
}
 
251
 
 
252
static void docerror(struct soap *soap, const char *s)
 
253
{ soap_begin_send(soap);
 
254
  soap->http_content = "application/javascript";
 
255
  soap_response(soap, SOAP_FILE);
 
256
  soap_send(soap, s);
 
257
  soap_end_send(soap);
 
258
}
 
259
 
 
260
static void strwrite(struct soap *soap, const char *s)
 
261
{ while (*s)
 
262
  { const char *t;
 
263
    for (t = s; *t; t++)
 
264
       if (*t == '\\' || *t == '"' || *t == '\n')
 
265
         break;
 
266
    soap_send_raw(soap, s, t - s);
 
267
    if (*t == '\\')
 
268
    { soap_send(soap, "\\\\");
 
269
      t++;
 
270
    }
 
271
    else if (*t == '"')
 
272
    { soap_send(soap, "\\\"");
 
273
      t++;
 
274
    }
 
275
    else if (*t == '\n')
 
276
    { t++;
 
277
      if (*t == '\n')
 
278
      { soap_send(soap, "<p/>"); /* two line breaks? Probably a new paragraph was intended */
 
279
        t++;
 
280
      }
 
281
      else
 
282
        soap_send(soap, " ");
 
283
    }
 
284
    s = t;
 
285
  }
 
286
}
 
287
 
 
288
static const char *decode_url(char *buf, size_t len, const char *val)
 
289
{ const char *s;
 
290
  char *t;
 
291
  if (!buf)
 
292
    return NULL;
 
293
  for (s = val; *s; s++)
 
294
    if (*s != ' ' && *s != '=')
 
295
      break;
 
296
  if (*s == '"')
 
297
  { t = buf;
 
298
    s++;
 
299
    while (*s && *s != '"' && --len)
 
300
      *t++ = *s++;
 
301
    *t = '\0';
 
302
    do s++;
 
303
    while (*s && *s != '&' && *s != '=');
 
304
  }
 
305
  else
 
306
  { t = buf;
 
307
    while (*s && *s != '&' && *s != '=' && --len)
 
308
    { switch (*s)
 
309
      { case '+':
 
310
          *t++ = ' ';
 
311
        case ' ':
 
312
          s++;
 
313
          break;
 
314
        case '%':
 
315
          *t++ = ((s[1] >= 'A' ? (s[1]&0x7) + 9 : s[1] - '0') << 4) + (s[2] >= 'A' ? (s[2]&0x7) + 9 : s[2] - '0');
 
316
          s += 3;
 
317
          break;
 
318
        default:
 
319
          *t++ = *s++;
 
320
      }
 
321
    }
 
322
    *t = '\0';
 
323
  }
 
324
  if (*s == '&')
 
325
    s++;
 
326
  return s;
 
327
}
 
328
 
 
329
static char *query_key(char *buf, size_t len, char **s)
 
330
{ char *t = *s;
 
331
  if (t && *t)
 
332
  { *s = (char*)decode_url(buf, len, t);
 
333
    return buf;
 
334
  }
 
335
  return *s = NULL;
 
336
}
 
337
 
 
338
static char *query_val(char *buf, size_t len, char **s)
 
339
{ char *t = *s;
 
340
  if (t && *t == '=')
 
341
  { *s = (char*)decode_url(buf, len, t);
 
342
    return buf;
 
343
  }
 
344
  return NULL;
 
345
}
 
346
 
 
347
/* RSS 0.91 doesn't use namespaces, but RSS 2.0 does, which means that soap->namespace=NULL when serializing RSS 0.91 feeds */
 
348
struct Namespace namespaces[] = {
 
349
{ "dc", "http://purl.org/dc/elements/1.1/" },
 
350
{ NULL, NULL } 
 
351
};