diff --git a/files/class.app.php b/files/class.app.php index 03eb937..000767c 100644 --- a/files/class.app.php +++ b/files/class.app.php @@ -11,7 +11,7 @@ function __construct($minimal = false) { $this->config = $config; $this->config['cache'] = $this->config['path'] . "/files/cache/"; - $this->config['log'] = $this->config['path'] . "/files/log/"; + $this->config['log'] = $this->config['path'] . "/files/logs/"; // Connect to database $this->connectDB($this->config['db'], false); @@ -69,6 +69,8 @@ function __construct($minimal = false) { $this->articles = new articles($this); // Create forum object $this->forum = new forum($this); + // Create RSS object + $this->rss = new rss(); if (!is_array($custom_css)) $custom_css = Array(); diff --git a/files/class.articles.php b/files/class.articles.php index 3672f4e..61c2ba2 100644 --- a/files/class.articles.php +++ b/files/class.articles.php @@ -439,19 +439,24 @@ public function acceptArticle($article_id) { if ($result->category_id == 0) { $slug = '/news/' . $result->slug; $type = 'news'; + $cat_id = 0; } else { $slug = '/articles/' . $result->slug; $type = 'article'; + $cat_id = 1; } $this->app->feed->call($result->username, $type, $result->title, $slug); // Award medal to user $this->app->user->awardMedal('writer', 2, $result->user_id); + // Add to RSS + if(!$this->app->rss->storeRSS($result->title, $slug, substr($result->body, 0, 200).'...', $cat_id)) + $this->app->log->add('rss', 'Failed to add an item to the feed.'); + return true; } - /* * COMMENTS */ diff --git a/files/class.forum.php b/files/class.forum.php index 26eaf8c..700331d 100644 --- a/files/class.forum.php +++ b/files/class.forum.php @@ -102,7 +102,7 @@ public function getSections($parent=null) { } public function printThreadPost($post, $first=false, $last=false, $admin=false) { - if (!$post) return; + if (!$post) return; $post->first = $first; $post->last = $last; @@ -454,6 +454,10 @@ public function newThread($section, $title, $body) { $this->app->ssga->set_event('forum', 'thread.new', '/forum/' . $slug, $this->app->user->uid); $this->app->ssga->send(); + // Add to RSS + if(!$this->app->rss->storeRSS($title, $slug, substr($body, 0, 200).'...', 2)) + $this->app->log->add('rss', 'Failed to add an item to the feed.'); + return '/forum/' . $slug; } diff --git a/files/class.rss.php b/files/class.rss.php new file mode 100644 index 0000000..5a07905 --- /dev/null +++ b/files/class.rss.php @@ -0,0 +1,178 @@ +getConstants())) + throw IllegalArgumentException(); + + $this->value = $value; + } + + final public function __toString() { + return $this->value; + } + } + + class feedType extends enumBase { + const ATOM = "atom"; + const RSS = "rss"; + } + + class feedCategory extends enumBase { + const ARTICLE = "Article"; + const FORUM = "Forum"; + const NEWS = "News"; + } + + class rss { + public function __construct() { + //load configuration file + require('config.php'); + + if (!isset($config) || !is_array($config)) + throw new Exception('Config error'); + + $this->config = $config; + $this->connectDB($this->config['db'], false); + } + + /** + * Create database connection + * + * @param object $config Databse connection config + * @param boolean $debug Should the connection ignore errors or throw exceptions + * + * @return void + * + * @todo Create site config option that is passed in to the debug param + */ + protected function connectDB($config, $debug=true) { + // Connect to database + try { + $dsn = "{$config['driver']}:host={$config['host']}"; + $dsn .= (!empty($config['port'])) ? ';port=' . $config['port'] : ''; + $dsn .= ";dbname={$config['database']}"; + $this->db = new PDO($dsn, $config['username'], $config['password']); + + if ($debug) + $this->db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); + + $this->db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ); + $this->db->setAttribute(PDO::MYSQL_ATTR_FOUND_ROWS, true); + } catch(PDOException $e) { + die($e->getMessage()); + } + } + + /** + * Store a new feed item in the DB + * + * @param string $title Feed title + * @param string $slug Link to the thread/news item/article + * @param string $description A short descriptive text + * @param integer $catID To allow RSS readers to cathegorize the feeds + * + * @return Boolean + * + * @todo Create everything, pubDate will be done using SQL Now() + */ + public function storeRSS($title, $slug, $description, $catID) { + $category = feedCategory::ARTICLE; + + switch ($catID) { + case 0: + $category = feedCategory::NEWS; + break; + case 1: + $category = feedCategory::ARTICLE; + break; + case 2: + $category = feedCategory::FORUM; + break; + } + + $link = $this->config['domain'] . $slug; + + try { + // Insert article + $st = $this->db->prepare('INSERT INTO `rss_feed` (`unique_id`,`title`,`link`,`description`,`category`) + VALUES (UUID(),:title,:link,:description,:category)'); + $st->execute(array(':title' => $title, ':link' => $link, ':description' => $description, ':category' => $category)); + + $this->db->commit(); + } catch(PDOException $e) { + $this->db->rollBack(); + return False; + } + return True; + } + + /** + * Create and parse RSS/ATOM feed + * + * @param feedType $type To determine output method + * + * @return array + */ + public function generateRSS($type) { + $sql = 'SELECT * FROM `rss_feed` ORDER BY `id` DESC'; + $st = $this->db->prepare($sql); + $st->execute(); + $result = $st->fetchAll(); + + if ($type == feedType::RSS) { + $data = ''; + $data .= ''; + $data .= ''; + $data .= ''; + $data .= 'HackThis!! RSS'; + $data .= 'https://www.hackthis.co.uk/'; + $data .= 'Want to learn about hacking, hackers and network security. Try our hacking challenges or join our community to discuss the latest software and cracking tools.'; + $data .= 'en-gb'; + + foreach ($result as $row) { + $data .= ''; + $data .= ''.$row->title.''; + $data .= ''.$row->unique_id.''; + $data .= ''.$row->link.''; + $data .= ''.$row->description.''; + $data .= ''.$row->category.''; + $data .= ''.$row->pubDate.''; + $data .= ''; + } + + $data .= ''; + $data .= ' '; + } elseif ($type == feedType::ATOM) { + $objDateTime = new DateTime('NOW'); + $data = ''; + $data .= ''; + $data .= ''; + $data .= 'https://www.hackthis.co.uk/'; + $data .= 'HackThis!! ATOM'; + $data .= ''.$objDateTime->format(DateTime::ATOM).''; + $data .= ''; + $data .= 'Want to learn about hacking, hackers and network security. Try our hacking challenges or join our community to discuss the latest software and cracking tools.'; + + foreach ($result as $row) { + $data .= ''; + $data .= ''.$row->title.''; + $data .= ''.$row->unique_id.''; + $data .= ''; + $data .= ''.$row->pubDate.''; + $data .= ''.$row->description.''; + $data .= ''; + $data .= ''; + } + + $data .= ' '; + } else { + $data = null; + throw IllegalArgumentException(); + } + + return $data; + } + } +?> diff --git a/files/footer.php b/files/footer.php index 1d44826..629cce0 100644 --- a/files/footer.php +++ b/files/footer.php @@ -45,6 +45,10 @@
  • Facebook
  • Twitter
  • GitHub
  • +
  • +   + +
  • diff --git a/html/files/css/main.scss b/html/files/css/main.scss index a01c6af..7a62536 100644 --- a/html/files/css/main.scss +++ b/html/files/css/main.scss @@ -511,7 +511,7 @@ div.image { a { color: $text; - .icon-facebook, .icon-twitter, .icon-feed { + .icon-facebook, .icon-twitter, .icon-feed, .icon-rss, .icon-atom { padding-right: 3px; } diff --git a/html/files/css/rss.css b/html/files/css/rss.css new file mode 100644 index 0000000..e9c8c2c --- /dev/null +++ b/html/files/css/rss.css @@ -0,0 +1,83 @@ +rss, feed { + background-color: #000; + font-family: Verdana, Arial, Helvetica, sans-serif; + font-size: 0.7em; + line-height: 130%; + margin: 1em; +} +/* HEADER */ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +channel { + display: block; + background-color: #1e1e1e; + padding-bottom: 0.3em; +} +feed>id { + display: block; + color: #0C8200; + font-size: 130%; + font-weight: bold; + margin: 0.3em 0.3em 1em 0.5em; +} +channel>title, feed>title { + display: block; + padding: 0.4em 0.2em; + color: #0C8200; + border-bottom: 1px solid black; + font-weight: bold; + font-size: 140%; + background-color: #141414; +} +channel>link, feed>link { + display: block; + color: #aaa; + font-size: 130%; + font-weight: bold; + margin: 0.5em; +} +channel>description, feed>subtitle, feed>updated { + display: block; + color: #aaa; + font-size: 130%; + font-weight: bold; + margin: 0.3em 0.5em 1em 0.5em; +} +language, feed>entry>link , feed>entry>category { + display: none; +} +/* CONTENT */ +/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ +channel>item, feed>entry { + background-color: #383838; + border: 1px solid #094802; + clear: both; + display: block; + padding: 0 0 0.5em; + margin: 1em; +} +channel>item>title, feed>entry>title { + background-color: #141414; + color: #FFF; + display: block; + font-size: 110%; + font-weight: bold; + padding: 0.3em 0.5em; +} +channel>item>description, channel>item>category, channel>item>guid, feed>entry>summary, feed>entry>id{ + display: block; + float: none; + text-align: left; + padding: 0.2em 0.5em 0.4em; + color: #aaa; +} +channel>item>link { + color: #fff; + display: block; + margin: 0.5em 0.3em 1em 0.3em; +} +channel>item>pubDate, feed>entry>updated { + color: #aaa; + display: block; + font-size: 86%; + padding: 0 0.5em; +} diff --git a/html/files/images/atom.png b/html/files/images/atom.png new file mode 100644 index 0000000..3c7f809 Binary files /dev/null and b/html/files/images/atom.png differ diff --git a/html/files/images/rss.png b/html/files/images/rss.png new file mode 100644 index 0000000..d5694f0 Binary files /dev/null and b/html/files/images/rss.png differ diff --git a/html/rss/atom.php b/html/rss/atom.php new file mode 100644 index 0000000..2f25f65 --- /dev/null +++ b/html/rss/atom.php @@ -0,0 +1,9 @@ +generateRSS(feedType::ATOM); + + header('Content-Type: application/xml'); + echo $rssFeed; +?> diff --git a/html/rss/rss.php b/html/rss/rss.php new file mode 100644 index 0000000..2839ebf --- /dev/null +++ b/html/rss/rss.php @@ -0,0 +1,9 @@ +generateRSS(feedType::RSS); + + header('Content-Type: application/xml'); + echo $rssFeed; +?> diff --git a/sql/schema.sql b/sql/schema.sql index 100571b..365b755 100644 --- a/sql/schema.sql +++ b/sql/schema.sql @@ -559,6 +559,19 @@ CREATE TABLE IF NOT EXISTS `irc_logs` ( PRIMARY KEY (`log_id`) ) ENGINE=MyISAM; +/* + RSS FEED +*/ +CREATE TABLE IF NOT EXISTS `rss_feed` ( + `id` int(11) NOT NULL AUTO_INCREMENT, + `unique_id` varchar(36) NOT NULL, + `title` varchar(200) NOT NULL, + `link` varchar(200) NOT NULL, + `description` text NOT NULL, + `category` varchar(20) NOT NULL, + `pubDate` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, + PRIMARY KEY (`id`) +) ENGINE=InnoDB; /* TRIGGERS diff --git a/sql/testdata.sql b/sql/testdata.sql index 58d8d1e..a67b00d 100644 --- a/sql/testdata.sql +++ b/sql/testdata.sql @@ -7,6 +7,7 @@ DELETE FROM users_profile; DELETE FROM articles_categories; DELETE FROM articles_draft; DELETE FROM articles_audit; +DELETE FROM rss_feed; -- Add a new user. INSERT INTO users (`username`, `password`, `email`) VALUES ('Osaka', '$2a$10$C5Ko0q9jlcTHKsZYvzYJxOD7DsxTsO9RFrihVdY3sGnkflf/e5XKe', 'test@gmail.com'); @@ -90,6 +91,15 @@ INSERT INTO `articles_comments` (`comment_id`, `article_id`, `user_id`, `parent_ (5, 2, 1, 4, 'LIES!!', NULL, '2013-05-13 18:03:51'), (6, 2, 4, 2, 'Me again...', NULL, '2013-05-13 19:34:34'); +-- rss_feed +INSERT INTO `rss_feed` (`unique_id`, `title`, `link`, `description`, `category`) VALUES +('6a3091e4-a5bb-11e5-acec-000c29ce2aa6', 'Test data 1', 'https://www.hackthis.co.uk/', 'This is a simple test.', 'News'), +('71957a4d-a5bb-11e5-acec-000c29ce2aa6', 'Test data 2', 'https://www.hackthis.co.uk/', 'This is a simple test.', 'Article'), +('8e74f552-a5bb-11e5-acec-000c29ce2aa6', 'Test data 3', 'https://www.hackthis.co.uk/', 'This is a simple test.', 'Forum'), +('8e74fe6f-a5bb-11e5-acec-000c29ce2aa6', 'Test data 4', 'https://www.hackthis.co.uk/', 'This is a simple test.', 'News'), +('8e7505e9-a5bb-11e5-acec-000c29ce2aa6', 'Test data 5', 'https://www.hackthis.co.uk/', 'This is a simple test.', 'Article'), +('8e750e55-a5bb-11e5-acec-000c29ce2aa6', 'Test data 6', 'https://www.hackthis.co.uk/', 'This is a simple test.', 'Forum'); + -- Check The Data. SELECT '== USER =='; SELECT user_id, username, password FROM users;