diff --git a/Makefile b/Makefile index 9dbfd0b..ac93c55 100644 --- a/Makefile +++ b/Makefile @@ -23,10 +23,6 @@ ${exe}: ${objs} @echo "Linking $@ ..." @${CC} ${ldflags} -o $@ $^ ${libs} -${exe}-static: ${srcs} - @echo "Statically linking $@ ..." - @${CC} ${cflags} ${ldflags} -s -static -o $@ $^ - $O%.o: %.c @echo " Compiling $< ..." @${CC} ${cflags} -MMD -MT "$(<:.c=.s) $@" -o $@ -c $< @@ -45,8 +41,6 @@ ifdef bindir exed := ${DESTDIR}${bindir} exei := ${exed}/$(notdir ${exe}) -o2si := ${exed}/opml2snow -s2oi := ${exed}/snow2opml ${exed}: @echo "Creating $@ ..." @@ -54,20 +48,14 @@ ${exed}: ${exei}: ${exe} | ${exed} @echo "Installing $@ ..." @${INSTALL_PROGRAM} $< $@ -${o2si}: opml2snow | ${exed} - @echo "Installing $@ ..." - @${INSTALL_PROGRAM} $< $@ -${s2oi}: ${o2si} | ${exed} - @echo "Installing $@ ..." - @(cd ${exed}; rm -f $@; ln -s $(notdir $<) $(notdir $@)) installdirs: ${exed} -install: ${exei} ${o2si} ${s2oi} +install: ${exei} uninstall: uninstall-bin uninstall-bin: @if [ -f ${exei} ]; then\ echo "Removing ${exei} ...";\ - rm -f ${exei} ${o2si} ${s2oi};\ + rm -f ${exei};\ fi endif @@ -77,7 +65,7 @@ endif clean: @if [ -d ${builddir} ]; then\ - rm -f ${exe} ${exe}-static ${objs} ${deps} $O.d;\ + rm -f ${exe} ${objs} ${deps} $O.d;\ rmdir ${builddir};\ fi diff --git a/conv.c b/conv.c index aa6b9fe..abb8c5d 100644 --- a/conv.c +++ b/conv.c @@ -418,7 +418,7 @@ void CleanupString (char* string, int tidyness) return; size_t len = strlen (string); - while (len && (string[0] == '\n' || string[0] == ' ' || string[0] == '\t')) { + while (len && isspace (string[0])) { // len=strlen(string) does not include \0 of string. // But since we copy from *string+1 \0 gets included. // Delicate code. Think twice before it ends in buffer overflows. @@ -426,12 +426,6 @@ void CleanupString (char* string, int tidyness) --len; } - // Remove trailing spaces. - while (len > 1 && string[len - 1] == ' ') { - string[len - 1] = 0; - --len; - } - // Eat newlines and tabs along the whole string. for (size_t i = 0; i < len; ++i) { if (string[i] == '\t') @@ -439,6 +433,10 @@ void CleanupString (char* string, int tidyness) if (tidyness == 1 && string[i] == '\n') string[i] = ' '; } + + // Remove trailing spaces. + while (len > 1 && isspace (string[len-1])) + string[--len] = 0; } // http://foo.bar/address.rdf -> http:__foo.bar_address.rdf diff --git a/feedio.c b/feedio.c index 85f98c9..1779744 100644 --- a/feedio.c +++ b/feedio.c @@ -22,6 +22,7 @@ #include "uiutil.h" #include "parse.h" #include "setup.h" +#include "cat.h" #include #include @@ -178,6 +179,35 @@ int LoadAllFeeds (unsigned numfeeds) return 0; } +void AddFeed (const char* url, const char* cname, const char* categories, const char* filter) +{ + struct feed* new_ptr = newFeedStruct(); + new_ptr->feedurl = strdup (url); + if (strncasecmp (new_ptr->feedurl, "exec:", strlen ("exec:")) == 0) + new_ptr->execurl = true; + else if (strncasecmp (new_ptr->feedurl, "smartfeed:", strlen ("smartfeed:")) == 0) + new_ptr->smartfeed = true; + if (cname && cname[0]) + new_ptr->custom_title = strdup (cname); + if (filter && filter[0]) + new_ptr->perfeedfilter = strdup (filter); + if (categories && categories[0]) { // Put categories into cat struct. + char* catlist = strdup (categories); + for (char* catnext = catlist; catnext;) + FeedCategoryAdd (new_ptr, strsep (&catnext, ",")); + free (catlist); + } + // Add to bottom of pointer chain. + if (!_feed_list) + _feed_list = new_ptr; + else { + new_ptr->prev = _feed_list; + while (new_ptr->prev->next) + new_ptr->prev = new_ptr->prev->next; + new_ptr->prev->next = new_ptr; + } +} + static void WriteFeedUrls (void) { if (!_feed_list_changed) @@ -185,7 +215,7 @@ static void WriteFeedUrls (void) // Make a backup of urls. char urlsfilename[PATH_MAX]; - ConfigFilePath ("urls", urlsfilename, sizeof(urlsfilename)); + ConfigFilePath ("urls.opml", urlsfilename, sizeof(urlsfilename)); // Write urls FILE* urlfile = fopen (urlsfilename, "w"); @@ -193,23 +223,51 @@ static void WriteFeedUrls (void) syslog (LOG_ERR, "error saving urls: %s", strerror (errno)); return; } - for (const struct feed * f = _feed_list; f; f = f->next) { - fputs (f->feedurl, urlfile); - fputc ('|', urlfile); - if (f->custom_title) - fputs (f->title, urlfile); - fputc ('|', urlfile); - for (const struct feedcategories * c = f->feedcategories; c; c = c->next) { - fputs (c->name, urlfile); - if (c->next) // Only add a colon of we run the loop again! - fputc (',', urlfile); - } - fputc ('|', urlfile); - if (f->perfeedfilter != NULL) - fputs (f->perfeedfilter, urlfile); - fputc ('\n', urlfile); // Add newline character. + // Write header + fputs ( + "\n" + "next) + if (f->perfeedfilter) + needNs = true; + if (needNs) + fputs (" xmlns:snow=\"http://snownews.kcore.de/ns/1.0/\"", urlfile); + + fputs ( + ">\n" + " \n" + " " SNOWNEWS_NAME " subscriptions\n" + " \n" + " \n" + , urlfile); + + // Write one outline element per feed + for (const struct feed* f = _feed_list; f; f = f->next) { + fputs ("\tcustom_title) + fprintf (urlfile, " text=\"%s\"", f->custom_title); + if (f->feedurl) + fprintf (urlfile, " xmlUrl=\"%s\"", f->feedurl); + if (f->feedcategories) { + fputs (" category=\"", urlfile); + for (const struct feedcategories* c = f->feedcategories; c; c = c->next) { + fputs (c->name, urlfile); + if (c->next) + fputc (',', urlfile); + } + fputs ("\"", urlfile); + } + if (f->perfeedfilter) + fprintf (urlfile, " snow:filter=\"%s\"", f->perfeedfilter); + fputs ("/>\n", urlfile); } + fputs ( + " \n" + "\n", urlfile); fclose (urlfile); _feed_list_changed = false; } @@ -232,7 +290,12 @@ static void WriteFeedCache (const struct feed* feed) return; } - fputs ("\n\n\n\n", cache); + fputs ( + "\n\n" + "\n\n", cache); if (feed->lastmodified) fprintf (cache, "%ld\n", feed->lastmodified); diff --git a/feedio.h b/feedio.h index cc9e9d0..afc0eee 100644 --- a/feedio.h +++ b/feedio.h @@ -22,4 +22,5 @@ int UpdateFeed (struct feed* cur_ptr); int UpdateAllFeeds (void); int LoadFeed (struct feed* cur_ptr); int LoadAllFeeds (unsigned numfeeds); +void AddFeed (const char* url, const char* cname, const char* categories, const char* filter); void WriteCache (void); diff --git a/main.h b/main.h index 05eabc4..510a70c 100644 --- a/main.h +++ b/main.h @@ -29,7 +29,6 @@ struct feed { char* link; char* description; char* lasterror; - char* content_type; char* custom_title; // Custom feed title. char* original; // Original feed title. char* perfeedfilter; // Pipe feed through this program before parsing. diff --git a/man/opml2snow.1 b/man/opml2snow.1 deleted file mode 100644 index e4696f5..0000000 --- a/man/opml2snow.1 +++ /dev/null @@ -1,60 +0,0 @@ -.\" Hey, EMACS: -*- nroff -*- -.\" First parameter, NAME, should be all caps -.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection -.\" other parameters are allowed: see man(7), man(1) -.TH opml2snow 1 "October 22, 2004" -.\" Please adjust this date whenever revising the manpage. -.\" -.\" Some roff macros, for reference: -.\" .nh disable hyphenation -.\" .hy enable hyphenation -.\" .ad l left justify -.\" .ad b justify to both left and right margins -.\" .nf disable filling -.\" .fi enable filling -.\" .br insert line break -.\" .sp insert n+1 empty lines -.\" for manpage-specific macros, see man(7) - -.SH NAME -opml2snow \- snownews OPML subsription file import/export utility - -.SH SYNOPSIS -.B opml2snow -.RI [ options ] " file.opml " ... - -.SH DESCRIPTION -This manual page documents briefly the -.B opml2snow -command. -This manual page was written for the Debian distribution -because the original program does not have a manual page. - -.PP -.B opml2snow -is a PERL script that will convert an OPML -.RI ( "Outline Processor Markup Language" ) -list of RSS subscriptions to the snownews format or export snownews' -internal subscription format to an OPML file. -It accepts input either on stdin, or as a list of files on the command\-line. -By default it will print to stdout, but if you want to append the output -to your subsription list instead, redirect the output with >> ~/.snownews/url - -.SH OPTIONS -.TP -.B \-h, \-\-help -Show a few brief usage examples. -.TP -.B \--export [urls file] -Export snownews' subscription list to an OPML file. It reads from -~/.snownews/urls by default if you don't pass an optional file location. - -.SH SEE ALSO -.BR snownews (1). -.PP -The OPML spec, available online at: -.RI < http://opml.scripting.com/spec > - -.SH AUTHOR -This manual page was written by Joe Nahmias , -for the Debian project (but may be used by others). diff --git a/man/snownews.1 b/man/snownews.1 index cabf56d..bafd3d9 100644 --- a/man/snownews.1 +++ b/man/snownews.1 @@ -70,7 +70,7 @@ will open the link (usually the complete news text) in the browser. The default browser is lynx, but you can change this by pressing .B 'B' in the main menu and entering a new default browser. Or you can edit -the file ~/.snownews/browser. The program replaces +the file ~/.config/snownews/browser. The program replaces %s with the URL when expanding the string. .P You can rename a feed by pressing the key @@ -112,7 +112,7 @@ You can see all defined categories for a feed in the feed info. .P .B Customizing keybindings .P -You can customize the keybindings by editing the file ~/.snownews/keybindings. +You can customize the keybindings by editing the file ~/.config/snownews/keybindings. The format is "function description:key". Do not change the string "function description". The single character behind the colon represents the key the program will associate with the corresponding function. If @@ -122,7 +122,7 @@ the default settings will be used instead. .B Colours .P If you prefer to see the world in colours you can enable (and configure) colour -support in Snownews. Edit the file ~/.snownews/colors. To globally enable +support in Snownews. Edit the file ~/.config/snownews/colors. To globally enable colours in the program, set enabled to "1". To set a colour, use the colour key value that is listed in the comment in that file. You can disable usage for single items by using the value "-1". @@ -134,25 +134,9 @@ the text. Tags will be stripped alltogether and some common HTML entities will be translated. By default only the five entities defined in XML (< (<), > (>), & (&), " (") and ' (')) plus a default setting included will be translated. You can influence this behaviour with -the definition file at ~/.snownews/html_entities. See the comments on top +the definition file at ~/.config/snownews/html_entities. See the comments on top of the file for further details. .P -.B Importing/exporting subscriptions from other programs: -.P -Snownews can import opml subscription files from other RSS readers into -its own format with the included program "opml2snow". -To convert an opml subscription file type "opml2snow MySubsriptions.opml" -with MySubscriptions.opml being the name of the file you want to convert. -The program will print the converted data to stdout. Use -"opml2snow file.opml >converted" to put the converted data into the file -"converted" or "opml2snow file.opml >>~/.snownews/urls" -to append it to snownews' subscription list. -.P -You can also export snownews' internal format to an OPML file with -"opml2snow --export". -.P -See "opml2snow -h" or its manpage for more usage examples. -.P .B HTTP client features .P Snownews' HTTP client will follow HTTP server redirects. If the URL you have @@ -168,7 +152,7 @@ To subscribe to a feed that requires authentication, use an URL .B http://username:password@server/feed.rss. You can use cookies to supply log in information to a webserver. Put the cookies you want Snownews to use into the file -.B ~/.snownews/cookies. +.B ~/.config/snownews/cookies. The file has to be in standard Netscape cookies.txt file format. Mozilla uses this format for example. Snownews will automatically send the right cookies to the right webserver. You can also just place a symlink to your browser's @@ -242,11 +226,6 @@ the program crash, regardless what you're doing is a bug and needs to be fixed. XML parsing errors are probably not fixable in Snownews since libxml is responsible for parsing a document's XML. Though you can report problematic feeds anyway, it may be a bug in Snownews. -.P -Please read http://kiza.kcore.de/software/snownews/faq#toc4 before you report a bug. - -.SH SEE ALSO -.BR opml2snow (1). .SH AUTHOR Oliver Feiler diff --git a/man/snownews.de.1 b/man/snownews.de.1 index a38c18b..9919e92 100644 --- a/man/snownews.de.1 +++ b/man/snownews.de.1 @@ -77,7 +77,7 @@ Webbrowser. Der Standardbrowser ist Lynx. Sie kЖnnen dies aber Дndern, indem Sie im HauptmenЭ die Taste .B 'B' -drЭcken. Alternativ kЖnnen Sie auch die Datei ~/.snownews/browser +drЭcken. Alternativ kЖnnen Sie auch die Datei ~/.config/snownews/browser editieren. Das Programm ersetzt %s durch die URL, wenn es den Webbrowser aufruft. .P @@ -127,7 +127,7 @@ der Feed Information. .B Tatenbelegung konfigurieren .P Die Tastenbelegung kЖnnen Sie Дndern, indem Sie die Datei -~/.snownews/keybindings editieren. Das Format der Datei ist +~/.config/snownews/keybindings editieren. Das Format der Datei ist "Funktionsbeschreibung:Taste". Дndern Sie bitte nicht den Text der Funktionsbeschreibung. Der einzelne Buchstabe hinter dem Doppelpunkt stellt die Taste dar, die das Programm mit der entsprechenden Funktion @@ -143,19 +143,7 @@ entfernt und gebr nur die in XML definierten Entities (< (<), > (>), & (&), " (") and ' (')) und eine interne Standardvorgabe umgewandelt. Sie kЖnnen diese Liste erweitern, indem Sie die gewЭnschten Zeichen in die -Datei ~/.snownews/html_conversion eintragen. -.P -.B Importieren von Abonnements aus anderen Programmen: -.P -Snownews kann opml Abonnements von anderen RSS Newsreadern in sein -eigenes Format importieren. Dies funktioniert mit dem mitgelieferten -Programm "opml2snow". Um eine Subscription Datei zu konvertieren, -tippen Sie "opml2snow Datei.opml", wobei Datei.opml die zu importierende -Datei ist. Das Programm gibt die konvertierten Daten auf den Bildschirm -aus. Verwenden Sie "opml2snow Datei.opml >konvertiert" um die Ausgabe -in die Datei "konvertiert" zu schreiben, oder "opml2snow Datei.opml ->>~/.snownews/urls" um die konvertierten Daten zu der Feedliste von -Snownews hinzuzufЭgen. Geben Sie "opml2snow -h" ein fЭr mehr Beispiele. +Datei ~/.config/snownews/html_conversion eintragen. .P .B Einige weitere nЭtzliche Dinge: .P diff --git a/man/snownews.fr.1 b/man/snownews.fr.1 index 27becfd..8d43933 100644 --- a/man/snownews.fr.1 +++ b/man/snownews.fr.1 @@ -72,7 +72,7 @@ ouvre le lien dans un navigateur. Le navigateur par dИfaut est lynx, mais ceci peut Йtre configurИ en pressant .B Shift+B dans le menu principal puis en entrant un nouveau navigateur. -Vous pouvez Иgalement Иditer le fichier ~/.snownews/browser. +Vous pouvez Иgalement Иditer le fichier ~/.config/snownews/browser. Le programme remplace %s par l'URL dans la chaНne entrИe. .P Une connexion peut Йtre interrompue en pressant @@ -110,27 +110,13 @@ pressez simplement son num .P Vous pouvez voir toutes les catИgories d'un feed dans son Иcran d'info. .P -Vous pouvez modifier les touches en Иditant le fichier ~/.snownews/keybindings. +Vous pouvez modifier les touches en Иditant le fichier ~/.config/snownews/keybindings. Le format est "description de la fonction:touche". Ne changez pas la partie "description de la fonction". Le caractХre suivant les deux points reprИsente la touche que le programme associera avec la fonction correspondante. Si une dИfinition est effacИe, ou si le programme ne peut pas lire le fichier pour quelque raison, alors le rИglage par dИfaut sera utilisИ. .P -.B Import de feeds d'un autre programme: -.P -Snownews peut importer des fichiers d'abonnements RSS issus d'autres programmes -dans son propre format au moyen de l'outil "opml2snow". -Pour convertir un fichier d'abonnement de type opml, taper: -"opml2snow MesAbonnements.opml" -oЫ MesAbonnements.opml est le nom du fichier Ю convertir. -opml2snow enverra le rИsultat de la conversion sur la sortie standard. -Taper "opml2snow fichier.opml > converti" pour Иcrire le rИsultat dans un -fichier appelИ "converti", ou encore "opml2snow fichier.opml >> ~/.snownews/urls" -pour ajouter les abonnements convertis dans le fichier des abonnements de -Snownews. -Voir "opml2snow -h" pour d'autres exemples d'utilisation. -.P .B Quelques dИtails supplИmentaires: .P Lors de la visualisation de la description d'un ИlИment, vous pouvez retourner diff --git a/man/snownews.it.1 b/man/snownews.it.1 index 54f6185..6eed4ff 100644 --- a/man/snownews.it.1 +++ b/man/snownews.it.1 @@ -81,7 +81,7 @@ premendo il tasto .B 'B' nel menu principale e impostando un browser differente. In alternativa, si pu modificare il file di configurazione -~/.snownews/browser. Il programma sostituisce alla stringa +~/.config/snownews/browser. Il programma sostituisce alla stringa %s l'URL indicata dal link. .P Le connessioni ai siti possono essere interrotte premendo il tasto @@ -136,7 +136,7 @@ Si possono vedere tutte le categorie cui un feed fa parte tra le informazioni relative ad un feed. .P Si possono personalizzare le associazioni dei tasti modificando il file -~/.snownews/keybindings. +~/.config/snownews/keybindings. Il formato del file О©╫semplicemente "descrizione della funzione:key". Attenzione: non si deve modificare la stringa "descrizione della funzione". @@ -146,22 +146,6 @@ Se si eliminano delle definizioni o se, per qualsiasi motivo, il programma non О©╫in grado di effettuare il parsing del file, verranno usate le impostazioni predefinite. .P -.B Importare sottoscrizioni da altri programmi. -.P -Snownews О©╫in grado di importare file di sottoscrizioni opml da altri lettori -RSS usando il programma "opml2snow". -Per convertire un file opml nel formato usato da Snownews, О©╫sufficiente digitare il comando -"opml2snow MySubsriptions.opml", dove -MySubscriptions.opml rappresenta il nome del file con le sottoscrizioni da -importare. -opml2snow stampa i dati convertiti sullo stdout. -Basta digitare -"opml2snow file.opml >converted" per salvare tali dati nel file -"converted", o "opml2snow file.opml >>~/.snownews/urls" -per appenderli alla lista dei feed sottoscritti da Snownews. -Per maggiori informazioni, si pu lanciare -"opml2snow -h". -.P .B Alcuni particolari interessanti. .P Se si sta visualizzando la descrizione di un elemento, О©╫possibile diff --git a/man/snownews.nl.1 b/man/snownews.nl.1 index 3dce612..162cc6d 100644 --- a/man/snownews.nl.1 +++ b/man/snownews.nl.1 @@ -16,7 +16,7 @@ Als u een feed selecteert en op Enter drukt zal het programma elk item van deze Selecteer een item en druk op Enter om de beschrijving te lezen. Als er geen beschrijving aan toegevoegd is zal de tekst 'Geen beschrijving beschikbaar.' verschijnen. U kunt met de pijltjestoetsen links en rechts, respectievelijk 'p' en 'n' het vorige of volgende nieuwsitem uit de lijst selecteren. Door op 'o' te drukken wordt de link (meestal de complete nieuwstekst) geopend in de browser. -De standaardbrowser is lynx, maar u kunt dit veranderen door op 'B' te drukken in het hoofdmenu en een nieuwe standaardbrowser in te voeren. Of u kunt het bestand ~/.snownews/browser bewerken. Het programma vervangt %s door de URL bij het uitbreiden van de string. +De standaardbrowser is lynx, maar u kunt dit veranderen door op 'B' te drukken in het hoofdmenu en een nieuwe standaardbrowser in te voeren. Of u kunt het bestand ~/.config/snownews/browser bewerken. Het programma vervangt %s door de URL bij het uitbreiden van de string. Netwerk verbindingen kunnen onderbroken worden door op .B 'z' @@ -44,14 +44,7 @@ U kunt alle al gedefinieerde catgorie .P .B Toetsenbord instellen .P -U kunt de toetsen veranderen door het bestand ~/.snownews/keybindings te bewerken. Het formaat is "functiebeschrijving:toets". Verander de "functiebeschrijving" niet. Het teken achter de dubbele punt is de toets die het programma aan die functie toewijst. Als u een definitie verwijdert of het programma kan het bestand, om de een of andere reden, niet lezen worden de standaard instellingen gebruikt. - -.B Abbonnementen importeren uit ander programma's: -.P -Snownews kan opml abbonnementsbestanden importeren van andere RSS lezers naar het eigen formaat met het bijgevoegde programma "opml2snow". -Om een opml abbonnementsbestand te converteren type "ompl2snow MijnAbbonnementen.opml" waarbij MijnAbbonnementen.opml de bestandsnaam is van het bestand dat u wilt converteren. -Het programma toont de geconverteerde data op de stdout. Gebruik "ompl2snow bestand.opml > geconverteerd" om de geconverteerde data in het bestand "geconverteerd" te plaatsen of "ompl2snow bestand.opml >> ~/.snownews/url" om het toe te voegen aan het einde van de abbonnementenlijst van Snownews. -Gebruik "opml2snow -h" voor meer voorbeelden van het gebruik. +U kunt de toetsen veranderen door het bestand ~/.config/snownews/keybindings te bewerken. Het formaat is "functiebeschrijving:toets". Verander de "functiebeschrijving" niet. Het teken achter de dubbele punt is de toets die het programma aan die functie toewijst. Als u een definitie verwijdert of het programma kan het bestand, om de een of andere reden, niet lezen worden de standaard instellingen gebruikt. .B Een paar dingen die het waard zijn uit te leggen: diff --git a/man/snownews.ru.KOI8-R.1 b/man/snownews.ru.KOI8-R.1 index b3e54ef..da76874 100644 --- a/man/snownews.ru.KOI8-R.1 +++ b/man/snownews.ru.KOI8-R.1 @@ -67,7 +67,7 @@ Snownews - Браузер по умолчанию - lynx, однако вы можете это изменить, нажав .B 'B' в основном меню (на основном экране), и ввести новую строку запуска -браузера по умолчанию. Либо можно отредактировать файл ~/.snownews/browser. +браузера по умолчанию. Либо можно отредактировать файл ~/.config/snownews/browser. программы заменит %s соответствующим адресом при обработке этой строки. (как организовать использование mozilla в качестве браузера для snownews, смотрите в FAQ: http://home.kcore.de/~kiza/software/snownews/faq#toc2.1 ) @@ -121,7 +121,7 @@ Snownews - .B Переназначение клавиш .P Переопределить назначение клавиш можно, отредактировав файл -~/.snownews/keybindings. Формат записей - "описание функции:клавиша". +~/.config/snownews/keybindings. Формат записей - "описание функции:клавиша". Строку "описание функции" изменять нельзя. Единичный символ после двоеточия описывает клавишу, которую программа назначит соответствующей функции. Если описание будет удалено из файла, или программа не сможет @@ -135,21 +135,9 @@ Snownews HTML-коды конвертируются. По умолчанию конвертируются только пять кодов, определенных в XML (< (<), > (>), & (&), " (") and ' (')) плюс определенные в стандартных настройках snownews. Это можно -изменить в файле ~/.snownews/html_entities. Дальнейшие объяснения смотрите +изменить в файле ~/.config/snownews/html_entities. Дальнейшие объяснения смотрите в комментариях в начале этого файла. .P -.B Импортирование подписок из других программ: -.P -Snownews может импортировать файлы подписок opml из других RSS-просмотрщиков -в свой собственный формат с помощью включенной в поставку программы "opml2snow". -Конвертирование opml-подписки производится командой "opml2snow MySubsriptions.opml", -где MySubscriptions.opml - имя файла, который вы желаете конвертировать. -Программа выдает сконвертированные данные на стандартный вывод. Команда -"opml2snow file.opml >converted" поместит сконвертированные данные в файл -"converted", команда "opml2snow file.opml >>~/.snownews/urls" - добавит -их в список лент Snownews. Для примеров использования программы, запустите -"opml2snow -h". -.P .B Некоторые стоящие упоминания вещи: .P Во время просмотра записи, для возвращения к предыдущему экрану @@ -177,7 +165,7 @@ Snownews .B http://username:password@server/feed.rss. Возможно также использовать cookies для передачи аутентификационной информации на вебсервер. Snownews будет использовать cookies, которые вы поместите в файл -.B ~/.snownews/cookies. +.B ~/.config/snownews/cookies. Файл должен быть в стандартном формате Netscape-овского cookies.txt. К примеру, Mozilla использует этот формат. Snownews автоматически посылает нужные cookie на нужный вебсервер. Возможно также просто создать символическую ссылку на @@ -235,8 +223,5 @@ Snownews Пожалуйста, прочтите http://kiza.kcore.de/software/snownews/faq#toc4 перед тем, как сообщать об ошибке. -.SH СМОТРИ ТАКЖЕ -.BR opml2snow (1). - .SH АВТОР Oliver Feiler diff --git a/netio.c b/netio.c index 2ba06cc..d262a98 100644 --- a/netio.c +++ b/netio.c @@ -118,7 +118,7 @@ void DownloadFeed (const char* url, struct feed* fp) // Check if failed because already up-to-date long unmet = 0; if (CURLE_OK == curl_easy_getinfo (curl, CURLINFO_CONDITION_UNMET, &unmet) && unmet) { - fp->lasterror = strdup (_("Feed already up to date")); + fp->lasterror = strdup (_("already up to date")); UIStatus (fp->lasterror, 0, 0); fp->problem = false; } else { diff --git a/opml2snow b/opml2snow deleted file mode 100755 index 9434111..0000000 --- a/opml2snow +++ /dev/null @@ -1,146 +0,0 @@ -#!/usr/bin/perl -####################################################################### -# $Id: opml2snow 1176 2007-12-02 10:55:52Z kiza $ -# -# Snownews - A lightweight console RSS newsreader -# -# Copyright 2003-2004 Oliver Feiler -# http://kiza.kcore.de/software/snownews/ -# -# opml2snow -# -# This program is free software; you can redistribute it and/or modify -# it under the terms of the GNU General Public License version 2 as -# published by the Free Software Foundation. -# -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with this program; if not, write to the Free Software -# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -####################################################################### - -use strict; -use XML::LibXML; -use Data::Dumper; -use English; - -####################################################################### -# Help -if (index($ARGV[0], "-h") >= 0) { - print "Snownews opml2snow - subsription file import/export utility\n\n". - "Creative usage examples:\n". - "Importing an OPML file:\n". - " opml2snow urls\n". - " opml2snow list.opml >urls\n". - " cat list.opml | opml2snow >urls\n\n". - "Exporting to OPML:\n". - " opml2snow --export [urls file] >MySubscriptions.opml\n". - " Alternatively you may run snow2opml [urls file] >file.opml\n\n". - "The program will print to stdout by default. If you want to append the output\n". - "to your subsription list, redirect to >>~/.snownews/urls instead.\n"; - exit (0); -} - -####################################################################### -# Importing -if (($PROGRAM_NAME =~ "snow2opml") || ($ARGV[0] eq "--export")) { - OPMLexport(); -} else { - my $parser = XML::LibXML->new(); - $parser->validation(0); # Turn off validation from libxml - $parser->recover(1); # And ignore any errors while parsing - - my(@lines) = <>; - my($input) = join ("\n", @lines); - - my($doc) = $parser->parse_string($input); - my($root) = $doc->documentElement(); - - # Parsing the document tree using xpath - my(@items) = $root->findnodes("//outline"); - foreach (@items) { - my(@attrs) = $_->attributes(); - foreach (@attrs) { - # Only print attribute xmlUrl="" - if ($_->nodeName =~ /xmlUrl/i) { - print $_->value."\n"; - } - } - } -} - -####################################################################### -# Exporting -sub OPMLexport { - my($inputfile); - if (defined($ARGV[1])) { - $inputfile = $ARGV[1]; - } else { - $inputfile = "$ENV{'HOME'}/.snownews/urls" - } - open (URLS, "$inputfile"); - my(@urls) = ; - close (URLS); - - if (scalar(@urls) == 0) { - print "Could not read anything from \"$inputfile\"!\nExiting.\n"; - exit(1); - } - - # Create bare OPML doc - my($opml) = XML::LibXML::Document->new(); - my($opml_root) = $opml->createElement('opml'); - $opml->setDocumentElement($opml_root); - - my($opml_comment) = $opml->createComment(' File generated by opml2snow '); - $opml_root->appendChild($opml_comment); - - my($opml_head) = $opml->createElement('head'); - $opml_root->appendChild($opml_head); - $opml_head->appendTextChild('title', 'MySubscriptions'); - - my($opml_body) = $opml->createElement('body'); - $opml_root->appendChild($opml_body); - - foreach(@urls) { - chomp; - /^(.*)?\|(.*?)\|(.*?)\|(.*)$/; - - my($feed_url) = $1; - my($feed_url_hash) = $feed_url; - $feed_url_hash =~ tr/[\x00-\x19\x27-\x2a\x2f\x5b-\x60\x7b-\xff]/_/; # Translated from Hashify in conversions.c - $feed_url_hash = substr($feed_url_hash, 0, 128); - - if ($feed_url_hash =~ /^smartfeed/) { - next; - } - my($feed_override_title) = $2; - my($feed_category) = $3; - my($feed_script) = 4; - - my($parser) = XML::LibXML->new(); - my($feed_doc) = $parser->parse_file("$ENV{'HOME'}/.snownews/cache/$feed_url_hash"); - my($feed_root) = $feed_doc->documentElement(); - $feed_root->setNamespace('http://purl.org/rss/1.0/', 'rss', 1); - - # Make outline element. Actually I have absolutely no idea how - # this should look like. I copied the layout from an OPML file - # produced by NetNewsWire. The OPML "spec" is supposed to be at: - # http://www.opml.org/spec - my($opml_outline) = $opml->createElement('outline'); - $opml_outline->setAttribute('text', $feed_root->findvalue('//rss:channel/rss:title')); - $opml_outline->setAttribute('title', $feed_root->findvalue('//rss:channel/rss:title')); - $opml_outline->setAttribute('description', $feed_root->findvalue('//rss:channel/rss:description')); - $opml_outline->setAttribute('type', 'rss'); - $opml_outline->setAttribute('version', 'RSS'); - $opml_outline->setAttribute('htmlUrl', $feed_root->findvalue('/rss:channel/rss:link')); - $opml_outline->setAttribute('xmlUrl', "$feed_url"); - $opml_body->appendChild($opml_outline); - } - - print $opml->serialize(1); -} diff --git a/parse.c b/parse.c index 93c37e6..aae961b 100644 --- a/parse.c +++ b/parse.c @@ -17,6 +17,7 @@ // along with Snownews. If not, see http://www.gnu.org/licenses/. #include "parse.h" +#include "feedio.h" #include "conv.h" #include @@ -466,3 +467,54 @@ int DeXML (struct feed* cur_ptr) } return 0; } + +unsigned ParseOPMLFile (const char* flbuf) +{ + unsigned nfeeds = 0; + xmlDocPtr doc = xmlRecoverMemory (flbuf, strlen (flbuf)); + if (!doc) + return nfeeds; + + xmlNodePtr rootnode = xmlDocGetRootElement (doc); + if (!rootnode) { + xmlFreeDoc (doc); + return nfeeds; + } + if (xmlStrcmp (rootnode->name, (const xmlChar*) "opml") == 0) { + for (xmlNodePtr body = rootnode->children; body; body = body->next) { + if (body->type != XML_ELEMENT_NODE + || 0 != xmlStrcmp (body->name, (const xmlChar*) "body")) + continue; + for (xmlNodePtr outline = body->children; outline; outline = outline->next) { + if (outline->type != XML_ELEMENT_NODE + || 0 != xmlStrcmp (outline->name, (const xmlChar*) "outline")) + continue; + + char* text = (char*) xmlGetProp (outline, (const xmlChar*) "text"); + char* xmlUrl = (char*) xmlGetProp (outline, (const xmlChar*) "xmlUrl"); + char* categories = (char*) xmlGetProp (outline, (const xmlChar*) "category"); + char* filter = (char*) xmlGetNsProp (outline, (const xmlChar*) "filter", snowNs); + CleanupString (xmlUrl, 0); + CleanupString (text, 0); + CleanupString (categories, 0); + CleanupString (filter, 0); + + if (xmlUrl && text) { + AddFeed (xmlUrl, text, categories, filter); + ++nfeeds; + } + + if (xmlUrl) + xmlFree (xmlUrl); + if (text) + xmlFree (text); + if (categories) + xmlFree (categories); + if (filter) + xmlFree (filter); + } + } + } + xmlFreeDoc (doc); + return nfeeds; +} diff --git a/parse.h b/parse.h index 437f432..52e84b1 100644 --- a/parse.h +++ b/parse.h @@ -18,3 +18,4 @@ #include "main.h" int DeXML (struct feed* cur_ptr); +unsigned ParseOPMLFile (const char* flbuf); diff --git a/setup.c b/setup.c index cc6f799..5c92919 100644 --- a/setup.c +++ b/setup.c @@ -21,6 +21,8 @@ #include "feedio.h" #include "uiutil.h" #include "conv.h" +#include "parse.h" +#include #include void ConfigFilePath (const char* filename, char* path, size_t pathsz) @@ -51,18 +53,40 @@ void CacheFilePath (const char* filename, char* path, size_t pathsz) path[pathlen-1] = 0; } +static char* LoadFile (const char* filename) +{ + struct stat st; + if (0 != stat (filename, &st) || !S_ISREG(st.st_mode) || !st.st_size) + return NULL; + int fd = open (filename, O_RDONLY); + if (fd < 0) + return NULL; + char* r = calloc (1, st.st_size); + for (ssize_t br = 0; br < st.st_size;) { + ssize_t ec = read (fd, &r[br], st.st_size-br); + if (ec <= 0) { + if (errno == EINTR) + continue; + free (r); + return NULL; + } + br += ec; + } + return r; +} + // Load browser command from ~./snownews/browser. static void SetupBrowser (const char* filename) { - char linebuf[128] = "lynx %s"; - FILE* browserfile = fopen (filename, "r"); - if (browserfile) { - fgets (linebuf, sizeof (linebuf), browserfile); - if (linebuf[strlen (linebuf) - 1] == '\n') - linebuf[strlen (linebuf) - 1] = '\0'; - fclose (browserfile); + char* fbuf = LoadFile (filename); + if (!fbuf) { + _settings.browser = strdup ("lynx %s"); + return; } - _settings.browser = strdup (linebuf); + size_t fbuflen = strlen(fbuf); + while (isspace (fbuf[fbuflen-1])) + fbuf[--fbuflen] = 0; + _settings.browser = fbuf; } void SaveBrowserSetting (void) @@ -368,56 +392,40 @@ static void SetupEntities (const char* file) } } +static unsigned ParseOldFeedListFile (char* flbuf) +{ + unsigned numfeeds = 0; + for (char* lineiter = flbuf; lineiter;) { + char* line = strsep (&lineiter, "\n"); + + // File format is url|custom name|comma seperated categories|filters + const char* url = strsep (&line, "|"); + if (!url || !url[0]) + continue; // no url + const char* cname = strsep (&line, "|"); + const char* categories = strsep (&line, "|"); + const char* filters = line; + + AddFeed (url, cname, categories, filters); + ++numfeeds; + } + return numfeeds; +} + static unsigned SetupFeedList (const char* filename) { unsigned numfeeds = 0; - FILE* configfile = fopen (filename, "r"); - if (!configfile) + char* flbuf = LoadFile (filename); + if (!flbuf) return numfeeds; // no feeds - while (!feof (configfile)) { - char linebuf[256]; - if (!fgets (linebuf, sizeof (linebuf), configfile)) - break; - if (linebuf[0] == '\n') - break; - linebuf[strlen (linebuf) - 1] = 0; // chop newline - // File format is url|custom name|comma seperated categories|filters - char* parse = linebuf; - const char* url = strsep (&parse, "|"); - if (!url || !url[0]) - continue; // no url - const char* cname = strsep (&parse, "|"); - char* categories = strsep (&parse, "|"); - const char* filters = parse; - - ++numfeeds; - - struct feed* new_ptr = newFeedStruct(); - new_ptr->feedurl = strdup (url); - if (strncasecmp (new_ptr->feedurl, "exec:", strlen ("exec:")) == 0) - new_ptr->execurl = true; - else if (strncasecmp (new_ptr->feedurl, "smartfeed:", strlen ("smartfeed:")) == 0) - new_ptr->smartfeed = true; - if (cname && cname[0]) - new_ptr->custom_title = strdup (cname); - if (filters && filters[0]) - new_ptr->perfeedfilter = strdup (filters); - if (categories && categories[0]) // Put categories into cat struct. - for (char *catnext = categories, *catname; (catname = strsep (&catnext, ","));) - FeedCategoryAdd (new_ptr, catname); - - // Add to bottom of pointer chain. - if (!_feed_list) - _feed_list = new_ptr; - else { - new_ptr->prev = _feed_list; - while (new_ptr->prev->next) - new_ptr->prev = new_ptr->prev->next; - new_ptr->prev->next = new_ptr; - } - } - fclose (configfile); + // Check the format; old snownews style or OPML + if (0 != strncmp (flbuf, "