initial load of upstream version 1.06.32
[xmlrpc-c] / examples / query-meerkat.c
1 /* A simple news-searcher, written in C to demonstrate how to use the
2    xmplrpc-c client library.
3
4    This program connects to an XMLRPC server that O'Reilly runs on the
5    Internet, gets some information, and displays it on Standard Output.
6    
7    Note that that server is not in any way designed specifically for xmlrpc-c.
8    It simply implements the XMLRPC protocol, and works with any client that
9    implements XMLRPC.
10    
11    The service that the aforementioned server provides is that it gives you
12    a list of news articles that match a certain regular expression.  You give
13    that regular expression an argument to this client program.
14
15    For more details about O'Reilly's excellent Meerkat news service, see:
16    http://www.oreillynet.com/pub/a/rss/2000/11/14/meerkat_xmlrpc.html
17 */
18
19 #include <stdlib.h>
20 #include <stdio.h>
21 #include <string.h>
22
23 #include <xmlrpc-c/base.h>
24 #include <xmlrpc-c/client.h>
25
26 #include "config.h"  /* information about this build environment */
27
28 #define NAME        "XML-RPC C Meerkat Query Demo"
29 #define VERSION     "1.0"
30 #define MEERKAT_URL "http://www.oreillynet.com/meerkat/xml-rpc/server.php"
31
32 struct cmdline {
33     const char * searchArg;
34     int hours;
35 };
36
37
38 static void
39 parseCommandLine(int              const argc, 
40                  const char **    const argv,
41                  struct cmdline * const cmdlineP) {
42
43     if (argc-1 < 1) {
44         fprintf(stderr, "Need at least one argument:  "
45                 "A mysql regular expression "
46                 "search pattern.  Try 'query-meerkat Linux'\n");
47         exit(1);
48     } else {
49         cmdlineP->searchArg = argv[1];
50
51         if (argc-1 < 2) {
52             cmdlineP->hours = 24;
53         } else {
54             cmdlineP->hours = atoi(argv[2]);
55             if (cmdlineP->hours > 49) {
56                 fprintf(stderr, "It's not nice to ask for > 49 hours "
57                         "at once.\n");
58                 exit(1);    
59             }
60             if (argc-1 > 2) {
61                 fprintf(stderr, "There are at most 2 arguments: "
62                         "search pattern "
63                         "and number of hours.");
64                 exit(1);
65             }
66         }
67     }
68 }
69
70
71
72 static void 
73 die_if_fault_occurred(xmlrpc_env * const env) {
74     /* We're a command-line utility, so we abort if an error occurs. */
75     if (env->fault_occurred) {
76         fprintf(stderr, "XML-RPC Fault #%d: %s\n",
77                 env->fault_code, env->fault_string);
78         exit(1);
79     }
80 }
81
82
83
84 /* Hey! We fit in one function. */
85 int 
86 main(int          const argc, 
87      const char** const argv) {
88
89     struct cmdline cmdline;
90     char time_period[16];
91     xmlrpc_env env;
92     xmlrpc_value *stories, *story;
93     size_t size, i;
94     int first;
95
96     parseCommandLine(argc, argv, &cmdline);
97
98     snprintf(time_period, sizeof(time_period), "%dHOUR", cmdline.hours);
99
100     xmlrpc_env_init(&env);
101
102     /* Set up our client. */
103     xmlrpc_client_init2(&env, XMLRPC_CLIENT_NO_FLAGS, NAME, VERSION, NULL, 0);
104
105     die_if_fault_occurred(&env);
106
107     /* Ask Meerkat to look for matching stories. */
108     stories = xmlrpc_client_call(&env, MEERKAT_URL,
109                                  "meerkat.getItems", "({s:s,s:i,s:s})",
110                                  "search", cmdline.searchArg,
111                                  "descriptions", (xmlrpc_int32) 76,
112                                  "time_period", time_period);
113     die_if_fault_occurred(&env);
114     
115     /* Loop over the stories. */
116     size = xmlrpc_array_size(&env, stories);
117     die_if_fault_occurred(&env);
118     first = 1;
119     for (i = 0; i < size; i++) {
120         const char * title;
121         const char * link;
122         const char * description;
123
124         /* Extract the useful information from our story. */
125         story = xmlrpc_array_get_item(&env, stories, i);
126         die_if_fault_occurred(&env);
127         xmlrpc_decompose_value(&env, story, "{s:s,s:s,s:s,*}",
128                                "title", &title,
129                                "link", &link,
130                                "description", &description);
131         die_if_fault_occurred(&env);
132
133         /* Print a separator line if necessary. */
134         if (first)
135             first = 0;
136         else
137             printf("\n");
138
139         /* Print the story. */
140         if (strlen(description) > 0) {
141             printf("%s\n%s\n%s\n", title, description, link);
142         } else {
143             printf("%s\n%s\n", title, link);
144         }
145         free((char*)title);
146         free((char*)link);
147         free((char*)description);
148     }
149     
150     /* Shut down our client. */
151     xmlrpc_DECREF(stories);
152     xmlrpc_env_clean(&env);
153     xmlrpc_client_cleanup();
154
155     return 0;
156 }