Store feed list as OPML
The old format consisted of |-separated lines, one per feed. OPML is the usual standard for RSS feed lists, and snownews included the opml2snow utility to convert to and from it. This commit converts urls format to native OPML, removing the need for the utility. The file is also renamed from urls to urls.opml.
This commit is contained in:
parent
6d776956ec
commit
62c0bd5e0e
18
Makefile
18
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
|
||||
|
||||
|
|
12
conv.c
12
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
|
||||
|
|
97
feedio.c
97
feedio.c
|
@ -22,6 +22,7 @@
|
|||
#include "uiutil.h"
|
||||
#include "parse.h"
|
||||
#include "setup.h"
|
||||
#include "cat.h"
|
||||
#include <ncurses.h>
|
||||
#include <libxml/parser.h>
|
||||
|
||||
|
@ -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 (
|
||||
"<?xml version=\"1.0\"?>\n"
|
||||
"<opml version=\"2.0\"", urlfile);
|
||||
|
||||
// See if the custom namespace is needed
|
||||
bool needNs = false;
|
||||
for (const struct feed* f = _feed_list; f; f = f->next)
|
||||
if (f->perfeedfilter)
|
||||
needNs = true;
|
||||
if (needNs)
|
||||
fputs (" xmlns:snow=\"http://snownews.kcore.de/ns/1.0/\"", urlfile);
|
||||
|
||||
fputs (
|
||||
">\n"
|
||||
" <head>\n"
|
||||
" <title>" SNOWNEWS_NAME " subscriptions</title>\n"
|
||||
" </head>\n"
|
||||
" <body>\n"
|
||||
, urlfile);
|
||||
|
||||
// Write one outline element per feed
|
||||
for (const struct feed* f = _feed_list; f; f = f->next) {
|
||||
fputs ("\t<outline", urlfile);
|
||||
if (f->custom_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 (
|
||||
" </body>\n"
|
||||
"</opml>\n", urlfile);
|
||||
fclose (urlfile);
|
||||
_feed_list_changed = false;
|
||||
}
|
||||
|
@ -232,7 +290,12 @@ static void WriteFeedCache (const struct feed* feed)
|
|||
return;
|
||||
}
|
||||
|
||||
fputs ("<?xml version=\"1.0\" ?>\n\n<rdf:RDF\n xmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n xmlns=\"http://purl.org/rss/1.0/\"\n xmlns:snow=\"http://snownews.kcore.de/ns/1.0/\">\n\n", cache);
|
||||
fputs (
|
||||
"<?xml version=\"1.0\" ?>\n\n"
|
||||
"<rdf:RDF\n"
|
||||
"\txmlns:rdf=\"http://www.w3.org/1999/02/22-rdf-syntax-ns#\"\n"
|
||||
"\txmlns=\"http://purl.org/rss/1.0/\"\n"
|
||||
"\txmlns:snow=\"http://snownews.kcore.de/ns/1.0/\">\n\n", cache);
|
||||
|
||||
if (feed->lastmodified)
|
||||
fprintf (cache, "<snow:lastmodified>%ld</snow:lastmodified>\n", feed->lastmodified);
|
||||
|
|
1
feedio.h
1
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);
|
||||
|
|
1
main.h
1
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.
|
||||
|
|
|
@ -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 <n> 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 <jello@debian.org>,
|
||||
for the Debian project (but may be used by others).
|
|
@ -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 <kiza@kcore.de>
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 <20>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 <20>in grado di effettuare il parsing del file, verranno usate le
|
||||
impostazioni predefinite.
|
||||
.P
|
||||
.B Importare sottoscrizioni da altri programmi.
|
||||
.P
|
||||
Snownews <20>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, <20>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, <20>possibile
|
||||
|
|
|
@ -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:
|
||||
|
||||
|
|
|
@ -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 <kiza@kcore.de>
|
||||
|
|
2
netio.c
2
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 {
|
||||
|
|
146
opml2snow
146
opml2snow
|
@ -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 <kiza@kcore.de>
|
||||
# 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 <list.opml >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) = <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);
|
||||
}
|
52
parse.c
52
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 <libxml/parser.h>
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
|
1
parse.h
1
parse.h
|
@ -18,3 +18,4 @@
|
|||
#include "main.h"
|
||||
|
||||
int DeXML (struct feed* cur_ptr);
|
||||
unsigned ParseOPMLFile (const char* flbuf);
|
||||
|
|
127
setup.c
127
setup.c
|
@ -21,6 +21,8 @@
|
|||
#include "feedio.h"
|
||||
#include "uiutil.h"
|
||||
#include "conv.h"
|
||||
#include "parse.h"
|
||||
#include <ctype.h>
|
||||
#include <ncurses.h>
|
||||
|
||||
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, "<?xml", strlen("<?xml"))) {
|
||||
numfeeds = ParseOldFeedListFile (flbuf);
|
||||
_feed_list_changed = true; // force conversion to OPML
|
||||
} else
|
||||
numfeeds = ParseOPMLFile (flbuf);
|
||||
free (flbuf);
|
||||
return numfeeds;
|
||||
}
|
||||
|
||||
|
@ -447,6 +455,17 @@ static void MigrateConfigToXDG (void)
|
|||
if (0 != rename (dirname, configdir))
|
||||
MainQuit ("Migrating configuration ~/.snownews to ~/.config/snownews", strerror (errno));
|
||||
}
|
||||
|
||||
// Convert urls to urls.opml
|
||||
char oldurls [PATH_MAX];
|
||||
ConfigFilePath ("urls", oldurls, sizeof(oldurls));
|
||||
if (0 == access (oldurls, F_OK)) {
|
||||
char newurls [PATH_MAX];
|
||||
ConfigFilePath ("urls.opml", newurls, sizeof(newurls));
|
||||
if (0 != rename (oldurls, newurls))
|
||||
MainQuit ("Migrating urls to urls.opml", strerror (errno));
|
||||
_feed_list_changed = true; // force conversion to OPML
|
||||
}
|
||||
}
|
||||
|
||||
// Create snownews' config directories if they do not exist yet,
|
||||
|
@ -494,6 +513,6 @@ unsigned Config (void)
|
|||
ConfigFilePath ("html_entities", filename, sizeof(filename));
|
||||
SetupEntities (filename);
|
||||
|
||||
ConfigFilePath ("urls", filename, sizeof(filename));
|
||||
ConfigFilePath ("urls.opml", filename, sizeof(filename));
|
||||
return SetupFeedList (filename);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue