Browse Source

Initial Commit of tCMS (version 1.1.2)

George Baugh 11 năm trước cách đây
mục cha
commit
9ba9c6db62
71 tập tin đã thay đổi với 1856 bổ sung0 xóa
  1. 21 0
      CHANGELOG
  2. 1 0
      blog/1-Welcome!.post
  3. 6 0
      css/avatars.css
  4. 6 0
      css/compat/ie.css
  5. 30 0
      css/compat/ie6-7.css
  6. 14 0
      css/compat/ie6.css
  7. 34 0
      css/print.css
  8. 239 0
      css/screen.css
  9. 91 0
      css/structure.css
  10. 1 0
      fileshare/readme.txt
  11. BIN
      img/avatar/humm.gif
  12. BIN
      img/icon/favicon.ico
  13. BIN
      img/icon/rss.png
  14. BIN
      img/mime/denied.gif
  15. BIN
      img/mime/missing.gif
  16. BIN
      img/mime/tsarchive.gif
  17. BIN
      img/mime/tsaudio.gif
  18. BIN
      img/mime/tscode.gif
  19. BIN
      img/mime/tsdoc.png
  20. BIN
      img/mime/tsdownload.gif
  21. BIN
      img/mime/tsfile.gif
  22. BIN
      img/mime/tsfolder-up.gif
  23. BIN
      img/mime/tsfolder.gif
  24. BIN
      img/mime/tsimage.gif
  25. BIN
      img/mime/tsmodel.gif
  26. BIN
      img/mime/tsmovie.gif
  27. BIN
      img/mime/tsprop.png
  28. BIN
      img/mime/tsschematic.gif
  29. BIN
      img/mime/tssoftware.gif
  30. BIN
      img/mime/tssticky.gif
  31. BIN
      img/sys/testpattern.jpg
  32. 35 0
      index.js
  33. 128 0
      index.php
  34. 17 0
      license.txt
  35. 1 0
      special/about.inc
  36. 1 0
      special/footbar.inc
  37. 1 0
      special/leftbar.inc
  38. 1 0
      special/rightbar.inc
  39. 17 0
      special/title.inc
  40. BIN
      sys/admin/.bengine.inc.swp
  41. BIN
      sys/admin/.settings.inc.swo
  42. 118 0
      sys/admin/bengine.inc
  43. 27 0
      sys/admin/config/main.json
  44. 7 0
      sys/admin/config/users.inc
  45. 12 0
      sys/admin/config/users.json
  46. 25 0
      sys/admin/index.js
  47. 50 0
      sys/admin/index.php
  48. 102 0
      sys/admin/mbengine.inc
  49. 24 0
      sys/admin/settings.inc
  50. 100 0
      sys/blogroll.inc
  51. 1 0
      sys/fileshare/include/audio-player-noswfobject.js
  52. 129 0
      sys/fileshare/include/audio-player-uncompressed.js
  53. 3 0
      sys/fileshare/include/audio-player.js
  54. 1 0
      sys/fileshare/include/blacklist
  55. BIN
      sys/fileshare/include/cortado.jar
  56. 12 0
      sys/fileshare/include/external.inc
  57. 12 0
      sys/fileshare/include/forbidden.inc
  58. 19 0
      sys/fileshare/include/license.txt
  59. 5 0
      sys/fileshare/include/notfound
  60. BIN
      sys/fileshare/include/player.swf
  61. 49 0
      sys/fileshare/sanitize.inc
  62. 17 0
      sys/fileshare/showaudio.inc
  63. 36 0
      sys/fileshare/showcode.inc
  64. 15 0
      sys/fileshare/showdoc.inc
  65. 144 0
      sys/fileshare/showfiles.inc
  66. 15 0
      sys/fileshare/showimg.inc
  67. 23 0
      sys/fileshare/showpost.inc
  68. 19 0
      sys/fileshare/showvideo.inc
  69. 128 0
      sys/microblog.inc
  70. 65 0
      sys/rss/blog.php
  71. 54 0
      sys/rss/microblog.php

+ 21 - 0
CHANGELOG

@@ -0,0 +1,21 @@
+BUGFIX RELEASE 1.1.1:
+
+Bug Fixes:
+*Made responsive JS/CSS more friendly to noscript users, made logic not so shitty
+*Added default favicon
+*Fixed lots of time related bugs in the linklog pages (microblog.inc, mbengine.inc, mbeditor.inc)
+*Made errors in linklog not cause php to die(), instead making it safely error out (so as not to mangle following dom)
+*Fixed a bug that prevented editing linklog posts
+*Fixed structure.css not loading on /sys/admin pages
+
+Misc. Code Changes:
+*Moved all json config files to sys/admin/config. No reason to have the main json definition in the toplevel directory for all to see.
+
+NEW WITH VERSION 1.1:
+
+*Design has been made more responsive, using only % and em values for width, positioning, etc. Also added a small JS file to further aid in responsiveness (the usual button show/hide stuff that JS is suited to).
+*Authoring, managing blog posts can now be done via the admin page, for those dissatisfied/unfamiliar with Drag and Drop blogging.
+
+Version 1.0 Release Notes:
+
+*Initial release. Not much to say other than that it has all the stuff I want out of a CMS. All changes from here on out will be bugfixing and feature addition, mostly as a boon to anyone who may choose to use tCMS. 

+ 1 - 0
blog/1-Welcome!.post

@@ -0,0 +1 @@
+Thank you for trying tCMS! To get started, please see the documentation over at tcms.troglodyne.net if you haven't already.

+ 6 - 0
css/avatars.css

@@ -0,0 +1,6 @@
+/*User Images set here*/
+a.Nobody {
+ background-image: url(../img/avatar/humm.gif);
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/avatar/hydra.png', sizingMethod='scale');
+ -ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/avatar/hydra.png', sizingMethod='scale')"
+}

+ 6 - 0
css/compat/ie.css

@@ -0,0 +1,6 @@
+a.rss, a.logo, a.usericon, a.avatar {
+ background-image: none !important;
+}
+p#linkcontainer {
+ width: 6em;
+}

+ 30 - 0
css/compat/ie6-7.css

@@ -0,0 +1,30 @@
+div.linkbar {
+ float: left;
+ clear: none;
+}
+div.kontent {
+ float: right;
+ clear: none;
+}
+img.titlebar {
+}
+a.logo {
+ font-size: 1.5em;
+ font-family: courier;
+ color: white;
+ text-decoration: none;
+}
+a.logo:hover {
+ text-decoration: underline;
+}
+#lefttitle {
+ visibility: hidden;
+ display: none;
+}
+#midtitle {
+ float: left;
+ vertical-align: middle;
+}
+#righttitle {
+ float: right;
+}

+ 14 - 0
css/compat/ie6.css

@@ -0,0 +1,14 @@
+body {
+ height: 100%;
+ overflow-y: auto;
+}
+div.topbar {
+ position: absolute;
+}
+#lefttitle {
+ visibility: hidden;
+ display: none;
+}
+#midtitle {
+ float: left;
+}

+ 34 - 0
css/print.css

@@ -0,0 +1,34 @@
+#littlemenu, #topkek, #leftbar, #rightbar, #footbar {
+ display: none !important;
+}
+#kontent {
+ text-align: left;
+ font-family: sans-serif;
+ font-size: 12pt;
+}
+p.title {
+ font-weight: bold;
+}
+ul {
+ list-style-type: disc;
+}
+table {
+ border-spacing: 0px;
+}
+td {
+ padding: 0px;
+}
+pre {
+ font-family: sans-serif;
+ font-size: 12pt;
+ margin-top: 5px;
+ margin-bottom: 5px;
+ white-space: pre-wrap;
+}
+h3.blogtitles {
+ margin-bottom: 5px;
+ margin-bottom: 5px;
+}
+em.blogdetail {
+ font-size: 8pt;
+}

+ 239 - 0
css/screen.css

@@ -0,0 +1,239 @@
+/*SCREEN.CSS - All styling for the screen view of the site should be done here*/
+
+/*Global tag based changes go here*/
+a {
+ color: rgb(0,0,0);
+ border: 0px;
+}
+body {
+ color: black;
+ background-color: gray;
+ font-family: sans-serif;
+ font-size: 150%;
+}
+img {
+ border: 0px;
+}
+table {
+ border-spacing: 0px;
+}
+td {
+ padding: 0px;
+ margin: 0px;
+}
+hr {
+ width: 100%
+}
+ul {
+ list-style-type: disc;
+}
+pre {
+ margin-top: .25em;
+ margin-bottom: .25em;
+ white-space: pre-wrap;
+ font-family: sans-serif;
+ font-size: 1em;
+}
+textarea {
+ height: 10em;
+ width: 99%;
+ background-color: #333;
+ height: 15em;
+}
+
+/*Major DOM Element Styling goes below*/
+#topkek {
+ background: rgb(0,0,0);
+ box-shadow: 0 .25em .5em black;
+}
+.toplel {
+ color: white;
+ vertical-align: middle;
+}
+#lefttitle {
+ font-family: courier;
+ font-size: 1em;
+ font-weight: bold;
+}
+#midtitle {
+ text-align: center;
+}
+#righttitle {
+ text-align: right;
+}
+#righttitle a, #configbar a {
+ padding-right: .5em;
+ border-right: .1em #333 solid;
+}
+#righttitle a:last-child, #configbar a:last-child {
+ border-right: 0;
+}
+#menubutton {
+ vertical-align: middle;
+}
+#littlemenu {
+ background-color: rgb(0,0,0);
+ background-color: rgba(0,0,0,.75);
+ border-bottom-left-radius: 1em;
+}
+#leftbar {
+
+}
+#kontent {
+ background: rgb(255,255,255); /*IE Fallback*/
+ background: rgba(255,255,255,.90);
+ border-radius: 0px 0px 1em 1em;
+ box-shadow: 0 .5em 1em black;
+}
+#rightbar {
+ 
+}
+#footbar {
+ color: white;
+ background-color: black;
+ text-align: center;
+}
+#stories {
+ vertical-align: top;
+}
+
+/*Icon/Button styles below*/
+.rss {
+ border: 0px;
+ height: 1em;
+ width: 1em;
+ background-size: 1em;
+ background-image: url(../img/icon/rss.png);
+ display: inline-block;
+ filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/icon/rss.png', sizingMethod='scale');
+ -ms-filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='../img/icon/rss.png', sizingMethod='scale')";
+}
+.usericon, .buddyicon {
+ width: 1em;
+ height: 1em;
+ float: right;
+ background-size: 1em;
+}
+.avatar {
+ width: 3em;
+ height: 3em;
+ float: left;
+ background-size: 3em;
+}
+button#clickme {
+ display: inline;
+ float: right;
+ box-shadow: 0px 0px 0.5em #66CCFF;
+ padding: 0 .25em;
+ font-size: .60em;
+ background-color: #333;
+ border-radius: .5em;
+ border: .25em solid black;
+ color: red;
+}
+button#clickme:active {
+ padding-left: .30em;
+ border-color: gray;
+}
+.coolbutton, .cooltext, textarea {
+ box-sizing: border-box;
+ border-radius: .5em;
+ border: .25em solid black;
+ color: white;
+ padding: .25em;
+ margin: .25em;
+}
+.coolbutton {
+ box-shadow: 0 0 .5em black;
+ background-color: #333;
+}
+.coolbutton:active {
+ padding-left: .30em;
+ border-color: gray;
+}
+.cooltext {
+ background-color: #333;
+}
+#Submissions input, #Submissions textarea {
+ width: 95%;
+ display: block;
+ margin-right: auto;
+ margin-left: auto;
+}
+#Submissions textarea {
+ height: 20em;
+ vertical-align: top;
+}
+
+/*Various other stylistic stuff below*/
+a.nudes {
+ color: rgb(0,255,0);
+}
+img.icon {
+ height: 1em;
+ width: 1em;
+}
+img.mblogimg, {
+ max-width: 100%;
+ display: block;
+}
+h3.blogtitles {
+ margin-bottom: .5em;
+ margin-top: 0px;
+}
+em.blogdetail {
+ font-size: .8em;
+}
+a.topbar {
+ text-decoration: none;
+ color: white;
+}
+a:hover.topbar {
+ text-decoration: underline;
+}
+img.titlebar {
+ height: 1.5em;
+ float: left;
+}
+p.title {
+ padding-top: 0px;
+ margin-top: 0px;
+ font-weight: bold;
+}
+p#linkcontainer {
+ padding: 2em .5em .5em .5em;
+ background: rgb(0,0,0); /*IE Fallback*/
+ background: rgba(0,0,0,.75);
+ border-bottom-left-radius: 1em;
+ margin-top: 0px;
+}
+span.bold {
+ font-weight: bold;
+}
+p.posteditortitle {
+ margin: 0px;
+ font-weight: bold;
+ border-bottom: .1em solid gray;
+ padding: .5em;
+}
+.disabled {
+ display: none;
+}
+.clear {
+ clear: both;
+}
+.mbedit_text {
+ display: inline-block;
+}
+.mbedit_button {
+ width: 5em;
+ display: inline-block;
+}
+#newposttitle {
+ width: 95%;
+ display: block;
+ box-sizing: border-box;
+}
+#newpostlink {
+ color: #990000;
+}

+ 91 - 0
css/structure.css

@@ -0,0 +1,91 @@
+/*First, we start off with specifying what parts of the DOM we want hidden*/
+/*Make sure it uses !important so that any JS helper for responsiveness doesn't override this*/
+#leftbar, #rightbar, #footbar, #midtitle {
+ display: none !important;
+}
+
+/*Now, on to positioning of the elements*/
+body {
+ position: relative;
+ margin: 0;
+ width: 100%;
+ min-height: 100vh;
+ max-height: 100%;
+}
+#topkek {
+ display: table;
+ position: fixed;
+ z-index: 2;
+ top: 0;
+ width: 100%;
+ height: 1.5em;
+}
+.toplel {
+ display: table-cell;
+}
+#lefttitle {
+ padding-left: .5em;
+ max-width: 50%;
+ min-width: 33%;
+}
+#midtitle {
+ width: 33%;
+}
+#righttitle {
+ min-width: 33%;
+ max-width: 50%;
+ padding-right: .5em;
+}
+#righttitle a, #configbar a {
+ display: inline-block;
+}
+#menubutton {
+ display: none;
+ min-width: 2%;
+ max-width: 33%;
+ padding-right: .5em;
+}
+#littlemenu {
+ display: none;
+ position: fixed;
+ z-index: 3;
+ top: 1.5em;
+ right: 0px;
+ padding: 0px .5em .5em .5em;
+}
+#littlemenu a {
+ display: block;
+}
+#kontainer {
+ display: table;
+ width: 100%;
+ padding-bottom: 2.5em;
+}
+.kontained {
+ display: table-cell;
+}
+#leftbar {
+ width: 6em;
+ padding-right: .5em;
+}
+#kontent {
+ padding: 2em .5em .5em .5em;
+ min-height: 50%;
+ max-width: 100%;
+ margin-top: 0px;
+}
+#rightbar {
+ width: 6em;
+ padding-left: .5em;
+}
+#footbar {
+ position: absolute;
+ bottom: 0;
+ width: 100%;
+ height: 1.5em;
+}
+#stories {
+ padding: 0px .5em .5em .5em;
+ width: 80%;
+ display: table-cell;
+}

+ 1 - 0
fileshare/readme.txt

@@ -0,0 +1 @@
+This is the fileshare. You should place stuff you wanna share here.

BIN
img/avatar/humm.gif


BIN
img/icon/favicon.ico


BIN
img/icon/rss.png


BIN
img/mime/denied.gif


BIN
img/mime/missing.gif


BIN
img/mime/tsarchive.gif


BIN
img/mime/tsaudio.gif


BIN
img/mime/tscode.gif


BIN
img/mime/tsdoc.png


BIN
img/mime/tsdownload.gif


BIN
img/mime/tsfile.gif


BIN
img/mime/tsfolder-up.gif


BIN
img/mime/tsfolder.gif


BIN
img/mime/tsimage.gif


BIN
img/mime/tsmodel.gif


BIN
img/mime/tsmovie.gif


BIN
img/mime/tsprop.png


BIN
img/mime/tsschematic.gif


BIN
img/mime/tssoftware.gif


BIN
img/mime/tssticky.gif


BIN
img/sys/testpattern.jpg


+ 35 - 0
index.js

@@ -0,0 +1,35 @@
+window.onload = navResize;
+window.onresize = navResize;
+
+function navResize() {
+	if (window.innerWidth < 900) {
+		//Hide original div, enable Menu Button 
+		document.getElementById('righttitle').style.display = 'none';
+		document.getElementById('menubutton').style.display = 'table-cell';
+		document.getElementById('leftbar').style.display = 'none';
+                document.getElementById('rightbar').style.display = 'none';
+	} else {
+		//Show original div, hide Menu Button 
+		document.getElementById('righttitle').style.display = '';
+		document.getElementById('leftbar').style.display = '';
+                document.getElementById('rightbar').style.display = '';
+		document.getElementById('menubutton').style.display = 'none';
+		document.getElementById('littlemenu').style.display = 'none';
+	}
+}
+
+function showMenu() {
+	if (document.getElementById('littlemenu').style.display != 'none') {
+		if (document.getElementById('littlemenu').style.display == 'block') {
+			document.getElementById('littlemenu').style.display = '';
+			document.getElementById('leftbar').style.display = 'none';
+                	document.getElementById('rightbar').style.display = 'none';
+			return;
+		}
+		var pasta = document.getElementById('righttitle').innerHTML;
+		document.getElementById('littlemenu').innerHTML = pasta;
+		document.getElementById('littlemenu').style.display = 'block';
+		document.getElementById('leftbar').style.display = '';
+                document.getElementById('rightbar').style.display = '';
+	} 
+}

+ 128 - 0
index.php

@@ -0,0 +1,128 @@
+<!doctype html>
+<html dir="ltr" lang="en-US">
+ <head>
+  <?php
+   //SRSBIZNUSS below - you probably shouldn't edit this unless you know what you are doing
+   //GET validation/sanitation and parameter variable definitions below
+   if (!$_SERVER["HTTPS"]) {
+    $protocol = "http";
+   } else {
+    $protocol = "https";
+   }
+   if (!$_GET['nav']) {
+    $nav = '';
+   }
+   else {
+    $nav = $_GET['nav'];
+   }
+   if (!$_GET['post']) {
+    $post = '';
+   }
+   else {
+    $post = $_GET['post'];
+   }
+
+   //input sanitization
+   $pwd=$post;
+   include 'sys/fileshare/sanitize.inc';
+   if ($san == 1) {
+    return(0);
+   };
+   extract(json_decode(file_get_contents('sys/admin/config/main.json'),true));
+  ?>
+  <meta charset="utf-8" />
+  <meta name="description" content="A Simple CMS by teodesian.net"/>
+  <link rel="stylesheet" type="text/css" href="css/structure.css" />
+  <link rel="stylesheet" type="text/css" href="css/screen.css" media="screen" />
+  <link rel="stylesheet" type="text/css" href="css/print.css" media="print" />
+  <link rel="stylesheet" type="text/css" href="css/avatars.css" />
+  <!--Compatibility Stylesheets-->
+  <!--[if lte IE 8]>
+   <link rel="stylesheet" type="text/css" href="css/compat/ie.css">
+  <![endif]-->
+  <!--[if lte IE 7]>
+   <link rel="stylesheet" type="text/css" href="css/compat/ie6-7.css">
+  <[endif]-->
+  <!--[if IE 6]>
+   <link rel="stylesheet" type="text/css" href="css/compat/ie6.css">
+  <![endif]-->
+  <link rel="icon" type="image/vnd.microsoft.icon" href="img/icon/favicon.ico" />
+  <script src="index.js"></script>
+  <title>
+   <?php
+    echo $htmltitle;
+   ?>
+  </title>
+ </head>
+ <body>
+  <div id="topkek">
+   <?php
+    //Site's Titlebar comes in here
+    include $toptitle;
+   ?>
+  </div>
+  <div id="littlemenu">
+  </div>
+  <div id="kontainer">
+   <div id="leftbar" class="kontained">
+    <?php
+     include $leftbar;
+    ?>
+   </div>
+   <div id="kontent" class="kontained">
+    <?php
+      /*$kontent basically is just a handler for what PHP include needs to be loaded
+      based on the context passed via GET params - if you wanna add another, add an
+      elseif case then specify the next number in the nav index along with the
+      corresponding file to include above.*/
+      if (empty($nav)) {
+        $kontent = $home;
+      }
+      elseif ($nav == 1) {
+        $kontent = $fileshare;
+      }
+      elseif ($nav == 2) {
+        $kontent = $microblog;
+        $editable = 0;
+      }
+      elseif ($nav == 3) {
+        $kontent = $blog;
+      }
+      elseif ($nav == 4) {
+        $kontent = $about;
+      }
+      elseif ($nav == 5) {
+        $kontent = $postloader;
+      }
+      elseif ($nav == 6) {
+        $kontent = $codeloader;
+      }
+      elseif ($nav == 7) {
+        $kontent = $audioloader;
+      }
+      elseif ($nav == 8) {
+        $kontent = $videoloader;
+      }
+      elseif ($nav == 9) {
+        $kontent = $imgloader;
+      }
+      elseif ($nav == 10) {
+        $kontent = $docloader;
+      }
+      //Main Content Display Frame goes below
+      include $kontent;
+    ?>
+   </div>
+   <div id="rightbar" class="kontained">
+    <?php
+     include $rightbar;
+    ?>
+   </div>
+  </div>
+   <div id="footbar">
+    <?php
+     include $footbar;
+    ?>
+   </div>
+ </body>
+</html>

+ 17 - 0
license.txt

@@ -0,0 +1,17 @@
+Copyright 2013 by Thomas A. and George S. Baugh
+The scripts/code/etc. that comprise tCMS are all released under the GPL.
+See https://gnu.org/licenses/gpl.html for details.
+
+    This program is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+    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.
+
+This projects also includes a version of Cortado (http://www.theora.org/cortado/)
+and audioplayer.js (http://wpaudioplayer.com/download/).
+For those two pieces of software, they are being used according to their licences,
+so for anything having to do with those, refer to their respective licenses.

+ 1 - 0
special/about.inc

@@ -0,0 +1 @@
+This is supposed to be a page all about the author(s) of this website. Nothing is here yet though.

+ 1 - 0
special/footbar.inc

@@ -0,0 +1 @@
+Potzrebie

+ 1 - 0
special/leftbar.inc

@@ -0,0 +1 @@
+Potzrebie

+ 1 - 0
special/rightbar.inc

@@ -0,0 +1 @@
+Potzrebie

+ 17 - 0
special/title.inc

@@ -0,0 +1,17 @@
+<div id="lefttitle" class="toplel">
+ <?php
+  echo $htmltitle;
+ ?>
+</div>
+<div id="midtitle" class="toplel">
+
+</div>
+<div id="righttitle" class="toplel">
+ <a href="index.php?nav=2" title="Micro Blog" class="topbar">LinkLog</a>
+ <a href="index.php?nav=3" title="Blog" class="topbar">Blog</a>
+ <a href="index.php?nav=1&amp;dir=fileshare" title="File Share" class="topbar">Fileshare</a>
+ <a href="index.php?nav=4" title="About" class="topbar">About</a>
+</div>
+<div id="menubutton" style="display: none;">
+ <button title="Menu" id="clickme" onclick="showMenu();return false;">&#9776;</button>
+</div>

BIN
sys/admin/.bengine.inc.swp


BIN
sys/admin/.settings.inc.swo


+ 118 - 0
sys/admin/bengine.inc

@@ -0,0 +1,118 @@
+<script type="text/javascript">
+//JS to load posts when you click on them to edit
+
+  window.postsLoaded = {};
+
+  function toggle(id) {
+   var foo = document.getElementById(id);
+   if (foo.style.display == 'block') {
+     foo.style.display = 'none';
+   } else {
+     foo.style.display = 'block';
+   }
+ }
+
+ function loadpost(fragment_url,element_id) {
+   if (window.postsLoaded[element_id]) return;
+   var element = document.getElementById(element_id);
+   element.innerHTML = 'Loading ...';
+   var xmlhttp = new XMLHttpRequest();
+   xmlhttp.open("GET", fragment_url);
+   xmlhttp.onreadystatechange = function() {
+     if (xmlhttp.readyState == 4 && xmlhttp.status == 200) {
+       element.innerHTML = xmlhttp.responseText;
+       window.postsLoaded[element_id] = true;
+     }
+   }
+   xmlhttp.send(null);
+ }
+</script>
+<!--Post Creation DOM-->
+<p class="posteditortitle">
+ <a id="newpostlink" href="javascript:toggle('newpost')" title="Toggle hiding of New Post editor">
+  Create New Post
+ </a>
+</p>
+<div id="newpost" class="disabled">
+ <form method="POST">
+  <input type="hidden" name="id" value="CHANGEME" />
+  Post Title:<br />
+  <input id="newposttitle" name="title" class="cooltext" />
+  Post Body: <span style="font-style: italic;">
+   All HTML Tags accepted! Please see <a href="" title="Manual">here</a> regarding how to disable auto-formatting,
+   or if additional help is required.
+  </span>
+  <textarea id="newposttext" name="content"></textarea><br />
+  <input type="submit" name="mod" value="Create Post" class="coolbutton" />
+ </form>
+ <hr />
+</div>
+<?php
+ /*Initialize vars, get directory contents*/
+ $postincrementer = 0;
+ $JSAIDS = "";
+ $dir = $_SERVER['DOCUMENT_ROOT'].$basedir.'/'.$blogdir;
+ $postlisting = scandir($dir);
+ rsort($postlisting, SORT_NUMERIC);
+ /*Post Manipulation*/
+ if ($_POST["id"] != "") {
+  /*Post Deletion*/
+  if ($_POST["mod"] == "Delete Post") {
+   $fh = unlink($_POST["id"]);
+   if (!$fh) die("ERROR: couldn't delete ".$_POST['id'].", check permissions");
+   echo "Deleted ".$_POST["id"]."<br />";
+  /*Post Editing*/
+  } elseif ($_POST["mod"] == "Commit Edit") {
+   $fh = fopen($_POST["id"], 'w');
+   if (!$fh) die("ERROR: couldn't write to ".$_POST['id'].", check permissions");
+   fwrite($fh,stripslashes($_POST["content"]));
+   fclose($fh);
+   echo "Edited ".$_POST["id"]."<br />";
+  /*Post Creation*/
+  } elseif ($_POST["mod"] == "Create Post") {
+    $pnum = intval(substr($postlisting[0],0,strpos($postlisting[0],'-'))) + 1;
+    $id = $dir.$pnum."-".$_POST["title"].".post";
+    /*echo $id."<br />";
+    var_dump($postlisting[0]);
+    var_dump($_POST);
+    die("FOOBAR");*/
+    $fh = fopen($id, 'w'); 
+    if (!$fh) die("ERROR: Couldn't Write ".$id.", check permissions");
+    fwrite($fh,stripslashes($_POST["content"]));
+    fclose($fh);
+    echo "Created ".$id."<br />";
+  /*Catchall*/
+  } else {
+    die("Nothing to do");
+  }
+ }
+  /*Spit out the posts into the DOM so that they can be edited/deleted*/
+  $postlisting = scandir($dir);
+  rsort($postlisting, SORT_NUMERIC);
+  foreach ($postlisting as $key=>$val) {
+    $id = $_SERVER["DOCUMENT_ROOT"].$basedir.$blogdir.basename($val);
+    $posttitle = strstr($val,'.', true);
+  if (!empty($posttitle)) {
+   $postincrementer++;
+   print "
+    <p id=\"post".$postincrementer."\" class=\"posteditortitle\">
+    <a id=\"link".$postincrementer."\" href=\"javascript:toggle('postcontent".$postincrementer."')\" title=\"Toggle hiding of post editor\">
+    ".$posttitle."
+    </a>
+    </p>
+    <div id=\"postcontent".$postincrementer."\" class=\"disabled\">
+     <form method=\"POST\">
+     <input type=\"hidden\" name=\"id\" value=\"$id\" />
+      <textarea id=\"innerHTML".$postincrementer."\" name=\"content\" \">
+      </textarea><br />
+      <input type=\"submit\" name=\"mod\" value=\"Commit Edit\" class=\"coolbutton\">
+      <input type=\"submit\" name=\"mod\" value=\"Delete Post\" class=\"coolbutton\">
+     </form>
+    </div>";
+   $JSAIDS.="document.getElementById('link".$postincrementer."').addEventListener('click',function () {loadpost('/".$basedir.$blogdir.$val."','innerHTML".$postincrementer."',false);});\nwindow.postsLoaded['innerHTML".$postincrementer."'] = false;";
+  }
+ }
+print "<script type=\"text/javascript\">\n
+ window.onload = function() { $JSAIDS };\n
+ </script>";
+?>

+ 27 - 0
sys/admin/config/main.json

@@ -0,0 +1,27 @@
+{
+    "toptitle" : "special/title.inc",
+    "leftbar" : "special/leftbar.inc",
+    "rightbar" : "special/rightbar.inc",
+    "footbar" : "special/footbar.inc",
+    "home" : "sys/blogroll.inc",
+    "fileshare" : "sys/fileshare/showfiles.inc",
+    "microblog" : "sys/microblog.inc",
+    "blog" : "sys/blogroll.inc",
+    "about" : "special/about.inc",
+    "postloader" : "sys/fileshare/showpost.inc",
+    "codeloader" : "sys/fileshare/showcode.inc",
+    "audioloader" : "sys/fileshare/showaudio.inc",
+    "videoloader" : "sys/fileshare/showvideo.inc",
+    "imgloader" : "sys/fileshare/showimg.inc",
+    "docloader" : "sys/fileshare/showdoc.inc",
+    "blogdir" : "blog/",
+    "microblogdir" : "microblog/",
+    "filesharedir" : "fileshare",
+    "rssdir" : "sys/rss/",
+    "icondir" : "img/mime/",
+    "basedir" : "",
+    "htmltitle" : "Unconfigured tCMS Website",
+    "blogtitle" : "Blog",
+    "microblogtitle" : "Linklog",
+    "timezone" : "America/Chicago"
+}

+ 7 - 0
sys/admin/config/users.inc

@@ -0,0 +1,7 @@
+<?php
+if ($_SERVER['REMOTE_USER'] == "admin") {
+    $poster = "admin";
+} else {
+    $poster = "Nobody";
+}
+?>

+ 12 - 0
sys/admin/config/users.json

@@ -0,0 +1,12 @@
+{
+  "tcmsUsers" : {
+    "admin" : {
+      "fullName" : "The Administrator",
+      "email" : "admin@example.com"
+    },
+    "Nobody" : {
+      "fullName" : "Anonymous",
+      "email" : "dev@null.io"
+    }
+  }
+}

+ 25 - 0
sys/admin/index.js

@@ -0,0 +1,25 @@
+window.onload = navResize;
+window.onresize = navResize;
+
+function navResize() {
+	if (window.innerWidth < 700) {
+		//Hide original div, create new one if it doesn't exist
+		document.getElementById('configbar').style.display = 'none';
+		document.getElementById('menubutton').style.display = '';
+	} else {
+		//Show original div, axe new one
+		document.getElementById('configbar').style.display = '';
+		document.getElementById('menubutton').style.display = 'none';
+		document.getElementById('littlemenu').style.display = 'none';
+	}
+}
+
+function showMenu() {
+	if (document.getElementById('littlemenu').style.display == 'none') {
+		var pasta = document.getElementById('configbar').innerHTML;
+		document.getElementById('littlemenu').innerHTML = pasta;
+		document.getElementById('littlemenu').style.display = '';
+	} else {
+		document.getElementById('littlemenu').style.display = 'none';
+	}
+}

+ 50 - 0
sys/admin/index.php

@@ -0,0 +1,50 @@
+<!doctype html>
+<html dir="ltr" lang="en-US">
+ <head>
+  <meta charset="utf-8" />
+  <meta name="description" content="tCMS Control Panel"/>
+  <link rel="stylesheet" type="text/css" href="../../css/structure.css" />
+  <link rel="stylesheet" type="text/css" href="../../css/screen.css" media="screen" />
+  <link rel="stylesheet" type="text/css" href="../../css/print.css" media="print" />
+  <link rel="icon" type="image/vnd.microsoft.icon" href="../../img/icon/favicon.ico" />
+  <title>tCMS Admin</title>
+  <?php
+   extract(json_decode(file_get_contents('config/main.json'),true));
+  ?>
+  <script src="/sys/admin/index.js"></script>
+ </head>
+ <body>
+  <div id="topkek" style="text-align: center; vertical-align: middle;">
+   <span id="configbar">
+    <a class="topbar" title="Edit Various Settings" href="index.php">Settings</a>
+    <a class="topbar" title="Blog Writer" href="index.php?nav=1">Blog Writer</a>
+    <a class="topbar" title="Pop off about Stuff" href="index.php?nav=2">MicroBlogger</a>
+   </span>
+   <button style="display: none;" id="menubutton" onClick="showMenu();return false;">
+    &#9776;
+   </button>
+  </div>
+  <div id="littlemenu" style="display: none;">
+  </div>
+  <div id="kontent" style="display: block;">
+   <?php
+    if ($_SERVER["HTTPS"] != "") {
+     $protocol = "https";
+    } else {
+     $protocol = "http";
+    }
+    $nav = $_GET['nav'];
+    if (empty($nav)) {
+     $kontent = "settings.inc";
+    }
+    elseif ($nav == 1) {
+     $kontent = "bengine.inc";
+    }
+    elseif ($nav == 2) {
+     $kontent = "mbengine.inc";
+    }
+    include $kontent;
+   ?>
+  </div>
+ </body>
+</html>

+ 102 - 0
sys/admin/mbengine.inc

@@ -0,0 +1,102 @@
+<?php
+include "config/users.inc";
+$badpost=false;
+$errmsg = array();
+if (isset($_POST["title"]) && $_POST["title"] != "") {
+	if (!isset($_POST['URL']) || $_POST["URL"] == "") {
+		$badpost = true;
+		$errmsg[] = "<em style=\"color: red\">* No url provided.</em><br />";
+	}
+	$url=stripslashes($_POST["URL"]);
+	//Error catching below
+	if (!filter_var($url,FILTER_VALIDATE_URL)) {
+		$badpost = true;
+		$errmsg[] = "<em style=\"color: red;\">* \"$url\" is not a valid ASCII URL.</em><br />";
+	}
+	if (!empty($_POST["IMG"]) && !filter_var(stripslashes($_POST["IMG"]),FILTER_VALIDATE_URL)) {
+    		$badpost = true;
+		$errmsg[] = "<em style=\"color: red;\">* Image \"$url\" is not a valid ASCII URL.</em><br />";
+  	}
+  	if (!empty($_POST["AUD"]) && !filter_var(stripslashes($_POST["AUD"]),FILTER_VALIDATE_URL)) {
+    		$badpost = true;
+		$errmsg[] = "<em style=\"color: red;\">* Audio \"$url\" is not a valid ASCII URL.</em><br />";
+  	}
+  	if (!isset($_POST["comment"]) || $_POST["comment"] == '') {
+    		$badpost = true;
+		$errmsg[] = "<em style=\"color: red;\">* Comment is blank.</em><br />";
+  	}
+	if (!$badpost) { 
+    		$title = stripslashes($_POST["title"]);
+    		$image = stripslashes($_POST["IMG"]);
+    		$audio = urlencode(stripslashes($_POST["AUD"]));
+    		$audiosrc = stripslashes($_POST["AUD"]);
+    		$comment = stripslashes($_POST["comment"]);
+    		$news2write = "<h3 class=\"blogtitles\"><a href=\"".$url."\">".$title."</a>";
+    		$news2write = $news2write."<a class=\"usericon ".$poster."\" href=\"index.php?nav=4\" title=\"Posted by ".$poster."\"></a>";
+    		$news2write = $news2write."</h3>";
+    		if ($image != "") {
+      			$news2write = $news2write."<img class=\"mblogimg\" src=\"".$image."\" />";
+    		}
+    		if ($audio != "") {
+      			$curlurl = "http://".$_SERVER["SERVER_NAME"]."/".$basedir.$microblog;
+      			$ch = curl_init($cur_url);
+      			curl_setopt($ch,CURLOPT_RETURNTRANSFER,true);
+      			curl_setopt($ch,CURLOPT_HEADER,false);
+      			$page_content = curl_exec($ch);
+      			$matches = array();
+      			preg_match('/audioplayer_[0-9]*/',$page_content,$matches);
+      			$numfound = count($matches);
+      			$audioinc = $numfound;
+      			++$audioinc;
+      			$news2write = $news2write."<p id=\"audioplayer_$audioinc\">Download Audio <a href=\"$audiosrc\">Here</a>.</p><script type=\"text/javascript\">AudioPlayer.embed(\"audioplayer_$audioinc\", {soundFile: \"$audio\"});</script><br />";
+    		};
+    		$news2write = $news2write.$comment."<hr />";
+		$tdtime = new DateTime(null, new DateTimeZone($timezone));
+    		$today = $tdtime->format('m.d.y');
+    		$now = $tdtime->format('H:i:s');
+    		$newsdir = $_SERVER["DOCUMENT_ROOT"].'/'.$basedir.$microblogdir;
+    		@mkdir($newsdir.$today);
+    		$fh = fopen($newsdir.$today."/".$now, 'w');
+		if (!$fh) die("ERROR: couldn't write $newsdir$today/$now to $newsdir$today, check permissions");
+		fwrite($fh,$news2write);
+		fclose($fh);
+	} else {
+		print "Could not post due to errors:<br />";
+		foreach ($errmsg as $err) {echo $err;}
+		print "POST Variable Dump below:<br /><em style=\"color: red\">";
+		var_dump($_POST);
+		print "</em>";
+	}
+} elseif ($_POST["id"] != "") {
+	if ($_POST["content"] == "") {
+		$res = unlink($_POST["id"]);
+		if (!$res) die("ERROR: couldn't delete ".$_POST['id'].", check permissions");
+		echo "Deleted ".$_POST["id"]."<br />";
+  } else {
+		$fh = fopen($_POST["id"], 'w');
+		if (!$fh) die("ERROR: couldn't write to ".$_POST['id'].", check permissions");
+    fwrite($fh,stripslashes($_POST["content"]));
+    fclose($fh);
+		echo "Edited ".$_POST["id"]."<br />";
+  }
+}
+?>
+<div style="width: 100%; display: table;">
+ <div style="width: 20%; display: table-cell;">
+  <p class="title">Submissions:</p>
+  <form id="Submissions" method="POST">
+   Title<br /><input class="cooltext" type="text" name="title" />
+   URL<br /><input class="cooltext" type="text" name="URL" />
+   Image<br /><input class="cooltext" type="text" name="IMG" />
+   Audio<br /><input class="cooltext" type="text" name="AUD" />
+   Comments:<br /><textarea class="cooltext" name="comment">Potzrebie</textarea>
+   <input class="coolbutton" type="submit" value="Publish" text="Publish" />
+  </form>
+ </div>
+ <div id="stories">
+  <?php
+   $editable = 1;
+   include $_SERVER["DOCUMENT_ROOT"].'/'.$basedir."sys/microblog.inc";
+  ?>
+ </div>
+</div>

+ 24 - 0
sys/admin/settings.inc

@@ -0,0 +1,24 @@
+<p class="title">
+ tCMS General Settings - Edit these Locally (for now).
+</p>
+<hr />
+<p class="title">
+ Configuration Variables
+</p>
+For now, every big config variable is set in /sys/admin/config/main.json. Refer to it if you know what you are doing.<br /><br />
+Soon I will have a users.json defining what users are there (or alias http auth users).
+<p class="title">
+Themes: Coming soon.
+</p>
+<!--<form id="themeForm" method="post" name="themeForm">
+<select name="selectedTheme">
+  <?php
+    
+
+    //echo '<option></option>';
+  ?>
+ </select>
+</form>-->
+<p>
+  Want to write your own theme (or modify one since I haven't finished the theme selector here)? Please see the <a href="teodesian.net/tCMS/index.php?nav=5&post=fileshare/manual/Chapter 03-Customization.post" title="GET UR MIND RITE">styling guide</a>.
+</p>

+ 100 - 0
sys/blogroll.inc

@@ -0,0 +1,100 @@
+<p class="title">
+ <a title="RSS" href="sys/rss/blog.php" class="rss"></a>
+ <?php
+  echo $blogtitle;
+ ?>
+ <hr />
+</p>
+<?php
+
+if ($_GET['post'] != "") {
+    $post=urldecode($_GET['post']);
+    $statz = stat($post);
+    $uid = $statz['uid'];
+    $udata = posix_getpwuid($uid);
+    $user = $udata['name'];
+
+    $date =  date("F d Y H:i:s", filemtime($post));
+
+    if (stristr($post,'.') != ".post") {
+        $title = basename($post);
+    } else {
+        $title = substr(strstr(basename($post),'-'),1,-5);
+    }
+
+    echo "<h3 class=\"blogtitles\"><a title=permalink href=\"index.php?nav=3&post=".urlencode($post)."\">$title</a></h3>\n";
+    echo "<em class=\"blogdetail\">Last modified on $date UTC by $user</em><hr />\n\n";
+    include "$post";
+    echo "\n<hr /><a style=\"textalign: center;\" href=\"".$_SERVER["PHP_SELF"]."?nav=3\">Back to Blog</a>";
+} else {
+
+$offset=0;
+if ($_GET['index'] != "" && !is_int($_GET['index'])) {
+	$offset = 10*$_GET['index'];
+}
+
+
+	//slurp up the files
+	$files = glob("blog/*.post");
+	$guid = count($files);
+
+	//sort by filename
+	
+	//initialize an array to house sort results
+	$files2 = array();
+	$files2 = array_pad($files2,$guid,0);
+
+	for ($i=0; $i<$guid; $i++) {
+		$j = explode('-',basename($files[$i]));
+		$j = $j[0];
+		$j = (int)$j;
+		$j--;
+		$files2[$j] = $files[$i];
+	}
+
+	$slen = count($files2)-1;
+	$ctr=0;
+	$older=0;
+
+	for ($i=$slen-$offset; $i>-1; $i--) {
+		$shitpost=$files2[$i];
+
+		//using a counter here to know when to stop, since I don't know how many posts there will be
+		if ($ctr > 9) {
+			$older=1;
+			break;
+		}
+		$ctr++;
+
+		$statz = stat($shitpost);
+		$uid = $statz['uid'];
+		$udata = posix_getpwuid($uid);
+		$user = $udata['name'];
+
+		$date =  date("F d Y H:i:s", filemtime($shitpost));
+
+		$title = substr(strstr(basename($shitpost),'-'),1,-5);
+
+		echo "<h3 class=\"blogtitles\"><a title=permalink href=\"".$_SERVER["PHP_SELF"]."?nav=3&post=".urlencode($shitpost)."\">$title</a></h3>\n";
+		echo "<em class=\"blogdetail\">Last modified on $date UTC by $user</em><br />\n";
+		include $shitpost;
+		echo "<hr />";
+	};
+
+echo "<table width=\"100%\"><tr><td>";
+if ($older) {
+	$offset=$_GET['index']+1;
+	echo "<a href=\"".$_SERVER["PHP_SELF"]."?nav=3&index=$offset\">Older Posts</a>";
+}
+echo "</td><td style=\"text-align: right;\">";
+if ($_GET['index'] != "") {
+	$offset=$_GET['index']-1;
+	if ($offset == 0) {
+		echo "<a href=\"".$_SERVER["PHP_SELF"]."?nav=3\">Newer Posts</a>";
+	} else {
+		echo "<a href=\"".$_SERVER["PHP_SELF"]."?nav=3&index=$offset\">Newer Posts</a>";
+	}
+}
+echo "</td></tr></table>\n";
+}
+?>

+ 1 - 0
sys/fileshare/include/audio-player-noswfobject.js

@@ -0,0 +1 @@
+var AudioPlayer=function(){var H=[];var D;var F="";var A={};var E=-1;var G="9";function B(I){if(document.all&&!window[I]){for(var J=0;J<document.forms.length;J++){if(document.forms[J][I]){return document.forms[J][I];break}}}return document.all?window[I]:document[I]}function C(I,J,K){B(I).addListener(J,K)}return{setup:function(J,I){F=J;A=I;if(swfobject.hasFlashPlayerVersion(G)){swfobject.switchOffAutoHideShow();swfobject.createCSS("p.audioplayer_container span","visibility:hidden;height:24px;overflow:hidden;padding:0;border:none;")}},getPlayer:function(I){return B(I)},addListener:function(I,J,K){C(I,J,K)},embed:function(I,K){var N={};var L;var J={};var O={};var M={};for(L in A){N[L]=A[L]}for(L in K){N[L]=K[L]}if(N.transparentpagebg=="yes"){J.bgcolor="#FFFFFF";J.wmode="transparent"}else{if(N.pagebg){J.bgcolor="#"+N.pagebg}J.wmode="opaque"}J.menu="false";for(L in N){if(L=="pagebg"||L=="width"||L=="transparentpagebg"){continue}O[L]=N[L]}M.name=I;M.style="outline: none";O.playerID=I;swfobject.embedSWF(F,I,N.width.toString(),"24",G,false,O,J,M);H.push(I)},syncVolumes:function(I,K){E=K;for(var J=0;J<H.length;J++){if(H[J]!=I){B(H[J]).setVolume(E)}}},activate:function(I,J){if(D&&D!=I){B(D).close()}D=I},load:function(K,I,L,J){B(K).load(I,L,J)},close:function(I){B(I).close();if(I==D){D=null}},open:function(I,J){if(J==undefined){J=1}B(I).open(J==undefined?0:J-1)},getVolume:function(I){return E}}}();

+ 129 - 0
sys/fileshare/include/audio-player-uncompressed.js

@@ -0,0 +1,129 @@
+var AudioPlayer = function () {
+	var instances = [];
+	var activePlayerID;
+	var playerURL = "";
+	var defaultOptions = {};
+	var currentVolume = -1;
+	var requiredFlashVersion = "9";
+	
+	function getPlayer(playerID) {
+		if (document.all && !window[playerID]) {
+			for (var i = 0; i < document.forms.length; i++) {
+				if (document.forms[i][playerID]) {
+					return document.forms[i][playerID];
+					break;
+				}
+			}
+		}
+		return document.all ? window[playerID] : document[playerID];
+	}
+	
+	function addListener (playerID, type, func) {
+		getPlayer(playerID).addListener(type, func);
+	}
+	
+	return {
+		setup: function (url, options) {
+			playerURL = url;
+			defaultOptions = options;
+			if (swfobject.hasFlashPlayerVersion(requiredFlashVersion)) {
+				swfobject.switchOffAutoHideShow();
+				swfobject.createCSS("p.audioplayer_container span", "visibility:hidden;height:24px;overflow:hidden;padding:0;border:none;");
+			}
+		},
+
+		getPlayer: function (playerID) {
+			return getPlayer(playerID);
+		},
+		
+		addListener: function (playerID, type, func) {
+			addListener(playerID, type, func);
+		},
+		
+		embed: function (elementID, options) {
+			var instanceOptions = {};
+			var key;
+			
+			var flashParams = {};
+			var flashVars = {};
+			var flashAttributes = {};
+	
+			// Merge default options and instance options
+			for (key in defaultOptions) {
+				instanceOptions[key] = defaultOptions[key];
+			}
+			for (key in options) {
+				instanceOptions[key] = options[key];
+			}
+			
+			if (instanceOptions.transparentpagebg == "yes") {
+				flashParams.bgcolor = "#FFFFFF";
+				flashParams.wmode = "transparent";
+			} else {
+				if (instanceOptions.pagebg) {
+					flashParams.bgcolor = "#" + instanceOptions.pagebg;
+				}
+				flashParams.wmode = "opaque";
+			}
+			
+			flashParams.menu = "false";
+			
+			for (key in instanceOptions) {
+				if (key == "pagebg" || key == "width" || key == "transparentpagebg") {
+					continue;
+				}
+				flashVars[key] = instanceOptions[key];
+			}
+			
+			flashAttributes.name = elementID;
+			flashAttributes.style = "outline: none";
+			
+			flashVars.playerID = elementID;
+			
+			swfobject.embedSWF(playerURL, elementID, instanceOptions.width.toString(), "24", requiredFlashVersion, false, flashVars, flashParams, flashAttributes);
+			
+			instances.push(elementID);
+		},
+		
+		syncVolumes: function (playerID, volume) {	
+			currentVolume = volume;
+			for (var i = 0; i < instances.length; i++) {
+				if (instances[i] != playerID) {
+					getPlayer(instances[i]).setVolume(currentVolume);
+				}
+			}
+		},
+		
+		activate: function (playerID, info) {
+			if (activePlayerID && activePlayerID != playerID) {
+				getPlayer(activePlayerID).close();
+			}
+
+			activePlayerID = playerID;
+		},
+		
+		load: function (playerID, soundFile, titles, artists) {
+			getPlayer(playerID).load(soundFile, titles, artists);
+		},
+		
+		close: function (playerID) {
+			getPlayer(playerID).close();
+			if (playerID == activePlayerID) {
+				activePlayerID = null;
+			}
+		},
+		
+		open: function (playerID, index) {
+			if (index == undefined) {
+				index = 1;
+			}
+			getPlayer(playerID).open(index == undefined ? 0 : index-1);
+		},
+		
+		getVolume: function (playerID) {
+			return currentVolume;
+		}
+		
+	}
+	
+}();

Những thai đổi đã bị hủy bỏ vì nó quá lớn
+ 3 - 0
sys/fileshare/include/audio-player.js


+ 1 - 0
sys/fileshare/include/blacklist

@@ -0,0 +1 @@
+img/sys/special/microblog/css/

BIN
sys/fileshare/include/cortado.jar


+ 12 - 0
sys/fileshare/include/external.inc

@@ -0,0 +1,12 @@
+<center>
+<?php
+
+$pwd = $_GET['dir'];
+
+echo '<p style="vertical-align: middle;">';
+echo '<img src="img/mime/denied.gif" alt="deeenied" />';
+echo 'No External linking Allowed';
+echo '<img src="img/mime/denied.gif" alt="deeniedagain" />';
+echo '</p>'
+
+?>

+ 12 - 0
sys/fileshare/include/forbidden.inc

@@ -0,0 +1,12 @@
+<center>
+<?php
+
+$pwd = $_GET['dir'];
+
+echo '<p style="vertical-align: middle;">';
+echo '<img src="img/mime/denied.gif" alt="deeenied" />';
+echo 'Access to '.$pwd.' Denied';
+echo '<img src="img/mime/denied.gif" alt="deeniedagain" />';
+echo '</p>'
+
+?>

+ 19 - 0
sys/fileshare/include/license.txt

@@ -0,0 +1,19 @@
+Copyright (c) 2010 Martin Laine
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.

+ 5 - 0
sys/fileshare/include/notfound

@@ -0,0 +1,5 @@
+<p style="text-align: center; vertical-align: center;">
+ <img src="img/mime/missing.gif" alt="burritos" />
+  File not found
+ <img src="img/mime/missing.gif" alt="getdownagain" />
+</p>

BIN
sys/fileshare/include/player.swf


+ 49 - 0
sys/fileshare/sanitize.inc

@@ -0,0 +1,49 @@
+<?php 
+$san=0;
+//Forbid anything starting with / and anything with .. in it; also remote links
+ $badguy = strpos($pwd, '/');
+ $badguys = strstr($pwd,'..');
+
+ $http = stristr($pwd,'http://');
+ $https = stristr($pwd,'https://');
+ $ftp = stristr($pwd, 'ftp://');
+ $gop = stristr($pwd, 'gopher://');
+
+ if ($badguy === 0) {
+        include 'sys/fileshare/include/forbidden.inc';
+        $san=1;
+	return(0);
+ }
+
+ if ($badguys !== FALSE) {
+        include 'sys/fileshare/include/forbidden.inc';
+        $san=1;
+	return(0);
+ }
+
+if ($http !== FALSE || $https !== FALSE || $ftp !== FALSE || $gop !== FALSE) {
+        include 'sys/fileshare/include/external.inc';
+        $san=1;
+	return(0);
+}
+
+ //Check the list of other forbidden directories
+ $blist = "sys/fileshare/include/blacklist";
+ $channel = fopen($blist, "r");
+ $contents = fread($channel, filesize($blist));
+ $readable = preg_split('[/]', $contents);
+ $countchocula = count($readable)-1;
+
+ for ($a = 0; $a < $countchocula; $a++) {
+
+        $patterns = '^'.$readable[$a];
+        $foos = ereg($patterns, $pwd);
+
+        if ($foos == 1) {
+                include 'sys/fileshare/include/forbidden.inc';
+		$san=1;
+                return(0);
+        }
+
+ }
+?>

+ 17 - 0
sys/fileshare/showaudio.inc

@@ -0,0 +1,17 @@
+<?php
+//Listen to audio -- ONLY MP3s IN THIS HOUSE
+//$title = basename($post);
+ $tag = id3_get_tag($post);
+ $date =  date("F d Y H:i:s", filemtime($post));
+ $parent = dirname($post);
+ echo "<h3><a class=nudes title=permalink href=\"$post\">".$tag["title"]."</a></h3>";
+ echo "By: ".$tag["artist"]."<br />";
+ echo "$date UTC<br/ >";
+ echo "<p id=\"audioplayer_1\">Alternative content</p>";
+ echo "<script type=\"text/javascript\">\n";
+ echo "AudioPlayer.embed(\"audioplayer_1\", {soundFile: \"".$protocol."://teodesian.net/".$post."\"});\n";
+ echo "</script><br />\n";
+ echo "Description:<br />";
+ echo $tag["comment"];
+ echo "<a title=back href=\"index.php?nav=1&dir=$parent\"><img alt=back src=".$icondir."tsfolder-up.gif />$parent</a><hr />";
+?>

+ 36 - 0
sys/fileshare/showcode.inc

@@ -0,0 +1,36 @@
+<?php
+//Browse text files (like code)
+$statz = stat($post);
+$uid = $statz['uid'];
+$udata = posix_getpwuid($uid);
+$user = $udata['name'];
+$date =  date("F d Y H:i:s", filemtime($post));
+$title = basename($post);
+echo "<h3 class=\"blogtitles\"><a title=permalink href=\"$post\">$title</a></h3>\n";
+echo "Last modified on $date UTC by $user<br /><br />\n";
+$text = file_get_contents($post);
+
+// Convert UTF-8 string to HTML entities
+$text = mb_convert_encoding($text, 'HTML-ENTITIES',"UTF-8");
+// Convert HTML entities into ISO-8859-1
+$text = html_entity_decode($text,ENT_NOQUOTES, "ISO-8859-1");
+// Convert characters > 127 into their hexidecimal equivalents
+for($i = 0; $i < strlen($text); $i++) {
+ $letter = $text[$i];
+ $num = ord($letter);
+ if($num>127) {
+  $out .= "&#$num;";
+ } elseif ($letter == "\n") {
+  $out .= "<br />";
+ } elseif ($letter == "\t") {
+  $out .= "&#8194;&#8194;&#8194;&#8194;";
+ } elseif ($letter == " ") {
+  $out .= "&#8194;";
+ } else {
+  $out .=  $letter;
+ }
+}
+echo $out;
+$parent = dirname($post);
+echo "<hr /><a title=back href=\"index.php?nav=1&dir=$parent\"><img alt=back src=img/mime/tsfolder-up.gif />$parent</a>";
+?>

+ 15 - 0
sys/fileshare/showdoc.inc

@@ -0,0 +1,15 @@
+<?php
+// Using googgle docs until a decent PDF viewer actually exists
+// PDFObject would be nice if it didn't require a browser plugin
+$statz = stat($post);
+$uid = $statz['uid'];
+$udata = posix_getpwuid($uid);
+$user = $udata['name'];
+$date =  date("F d Y H:i:s", filemtime($post));
+$title = basename($post);
+$parent = dirname($post);
+echo "<a title=back href=\"index.php?nav=1&dir=$parent\"><img alt=back src=img/mime/tsfolder-up.gif />$parent</a><hr />";
+echo "<h3 class=blogtitles><a title=permalink href=\"$post\">$title</a></h3>\n";
+echo "<em class=blogdetail>Last modified on $date UTC by $user</em><br /><br />\n";
+echo "<iframe src=\"http://docs.google.com/gview?url=http://teodesian.net/$post&embedded=true\" style=\"width:100%; min-height:500px;\" frameborder=\"0\"></iframe>";
+?>

+ 144 - 0
sys/fileshare/showfiles.inc

@@ -0,0 +1,144 @@
+<?php
+ $dir = $_GET['dir'];
+ $pwd = $dir;
+
+ //These variables are to check whether the directory we will link to exists, and to know what directory we are in 
+ $check = @scandir($pwd.'/../', 1);
+ $splode = preg_split('[/]', $pwd, -1);
+ $predir = count($splode)-1;
+ $test = array_slice($splode, -1, 1);
+
+ #Establish MIME Type data
+ #Link is used to specify special handler URLS for particular files
+ #File specifies the link icon
+ $arch_types = array(".tar",".gz",".z7",".bz",".bz2",".zip",".rar",".lsz",
+		    "link" => "",
+		    "file" => "tsarchive.gif");
+ //Only MP3 supported for now
+ $audio_types = array(".mp3",
+		     "link" => "index.php?nav=7&post=",
+		     "file" => "tsaudio.gif");
+ $video_types = array(".ogv",
+		     "link" => "index.php?nav=8&post=",
+		     "file" => "tsmovie.gif");
+ $image_types = array(".bmp",".gif",".jpg",".jpeg",".png",".ico",".svg",".xpm",
+		     "link" => "index.php?nav=9&post=",
+		     "file" => "tsimage.gif");
+ $schematic_types = array(".dwg",".dxf",".cad",".gcode",".mcode",
+			 "link" => "",
+			 "file" => "tsschematic.gif");
+ $model_types = array(".stl",".blend",".3ds",
+		     "link" => "",
+		     "file" => "tsmodel.gif");
+ $binary_types = array(".exe",".o",".dll",".so",".jnilib",".a",".bin",".hex",
+		      "link" => "",
+		      "file" => "tssoftware.gif");
+ $code_types = array(".py",".c",".h",".js",".php",".tcl",".m",".txt",
+		    "link" => "index.php?nav=6&post=",
+		    "file" => "tscode.gif");
+ $doc_types = array(".htm",".html",".post",
+		   "link" => "index.php?nav=5&post=",
+                   "file" => "tsdoc.png");
+ $legacy_types = array(".pdf",".doc",".docx",".xls",".xlsx",".ppt",".pptx",".pages",".ai",".psd",".tiff",".tif",".eps",".ps",".xps",
+		   "link" => "index.php?nav=10&post=",
+		   "file" => "tsprop.png");
+ $mime_types = array($arch_types,$audio_types,$video_types,$image_types,$schematic_types,$model_types,$binary_types,$code_types,$doc_types,$legacy_types);
+
+ //Find the directory contents
+ $ls = @scandir($pwd, 1);
+
+// $dlist = array_filter($ls,function ($a) {return is_dir($a);});
+ $dban1 = '.';
+ $dban2 = '..';
+ $dkey = array_search($dban1,$ls);
+ if ($dkey!==false){unset($ls[$dkey]);};
+ $dkey = array_search($dban2,$ls);
+ if ($dkey!==false){unset($ls[$dkey]);};
+
+ //See if this directory is even there
+ if (@in_array($test[0], $check)) {
+	echo 'Directory listing for '.$pwd;
+	echo '<hr />';
+	$cnt = count($ls);
+    $dlist = array();
+    $flist = array();
+
+    //Trying to sort here
+    for ($n = 0; $n < $cnt; $n++) {
+        $filechk = @scandir($pwd.'/'.$ls[$n]);
+        if (! $filechk) {
+            foreach($mime_types as $mimes) {
+                foreach($mimes as $type) {
+                    $sstrn = @stristr($ls[$n],$type);
+                    if($sstrn !== FALSE && strlen($sstrn) == strlen($type)) {
+                        array_push($flist, $ls[$n]);
+                    }
+                }
+            }
+        }
+        else {
+            array_push($dlist, $ls[$n]);
+        }
+    }
+    sort($dlist);
+    sort($flist);
+    $ls = array_merge($dlist,$flist);
+	
+    //Yeah, I know this looks familiar. There's prolly some way to combine this by setting the $ikon and $link vars as an array.
+    for ($n = 0; $n < $cnt; $n++) {
+
+		//create links based on whether we are a file, and if otherwise we are a directory
+		$filechk = @scandir($pwd.'/'.$ls[$n]);
+		if (! $filechk) {
+			//default values for uncaught filetypes
+			$ikon = "tsfile.gif";
+			$link = "";
+
+			foreach ($mime_types as $mimes) {
+				foreach ($mimes as $type) {
+					//$link = $mimes["link"];
+                                        $sstrn = @stristr($ls[$n],$type);
+					if ($sstrn !== FALSE && strlen($sstrn) == strlen($type)) {
+						$ikon = $mimes["file"];
+						$link = $mimes["link"];
+						break 2;
+					};
+				};
+			};
+			echo '<img class="icon" src='.$icondir.$ikon.' />';
+			echo '<a href="'.$link.$pwd.'/'.$ls[$n].'">'.$ls[$n].'</a><br />';
+		}
+		else {
+			echo '<img src="'.$icondir.'tsfolder.gif" />';
+			echo '<a href="index.php?nav=1&dir='.$pwd.'/'.$ls[$n].'">'.$ls[$n].'</a><br />'."\n";
+		}
+	}
+
+	//Figure out what the previous directory is
+	$prevdirname = '';
+
+	for ($i =0; $i < $predir; $i++) {
+
+		//We want to catch the first case, and not put a / before it
+		if ($i == 0) {
+			$prevdirname = $prevdirname.$splode[$i];
+		}
+		else {
+			$prevdirname = $prevdirname.'/'.$splode[$i];
+		}
+	}
+
+	//If we are not in the TLD, make a link to the previous dir
+	if ($prevdirname <> '') {
+
+		echo '<img src="'.$icondir.'tsfolder-up.gif" />';
+		echo '<a href="index.php?nav=1&dir='.$prevdirname.'">Up one level</a>'."\n";
+
+	}
+ }
+
+ //Catch bogus directories
+ else {
+ 	include 'sys/fileshare/include/notfound';
+ }
+?> 

+ 15 - 0
sys/fileshare/showimg.inc

@@ -0,0 +1,15 @@
+<?php
+$info =  getimagesize($post);
+$ratio = round($info[0]/$info[1],2);
+$parent = dirname($post);
+if ($ratio == 1.00) {
+ echo "<img alt=\"$post\" src=\"$post\" height=100% width=100% />";
+} elseif ($ratio > 1.00) {
+ $ht = (1.20-($ratio-1))*100;
+ echo "<img alt=\"$post\" src=\"$post\" height=$ht% width=100% />";
+} else {
+ $wd = 100-(($ratio-1)*100);
+ echo "<img alt=\"$post\" src=\"$post\" style=\"padding-left: auto; padding-right: auto;\" />";
+}
+echo "<a title=back href=\"index.php?nav=1&dir=$parent\"><img alt=back src=".$icondir."tsfolder-up.gif /></a>".basename($post)."&nbsp".$info[0]."x".$info[1]."<hr />";
+?>

+ 23 - 0
sys/fileshare/showpost.inc

@@ -0,0 +1,23 @@
+<?php
+//Generic .post file loader
+if ($nav == 5 && file_exists($post)) {
+ $statz = stat($post);
+ $uid = $statz['uid'];
+ $udata = posix_getpwuid($uid);
+ $user = $udata['name'];
+ $date =  date("F d Y H:i:s", filemtime($post));
+ if (stristr($post,'.') != ".post") {
+  $title = basename($post);
+ } else {
+  $title = strstr(basename($post),'.', true);
+ }
+ echo "<h3 class=\"blogtitles\"><a title=permalink href=\"index.php?nav=5&post=$post\">$title</a></h3>\n";
+ echo "<em class=\"blogdetail\">Last modified on $date UTC by $user</em><br /><hr />\n";
+ include "$post";
+ $parent = dirname($post);
+ echo "<hr /><a style=\"padding-left: auto; padding-right: auto;\" title=back href=\"index.php?nav=1&dir=$parent\"><img alt=back src=img/mime/tsfolder-up.gif /></a>$parent";
+}
+
+//404 Loader for files specified in GET param that don't actually exist
+elseif ($nav == 5 && !file_exists($post)) {echo "<h1 style=\"padding-left: auto; padding-right: auto;\">404 - Not Found</h1>";}
+?>

+ 19 - 0
sys/fileshare/showvideo.inc

@@ -0,0 +1,19 @@
+<?php
+//watch movies -- Only OGV is supported
+$parent = dirname($post);
+echo "<a title=back href=\"index.php?nav=1&dir=$parent\"><img alt=back src=".$icondir."tsfolder-up.gif /></a>$parent<hr />";
+$title = basename($post);
+echo "<h3 class=blogtitles><a title=permalink href=\"$post\">".$title."</a></h3>";
+echo "<video src=\"".$post."\" type=\"video/ogg\" codecs=\"theora, vorbis\" controls=\"controls\" width=\"100%\" height=\"80%\" poster=\"img/sys/testpattern.jpg\">";
+echo "<applet code=\"com.fluendo.player.Cortado.class\" archive=\"sys/fileshare/video/cortado.jar\" width=\"100%\" height=\"80%\">";
+echo "<param name=\"url\" value=\"http://teodesian.net/".$post."\"/>\n";
+echo "<param name='bufferSize' value='4096'>\n";
+echo "<param name='bufferHigh' value='25'>\n";
+echo "<param name='bufferLow' value='5'>\n";
+echo "<param name='autoPlay' value='false'>\n";
+echo "<param name='statusHeight' value='20'>\n";
+echo "Install the Java Plugin, or Enable Scripts to see video here.<br />";
+echo "Or, <a href=\"".$post."\">download the video.\n";
+echo "</applet>";
+echo "</video>";
+?>

+ 128 - 0
sys/microblog.inc

@@ -0,0 +1,128 @@
+<!--Scripts below allow audio player JS to show up with fancy little player-->
+<script type="text/javascript" src="sys/fileshare/include/audio-player.js"></script>
+<script type="text/javascript">
+	AudioPlayer.setup("sys/fileshare/include/player.swf", {
+	width: 290,
+	transparentpagebg: "yes",
+	});
+</script>
+<?php
+  if ($editable) {
+    echo "
+      <script type=\"text/javascript\">
+        function switchMenu(obj) {
+          var el = document.getElementById(obj);
+          if ( el.style.display != 'none' ) {
+            el.style.display = 'none';
+          }
+          else {
+            el.style.display = '';
+	  }
+        }
+      </script>\n";
+  }
+  echo '<p class="title"><a title="RSS" class="rss" href="/'.$basedir.$rssdir.'microblog.php"></a>';
+  echo $microblogtitle;
+  //Set important times - $tdtime is today's date, $oldtime is the oldest known date a tCMS install had nuze for - defaults to today then searches microblog dir for entries to set date
+  $tdtime = new DateTime(null, new DateTimeZone($timezone));
+  $oldtime = clone $tdtime;
+  //limit results of directory read to first entry
+  function &oldtimer($timezone, $basedir, $microblogdir) {
+    if ($handle = opendir($_SERVER["DOCUMENT_ROOT"].'/'.$basedir.$microblogdir)) {
+      while (false !== ($entry = readdir($handle))) {
+        if ($entry != "." && $entry != "..") {
+          $oldtime = DateTime::createFromFormat('m.d.y', $entry, new DateTimeZone ($timezone));
+          closedir($handle);
+          return($oldtime);
+        }
+      }
+    }
+  };
+  $oldtime = &oldtimer($timezone, $basedir, $microblogdir);
+  $oldtime->sub(new DateInterval('P1D'));
+  //$today and $tmrw refer to times relative to what is passed by GET params - $today is the date requested by GET, $tmrw is bool designating whether $today is something other than $tdtime 
+  //error indicates whether you supplied a bogus GET param for date.
+  $tmrw = 0;
+  $error = 0;
+  $today = clone $tdtime;
+  if ($_GET["date"] != "") {
+    $today = DateTime::createFromFormat('m.d.y', $_GET["date"], new DateTimeZone ($timezone));
+    //Catch bogus input, set $tmwr to TRUE if $today was set to something other than today's date
+    if (!filter_var($_GET["date"],FILTER_VALIDATE_REGEXP,array('options' => array('regexp' => "/^(0[1-9]|1[012])[.](0[1-9]|[12][0-9]|3[01])[.]\d\d/")))) {
+      echo "</p>That's a funny looking date you provided there, mister.\n";
+      $error=1;
+    }
+    else if ($today > $tdtime) { //catch if day supplied by GET is IN THE FUTURE
+      echo "</p>Welcome to the future<br /><img style=\"max-width:100%; padding-left: auto; padding-right: auto;\" src=\"http://gunshowcomic.com/comics/20090930.png\" />\n";
+      $error=1;
+    }   
+    else if ($today < $tdtime) {
+      $tmrw = 1;
+    }
+  }
+  //Catch if day in question has no news - If not, display day before (or before that if still no news. $oldtime used here to tell when to stop looping back)
+  if (!$error) {
+    while (empty($todaysnews)) {
+     $yesterday = clone $today;
+     $yesterday->sub(new DateInterval('P1D'));
+     //Detect if We're at the end of postings
+     if ($yesterday < $oldtime) {
+        echo " (".$today->format('m.d.y')."):</p><hr />";
+        echo "For me, it was a beginning, but for you it is the end of the road.<br /><hr />\n";
+        if ($oldtime != $tdtime) {
+          $tomorrow = clone $oldtime;
+          $tomorrow->add(new DateInterval('P1D'));
+	  $tomorrow = $tomorrow->format('m.d.y');
+        }
+        $todaysnews = "end";
+      }
+      if ($todaysnews != "end") {
+        //Get news from directory if any exists for that day
+        $todaysnews = glob($_SERVER["DOCUMENT_ROOT"].'/'.$basedir.$microblogdir.$today->format('m.d.y')."/*");
+        //Set display date for today's news, set $today to be yesterday in order to get while loop to recurse correctly
+        $realtime = $today->format('m.d.y');
+        $today = clone $yesterday;
+        //Finish by setting times for Yesterday and Tomorrow so that they can be used in links below
+        $tomorrow = clone $yesterday;
+        $tomorrow->add(new DateInterval('P2D'));
+        $tomorrow = $tomorrow->format('m.d.y');
+        $yesterday = $yesterday->format('m.d.y');
+      }
+    }
+    if ($todaysnews != "end") {
+      echo " (".$realtime."):</p><hr />\n";
+      foreach ($todaysnews as $i) {
+        $fh = fopen($i,'r');
+        $fc = fread($fh,10000); //If a microblog item is more than 1kb, you are doing something wrong.
+        fclose($fh);
+        echo $fc;
+        if ($editable) {
+          $id=basename($i);
+	  echo "
+            <a style=\"display: inline-block;\" onclick=\"switchMenu('$id');\">[Edit]</a>
+            <div style=\"display: none;\" id=\"$id\">
+             <form style=\"display: inline\" method=\"POST\">
+              <input type=\"hidden\" name=\"id\" value=\"$i\" />
+              <input type='hidden' name='action' value='Edit' />
+              <textarea class=\"mbedit_text\" name=\"content\">$fc</textarea>
+              <input class=\"coolbutton mbedit_button\" type=\"submit\" Value=\"Edit\" />
+             </form>
+             <form style=\"display: inline\" method=\"POST\">
+              <input type=\"hidden\" name=\"id\" value=\"$i\" />
+              <input type='hidden' name='action' value='Delete' />
+              <input class=\"coolbutton mbedit_button\" type=\"submit\" value=\"Delete\" />
+             </form>
+            </div>
+            <hr class=\"clear\" />";
+        }
+        echo "\n";
+      }
+      echo "<a style=\"float: left;\" title=\"skips empty days\" href=\"".$_SERVER["PHP_SELF"]."?nav=2&date=".$yesterday."\">Yesterday's News</a>\n";
+    }
+    if ($tmrw) {
+      echo "<a style=\"float: right;\" href=\"".$_SERVER["PHP_SELF"]."?nav=2&date=".$tomorrow."\">Tomorrow's News</a>\n";
+    }
+  } else {
+    //Do nothing - errors thrown above
+  }
+?>

+ 65 - 0
sys/rss/blog.php

@@ -0,0 +1,65 @@
+<?php
+	extract(json_decode(file_get_contents('../admin/config/main.json'),true));
+    echo "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n";
+	echo "<rss version=\"2.0\" xmlns:atom=\"http://www.w3.org/2005/Atom\">\n";
+	echo "<channel>\n";
+    $atomlink = "http://".$_SERVER["SERVER_NAME"]."/".$basedir.$rssdir."blog.php";
+	echo "<atom:link href=\"".$atomlink."\" rel=\"self\" type=\"application/rss+xml\" />";
+	echo "\t<title>".$htmltitle."</title>\n";
+	echo "\t<description>".$blogtitle."</description>\n";
+	echo "\t<link>http://".$_SERVER["SERVER_NAME"]."/".$basedir."</link>\n";
+
+	$tiem = date(DATE_RFC2822, time());
+
+	echo "\t<lastBuildDate>$tiem</lastBuildDate>\n";
+	echo "\t<pubDate>$tiem</pubDate>\n";
+
+	$files = glob($_SERVER["DOCUMENT_ROOT"]."/".$basedir.$blogdir."*.post");
+	$guid = count($files);
+
+	//sort by filename
+	
+	//initialize an array to house sort results
+	$files2 = array();
+	$files2 = array_pad($files2,$guid,0);
+
+	for ($i=0; $i<$guid; $i++) {
+		$j = explode('-',basename($files[$i]));
+		$j = $j[0];
+		$j = (int)$j;
+		$j--;
+		$files2[$j] = $files[$i];
+	}
+
+	$slen = count($files2)-1;
+	$ctr = 0;
+
+		for ($i=$slen; $i>-1; $i--) {
+			$shitpost=$files2[$i];
+		
+			if ($ctr > 9) {break;};
+			$ctr++;
+
+                	$statz = stat($shitpost);
+                	$uid = $statz['uid'];
+                	$udata = posix_getpwuid($uid);
+                	$user = $udata['name'];
+
+                	$date =  date(DATE_RFC2822, filemtime($shitpost));
+
+                	$title = substr(strstr(basename($shitpost),'-'),1,-5);
+			$contents = file_get_contents($shitpost);
+
+			echo "\t<item>\n";
+               		echo "\t\t<title>$title</title>\n";
+                	echo "\t\t<description><![CDATA[".$contents."]]>\t\t</description>\n";
+			echo "\t\t<link>http://teodesian.net/index.php?nav=8&amp;post=".$shitpost."</link>\n";
+			echo "\t\t<guid isPermaLink=\"false\">$guid-teodesian.net</guid>\n";
+			echo "\t\t<pubDate>".$date."</pubDate>\n";
+			echo "\t\t<author>".$user."</author>\n";
+			echo "\t</item>\n";
+			$guid--;
+		}
+	echo "</channel>\n";
+	echo "</rss>";
+?>

+ 54 - 0
sys/rss/microblog.php

@@ -0,0 +1,54 @@
+<?php
+  //Import your config, set some stuff up, then construct the mining laser
+  extract(json_decode(file_get_contents('../admin/config/main.json'),true));
+  extract(json_decode(file_get_contents('../admin/config/users.json'),true));
+  date_default_timezone_set($timezone);
+  $tiem = date(DATE_RSS);
+  $today = date("m.d.y");
+  $atomlink = "http://".$_SERVER["SERVER_NAME"]."/".$basedir.$rssdir."microblog.php";
+  $newsdir = $_SERVER["DOCUMENT_ROOT"]."/".$basedir.$microblogdir;
+  $files = glob($newsdir.$today."/*");
+  $slen = count($files);
+  $feed = '<?xml version="1.0" encoding="UTF-8"?>
+            <rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
+	     <channel>
+	      <atom:link href="'.$atomlink.'" rel="self" type="application/rss+xml" />
+	      <title>'.$htmltitle.'</title>
+	      <description>'.$microblogtitle.' RSS Feed</description>
+	      <link>http://'.$_SERVER['SERVER_NAME'].'/'.$basedir.'</link>
+	      <lastBuildDate>'.$tiem.'</lastBuildDate>
+	      <pubDate>'.$tiem.'</pubDate>';
+  foreach ($files as $shitpost) {
+    $storyPubDate =  date(DATE_RSS, strtotime(basename($shitpost)));
+    $contents = file_get_contents($shitpost);
+    //HAHAHA You thought you needed an XML parser, didn't you?
+    $theRipper = explode("<",$contents);
+    $theRipper = explode(">",$theRipper[2]);
+    $storyTitle = $theRipper[1];
+    $theRipper = explode('"',$theRipper[0]);
+    $storyLink = htmlspecialchars($theRipper[1]);
+    $theRipper = explode("</h3>",$contents);
+    $theRipper = explode("<hr />",$theRipper[1]);
+    $storyText = $theRipper[0];
+    $theRipper = explode("title=\"Posted by ",$contents);
+    $theRipper = explode('"',$theRipper[1]);
+    $poster = $theRipper[0];
+    $email = "null@example.com";
+    $author = "X";
+    if(isset($tcmsUsers[$poster])) {
+        $email = $tcmsUsers[$poster]["email"];
+        $author = $tcmsUsers[$poster]["fullName"]; 
+    }
+    $feed .= '<item>
+               <title>'.$storyTitle.'</title>
+               <description><![CDATA['.$storyText.']]></description>
+               <link>'.$storyLink.'</link>
+               <guid isPermaLink="false">'.basename($shitpost).'-'.$_SERVER["SERVER_NAME"].'</guid>
+               <pubDate>'.$storyPubDate.'</pubDate>
+               <author>'.$email.' ('.$author.')</author>
+              </item>';
+  }
+  $feed .= ' </channel>
+            </rss>';
+  print_r($feed);
+?>

Một số tệp đã không được hiển thị bởi vì quá nhiều tập tin thay đổi trong này khác