diff --git a/LICENSE b/LICENSE

new file mode 100755

index 0000000000000000000000000000000000000000..027d71d0073f90db1ea80f7524f6fceccb001e93

--- /dev/null

+++ b/LICENSE

@@ -0,0 +1,29 @@

+BSD 3-Clause License

+

+Copyright (c) 2018-2020, René Wagner

+All rights reserved.

+

+Redistribution and use in source and binary forms, with or without

+modification, are permitted provided that the following conditions are met:

+

+* Redistributions of source code must retain the above copyright notice, this

+ list of conditions and the following disclaimer.

+

+* Redistributions in binary form must reproduce the above copyright notice,

+ this list of conditions and the following disclaimer in the documentation

+ and/or other materials provided with the distribution.

+

+* Neither the name of the copyright holder nor the names of its

+ contributors may be used to endorse or promote products derived from

+ this software without specific prior written permission.

+

+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"

+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE

+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE

+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE

+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL

+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR

+SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER

+CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,

+OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE

+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

diff --git a/README.md b/README.md

new file mode 100644

index 0000000000000000000000000000000000000000..0cb8d9e9e84d9126815c779aed2fbbfef945c681

--- /dev/null

+++ b/README.md

@@ -0,0 +1,24 @@

+# orrg (online rss feed reader for gemini)

+

+*orrg* is a cgi script for [gemini](gemini://gemini.circumlunar.space) servers.

+It fetches an arbitrary rss feed given by the user and renders its content as a gemini site.

+

+Visit the [demo](gemini://gmndemo.clttr.info/orrg.pl).

+

+## features

+

+Load an arbitrary atom/rss feed.

+

+# installation

+

+- setup your geminiserver with cgi enabled

+- `git clone` the repo to the directory

+- open the capsule in a gemini client

+

+## requirements

+

+- gemini server with cgi enabled (like gmnisrv or stargazer)

+- Perl >= 5.28 with modules

+ - URI::Escape

+ - XML::FeedPP

+ - LWP::UserAgent

diff --git a/orrg.pl b/orrg.pl

new file mode 100755

index 0000000000000000000000000000000000000000..0425f84b46641f18f49edcaaacc01ed103533545

--- /dev/null

+++ b/orrg.pl

@@ -0,0 +1,97 @@

+#!/usr/bin/perl

+# Copyright René Wagner 2020

+# licenced under BSD 3-Clause licence

+# https://git.sr.ht/~rwa/willgemini.support

+

+use strict;

+no warnings 'experimental';

+use URI::Escape;

+use XML::FeedPP;

+use v5.10;

+# enable UTF-8 mode for everything

+use utf8;

+binmode STDOUT, ':utf8';

+binmode STDERR, ':utf8';

+

+# define return codes

+our %RC = (

+ 'INPUT', 10,

+ 'SENSITIVE_INPUT', 11,

+ 'SUCCESS', 20,

+ 'TEMPORARY_REDIRECT', 30,

+ 'PERMANENT_REDIRECT', 31,

+ 'TEMPORARY_FAILURE', 40,

+ 'SERVER_UNAVAILABLE', 41,

+ 'CGI_ERROR', 42,

+ 'PROXY_ERROR', 43,

+ 'SLOW_DOWN', 44,

+ 'PERMANENT_FAILURE', 50,

+ 'NOT_FOUND', 51,

+ 'GONE', 52,

+ 'PROXY_REQUEST_REFUSE', 53,

+ 'BAD_REQUEST', 59,

+ 'CLIENT_CERT_REQUIRED', 60,

+ 'CERT_NOT_AUTHORISED', 61,

+ 'CERT_NOT_VALID', 62

+ );

+

+if (!defined($ENV{'SERVER_PROTOCOL'}) || $ENV{'SERVER_PROTOCOL'} ne 'GEMINI')

+{

+ write_response('CGI_ERROR', '', undef);

+}

+

+my $query = lc(uri_unescape($ENV{'QUERY_STRING'}));

+

+if ($query eq '' || $query !~ /^https\:\/\//) {

+ write_response('INPUT', 'Paste the URI of the rss feed you want to read:', undef);

+}

+write_response('SUCCESS', 'text/gemini', create_response($query));

+

+exit;

+

+sub create_response

+{

+ my ( $qs ) = @_;

+ my @body = ();

+

+ my $feed = XML::FeedPP->new($qs, utf8_flag => 1);

+

+ if ( !defined($feed) ) {

+ push @body, ('# orrg error', '', 'The requested feed could not be loaded. :(', '', '=> '. $qs .' open feed in browser');

+ return @body;

+ }

+

+ push @body, '# '. $feed->title;

+ push @body, ('', $feed->description);

+ push @body, ('=> '.$feed->link.' link to the feed', '');

+ push @body, ('## recent feed items', '');

+

+ foreach my $it ($feed->get_item()) {

+ if ( $it->get('description') ne '') {

+ push @body, '## '. $it->title;

+ push @body, '';

+ push @body, $it->description;

+ }

+ else {

+ push @body, $it->title;

+ }

+

+ push @body, ('=> '.$it->link.' open entry in browser', '');

+ }

+

+ return @body;

+}

+

+sub write_response

+{

+ my ($returncode, $meta, @content) = @_;

+

+ if (!defined($RC{$returncode})) { die "Unknown response code!"; }

+

+ printf("%d %s\r\n", $RC{$returncode}, ($meta eq '') ? $returncode : $meta);

+ foreach (@content) {

+ print("$_\r\n");

+ }

+

+ exit;

+}