diff --git a/fortunate/README b/fortunate/README
new file mode 100644
index 0000000..8297cf4
--- /dev/null
+++ b/fortunate/README
@@ -0,0 +1,7 @@
+This addon requires a fortune server. You may use the DB supplied here to create one.
+
+gunzip the fortunate.sql.gz and import into your database.
+Copy cookie.php to the top level Friendica directory.
+Edit fortunate.php and change FORTUNATE_SERVER definition to your hostname. Change the http in that file to https if your server doesn't support http.
+
+Many additional options are available if you examine cookie.php - a clever developer can provide a settings page to tailor this to one's liking. Also several languages are supported, and it would be convenient to set this to the current Friendica language if that is amongst those supported.
\ No newline at end of file
diff --git a/fortunate/cookie.php b/fortunate/cookie.php
new file mode 100644
index 0000000..3022776
--- /dev/null
+++ b/fortunate/cookie.php
@@ -0,0 +1,349 @@
+real_escape_string($_GET['lang']);
+
+if(strlen($_GET['pattern']))
+ $pattern = @$db->real_escape_string(urldecode($_GET['pattern']));
+
+if(strlen($_GET['regex']))
+ $regex = @$db->real_escape_string(urldecode($_GET['regex']));
+
+if(strlen($_GET['db']))
+ $table = @$db->real_escape_string(urldecode($_GET['db']));
+else
+ $table = '';
+
+if($length < 0)
+ $length = 0;
+if($numlines < 0)
+ $numlines = 0;
+
+function do_query($table,$length,$numlines,$adult,$cat,$limit,$lang,$pattern,$regex,$equal) {
+ global $db;
+ $rnd = mt_rand();
+ $r = [];
+
+ $typesql = (($table) ? " WHERE `category` = '$table' " : " WHERE 1 ");
+ $lengthsql = (($length) ? " AND LENGTH(`text`) < $length " : "" );
+
+ if($adult == 2)
+ $adultsql = " AND offensive = 1 ";
+ elseif($adult == 1)
+ $adultsql = "";
+ else
+ $adultsql = " AND offensive = 0 ";
+
+
+ if($numlines)
+ $lengthsql .=
+ " AND (LENGTH(`text`) - LENGTH(REPLACE(`text`,\"\n\",\"\"))) <= $numlines ";
+
+ $langsql = " AND lang = '$lang' ";
+
+ $patsql = '';
+ if(strlen($pattern))
+ $patsql = " AND MATCH text AGAINST ('$pattern' IN BOOLEAN MODE) ";
+
+ $regexsql = '';
+ if(strlen($regex))
+ $regexsql = " AND text REGEXP '$regex' ";
+
+ $eqsql = '';
+
+ if($equal) {
+ $catsavail = [];
+ $res = @$db->query("SELECT DISTINCT ( `category` ) FROM `fortune`
+ $typesql
+ $adultsql
+ $lengthsql
+ $langsql
+ $patsql
+ $regexsql ");
+ if($res->num_rows) {
+ while($x = $res->fetch_array(MYSQL_ASSOC))
+ $catsavail[] = $x['category'];
+
+ $eqsql = " AND `category` = '"
+ . $catsavail[mt_rand(0,$res->num_rows - 1)] . "' ";
+ }
+ }
+
+ $result = @$db->query("SELECT `text`, `category` FROM `fortune`
+ $typesql
+ $adultsql
+ $lengthsql
+ $langsql
+ $patsql
+ $regexsql
+ $eqsql
+ ORDER BY RAND($rnd)
+ LIMIT $limit");
+
+ if($result->num_rows) {
+ while($x = $result->fetch_array(MYSQL_ASSOC))
+ $r[] = fortune_to_html($x['text'])
+ .(($cat) ? " [{$x['category']}] " : "");
+ }
+ return $r;
+}
+
+
+function do_stats($table,$length,$numlines,$adult,$cat,$limit,$lang,$pattern,$regex,$equal) {
+ global $db;
+ $rnd = mt_rand();
+ $r = [];
+
+ $typesql = (($table) ? " WHERE `category` = '$table' " : " WHERE 1 ");
+ $lengthsql = (($length) ? " AND LENGTH(`text`) < $length " : "" );
+
+ if($adult == 2)
+ $adultsql = " AND offensive = 1 ";
+ elseif($adult == 1)
+ $adultsql = "";
+ else
+ $adultsql = " AND offensive = 0 ";
+
+
+ if($numlines)
+ $lengthsql .=
+ " AND (LENGTH(`text`) - LENGTH(REPLACE(`text`,\"\n\",\"\"))) <= $numlines ";
+
+ $langsql = " AND lang = '$lang' ";
+
+ $patsql = '';
+ if(strlen($pattern))
+ $patsql = " AND MATCH text AGAINST ('$pattern' IN BOOLEAN MODE) ";
+
+ $regexsql = '';
+ if(strlen($regex))
+ $regexsql = " AND text REGEXP '$regex' ";
+
+ $eqsql = '';
+
+ $result = @$db->query("SELECT `text`, `category` FROM `fortune`
+ $typesql
+ $adultsql
+ $lengthsql
+ $langsql
+ $patsql
+ $regexsql
+ $eqsql");
+
+
+ echo ' ' . $result->num_rows . ' matching quotations. ';
+
+
+ $res = @$db->query("SELECT DISTINCT ( `category` ) FROM `fortune`
+ $typesql
+ $adultsql
+ $lengthsql
+ $langsql
+ $patsql
+ $regexsql ");
+ if($res->num_rows) {
+ echo ' Matching Databases: ';
+ while($x = $res->fetch_array(MYSQL_ASSOC))
+ echo $x['category'].' ';
+
+ }
+ else
+ echo ' No matching databases using those search parameters - please refine your options. ';
+
+
+}
+
+
+function fortune_to_html($s) {
+
+ // First pass - escape all the HTML entities, and while we're at it
+ // get rid of any MS-DOS end-of-line characters and expand tabs to
+ // 8 non-breaking spaces, and translate linefeeds to .
+ // We also get rid of ^G which used to sound the terminal beep or bell
+ // on ASCII terminals and were humourous in some fortunes.
+ // We could map these to autoplay a short sound file but browser support
+ // is still sketchy and then there's the issue of where to locate the
+ // URL, and a lot of people find autoplay sounds downright annoying.
+ // So for now, just remove them.
+
+ $s = str_replace(
+ ["&",
+ "<",
+ ">",
+ '"',
+ "\007",
+ "\t",
+ "\r",
+ "\n"],
+
+ ["&",
+ "<",
+ ">",
+ """,
+ "",
+ " ",
+ "",
+ " "],
+ $s);
+ // Replace pseudo diacritics
+ // These were used to produce accented characters. For instance an accented
+ // e would have been encoded by '^He - the backspace moving the cursor
+ // backward so both the single quote and the e would appear in the same
+ // character position. Umlauts were quite clever - they used a double quote
+ // as the accent mark over a normal character.
+
+ $s = preg_replace("/'\010([a-zA-Z])/","&\\1acute;",$s);
+ $s = preg_replace("/\"\010([a-zA-Z])/","&\\1uml;",$s);
+ $s = preg_replace("/\`\010([a-zA-Z])/","&\\1grave;",$s);
+ $s = preg_replace("/\^\010([a-zA-Z])/","&\\1circ;",$s);
+ $s = preg_replace("/\~\010([a-zA-Z])/","&\\1tilde;",$s);
+
+ // Ignore multiple underlines for the same character. These were
+ // most useful when sent to a line printer back in the day as it
+ // would type over the same character a number of times making it
+ // much darker (e.g. bold). I think there are only one or two
+ // instances of this in the current (2008) fortune cookie database.
+
+ $s = preg_replace("/(_\010)+/","_\010",$s);
+ // Map the characters which sit underneath a backspace.
+ // If you can come up with a regex to do all of the following
+ // madness - be my guest.
+ // It's not as simple as you think. We need to take something
+ // that has been backspaced over an arbitrary number of times
+ // and wrap a forward looking matching number of characters in
+ // HTML, whilst deciding if it's intended as an underline or
+ // strikeout sequence.
+
+ // Essentially we produce a string of '1' and '0' characters
+ // the same length as the source text.
+ // Any position which is marked '1' has been backspaced over.
+
+ $cursor = 0;
+ $dst = $s;
+ $bs_found = false;
+ for($x = 0; $x < strlen($s); $x ++) {
+ if($s[$x] == "\010" && $cursor) {
+ $bs_found = true;
+ $cursor --;
+ $dst[$cursor] = '1';
+ $dst[$x] = '0';
+ $continue;
+ }
+ else {
+ if($bs_found) {
+ $bs_found = false;
+ $cursor = $x;
+ }
+ $dst[$cursor] = '0';
+ $cursor ++;
+ }
+
+ }
+
+ $out = '';
+ $strike = false;
+ $bold = false;
+
+ // Underline sequence, convert to bold to avoid confusion with links.
+ // These were generally used for emphasis so it's a reasonable choice.
+ // Please note that this logic will fail if there is an underline sequence
+ // and also a strikeout sequence in the same fortune.
+
+ if(strstr($s,"_\010")) {
+ $len = 0;
+ for($x = 0; $x < strlen($s); $x ++) {
+ if($dst[$x] == '1') {
+ $len ++;
+ $bold = true;
+ }
+ else {
+ if($bold) {
+ $out .= '';
+ while($s[$x] == "\010")
+ $x ++;
+ $out .= substr($s,$x,$len);
+ $out .= '';
+ $x = $x + $len - 1;
+ $len = 0;
+ $bold = false;
+ }
+ else
+ $out .= $s[$x];
+ }
+ }
+ }
+
+ // These aren't seen very often these days - simulation of
+ // backspace/replace. You could occasionally see the original text
+ // on slower terminals before it got replaced. Once modems reached
+ // 4800/9600 baud in the late 70's and early 80's the effect was
+ // mostly lost - but if you find a really old fortune file you might
+ // encounter a few of these.
+
+ else {
+ for($x = 0; $x < strlen($s); $x ++) {
+ if($dst[$x] == '1') {
+ if($strike)
+ $out .= $s[$x];
+ else
+ $out .= ''.$s[$x];
+ $strike = true;
+ }
+ else {
+ if($strike)
+ $out .= '';
+ $strike = false;
+ $out .= $s[$x];
+ }
+ }
+ }
+
+ // Many of the underline sequences are also wrapped in asterisks,
+ // which was yet another way of marking ASCII as 'bold'.
+ // So if it's an underline sequence, and there are asterisks
+ // on both ends, strip the asterisks as we've already emboldened the text.
+
+ $out = preg_replace('/\*([^<]*<\/strong>)\*/',"\\1",$out);
+
+ // Finally, remove the backspace characters which we don't need anymore.
+
+ return str_replace("\010","",$out);
+}
+
+$result1 = do_query($table,$length,$numlines,$adult,$cat,1,$lang,$pattern,$regex,$equal);
+
+if(count($result1))
+ echo $result1[0];
+
+if($stats)
+ do_stats($table,$length,$numlines,$adult,$cat,1,$lang,$pattern,$regex,$equal);
+
+
diff --git a/fortunate/fortunate.css b/fortunate/fortunate.css
new file mode 100644
index 0000000..61813b7
--- /dev/null
+++ b/fortunate/fortunate.css
@@ -0,0 +1,7 @@
+.fortunate {
+ margin-top: 25px;
+ margin-left: 100px;
+ margin-bottom: 25px;
+ color: #000088;
+ font-size: 14px;
+}
\ No newline at end of file
diff --git a/fortunate/fortunate.php b/fortunate/fortunate.php
new file mode 100644
index 0000000..8c15caa
--- /dev/null
+++ b/fortunate/fortunate.php
@@ -0,0 +1,38 @@
+
+ */
+use Friendica\Core\Addon;
+use Friendica\Util\Network;
+
+// IMPORTANT: SET THIS to your fortunate server
+
+define('FORTUNATE_SERVER', 'hostname.com');
+
+function fortunate_install()
+{
+ Addon::registerHook('page_end', 'addon/fortunate/fortunate.php', 'fortunate_fetch');
+ if (FORTUNATE_SERVER == 'hostname.com' && is_site_admin()) {
+ notice('Fortunate addon requires configuration. See README');
+ }
+}
+
+function fortunate_uninstall()
+{
+ Addon::unregisterHook('page_end', 'addon/fortunate/fortunate.php', 'fortunate_fetch');
+}
+
+
+function fortunate_fetch(&$a, &$b)
+{
+ $a->page['htmlhead'] .= '' . "\r\n";
+
+ if (FORTUNATE_SERVER != 'hostname.com') {
+ $s = Network::fetchUrl('http://' . FORTUNATE_SERVER . '/cookie.php?numlines=2&equal=1&rand=' . mt_rand());
+ $b .= '
' . $s . '
';
+ }
+}
diff --git a/fortunate/fortunemod.sql.gz b/fortunate/fortunemod.sql.gz
new file mode 100644
index 0000000..2ce0e55
Binary files /dev/null and b/fortunate/fortunemod.sql.gz differ
diff --git a/fortunate/lang/C/messages.po b/fortunate/lang/C/messages.po
new file mode 100644
index 0000000..e69de29