Переглянути джерело

Initial Commit of tCMS (version 1.1.2)

George Baugh 11 роки тому
батько
коміт
9ba9c6db62
71 змінених файлів з 1856 додано та 0 видалено
  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;
+		}
+		
+	}
+	
+}();

Різницю між файлами не показано, бо вона завелика
+ 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);
+?>

Деякі файли не було показано, через те що забагато файлів було змінено