2 * Copyright (C) 2009,2010 Toni Gundogdu <legatvs@gmail.com>
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library 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 GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
25 #include <curl/curl.h>
27 #include "quvi/quvi.h"
31 #include "curl_wrap.h"
33 #define is_invarg(p) \
34 do { if (p == NULL) return (QUVI_INVARG); } while (0)
36 #define is_badhandle(h) \
37 do { if (h == NULL) return (QUVI_BADHANDLE); } while (0)
41 QUVIcode
quvi_init(quvi_t
* dst
)
48 quvi
= calloc(1, sizeof(*quvi
));
54 curl_global_init(CURL_GLOBAL_ALL
);
56 quvi
->curl
= curl_easy_init();
60 return (QUVI_CURLINIT
);
63 /* Set library defaults. */
64 quvi_setopt(quvi
, QUVIOPT_FORMAT
, "default");
65 quvi_setopt(quvi
, QUVIOPT_CATEGORY
, QUVIPROTO_HTTP
);
67 curl_easy_setopt(quvi
->curl
, CURLOPT_USERAGENT
, "Mozilla/5.0");
68 curl_easy_setopt(quvi
->curl
, CURLOPT_FOLLOWLOCATION
, 1L);
69 curl_easy_setopt(quvi
->curl
, CURLOPT_NOBODY
, 0L);
71 return (init_lua(quvi
));
76 void quvi_close(quvi_t
* handle
)
80 quvi
= (_quvi_t
*) handle
;
86 assert((*quvi
)->util_scripts
== NULL
);
87 assert((*quvi
)->website_scripts
== NULL
);
89 _free((*quvi
)->format
);
90 assert((*quvi
)->format
== NULL
);
92 _free((*quvi
)->errmsg
);
93 assert((*quvi
)->errmsg
== NULL
);
95 curl_easy_cleanup((*quvi
)->curl
);
99 assert((*quvi
) == NULL
);
101 curl_global_cleanup();
107 QUVIcode
quvi_supported(quvi_t quvi
, char *url
)
115 video
= calloc(1, sizeof(*video
));
121 freprintf(&video
->page_link
, "%s", url
);
123 rc
= find_host_script(video
);
125 quvi_parse_close((quvi_video_t
) & video
);
132 QUVIcode
quvi_parse(quvi_t quvi
, char *url
, quvi_video_t
* dst
)
142 video
= calloc(1, sizeof(*video
));
149 freprintf(&video
->page_link
, "%s", url
);
151 if (!video
->quvi
->no_shortened
)
153 rc
= is_shortened_url(video
);
160 rc
= find_host_script_and_parse(video
);
165 if (strlen(video
->redirect
)) /* Found a redirect. */
167 freprintf(&video
->page_link
, "%s", video
->redirect
);
175 #ifdef HAVE_ICONV /* Convert character set encoding to utf8. */
179 assert(video
->title
!= NULL
); /* must be set in the lua script */
181 video
->title
= from_html_entities(video
->title
);
183 if (!video
->quvi
->no_verify
)
185 llst_node_t curr
= video
->link
;
188 rc
= query_file_length(video
->quvi
, curr
);
195 /* set current video link to first link in the list. */
196 video
->curr
= video
->link
;
201 /* quvi_parse_close */
203 void quvi_parse_close(quvi_video_t
* handle
)
205 _quvi_video_t
*video
;
207 video
= (_quvi_video_t
*) handle
;
211 llst_node_t curr
= (*video
)->link
;
215 _quvi_video_link_t l
= (_quvi_video_link_t
) curr
->data
;
218 _free(l
->content_type
);
221 llst_free(&(*video
)->link
);
224 _free((*video
)->title
);
225 _free((*video
)->charset
);
226 _free((*video
)->page_link
);
227 _free((*video
)->host_id
);
228 _free((*video
)->redirect
);
229 _free((*video
)->starttime
);
235 static QUVIcode
_setopt(_quvi_t quvi
, QUVIoption opt
, va_list arg
)
241 asprintf(&opt, "%s", va_arg(arg,char *)); \
245 do { opt = va_arg(arg,long); } while(0); break
251 case QUVIOPT_NOVERIFY
:
252 _setn(quvi
->no_verify
);
253 case QUVIOPT_STATUSFUNCTION
:
254 quvi
->status_func
= va_arg(arg
, quvi_callback_status
);
256 case QUVIOPT_WRITEFUNCTION
:
257 quvi
->write_func
= va_arg(arg
, quvi_callback_write
);
259 case QUVIOPT_NOSHORTENED
:
260 _setn(quvi
->no_shortened
);
261 case QUVIOPT_CATEGORY
:
262 _setn(quvi
->category
);
264 return (QUVI_INVARG
);
273 QUVIcode
quvi_setopt(quvi_t quvi
, QUVIoption opt
, ...)
281 rc
= _setopt(quvi
, opt
, arg
);
287 static const char empty
[] = "";
289 static QUVIcode
_getprop(_quvi_video_t video
, QUVIproperty prop
, ...)
291 _quvi_video_link_t qvl
;
299 qvl
= (_quvi_video_link_t
) video
->curr
->data
;
308 type
= QUVIPROPERTY_TYPEMASK
& (int)prop
;
310 #define _initv(var,type) \
312 if ( !(var = va_arg(arg,type)) ) \
318 case QUVIPROPERTY_DOUBLE
:
319 _initv(dp
, double *);
320 case QUVIPROPERTY_STRING
:
322 case QUVIPROPERTY_LONG
:
332 #define _sets(with) \
333 do { *sp = with ? with:(char*)empty; } while(0); break
335 #define _setn(var,with) \
336 do { *var = with; } while(0); break
340 case QUVIPROP_HOSTID
:
341 _sets(video
->host_id
);
342 case QUVIPROP_PAGEURL
:
343 _sets(video
->page_link
);
344 case QUVIPROP_PAGETITLE
:
346 case QUVIPROP_VIDEOID
:
348 case QUVIPROP_VIDEOURL
:
350 case QUVIPROP_VIDEOFILELENGTH
:
351 _setn(dp
, qvl
->length
);
352 case QUVIPROP_VIDEOFILECONTENTTYPE
:
353 _sets(qvl
->content_type
);
354 case QUVIPROP_VIDEOFILESUFFIX
:
356 case QUVIPROP_HTTPCODE
:
357 _setn(lp
, video
->quvi
->httpcode
);
358 case QUVIPROP_VIDEOFORMAT
:
359 _sets(video
->quvi
->format
);
360 case QUVIPROP_STARTTIME
:
361 _sets(video
->starttime
);
369 static QUVIcode
_getinfo(_quvi_t quvi
, QUVIinfo info
, ...)
386 type
= QUVIINFO_TYPEMASK
& (int)info
;
390 case QUVIINFO_DOUBLE
:
391 _initv(dp
, double *);
392 case QUVIINFO_STRING
:
406 #define _setv(with) \
407 do { *vp = with ? with:NULL; } while(0); break
413 case QUVIINFO_CURLCODE
:
414 _setn(lp
, quvi
->curlcode
);
415 case QUVIINFO_HTTPCODE
:
416 _setn(lp
, quvi
->httpcode
);
431 QUVIcode
quvi_getinfo(quvi_t quvi
, QUVIinfo info
, ...)
439 p
= va_arg(arg
, void *);
442 return (_getinfo(quvi
, info
, p
));
447 QUVIcode
quvi_getprop(quvi_video_t video
, QUVIproperty prop
, ...)
455 p
= va_arg(arg
, void *);
458 return (_getprop(video
, prop
, p
));
461 /* quvi_next_videolink */
463 QUVIcode
quvi_next_videolink(quvi_video_t handle
)
467 is_badhandle(handle
);
469 video
= (_quvi_video_t
) handle
;
471 /* start from the first */
474 video
->curr
= video
->link
;
478 /* move to the next */
479 video
->curr
= video
->curr
->next
;
482 video
->curr
= video
->link
; /* reset */
489 static llst_node_t curr_host
= NULL
;
491 /* quvi_next_supported_website */
494 quvi_next_supported_website(quvi_t handle
, char **domain
,
497 struct lua_ident_s ident
;
501 is_badhandle(handle
);
502 quvi
= (_quvi_t
) handle
;
507 if (!quvi
->website_scripts
)
508 return (QUVI_NOLUAWEBSITE
);
511 curr_host
= quvi
->website_scripts
;
514 curr_host
= curr_host
->next
;
522 ident
.formats
= NULL
;
524 rc
= run_ident_func(&ident
, curr_host
);
526 if (rc
== QUVI_NOSUPPORT
)
528 /* The website scripts return QUVI_NOSUPPORT in all cases. This is
529 * because of the undefined URL that we pass to them above (ident.url
530 * = NULL). We are only interested in the `domain' and `formats'
531 * information anyway, so this is OK. */
532 if (ident
.categories
& quvi
->category
)
534 *domain
= ident
.domain
;
535 *formats
= ident
.formats
;
541 _free(ident
.formats
);
542 rc
= quvi_next_supported_website(handle
, domain
, formats
);
549 /* quvi_next_host, NOTE: deprecated. */
551 QUVIcode
quvi_next_host(char **domain
, char **formats
)
553 *domain
= *formats
= NULL
;
562 char *quvi_strerror(quvi_t handle
, QUVIcode code
)
564 static const char *errormsgs
[] =
567 "memory allocation failed",
568 "bad handle argument to function",
569 "invalid argument to function",
570 "curl initialization failed",
571 "end of list iteration",
572 "aborted by callback",
573 "lua initilization failed",
574 "lua website scripts not found",
575 "lua util scripts not found",
576 "invalid error code (internal _INTERNAL_QUVI_LAST)"
579 _quvi_t quvi
= (_quvi_t
) handle
;
583 if (code
> _INTERNAL_QUVI_LAST
)
584 return (quvi
->errmsg
);
588 if (code
> _INTERNAL_QUVI_LAST
)
589 code
= _INTERNAL_QUVI_LAST
;
592 return ((char *)errormsgs
[code
]);
597 char *quvi_version(QUVIversion type
)
599 static const char version
[] = PACKAGE_VERSION
;
600 static const char version_long
[] =
607 " built on " BUILD_DATE
609 " for " CANONICAL_TARGET
" ("
621 if (type
== QUVI_VERSION_LONG
)
622 return ((char *)version_long
);
623 return ((char *)version
);
628 void quvi_free(void *ptr
)
634 /* vim: set ts=2 sw=2 tw=72 expandtab: */