aboutsummaryrefslogtreecommitdiff
path: root/lib/functions.php
diff options
context:
space:
mode:
authorArno Richter <oelna@oelna.de>2022-12-13 22:27:21 +0100
committerArno Richter <oelna@oelna.de>2022-12-13 22:27:44 +0100
commit0b075f3ea2616cfde4d976199a69ba631174a336 (patch)
treebb1feef58d9c714f6c3fb0b75f1e52b0181cf2af /lib/functions.php
parentf0e3ff408db8ee40611f75cdf96892f90034bd60 (diff)
downloadmicroblog-0b075f3ea2616cfde4d976199a69ba631174a336.tar.gz
microblog-0b075f3ea2616cfde4d976199a69ba631174a336.tar.bz2
microblog-0b075f3ea2616cfde4d976199a69ba631174a336.zip
gave up and sorted files into a directory structure. made snippets for header, nav and footer. made it easier to add additional css files as themes. prepare a little for addition of a real template engine. added a css reset file to share between themes, if warranted.
Diffstat (limited to 'lib/functions.php')
-rw-r--r--lib/functions.php258
1 files changed, 258 insertions, 0 deletions
diff --git a/lib/functions.php b/lib/functions.php
new file mode 100644
index 0000000..268808c
--- /dev/null
+++ b/lib/functions.php
@@ -0,0 +1,258 @@
+<?php
+
+function path($fragment=null) {
+ global $config;
+ if($fragment === null) return $config['path'];
+ return (!empty($config['path'][$fragment])) ? $config['path'][$fragment] : false;
+}
+
+function check_login() {
+ global $config;
+
+ if(isset($_COOKIE['microblog_login'])) {
+ if($_COOKIE['microblog_login'] === sha1($config['url'].$config['admin_pass'])) {
+ // correct auth data, extend cookie life
+ $domain = ($_SERVER['HTTP_HOST'] != 'localhost') ? $_SERVER['HTTP_HOST'] : false;
+ setcookie('microblog_login', sha1($config['url'].$config['admin_pass']), NOW+$config['cookie_life'], '/', $domain, false);
+
+ return true;
+ } else {
+ // invalid cookie data
+ unset($_COOKIE['microblog_login']);
+ setcookie('microblog_login', '', time()-3600, '/', $domain, false);
+ }
+ }
+
+ return false;
+}
+
+function db_insert($content, $timestamp=NOW) {
+ global $db;
+ if(empty($db)) return false;
+
+ $statement = $db->prepare('INSERT INTO posts (post_content, post_timestamp, post_guid) VALUES (:post_content, :post_timestamp, :post_guid)');
+ $statement->bindValue(':post_content', $content, PDO::PARAM_STR);
+ $statement->bindValue(':post_timestamp', $timestamp, PDO::PARAM_INT);
+ $statement->bindValue(':post_guid', uuidv4(), PDO::PARAM_STR);
+
+ $statement->execute();
+
+ return $db->lastInsertId();
+}
+
+function db_delete($post_id) {
+ global $db;
+ if(empty($db)) return false;
+ if(!is_numeric($post_id) || $post_id <= 0) return false;
+
+ /*
+ $statement = $db->prepare('DELETE FROM posts WHERE id = :id');
+ $statement->bindParam(':id', $post_id, PDO::PARAM_INT);
+ */
+
+ // mark as deleted instead (for undo?!)
+ $statement = $db->prepare('UPDATE posts SET post_deleted = :post_deleted WHERE id = :id');
+ $statement->bindValue(':id', $post_id, PDO::PARAM_INT);
+ $statement->bindValue(':post_deleted', time(), PDO::PARAM_INT);
+
+ $statement->execute();
+
+ return $statement->rowCount();
+}
+
+function db_update($post_id, $content, $timestamp=null) {
+ global $db;
+ if(empty($db)) return false;
+ if(empty($content)) return false;
+ if(!is_numeric($post_id) || $post_id <= 0) return false;
+
+ if($timestamp !== null) {
+ $statement = $db->prepare('UPDATE posts SET post_content = :post_content, post_edited = :post_edited, post_timestamp = :post_timestamp WHERE id = :id');
+ $statement->bindValue(':post_timestamp', $timestamp, PDO::PARAM_INT);
+ } else {
+ $statement = $db->prepare('UPDATE posts SET post_content = :post_content, post_edited = :post_edited WHERE id = :id');
+ }
+ $statement->bindValue(':id', $post_id, PDO::PARAM_INT);
+ $statement->bindValue(':post_content', $content, PDO::PARAM_STR);
+ $statement->bindValue(':post_edited', time(), PDO::PARAM_INT);
+
+ $statement->execute();
+
+ return $statement->rowCount();
+}
+
+function db_select_post($id=0) {
+ global $db;
+ if(empty($db)) return false;
+ if($id === 0) return false;
+
+ $statement = $db->prepare('SELECT * FROM posts WHERE id = :id LIMIT 1');
+ $statement->bindValue(':id', $id, PDO::PARAM_INT);
+ $statement->execute();
+ $row = $statement->fetch(PDO::FETCH_ASSOC);
+
+ return (!empty($row)) ? $row : false;
+}
+
+function db_select_posts($from, $amount=10, $sort='desc', $offset=0) {
+ global $db;
+ if(empty($db)) return false;
+ if(empty($from)) $from = time();
+ if($sort !== 'desc') $sort = 'asc';
+
+ $statement = $db->prepare('SELECT * FROM posts WHERE post_timestamp < :post_timestamp AND post_deleted IS NULL ORDER BY post_timestamp '.$sort.' LIMIT :limit OFFSET :page');
+ $statement->bindValue(':post_timestamp', $from, PDO::PARAM_INT);
+ $statement->bindValue(':limit', $amount, PDO::PARAM_INT);
+ $statement->bindValue(':page', $offset, PDO::PARAM_INT);
+ $statement->execute();
+ $rows = $statement->fetchAll(PDO::FETCH_ASSOC);
+
+ return (!empty($rows)) ? $rows : false;
+}
+
+function db_posts_count() {
+ global $config;
+ global $db;
+ if(empty($db)) return false;
+
+ $statement = $db->prepare('SELECT COUNT(*) AS posts_count FROM posts');
+ $statement->execute();
+ $row = $statement->fetch(PDO::FETCH_ASSOC);
+
+ return (int) $row['posts_count'];
+}
+
+/* function that pings the official micro.blog endpoint for feed refreshes */
+function ping_microblog() {
+ global $config;
+ $ping_url = 'https://micro.blog/ping';
+ $feed_url = $config['url'].'/feed/json';
+
+ $ch = curl_init($ping_url);
+ curl_setopt($ch, CURLOPT_POST, true);
+ curl_setopt($ch, CURLOPT_POSTFIELDS, 'url='.urlencode($feed_url));
+ curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
+ curl_setopt($ch, CURLOPT_HEADER, true);
+ curl_setopt($ch, CURLOPT_NOBODY, true);
+ curl_setopt($ch, CURLOPT_TIMEOUT, 10);
+ curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
+
+ $response = curl_exec($ch);
+ $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
+
+ return ($status == 200) ? true : false;
+}
+
+function rebuild_feeds($amount=10) {
+
+ $posts = db_select_posts(NOW+60, $amount, 'desc');
+
+ rebuild_json_feed($posts);
+ rebuild_atom_feed($posts);
+}
+
+function rebuild_json_feed($posts=[]) {
+ global $config;
+
+ if (!file_exists(ROOT.DS.'feed')) {
+ mkdir(ROOT.DS.'feed', 0755);
+ }
+
+ $filename = ROOT.DS.'feed'.DS.'feed.json';
+
+ $feed = array(
+ 'version' => 'https://jsonfeed.org/version/1',
+ 'title' => 'status updates by '.$config['microblog_account'],
+ 'description' => '',
+ 'home_page_url' => $config['url'],
+ 'feed_url' => $config['url'].'/feed/feed.json',
+ 'user_comment' => '',
+ 'favicon' => '',
+ 'author' => array('name' => $config['microblog_account']),
+ 'items' => array()
+ );
+
+ foreach($posts as $post) {
+
+ $feed['items'][] = array(
+ 'id' => ($post['post_guid'] ? 'urn:uuid:'.$post['post_guid'] : $config['url'].'/'.$post['id']),
+ 'url' => $config['url'].'/'.$post['id'],
+ 'title' => '',
+ 'content_html' => $post['post_content'],
+ 'date_published' => gmdate('Y-m-d\TH:i:s\Z', $post['post_timestamp'])
+ );
+ }
+
+ if(file_put_contents($filename, json_encode($feed, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES))) {
+ return true;
+ } else return false;
+}
+
+function rebuild_atom_feed($posts=[]) {
+ global $config;
+
+ if (!file_exists(ROOT.DS.'feed')) {
+ mkdir(ROOT.DS.'feed', 0755);
+ }
+
+ $filename = ROOT.DS.'feed'.DS.'feed.xml';
+
+ $feed = '<?xml version="1.0" encoding="UTF-8" ?'.'>'.NL;
+ $feed .= '<feed xmlns="http://www.w3.org/2005/Atom">'.NL;
+ $feed .= '<author><name>'.$config['microblog_account'].'</name></author>'.NL;
+ $feed .= '<title>status updates by '.$config['microblog_account'].'</title>'.NL;
+ $feed .= '<id>'.$config['url'].'</id>'.NL;
+ $feed .= '<updated>'.gmdate('Y-m-d\TH:i:s\Z').'</updated>'.NL;
+
+ foreach($posts as $post) {
+
+ $published = gmdate('Y-m-d\TH:i:s\Z', $post['post_timestamp']);
+ $updated = ($post['post_edited'] > $post['post_timestamp']) ? gmdate('Y-m-d\TH:i:s\Z', $post['post_edited']) : $published;
+
+ $feed .= '<entry>'.NL;
+ $feed .= '<title type="text">'.date('Y-m-d H:i', $post['post_timestamp']).'</title>'.NL;
+ $feed .= '<link rel="alternate" type="text/html" href="'.$config['url'].'/'.$post['id'].'" />'.NL;
+ $feed .= '<id>'.($post['post_guid'] ? 'urn:uuid:'.$post['post_guid'] : $config['url'].'/'.$post['id']).'</id>'.NL;
+ $feed .= '<updated>'.$updated.'</updated>'.NL;
+ $feed .= '<published>'.$published.'</published>'.NL;
+ $feed .= '<content type="text">'.$post['post_content'].'</content>'.NL;
+ $feed .= '</entry>'.NL;
+ }
+
+ $feed .= '</feed>';
+
+ if(file_put_contents($filename, $feed)) {
+ return true;
+ } else return false;
+}
+
+function uuidv4($data = null) { // https://stackoverflow.com/a/15875555/3625228
+
+ $data = $data ?? openssl_random_pseudo_bytes(16);
+ assert(strlen($data) == 16);
+
+ $data[6] = chr(ord($data[6]) & 0x0f | 0x40); // set version to 0100
+ $data[8] = chr(ord($data[8]) & 0x3f | 0x80); // set bits 6-7 to 10
+
+ return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
+}
+
+function twitter_post_status($status='') {
+ global $config;
+ require_once(ROOT.DS.'lib'.DS.'twitter_api.php');
+
+ if(empty($status)) return array('errors' => 1);
+ if(empty($config['twitter']['oauth_access_token']) ||
+ empty($config['twitter']['oauth_access_token_secret']) ||
+ empty($config['twitter']['consumer_key']) ||
+ empty($config['twitter']['consumer_secret'])) return array('errors' => 2);
+
+ $url = 'https://api.twitter.com/1.1/statuses/update.json';
+ $postfields = array(
+ 'status' => $status,
+ 'trim_user' => 1
+ );
+
+ $twitter = new TwitterAPIExchange($config['twitter']);
+ return $twitter->buildOauth($url, 'POST')->setPostfields($postfields)->performRequest();
+}