diff options
Diffstat (limited to 'src/Infobox')
| -rw-r--r-- | src/Infobox/Calculator.c | 41 | ||||
| -rw-r--r-- | src/Infobox/Dictionary.c | 197 | ||||
| -rw-r--r-- | src/Infobox/Dictionary.h | 2 | ||||
| -rw-r--r-- | src/Infobox/UnitConversion.c | 643 | ||||
| -rw-r--r-- | src/Infobox/Wikipedia.c | 155 |
5 files changed, 592 insertions, 446 deletions
diff --git a/src/Infobox/Calculator.c b/src/Infobox/Calculator.c index 22563f7..16bc4fa 100644 --- a/src/Infobox/Calculator.c +++ b/src/Infobox/Calculator.c @@ -1,9 +1,9 @@ #include "Calculator.h" +#include <ctype.h> +#include <math.h> #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <math.h> -#include <ctype.h> static char logic_log[4096]; @@ -15,7 +15,8 @@ typedef struct { static double parse_expression(Parser *p); static void skip_ws(Parser *p) { - while (p->buffer[p->pos] == ' ') p->pos++; + while (p->buffer[p->pos] == ' ') + p->pos++; } static double parse_factor(Parser *p) { @@ -27,7 +28,8 @@ static double parse_factor(Parser *p) { if (p->buffer[p->pos] == '(') { p->pos++; double res = parse_expression(p); - if (p->buffer[p->pos] == ')') p->pos++; + if (p->buffer[p->pos] == ')') + p->pos++; return res; } char *endptr; @@ -50,7 +52,7 @@ static double parse_term(Parser *p) { char step[256]; snprintf(step, sizeof(step), "<div>%g %c %g = <b>%g</b></div>", old, op, - right, left); + right, left); strncat(logic_log, step, sizeof(logic_log) - strlen(logic_log) - 1); } else break; @@ -72,7 +74,7 @@ static double parse_expression(Parser *p) { char step[256]; snprintf(step, sizeof(step), "<div>%g %c %g = <b>%g</b></div>", old, op, - right, left); + right, left); strncat(logic_log, step, sizeof(logic_log) - strlen(logic_log) - 1); } else break; @@ -82,33 +84,34 @@ static double parse_expression(Parser *p) { double evaluate(const char *expr) { logic_log[0] = '\0'; - if (!expr || strlen(expr) == 0) return 0.0; + if (!expr || strlen(expr) == 0) + return 0.0; Parser p = {expr, 0}; return parse_expression(&p); } InfoBox fetch_calc_data(char *math_input) { InfoBox info = {NULL, NULL, NULL, NULL}; - if (!math_input) return info; + if (!math_input) + return info; double result = evaluate(math_input); char html_output[5120]; snprintf(html_output, sizeof(html_output), - "<div class='calc-container' style='line-height: 1.6;'>" - "%s" - "<div style='margin-top: 8px; border-top: 1px solid #eee; " - "padding-top: 8px; font-size: 1.2em;'>" - "<b>%g</b>" - "</div>" - "</div>", - strlen(logic_log) > 0 ? logic_log : "<div>Constant value</div>", - result); + "<div class='calc-container' style='line-height: 1.6;'>" + "%s" + "<div style='margin-top: 8px; border-top: 1px solid #eee; " + "padding-top: 8px; font-size: 1.2em;'>" + "<b>%g</b>" + "</div>" + "</div>", + strlen(logic_log) > 0 ? logic_log : "<div>Constant value</div>", + result); info.title = strdup("Calculation"); info.extract = strdup(html_output); - info.thumbnail_url = - strdup("/static/calculation.svg"); + info.thumbnail_url = strdup("/static/calculation.svg"); info.url = strdup("#"); return info; diff --git a/src/Infobox/Dictionary.c b/src/Infobox/Dictionary.c index 1900c21..053b0f2 100644 --- a/src/Infobox/Dictionary.c +++ b/src/Infobox/Dictionary.c @@ -1,6 +1,7 @@ #include "Dictionary.h" #include "../Proxy/Proxy.h" #include "../Scraping/Scraping.h" +#include <ctype.h> #include <curl/curl.h> #include <libxml/HTMLparser.h> #include <libxml/xpath.h> @@ -8,42 +9,60 @@ #include <stdlib.h> #include <string.h> #include <strings.h> -#include <ctype.h> -static const char *PREFIXES[] = { - "what is the definition of ", "what's the definition of ", - "what is the meaning of ", "what's the meaning of ", - "what does the word ", "definition of ", "meaning of ", "def of ", - "define ", "definition ", "define:", "def ", "def:", - "what does ", "what is ", "what's ", "whats ", - "meaning ", "dictionary ", "dict ", NULL -}; +static const char *PREFIXES[] = {"what is the definition of ", + "what's the definition of ", + "what is the meaning of ", + "what's the meaning of ", + "what does the word ", + "definition of ", + "meaning of ", + "def of ", + "define ", + "definition ", + "define:", + "def ", + "def:", + "what does ", + "what is ", + "what's ", + "whats ", + "meaning ", + "dictionary ", + "dict ", + NULL}; static const char *SUFFIXES[] = { - " definition", " def", " meaning", " mean", " means", - " dictionary", " dict", " define", " defined", - " definition?", " def?", " meaning?", " mean?", " means?", - " in english", " in english?", NULL -}; + " definition", " def", " meaning", " mean", " means", + " dictionary", " dict", " define", " defined", " definition?", + " def?", " meaning?", " mean?", " means?", " in english", + " in english?", NULL}; static const char *SKIP_WORDS[] = {"of ", "the ", "a ", "an ", NULL}; static const char *strcasestr_impl(const char *haystack, const char *needle) { - if (!haystack || !needle || !*needle) return haystack; + if (!haystack || !needle || !*needle) + return haystack; size_t len = strlen(needle); for (const char *h = haystack; *h; h++) { - if (strncasecmp(h, needle, len) == 0) return h; + if (strncasecmp(h, needle, len) == 0) + return h; } return NULL; } -struct MemStruct { char *memory; size_t size; }; +struct MemStruct { + char *memory; + size_t size; +}; -static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) { +static size_t WriteCallback(void *contents, size_t size, size_t nmemb, + void *userp) { size_t realsize = size * nmemb; struct MemStruct *mem = (struct MemStruct *)userp; char *ptr = realloc(mem->memory, mem->size + realsize + 1); - if (!ptr) return 0; + if (!ptr) + return 0; mem->memory = ptr; memcpy(&(mem->memory[mem->size]), contents, realsize); mem->size += realsize; @@ -53,40 +72,57 @@ static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *use static char *xpath_text(xmlDocPtr doc, const char *xpath) { xmlXPathContextPtr ctx = xmlXPathNewContext(doc); - if (!ctx) return NULL; + if (!ctx) + return NULL; xmlXPathObjectPtr obj = xmlXPathEvalExpression((const xmlChar *)xpath, ctx); xmlXPathFreeContext(ctx); if (!obj || !obj->nodesetval || obj->nodesetval->nodeNr == 0) { - if (obj) xmlXPathFreeObject(obj); + if (obj) + xmlXPathFreeObject(obj); return NULL; } xmlChar *content = xmlNodeGetContent(obj->nodesetval->nodeTab[0]); char *result = content ? strdup((char *)content) : NULL; - if (content) xmlFree(content); + if (content) + xmlFree(content); xmlXPathFreeObject(obj); return result; } -static char *build_html(const char *word, const char *pron, const char *pos, - const char *def, const char *ex) { +static char *build_html(const char *word, const char *pron, const char *pos, + const char *def, const char *ex) { char html[4096]; - int n = snprintf(html, sizeof(html), "<div class='dict-container' style='line-height: 1.6;'>"); - if (word) n += snprintf(html + n, sizeof(html) - n, - "<div style='font-size: 1.3em; font-weight: bold; margin-bottom: 4px;'>%s</div>", word); - if (pron) n += snprintf(html + n, sizeof(html) - n, - "<div style='color: #666; margin-bottom: 8px;'>/%s/</div>", pron); - if (pos) n += snprintf(html + n, sizeof(html) - n, - "<div style='font-style: italic; color: #888; margin-bottom: 8px;'>%s</div>", pos); - if (def) n += snprintf(html + n, sizeof(html) - n, - "<div style='margin-bottom: 8px;'>%s</div>", def); - if (ex) n += snprintf(html + n, sizeof(html) - n, - "<div style='color: #555; font-style: italic; margin-top: 8px;'>\"%s\"</div>", ex); + int n = snprintf(html, sizeof(html), + "<div class='dict-container' style='line-height: 1.6;'>"); + if (word) + n += snprintf(html + n, sizeof(html) - n, + "<div style='font-size: 1.3em; font-weight: bold; " + "margin-bottom: 4px;'>%s</div>", + word); + if (pron) + n += snprintf(html + n, sizeof(html) - n, + "<div style='color: #666; margin-bottom: 8px;'>/%s/</div>", + pron); + if (pos) + n += snprintf(html + n, sizeof(html) - n, + "<div style='font-style: italic; color: #888; margin-bottom: " + "8px;'>%s</div>", + pos); + if (def) + n += snprintf(html + n, sizeof(html) - n, + "<div style='margin-bottom: 8px;'>%s</div>", def); + if (ex) + n += snprintf(html + n, sizeof(html) - n, + "<div style='color: #555; font-style: italic; margin-top: " + "8px;'>\"%s\"</div>", + ex); snprintf(html + n, sizeof(html) - n, "</div>"); return strdup(html); } static char *extract_word(const char *query) { - if (!query) return NULL; + if (!query) + return NULL; const char *start = query; @@ -98,9 +134,11 @@ static char *extract_word(const char *query) { } } - while (*start == ' ') start++; + while (*start == ' ') + start++; char *word = strdup(start); - if (!word) return NULL; + if (!word) + return NULL; int changed = 1; while (changed) { @@ -130,29 +168,37 @@ static char *extract_word(const char *query) { } size_t len = strlen(word); - while (len > 0 && (word[len-1] == ' ' || word[len-1] == '?' || - word[len-1] == '!' || word[len-1] == '.')) { + while (len > 0 && (word[len - 1] == ' ' || word[len - 1] == '?' || + word[len - 1] == '!' || word[len - 1] == '.')) { word[--len] = '\0'; } - if (len == 0) { free(word); return NULL; } + if (len == 0) { + free(word); + return NULL; + } - for (size_t i = 0; i < len; i++) word[i] = tolower((unsigned char)word[i]); + for (size_t i = 0; i < len; i++) + word[i] = tolower((unsigned char)word[i]); char *space = strchr(word, ' '); - if (space) *space = '\0'; + if (space) + *space = '\0'; return word; } int is_dictionary_query(const char *query) { - if (!query) return 0; + if (!query) + return 0; for (int i = 0; PREFIXES[i]; i++) { size_t len = strlen(PREFIXES[i]); if (strncasecmp(query, PREFIXES[i], len) == 0) { const char *after = query + len; - while (*after == ' ') after++; - if (*after != '\0') return 1; + while (*after == ' ') + after++; + if (*after != '\0') + return 1; } } @@ -160,23 +206,29 @@ int is_dictionary_query(const char *query) { const char *pos = strcasestr_impl(query, SUFFIXES[i]); if (pos) { const char *after = pos + strlen(SUFFIXES[i]); - while (*after == ' ' || *after == '?' || *after == '!' || *after == '.') after++; - if (*after == '\0' && pos > query && (pos - query) < 100) return 1; + while (*after == ' ' || *after == '?' || *after == '!' || *after == '.') + after++; + if (*after == '\0' && pos > query && (pos - query) < 100) + return 1; } } - if (strncasecmp(query, "what is ", 8) == 0 || - strncasecmp(query, "what's ", 7) == 0 || - strncasecmp(query, "whats ", 6) == 0) { - const char *word = query + (strncasecmp(query, "what is ", 8) == 0 ? 8 : - strncasecmp(query, "what's ", 7) == 0 ? 7 : 6); - const char *articles[] = {"the ", "your ", "my ", "his ", "her ", "their ", - "our ", "this ", "that ", "these ", "those ", "a ", "an ", NULL}; + if (strncasecmp(query, "what is ", 8) == 0 || + strncasecmp(query, "what's ", 7) == 0 || + strncasecmp(query, "whats ", 6) == 0) { + const char *word = query + (strncasecmp(query, "what is ", 8) == 0 ? 8 + : strncasecmp(query, "what's ", 7) == 0 ? 7 + : 6); + const char *articles[] = {"the ", "your ", "my ", "his ", "her ", + "their ", "our ", "this ", "that ", "these ", + "those ", "a ", "an ", NULL}; for (int i = 0; articles[i]; i++) { - if (strncasecmp(word, articles[i], strlen(articles[i])) == 0) return 0; + if (strncasecmp(word, articles[i], strlen(articles[i])) == 0) + return 0; } const char *space = strchr(word, ' '); - if (!space || *(space + 1) == '\0' || *(space + 1) == '?') return 1; + if (!space || *(space + 1) == '\0' || *(space + 1) == '?') + return 1; } return 0; @@ -184,10 +236,14 @@ int is_dictionary_query(const char *query) { char *construct_dictionary_url(const char *query) { char *word = extract_word(query); - if (!word) return NULL; + if (!word) + return NULL; CURL *curl = curl_easy_init(); - if (!curl) { free(word); return NULL; } + if (!curl) { + free(word); + return NULL; + } char *escaped = curl_easy_escape(curl, word, 0); const char *base = "https://dictionary.cambridge.org/dictionary/english/"; @@ -207,10 +263,14 @@ InfoBox fetch_dictionary_data(const char *query) { InfoBox info = {NULL, NULL, NULL, NULL}; char *url = construct_dictionary_url(query); - if (!url) return info; + if (!url) + return info; CURL *curl = curl_easy_init(); - if (!curl) { free(url); return info; } + if (!curl) { + free(url); + return info; + } struct MemStruct chunk = {malloc(1), 0}; curl_easy_setopt(curl, CURLOPT_URL, url); @@ -222,10 +282,13 @@ InfoBox fetch_dictionary_data(const char *query) { if (curl_easy_perform(curl) == CURLE_OK && chunk.size > 0) { htmlDocPtr doc = htmlReadMemory(chunk.memory, chunk.size, url, NULL, - HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | HTML_PARSE_NOWARNING); + HTML_PARSE_RECOVER | HTML_PARSE_NOERROR | + HTML_PARSE_NOWARNING); if (doc) { char *word = xpath_text(doc, "//span[@class='hw dhw']"); - char *pron = xpath_text(doc, "//span[@class='us dpron-i']//span[@class='ipa dipa lpr-2 lpl-1']"); + char *pron = xpath_text( + doc, + "//span[@class='us dpron-i']//span[@class='ipa dipa lpr-2 lpl-1']"); char *pos = xpath_text(doc, "//span[@class='pos dpos']"); char *def = xpath_text(doc, "(//div[@class='def ddef_d db'])[1]"); char *ex = xpath_text(doc, "(//span[@class='eg deg'])[1]"); @@ -237,7 +300,11 @@ InfoBox fetch_dictionary_data(const char *query) { info.url = strdup(url); } - free(word); free(pron); free(pos); free(def); free(ex); + free(word); + free(pron); + free(pos); + free(def); + free(ex); xmlFreeDoc(doc); } } @@ -246,4 +313,4 @@ InfoBox fetch_dictionary_data(const char *query) { free(chunk.memory); free(url); return info; -}
\ No newline at end of file +} diff --git a/src/Infobox/Dictionary.h b/src/Infobox/Dictionary.h index 2f212c3..862edba 100644 --- a/src/Infobox/Dictionary.h +++ b/src/Infobox/Dictionary.h @@ -7,4 +7,4 @@ InfoBox fetch_dictionary_data(const char *word); char *construct_dictionary_url(const char *word); int is_dictionary_query(const char *query); -#endif
\ No newline at end of file +#endif diff --git a/src/Infobox/UnitConversion.c b/src/Infobox/UnitConversion.c index 933dd71..4269f3c 100644 --- a/src/Infobox/UnitConversion.c +++ b/src/Infobox/UnitConversion.c @@ -23,49 +23,73 @@ typedef struct { } UnitDef; static const UnitDef UNITS[] = { - {"metre", {"m", "metres", "meter", "meters"}, UNIT_LENGTH, 1.0}, - {"kilometre", {"km", "kilometres", "kilometer", "kilometers"}, UNIT_LENGTH, 1000.0}, - {"centimetre", {"cm", "centimetres", "centimeter", "centimeters"}, UNIT_LENGTH, 0.01}, - {"millimetre", {"mm", "millimetres", "millimeter", "millimeters"}, UNIT_LENGTH, 0.001}, - {"mile", {"mi", "miles"}, UNIT_LENGTH, 1609.344}, - {"yard", {"yd", "yards"}, UNIT_LENGTH, 0.9144}, - {"foot", {"ft", "feet", "'"}, UNIT_LENGTH, 0.3048}, - {"inch", {"in", "inches", "\""}, UNIT_LENGTH, 0.0254}, - - {"kilogram", {"kg", "kilograms", "kilo", "kilos"}, UNIT_WEIGHT, 1.0}, - {"gram", {"g", "grams"}, UNIT_WEIGHT, 0.001}, - {"milligram", {"mg", "milligrams"}, UNIT_WEIGHT, 0.000001}, - {"pound", {"lb", "lbs", "pounds"}, UNIT_WEIGHT, 0.453592}, - {"ounce", {"oz", "ounces"}, UNIT_WEIGHT, 0.0283495}, - {"tonne", {"tonnes", "tons", "ton"}, UNIT_WEIGHT, 1000.0}, - {"stone", {"st", "stones"}, UNIT_WEIGHT, 6.35029}, - - {"celsius", {"c", "°c", "degrees celsius", "degrees c"}, UNIT_TEMP, 1.0}, - {"fahrenheit", {"f", "°f", "degrees fahrenheit", "degrees f"}, UNIT_TEMP, 1.0}, - {"kelvin", {"k", "degrees kelvin", "degrees k"}, UNIT_TEMP, 1.0}, - - {"litre", {"l", "litres", "liter", "liters"}, UNIT_VOLUME, 1.0}, - {"millilitre", {"ml", "millilitres", "milliliter", "milliliters"}, UNIT_VOLUME, 0.001}, - {"gallon", {"gal", "gallons"}, UNIT_VOLUME, 3.78541}, - {"quart", {"qt", "quarts"}, UNIT_VOLUME, 0.946353}, - {"pint", {"pt", "pints"}, UNIT_VOLUME, 0.473176}, - {"cup", {"cups"}, UNIT_VOLUME, 0.236588}, - {"fluid ounce", {"fl oz", "fluid ounces"}, UNIT_VOLUME, 0.0295735}, - - {"square metre", {"sqm", "sq m", "m2", "square metres"}, UNIT_AREA, 1.0}, - {"square foot", {"sqft", "sq ft", "ft2", "square feet"}, UNIT_AREA, 0.092903}, - {"square kilometre", {"sqkm", "sq km", "km2", "square kilometres"}, UNIT_AREA, 1000000.0}, - {"square mile", {"sqmi", "sq mi", "mi2", "square miles"}, UNIT_AREA, 2589988.0}, - {"acre", {"acres"}, UNIT_AREA, 4046.86}, - {"hectare", {"ha", "hectares"}, UNIT_AREA, 10000.0}, - - {"second", {"sec", "seconds", "s"}, UNIT_TIME, 1.0}, - {"minute", {"min", "minutes"}, UNIT_TIME, 60.0}, - {"hour", {"hr", "hours", "h"}, UNIT_TIME, 3600.0}, - {"day", {"days", "d"}, UNIT_TIME, 86400.0}, - {"week", {"weeks", "wk"}, UNIT_TIME, 604800.0}, - {"month", {"months", "mo"}, UNIT_TIME, 2629746.0}, - {"year", {"years", "yr"}, UNIT_TIME, 31556952.0}, + {"metre", {"m", "metres", "meter", "meters"}, UNIT_LENGTH, 1.0}, + {"kilometre", + {"km", "kilometres", "kilometer", "kilometers"}, + UNIT_LENGTH, + 1000.0}, + {"centimetre", + {"cm", "centimetres", "centimeter", "centimeters"}, + UNIT_LENGTH, + 0.01}, + {"millimetre", + {"mm", "millimetres", "millimeter", "millimeters"}, + UNIT_LENGTH, + 0.001}, + {"mile", {"mi", "miles"}, UNIT_LENGTH, 1609.344}, + {"yard", {"yd", "yards"}, UNIT_LENGTH, 0.9144}, + {"foot", {"ft", "feet", "'"}, UNIT_LENGTH, 0.3048}, + {"inch", {"in", "inches", "\""}, UNIT_LENGTH, 0.0254}, + + {"kilogram", {"kg", "kilograms", "kilo", "kilos"}, UNIT_WEIGHT, 1.0}, + {"gram", {"g", "grams"}, UNIT_WEIGHT, 0.001}, + {"milligram", {"mg", "milligrams"}, UNIT_WEIGHT, 0.000001}, + {"pound", {"lb", "lbs", "pounds"}, UNIT_WEIGHT, 0.453592}, + {"ounce", {"oz", "ounces"}, UNIT_WEIGHT, 0.0283495}, + {"tonne", {"tonnes", "tons", "ton"}, UNIT_WEIGHT, 1000.0}, + {"stone", {"st", "stones"}, UNIT_WEIGHT, 6.35029}, + + {"celsius", {"c", "°c", "degrees celsius", "degrees c"}, UNIT_TEMP, 1.0}, + {"fahrenheit", + {"f", "°f", "degrees fahrenheit", "degrees f"}, + UNIT_TEMP, + 1.0}, + {"kelvin", {"k", "degrees kelvin", "degrees k"}, UNIT_TEMP, 1.0}, + + {"litre", {"l", "litres", "liter", "liters"}, UNIT_VOLUME, 1.0}, + {"millilitre", + {"ml", "millilitres", "milliliter", "milliliters"}, + UNIT_VOLUME, + 0.001}, + {"gallon", {"gal", "gallons"}, UNIT_VOLUME, 3.78541}, + {"quart", {"qt", "quarts"}, UNIT_VOLUME, 0.946353}, + {"pint", {"pt", "pints"}, UNIT_VOLUME, 0.473176}, + {"cup", {"cups"}, UNIT_VOLUME, 0.236588}, + {"fluid ounce", {"fl oz", "fluid ounces"}, UNIT_VOLUME, 0.0295735}, + + {"square metre", {"sqm", "sq m", "m2", "square metres"}, UNIT_AREA, 1.0}, + {"square foot", + {"sqft", "sq ft", "ft2", "square feet"}, + UNIT_AREA, + 0.092903}, + {"square kilometre", + {"sqkm", "sq km", "km2", "square kilometres"}, + UNIT_AREA, + 1000000.0}, + {"square mile", + {"sqmi", "sq mi", "mi2", "square miles"}, + UNIT_AREA, + 2589988.0}, + {"acre", {"acres"}, UNIT_AREA, 4046.86}, + {"hectare", {"ha", "hectares"}, UNIT_AREA, 10000.0}, + + {"second", {"sec", "seconds", "s"}, UNIT_TIME, 1.0}, + {"minute", {"min", "minutes"}, UNIT_TIME, 60.0}, + {"hour", {"hr", "hours", "h"}, UNIT_TIME, 3600.0}, + {"day", {"days", "d"}, UNIT_TIME, 86400.0}, + {"week", {"weeks", "wk"}, UNIT_TIME, 604800.0}, + {"month", {"months", "mo"}, UNIT_TIME, 2629746.0}, + {"year", {"years", "yr"}, UNIT_TIME, 31556952.0}, }; static const int UNIT_COUNT = sizeof(UNITS) / sizeof(UNITS[0]); @@ -75,136 +99,142 @@ static int is_whitespace(char c) { } static const UnitDef *find_unit(const char *str) { - if (!str || !*str) return NULL; + if (!str || !*str) + return NULL; size_t len = strlen(str); char normalized[64] = {0}; size_t j = 0; for (size_t i = 0; i < len && j < 63; i++) { - if ((unsigned char)str[i] == 0xC2 && (unsigned char)str[i+1] == 0xB0) { - i++; - continue; - } - if (str[i] == '^' && i + 1 < len && str[i + 1] == '2') { - normalized[j++] = '2'; - i++; - continue; - } - normalized[j++] = tolower((unsigned char)str[i]); + if ((unsigned char)str[i] == 0xC2 && (unsigned char)str[i + 1] == 0xB0) { + i++; + continue; + } + if (str[i] == '^' && i + 1 < len && str[i + 1] == '2') { + normalized[j++] = '2'; + i++; + continue; + } + normalized[j++] = tolower((unsigned char)str[i]); } normalized[j] = '\0'; for (int i = 0; i < UNIT_COUNT; i++) { - if (strcmp(normalized, UNITS[i].name) == 0) return &UNITS[i]; - for (int k = 0; k < 4 && UNITS[i].alias[k]; k++) { - if (strcmp(normalized, UNITS[i].alias[k]) == 0) return &UNITS[i]; - } + if (strcmp(normalized, UNITS[i].name) == 0) + return &UNITS[i]; + for (int k = 0; k < 4 && UNITS[i].alias[k]; k++) { + if (strcmp(normalized, UNITS[i].alias[k]) == 0) + return &UNITS[i]; + } } return NULL; } int is_unit_conv_query(const char *query) { - if (!query) return 0; + if (!query) + return 0; - const char *patterns[] = { - " to ", " in ", " into ", - " = ", " equals ", " equal ", - " convert ", " conversion ", - " -> ", " → ", - NULL - }; + const char *patterns[] = {" to ", " in ", " into ", " = ", + " equals ", " equal ", " convert ", " conversion ", + " -> ", " → ", NULL}; int has_pattern = 0; for (int i = 0; patterns[i]; i++) { - if (strstr(query, patterns[i])) { - has_pattern = 1; - break; - } + if (strstr(query, patterns[i])) { + has_pattern = 1; + break; + } } if (!has_pattern) { - const char *last_space = strrchr(query, ' '); - if (last_space) { - const UnitDef *u = find_unit(last_space + 1); - if (u) { - const char *before = query; - while (*before && is_whitespace(*before)) before++; - const char *num_end = before; - while (*num_end && - (isdigit(*num_end) || *num_end == '.' || *num_end == '-' || - *num_end == '+' || *num_end == '/' || *num_end == '\'' || *num_end == '"')) { - num_end++; - } - if (num_end > before) has_pattern = 1; + const char *last_space = strrchr(query, ' '); + if (last_space) { + const UnitDef *u = find_unit(last_space + 1); + if (u) { + const char *before = query; + while (*before && is_whitespace(*before)) + before++; + const char *num_end = before; + while (*num_end && + (isdigit(*num_end) || *num_end == '.' || *num_end == '-' || + *num_end == '+' || *num_end == '/' || *num_end == '\'' || + *num_end == '"')) { + num_end++; + } + if (num_end > before) + has_pattern = 1; + } } } - } return has_pattern; } static double parse_value(const char **ptr) { const char *p = *ptr; - while (*p && is_whitespace(*p)) p++; + while (*p && is_whitespace(*p)) + p++; double value = 0.0; int has_num = 0; - if (*p == '-' || *p == '+') p++; - while (*p >= '0' && *p <= '9') { - value = value * 10 + (*p - '0'); - has_num = 1; - p++; - } - if (*p == '.') { - p++; - double frac = 0.1; + if (*p == '-' || *p == '+') + p++; while (*p >= '0' && *p <= '9') { - value += (*p - '0') * frac; - frac *= 0.1; + value = value * 10 + (*p - '0'); has_num = 1; p++; } + if (*p == '.') { + p++; + double frac = 0.1; + while (*p >= '0' && *p <= '9') { + value += (*p - '0') * frac; + frac *= 0.1; + has_num = 1; + p++; + } } if (*p == '/' && has_num) { - p++; - double denom = 0.0; - int has_denom = 0; - while (*p >= '0' && *p <= '9') { - denom = denom * 10 + (*p - '0'); - has_denom = 1; p++; - } - if (has_denom && denom > 0) { - value = value / denom; - } + double denom = 0.0; + int has_denom = 0; + while (*p >= '0' && *p <= '9') { + denom = denom * 10 + (*p - '0'); + has_denom = 1; + p++; + } + if (has_denom && denom > 0) { + value = value / denom; + } } while (*p == '\'' || *p == '"') { - double extra = 0.0; - p++; - while (*p >= '0' && *p <= '9') { - extra = extra * 10 + (*p - '0'); + double extra = 0.0; p++; - } - if (*p == '.') { - p++; - double frac = 0.1; while (*p >= '0' && *p <= '9') { - extra += (*p - '0') * frac; - frac *= 0.1; - p++; + extra = extra * 10 + (*p - '0'); + p++; } - } - if (*p == '\'' || *p == '"') p++; - value += extra * (p[-1] == '\'' ? 0.3048 : 0.0254); + if (*p == '.') { + p++; + double frac = 0.1; + while (*p >= '0' && *p <= '9') { + extra += (*p - '0') * frac; + frac *= 0.1; + p++; + } + } + if (*p == '\'' || *p == '"') + p++; + value += extra * (p[-1] == '\'' ? 0.3048 : 0.0254); } if (!has_num) { - *ptr = p; - return 0.0; + *ptr = p; + return 0.0; } *ptr = p; @@ -212,10 +242,13 @@ static double parse_value(const char **ptr) { } static int is_separator(char c) { - return is_whitespace(c) || c == ',' || c == '.' || c == '(' || c == ')' || c == '\0'; + return is_whitespace(c) || c == ',' || c == '.' || c == '(' || c == ')' || + c == '\0'; } -static int parse_conversion_query(const char *query, double *value, const UnitDef **from_unit, const UnitDef **to_unit) { +static int parse_conversion_query(const char *query, double *value, + const UnitDef **from_unit, + const UnitDef **to_unit) { *value = 0; *from_unit = NULL; *to_unit = NULL; @@ -223,127 +256,151 @@ static int parse_conversion_query(const char *query, double *value, const UnitDe const char *value_end = query; *value = parse_value(&value_end); - if (value_end == query) return 0; + if (value_end == query) + return 0; const char *p = value_end; - while (*p && is_whitespace(*p)) p++; + while (*p && is_whitespace(*p)) + p++; size_t remaining = strlen(p); - if (remaining < 2) return 0; + if (remaining < 2) + return 0; - const char *to_keywords[] = {" to ", " in ", " into ", " -> ", " → ", " = ", NULL}; + const char *to_keywords[] = {" to ", " in ", " into ", " -> ", + " → ", " = ", NULL}; const char *to_pos = NULL; size_t keyword_len = 0; for (int i = 0; to_keywords[i]; i++) { - const char *found = strstr(p, to_keywords[i]); - if (found) { - to_pos = found + strlen(to_keywords[i]); - keyword_len = strlen(to_keywords[i]); - break; - } + const char *found = strstr(p, to_keywords[i]); + if (found) { + to_pos = found + strlen(to_keywords[i]); + keyword_len = strlen(to_keywords[i]); + break; + } } if (!to_pos) { - const char *last_space = strrchr(p, ' '); - if (last_space && last_space > p) { - char from_part[64] = {0}; - size_t len = last_space - p; - if (len < 63) { - strncpy(from_part, p, len); - *from_unit = find_unit(from_part); - if (*from_unit) { - *to_unit = find_unit(last_space + 1); - return *to_unit ? 1 : 0; - } + const char *last_space = strrchr(p, ' '); + if (last_space && last_space > p) { + char from_part[64] = {0}; + size_t len = last_space - p; + if (len < 63) { + strncpy(from_part, p, len); + *from_unit = find_unit(from_part); + if (*from_unit) { + *to_unit = find_unit(last_space + 1); + return *to_unit ? 1 : 0; + } + } } - } - return 0; + return 0; } char from_part[64] = {0}; size_t from_len = to_pos - p - keyword_len; - if (from_len > 63) from_len = 63; + if (from_len > 63) + from_len = 63; strncpy(from_part, p, from_len); char *end_from = from_part + from_len; - while (end_from > from_part && is_whitespace(end_from[-1])) end_from--; + while (end_from > from_part && is_whitespace(end_from[-1])) + end_from--; *end_from = '\0'; *from_unit = find_unit(from_part); if (!*from_unit) { - char *end = from_part + strlen(from_part); - while (end > from_part) { - while (end > from_part && is_whitespace(end[-1])) end--; - if (end <= from_part) break; - char *start = end; - while (start > from_part && !is_whitespace(start[-1])) start--; - size_t word_len = end - start; - memmove(from_part + word_len + 1, from_part, start - from_part); - from_part[word_len] = ' '; - from_part[word_len + 1] = '\0'; - *from_unit = find_unit(from_part); - if (*from_unit) break; - end = start; - } + char *end = from_part + strlen(from_part); + while (end > from_part) { + while (end > from_part && is_whitespace(end[-1])) + end--; + if (end <= from_part) + break; + char *start = end; + while (start > from_part && !is_whitespace(start[-1])) + start--; + size_t word_len = end - start; + memmove(from_part + word_len + 1, from_part, start - from_part); + from_part[word_len] = ' '; + from_part[word_len + 1] = '\0'; + *from_unit = find_unit(from_part); + if (*from_unit) + break; + end = start; + } } - if (!*from_unit) return 0; + if (!*from_unit) + return 0; - while (*to_pos && is_whitespace(*to_pos)) to_pos++; + while (*to_pos && is_whitespace(*to_pos)) + to_pos++; - if (!*to_pos) return 0; + if (!*to_pos) + return 0; char to_part[64] = {0}; size_t to_len = 0; const char *tp = to_pos; while (*tp && !is_separator(*tp) && to_len < 63) { - to_part[to_len++] = *tp++; + to_part[to_len++] = *tp++; } to_part[to_len] = '\0'; *to_unit = find_unit(to_part); if (!*to_unit) { - const char *try_ptr = to_pos; - while (*try_ptr && is_whitespace(*try_ptr)) try_ptr++; - char try_buf[64] = {0}; - size_t try_len = 0; - while (*try_ptr && try_len < 63) { - try_buf[try_len++] = *try_ptr++; - } - while (try_len > 0) { - *to_unit = find_unit(try_buf); - if (*to_unit) { - strcpy(to_part, try_buf); - break; + const char *try_ptr = to_pos; + while (*try_ptr && is_whitespace(*try_ptr)) + try_ptr++; + char try_buf[64] = {0}; + size_t try_len = 0; + while (*try_ptr && try_len < 63) { + try_buf[try_len++] = *try_ptr++; + } + while (try_len > 0) { + *to_unit = find_unit(try_buf); + if (*to_unit) { + strcpy(to_part, try_buf); + break; + } + char *last_space = strrchr(try_buf, ' '); + if (!last_space) + break; + *last_space = '\0'; + try_len = strlen(try_buf); } - char *last_space = strrchr(try_buf, ' '); - if (!last_space) break; - *last_space = '\0'; - try_len = strlen(try_buf); - } } return *to_unit ? 1 : 0; } -static double convert_temp(double value, const UnitDef *from, const UnitDef *to) { +static double convert_temp(double value, const UnitDef *from, + const UnitDef *to) { double celsius = 0; - if (strcmp(from->name, "celsius") == 0) celsius = value; - else if (strcmp(from->name, "fahrenheit") == 0) celsius = (value - 32) * 5.0 / 9.0; - else if (strcmp(from->name, "kelvin") == 0) celsius = value - 273.15; - - if (strcmp(to->name, "celsius") == 0) return celsius; - else if (strcmp(to->name, "fahrenheit") == 0) return celsius * 9.0 / 5.0 + 32; - else if (strcmp(to->name, "kelvin") == 0) return celsius + 273.15; + if (strcmp(from->name, "celsius") == 0) + celsius = value; + else if (strcmp(from->name, "fahrenheit") == 0) + celsius = (value - 32) * 5.0 / 9.0; + else if (strcmp(from->name, "kelvin") == 0) + celsius = value - 273.15; + + if (strcmp(to->name, "celsius") == 0) + return celsius; + else if (strcmp(to->name, "fahrenheit") == 0) + return celsius * 9.0 / 5.0 + 32; + else if (strcmp(to->name, "kelvin") == 0) + return celsius + 273.15; return 0; } -static double convert_value(double value, const UnitDef *from, const UnitDef *to) { - if (from->type != to->type) return 0; +static double convert_value(double value, const UnitDef *from, + const UnitDef *to) { + if (from->type != to->type) + return 0; if (from->type == UNIT_TEMP) { - return convert_temp(value, from, to); + return convert_temp(value, from, to); } double base_value = value * from->to_base; @@ -351,112 +408,124 @@ static double convert_value(double value, const UnitDef *from, const UnitDef *to } static void format_number(double val, char *buf, size_t bufsize) { - if (bufsize == 0) return; + if (bufsize == 0) + return; if (val == 0) { - snprintf(buf, bufsize, "0"); - return; + snprintf(buf, bufsize, "0"); + return; } if (fabs(val) < 0.01 && fabs(val) > 0) { - snprintf(buf, bufsize, "%.2g", val); + snprintf(buf, bufsize, "%.2g", val); } else if (fabs(val) < 1) { - snprintf(buf, bufsize, "%.2f", val); - char *p = buf + strlen(buf) - 1; - while (p > buf && *p == '0') *p-- = '\0'; - if (*p == '.') *p = '\0'; + snprintf(buf, bufsize, "%.2f", val); + char *p = buf + strlen(buf) - 1; + while (p > buf && *p == '0') + *p-- = '\0'; + if (*p == '.') + *p = '\0'; } else if (fmod(val + 0.0001, 1.0) < 0.0002) { - snprintf(buf, bufsize, "%.0f", val); + snprintf(buf, bufsize, "%.0f", val); } else { - snprintf(buf, bufsize, "%.2f", val); - char *p = buf + strlen(buf) - 1; - while (p > buf && *p == '0') *p-- = '\0'; - if (*p == '.') *p = '\0'; + snprintf(buf, bufsize, "%.2f", val); + char *p = buf + strlen(buf) - 1; + while (p > buf && *p == '0') + *p-- = '\0'; + if (*p == '.') + *p = '\0'; } } -static const char *pluralize(const char *unit, double value, char *buf, size_t bufsize) { +static const char *pluralize(const char *unit, double value, char *buf, + size_t bufsize) { int is_one = (fabs(value - 1.0) < 0.0001 || fabs(value + 1.0) < 0.0001); size_t len = strlen(unit); - if (len == 0 || bufsize == 0) return unit; + if (len == 0 || bufsize == 0) + return unit; strncpy(buf, unit, bufsize - 1); buf[bufsize - 1] = '\0'; if (strcmp(unit, "foot") == 0 || strcmp(unit, "square foot") == 0) { - if (is_one) strcpy(buf, unit); - else strcpy(buf, strcmp(unit, "square foot") == 0 ? "square feet" : "feet"); - return buf; + if (is_one) + strcpy(buf, unit); + else + strcpy(buf, strcmp(unit, "square foot") == 0 ? "square feet" : "feet"); + return buf; } if (strcmp(unit, "inch") == 0 || strcmp(unit, "square inch") == 0) { - if (is_one) strcpy(buf, unit); - else strcpy(buf, strcmp(unit, "square inch") == 0 ? "square inches" : "inches"); - return buf; + if (is_one) + strcpy(buf, unit); + else + strcpy(buf, + strcmp(unit, "square inch") == 0 ? "square inches" : "inches"); + return buf; } if (strcmp(unit, "stone") == 0) { - if (is_one) strcpy(buf, "stone"); - else strcpy(buf, "stones"); - return buf; - } - if (strcmp(unit, "celsius") == 0 || - strcmp(unit, "fahrenheit") == 0 || - strcmp(unit, "kelvin") == 0) { - strcpy(buf, unit); - return buf; - } - - if (unit[len-1] == 's' || - unit[len-1] == 'x' || - unit[len-1] == 'z' || - (len >= 2 && unit[len-2] == 'c' && unit[len-1] == 'h') || - (len >= 2 && unit[len-2] == 's' && unit[len-1] == 'h')) { - if (!is_one) { - buf[len] = 'e'; - buf[len+1] = '\0'; - } - } else if (unit[len-1] == 'y' && len >= 2 && - !(unit[len-2] == 'a' || unit[len-2] == 'e' || - unit[len-2] == 'i' || unit[len-2] == 'o' || - unit[len-2] == 'u')) { - if (is_one) { - buf[len-1] = '\0'; - } else { - buf[len] = 's'; - buf[len+1] = '\0'; - } - } else if (len >= 2 && unit[len-2] == 'f' && unit[len-1] == 'e') { - if (is_one) { - buf[len-2] = '\0'; - } else { - buf[len-1] = 's'; - buf[len] = '\0'; - } - } else if (unit[len-1] == 'f' && len >= 1) { - if (is_one) { - buf[len-1] = '\0'; - } else { - buf[len-1] = 'v'; - buf[len] = 'e'; - buf[len+1] = 's'; - buf[len+2] = '\0'; - } - } else if (unit[len-1] == 'e' && len >= 2 && unit[len-2] == 'f') { - if (is_one) { - buf[len-2] = '\0'; - } else { - buf[len-1] = 's'; - buf[len] = '\0'; - } + if (is_one) + strcpy(buf, "stone"); + else + strcpy(buf, "stones"); + return buf; + } + if (strcmp(unit, "celsius") == 0 || strcmp(unit, "fahrenheit") == 0 || + strcmp(unit, "kelvin") == 0) { + strcpy(buf, unit); + return buf; + } + + if (unit[len - 1] == 's' || unit[len - 1] == 'x' || unit[len - 1] == 'z' || + (len >= 2 && unit[len - 2] == 'c' && unit[len - 1] == 'h') || + (len >= 2 && unit[len - 2] == 's' && unit[len - 1] == 'h')) { + if (!is_one) { + buf[len] = 'e'; + buf[len + 1] = '\0'; + } + } else if (unit[len - 1] == 'y' && len >= 2 && + !(unit[len - 2] == 'a' || unit[len - 2] == 'e' || + unit[len - 2] == 'i' || unit[len - 2] == 'o' || + unit[len - 2] == 'u')) { + if (is_one) { + buf[len - 1] = '\0'; + } else { + buf[len] = 's'; + buf[len + 1] = '\0'; + } + } else if (len >= 2 && unit[len - 2] == 'f' && unit[len - 1] == 'e') { + if (is_one) { + buf[len - 2] = '\0'; + } else { + buf[len - 1] = 's'; + buf[len] = '\0'; + } + } else if (unit[len - 1] == 'f' && len >= 1) { + if (is_one) { + buf[len - 1] = '\0'; + } else { + buf[len - 1] = 'v'; + buf[len] = 'e'; + buf[len + 1] = 's'; + buf[len + 2] = '\0'; + } + } else if (unit[len - 1] == 'e' && len >= 2 && unit[len - 2] == 'f') { + if (is_one) { + buf[len - 2] = '\0'; + } else { + buf[len - 1] = 's'; + buf[len] = '\0'; + } } else { - if (!is_one) { - buf[len] = 's'; - buf[len+1] = '\0'; - } + if (!is_one) { + buf[len] = 's'; + buf[len + 1] = '\0'; + } } return buf; } -static char *build_html(double value, const UnitDef *from, double result, const UnitDef *to) { +static char *build_html(double value, const UnitDef *from, double result, + const UnitDef *to) { static char html[4096]; char val_buf[64], res_buf[64], from_name_buf[64], to_name_buf[64]; format_number(value, val_buf, sizeof(val_buf)); @@ -466,30 +535,34 @@ static char *build_html(double value, const UnitDef *from, double result, const pluralize(to->name, result, to_name_buf, sizeof(to_name_buf)); int n = snprintf(html, sizeof(html), - "<div class='unit-conv-container' style='line-height: 1.6;'>" - "<div style='font-size: 1.3em; margin-bottom: 8px;'>" - "<b>%s %s</b> = <b>%s %s</b>" - "</div>", - val_buf, from_name_buf, - res_buf, to_name_buf); + "<div class='unit-conv-container' style='line-height: 1.6;'>" + "<div style='font-size: 1.3em; margin-bottom: 8px;'>" + "<b>%s %s</b> = <b>%s %s</b>" + "</div>", + val_buf, from_name_buf, res_buf, to_name_buf); snprintf(html + n, sizeof(html) - n, "</div>"); return html; } InfoBox fetch_unit_conv_data(const char *query) { InfoBox info = {NULL, NULL, NULL, NULL}; - if (!query) return info; + if (!query) + return info; double value = 0; const UnitDef *from = NULL; const UnitDef *to = NULL; - if (!parse_conversion_query(query, &value, &from, &to)) return info; - if (!from || !to) return info; - if (from->type != to->type) return info; + if (!parse_conversion_query(query, &value, &from, &to)) + return info; + if (!from || !to) + return info; + if (from->type != to->type) + return info; double result = convert_value(value, from, to); - if (result == 0 && value != 0 && from->type != UNIT_TEMP) return info; + if (result == 0 && value != 0 && from->type != UNIT_TEMP) + return info; info.title = strdup("Unit Conversion"); info.extract = strdup(build_html(value, from, result, to)); diff --git a/src/Infobox/Wikipedia.c b/src/Infobox/Wikipedia.c index 09c13c6..ffcc75b 100644 --- a/src/Infobox/Wikipedia.c +++ b/src/Infobox/Wikipedia.c @@ -14,41 +14,43 @@ struct WikiMemoryStruct { }; static void shorten_summary(char **extract_ptr, int max_chars) { - if (!extract_ptr || !*extract_ptr) return; + if (!extract_ptr || !*extract_ptr) + return; char *text = *extract_ptr; int len = strlen(text); - if (len <= max_chars) return; + if (len <= max_chars) + return; int end_pos = max_chars; for (int i = max_chars; i > (max_chars / 2); i--) { - if (text[i] == '.' || text[i] == '!' || text[i] == '?') { - end_pos = i + 1; - break; - } + if (text[i] == '.' || text[i] == '!' || text[i] == '?') { + end_pos = i + 1; + break; + } } char *new_text = (char *)malloc(end_pos + 4); if (new_text) { - strncpy(new_text, text, end_pos); - new_text[end_pos] = '\0'; - strcat(new_text, "..."); - free(*extract_ptr); - *extract_ptr = new_text; + strncpy(new_text, text, end_pos); + new_text[end_pos] = '\0'; + strcat(new_text, "..."); + free(*extract_ptr); + *extract_ptr = new_text; } } static size_t WikiWriteMemoryCallback(void *contents, size_t size, size_t nmemb, - void *userp) { + void *userp) { size_t realsize = size * nmemb; struct WikiMemoryStruct *mem = (struct WikiMemoryStruct *)userp; char *ptr = realloc(mem->memory, mem->size + realsize + 1); if (ptr == NULL) { - fprintf(stderr, "Not enough memory (realloc returned NULL)\n"); - return 0; + fprintf(stderr, "Not enough memory (realloc returned NULL)\n"); + return 0; } mem->memory = ptr; @@ -63,48 +65,49 @@ static void extract_wiki_info(xmlNode *node, InfoBox *info) { xmlNode *cur_node = NULL; for (cur_node = node; cur_node; cur_node = cur_node->next) { - if (cur_node->type == XML_ELEMENT_NODE) { - if (strcmp((const char *)cur_node->name, "page") == 0) { - xmlChar *title = xmlGetProp(cur_node, (const xmlChar *)"title"); - if (title) { - info->title = strdup((const char *)title); - - const char *base_article_url = "https://en.wikipedia.org/wiki/"; - char *formatted_title = strdup((const char *)title); - for (int i = 0; formatted_title[i]; i++) { - if (formatted_title[i] == ' ') formatted_title[i] = '_'; + if (cur_node->type == XML_ELEMENT_NODE) { + if (strcmp((const char *)cur_node->name, "page") == 0) { + xmlChar *title = xmlGetProp(cur_node, (const xmlChar *)"title"); + if (title) { + info->title = strdup((const char *)title); + + const char *base_article_url = "https://en.wikipedia.org/wiki/"; + char *formatted_title = strdup((const char *)title); + for (int i = 0; formatted_title[i]; i++) { + if (formatted_title[i] == ' ') + formatted_title[i] = '_'; + } + + info->url = + malloc(strlen(base_article_url) + strlen(formatted_title) + 1); + if (info->url) { + strcpy(info->url, base_article_url); + strcat(info->url, formatted_title); + } + free(formatted_title); + xmlFree(title); + } } - info->url = - malloc(strlen(base_article_url) + strlen(formatted_title) + 1); - if (info->url) { - strcpy(info->url, base_article_url); - strcat(info->url, formatted_title); + if (strcmp((const char *)cur_node->name, "thumbnail") == 0) { + xmlChar *source = xmlGetProp(cur_node, (const xmlChar *)"source"); + if (source) { + info->thumbnail_url = strdup((const char *)source); + xmlFree(source); + } } - free(formatted_title); - xmlFree(title); - } - } - - if (strcmp((const char *)cur_node->name, "thumbnail") == 0) { - xmlChar *source = xmlGetProp(cur_node, (const xmlChar *)"source"); - if (source) { - info->thumbnail_url = strdup((const char *)source); - xmlFree(source); - } - } - if (strcmp((const char *)cur_node->name, "extract") == 0) { - xmlChar *content = xmlNodeGetContent(cur_node); - if (content) { - info->extract = strdup((const char *)content); + if (strcmp((const char *)cur_node->name, "extract") == 0) { + xmlChar *content = xmlNodeGetContent(cur_node); + if (content) { + info->extract = strdup((const char *)content); - shorten_summary(&(info->extract), 300); - xmlFree(content); - } + shorten_summary(&(info->extract), 300); + xmlFree(content); + } + } } - } - extract_wiki_info(cur_node->children, info); + extract_wiki_info(cur_node->children, info); } } @@ -120,27 +123,27 @@ InfoBox fetch_wiki_data(char *api_url) { curl_handle = curl_easy_init(); if (curl_handle) { - curl_easy_setopt(curl_handle, CURLOPT_URL, api_url); - curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, - WikiWriteMemoryCallback); - curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); - curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); - apply_proxy_settings(curl_handle); - - res = curl_easy_perform(curl_handle); - - if (res == CURLE_OK) { - xmlDocPtr doc = - xmlReadMemory(chunk.memory, chunk.size, "noname.xml", NULL, 0); - if (doc != NULL) { - xmlNode *root_element = xmlDocGetRootElement(doc); - extract_wiki_info(root_element, &info); - xmlFreeDoc(doc); + curl_easy_setopt(curl_handle, CURLOPT_URL, api_url); + curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, + WikiWriteMemoryCallback); + curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk); + curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0"); + apply_proxy_settings(curl_handle); + + res = curl_easy_perform(curl_handle); + + if (res == CURLE_OK) { + xmlDocPtr doc = + xmlReadMemory(chunk.memory, chunk.size, "noname.xml", NULL, 0); + if (doc != NULL) { + xmlNode *root_element = xmlDocGetRootElement(doc); + extract_wiki_info(root_element, &info); + xmlFreeDoc(doc); + } } - } - curl_easy_cleanup(curl_handle); - free(chunk.memory); + curl_easy_cleanup(curl_handle); + free(chunk.memory); } return info; @@ -148,18 +151,18 @@ InfoBox fetch_wiki_data(char *api_url) { char *construct_wiki_url(const char *search_term) { CURL *curl = curl_easy_init(); - if (!curl) return NULL; + if (!curl) + return NULL; char *escaped_term = curl_easy_escape(curl, search_term, 0); - const char *base = - "https://en.wikipedia.org/w/" - "api.php?action=query&prop=extracts|pageimages&exintro&" - "explaintext&pithumbsize=400&format=xml&origin=*&titles="; + const char *base = "https://en.wikipedia.org/w/" + "api.php?action=query&prop=extracts|pageimages&exintro&" + "explaintext&pithumbsize=400&format=xml&origin=*&titles="; char *full_url = malloc(strlen(base) + strlen(escaped_term) + 1); if (full_url) { - strcpy(full_url, base); - strcat(full_url, escaped_term); + strcpy(full_url, base); + strcat(full_url, escaped_term); } curl_free(escaped_term); |
