diff --git a/dub.sdl b/dub.sdl index 694ff62..23ae9ee 100644 --- a/dub.sdl +++ b/dub.sdl @@ -8,5 +8,6 @@ dependency "requests" version="~>1.0.9" dependency "vibe-d:web" version=">0.8.5" dependency "sumtype" version="~>0.8.13" -dependency "d_rss" version="~>0.1.4" dependency "pegged" version=">=0.0.0" + +libs "mrss" diff --git a/source/app.d b/source/app.d index 626c29f..d3f476e 100644 --- a/source/app.d +++ b/source/app.d @@ -140,8 +140,6 @@ void main(string[] args) { - setLogLevel(LogLevel.debug_); - // CLI arguments bool daemon = false; EndpointType endpoint = EndpointType.html; diff --git a/source/cartastraccia/actor.d b/source/cartastraccia/actor.d index 5766b2f..31bbf5d 100644 --- a/source/cartastraccia/actor.d +++ b/source/cartastraccia/actor.d @@ -20,6 +20,8 @@ import core.time; import std.conv : to; import std.variant; +import std.string : assumeUTF; +import std.utf : validate; alias TaskMap = Task[string]; @@ -42,7 +44,8 @@ req.keepAlive = false; req.timeout = ACTOR_REQ_TIMEOUT; auto res = req.get(path); - string tmp = res.responseBody.data.to!string; + string tmp = res.responseBody.data.assumeUTF; + validate(tmp); parseRSS(rss, tmp); } catch (Exception e) { @@ -57,7 +60,7 @@ rss.match!( (ref InvalidRSS i) { logWarn("Invalid feed at: "~path); - logWarn("Caused by entry \""~i.element~"\": "~i.content); + logWarn("Caused by: \""~i.element~"\": "~i.content); }, (ref FailedRSS f) { logWarn("Failed to load feed: "~ feedName); diff --git a/source/cartastraccia/include/mrss.d b/source/cartastraccia/include/mrss.d new file mode 100644 index 0000000..58ba2cf --- /dev/null +++ b/source/cartastraccia/include/mrss.d @@ -0,0 +1,873 @@ +module cartastraccia.include.mrss; + +import core.stdc.time; + +extern(C) nothrow +{ + +//typedef struct mrss_t mrss_t; +//typedef struct mrss_options_t mrss_options_t; +//typedef struct mrss_item_t mrss_item_t; +//typedef struct mrss_category_t mrss_category_t; +//typedef struct mrss_hour_t mrss_hour_t; +//typedef struct mrss_day_t mrss_day_t; +//typedef struct mrss_tag_t mrss_tag_t; +//typedef struct mrss_attribute_t mrss_attribute_t; +//typedef void * mrss_generic_t; + +alias mrss_generic_t = void*; + +/** This enum describes the error type of libmrss */ +immutable enum mrss_error_t { + MRSS_OK = 0, /**< No error */ + MRSS_ERR_POSIX, /**< For the correct error, use errno */ + MRSS_ERR_PARSER, /**< Parser error */ + MRSS_ERR_DOWNLOAD, /**< Download error */ + MRSS_ERR_VERSION, /**< The RSS has a no compatible VERSION */ + MRSS_ERR_DATA /**< The parameters are incorrect */ +} + +immutable enum mrss_version_t { + MRSS_VERSION_0_91, /**< 0.91 RSS version */ + MRSS_VERSION_0_92, /**< 0.92 RSS version */ + MRSS_VERSION_1_0, /**< 1.0 RSS version */ + MRSS_VERSION_2_0, /**< 2.0 RSS version */ + MRSS_VERSION_ATOM_0_3, /**< 0.3 Atom version */ + MRSS_VERSION_ATOM_1_0 /**< 1.0 Atom version */ +} + +/** Flag list for mrss_set and mrss_get functions */ +immutable enum mrss_flag_t { + /* Generic */ + + /** Set the ersion to a mrss_t element - the value is a mrss_version_t enum */ + MRSS_FLAG_VERSION = 1, + + /** Set the title to a mrss_t element - the value is a string */ + MRSS_FLAG_TITLE, + /** Set the title type to a mrss_t element - the value is a string (ex: text, html, ...)*/ + MRSS_FLAG_TITLE_TYPE, + /** Set the description to a mrss_t element - the value is a string */ + MRSS_FLAG_DESCRIPTION, + /** Set the description type to a mrss_t element - the value is a string */ + MRSS_FLAG_DESCRIPTION_TYPE, + /** Set the link to a mrss_t element - the value is a string */ + MRSS_FLAG_LINK, + /** Set the id to a mrss_t element - the value is a string */ + MRSS_FLAG_ID, + /** Set the language to a mrss_t element - the value is a string */ + MRSS_FLAG_LANGUAGE, + /** Set the rating to a mrss_t element - the value is a string */ + MRSS_FLAG_RATING, + /** Set the copyright to a mrss_t element - the value is a string */ + MRSS_FLAG_COPYRIGHT, + /** Set the copyright type to a mrss_t element - the value is a string */ + MRSS_FLAG_COPYRIGHT_TYPE, + /** Set the pubDate to a mrss_t element - the value is a string */ + MRSS_FLAG_PUBDATE, + /** Set the lastBuildDate to a mrss_t element - the value is a string */ + MRSS_FLAG_LASTBUILDDATE, + /** Set the docs to a mrss_t element - the value is a string */ + MRSS_FLAG_DOCS, + /** Set the managingeditor to a mrss_t element - the value is a string */ + MRSS_FLAG_MANAGINGEDITOR, + /** Set the managingeditor's email to a mrss_t element - the value is a string */ + MRSS_FLAG_MANAGINGEDITOR_EMAIL, + /** Set the managingeditor's uri to a mrss_t element - the value is a string */ + MRSS_FLAG_MANAGINGEDITOR_URI, + /** Set the webMaster to a mrss_t element - the value is a string */ + MRSS_FLAG_WEBMASTER, + /** Set the generator to a mrss_t element - the value is a string */ + MRSS_FLAG_TTL, + /** Set the about to a mrss_t element - the value is a string */ + MRSS_FLAG_ABOUT, + + /* Contributor */ + + /** Set the contributor to a mrss_t element - the value is a string */ + MRSS_FLAG_CONTRIBUTOR, + /** Set the contributor's email to a mrss_t element - the value is a string */ + MRSS_FLAG_CONTRIBUTOR_EMAIL, + /** Set the contributor's uri to a mrss_t element - the value is a string */ + MRSS_FLAG_CONTRIBUTOR_URI, + + /* Generator */ + + /** Set the generator to a mrss_t element - the value is a string */ + MRSS_FLAG_GENERATOR, + /** Set the generator's email to a mrss_t element - the value is a string */ + MRSS_FLAG_GENERATOR_URI, + /** Set the generator's uri to a mrss_t element - the value is a string */ + MRSS_FLAG_GENERATOR_VERSION, + + /* Image */ + + /** Set the image_title to a mrss_t element - the value is a string */ + MRSS_FLAG_IMAGE_TITLE, + /** Set the image_url to a mrss_t element - the value is a string */ + MRSS_FLAG_IMAGE_URL, + /** Set the image_logo to a mrss_t element - the value is a string */ + MRSS_FLAG_IMAGE_LOGO, + /** Set the image_link to a mrss_t element - the value is a string */ + MRSS_FLAG_IMAGE_LINK, + /** Set the image_width to a mrss_t element - the value is a integer */ + MRSS_FLAG_IMAGE_WIDTH, + /** Set the image_height to a mrss_t element - the value is a integer */ + MRSS_FLAG_IMAGE_HEIGHT, + /** Set the image_description to a mrss_t element - the value is a string */ + MRSS_FLAG_IMAGE_DESCRIPTION, + + /* TextInput */ + + /** Set the textinput_title to a mrss_t element - the value is a string */ + MRSS_FLAG_TEXTINPUT_TITLE, + /** Set the textinput_description to a mrss_t element - the value is a string */ + MRSS_FLAG_TEXTINPUT_DESCRIPTION, + /** Set the textinput_name to a mrss_t element - the value is a string */ + MRSS_FLAG_TEXTINPUT_NAME, + /** Set the textinput_link to a mrss_t element - the value is a string */ + MRSS_FLAG_TEXTINPUT_LINK, + + /* Cloud */ + + /** Set the cloud to a mrss_t element - the value is a string */ + MRSS_FLAG_CLOUD, + /** Set the cloud_domain to a mrss_t element - the value is a string */ + MRSS_FLAG_CLOUD_DOMAIN, + /** Set the cloud_port to a mrss_t element - the value is a string */ + MRSS_FLAG_CLOUD_PORT, + /** Set the cloud_path to a mrss_t element - the value is a integer */ + MRSS_FLAG_CLOUD_PATH, + /** Set the cloud_registerProcedure to a mrss_t element - + * the value is a string */ + MRSS_FLAG_CLOUD_REGISTERPROCEDURE, + /** Set the cloud_protocol to a mrss_t element - the value is a string */ + MRSS_FLAG_CLOUD_PROTOCOL, + + /* SkipHours */ + + /** Set the hour to a mrss_hour_t element - the value is a string */ + MRSS_FLAG_HOUR, + + /* SkipDays */ + + /** Set the day to a mrss_day_t element - the value is a string */ + MRSS_FLAG_DAY, + + /* Category or Item/Category */ + + /** Set the category to a mrss_category_t element - the value is a string */ + MRSS_FLAG_CATEGORY, + /** Set the domain to a mrss_category_t element - the value is a string */ + MRSS_FLAG_CATEGORY_DOMAIN, + /** Set the label to a mrss_category_t element - the value is a string */ + MRSS_FLAG_CATEGORY_LABEL, + + /* Item */ + + /** Set the title to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_TITLE, + /** Set the title type to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_TITLE_TYPE, + /** Set the link to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_LINK, + /** Set the description to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_DESCRIPTION, + /** Set the description type to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_DESCRIPTION_TYPE, + /** Set the copyright to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_COPYRIGHT, + /** Set the copyright type to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_COPYRIGHT_TYPE, + + /** Set the author to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_AUTHOR, + /** Set the author's uri to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_AUTHOR_URI, + /** Set the author's email to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_AUTHOR_EMAIL, + + /** Set the contributor to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_CONTRIBUTOR, + /** Set the contributor's uri to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_CONTRIBUTOR_URI, + /** Set the contributor's email to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_CONTRIBUTOR_EMAIL, + + /** Set the comments to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_COMMENTS, + /** Set the pubDate to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_PUBDATE, + /** Set the guid to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_GUID, + /** Set the guid_isPermaLink to a mrss_item_t element - + * the value is a integer */ + MRSS_FLAG_ITEM_GUID_ISPERMALINK, + /** Set the source to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_SOURCE, + /** Set the source_url to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_SOURCE_URL, + /** Set the enclosure to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_ENCLOSURE, + /** Set the enclosure_url to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_ENCLOSURE_URL, + /** Set the enclosure_length to a mrss_item_t element - + * the value is a integer */ + MRSS_FLAG_ITEM_ENCLOSURE_LENGTH, + /** Set the enclosure_type to a mrss_item_t element - the value is a string */ + MRSS_FLAG_ITEM_ENCLOSURE_TYPE, + + /* Item */ + + /** Set the name to a mrss_tag_t element - the value is a string */ + MRSS_FLAG_TAG_NAME, + + /** Set the value to a mrss_tag_t element - the value is a string */ + MRSS_FLAG_TAG_VALUE, + + /** Set the namespace to a mrss_tag_t element - the value is a string */ + MRSS_FLAG_TAG_NS, + + /** Set the name to a mrss_attribute_t element - the value is a string */ + MRSS_FLAG_ATTRIBUTE_NAME, + + /** Set the value to a mrss_attribute_t element - the value is a string */ + MRSS_FLAG_ATTRIBUTE_VALUE, + + /** Set the namespace to a mrss_attribute_t element - the value is a string */ + MRSS_FLAG_ATTRIBUTE_NS, + + /** Set the terminetor flag */ + MRSS_FLAG_END = 0 + +} + +/** Enum for the casting of the libmrss data struct */ +immutable enum mrss_element_t { + /** The data struct is a mrss_t */ + MRSS_ELEMENT_CHANNEL, + /** The data struct is a mrss_item_t */ + MRSS_ELEMENT_ITEM, + /** The data struct is a mrss_hour_t */ + MRSS_ELEMENT_SKIPHOURS, + /** The data struct is a mrss_day_t */ + MRSS_ELEMENT_SKIPDAYS, + /** The data struct is a mrss_category_t */ + MRSS_ELEMENT_CATEGORY, + /** The data struct is a mrss_tag_t */ + MRSS_ELEMENT_TAG, + /** The data struct is a mrss_attribute_t */ + MRSS_ELEMENT_ATTRIBUTE +} + +/** Data struct for any items of RSS. It contains a pointer to the list + * of categories. + * + * \brief + * Struct data for item elements */ +struct mrss_item_t { + + /** For internal use only: */ + mrss_element_t element; + int allocated; + + /* Data: */ + + /* 0.91 0.92 1.0 2.0 ATOM */ + char *title; /* R O O O R */ + char *title_type; /* - - - - O */ + char *link; /* R O O O O */ + char *description; /* R O - O O */ + char *description_type; /* - - - - 0 */ + char *copyright; /* - - - - O */ + char *copyright_type; /* - - - - O */ + + char *author; /* - - - O O */ + char *author_uri; /* - - - - O */ + char *author_email; /* - - - - O */ + + char *contributor; /* - - - - O */ + char *contributor_uri; /* - - - - O */ + char *contributor_email; /* - - - - O */ + + char *comments; /* - - - O - */ + char *pubDate; /* - - - O O */ + char *guid; /* - - - O O */ + int guid_isPermaLink; /* - - - O - */ + + char *source; /* - O - O - */ + char *source_url; /* - R - R - */ + + char *enclosure; /* - O - O - */ + char *enclosure_url; /* - R - R - */ + int enclosure_length; /* - R - R - */ + char *enclosure_type; /* - R - R - */ + + mrss_category_t *category; /* - O - O O */ + mrss_tag_t *other_tags; + mrss_item_t *next; +}; + +/** Data struct for skipHours elements. + * + * \brief + * Struct data for skipHours elements */ +struct mrss_hour_t { + /** For internal use only: */ + mrss_element_t element; + int allocated; + + /* Data: */ + /* 0.91 0.92 1.0 2.0 ATOM */ + char *hour; /* R R - R - */ + mrss_hour_t *next; +}; + +/** Data struct for skipDays elements. + * + * \brief + * Struct data for skipDays elements */ +struct mrss_day_t { + /** For internal use only: */ + mrss_element_t element; + int allocated; + + /* Data: */ + /* 0.91 0.92 1.0 2.0 ATOM */ + char *day; /* R R - R - */ + mrss_day_t *next; +}; + +/** Data struct for category elements + * + * \brief + * Struct data for category elements */ +struct mrss_category_t { + /** For internal use only: */ + mrss_element_t element; + int allocated; + + /* Data: */ + /* 0.91 0.92 1.0 2.0 ATOM */ + char *category; /* - R - R R */ + char *domain; /* - O - O O */ + char *label; /* - - - - O */ + mrss_category_t *next; +}; + +/** Principal data struct. It contains pointers to any other structures. + * + * \brief + * Principal data struct. It contains pointers to any other structures */ +struct mrss_t { + /** For internal use only: */ + mrss_element_t element; + int allocated; + int curl_error; + + /* Data: */ + + char *file; + size_t size; + char *encoding; + + mrss_version_t _version; /* 0.91 0.92 1.0 2.0 ATOM */ + + char *title; /* R R R R R */ + char *title_type; /* - - - - O */ + char *description; /* R R R R R */ + char *description_type; /* - - - - O */ + char *link; /* R R R R O */ + char *id; /* - - - - O */ + char *language; /* R O - O O */ + char *rating; /* O O - O - */ + char *copyright; /* O O - O O */ + char *copyright_type; /* - - - - O */ + char *pubDate; /* O O - O - */ + char *lastBuildDate; /* O O - O O */ + char *docs; /* O O - O - */ + char *managingeditor; /* O O - O O */ + char *managingeditor_email; /* O O - O O */ + char *managingeditor_uri; /* O O - O O */ + char *webMaster; /* O O - O - */ + int ttl; /* - - - O - */ + char *about; /* - - R - - */ + + /* Contributor */ /* - - - - O */ + char *contributor; /* - - - - R */ + char *contributor_email; /* - - - - O */ + char *contributor_uri; /* - - - - O */ + + /* Generator */ + char *generator; /* - - - O O */ + char *generator_uri; /* - - - - O */ + char *generator_version; /* - - - - O */ + + /* Tag Image: */ /* O O O O - */ + char *image_title; /* R R R R - */ + char *image_url; /* R R R R O */ + char *image_logo; /* - - - - O */ + char *image_link; /* R R R R - */ + uint image_width; /* O O - O - */ + uint image_height; /* O O - O - */ + char *image_description; /* O O - O - */ + + /* TextInput: */ /* O O O O - */ + char *textinput_title; /* R R R R - */ + char *textinput_description; /* R R R R - */ + char *textinput_name; /* R R R R - */ + char *textinput_link; /* R R R R - */ + + /* Cloud */ + char *cloud; /* - O - O - */ + char *cloud_domain; /* - R - R - */ + int cloud_port; /* - R - R - */ + char *cloud_path; /* - R - R - */ + char *cloud_registerProcedure;/* - R - R - */ + char *cloud_protocol; /* - R - R - */ + + mrss_hour_t *skipHours; /* O O - O - */ + mrss_day_t *skipDays; /* O O - O - */ + + mrss_category_t *category; /* - O - O O */ + + mrss_item_t *item; /* R R R R R */ + + mrss_tag_t *other_tags; + +//#ifdef USE_LOCALE + //void *c_locale; +//#endif + +}; + +/** Data struct for any other tag out of the RSS namespace. + * + * \brief + * Struct data for external tags */ +struct mrss_tag_t { + /** For internal use only: */ + mrss_element_t element; + int allocated; + + /*name of the tag */ + char *name; + + /* value */ + char *value; + + /* namespace */ + char *ns; + + /* list of attributes: */ + mrss_attribute_t *attributes; + + /* Sub tags: */ + mrss_tag_t *children; + + /* the next tag: */ + mrss_tag_t *next; +}; + +/** Data struct for the attributes of the tag + * + * \brief + * Struct data for external attribute */ +struct mrss_attribute_t { + /** For internal use only: */ + mrss_element_t element; + int allocated; + + /* name of the tag */ + char *name; + + /* value */ + char *value; + + /* namespace */ + char *ns; + + /* The next attribute: */ + mrss_attribute_t *next; +}; + +/** Options data struct. It contains some user preferences. + * + * \brief + * Options data struct. It contains some user preferences. */ +struct mrss_options_t { + int timeout; + char *proxy; + char *proxy_authentication; + char *certfile; + char *cacert; + char *password; + int verifypeer; + char *authentication; + char *user_agent; +}; + +/** PARSE FUNCTIONS *********************************************************/ + +/** + * Parses a url and creates the data struct of the feed RSS url. + * This function downloads your request if this is http or ftp. + * \param url The url to be parsed + * \param mrss the pointer to your data struct + * \return the error code + */ +mrss_error_t mrss_parse_url (char * url, + mrss_t ** mrss); + +/** + * Like the previous function but with a options struct. + * \param url The url to be parsed + * \param mrss the pointer to your data struct + * \param options a pointer to a options data struct + * \return the error code + */ +mrss_error_t mrss_parse_url_with_options + (char * url, + mrss_t ** mrss, + mrss_options_t * options); + +/** + * Like the previous function but with CURLcode error + * \param url The url to be parsed + * \param mrss the pointer to your data struct + * \param options a pointer to a options data struct. It can be NULL + * \param curlcode the error code from libcurl + * \return the error code + */ +//mrss_error_t mrss_parse_url_with_options_and_error + //(char * url, + //mrss_t ** mrss, + //mrss_options_t * options, + //CURLcode * curlcode); + +/** + * Like the previous function but you take ownership of the downloaded buffer + * in case of success + * \param url The url to be parsed + * \param mrss the pointer to your data struct + * \param options a pointer to a options data struct + * \param curlcode the error code from libcurl + * \param feed_content a pointer to the buffer with the document. This is not NULL terminated + * \param feed_size the size of the buffer above + * \return the error code + */ +//mrss_error_t mrss_parse_url_with_options_error_and_transfer_buffer + //(char * url, + //mrss_t ** mrss, + //mrss_options_t * options, + //CURLcode * curlcode, + //char ** feed_content, + //int * feed_size); + +/** + * Parses a file and creates the data struct of the feed RSS url + * \param file The file to be parsed + * \param mrss the pointer to your data struct + * \return the error code + */ +mrss_error_t mrss_parse_file (char * file, + mrss_t ** mrss); + +/** + * Parses a buffer and creates the data struct of the feed RSS url + * \param buffer Pointer to the xml memory stream to be parsed + * \param size_buffer The size of the array of char + * \param mrss the pointer to your data struct + * \return the error code + */ +mrss_error_t mrss_parse_buffer (char * buffer, + size_t size_buffer, + mrss_t ** mrss); + +/** WRITE FUNCTIONS *********************************************************/ + +/** + * Writes a RSS struct data in a local file + * \param mrss the rss struct data + * \param file the local file + * \return the error code + */ +mrss_error_t mrss_write_file (mrss_t * mrss, + char * file); + +/** + * Write a RSS struct data in a buffer. + * + * \code + * char *buffer; + * buffer=NULL; //<--- This is important!! + * mrss_write_buffer (mrss, &buffer); + * \endcode + * + * The buffer must be NULL. + * \param mrss the rss struct data + * \param buffer the buffer + * \return the error code + */ +mrss_error_t mrss_write_buffer (mrss_t * mrss, + char ** buffer); + +/** FREE FUNCTION ***********************************************************/ + +/** + * This function frees any type of data struct of libmrss. If the element + * is alloced by libmrss, it will be freed, else this function frees + * only the internal data. + * + * \code + * mrss_t *t=....; + * mrss_item_t *item=...; + * + * mrss_free(t); + * mrss_free(item); + * \endcode + * + * \param element the data struct + * \return the error code + */ +mrss_error_t mrss_free (mrss_generic_t element); + +/** GENERIC FUNCTION ********************************************************/ + +/** + * This function returns a static string with the description of error code + * \param err the error code that you need as string + * \return a string. Don't free this string! + */ +char * mrss_strerror (mrss_error_t err); + +/** + * This function returns a static string with the description of curl code + * \param err the error code that you need as string + * \return a string. Don't free this string! + */ +//char * mrss_curl_strerror (CURLcode err); + +/** + * This function returns the mrss_element_t of a mrss data struct. + * \param element it is the element that you want check + * \param ret it is a pointer to a mrss_element_t. It will be sets. + * \return the error code + */ +mrss_error_t mrss_element (mrss_generic_t element, + mrss_element_t *ret); + +/** + * This function returns the number of seconds sinze Jennuary 1st 1970 in the + * UTC time zone, for the url that the urlstring parameter specifies. + * + * \param urlstring the url + * \param lastmodified is a pointer to a time_t struct. The return value can + * be 0 if the HEAD request does not return a Last-Modified value. + * \return the error code + */ +mrss_error_t mrss_get_last_modified (char * urlstring, + time_t * lastmodified); + +/** + * Like the previous function but with a options struct. + * + * \param urlstring the url + * \param lastmodified is a pointer to a time_t struct. The return value can + * be 0 if the HEAD request does not return a Last-Modified value. + * \param options a pointer to a options struct + * \return the error code + */ +mrss_error_t mrss_get_last_modified_with_options + (char * urlstring, + time_t * lastmodified, + mrss_options_t * options); +/** + * Like the previous function but with a CURLcode pointer. + * + * \param urlstring the url + * \param lastmodified is a pointer to a time_t struct. The return value can + * be 0 if the HEAD request does not return a Last-Modified value. + * \param options a pointer to a options struct + * \param curl_code it will contain the error code of libcurl + * \return the error code + */ +//mrss_error_t mrss_get_last_modified_with_options_and_error + //(char * urlstring, + //time_t * lastmodified, + //mrss_options_t * options, + //CURLcode * curl_code); + +/** EDIT FUNCTIONS **********************************************************/ + +/** If you want create a new feed RSS from scratch, you need use + * this function as the first. + * + * \code + * mrss_t *d; + * mrss_error_t err; + * char *string; + * int integer; + * + * d=NULL; // ->this is important! If d!=NULL, mrss_new doesn't alloc memory. + * mrss_new(&d); + * + * err=mrss_set (d, + * MRSS_FLAG_VERSION, MRSS_VERSION_0_92, + * MRSS_FLAG_TITLE, "the title!", + * MRSS_FLAG_TTL, 12, + * MRSS_FLAG_END); + * + * if(err!=MRSS_OK) printf("%s\n",mrss_strerror(err)); + * + * err=mrss_get (d, + * MRSS_FLAG_TITLE, &string, + * MRSS_FLAG_TTL, &integer, + * MRSS_FLAG_END); + * + * if(err!=MRSS_OK) printf("%s\n",mrss_strerror(err)); + * printf("The title is: '%s'\n", string); + * printf("The ttl is: '%d'\n", integer); + * free(string); + * \endcode + * + * \param mrss is the pointer to the new data struct + * \return the error code + */ +mrss_error_t mrss_new (mrss_t ** mrss); + +/** + * For insert/replace/remove a flags use this function as this example: + * \code + * mrss_set(mrss, MRSS_FLAG_TITLE, "hello world", MRSS_FLAG_END); + * mrss_set(item, MRSS_FLAG_DESCRIPTION, NULL, MRSS_FLAG_END); + * \endcode + * + * \param element it is the mrss data that you want changes the the next + * list of elements. The list is composted by KEY - VALUES and as last + * element MRSS_FLAG_END. The variable of value depends from key. + * \see mrss_flag_t + * \return the error code + */ +mrss_error_t mrss_set (mrss_generic_t element, + ...); + +/** + * This function returns the request arguments. The syntax is the same of + * mrss_set but the values of the list are pointer to data element (int *, + * char **). If the key needs a char **, the value will be allocated. + * \code + * mrss_get(category, MRSS_FLAG_CATEGORY_DOMAIN, &string, MRSS_FLAG_END); + * if(string) free(string); + * \endcode + * \param element it is any type of mrss data struct. + * \return the error code + */ +mrss_error_t mrss_get (mrss_generic_t element, + ...); + +/** + * This function adds an element to another element. For example you can + * add a item to a channel, or a category to a item, and so on. Look this + * example: + * \code + * mrss_item_t *item = NULL; + * mrss_hour_t *hour = NULL; + * mrss_day_t day; // If the element is no null, the function + * mrss_category_t category, // does not alloc it + * + * mrss_new_subdata(mrss, MRSS_ELEMENT_ITEM, &item); + * mrss_new_subdata(mrss, MRSS_ELEMENT_SKIPHOURS, &hour); + * mrss_new_subdata(mrss, MRSS_ELEMENT_SKIPDAYS, &day); + * mrss_new_subdata(item, MRSS_ELEMENT_ITEM_CATEGORY, &category); + * \endcode + * \param element it is the parent element + * \param subelement it is the type of the child (MRSS_ELEMENT_ITEM, + * MRSS_ELEMENT_CATEGORY, ...) + * \param subdata it is the pointer to the new struct. If the pointer + * of *subdata exists, it will no alloced, else yes. + * \return the error code + * \see mrss_element_t + */ +mrss_error_t mrss_new_subdata (mrss_generic_t element, + mrss_element_t subelement, + mrss_generic_t subdata); + +/** + * This function removes a subdata element. As first argoment you must specify + * the parent, and second argoment the child. + * \code + * mrss_remove_subdata(mrss, item); + * \endcode + * \param element it is the parent + * \param subdata the child that you want remove. Remember: + * mrss_remove_subdata does not free the memory. So you can remove a item + * and reinsert it after. + * \return the error code + */ +mrss_error_t mrss_remove_subdata (mrss_generic_t element, + mrss_generic_t subdata); + +/* TAGS FUNCTIONS **********************************************************/ + +/** + * This function search a tag in a mrss_t, a mrss_item_t or a mrss_tag_t from + * name and a namespace. + * \param element it is the parent node (mrss_t or mrss_item_t) + * \param name the name of the element + * \param ns the namespace. It can be null if the tag has a null namespace + * \param tag the return pointer + * \return the error code + */ +mrss_error_t mrss_search_tag (mrss_generic_t element, + char * name, + char * ns, + mrss_tag_t ** tag); + +/** + * This function search an attribute from a mrss_tag_t, a name and a namespace + * \param element it is the mrss_tag_t + * \param name the name of the element + * \param ns the namespace. It can be null if the tag has a null namespace + * \param attribute the return pointer + * \return the error code + */ +mrss_error_t mrss_search_attribute (mrss_generic_t element, + char * name, + char * ns, + mrss_attribute_t ** attribute); + +/* OPTIONS FUNCTIONS *******************************************************/ + +/** + * This function creates a options struct. + * + * \param timeout timeout for the download procedure + * \param proxy a proxy server. can be NULL + * \param proxy_authentication a proxy authentication (user:pwd). can be NULL + * \param certfile a certificate for ssl autentication connection + * \param password the password of certfile + * \param cacert CA certificate to verify peer against. can be NULL + * \param verifypeer active/deactive the peer check + * \param authentication an authentication login (user:pwd). can be NULL + * \param user_agent a user_agent. can be NULL + * \return a pointer to a new allocated mrss_options_t struct + */ +mrss_options_t * + mrss_options_new (int timeout, + char *proxy, + char *proxy_authentication, + char *certfile, + char *password, + char *cacert, + int verifypeer, + char *authentication, + char *user_agent); + +/** + * This function destroys a options struct. + * \param options a pointer to a options struct + */ +void mrss_options_free (mrss_options_t *options); + +} diff --git a/source/cartastraccia/rss.d b/source/cartastraccia/rss.d index 6f41125..c55c7dd 100644 --- a/source/cartastraccia/rss.d +++ b/source/cartastraccia/rss.d @@ -1,11 +1,11 @@ module cartastraccia.rss; import cartastraccia.actor : FeedActorRequest; +import cartastraccia.include.mrss; import vibe.core.log; import vibe.http.server : render; import sumtype; -import mrss; import std.algorithm : startsWith, sort, move; import std.datetime; @@ -127,10 +127,12 @@ void parseRSS(ref RSS rss, string feed) @trusted { mrss_t* rssData; - mrss_error_t err = mrss_parse_buffer(feed.toZString, feed.length, &rssData); + size_t len; + auto fz = feed.toZString(len); + mrss_error_t err = mrss_parse_buffer(fz, len, &rssData); if(err) { - rss = InvalidRSS("mrss", ""); + rss = InvalidRSS("mrss", err.to!string); } else { rss = ValidRSS(); @@ -142,7 +144,7 @@ mrss_item_t* item = rssData.item; while(item) { newItem(item, vrss); - item = rssData.item; + item = item.next; } }); } @@ -150,13 +152,13 @@ // parse date and sort in descending order (newest first) rss.tryMatch!( (ref InvalidRSS i) { - logWarn("Invalid RSS for feed: " ~ feed); return; }, (ref ValidRSS vr) { - vr.channel.items.sort!( (i,j) => - (parseRFC822DateTime(i.pubDate) - > parseRFC822DateTime(j.pubDate))); + vr.channel.items.sort!( (i,j) { + return (parseRFC822DateTime(i.pubDate) + > parseRFC822DateTime(j.pubDate)); + }); }); } @@ -165,7 +167,7 @@ void newChannel(mrss_t* rssData, ref ValidRSS rss) { static foreach(m; __traits(allMembers, RSSChannel)) { - static if(is(typeof(__traits(getMember, mrss_t, m)) == char[])) { + static if(is(typeof(__traits(getMember, mrss_t, m)) == char*)) { mixin("rss.channel."~m~" = rssData."~m~".ZtoString.idup;"); } } @@ -176,8 +178,8 @@ RSSItem newItem; static foreach(m; __traits(allMembers, RSSItem)) { - static if(is(typeof(__traits(getMember, mrss_t, m)) == char[])) { - mixin("newItem."~m~" = rssItem."~m~".ZtoString.idup;"); + static if(is(typeof(__traits(getMember, mrss_item_t, m)) == char*)) { + mixin("newItem."~m~" = rssItem."~m~".to!string;"); } } @@ -192,10 +194,11 @@ return null; } -char* toZString(string s) +auto toZString(string s, ref size_t len) { - char[] ret=cast(char[])s; - if (ret[$-1]!='\0') - ret~="\0"; + char[] ret = s.to!(char[]); + if (ret[$-1] != '\0') + ret ~= "\0".to!(char[]); + len = ret.length; return ret.ptr; }