~ubuntu-branches/ubuntu/natty/xfce4-weather-plugin/natty-proposed

« back to all changes in this revision

Viewing changes to panel-plugin/http_client.c

  • Committer: Bazaar Package Importer
  • Author(s): Yves-Alexis Perez, Simon Huggins, Yves-Alexis Perez
  • Date: 2007-12-08 19:28:17 UTC
  • mfrom: (0.1.5 upstream)
  • Revision ID: james.westby@ubuntu.com-20071208192817-xjr2u2eshv19ndp5
Tags: 0.6.2-1
[ Simon Huggins ]
* debian/control: Move fake Homepage field to a real one now dpkg
  supports it.
* Add Vcs-* headers to debian/control

[ Yves-Alexis Perez ]
* New upstream release.
* debian/control:
  - updated standard versions to 3.7.3.
  - updated my email to the debian.org one.
* debian/copyright: updated copyrights, authors and license.
* debian/NEWS: remove tab at beginning of lines. 

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* vim: set expandtab ts=8 sw=4: */
2
 
 
3
 
/*  This program is free software; you can redistribute it and/or modify
4
 
 *  it under the terms of the GNU General Public License as published by
5
 
 *  the Free Software Foundation; either version 2 of the License, or
6
 
 *  (at your option) any later version.
7
 
 *
8
 
 *  This program is distributed in the hope that it will be useful,
9
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
 *  GNU Library General Public License for more details.
12
 
 *
13
 
 *  You should have received a copy of the GNU General Public License
14
 
 *  along with this program; if not, write to the Free Software
15
 
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
16
 
 */
17
 
 
18
 
#ifdef HAVE_CONFIG_H
19
 
#include <config.h>
20
 
#endif
21
 
 
22
 
#include <fcntl.h>
23
 
#include <errno.h>
24
 
#include <stdio.h>
25
 
#include <sys/socket.h>
26
 
#include <netdb.h>
27
 
#include <netinet/in.h>
28
 
#include <sys/types.h>
29
 
#include <string.h>
30
 
#include <unistd.h>
31
 
#include <glib.h>
32
 
 
33
 
#include <libxfce4util/libxfce4util.h>
34
 
#include <libxfce4panel/xfce-panel-macros.h>
35
 
 
36
 
#include "http_client.h"
37
 
 
38
 
struct request_data 
39
 
{
40
 
    int    fd;
41
 
    
42
 
    FILE      *save_fp;
43
 
    gchar     *save_filename;
44
 
    gchar    **save_buffer;
45
 
 
46
 
    gboolean   has_header;
47
 
    gchar      last_chars[4];
48
 
 
49
 
    gchar     *request_buffer;
50
 
    gint       offset;
51
 
    gint       size;
52
 
 
53
 
    CB_TYPE    cb_function;
54
 
    gpointer   cb_data;
55
 
};
56
 
 
57
 
static gboolean
58
 
keep_receiving (gpointer data);
59
 
 
60
 
 
61
 
static int
62
 
http_connect (gchar *hostname,
63
 
          gint   port)
64
 
{
65
 
    struct sockaddr_in dest_host;
66
 
    struct hostent *host_address;
67
 
    gint fd;
68
 
           
69
 
    if ((host_address = gethostbyname(hostname)) == NULL)
70
 
        return -1;
71
 
 
72
 
    if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1)
73
 
        return -1;
74
 
       
75
 
    dest_host.sin_family = AF_INET;
76
 
    dest_host.sin_port = htons(port);
77
 
    dest_host.sin_addr = *((struct in_addr *)host_address->h_addr);
78
 
    memset(&(dest_host.sin_zero), '\0', 8);
79
 
    fcntl(fd, F_SETFL, O_NONBLOCK);
80
 
    
81
 
    if ((connect(fd, (struct sockaddr *)&dest_host, sizeof(struct sockaddr)) == -1)
82
 
            && errno != EINPROGRESS)
83
 
    {
84
 
        perror("http_connect()");
85
 
        return -1;
86
 
    }
87
 
    else
88
 
        return fd;
89
 
    
90
 
}
91
 
       
92
 
static void
93
 
request_free (struct request_data *request)
94
 
{
95
 
    if (request->request_buffer)
96
 
        g_free(request->request_buffer);
97
 
 
98
 
    if (request->save_filename)
99
 
        g_free(request->save_filename);
100
 
 
101
 
    if (request->save_fp)
102
 
        fclose(request->save_fp);
103
 
 
104
 
    if (request->fd)
105
 
        close(request->fd);
106
 
 
107
 
    panel_slice_free (struct request_data, request);
108
 
}
109
 
 
110
 
static void
111
 
request_save (struct request_data *request,
112
 
          const gchar     *buffer)
113
 
{
114
 
    DBG ("Request Save");
115
 
 
116
 
    if (request->save_filename)
117
 
        if (!request->save_fp && 
118
 
                (request->save_fp = fopen(request->save_filename, "w"))
119
 
                == NULL)
120
 
            return;
121
 
        else
122
 
            fwrite(buffer, sizeof(char), strlen(buffer), 
123
 
                    request->save_fp);
124
 
    else
125
 
    {
126
 
        if (*request->save_buffer)
127
 
        {
128
 
            gchar *newbuff = g_strconcat(*request->save_buffer,
129
 
                    buffer, NULL);
130
 
            g_free(*request->save_buffer);
131
 
            *request->save_buffer = newbuff;
132
 
        }
133
 
        else
134
 
            *request->save_buffer = g_strdup(buffer);
135
 
    }
136
 
}               
137
 
        
138
 
static gboolean
139
 
keep_sending (gpointer data)
140
 
{
141
 
    struct request_data *request = (struct request_data *)data;
142
 
    gint n;
143
 
 
144
 
    if (!request)
145
 
    {
146
 
        DBG ("keep_sending(): empty request data");
147
 
        return FALSE;
148
 
    }
149
 
    
150
 
    if ((n = send(request->fd, request->request_buffer + request->offset, 
151
 
                    request->size - request->offset, 
152
 
                    0)) != -1)
153
 
    {
154
 
        request->offset += n;
155
 
 
156
 
        DBG ("now at offset: %d", request->offset);
157
 
        DBG ("now at byte: %d", n);
158
 
        
159
 
        if (request->offset == request->size)
160
 
        {
161
 
            DBG ("keep_sending(): ok data sent");
162
 
            g_idle_add(keep_receiving, (gpointer) request);
163
 
            return FALSE;
164
 
        }
165
 
    }
166
 
    else if (errno != EAGAIN) /* some other error happened */
167
 
    {
168
 
#if DEBUG
169
 
        perror("keep_sending()");
170
 
#endif          
171
 
        
172
 
        DBG ("file desc: %d", request->fd);
173
 
        
174
 
        request_free(request);
175
 
        return FALSE;
176
 
    }
177
 
 
178
 
    return TRUE;
179
 
180
 
 
181
 
static gboolean
182
 
keep_receiving (gpointer data)
183
 
{
184
 
    struct request_data *request = (struct request_data *)data;
185
 
    gchar recvbuffer[1024];
186
 
    gint n;
187
 
    gchar *p;
188
 
    gchar *str = NULL;
189
 
    
190
 
    if (!request)
191
 
    {
192
 
        DBG ("keep_receiving(): empty request data ");
193
 
        return FALSE;
194
 
    }
195
 
 
196
 
    if ((n = recv(request->fd, recvbuffer, sizeof(recvbuffer) - 
197
 
                    sizeof(char), 0)) > 0)
198
 
    {
199
 
        recvbuffer[n] = '\0';
200
 
 
201
 
        DBG ("keep_receiving(): bytes recv: %d", n);
202
 
        
203
 
        if (!request->has_header)
204
 
        {
205
 
            if (request->last_chars != '\0')
206
 
                str = g_strconcat(request->last_chars, 
207
 
                        recvbuffer, NULL);
208
 
            
209
 
            if ((p = strstr(str, "\r\n\r\n")))
210
 
            {
211
 
                request_save(request, p + 4);
212
 
                request->has_header = TRUE;
213
 
                DBG ("keep_receiving(): got header");
214
 
            }
215
 
            else
216
 
            {
217
 
                DBG ("keep_receiving(): no header yet\n\n%s\n..\n",
218
 
                        recvbuffer);      
219
 
                memcpy(request->last_chars, recvbuffer + (n - 4), 
220
 
                        sizeof(char) * 3);
221
 
            }
222
 
 
223
 
            g_free(str);
224
 
        }
225
 
        else
226
 
            request_save(request, recvbuffer);
227
 
    }
228
 
    else if (n == 0)
229
 
    {
230
 
        CB_TYPE callback = request->cb_function;
231
 
        gpointer data = request->cb_data;
232
 
        DBG ("keep_receiving(): ending with succes");
233
 
        request_free(request);
234
 
 
235
 
        callback(TRUE, data);
236
 
        return FALSE;
237
 
    }
238
 
    else if (errno != EAGAIN)
239
 
    {
240
 
        perror("keep_receiving()");
241
 
        request->cb_function(FALSE, request->cb_data);
242
 
        request_free(request);
243
 
        return FALSE;
244
 
    }
245
 
 
246
 
    return TRUE;
247
 
}
248
 
                
249
 
                
250
 
 
251
 
static gboolean
252
 
http_get (gchar     *url,
253
 
      gchar     *hostname,
254
 
      gboolean   savefile,
255
 
      gchar    **fname_buff, 
256
 
      gchar     *proxy_host,
257
 
      gint       proxy_port,
258
 
      CB_TYPE    callback,
259
 
      gpointer   data)
260
 
{
261
 
    struct request_data *request = panel_slice_new0 (struct request_data);
262
 
 
263
 
    if (!request)
264
 
    {
265
 
#if DEBUG
266
 
        perror("http_get(): empty request");
267
 
#endif
268
 
        return FALSE;
269
 
    }
270
 
    
271
 
    request->has_header = FALSE;
272
 
    request->cb_function = callback;
273
 
    request->cb_data = data;
274
 
 
275
 
    if (proxy_host)
276
 
    {
277
 
        DBG ("using proxy %s", proxy_host);
278
 
        request->fd = http_connect(proxy_host, proxy_port);
279
 
    }
280
 
    else
281
 
    {
282
 
        DBG ("Not USING PROXY");
283
 
        request->fd = http_connect(hostname, 80);
284
 
    }
285
 
 
286
 
    if (request->fd == -1)
287
 
    {
288
 
        DBG ("http_get(): fd = -1 returned");
289
 
        request_free(request);
290
 
        return FALSE;
291
 
    }
292
 
    
293
 
    if (proxy_host)
294
 
        request->request_buffer = g_strdup_printf(
295
 
                "GET http://%s%s HTTP/1.0\r\n\r\n",
296
 
                hostname, url);
297
 
    else
298
 
        request->request_buffer = g_strdup_printf("GET %s HTTP/1.0\r\n"
299
 
                "Host: %s\r\n\r\n", url, hostname);
300
 
 
301
 
    if (request->request_buffer == NULL)
302
 
    {
303
 
#if DEBUG
304
 
        perror("http_get(): empty request buffer\n");
305
 
#endif
306
 
        close(request->fd);
307
 
        panel_slice_free(struct request_data, request);
308
 
        return FALSE;
309
 
    }
310
 
 
311
 
    request->size = strlen (request->request_buffer);
312
 
 
313
 
    if (savefile)
314
 
        request->save_filename = g_strdup (*fname_buff);
315
 
    else
316
 
        request->save_buffer = fname_buff;
317
 
 
318
 
    DBG ("http_get(): adding idle function");
319
 
    
320
 
    (void)g_idle_add ((GSourceFunc)keep_sending, (gpointer)request);
321
 
 
322
 
    DBG ("http_get(): request added");
323
 
 
324
 
    return TRUE;
325
 
}    
326
 
 
327
 
gboolean
328
 
http_get_file (gchar   *url,
329
 
               gchar   *hostname,
330
 
               gchar   *filename, 
331
 
               gchar   *proxy_host,
332
 
               gint     proxy_port,
333
 
               CB_TYPE  callback,
334
 
               gpointer data)
335
 
{
336
 
    return http_get (url, hostname, TRUE, &filename, proxy_host, proxy_port, 
337
 
            callback, data);
338
 
}
339
 
 
340
 
gboolean
341
 
http_get_buffer (gchar    *url,
342
 
                 gchar    *hostname,
343
 
                 gchar    *proxy_host, 
344
 
                 gint      proxy_port,
345
 
                 gchar   **buffer,
346
 
                 CB_TYPE   callback,
347
 
                 gpointer  data)
348
 
{  
349
 
    return http_get (url, hostname, FALSE, buffer, proxy_host, proxy_port, 
350
 
            callback, data);
351
 
}