From 4089fde241216dbc2ae5cb3f9b300a402d2ad03a Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 18 May 2014 03:29:17 -0500
Subject: [PATCH 01/54] Initial commit

---
 bdif/class.html2text.dm             |  489 +++++++++++++
 bdif/codecomments.dm                |    6 +
 bdif/console.dm                     |   17 +
 bdif/dialogbox.dm                   |    8 +
 bdif/doceditor.dm                   |   39 +
 bdif/footer.dm                      |  189 +++++
 bdif/header.dm                      |  226 ++++++
 bdif/ie_style.css                   |  146 ++++
 bdif/js_hide.css                    |    7 +
 bdif/js_hide2.css                   |    3 +
 bdif/js_hide3.css                   |    3 +
 bdif/login.dm                       |   21 +
 bdif/newspost.dm                    |   30 +
 bdif/newssubmission.dm              |   36 +
 bdif/packeteditor.dm                |  113 +++
 bdif/packeteditor.dm.orig           |   99 +++
 bdif/style.css                      |  214 ++++++
 check-servers.json                  |    1 +
 check-servers.log                   |   80 ++
 check-servers.php                   |  348 +++++++++
 check-servers.sh                    |   14 +
 cpw.php                             |  100 +++
 credits.php                         |   45 ++
 csseditor.php                       |   88 +++
 db.php                              |   22 +
 doc.php                             |  502 +++++++++++++
 doceditor.dm                        |   39 +
 encryption.php                      |    9 +
 experiment.php                      |   28 +
 favicon.pdn                         |  Bin 0 -> 10988 bytes
 favicon.png                         |  Bin 0 -> 2758 bytes
 func.php                            | 1057 +++++++++++++++++++++++++++
 functions.php                       | 1050 ++++++++++++++++++++++++++
 generatecode.php                    |  201 +++++
 generatedocs.php                    |  209 ++++++
 getcss.php                          |    7 +
 google7a3f778535b1424a.html         |    0
 google_adsense_script.html          |   11 +
 googlefd09e99f79286101.html         |    1 +
 help.php                            |  101 +++
 hosting.php                         |   11 +
 image.php                           |   54 ++
 images/DBDiagram.png                |  Bin 0 -> 198453 bytes
 images/DarkBlizzbnetweb.gif         |  Bin 0 -> 3361 bytes
 images/GG_linktous_91x32_1.gif      |  Bin 0 -> 950 bytes
 images/Jailout2000.jpg              |  Bin 0 -> 2410 bytes
 images/Thumbs.db                    |  Bin 0 -> 3072 bytes
 images/barbg.jpg                    |  Bin 0 -> 12913 bytes
 images/barbg.psd                    |  Bin 0 -> 21691 bytes
 images/barbgwhitecyan.jpg           |  Bin 0 -> 21849 bytes
 images/bnetdocsicon.png             |  Bin 0 -> 6004 bytes
 images/bnetdocslogo.jpg             |  Bin 0 -> 55196 bytes
 images/bnetdocslogo.png             |  Bin 0 -> 50652 bytes
 images/bnetdocslogo.psd             |  Bin 0 -> 432242 bytes
 images/bneticon.png                 |  Bin 0 -> 13322 bytes
 images/bnlsicon.png                 |  Bin 0 -> 5967 bytes
 images/circuit.gif                  |  Bin 0 -> 17212 bytes
 images/circuit.png                  |  Bin 0 -> 21276 bytes
 images/close.gif                    |  Bin 0 -> 109 bytes
 images/connected.png                |  Bin 0 -> 2955 bytes
 images/cssvalid.jpg                 |  Bin 0 -> 24237 bytes
 images/diabloicon.png               |  Bin 0 -> 9875 bytes
 images/disconnected.png             |  Bin 0 -> 2952 bytes
 images/fade.png                     |  Bin 0 -> 2840 bytes
 images/games/d2exp.jpg              |  Bin 0 -> 718 bytes
 images/games/diablo.jpg             |  Bin 0 -> 5630 bytes
 images/games/diablo2.jpg            |  Bin 0 -> 5995 bytes
 images/games/diablosw.jpg           |  Bin 0 -> 5663 bytes
 images/games/jsc.jpg                |  Bin 0 -> 6668 bytes
 images/games/sc.jpg                 |  Bin 0 -> 5540 bytes
 images/games/starx.jpg              |  Bin 0 -> 5845 bytes
 images/games/sware.jpg              |  Bin 0 -> 5690 bytes
 images/games/w3xp.jpg               |  Bin 0 -> 12653 bytes
 images/games/war2.jpg               |  Bin 0 -> 6530 bytes
 images/games/war3.jpg               |  Bin 0 -> 668 bytes
 images/games/wow.jpg                |  Bin 0 -> 22806 bytes
 images/grey.png                     |  Bin 0 -> 2842 bytes
 images/icondelete.jpg               |  Bin 0 -> 582 bytes
 images/infolink2.gif                |  Bin 0 -> 22630 bytes
 images/newsicon/blizzicon.png       |  Bin 0 -> 5144 bytes
 images/newsicon/bnetdocsicon.png    |  Bin 0 -> 6004 bytes
 images/newsicon/bneticon.png        |  Bin 0 -> 9450 bytes
 images/newsicon/bneticon.png.bak    |  Bin 0 -> 13322 bytes
 images/newsicon/bnlsicon.png        |  Bin 0 -> 5967 bytes
 images/newsicon/clone/image.jpg     |   99 +++
 images/newsicon/clone/matrix.jpg    |  Bin 0 -> 79420 bytes
 images/newsicon/diabloicon.png      |  Bin 0 -> 9875 bytes
 images/newsicon/starcraft2icon.png  |  Bin 0 -> 16216 bytes
 images/newsicon/starcrafticon.png   |  Bin 0 -> 18157 bytes
 images/newsicon/war3icon.png        |  Bin 0 -> 22204 bytes
 images/newsicon/warcrafticon.png    |  Bin 0 -> 10253 bytes
 images/punchicon.gif                |  Bin 0 -> 2491 bytes
 images/punchicon.psd                |  Bin 0 -> 207656 bytes
 images/rss.gif                      |  Bin 0 -> 1036 bytes
 images/shader.psd                   |  Bin 0 -> 22100 bytes
 images/starcraft2icon.png           |  Bin 0 -> 16216 bytes
 images/starcrafticon.png            |  Bin 0 -> 18157 bytes
 images/stars.jpg                    |  Bin 0 -> 274794 bytes
 images/starsfade.jpg                |  Bin 0 -> 102239 bytes
 images/starsfade.png                |  Bin 0 -> 2840 bytes
 images/stealth/image.jpg            |   97 +++
 images/stealth/matrix.jpg           |  Bin 0 -> 79420 bytes
 images/stealth/matrix.psd           |  Bin 0 -> 357660 bytes
 images/test.jpg                     |  Bin 0 -> 104873 bytes
 images/titleshader.psd              |  Bin 0 -> 22412 bytes
 images/vl_linkto.gif                |  Bin 0 -> 2960 bytes
 images/wait.gif                     |  Bin 0 -> 1542 bytes
 images/wallpapers/blueiso.gif       |  Bin 0 -> 3279 bytes
 images/wallpapers/bluesquares.jpg   |  Bin 0 -> 16091 bytes
 images/wallpapers/grunge.jpg        |  Bin 0 -> 51109 bytes
 images/wallpapers/hex.jpg           |  Bin 0 -> 52620 bytes
 images/wallpapers/snowflake.jpg     |  Bin 0 -> 7160 bytes
 images/wallpapers/weirdblueness.jpg |  Bin 0 -> 30837 bytes
 images/warcrafticon.png             |  Bin 0 -> 10253 bytes
 index.php                           |  141 ++++
 js/standard.js                      |  162 ++++
 left.php                            |   17 +
 legalism.php                        |  308 ++++++++
 login.php                           |   46 ++
 logout.php                          |   19 +
 logsrss.php                         |  156 ++++
 menu.php                            |    6 +
 news.php                            |  193 +++++
 newsrss.php                         |   80 ++
 packet.php                          |  721 ++++++++++++++++++
 postcomment.php                     |  162 ++++
 register.php                        |  123 ++++
 resetpw.php                         |   55 ++
 robots.txt                          |    6 +
 sandbox.php                         |   48 ++
 search.php                          |  162 ++++
 security_intrusion.html             |   20 +
 sessionhandler.php                  |   85 +++
 temp/logsrss.php                    |  110 +++
 test.php                            |    3 +
 usercss/1337D00D.css                |  223 ++++++
 usercss/Accused.css                 |  223 ++++++
 usercss/Alendar.css                 |  224 ++++++
 usercss/Camel.css                   |  216 ++++++
 usercss/Chriso.css                  |  223 ++++++
 usercss/DeFirence.css               |  223 ++++++
 usercss/Dragon_Legion.css           |  223 ++++++
 usercss/Goliath.css                 |  223 ++++++
 usercss/Hdx.css                     |  221 ++++++
 usercss/Hell-Lord.css               |  212 ++++++
 usercss/Imperceptus.css             |  223 ++++++
 usercss/Jailout2000.css             |  238 ++++++
 usercss/Joe[x86].css                |  227 ++++++
 usercss/Kyro.css                    |  220 ++++++
 usercss/Leaky.css                   |  222 ++++++
 usercss/LordVader.css               |  221 ++++++
 usercss/Mixter.css                  |  223 ++++++
 usercss/PapayaDealer.css            |  217 ++++++
 usercss/Ribose.css                  |  208 ++++++
 usercss/RichardNixon.css            |  217 ++++++
 usercss/Sixen.css                   |  221 ++++++
 usercss/TaintedWorks.css            |  227 ++++++
 usercss/Toss83.css                  |  221 ++++++
 usercss/buzz44.css                  |  183 +++++
 usercss/dark.css                    |  228 ++++++
 usercss/default.css                 |  225 ++++++
 usercss/dypso.css                   |    0
 usercss/idiat.css                   |  226 ++++++
 usercss/l2k-Shadow.css              |  208 ++++++
 usercss/lowfi.css                   |  221 ++++++
 usercss/nine.css                    |  223 ++++++
 usercss/nitroxs.css                 |  223 ++++++
 usercss/noc.css                     |  225 ++++++
 usercss/oXiDe.css                   |  223 ++++++
 usercss/plugins.css                 |  223 ++++++
 usercss/privt.css                   |  223 ++++++
 usercss/rabbit.css                  |  196 +++++
 usercss/sL8.css                     |  223 ++++++
 verbyte-cpp.html                    |  248 +++++++
 verbyte-java.txt                    |   51 ++
 viewlogs.php                        |  232 ++++++
 176 files changed, 17120 insertions(+)
 create mode 100644 bdif/class.html2text.dm
 create mode 100644 bdif/codecomments.dm
 create mode 100644 bdif/console.dm
 create mode 100644 bdif/dialogbox.dm
 create mode 100644 bdif/doceditor.dm
 create mode 100644 bdif/footer.dm
 create mode 100644 bdif/header.dm
 create mode 100644 bdif/ie_style.css
 create mode 100644 bdif/js_hide.css
 create mode 100644 bdif/js_hide2.css
 create mode 100644 bdif/js_hide3.css
 create mode 100644 bdif/login.dm
 create mode 100644 bdif/newspost.dm
 create mode 100644 bdif/newssubmission.dm
 create mode 100644 bdif/packeteditor.dm
 create mode 100644 bdif/packeteditor.dm.orig
 create mode 100644 bdif/style.css
 create mode 100644 check-servers.json
 create mode 100644 check-servers.log
 create mode 100644 check-servers.php
 create mode 100755 check-servers.sh
 create mode 100644 cpw.php
 create mode 100644 credits.php
 create mode 100644 csseditor.php
 create mode 100644 db.php
 create mode 100644 doc.php
 create mode 100644 doceditor.dm
 create mode 100644 encryption.php
 create mode 100644 experiment.php
 create mode 100644 favicon.pdn
 create mode 100644 favicon.png
 create mode 100644 func.php
 create mode 100644 functions.php
 create mode 100644 generatecode.php
 create mode 100644 generatedocs.php
 create mode 100644 getcss.php
 create mode 100644 google7a3f778535b1424a.html
 create mode 100644 google_adsense_script.html
 create mode 100644 googlefd09e99f79286101.html
 create mode 100644 help.php
 create mode 100644 hosting.php
 create mode 100644 image.php
 create mode 100644 images/DBDiagram.png
 create mode 100644 images/DarkBlizzbnetweb.gif
 create mode 100644 images/GG_linktous_91x32_1.gif
 create mode 100644 images/Jailout2000.jpg
 create mode 100644 images/Thumbs.db
 create mode 100644 images/barbg.jpg
 create mode 100644 images/barbg.psd
 create mode 100644 images/barbgwhitecyan.jpg
 create mode 100644 images/bnetdocsicon.png
 create mode 100644 images/bnetdocslogo.jpg
 create mode 100644 images/bnetdocslogo.png
 create mode 100644 images/bnetdocslogo.psd
 create mode 100644 images/bneticon.png
 create mode 100644 images/bnlsicon.png
 create mode 100644 images/circuit.gif
 create mode 100644 images/circuit.png
 create mode 100644 images/close.gif
 create mode 100644 images/connected.png
 create mode 100644 images/cssvalid.jpg
 create mode 100644 images/diabloicon.png
 create mode 100644 images/disconnected.png
 create mode 100644 images/fade.png
 create mode 100644 images/games/d2exp.jpg
 create mode 100644 images/games/diablo.jpg
 create mode 100644 images/games/diablo2.jpg
 create mode 100644 images/games/diablosw.jpg
 create mode 100644 images/games/jsc.jpg
 create mode 100644 images/games/sc.jpg
 create mode 100644 images/games/starx.jpg
 create mode 100644 images/games/sware.jpg
 create mode 100644 images/games/w3xp.jpg
 create mode 100644 images/games/war2.jpg
 create mode 100644 images/games/war3.jpg
 create mode 100644 images/games/wow.jpg
 create mode 100644 images/grey.png
 create mode 100644 images/icondelete.jpg
 create mode 100644 images/infolink2.gif
 create mode 100644 images/newsicon/blizzicon.png
 create mode 100644 images/newsicon/bnetdocsicon.png
 create mode 100644 images/newsicon/bneticon.png
 create mode 100644 images/newsicon/bneticon.png.bak
 create mode 100644 images/newsicon/bnlsicon.png
 create mode 100644 images/newsicon/clone/image.jpg
 create mode 100644 images/newsicon/clone/matrix.jpg
 create mode 100644 images/newsicon/diabloicon.png
 create mode 100644 images/newsicon/starcraft2icon.png
 create mode 100644 images/newsicon/starcrafticon.png
 create mode 100644 images/newsicon/war3icon.png
 create mode 100644 images/newsicon/warcrafticon.png
 create mode 100644 images/punchicon.gif
 create mode 100644 images/punchicon.psd
 create mode 100644 images/rss.gif
 create mode 100644 images/shader.psd
 create mode 100644 images/starcraft2icon.png
 create mode 100644 images/starcrafticon.png
 create mode 100644 images/stars.jpg
 create mode 100644 images/starsfade.jpg
 create mode 100644 images/starsfade.png
 create mode 100644 images/stealth/image.jpg
 create mode 100644 images/stealth/matrix.jpg
 create mode 100644 images/stealth/matrix.psd
 create mode 100644 images/test.jpg
 create mode 100644 images/titleshader.psd
 create mode 100644 images/vl_linkto.gif
 create mode 100644 images/wait.gif
 create mode 100644 images/wallpapers/blueiso.gif
 create mode 100644 images/wallpapers/bluesquares.jpg
 create mode 100644 images/wallpapers/grunge.jpg
 create mode 100644 images/wallpapers/hex.jpg
 create mode 100644 images/wallpapers/snowflake.jpg
 create mode 100644 images/wallpapers/weirdblueness.jpg
 create mode 100644 images/warcrafticon.png
 create mode 100644 index.php
 create mode 100644 js/standard.js
 create mode 100644 left.php
 create mode 100644 legalism.php
 create mode 100644 login.php
 create mode 100644 logout.php
 create mode 100644 logsrss.php
 create mode 100644 menu.php
 create mode 100644 news.php
 create mode 100644 newsrss.php
 create mode 100644 packet.php
 create mode 100644 postcomment.php
 create mode 100644 register.php
 create mode 100644 resetpw.php
 create mode 100644 robots.txt
 create mode 100644 sandbox.php
 create mode 100644 search.php
 create mode 100644 security_intrusion.html
 create mode 100644 sessionhandler.php
 create mode 100644 temp/logsrss.php
 create mode 100644 test.php
 create mode 100644 usercss/1337D00D.css
 create mode 100644 usercss/Accused.css
 create mode 100644 usercss/Alendar.css
 create mode 100644 usercss/Camel.css
 create mode 100644 usercss/Chriso.css
 create mode 100644 usercss/DeFirence.css
 create mode 100644 usercss/Dragon_Legion.css
 create mode 100644 usercss/Goliath.css
 create mode 100644 usercss/Hdx.css
 create mode 100644 usercss/Hell-Lord.css
 create mode 100644 usercss/Imperceptus.css
 create mode 100644 usercss/Jailout2000.css
 create mode 100644 usercss/Joe[x86].css
 create mode 100644 usercss/Kyro.css
 create mode 100644 usercss/Leaky.css
 create mode 100644 usercss/LordVader.css
 create mode 100644 usercss/Mixter.css
 create mode 100644 usercss/PapayaDealer.css
 create mode 100644 usercss/Ribose.css
 create mode 100644 usercss/RichardNixon.css
 create mode 100644 usercss/Sixen.css
 create mode 100644 usercss/TaintedWorks.css
 create mode 100644 usercss/Toss83.css
 create mode 100644 usercss/buzz44.css
 create mode 100644 usercss/dark.css
 create mode 100644 usercss/default.css
 create mode 100644 usercss/dypso.css
 create mode 100644 usercss/idiat.css
 create mode 100644 usercss/l2k-Shadow.css
 create mode 100644 usercss/lowfi.css
 create mode 100644 usercss/nine.css
 create mode 100644 usercss/nitroxs.css
 create mode 100644 usercss/noc.css
 create mode 100644 usercss/oXiDe.css
 create mode 100644 usercss/plugins.css
 create mode 100644 usercss/privt.css
 create mode 100644 usercss/rabbit.css
 create mode 100644 usercss/sL8.css
 create mode 100644 verbyte-cpp.html
 create mode 100644 verbyte-java.txt
 create mode 100644 viewlogs.php

diff --git a/bdif/class.html2text.dm b/bdif/class.html2text.dm
new file mode 100644
index 00000000..a6d774af
--- /dev/null
+++ b/bdif/class.html2text.dm
@@ -0,0 +1,489 @@
+<?php
+
+/*************************************************************************
+ *                                                                       *
+ * class.html2text.inc                                                   *
+ *                                                                       *
+ *************************************************************************
+ *                                                                       *
+ * Converts HTML to formatted plain text                                 *
+ *                                                                       *
+ * Copyright (c) 2005-2007 Jon Abernathy <jon@chuggnutt.com>             *
+ * All rights reserved.                                                  *
+ *                                                                       *
+ * This script 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 2 of the License, or     *
+ * (at your option) any later version.                                   *
+ *                                                                       *
+ * The GNU General Public License can be found at                        *
+ * http://www.gnu.org/copyleft/gpl.html.                                 *
+ *                                                                       *
+ * This script 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. See the          *
+ * GNU General Public License for more details.                          *
+ *                                                                       *
+ * Author(s): Jon Abernathy <jon@chuggnutt.com>                          *
+ *                                                                       *
+ * Last modified: 08/08/07                                               *
+ *                                                                       *
+ *************************************************************************/
+
+
+/**
+ *  Takes HTML and converts it to formatted, plain text.
+ *
+ *  Thanks to Alexander Krug (http://www.krugar.de/) to pointing out and
+ *  correcting an error in the regexp search array. Fixed 7/30/03.
+ *
+ *  Updated set_html() function's file reading mechanism, 9/25/03.
+ *
+ *  Thanks to Joss Sanglier (http://www.dancingbear.co.uk/) for adding
+ *  several more HTML entity codes to the $search and $replace arrays.
+ *  Updated 11/7/03.
+ *
+ *  Thanks to Darius Kasperavicius (http://www.dar.dar.lt/) for
+ *  suggesting the addition of $allowed_tags and its supporting function
+ *  (which I slightly modified). Updated 3/12/04.
+ *
+ *  Thanks to Justin Dearing for pointing out that a replacement for the
+ *  <TH> tag was missing, and suggesting an appropriate fix.
+ *  Updated 8/25/04.
+ *
+ *  Thanks to Mathieu Collas (http://www.myefarm.com/) for finding a
+ *  display/formatting bug in the _build_link_list() function: email
+ *  readers would show the left bracket and number ("[1") as part of the
+ *  rendered email address.
+ *  Updated 12/16/04.
+ *
+ *  Thanks to Wojciech Bajon (http://histeria.pl/) for submitting code
+ *  to handle relative links, which I hadn't considered. I modified his
+ *  code a bit to handle normal HTTP links and MAILTO links. Also for
+ *  suggesting three additional HTML entity codes to search for.
+ *  Updated 03/02/05.
+ *
+ *  Thanks to Jacob Chandler for pointing out another link condition
+ *  for the _build_link_list() function: "https".
+ *  Updated 04/06/05.
+ *
+ *  Thanks to Marc Bertrand (http://www.dresdensky.com/) for
+ *  suggesting a revision to the word wrapping functionality; if you
+ *  specify a $width of 0 or less, word wrapping will be ignored.
+ *  Updated 11/02/06.
+ *
+ *  *** Big housecleaning updates below:
+ *
+ *  Thanks to Colin Brown (http://www.sparkdriver.co.uk/) for
+ *  suggesting the fix to handle </li> and blank lines (whitespace).
+ *  Christian Basedau (http://www.movetheweb.de/) also suggested the
+ *  blank lines fix.
+ *
+ *  Special thanks to Marcus Bointon (http://www.synchromedia.co.uk/),
+ *  Christian Basedau, Norbert Laposa (http://ln5.co.uk/),
+ *  Bas van de Weijer, and Marijn van Butselaar
+ *  for pointing out my glaring error in the <th> handling. Marcus also
+ *  supplied a host of fixes.
+ *
+ *  Thanks to Jeffrey Silverman (http://www.newtnotes.com/) for pointing
+ *  out that extra spaces should be compressed--a problem addressed with
+ *  Marcus Bointon's fixes but that I had not yet incorporated.
+ *
+ *    Thanks to Daniel Schledermann (http://www.typoconsult.dk/) for
+ *  suggesting a valuable fix with <a> tag handling.
+ *
+ *  Thanks to Wojciech Bajon (again!) for suggesting fixes and additions,
+ *  including the <a> tag handling that Daniel Schledermann pointed
+ *  out but that I had not yet incorporated. I haven't (yet)
+ *  incorporated all of Wojciech's changes, though I may at some
+ *  future time.
+ *
+ *  *** End of the housecleaning updates. Updated 08/08/07.
+ *
+ *  @author Jon Abernathy <jon@chuggnutt.com>
+ *  @version 1.0.0
+ *  @since PHP 4.0.2
+ */
+class html2text
+{
+
+    /**
+     *  Contains the HTML content to convert.
+     *
+     *  @var string $html
+     *  @access public
+     */
+    var $html;
+
+    /**
+     *  Contains the converted, formatted text.
+     *
+     *  @var string $text
+     *  @access public
+     */
+    var $text;
+
+    /**
+     *  Maximum width of the formatted text, in columns.
+     *
+     *  Set this value to 0 (or less) to ignore word wrapping
+     *  and not constrain text to a fixed-width column.
+     *
+     *  @var integer $width
+     *  @access public
+     */
+    var $width = 120;
+
+    /**
+     *  List of preg* regular expression patterns to search for,
+     *  used in conjunction with $replace.
+     *
+     *  @var array $search
+     *  @access public
+     *  @see $replace
+     */
+    var $search = array(
+        "/\r/",                                  // Non-legal carriage return
+        "/[\n\t]+/",                             // Newlines and tabs
+        '/[ ]{2,}/',                             // Runs of spaces, pre-handling
+        '/<script[^>]*>.*?<\/script>/i',         // <script>s -- which strip_tags supposedly has problems with
+        '/<style[^>]*>.*?<\/style>/i',           // <style>s -- which strip_tags supposedly has problems with
+        //'/<!-- .* -->/',                         // Comments -- which strip_tags might have problem a with
+        '/<h[123][^>]*>(.*?)<\/h[123]>/ie',      // H1 - H3
+        '/<h[456][^>]*>(.*?)<\/h[456]>/ie',      // H4 - H6
+        '/<p[^>]*>/i',                           // <P>
+        '/<br[^>]*>/i',                          // <br>
+        '/<b[^>]*>(.*?)<\/b>/ie',                // <b>
+        '/<strong[^>]*>(.*?)<\/strong>/ie',      // <strong>
+        '/<i[^>]*>(.*?)<\/i>/i',                 // <i>
+        '/<em[^>]*>(.*?)<\/em>/i',               // <em>
+        '/(<ul[^>]*>|<\/ul>)/i',                 // <ul> and </ul>
+        '/(<ol[^>]*>|<\/ol>)/i',                 // <ol> and </ol>
+        '/<li[^>]*>(.*?)<\/li>/i',               // <li> and </li>
+        '/<li[^>]*>/i',                          // <li>
+        '/<a [^>]*href="([^"]+)"[^>]*>(.*?)<\/a>/ie',
+                                                 // <a href="">
+        '/<hr[^>]*>/i',                          // <hr>
+        '/(<table[^>]*>|<\/table>)/i',           // <table> and </table>
+        '/(<tr[^>]*>|<\/tr>)/i',                 // <tr> and </tr>
+        '/<td[^>]*>(.*?)<\/td>/i',               // <td> and </td>
+        '/<th[^>]*>(.*?)<\/th>/ie',              // <th> and </th>
+        '/&(nbsp|#160);/i',                      // Non-breaking space
+        '/&(quot|rdquo|ldquo|#8220|#8221|#147|#148);/i',
+                                                 // Double quotes
+        '/&(apos|rsquo|lsquo|#8216|#8217);/i',   // Single quotes
+        '/&gt;/i',                               // Greater-than
+        '/&lt;/i',                               // Less-than
+        '/&(amp|#38);/i',                        // Ampersand
+        '/&(copy|#169);/i',                      // Copyright
+        '/&(trade|#8482|#153);/i',               // Trademark
+        '/&(reg|#174);/i',                       // Registered
+        '/&(mdash|#151|#8212);/i',               // mdash
+        '/&(ndash|minus|#8211|#8722);/i',        // ndash
+        '/&(bull|#149|#8226);/i',                // Bullet
+        '/&(pound|#163);/i',                     // Pound sign
+        '/&(euro|#8364);/i',                     // Euro sign
+        '/&[^&;]+;/i',                           // Unknown/unhandled entities
+        '/[ ]{2,}/'                              // Runs of spaces, post-handling
+    );
+
+    /**
+     *  List of pattern replacements corresponding to patterns searched.
+     *
+     *  @var array $replace
+     *  @access public
+     *  @see $search
+     */
+    var $replace = array(
+        '',                                     // Non-legal carriage return
+        ' ',                                    // Newlines and tabs
+        ' ',                                    // Runs of spaces, pre-handling
+        '',                                     // <script>s -- which strip_tags supposedly has problems with
+        '',                                     // <style>s -- which strip_tags supposedly has problems with
+        //'',                                     // Comments -- which strip_tags might have problem a with
+        "strtoupper(\"\n\n\\1\n\n\")",          // H1 - H3
+        "ucwords(\"\n\n\\1\n\n\")",             // H4 - H6
+        "\n\n\t",                               // <P>
+        "\n",                                   // <br>
+        'strtoupper("\\1")',                    // <b>
+        'strtoupper("\\1")',                    // <strong>
+        '_\\1_',                                // <i>
+        '_\\1_',                                // <em>
+        "\n\n",                                 // <ul> and </ul>
+        "\n\n",                                 // <ol> and </ol>
+        "\t* \\1\n",                            // <li> and </li>
+        "\n\t* ",                               // <li>
+        '$this->_build_link_list("\\1", "\\2")',
+                                                // <a href="">
+        "\n-------------------------\n",        // <hr>
+        "\n\n",                                 // <table> and </table>
+        "\n",                                   // <tr> and </tr>
+        "\t\t\\1\n",                            // <td> and </td>
+        "strtoupper(\"\t\t\\1\n\")",            // <th> and </th>
+        ' ',                                    // Non-breaking space
+        '"',                                    // Double quotes
+        "'",                                    // Single quotes
+        '>',
+        '<',
+        '&',
+        '(c)',
+        '(tm)',
+        '(R)',
+        '--',
+        '-',
+        '*',
+        '�',
+        'EUR',                                  // Euro sign. � ?
+        '',                                     // Unknown/unhandled entities
+        ' '                                     // Runs of spaces, post-handling
+    );
+
+    /**
+     *  Contains a list of HTML tags to allow in the resulting text.
+     *
+     *  @var string $allowed_tags
+     *  @access public
+     *  @see set_allowed_tags()
+     */
+    var $allowed_tags = '';
+
+    /**
+     *  Contains the base URL that relative links should resolve to.
+     *
+     *  @var string $url
+     *  @access public
+     */
+    var $url;
+
+    /**
+     *  Indicates whether content in the $html variable has been converted yet.
+     *
+     *  @var boolean $_converted
+     *  @access private
+     *  @see $html, $text
+     */
+    var $_converted = false;
+
+    /**
+     *  Contains URL addresses from links to be rendered in plain text.
+     *
+     *  @var string $_link_list
+     *  @access private
+     *  @see _build_link_list()
+     */
+    var $_link_list = '';
+    
+    /**
+     *  Number of valid links detected in the text, used for plain text
+     *  display (rendered similar to footnotes).
+     *
+     *  @var integer $_link_count
+     *  @access private
+     *  @see _build_link_list()
+     */
+    var $_link_count = 0;
+
+    /**
+     *  Constructor.
+     *
+     *  If the HTML source string (or file) is supplied, the class
+     *  will instantiate with that source propagated, all that has
+     *  to be done it to call get_text().
+     *
+     *  @param string $source HTML content
+     *  @param boolean $from_file Indicates $source is a file to pull content from
+     *  @access public
+     *  @return void
+     */
+    function html2text( $source = '', $from_file = false )
+    {
+        if ( !empty($source) ) {
+            $this->set_html($source, $from_file);
+        }
+        $this->set_base_url();
+    }
+
+    /**
+     *  Loads source HTML into memory, either from $source string or a file.
+     *
+     *  @param string $source HTML content
+     *  @param boolean $from_file Indicates $source is a file to pull content from
+     *  @access public
+     *  @return void
+     */
+    function set_html( $source, $from_file = false )
+    {
+        $this->html = $source;
+
+        if ( $from_file && file_exists($source) ) {
+            $fp = fopen($source, 'r');
+            $this->html = fread($fp, filesize($source));
+            fclose($fp);
+        }
+
+        $this->_converted = false;
+    }
+
+    /**
+     *  Returns the text, converted from HTML.
+     *
+     *  @access public
+     *  @return string
+     */
+    function get_text()
+    {
+        if ( !$this->_converted ) {
+            $this->_convert();
+        }
+
+        return $this->text;
+    }
+
+    /**
+     *  Prints the text, converted from HTML.
+     *
+     *  @access public
+     *  @return void
+     */
+    function print_text()
+    {
+        print $this->get_text();
+    }
+
+    /**
+     *  Alias to print_text(), operates identically.
+     *
+     *  @access public
+     *  @return void
+     *  @see print_text()
+     */
+    function p()
+    {
+        print $this->get_text();
+    }
+
+    /**
+     *  Sets the allowed HTML tags to pass through to the resulting text.
+     *
+     *  Tags should be in the form "<p>", with no corresponding closing tag.
+     *
+     *  @access public
+     *  @return void
+     */
+    function set_allowed_tags( $allowed_tags = '' )
+    {
+        if ( !empty($allowed_tags) ) {
+            $this->allowed_tags = $allowed_tags;
+        }
+    }
+
+    /**
+     *  Sets a base URL to handle relative links.
+     *
+     *  @access public
+     *  @return void
+     */
+    function set_base_url( $url = '' )
+    {
+        if ( empty($url) ) {
+            if ( !empty($_SERVER['HTTP_HOST']) ) {
+                $this->url = 'http://' . $_SERVER['HTTP_HOST'];
+            } else {
+                $this->url = '';
+            }
+        } else {
+            // Strip any trailing slashes for consistency (relative
+            // URLs may already start with a slash like "/file.html")
+            if ( substr($url, -1) == '/' ) {
+                $url = substr($url, 0, -1);
+            }
+            $this->url = $url;
+        }
+    }
+
+    /**
+     *  Workhorse function that does actual conversion.
+     *
+     *  First performs custom tag replacement specified by $search and
+     *  $replace arrays. Then strips any remaining HTML tags, reduces whitespace
+     *  and newlines to a readable format, and word wraps the text to
+     *  $width characters.
+     *
+     *  @access private
+     *  @return void
+     */
+    function _convert()
+    {
+        // Variables used for building the link list
+        $this->_link_count = 0;
+        $this->_link_list = '';
+
+        $text = trim(stripslashes($this->html));
+
+        // Run our defined search-and-replace
+        $text = preg_replace($this->search, $this->replace, $text);
+
+        // Strip any other HTML tags
+        $text = strip_tags($text, $this->allowed_tags);
+
+        // Bring down number of empty lines to 2 max
+        $text = preg_replace("/\n\s+\n/", "\n\n", $text);
+        $text = preg_replace("/[\n]{3,}/", "\n\n", $text);
+
+        // Add link list
+        if ( !empty($this->_link_list) ) {
+            $text .= "\n\nLinks:\n------\n" . $this->_link_list;
+        }
+
+        // Wrap the text to a readable format
+        // for PHP versions >= 4.0.2. Default width is 75
+        // If width is 0 or less, don't wrap the text.
+        if ( $this->width > 0 ) {
+            $text = wordwrap($text, $this->width);
+        }
+
+        $this->text = $text;
+
+        $this->_converted = true;
+    }
+
+    /**
+     *  Helper function called by preg_replace() on link replacement.
+     *
+     *  Maintains an internal list of links to be displayed at the end of the
+     *  text, with numeric indices to the original point in the text they
+     *  appeared. Also makes an effort at identifying and handling absolute
+     *  and relative links.
+     *
+     *  @param string $link URL of the link
+     *  @param string $display Part of the text to associate number with
+     *  @access private
+     *  @return string
+     */
+    function _build_link_list( $link, $display )
+    {
+        if ( substr($link, 0, 7) == 'http://' || substr($link, 0, 8) == 'https://' ||
+             substr($link, 0, 7) == 'mailto:' ) {
+            $this->_link_count++;
+            $this->_link_list .= "[" . $this->_link_count . "] $link\n";
+            $additional = ' [' . $this->_link_count . ']';
+        } elseif ( substr($link, 0, 11) == 'javascript:' ) {
+            // Don't count the link; ignore it
+            $additional = '';
+        // what about href="#anchor" ?
+        } else {
+            $this->_link_count++;
+            $this->_link_list .= "[" . $this->_link_count . "] " . $this->url;
+            if ( substr($link, 0, 1) != '/' ) {
+                $this->_link_list .= '/';
+            }
+            $this->_link_list .= "$link\n";
+            $additional = ' [' . $this->_link_count . ']';
+        }
+
+        return $display . $additional;
+    }
+
+}
+
+?>
\ No newline at end of file
diff --git a/bdif/codecomments.dm b/bdif/codecomments.dm
new file mode 100644
index 00000000..6bcca476
--- /dev/null
+++ b/bdif/codecomments.dm
@@ -0,0 +1,6 @@
+<? global $language, $groupname, $commentizer; ?>
+<?=$commentizer;?> PacketID Constants for <?=$language;?> 
+<?=$commentizer;?> Generated by BNETDocs: Redux on <? echo date('F j, Y');?> 
+<?=$commentizer;?> BNETDocs: Redux software written by Don Cullen AKA Kyro
+<?=$commentizer;?> Original BNETDocs content compiled by Arta & Skywing
+
diff --git a/bdif/console.dm b/bdif/console.dm
new file mode 100644
index 00000000..20b397db
--- /dev/null
+++ b/bdif/console.dm
@@ -0,0 +1,17 @@
+<? #Console.dm
+	global $ip, $userid;
+	
+	if(!$userid){
+		logthis($userid, 'Attempted to force direct access to console without logging in. Attempt blocked.', 'hack');
+		blockhack();
+	}
+	
+	$rank = rank($userid);
+	if($rank > 2) echo '<a href="/?op=news&mode=post">Post News</a><br>';
+	if($rank > 2) echo '<a href="/?op=viewlogs">View Logs</a><br>';
+	if($rank > 2) echo '<a href="/?op=packet&mode=add">Add Packet</a><br>';
+	if($rank > 2) echo '<a href="/?op=doc&mode=add">Add Document</a><br>';
+	echo '<a href="/?op=csseditor">CSS Theme Editor</a><br>';
+	echo '<a href="/?op=cpw">Change Password</a><br>';
+	echo '<a href="/?op=logout">Log Out</a><br>';
+?><br>
\ No newline at end of file
diff --git a/bdif/dialogbox.dm b/bdif/dialogbox.dm
new file mode 100644
index 00000000..d2427c0d
--- /dev/null
+++ b/bdif/dialogbox.dm
@@ -0,0 +1,8 @@
+	<div id="container">
+	<div id="main2">
+	<? if($title != 'none'){ ?><div id="author"><?=$title;?></div><? } ?>
+	<div align="center">
+	<div style="width: 97%;" align="left">
+	<?=$text;?>
+	</div>
+	</div></div></div>
\ No newline at end of file
diff --git a/bdif/doceditor.dm b/bdif/doceditor.dm
new file mode 100644
index 00000000..0daf8837
--- /dev/null
+++ b/bdif/doceditor.dm
@@ -0,0 +1,39 @@
+			<? 
+				global $userid, $rank, $postdate, $title, $content, $edit, $did, $action; 
+			?>
+			<div id="newscontainer">
+			<div id="main2">
+			<h2>Document Editor</h2>
+			<blockquote><form method="POST" name="doceditor" action="/?op=doc&action=<?=$action;?><? if($action=='edit') echo '&did='.$did; ?>">
+			</center>
+			<table border=0 cellspacing=2 cellpadding=2 width=100%>
+				<tr>
+					<td width=0>Title:</td><td width=100%><input type="text" name="title" value="<?=$title;?>" size=45 id="inputbox"></td>
+				</tr>
+				<tr>
+					<td valign=top>Content:</td>
+					<td>
+						<textarea onclick="sz(this);" onkeyup="sz(this)" style="width: 100%;" id="inputbox" name="content" rows="10" cols="81"><?=$content;?></textarea>
+					</td>
+				</tr>
+				<tr>
+					<td>Related:</td><td><input type="text" name="mrelated" value="<?=$related;?>" size=45 id="inputbox"> <font size=1>[ <a href="/?op=help&topic=related links">HELP</a> ]</font></td>
+				</tr>
+				<tr>
+					<td nowrap>Clearance Required:</td>
+					<td>
+						<select name="mclearance" size="1">
+						<option <?=$dcgueselected;?> value="0">Guest</option>
+						<option <?=$dcuseselected;?> value="1">User</option>
+						<option <?=$dcsupselected;?> value="2">Superuser</option>
+						<option <?=$dcediselected;?> value="3">Editor</option>
+						<option <?=$dcadmselected;?> value="4">Administrator</option>
+						</select>
+					</td>
+				</tr>
+			</table>
+			<br>
+			<input type="submit" id="abutton" onclick="this.disabled=false;" value="Submit"></form>
+			</blockquote>
+			</div></div>
+			<br>
\ No newline at end of file
diff --git a/bdif/footer.dm b/bdif/footer.dm
new file mode 100644
index 00000000..98a09a44
--- /dev/null
+++ b/bdif/footer.dm
@@ -0,0 +1,189 @@
+<? global $ie; ?>
+</td>
+<div id="frills">
+<td width=20% valign=top id="frills">
+	<? if($ie){ ?>
+	<div id="container">
+	<div id="main2">
+	<div id="author">ALERT</div>
+	<table border=0 cellspacing=0 cellpadding=4><tr><td>
+	We recommend you use Firefox to view this site. This site has been optimized for Firefox.<br>
+	<br>
+	<center><a href="http://getfirefox.com/" title="Get Firefox - The Browser, Reloaded.">
+	<img src="http://www.mozilla.org/products/firefox/buttons/getfirefox_88x31.png"	width="88" height="31" border="0" alt="Get Firefox"></a></center>
+	</td></tr></table>
+	</div></div>
+	<? } ?>
+
+	<!--<div id="container">
+	<div id="main2">
+	<div id="author">BNLS Redirector Status</div>
+		<div align=center>
+		<table cellspacing=2 cellpadding=2 border=0>
+		<?
+			//$sid = GetInfo('servers', 'serveraddress', 'bnls.dementedminds.net', 'id');
+			//$target = GetInfo('servers', 'id', $sid, 'target');
+			//$sid = GetInfo('servers', 'serveraddress', $target, 'id');
+			//$status = checkserver($sid);
+			//echo '<tr><td><font size=2><br>bnls.dementedminds.net: </td><td><br><img src="'.statusimg($status).'"><br></font></td></tr>';
+			//echo '<tr><td colspan=2><font size=2>Redirecting to: '.$target.'</td></tr>';
+		?>
+		</table>
+		</div>
+		<br>
+	</div></div>-->
+	
+	<?
+		$sqlquery = 'SELECT id,serveraddress,target,status FROM servers WHERE target != \'\'';
+		$redirects = mysql_query($sqlquery); $displayed = false;
+		while ($redirect = mysql_fetch_array($redirects)) {
+			if (!$displayed) {
+				echo "\t<div id=\"container\">\n\t<div id=\"main2\">\n\t<div id=\"author\">BNLS Redirecter Status</div>\n\t\t<div align=center>\n";
+				$displayed = true;
+			}
+			echo "\t\t<table cellspacing=2 cellpadding=2 border=0>\n"
+				."\t\t\t<tr><td><font size=2><br>" . $redirect['serveraddress'] . "</td><td><br><img src=\"".statusimg($redirect['status'])."\"><br></font></td></tr>\n"
+				."\t\t\t<tr><td colspan=2><font size=2>Redirecting to: " . $redirect['target'] . "</td></tr>\n"
+				."\t\t</table>\n";
+		} if ($displayed) echo '</div></div>';
+	?>
+	
+	<div id="container">
+	<div id="main2">
+	<div id="author">BNLS Server Status</div>
+		<div align=center>
+		<table cellspacing=2 cellpadding=2 border=0>
+		<?
+			$sqlquery = 'SELECT id,serveraddress,status FROM servers ORDER BY status DESC,id ASC';
+			$serverarray = mysql_query($sqlquery);
+			while($row = mysql_fetch_array($serverarray)){
+				$sid = $row['id'];
+				$saddress = $row['serveraddress'];
+				$status = $row['status'];
+				if($status=='offline'){
+					$status = false;
+				} else {
+					$status = true;
+				}
+				/*if($saddress != 'bnls.dementedminds.net')*/ echo '<tr><td><font size=2>'.$saddress.': </td><td><img src="'.statusimg($status).'"><br></font></td></tr>';
+			} 
+		?>
+		</table>
+		</div>
+		<br>
+		<center><font size=1><img src="<? echo statusimg(true); ?>"> = Online &nbsp; &nbsp; &nbsp; <img src="<? echo statusimg(false); ?>"> = Offline<br><br></font></center>
+	</div></div>
+	
+	<div id="container">
+	<div id="main2">
+	<div id="author">Battle.net Server Status</div>
+		<div align=center>
+		<?
+			$sqlquery = 'SELECT version FROM bnetservers GROUP BY version ASC';
+			$versions = mysql_query($sqlquery);
+			while ($version = mysql_fetch_array($versions)) {
+				echo '<h2>' . $version['version'] . '</h2><table cellspacing=2 cellpadding=2 border=0>';
+				$sqlquery = 'SELECT id,serveraddress,status FROM bnetservers WHERE version = \'' . $version['version'] . '\' ORDER BY status DESC,id ASC';
+				$serverarray = mysql_query($sqlquery);
+				while($row = mysql_fetch_array($serverarray)){
+					$sid = $row['id'];
+					$saddress = $row['serveraddress'];
+					$status = $row['status'];
+					if($status=='offline'){
+						$status = false;
+					} else {
+						$status = true;
+					}
+					echo '<tr><td><font size=2>'.$saddress.': </td><td><img src="'.statusimg($status).'"><br></font></td></tr>';
+				}
+				echo '</table>';
+			}
+		?>
+		</div>
+		<br>
+		<center><font size=1><img src="<? echo statusimg(true); ?>"> = Online &nbsp; &nbsp; &nbsp; <img src="<? echo statusimg(false); ?>"> = Offline<br><br></font></center>
+	</div></div>
+	
+	<div id="links">
+	<div id="container">
+	<div id="main2">
+	<div id="author">Links</div>
+		<center>
+		<a href="http://forum.valhallalegends.com/" target="_blank"><img src="/images/vl_linkto.gif" alt="Valhalla Legends" title="vL Forums"></a>
+		<a href="http://www.gosugamers.net" target="_blank"><img src="/images/GG_linktous_91x32_1.gif" alt="Gosu Gamers"></a><br>
+		<a href="http://www.jailout2000.com" target="_blank"><img src="/images/Jailout2000.jpg" alt="Jailout2000" title="Jailout2000's Website"></a>
+		<a href="http://www.darkblizz.org" target="_blank"><img src="/images/DarkBlizzbnetweb.gif" alt="DarkBlizz" title="DarkBlizz - Making Battle.net Magic"></a><br>
+		</center>
+	</div></div></div>
+	
+	<div id="rssfeeds">
+	<div id="container">
+	<div id="main2">
+	<div id="author">RSS Feeds</div>
+		<br>
+		<a href="//www.bnetdocs.org/newsrss.php"><img src="/images/rss.gif"> &nbsp; BNETDocs News</a><br>
+		<?
+			if($userid){
+				?>
+				<a href="//www.bnetdocs.org/logsrss.php"><img src="/images/rss.gif"> &nbsp; BNETDocs Logs</a><br>
+				<?
+			}
+		?>
+		<br>
+	</div></div></div>
+	
+	
+	<?
+	if(!$userid){
+	?>
+	<div id="container">
+	<div id="main2">
+	<div id="author">Advertisements</div>
+		<div align=center>
+		<a href="/">Sponsor Us; Advertise here!</a><br><br>
+		<script type="text/javascript"><!--
+		google_ad_client = "pub-5293484515355302";
+		google_ad_width = 160;
+		google_ad_height = 600;
+		google_ad_format = "160x600_as";
+		google_ad_type = "text_image";
+		//2007-06-19: BNETDocs
+		google_ad_channel = "2273844208";
+		//-->
+		</script>
+		<script type="text/javascript"
+		  src="//pagead2.googlesyndication.com/pagead/show_ads.js">
+		</script>
+	</div>
+	</div>
+	</div>
+	<?
+	}
+	?>
+	</td>
+</tr></table>
+<br><br>
+<div id="copyrights">
+<div id="author">Copyrights</div>
+<br>Site scripts and design copyrights reserved to <a href="http://www.doncullen.net">Don Cullen</a>.<br>
+Contents copyrighted to Blizzard and their parent corporation, Vivendi.<br>
+Main credits for contents goes to Arta. <a href="/?op=credits">View the rest of credits.</a><br>
+Demented Minds copyrights reserved to <a href="http://www.doncullen.net">Don Cullen</a> 2003-present.<br>
+Copyright infringements will be prosecuted to the fullest extent allowable by law.
+<br>
+<a href="/?op=legalism"><font size="1">Please view our legal disclaimer and terms of service.</font></a><br><br>
+<?
+if($userid == 1){
+	?><a href="https://www.google.com/analytics/reporting/dashboard?id=4966196&pdr=20070819-20070918&cmp=average">Site Stats</a><?
+}
+?>
+</div>
+</div>
+<script src="//www.google-analytics.com/urchin.js" type="text/javascript">
+</script>
+<script type="text/javascript">
+_uacct = "UA-2637626-2";
+urchinTracker();
+</script>
+</body>
+</html>
diff --git a/bdif/header.dm b/bdif/header.dm
new file mode 100644
index 00000000..f5b5bb77
--- /dev/null
+++ b/bdif/header.dm
@@ -0,0 +1,226 @@
+<? global $ip, $userid, $auth; $openedmenus = $_GET['ep'];?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
+   "http://www.w3.org/TR/html4/loose.dtd">
+<html>
+<head>
+	<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
+	<meta name="description" content="Battle.Net Logon Sequences, Packets, information and protocols reference site.">
+	<meta name="keywords" content="Battle.Net, Logon Sequences, Packets, information, protocols reference, programming, coding, Starcraft, Warcraft, Diablo">
+
+	<? 
+	if(preg_match('/(?i)msie [1-9]/',$_SERVER['HTTP_USER_AGENT'])) { 
+		$ie = true;
+	} else { 
+		$ie = false;
+	} 
+	if($userid){
+		$usercss = GetData($userid, 'usercss');
+		if($usercss){
+			$found = false;
+			if($usercss == 'custom'){ #user's own css file
+				$usercssfile = '/usercss/'.whoisid($userid).'.css';
+				?><link rel="stylesheet" type="text/css" href="<?=$usercssfile;?>"><?
+			} elseif(substr($usercss, 0, 6) == 'user: ') { #using another member's css file
+				$usercssfile = 'usercss/'.substr($usercss, 6).'.css';
+				?><link rel="stylesheet" type="text/css" href="<?=$usercssfile;?>"><?
+			} else {
+				#do loop, if found, break, otherwise, use v1 styling
+				$sqlquery = 'SELECT * FROM themes';
+				$themearray = mysql_query($sqlquery);
+				while($row = mysql_fetch_array($themearray)){
+					$themename = $row['theme'];
+					$cssfile = $row['cssfile'];
+					if($cssfile == $usercss){
+						$usercssfile = 'usercss/'.$cssfile.'.css';
+						$found = true;
+					}
+				}
+				if(!$found){
+					?>
+					<!-- Now include user's css if available -->
+					<style type="text/css">
+					<?=$usercss;?>
+					</style>
+					<!-- End User CSS Inclusion -->		
+					<?
+				} else {
+					?><link rel="stylesheet" type="text/css" href="<?=$usercssfile;?>"><?
+				}
+			}
+		} else {
+			$usercssfile = '/usercss/default.css';
+			?><link rel="stylesheet" type="text/css" href="<?=$usercssfile;?>"><?
+		}
+	} else {
+		$usercssfile = '/usercss/default.css';
+		?><link rel="stylesheet" type="text/css" href="<?=$usercssfile;?>"><?
+	}
+	?>
+	<title>BNETDocs: Redux</title>
+	<script src="/js/standard.js" type="text/javascript"></script>
+	<link rel="alternate" type="application/rss+xml" title="BNETDocs Redux News" href="/newsrss.php">
+	<link rel="icon" type="image/png" href="/favicon.png" sizes="32x32">
+  <?
+  // FIGHT FOR THE FUTURE - STOP THE SLOW LANE (http://www.stoptheslowlane.com/)
+  if (date('Y-m-d') == '2014-05-15') {
+    ?>
+	<style id="_sl_hide" type="text/css">body { display: none; }</style>
+    <?
+    if (rand(0, 1) == 1) {
+      ?>
+	<script type="text/javascript">var _sl_options = { animation: 'blur' }; // Alternate Comcast animation</script>
+      <?
+    }
+    ?>
+	<script src="https://fightforthefuture.github.io/stoptheslowlane/widget/slowlane.js"></script>
+    <?
+  } // END OF STOP THE SLOW LANE
+  ?>
+</head>
+<!-- google_ad_section_start -->
+<!-- Battle.net StarCraft WarCraft Diablo War Counterstrike FPS Army Navy Marines Game Games RPG Vikings Blizzard Gold Leveling Mining Free Tutorials Movies Matrix 
+Computers Programming Binary Coding Hacking -->
+<!-- google_ad_section_end -->
+<body onload="doonload()">
+<div id="content" align=center>
+<div align=left id="logo"><img src="/images/bnetdocslogo.png"><br>
+<br></div>
+<div align=left id="textonlylogo"><br><h1>BNETDocs Redux</h1></div>
+<table border=0 cellspacing=0 cellpadding=7 width=100%><tr>
+<td width=20% valign=top nowrap>
+	<div id="container">
+	<div id="main2">
+	<div align=left>
+	<h2>Navigation</h2>
+	<div id="divMain_Menu"><div id="author">Main Menu</div><div class="navmenu" id="bodyMain_Menu">
+		<a href="/">Main Page</a><br>
+		<a href="/?mode=all">View News History</a><br>
+		<a href="generatedocs.php">Download BNETDocs as Text</a><br>
+		<a href="/?op=search">Search BNETDocs</a> &nbsp; <font color=red size=1>Incomplete</font><br>
+		<a href="/forums/">Forums</a><br>
+		<a href="/?op=credits">Credits</a><br>
+		<a href="/archives/" target="_blank">BNETDocs Archives</a><br><br>
+	</div></div>
+	<div id="divConsole"><div id="author">Console</div><div class="navmenu" id="bodyConsole">
+		<?
+			if($userid){
+				#session exists
+				include 'bdif/console.dm';
+			} else {
+				#no session, show login
+				#echo '<div id="login" onclick="ajax(\'login.php\', \'?op=login\', \'login\');">Click to login.</div>';
+				include 'bdif/login.dm';
+			}
+		?>
+	</div></div>
+	<div id="divDocuments"><div id="author">Documents</div><div class="navmenu" id="bodyDocuments">
+		<?
+		$sqlqueryz = 'SELECT * FROM documents ORDER BY title ASC';
+		$docarray = mysql_query($sqlqueryz);
+		$doccount = 0;
+		function _clearance_name($clearance)
+		{
+			switch ($clearance)
+			{
+				case 0: $clearancename = 'Guest'; break;
+				case 1: $clearancename = 'User'; break;
+				case 2: $clearancename = 'Superuser'; break;
+				case 3: $clearancename = 'Editor'; break;
+				case 4:
+				case 5: $clearancename = 'Administrator'; break;
+				default:
+					$clearancename = 'Unknown&nbsp;('.$clearance.')';
+			}
+			return $clearancename;
+		}
+		while($rowz = mysql_fetch_array($docarray)){
+			$did = $rowz['id'];
+			$title = delslash($rowz['title']);
+			$clearance = $rowz['clearance'];
+			if($clearance <= rank($userid)){
+				echo '<a href="/?op=doc&did='.$did.'">'.$title.'</a>'.(rank($userid) >= 4 ? '<span>'._clearance_name($clearance).'</span>' : '').'<br>'."\n";
+			}
+			$doccount++;
+		}
+		if($doccount < 1) echo 'No documents available.';
+		$title = '';
+		?>
+	</div></div>
+	<div id="divGenerate_Code"><div id="author" nowrap>Generate Code: All packets</div><div class="navmenu" id="bodyGenerate_Code">
+		<a href="/?op=generatecode&gid=all&lang=vb">Visual Basic 6.0</a><br>
+		<a href="/?op=generatecode&gid=all&lang=cpp">C++</a><br>
+		<a href="/?op=generatecode&gid=all&lang=csharp">C#.NET (C Sharp)</a><br>
+		<a href="/?op=generatecode&gid=all&lang=java">Java</a><br>
+		<a href="/?op=generatecode&gid=all&lang=pas">Pascal</a><br>
+		<a href="/?op=generatecode&gid=all&lang=php">PHP</a><br><br>
+	</div></div>
+	<div id="divPackets"><div id="author">Packets</div><div class="navmenu" id="bodyPackets">
+		Quick Jump: [ <a href="/?op=help&topic=quick jump">help</a> ]<br><font size=1><br></font>
+		<form method="POST" name="quickjumpform" action="/?op=packet">
+		<input type="text" id="inputbox" name="quickjump"><input type="submit" id="abutton" value="go">
+		</form>
+		<br>
+		<?
+		$sqlquerya = 'SELECT * FROM groups ORDER BY displayorder';
+		$groupsarray = mysql_query($sqlquerya);
+		$zs1 = 1;
+		while($rowa = mysql_fetch_array($groupsarray)){
+			$gid = $rowa['id'];
+			$groupname = $rowa['groupname'];
+			$groupdivname = str_replace(' ', '_', $groupname);
+			$groupdivname = str_replace('.', '_', $groupdivname);
+			echo '<div id="'.$groupdivname.'">'."\n".$groupname.' [ <a id="x'.$zs1.'1" href="#" onclick="toggle_visibility(\'a'.$zs1.'\'); toggle_name(this); return(false);">+'.$clicktext.'</a> ]<br>'."\n".'<div class="togglable" id="a'.$zs1.'">'."\n";
+			$zs1++;
+			if(($groupname == 'D2GS Messages') || ($groupname == 'W3GS Messages')){
+				$sqlquery = 'SELECT * FROM packets WHERE pgroup='.$gid.' ORDER BY direction,messageid,messagename ASC';
+			} else {
+				$sqlquery = 'SELECT * FROM packets WHERE pgroup='.$gid.' ORDER BY messageid,direction DESC';
+			}
+			$packetsarray = mysql_query($sqlquery);
+			while($row = mysql_fetch_array($packetsarray)){
+				$pid = $row['id'];
+				$direction = $row['direction'];
+				$direction = GetInfo('traffic', 'id', $direction, 'shortdescr') . ' ';
+				$messageid = '['.$row['messageid'].'] ';
+				$messagename = $row['messagename'];
+				$pclearance = $row['clearance'];
+				switch ($row['status']) {
+					case 0:
+						$status = '<font class="raw">RAW</font>'."\n";
+						break;
+					case 1: 
+						$status = '';
+						break;
+					case 2:
+						$status = '<font class="research">RESEARCH</font>'."\n";
+						break;
+					case 3:
+						$status = '<font class="defunct">DEFUNCT</font>'."\n";
+						break;
+				}
+				if($pclearance > 0){
+					if($userid){
+						if(rank($userid) > $pclearance){
+							echo '<a href="/?op=packet&pid='.$pid.'"><font size=1>'.$direction.$messageid.$messagename.'</font></a>'.$status.'<br>'."\n";
+						}
+						if(rank($userid) == $pclearance){
+							echo '<a href="/?op=packet&pid='.$pid.'"><font size=1>'.$direction.$messageid.$messagename.'</font></a>'.$status.'<br>'."\n";
+						}
+					}
+				} else {
+					if(!$pclearance){
+						echo '<a href="/?op=packet&pid='.$pid.'"><font size=1>'.$direction.$messageid.$messagename.'</font></a>'.$status.'<br>'."\n";
+					}
+				}
+			} 
+			echo "\n".'<br>'."\n".'<font id="viewcode">View Code: [&nbsp; <a href="/?op=generatecode&gid='.$gid.'&lang=pas">PAS</a> <a href="/?op=generatecode&gid='.$gid.'&lang=cpp">CPP</a> <a href="/?op=generatecode&gid='.$gid.'&lang=vb">VB</a> <a href="/?op=generatecode&gid='.$gid.'&lang=php">PHP</a> &nbsp;]</font><br>'."\n".'</div>'.'<br>'."\n".'</div>'."\n";
+		} 
+		?>
+		</div></div>
+	<div id="divOther_Resources"><div id="author">Other Resources</div><div class="navmenu" id="bodyOther_Resouces">
+		<a href="/archives/bnlsprotocolspec.txt" target="_blank">BNLS Protocol Specs</a><br>
+		<a href="/archives/bnsp-latest.txt" target="_blank">BotNet Protocol Specs</a><br>
+		<a href="http://forum.valhallalegends.com/index.php?board=17.0" target="_blank">BNET Bot Development Forums</a><br><br>
+	</div></div></div></div></div>
+</td>
+<td width=60% valign=top>
diff --git a/bdif/ie_style.css b/bdif/ie_style.css
new file mode 100644
index 00000000..0cbac6c3
--- /dev/null
+++ b/bdif/ie_style.css
@@ -0,0 +1,146 @@
+body{
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	position: fixed;
+	overflow: auto;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/starsfade.png);
+	border: 1px solid black;
+	padding: 1;
+	margin: 10 0 0 0;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/starsfade.png);
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1;
+	margin: 10 0 0 0;	
+}
+
+div#punch2{
+	float: left; 
+	width: 100px; 
+	height: 75px; 
+	text-align: center; 
+	color: white; 
+	border-width: 0 1px 1px 0; 
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#punch2 img{
+	height: 75px; 
+	width: 100px;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/starsfade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url('/images/barbg.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: left
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a:link{
+	color: lime;
+	text-decoration: underline;
+	text-transform: none; 
+}
+
+a:visited{
+	color: lime;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:active{
+	color: lime;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:hover{
+	color: #FF0000;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url('../images/barbg.jpg');
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
\ No newline at end of file
diff --git a/bdif/js_hide.css b/bdif/js_hide.css
new file mode 100644
index 00000000..c049647e
--- /dev/null
+++ b/bdif/js_hide.css
@@ -0,0 +1,7 @@
+div.togglable {
+	display: none;
+}
+
+div.disappear {
+	display: inline;
+}
\ No newline at end of file
diff --git a/bdif/js_hide2.css b/bdif/js_hide2.css
new file mode 100644
index 00000000..56d53114
--- /dev/null
+++ b/bdif/js_hide2.css
@@ -0,0 +1,3 @@
+div.disappear {
+	display: none;
+}
\ No newline at end of file
diff --git a/bdif/js_hide3.css b/bdif/js_hide3.css
new file mode 100644
index 00000000..fcceeb76
--- /dev/null
+++ b/bdif/js_hide3.css
@@ -0,0 +1,3 @@
+div.disappear {
+	display: inline;
+}
\ No newline at end of file
diff --git a/bdif/login.dm b/bdif/login.dm
new file mode 100644
index 00000000..5aed04a9
--- /dev/null
+++ b/bdif/login.dm
@@ -0,0 +1,21 @@
+<?
+	global $auth, $ip;
+	
+	if($auth != 'true') die('<html><head><title>BNETDocs: Redux</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	$username = $_POST['username'];
+	$password = $_POST['password'];
+	$rememberme = $_POST['rememberme'];
+?>
+		<div id="console">
+		<form method="post" onsubmit="return validate_form(this)" action="/?op=login"><br>
+		&nbsp;&nbsp;Username:<br>
+		&nbsp;&nbsp;<input type="text" id="inputbox" name="username"><br><br>
+		&nbsp;&nbsp;Password:<br>
+		&nbsp;&nbsp;<input type="password" id="inputbox" name="password"><br><br>
+		&nbsp;&nbsp;<input type="checkbox" id="inputbox" name="rememberme" value="yes">Remember me<br><br>
+		&nbsp;&nbsp;<input type="submit" id="abutton" value="Login"><br>
+		</form>
+		<br><center><a href="/?op=register">Register</a>&nbsp;|&nbsp;<a href="/?op=resetpw">Password Reset</a></center>
+		<br>
+		</div>
diff --git a/bdif/newspost.dm b/bdif/newspost.dm
new file mode 100644
index 00000000..eaa5aa10
--- /dev/null
+++ b/bdif/newspost.dm
@@ -0,0 +1,30 @@
+<? global $author, $rank, $postdate, $icon, $title, $content, $nid, $userid; ?>
+<div id="newscontainer">
+<div id="main2">
+<h2><?=$title;?></h2>
+<div id="author">Posted by <?=whoisid($author);?> <?=$rank;?> on <?=$postdate;?></div>
+<img id="newsicon" src="/images/newsicon/<?=$icon;?>icon.png" alt="icon" align="left">
+<p><?=$content;?></p>
+<?
+	if($userid){
+		if(rank($userid) > 2){
+			?>
+			<div id="author" align=right >
+			<div class="menu">
+			<? 
+			if($userid == $author || $userid == 1){ 
+				?>
+				<a href="/?op=news&mode=edit&nid=<?=$nid;?>"><span>Edit</span></a>
+				<? 
+			} 
+			if((rank($userid) > 4) || ($userid == $author)){
+				?>
+				<a onClick="return confimdelete();" href="/?op=news&mode=delete&nid=<?=$nid;?>"><span>Delete</span></a>
+				<?
+			}
+		}
+	}
+?>
+<!--<a href="#"><span>View Comments</span></a>-->
+</div></div></div></div>
+<br>
\ No newline at end of file
diff --git a/bdif/newssubmission.dm b/bdif/newssubmission.dm
new file mode 100644
index 00000000..49c7ab76
--- /dev/null
+++ b/bdif/newssubmission.dm
@@ -0,0 +1,36 @@
+			<? 
+				global $userid, $rank, $postdate, $title, $content, $edit, $topictype; 
+				if(!$topictype) $topictype = 'bnetdocs';
+			?>
+			<div id="newscontainer">
+			<div id="main2">
+			<h2>Post News</h2>
+			<div id="author">Posting as <?=whoisid($userid);?> <?=$rank;?> on <?=$postdate;?></div>
+			<blockquote><form method="POST" name="thenews" action="/?op=news<?=$edit;?>">
+			<center><img src="/images/newsicon/<?=$topictype;?>icon.png" name="thepic"><br>
+			<input type="text"  name="subject" value="<?=$title;?>" style="text-align: center; width: 100%;" id="inputbox"></center><br>
+			<br>
+			<textarea style="width: 100%;" id="inputbox" rows="10" name="text" cols="81"><?=$content;?></textarea><br>
+			<br>
+			</blockquote>
+				<div align=center>
+				<table border=0 cellpadding=0 cellspacing=0 width=87%><tr>
+				<td>
+					Choose News Icon: <select name="pictureselector" size="1" onChange="showimage()">
+					<option <?=$bdselected;?> value="bnetdocs">BNETDocs</option>
+					<option <?=$bnselected;?> value="bnet">Battle.net</option>
+					<option <?=$bnlsselected;?> value="bnls">BNLS</option>
+					<option <?=$scselected;?> value="starcraft">Starcraft</option>
+					<option <?=$scselected;?> value="starcraft2">Starcraft II</option>
+					<option <?=$wcselected;?> value="warcraft">World of Warcraft</option>
+					<option <?=$wcselected;?> value="war3">Warcraft III</option>
+					<option <?=$dselected;?> value="diablo">Diablo</option>
+					<option <?=$scselected;?> value="blizz">Blizzard</option>
+					</select>
+				</td>
+				<td align=right>
+					<input type="submit" id="abutton" onclick="this.disabled=false;" value="Post"></form>
+				</td>
+				</tr></table><br></div>
+			</div></div>
+			<br>
\ No newline at end of file
diff --git a/bdif/packeteditor.dm b/bdif/packeteditor.dm
new file mode 100644
index 00000000..7832bbd3
--- /dev/null
+++ b/bdif/packeteditor.dm
@@ -0,0 +1,113 @@
+			<? 
+				global $userid, $rank, $postdate, $title, $content, $edit, $topictype, $action; 
+				if(!$topictype) $topictype = 'bnetdocs';
+			?>
+			<div id="newscontainer">
+			<div id="main2">
+			<h2>Packet Editor</h2>
+			<blockquote><form method="POST" name="packeteditor" action="/?op=packet&action=<?=$action;?><? if($action=='edit') echo '&pid='.$pid; ?>">
+			</center>
+			<table border=0 cellspacing=2 cellpadding=2 width=100%>
+				<tr>
+					<td width=0>Message ID:</td><td width=100%><input type="text" name="mid" value="<?=$messageid;?>" size=45 id="inputbox"></td>
+				</tr>
+				<tr>
+					<td>Message Name:</td><td><input type="text" name="mname" value="<?=$messagename;?>" size=45 id="inputbox"></td>
+				</tr>
+				<tr>
+					<td>Direction:</td>
+					<td>
+						<select name="mdirection" size="1">
+						<?
+						$sqlquerya = 'SELECT * FROM traffic ORDER BY id';
+						$trafficarray = mysql_query($sqlquerya);
+						while($rowa = mysql_fetch_array($trafficarray)){
+							$tid = $rowa['id'];
+							$code = $rowa['code'];
+							$descr = $rowa['descr'];
+							if($tid == $direction){
+								$pdselected = 'selected';
+							} else {
+								$pdselected = '';
+							}
+							?><option <?=$pdselected;?> value="<?=$tid;?>"><?=$descr;?></option><?
+						}
+						?>
+						</select>
+					</td>
+				</tr>
+				<tr>
+					<td valign=top>Used By:</td><td>
+						<!-- Jailout2000: Added "id" attribute and added label tag to the following checkboxes -->
+						<input name="scsw" id="scsw" <?=$cbscsw;?> value="1" type="checkbox"><label for="scsw"><img src="/images/games/sware.jpg"></label>&nbsp;&nbsp;&nbsp;&nbsp;<input name="sc" id="sc" <?=$cbsc;?> value="1" type="checkbox"><label for="sc"><img src="/images/games/sc.jpg"></label><br>
+						<input name="bw" id="bw" <?=$cbbw;?> value="1" type="checkbox"><label for="bw"><img src="/images/games/starx.jpg"></label>&nbsp;&nbsp;&nbsp;&nbsp;<input name="jsc" id="jsc" <?=$cbjsc;?> value="1" type="checkbox"><label for="jsc"><img src="/images/games/jsc.jpg"></label><br>
+						<input name="dsw" id="dsw" <?=$cbdsw;?> value="1" type="checkbox"><label for="dsw"><img src="/images/games/diablosw.jpg"></label>&nbsp;&nbsp;&nbsp;&nbsp;<input name="diablo" id="diablo" <?=$cbdiablo;?> value="1" type="checkbox"><label for="diablo"><img src="/images/games/diablo.jpg"></label><br>
+						<input name="d2" id="d2" <?=$cbd2;?> value="1" type="checkbox"><label for="d2"><img src="/images/games/diablo2.jpg"></label>&nbsp;&nbsp;&nbsp;&nbsp;<input name="d2lod" id="d2lod" <?=$cbd2lod;?> value="1" type="checkbox"><label for="d2lod"><img src="/images/games/d2exp.jpg"></label><br>
+						<input name="wc2" id="wc2" <?=$cbwc2;?> value="1" type="checkbox"><label for="wc2"><img src="/images/games/war2.jpg"></label>&nbsp;&nbsp;&nbsp;&nbsp;<input name="wc3" id="wc3" <?=$cbwc3;?> value="1" type="checkbox"><label for="wc3"><img src="/images/games/war3.jpg"></label><br>
+						<input name="wc3tft" id="wc3tft" <?=$cbwc3tft;?> value="1" type="checkbox"><label for="wc3tft"><img src="/images/games/w3xp.jpg"></label>&nbsp;&nbsp;&nbsp;&nbsp;<input name="wow" id="wow" <?=$cbwow;?> value="1" type="checkbox"><label for="wow"><img src="/images/games/wow.jpg"></label><br>
+						<input name="none" id="none" <?=$cnone;?> value="1" type="checkbox" onClick="this.checked=scheck(this.form.list)"><label for="none">None</label><br>
+					</td>
+				</tr>
+				<tr>
+					<td valign=top colspan=2>Format:<br>
+						<textarea onclick="sz(this);" onkeyup="sz(this)" style="width: 100%;" id="inputbox" name="mformat" rows="10"><?=$format;?></textarea><br>
+					</td>
+				</tr>
+				<tr>
+					<td valign=top colspan=2>Remarks:<br>
+						<textarea onclick="sz(this);" onkeyup="sz(this)" style="width: 100%;" id="inputbox" rows="10" name="mremarks"><?=$remarks;?></textarea>
+					</td>
+				</tr>
+				<tr>
+					<td>Related:</td><td><input type="text" name="mrelated" value="<?=$related;?>" size=45 id="inputbox"> <font size=1>[ <a href="/?op=help&topic=related links">HELP</a> ]</font></td>
+				</tr>
+				<tr>
+					<td nowrap>Packet Status:</td>
+					<td>
+						<select name="mstatus" size="1">
+						<option <?=$psrawselected;?> value="0">Raw</option>
+						<option <?=$psnorselected;?> value="1">Normal</option>
+						<option <?=$psresselected;?> value="2">Research</option>
+						<option <?=$psdefselected;?> value="3">Defunct</option>
+						</select>
+					</td>
+				</tr>
+				<tr>
+					<td nowrap>Clearance Required:</td>
+					<td>
+						<select name="mclearance" size="1">
+						<option <?=$pcgueselected;?> value="0">Guest</option>
+						<option <?=$pcuseselected;?> value="1">User</option>
+						<option <?=$pcsupselected;?> value="2">Superuser</option>
+						<option <?=$pcediselected;?> value="3">Editor</option>
+						<option <?=$pcadmselected;?> value="4">Administrator</option>
+						</select>
+					</td>
+				</tr>
+				<tr>
+					<td nowrap>Packet Group:</td>
+					<td>
+						<select name="mgroup" size="1">
+						<?
+						$sqlquerya = 'SELECT id,groupname FROM groups ORDER BY displayorder';
+						$groupsarray = mysql_query($sqlquerya);
+						while($rowa = mysql_fetch_array($groupsarray)){
+							$gid = $rowa['id'];
+							$groupname = $rowa['groupname'];
+							if($gid == $pgroupid){
+								$pgselected = 'selected';
+							} else {
+								$pgselected = '';
+							}
+							?><option <?=$pgselected;?> value="<?=$gid;?>"><?=$groupname;?></option><?
+						}
+						?>
+						</select>
+					</td>
+				</tr>
+			</table>
+			<br>
+			<input type="submit" id="abutton" onclick="this.disabled=false;" value="Submit"></form>
+			</blockquote>
+			</div></div>
+			<br>
\ No newline at end of file
diff --git a/bdif/packeteditor.dm.orig b/bdif/packeteditor.dm.orig
new file mode 100644
index 00000000..5f8f05e1
--- /dev/null
+++ b/bdif/packeteditor.dm.orig
@@ -0,0 +1,99 @@
+			<? 
+				global $userid, $rank, $postdate, $title, $content, $edit, $topictype, $action; 
+				if(!$topictype) $topictype = 'bnetdocs';
+			?>
+			<div id="newscontainer">
+			<div id="main2">
+			<h2>Packet Editor</h2>
+			<blockquote><form method="POST" name="packeteditor" action="/?op=packet&action=<?=$action;?><? if($action=='edit') echo '&pid='.$pid; ?>">
+			</center>
+			<table border=0 cellspacing=2 cellpadding=2 width=100%>
+				<tr>
+					<td width=0>Message ID:</td><td width=100%><input type="text" name="mid" value="<?=$messageid;?>" size=45 id="inputbox"></td>
+				</tr>
+				<tr>
+					<td>Message Name:</td><td><input type="text" name="mname" value="<?=$messagename;?>" size=45 id="inputbox"></td>
+				</tr>
+				<tr>
+					<td>Direction:</td>
+					<td>
+						<select name="mdirection" size="1">
+						<option <?=$pdsselected;?> value="1">Server to Client</option>
+						<option <?=$pdcselected;?> value="0">Client to Server</option>
+						</select>
+					</td>
+				</tr>
+				<tr>
+					<td valign=top>Used By:</td><td>
+						<input name="scsw" <?=$cbscsw;?> value="1" type="checkbox"><img src="/images/games/sware.jpg">&nbsp;&nbsp;&nbsp;&nbsp;<input name="sc" <?=$cbsc;?> value="1" type="checkbox"><img src="/images/games/sc.jpg"><br>
+						<input name="bw" <?=$cbbw;?> value="1" type="checkbox"><img src="/images/games/starx.jpg">&nbsp;&nbsp;&nbsp;&nbsp;<input name="jsc" <?=$cbjsc;?> value="1" type="checkbox"><img src="/images/games/jsc.jpg"><br>
+						<input name="dsw" <?=$cbdsw;?> value="1" type="checkbox"><img src="/images/games/diablosw.jpg">&nbsp;&nbsp;&nbsp;&nbsp;<input name="diablo" <?=$cbdiablo;?> value="1" type="checkbox"><img src="/images/games/diablo.jpg"><br>
+						<input name="d2" <?=$cbd2;?> value="1" type="checkbox"><img src="/images/games/diablo2.jpg">&nbsp;&nbsp;&nbsp;&nbsp;<input name="d2lod" <?=$cbd2lod;?> value="1" type="checkbox"><img src="/images/games/d2exp.jpg"><br>
+						<input name="wc2" <?=$cbwc2;?> value="1" type="checkbox"><img src="/images/games/war2.jpg">&nbsp;&nbsp;&nbsp;&nbsp;<input name="wc3" <?=$cbwc3;?> value="1" type="checkbox"><img src="/images/games/war3.jpg"><br>
+						<input name="wc3tft" <?=$cbwc3tft;?> value="1" type="checkbox"><img src="/images/games/w3xp.jpg">&nbsp;&nbsp;&nbsp;&nbsp;<input name="wow" <?=$cbwow;?> value="1" type="checkbox"><img src="/images/games/wow.jpg"><br>
+						<input name="none" <?=$cnone;?> value="1" type="checkbox" onClick="this.checked=scheck(this.form.list)">None<br>
+					</td>
+				</tr>
+				<tr>
+					<td valign=top colspan=2>Format:<br>
+						<textarea onclick="sz(this);" onkeyup="sz(this)" style="width: 100%;" id="inputbox" name="mformat" rows="10"><?=$format;?></textarea><br>
+					</td>
+				</tr>
+				<tr>
+					<td valign=top colspan=2>Remarks:<br>
+						<textarea onclick="sz(this);" onkeyup="sz(this)" style="width: 100%;" id="inputbox" rows="10" name="mremarks"><?=$remarks;?></textarea>
+					</td>
+				</tr>
+				<tr>
+					<td>Related:</td><td><input type="text" name="mrelated" value="<?=$related;?>" size=45 id="inputbox"> <font size=1>[ <a href="/?op=help&topic=related links">HELP</a> ]</font></td>
+				</tr>
+				<tr>
+					<td nowrap>Packet Status:</td>
+					<td>
+						<select name="mstatus" size="1">
+						<option <?=$psrawselected;?> value="0">Raw</option>
+						<option <?=$psnorselected;?> value="1">Normal</option>
+						<option <?=$psresselected;?> value="2">Research</option>
+						<option <?=$psdefselected;?> value="3">Defunct</option>
+						</select>
+					</td>
+				</tr>
+				<tr>
+					<td nowrap>Clearance Required:</td>
+					<td>
+						<select name="mclearance" size="1">
+						<option <?=$pcgueselected;?> value="0">Guest</option>
+						<option <?=$pcuseselected;?> value="1">User</option>
+						<option <?=$pcsupselected;?> value="2">Superuser</option>
+						<option <?=$pcediselected;?> value="3">Editor</option>
+						<option <?=$pcadmselected;?> value="4">Administrator</option>
+						</select>
+					</td>
+				</tr>
+				<tr>
+					<td nowrap>Packet Group:</td>
+					<td>
+						<select name="mgroup" size="1">
+						<?
+						$sqlquerya = 'SELECT * FROM groups ORDER BY id';
+						$groupsarray = mysql_query($sqlquerya);
+						while($rowa = mysql_fetch_array($groupsarray)){
+							$gid = $rowa['id'];
+							$groupname = $rowa['groupname'];
+							if($gid == $pgroupid){
+								$pgselected = 'selected';
+							} else {
+								$pgselected = '';
+							}
+							?><option <?=$pgselected;?> value="<?=$gid;?>"><?=$groupname;?></option><?
+						}
+						?>
+						</select>
+					</td>
+				</tr>
+			</table>
+			<br>
+			<input type="submit" id="abutton" onclick="this.disabled=false;" value="Submit"></form>
+			</blockquote>
+			</div></div>
+			<br>
\ No newline at end of file
diff --git a/bdif/style.css b/bdif/style.css
new file mode 100644
index 00000000..dad9056c
--- /dev/null
+++ b/bdif/style.css
@@ -0,0 +1,214 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+select  { 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#viewcode {
+	color: black;
+	font-size: 10px;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#packets {
+	font-family: Courier New;
+}
+
+#container{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border-width: 2px;
+	border-spacing: 2px;
+	border-style: solid;
+	border-color: blue;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+}
+
+div#punch2{
+	float: left; 
+	width: 100px; 
+	height: 75px; 
+	text-align: center; 
+	color: white; 
+	border-width: 0 1px 1px 0; 
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+	display: none;
+}
+
+div#punch2 img{
+	height: 75px; 
+	width: 100px;
+	display: none;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-size: 9px;
+	text-align: left
+}
+
+#abutton{
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a:link{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none; 
+}
+
+a:visited{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:active{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:hover{
+	color: #00CCCC;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#code{
+	color: black;				 /* Foreground color */
+	background: white;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px; /* Font */
+	background-image: url('../images/barbgwhitecyan.jpg');
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/check-servers.json b/check-servers.json
new file mode 100644
index 00000000..414415ab
--- /dev/null
+++ b/check-servers.json
@@ -0,0 +1 @@
+{"phoenix_servers":[{"id":1,"address":"uswest.battle.net","port":6112,"type":1,"label":"uswest.battle.net","online":true},{"id":2,"address":"exodus.battle.net","port":6112,"type":1,"label":"exodus.battle.net","online":true},{"id":3,"address":"useast.battle.net","port":6112,"type":1,"label":"useast.battle.net","online":true},{"id":4,"address":"asia.battle.net","port":6112,"type":1,"label":"asia.battle.net","online":true},{"id":5,"address":"europe.battle.net","port":6112,"type":1,"label":"europe.battle.net","online":true},{"id":6,"address":"beta.battle.net","port":6112,"type":1,"label":"beta.battle.net","online":false},{"id":7,"address":"classicbeta.battle.net","port":6112,"type":1,"label":"classicbeta.battle.net","online":false},{"id":8,"address":"ustest.battle.net","port":6112,"type":1,"label":"ustest.battle.net","online":true},{"id":9,"address":"demo.war3.battle.net","port":6112,"type":1,"label":"demo.war3.battle.net","online":true},{"id":10,"address":"us.logon.battle.net","port":1119,"type":2,"label":"us.logon.battle.net","online":true},{"id":11,"address":"eu.logon.battle.net","port":1119,"type":2,"label":"eu.logon.battle.net","online":true},{"id":12,"address":"kr.logon.battle.net","port":1119,"type":2,"label":"kr.logon.battle.net","online":true},{"id":13,"address":"cn.logon.battle.net","port":1119,"type":2,"label":"cn.logon.battle.net","online":true},{"id":14,"address":"public-test.logon.battle.net","port":1119,"type":2,"label":"public-test.logon.battle.net","online":true},{"id":15,"address":"us.patch.battle.net","port":1119,"type":2,"label":"us.patch.battle.net","online":true},{"id":16,"address":"eu.patch.battle.net","port":1119,"type":2,"label":"eu.patch.battle.net","online":true},{"id":17,"address":"kr.patch.battle.net","port":1119,"type":2,"label":"kr.patch.battle.net","online":true},{"id":18,"address":"cn.patch.battle.net","port":1119,"type":2,"label":"cn.patch.battle.net","online":true},{"id":19,"address":"public-test.patch.battle.net","port":1119,"type":2,"label":"public-test.patch.battle.net","online":true},{"id":20,"address":"server.eurobattle.net","port":6112,"type":3,"label":"server.eurobattle.net","online":true},{"id":21,"address":"pvpgn.boredaussie.com","port":6112,"type":3,"label":"pvpgn.boredaussie.com","online":false},{"id":22,"address":"rubattle.net","port":6112,"type":3,"label":"rubattle.net","online":true},{"id":23,"address":"sc.theabyss.ru","port":6112,"type":3,"label":"sc.theabyss.ru","online":true},{"id":24,"address":"bnetd.fishbattle.net","port":6112,"type":3,"label":"bnetd.fishbattle.net","online":true},{"id":25,"address":"svr1.no-ip.org","port":6112,"type":3,"label":"svr1.no-ip.org","online":false},{"id":26,"address":"vetsvr.no-ip.org","port":6112,"type":3,"label":"vetsvr.no-ip.org","online":false},{"id":27,"address":"bnls.net","port":9367,"type":5,"label":"bnls.net","online":true},{"id":28,"address":"bnls.mattkv.net","port":9367,"type":5,"label":"bnls.mattkv.net","online":true},{"id":29,"address":"phix.no-ip.org","port":9367,"type":5,"label":"phix.no-ip.org","online":true},{"id":30,"address":"bnls.anubisdev.net","port":9367,"type":5,"label":"bnls.anubisdev.net","online":true},{"id":31,"address":"pyro.no-ip.biz","port":9367,"type":5,"label":"pyro.no-ip.biz","online":true},{"id":32,"address":"vectorjbls.no-ip.org","port":9367,"type":5,"label":"vectorjbls.no-ip.org","online":true},{"id":33,"address":"knight.mattkv.net","port":9367,"type":5,"label":"knight.mattkv.net","online":false},{"id":34,"address":"bnls.war-lords.net","port":9367,"type":5,"label":"bnls.war-lords.net","online":false},{"id":35,"address":"jailout2000.com","port":10011,"type":8,"label":"Jailout's TeamSpeak","online":true},{"id":36,"address":"jailout2000.com","port":25565,"type":6,"label":"Jailout's Minecraft Server","online":false}],"phoenix_server_types":[[1,"Official Battle.net v1 Servers"],[2,"Official Battle.net v2 Servers"],[3,"Unofficial Battle.net v1 Servers"],[5,"Battle.Net Logon Servers"],[6,"Minecraft Servers"],[8,"TeamSpeak 3 Servers"]],"redux_servers":{"bnet":[{"id":1,"address":"uswest.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":2,"address":"exodus.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":3,"address":"useast.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":4,"address":"asia.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":5,"address":"europe.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":6,"address":"beta.battle.net","port":6112,"version":"Battle.net v1","online":false},{"id":7,"address":"classicbeta.battle.net","port":6112,"version":"Battle.net v1","online":false},{"id":8,"address":"ustest.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":9,"address":"demo.war3.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":10,"address":"us.logon.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":11,"address":"eu.logon.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":12,"address":"kr.logon.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":13,"address":"cn.logon.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":14,"address":"public-test.logon.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":15,"address":"us.patch.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":16,"address":"eu.patch.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":17,"address":"kr.patch.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":18,"address":"cn.patch.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":19,"address":"public-test.patch.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":20,"address":"server.eurobattle.net","port":6112,"version":"PvPGN","online":true},{"id":21,"address":"pvpgn.boredaussie.com","port":6112,"version":"PvPGN","online":false},{"id":22,"address":"rubattle.net","port":6112,"version":"PvPGN","online":true},{"id":23,"address":"sc.theabyss.ru","port":6112,"version":"PvPGN","online":true},{"id":24,"address":"bnetd.fishbattle.net","port":6112,"version":"PvPGN","online":true},{"id":25,"address":"svr1.no-ip.org","port":6112,"version":"PvPGN","online":false},{"id":26,"address":"vetsvr.no-ip.org","port":6112,"version":"PvPGN","online":false}],"bnls":[{"id":1,"address":"bnls.net","port":9367,"online":true},{"id":2,"address":"bnls.mattkv.net","port":9367,"online":true},{"id":3,"address":"phix.no-ip.org","port":9367,"online":true},{"id":4,"address":"bnls.anubisdev.net","port":9367,"online":true},{"id":5,"address":"pyro.no-ip.biz","port":9367,"online":true},{"id":6,"address":"vectorjbls.no-ip.org","port":9367,"online":true},{"id":7,"address":"knight.mattkv.net","port":9367,"online":false},{"id":8,"address":"bnls.war-lords.net","port":9367,"online":false}]},"timestamp":{"utc_offset":-18000,"start":1400401201.8549,"end":1400401238.4269,"difference":36.572010040283,"total_time":"36.57s"}}
\ No newline at end of file
diff --git a/check-servers.log b/check-servers.log
new file mode 100644
index 00000000..a7258336
--- /dev/null
+++ b/check-servers.log
@@ -0,0 +1,80 @@
+[1;29m[2014-05-18 03:20:01 -0500] [0;0m[1;33mScript execution started.[0;0m
+[1;29m[2014-05-18 03:20:01 -0500] [0;0m[1;33mUpdating BNETDocs Redux server tables...[0;0m
+[1;29m[2014-05-18 03:20:01 -0500] [0;0m[1;32mConnected to database server.[0;0m
+[1;29m[2014-05-18 03:20:01 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   uswest.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:01 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   exodus.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   useast.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   asia.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   europe.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;31moffline[0;0m:  beta.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;31moffline[0;0m:  classicbeta.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   ustest.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   demo.war3.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   us.logon.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:03 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   eu.logon.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:03 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   kr.logon.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:04 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   cn.logon.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:04 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   public-test.logon.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:04 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   us.patch.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:04 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   eu.patch.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:05 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   kr.patch.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:08 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   cn.patch.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:08 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   public-test.patch.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:08 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   server.eurobattle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:08 -0500] [0;0m[1;34mBNET[0;0m server is [1;31moffline[0;0m:  pvpgn.boredaussie.com:6112[0;0m
+[1;29m[2014-05-18 03:20:09 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   rubattle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:09 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   sc.theabyss.ru:6112[0;0m
+[1;29m[2014-05-18 03:20:09 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   bnetd.fishbattle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:18 -0500] [0;0m[1;34mBNET[0;0m server is [1;31moffline[0;0m:  svr1.no-ip.org:6112[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;34mBNET[0;0m server is [1;31moffline[0;0m:  vetsvr.no-ip.org:6112[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;32monline[0;0m:   bnls.net:9367[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;32monline[0;0m:   bnls.mattkv.net:9367[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;32monline[0;0m:   phix.no-ip.org:9367[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;32monline[0;0m:   bnls.anubisdev.net:9367[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;32monline[0;0m:   pyro.no-ip.biz:9367[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;32monline[0;0m:   vectorjbls.no-ip.org:9367[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;31moffline[0;0m:  knight.mattkv.net:9367[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;31moffline[0;0m:  bnls.war-lords.net:9367[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;33mUpdating BNETDocs Phoenix server table...[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;32mConnected to database server.[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0mServer [1;36m1[0;0m is [1;32monline[0;0m:   uswest.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0mServer [1;36m2[0;0m is [1;32monline[0;0m:   exodus.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:23 -0500] [0;0mServer [1;36m3[0;0m is [1;32monline[0;0m:   useast.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m4[0;0m is [1;32monline[0;0m:   asia.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m5[0;0m is [1;32monline[0;0m:   europe.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m6[0;0m is [1;31moffline[0;0m:  beta.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m7[0;0m is [1;31moffline[0;0m:  classicbeta.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m8[0;0m is [1;32monline[0;0m:   ustest.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m9[0;0m is [1;32monline[0;0m:   demo.war3.battle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m10[0;0m is [1;32monline[0;0m:   us.logon.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m11[0;0m is [1;32monline[0;0m:   eu.logon.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m12[0;0m is [1;32monline[0;0m:   kr.logon.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:25 -0500] [0;0mServer [1;36m13[0;0m is [1;32monline[0;0m:   cn.logon.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:25 -0500] [0;0mServer [1;36m14[0;0m is [1;32monline[0;0m:   public-test.logon.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:25 -0500] [0;0mServer [1;36m15[0;0m is [1;32monline[0;0m:   us.patch.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:25 -0500] [0;0mServer [1;36m16[0;0m is [1;32monline[0;0m:   eu.patch.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:25 -0500] [0;0mServer [1;36m17[0;0m is [1;32monline[0;0m:   kr.patch.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:26 -0500] [0;0mServer [1;36m18[0;0m is [1;32monline[0;0m:   cn.patch.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:26 -0500] [0;0mServer [1;36m19[0;0m is [1;32monline[0;0m:   public-test.patch.battle.net:1119[0;0m
+[1;29m[2014-05-18 03:20:27 -0500] [0;0mServer [1;36m20[0;0m is [1;32monline[0;0m:   server.eurobattle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:27 -0500] [0;0mServer [1;36m21[0;0m is [1;31moffline[0;0m:  pvpgn.boredaussie.com:6112[0;0m
+[1;29m[2014-05-18 03:20:27 -0500] [0;0mServer [1;36m22[0;0m is [1;32monline[0;0m:   rubattle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:27 -0500] [0;0mServer [1;36m23[0;0m is [1;32monline[0;0m:   sc.theabyss.ru:6112[0;0m
+[1;29m[2014-05-18 03:20:27 -0500] [0;0mServer [1;36m24[0;0m is [1;32monline[0;0m:   bnetd.fishbattle.net:6112[0;0m
+[1;29m[2014-05-18 03:20:32 -0500] [0;0mServer [1;36m25[0;0m is [1;31moffline[0;0m:  svr1.no-ip.org:6112[0;0m
+[1;29m[2014-05-18 03:20:37 -0500] [0;0mServer [1;36m26[0;0m is [1;31moffline[0;0m:  vetsvr.no-ip.org:6112[0;0m
+[1;29m[2014-05-18 03:20:37 -0500] [0;0mServer [1;36m27[0;0m is [1;32monline[0;0m:   bnls.net:9367[0;0m
+[1;29m[2014-05-18 03:20:37 -0500] [0;0mServer [1;36m28[0;0m is [1;32monline[0;0m:   bnls.mattkv.net:9367[0;0m
+[1;29m[2014-05-18 03:20:37 -0500] [0;0mServer [1;36m29[0;0m is [1;32monline[0;0m:   phix.no-ip.org:9367[0;0m
+[1;29m[2014-05-18 03:20:37 -0500] [0;0mServer [1;36m30[0;0m is [1;32monline[0;0m:   bnls.anubisdev.net:9367[0;0m
+[1;29m[2014-05-18 03:20:37 -0500] [0;0mServer [1;36m31[0;0m is [1;32monline[0;0m:   pyro.no-ip.biz:9367[0;0m
+[1;29m[2014-05-18 03:20:38 -0500] [0;0mServer [1;36m32[0;0m is [1;32monline[0;0m:   vectorjbls.no-ip.org:9367[0;0m
+[1;29m[2014-05-18 03:20:38 -0500] [0;0mServer [1;36m33[0;0m is [1;31moffline[0;0m:  knight.mattkv.net:9367[0;0m
+[1;29m[2014-05-18 03:20:38 -0500] [0;0mServer [1;36m34[0;0m is [1;31moffline[0;0m:  bnls.war-lords.net:9367[0;0m
+[1;29m[2014-05-18 03:20:38 -0500] [0;0mServer [1;36m35[0;0m is [1;32monline[0;0m:   jailout2000.com:10011[0;0m
+[1;29m[2014-05-18 03:20:38 -0500] [0;0mServer [1;36m36[0;0m is [1;31moffline[0;0m:  jailout2000.com:25565[0;0m
+[1;29m[2014-05-18 03:20:38 -0500] [0;0m[1;33mAdding log entry to records...[0;0m
+[1;29m[2014-05-18 03:20:38 -0500] [0;0m[1;32mConnected to database server.[0;0m
+[1;29m[2014-05-18 03:20:38 -0500] [0;0m[1;32mLog entry recorded to logs table.[0;0m
+[1;29m[2014-05-18 03:20:38 -0500] [0;0m[1;32mLog entry recorded to filesystem.[0;0m
+[1;29m[2014-05-18 03:20:38 -0500] [0;0m[1;33mScript execution finished in [4;33m36.58s[0;33m[1;33m.[0;0m
diff --git a/check-servers.php b/check-servers.php
new file mode 100644
index 00000000..a0507baf
--- /dev/null
+++ b/check-servers.php
@@ -0,0 +1,348 @@
+<?php
+
+  if (php_sapi_name() != "cli") {
+    http_response_code(503);
+    header("Cache-Control: max-age=0, must-revalidate, no-cache, no-store");
+    header("Content-Type: text/plain;charset=utf-8");
+    echo "This file is intended to be executed via php's command line.";
+    exit(1);
+  }
+  
+  if ($argc > 1) {
+    echo "Usage: php -f " . $argv[0] . "\n";
+    exit(1);
+  }
+  
+  final class Logger {
+
+    const FILENAME    = "/home/nginx/bnetdocs/check-servers.log";
+    const DATE_FORMAT = "Y-m-d H:i:s O";
+
+    private static $fileHandle;
+
+    public static function initialize() {
+      self::$fileHandle = fopen(self::FILENAME, "w");
+    }
+
+    public static function finalize() {
+      fclose(self::$fileHandle);
+    }
+
+    public static function write($message, $suppressTimestamp = true) {
+      if (!$suppressTimestamp) {
+        $timestamp = "\e[1;29m[" . date(self::DATE_FORMAT) . "] \e[0;0m";
+        fwrite(self::$fileHandle, $timestamp);
+        echo $timestamp;
+      }
+      fwrite(self::$fileHandle, $message);
+      echo $message;
+    }
+
+    public static function writeLine($message) {
+      self::write($message . "\n", false);
+    }
+
+  }
+
+  final class DB {
+
+    private $sql;
+
+    public function __construct() {
+      $this->sql = mysqli_init();
+    }
+
+    public function connect($host, $user, $pass, $db) {
+      return @$this->sql->real_connect($host, $user, $pass, $db);
+    }
+
+    public function close() {
+      return $this->sql->close();
+    }
+
+    public function error() {
+      return $this->sql->error;
+    }
+
+    public function errno() {
+      return $this->sql->errno;
+    }
+
+    public function escape($data) {
+      return $this->sql->real_escape_string($data);
+    }
+
+    public function query($str) {
+      $res = $this->sql->query($str);
+      if (!is_object($res)) return false;
+      $items = array();
+      while ($item = $res->fetch_assoc()) {
+        $items[] = $item;
+      }
+      $res->free();
+      return $items;
+    }
+
+  }
+
+  final class ServerCheck {
+
+    const CONNECT_TIMEOUT = 5;
+
+    private $sock;
+
+    public function __construct() {
+      $this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
+    }
+
+    public function __destruct() {
+      if (isset($this->sock) && ($this->sock instanceof resource))
+        socket_close($this->sock);
+    }
+
+    public function connect($address, $port) {
+      $timeout = self::CONNECT_TIMEOUT;
+      $time = time();
+      socket_set_nonblock($this->sock);
+      while (!@socket_connect($this->sock, $address, $port)) {
+        $err = socket_last_error($this->sock);
+        if ($err == 115 || $err == 114) {
+          if ((time() - $time) >= $timeout) {
+            socket_close($this->sock);
+            return false;
+          }
+          sleep(0.1);
+          continue;
+        }
+        return false;
+      }
+      socket_set_block($this->sock);
+      return true;
+    }
+
+    public function close() {
+      if (isset($this->sock) && ($this->sock instanceof resource))
+        socket_close($this->sock);
+      return true;
+    }
+
+    public function errno() {
+      return socket_last_error($this->sock);
+    }
+
+    public function error() {
+      return socket_strerror($this->errno());
+    }
+
+  }
+
+  Logger::initialize();
+  Logger::writeLine("\e[1;33mScript execution started.\e[0;0m");
+  $script_start = microtime(true);
+  $exit_code = 0;
+  
+  /**
+   * Statistics definition
+   **/
+  $stats = array(
+    "phoenix_servers"      => array(),
+    "phoenix_server_types" => array(),
+    "redux_servers"        => array(
+      "bnet"               => array(),
+      "bnls"               => array(),
+    ),
+    "timestamp"            => array(
+      "utc_offset"         => (int)date("Z"),
+      "start"              => $script_start,
+      "end"                => null,
+      "difference"         => null,
+      "total_time"         => null,
+    ),
+  );
+
+  /**
+   * BNETDocs Redux's servers
+   **/
+  Logger::writeLine("\e[1;33mUpdating BNETDocs Redux server tables...\e[0;0m");
+  $db = new DB();
+  if (!$db->connect("127.0.0.1", "bnetdocs", "redux123", "bnetdocs_botdev")) {
+    Logger::writeLine("\e[1;31mUnable to connect to the database.\e[0;0m");
+    Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
+    $exit_code = 1;
+  } else {
+    Logger::writeLine("\e[1;32mConnected to database server.\e[0;0m");
+
+    /**
+     * BNETDocs Redux's BNET servers
+     **/
+    $servers = $db->query("SELECT `id`, `serveraddress`, `port`, `version` FROM `bnetservers` ORDER BY `id` ASC;");
+    if (!$servers) {
+      Logger::writeLine("\e[1;31mFailed to retrieve the BNETDocs Redux BNET servers.\e[0;0m");
+      Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
+      $exit_code = 1;
+    } else {
+      foreach ($servers as $server) {
+        $server_stats = array(
+          "id"      => (int)$server["id"],
+          "address" => (string)$server["serveraddress"],
+          "port"    => (int)$server["port"],
+          "version" => (string)$server["version"],
+          "online"  => null,
+        );
+        $sock = new ServerCheck();
+        if (!$sock->connect($server["serveraddress"], $server["port"])) {
+          Logger::writeLine("\e[1;34mBNET\e[0;0m server is \e[1;31moffline\e[0;0m:  " . $server["serveraddress"] . ":" . $server["port"] . "\e[0;0m");
+          $db->query("UPDATE `bnetservers` SET `status` = 'offline' WHERE `id` = '" . $db->escape($server["id"]) . "' LIMIT 1;");
+          $server_stats["online"] = false;
+        } else {
+          Logger::writeLine("\e[1;34mBNET\e[0;0m server is \e[1;32monline\e[0;0m:   " . $server["serveraddress"] . ":" . $server["port"] . "\e[0;0m");
+          $db->query("UPDATE `bnetservers` SET `status` = 'online' WHERE `id` = '" . $db->escape($server["id"]) . "' LIMIT 1;");
+          $server_stats["online"] = true;
+        }
+        $stats["redux_servers"]["bnet"][] = $server_stats;
+        $sock->close();
+      }
+    }
+    
+    /**
+     * BNETDocs Redux's BNLS servers
+     **/
+    $servers = $db->query("SELECT `id`, `serveraddress`, `port` FROM `servers` ORDER BY `id` ASC;");
+    if (!$servers) {
+      Logger::writeLine("\e[1;31mFailed to retrieve the BNETDocs Redux BNLS servers.\e[0;0m");
+      Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
+      $exit_code = 1;
+    } else {
+      foreach ($servers as $server) {
+        $server_stats = array(
+          "id"      => (int)$server["id"],
+          "address" => (string)$server["serveraddress"],
+          "port"    => (int)$server["port"],
+          "online"  => null,
+        );
+        $sock = new ServerCheck();
+        if (!$sock->connect($server["serveraddress"], $server["port"])) {
+          Logger::writeLine("\e[1;35mBNLS\e[0;0m server is \e[1;31moffline\e[0;0m:  " . $server["serveraddress"] . ":" . $server["port"] . "\e[0;0m");
+          $db->query("UPDATE `servers` SET `status` = 'offline' WHERE `id` = '" . $db->escape($server["id"]) . "' LIMIT 1;");
+          $server_stats["online"] = false;
+        } else {
+          Logger::writeLine("\e[1;35mBNLS\e[0;0m server is \e[1;32monline\e[0;0m:   " . $server["serveraddress"] . ":" . $server["port"] . "\e[0;0m");
+          $db->query("UPDATE `servers` SET `status` = 'online' WHERE `id` = '" . $db->escape($server["id"]) . "' LIMIT 1;");
+          $server_stats["online"] = true;
+        }
+        $stats["redux_servers"]["bnls"][] = $server_stats;
+        $sock->close();
+      }
+    }
+    
+    $db->close();
+  }
+  
+  /**
+   * BNETDocs Phoenix's servers
+   **/
+  Logger::writeLine("\e[1;33mUpdating BNETDocs Phoenix server table...\e[0;0m");
+  $db = new DB();
+  if (!$db->connect("127.0.0.1", "bnetdocs", "redux123", "bnetdocs_phoenix")) {
+    Logger::writeLine("\e[1;31mUnable to connect to the database.\e[0;0m");
+    Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
+    $exit_code = 1;
+  } else {
+    Logger::writeLine("\e[1;32mConnected to database server.\e[0;0m");
+
+    define('STATUS_ONLINE',   1);
+    define('STATUS_DISABLED', 2);
+
+    $servers = $db->query("SELECT t.`id` AS `id`, t.`label` AS `label` FROM `server_types` t JOIN `servers` s ON t.`id` = s.`type` AND NOT s.`status` & " . STATUS_DISABLED . " GROUP BY t.`id` ASC;");
+    if (!$servers) {
+      Logger::writeLine("\e[1;31mFailed to retrieve the BNETDocs Phoenix server types.\e[0;0m");
+      Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
+      $exit_code = 1;
+    } else {
+      $types = array();
+      foreach ($servers as $server) {
+        $type_id    = (int)$server["id"];
+        $type_label = (string)$server["label"];
+        $types[]    = array($type_id, $type_label);
+      }
+      $stats["phoenix_server_types"] = $types;
+    }
+
+    $servers = $db->query("SELECT `id`, `address`, `port`, `type`, `label` FROM `servers` WHERE NOT (`status` & " . STATUS_DISABLED . ") ORDER BY `id` ASC;");
+    if (!$servers) {
+      Logger::writeLine("\e[1;31mFailed to retrieve the BNETDocs Phoenix servers.\e[0;0m");
+      Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
+      $exit_code = 1;
+    } else {
+      foreach ($servers as $server) {
+        $server_stats = array(
+          "id"         => (int)$server["id"],
+          "address"    => (string)$server["address"],
+          "port"       => (int)$server["port"],
+          "type"       => (int)$server["type"],
+          "label"      => (string)$server["label"],
+          "online"     => null,
+        );
+        $sock = new ServerCheck();
+        if (!$sock->connect($server["address"], $server["port"])) {
+          Logger::writeLine("Server \e[1;36m" . $server["id"] . "\e[0;0m is \e[1;31moffline\e[0;0m:  " . $server["address"] . ":" . $server["port"] . "\e[0;0m");
+          $db->query("UPDATE `servers` SET `status` = (`status` & ~" . STATUS_ONLINE . "), `date_updated` = NOW() WHERE `id` = '" . $db->escape($server["id"]) . "' LIMIT 1;");
+          $server_stats["online"] = false;
+        } else {
+          Logger::writeLine("Server \e[1;36m" . $server["id"] . "\e[0;0m is \e[1;32monline\e[0;0m:   " . $server["address"] . ":" . $server["port"] . "\e[0;0m");
+          $db->query("UPDATE `servers` SET `status` = (`status` | " . STATUS_ONLINE . "), `date_updated` = NOW() WHERE `id` = '" . $db->escape($server["id"]) . "' LIMIT 1;");
+          $server_stats["online"] = true;
+        }
+        $stats["phoenix_servers"][] = $server_stats;
+        $sock->close();
+      }
+    }
+    
+    $db->close();
+  }
+  
+  /**
+   * Logging mechanisms
+   **/
+  Logger::writeLine("\e[1;33mAdding log entry to records...\e[0;0m");
+  $script_end = microtime(true);
+  $script_time = $script_end - $script_start;
+  $stats["timestamp"]["end"] = $script_end;
+  $stats["timestamp"]["difference"] = $script_time;
+  $stats["timestamp"]["total_time"] = sprintf("%01.2fs", $script_time);
+  $str_stats = json_encode($stats);
+  $db = new DB();
+  if (!$db->connect("127.0.0.1", "bnetdocs", "redux123", "bnetdocs_phoenix")) {
+    Logger::writeLine("\e[1;31mUnable to connect to the database.\e[0;0m");
+    Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
+    $exit_code = 1;
+  } else {
+    Logger::writeLine("\e[1;32mConnected to database server.\e[0;0m");
+
+    $db->query("INSERT INTO `logs` (`type_id`, `event_date`, `content`) "
+      . "SELECT `type_id`, "
+      . "NOW() AS `event_date`, "
+      . "'" . $db->escape($str_stats) . "' AS `content` "
+      . "FROM `log_types` WHERE `type_name` = 'servers_refreshed_system';");
+    if ($db->errno() == 0) {
+      Logger::writeLine("\e[1;32mLog entry recorded to logs table.\e[0;0m");
+    } else {
+      Logger::writeLine("\e[1;31mLog entry failed to be recorded to logs table.\e[0;0m");
+    }
+    
+    $db->close();
+  }
+  try {
+    $fh = fopen("/home/nginx/bnetdocs/check-servers.json", "w");
+    fwrite($fh, $str_stats);
+    fclose($fh);
+    Logger::writeLine("\e[1;32mLog entry recorded to filesystem.\e[0;0m");
+  } catch (Exception $e) {
+    Logger::writeLine("\e[1;31mLog entry failed to be recorded to filesystem.\e[0;0m");
+  }
+
+  $script_time = microtime(true) - $script_start;
+  Logger::writeLine("\e[1;33mScript execution finished in \e[4;33m" . round($script_time, 2) . "s\e[0;33m\e[1;33m.\e[0;0m");
+  Logger::finalize();
+  exit($exit_code);
+  
diff --git a/check-servers.sh b/check-servers.sh
new file mode 100755
index 00000000..ce9fea43
--- /dev/null
+++ b/check-servers.sh
@@ -0,0 +1,14 @@
+#!/bin/sh
+
+php -f /home/nginx/bnetdocs/check-servers.php
+EXIT_CODE=$?
+
+if [ $EXIT_CODE -ne 0 ]; then
+  echo -ne "\e[1;29m["
+  echo -n "`date +'%Y-%m-%d %H:%M:%S %z'`"
+  echo -ne "] \e[0;0m"
+  echo -e "\e[1;31mScript did not finish successfully.\e[0;0m"
+fi
+
+exit $EXIT_CODE
+
diff --git a/cpw.php b/cpw.php
new file mode 100644
index 00000000..38a42144
--- /dev/null
+++ b/cpw.php
@@ -0,0 +1,100 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth, $ip;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	if(!$userid) die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+
+	if($_POST['oldpw']) $_POST['oldpw'] = trim($_POST['oldpw']);
+	if($_POST['newpw']) $_POST['newpw'] = trim($_POST['newpw']);
+	
+	if(!$_POST['oldpw'] && !$_POST['newpw']){
+		?>
+			<div id="container">
+			<div id="main2">
+			<h2>Change Password</h2>
+			<blockquote>
+			<form method="post" action="/?op=cpw"><br>
+			&nbsp;&nbsp;Old Password:<br>
+			&nbsp;&nbsp;<input type="password" id="inputbox" name="oldpw"><br><br>
+			&nbsp;&nbsp;New Password:<br>
+			&nbsp;&nbsp;<input type="password" id="inputbox" name="newpw"><br><br>
+			&nbsp;&nbsp;<input type="submit" id="abutton" value="Change"><br>
+			</form>
+			<br></blockquote></div></div>
+		<?
+		$error = 'true';
+	} else {
+		if(!$_POST['oldpw']){
+			?>
+			<div id="container">
+			<div id="main2">
+			<h2>Change Password</h2>
+			<blockquote>
+			<form method="post" action="/?op=cpw"><br>
+			&nbsp;&nbsp;Old Password:<br>
+			&nbsp;&nbsp;<input type="password" id="inputbox" name="oldpw">&nbsp;&nbsp;&nbsp;<font color=red><b>REQUIRED!</b></font><br><br>
+			&nbsp;&nbsp;New Password:<br>
+			&nbsp;&nbsp;<input type="password" id="inputbox" name="newpw"><br><br>
+			&nbsp;&nbsp;<input type="submit" id="abutton" value="Change"><br>
+			</form>
+			<br></blockquote></div></div>
+			<?
+			$error = 'true';
+		}
+		if(!$_POST['newpw']){
+			?>
+			<div id="container">
+			<div id="main2">
+			<h2>Change Password</h2>
+			<blockquote>
+			<form method="post" action="/?op=cpw"><br>
+			&nbsp;&nbsp;Old Password:<br>
+			&nbsp;&nbsp;<input type="password" id="inputbox" name="oldpw"><br><br>
+			&nbsp;&nbsp;New Password:<br>
+			&nbsp;&nbsp;<input type="password" id="inputbox" name="newpw">&nbsp;&nbsp;&nbsp;<font color=red><b>REQUIRED!</b></font><br><br>
+			&nbsp;&nbsp;<input type="submit" id="abutton" value="Change"><br>
+			</form>
+			<br></blockquote></div></div>
+			<?
+			$error = 'true';
+		}
+		if($_POST['oldpw'] && $_POST['newpw']){
+			$currentpassword = GetData($userid, 'password');
+			$oldpassword = md5($_POST['oldpw']);
+			$newpassword = md5($_POST['newpw']);
+			
+			if($oldpassword != $currentpassword){
+				?>
+				<div id="container">
+				<div id="main2">
+				<h2>Change Password</h2>
+				<blockquote>
+				<form method="post" action="/?op=cpw"><br>
+				&nbsp;&nbsp;Old Password:<br>
+				&nbsp;&nbsp;<input type="password" id="inputbox" name="oldpw">&nbsp;&nbsp;&nbsp;<font color=red><b>INVALID PASSWORD!</b></font><br><br>
+				&nbsp;&nbsp;New Password:<br>
+				&nbsp;&nbsp;<input type="password" id="inputbox" name="newpw"><br><br>
+				&nbsp;&nbsp;<input type="submit" id="abutton" value="Change"><br>
+				</form>
+				<br></blockquote></div></div>
+				<?
+				$error = 'true';
+			}
+			if(!$error){
+				# Now we can finally change the damn password.
+				WriteData($userid, 'password', $newpassword);
+				?><div id="container">
+				<div id="main2">
+				<h2>Change Password</h2>
+				<br><br>
+				<center><b>Your password has been changed successfully.</b></center>
+				<br><br><br>
+				</div></div><?
+			}
+		}
+	}
+?>
diff --git a/credits.php b/credits.php
new file mode 100644
index 00000000..f94fe8a9
--- /dev/null
+++ b/credits.php
@@ -0,0 +1,45 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+?>
+<div id="container">
+<div id="main2">
+<h2>BNETDocs Credits</h2>
+<br><center>BNETDocs software written & maintained by <a href="http://www.doncullen.net/">Don Cullen</a> AKA <a href="http://www.dementedminds.net/index.php?op=profile&who=DM-Kyro">Kyro</a>.<br></center>
+<br>
+<center>Initial BNETDocs content compiled by <a href="mailto:arta@valhallalegends.com">Arta</a> and Skywing.<br></center>
+<br>
+<div id="author"><center>BNETDocs is administrated by:</center></div>
+<br><center>
+	<?
+		$sqlquery = 'SELECT * FROM users WHERE levelofaccess > 3 ORDER BY id ASC';
+		$membersarray = mysql_query($sqlquery);
+		while($row = mysql_fetch_array($membersarray)){
+			$username = $row['username'];
+			echo $username.'<br>';
+		} 
+	?>
+<br></center>
+<div id="author"><center>BNETDocs is edited by:</center></div>
+<br><center>
+	<?
+		$sqlquery = 'SELECT * FROM users WHERE levelofaccess=3 ORDER BY id ASC';
+		$membersarray = mysql_query($sqlquery);
+		while($row = mysql_fetch_array($membersarray)){
+			$username = ucfirst($row['username']);
+			echo $username.'<br>';
+		} 
+	?>
+<br></center>
+<div id="author"><center>Many thanks to the following, in no particular order, for their contributions:</center></div>
+<br><center>
+Arta, Skywing, Noodlez, Kane, Spht, Soul Taker, Barumonk[RC], iago[vL], TheMinistered,<br>
+[vL]Kp, Cloaked, Lord[nK], Ringo, shadypalm88, UserLoser, LivedKrad, Joe[x86], R.a.b.b.i.t.,<br>
+l2-Shadow, Smarter, Camel. While their contibutions aren't known to the new administrator (Kyro), their contributions are still nonetheless 
+appreciated. If you're the contributor mentioned in the previous list, please contact Kyro to have your contributions listed here.<br><br> DevCode -- Programatically obtain the VerByte code without reliance on BNLS<br><br></center>
+</div></div>
\ No newline at end of file
diff --git a/csseditor.php b/csseditor.php
new file mode 100644
index 00000000..5d09bc26
--- /dev/null
+++ b/csseditor.php
@@ -0,0 +1,88 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth, $ie;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	if(!$userid) die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+	
+	if(!$_POST){
+		if($_GET['defaultcss']) WriteData($userid, 'usercss', 'default');
+		if($_GET['lowfi']) WriteData($userid, 'usercss', 'lowfi');
+		if($_GET['dark']) WriteData($userid, 'usercss', 'dark');
+		if($_GET['dark'] || $_GET['lowfi'] || $_GET['defaultcss']){
+			redirect('/?op=csseditor');
+			exit();
+		}
+		$usercss = GetData($userid, 'usercss');
+		if($usercss == 'custom'){
+			$csstype='<span id="important">Custom</span>';
+		} elseif(substr($usercss, 0, 6) == 'user: ') { #using another member's css file
+			$csstype='Subscribed to '.substr($usercss, 6).'\'s CSS Theme.';
+		} else {
+			$csstype=$usercss;
+		}
+		
+		$found = false;
+		
+		if($usercss == 'custom'){ #user's own css file
+			$usercssfile = 'usercss/'.whoisid($userid).'.css';
+			$csstype='<span id="important">Custom</span>';
+			$found = true;
+		} elseif(substr($usercss, 0, 6) == 'user: ') { #using another member's css file
+			$usercssfile = 'usercss/'.substr($usercss, 6).'.css';
+			$csstype='Subscribed to '.substr($usercss, 6).'\'s CSS Theme.';
+			$found = true;
+		} else {
+			#do loop, if found, break, otherwise, use v1 styling
+			$sqlquery = 'SELECT * FROM themes';
+			$themearray = mysql_query($sqlquery);
+			while($row = mysql_fetch_array($themearray)){
+				$themename = $row['theme'];
+				$cssfile = $row['cssfile'];
+				if($cssfile == $usercss){
+					$usercssfile = 'usercss/'.$cssfile.'.css';
+					$csstype=$usercss;
+					$found = true;
+				}
+			}
+			if(!$csstype) $csstype='<span id="important">Custom using v1.0 CSS Theme Editor</span>';
+		}
+		
+		if($found){
+			$usercss = file_get_contents($usercssfile);
+		}
+		
+		?><div id="container">
+		<div id="main2">
+		<h2>CSS Theme Editor</h2>
+		<div align=center>
+		<br>
+		<center>Warning: if you modify the CSS, it becomes custom!<br><br>
+		If you were using a pre-set theme, and you switch to custom, your CSS will *not* auto-update itself if the contributor of the pre-set CSS Theme updates it!</center><br>
+		<? echo '<center>CSS Theme in use: '.$csstype.'</center><br>'; ?>
+		<form method="POST" name="newcss" action="/?op=csseditor">
+		<textarea name="csstheme" style="width: 90%;" id="inputbox" rows="20" cols="81"><?=$usercss;?></textarea>
+		<br><br><input type="submit" id="abutton" style="width:900" value="Save Custom"></form><br><a href="/?op=csseditor&dark=true">Load Dark Redux CSS</a>
+		<br><a href="/?op=csseditor&defaultcss=true">Load Default BNETDocs CSS</a>
+		<br><a href="/?op=csseditor&lowfi=true">Load Low-fi CSS</a>
+		<br><br>
+		</div></div></div><?
+	} else {
+		#Process post
+		$csstheme = $_POST['csstheme'];
+		$usercssfile = 'usercss/'.whoisid($userid).'.css';
+		if (is_writable($usercssfile))
+		{
+			$fp = fopen($usercssfile, 'w');
+			fwrite($fp, $csstheme);
+			fclose($fp);
+			WriteData($userid, 'usercss', 'custom');
+		} else {
+			logthis($userid, 'was unable to save their custom CSS file.', 'CONFIDENTAL');
+		}
+		redirect(curPageURL());
+	}
+?>
\ No newline at end of file
diff --git a/db.php b/db.php
new file mode 100644
index 00000000..ff3330ab
--- /dev/null
+++ b/db.php
@@ -0,0 +1,22 @@
+<?
+	######################
+	# Database Key Script
+	######################
+
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+
+	$dbhost = 'localhost';
+	$dbusername = 'bnetdocs';
+	$dbpasswd = 'redux123';
+	$database_name = 'bnetdocs_botdev';
+
+	@$connection = mysql_connect("$dbhost","$dbusername","$dbpasswd") or die ("Couldn't connect to server because ".mysql_error());
+	@$db = mysql_select_db("$database_name", $connection) or die("Couldn't select database because ".mysql_error());
+	@mysql_query('SET NAMES utf8_general_ci;');
+?>
diff --git a/doc.php b/doc.php
new file mode 100644
index 00000000..2ec369f0
--- /dev/null
+++ b/doc.php
@@ -0,0 +1,502 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+
+	# Begin Code
+	# -------------
+
+	$did = sanitize($_GET['did']);
+	$mode = sanitize($_GET['mode']);
+	$action = sanitize($_GET['action']);
+	$messageid = '';
+	$messagename = '';
+
+	if($mode == 'add'){
+		#Check rank
+		if($userid){
+			if(rank($userid) > 2){
+				#Allowed to add, now draw form
+				$action = 'add';
+				include 'bdif/doceditor.dm';
+			} else {
+				#Not allowed to add
+				logthis($userid, 'Illegally attempted to add a new document. Attempt blocked.', 'hack');
+				blockhack();
+			}
+		} else {
+			logthis($userid, 'Illegally attempted to add a new document. Attempt blocked.', 'hack');
+			blockhack();
+		}
+	} elseif($mode == 'edit'){
+		$action = 'edit';
+		#Check rank
+		if($userid){
+			if(rank($userid) > 2){
+				#Allowed to edit, now draw form
+				if(!$did){
+					logthis($userid, 'Illegally attempted to edit a document. Attempt blocked.', 'hack');
+					blockhack();
+				}
+				$title = delslash(GetInfo('documents', 'id', $did, 'title'));
+				$content = GetInfo('documents', 'id', $did, 'contents');
+				$related = GetInfo('documents', 'id', $did, 'related');
+				$clearance = GetInfo('documents', 'id', $did, 'clearance');
+
+				if($clearance == 0) $dcgueselected = 'selected';
+				if($clearance == 1) $dcuseselected = 'selected';
+				if($clearance == 2) $dcsupselected = 'selected';
+				if($clearance == 3) $dcediselected = 'selected';
+				if($clearance == 4) $dcadmselected = 'selected';
+
+				$action = 'edit';
+				include 'bdif/doceditor.dm';
+			} else {
+				#Not allowed to edit
+				logthis($userid, 'Illegally attempted to edit a document. Attempt blocked.', 'hack');
+				blockhack();
+			}
+		} else {
+			logthis($userid, 'Illegally attempted to edit a document. Attempt blocked.', 'hack');
+			blockhack();
+		}
+	} elseif($mode == 'delete'){
+		$action = 'delete';
+		#Check rank
+		if($userid){
+			if(rank($userid) > 2){
+				#Allowed to delete, now process deletion
+				if(!$did){
+					logthis($userid, 'attempted to delete a document without specifying document. Attempt blocked.', 'hack');
+					blockhack();
+				}
+				$title = GetInfo('documents', 'id', $did, 'title');
+				$content = GetInfo('documents', 'id', $did, 'contents');
+				$related = GetInfo('documents', 'id', $did, 'related');
+				$clearance = GetInfo('documents', 'id', $did, 'clearance');
+
+				if(strlen($related) > 0){
+					$linkarray = explode(',', $related);
+					foreach($linkarray as $link){
+						if($link){
+							$link = trim(strtoupper($link));
+							if(substr($link, 0, 1) == 'D' || substr($link, 0, 1) == 'P'){
+								if(substr($link, 0, 1) == 'D') $table = 'documents';
+								if(substr($link, 0, 1) == 'P') $table = 'packets';
+								if(FieldVerify('id', $table, substr($link, 1))){
+									# Link has been validated
+									$letter = substr($link, 0, 1);
+									if($letter == 'P'){
+										$rpdbid = substr($link, 1);
+										$rdid = GetInfo('packets', 'id', $rpdbid, 'messageid');
+										$rpname = GetInfo('packets', 'id', $rpdbid, 'messagename');
+										$rpdirection = GetInfo('packets', 'id', $rpdbid, 'direction');
+										if($rpdirection == 0){
+											$rpdirection = "&nbsp;(C->S)";
+										} else {
+											$rpdirection = "&nbsp;(S->C)";
+										}
+										$relatedlinkstring .= '<a href="/?op=packet&pid='.$rpdbid.'">['.$rdid.']&nbsp;'.$rpname.$rpdirection.'</a>, ';
+									} else {
+										$rpdbid = substr($link, 1);
+										$title = GetInfo('documents', 'id', $rpdbid, 'title');
+										$relatedlinkstring .= '<a href="/?op=doc&did='.$rpdbid.'">'.$title.'</a>, ';
+									}
+								}
+							} else {
+								$relatedlinkstring .= '<a href="'.$link.'">'.$link.'</a>, ';
+							}
+						}
+					}	
+					if(strlen($relatedlinkstring) > 0) $relatedlinkstring = substr_replace($relatedlinkstring,"",-2);
+				}
+
+				$logstring = 'Title: '.$title.'
+Content: '.$content.'
+Related: '.$relatedlinkstring;
+				
+				# Delete packet from database
+				$sql = "DELETE FROM `documents` WHERE id=$did";
+				mysql_query($sql) or die("Document Delete Error: ".mysql_error());
+
+				# Finished adding, confirm addition and take user to new packet.
+				logthis($userid, 'Deleted a document. Document Data: 
+'.$logstring.'', 'docdel');
+				WriteData($userid, 'msg', 'Successfully deleted the document! Thanks for your contribution!');
+				redirect('/');
+			} else {
+				#Not allowed to delete
+				logthis($userid, 'Illegally attempted to delete a document. Attempt blocked.', 'hack');
+				blockhack();
+			}
+		} else {
+			logthis($userid, 'Illegally attempted to delete a document. Attempt blocked.', 'hack');
+			blockhack();
+		}
+	} else {
+		if($action){
+			if($action == 'edit'){
+				# Update
+				# Obtain POST'ed data
+
+				$title = removeEvilTags(sanitize($_POST['title']));
+				$content = removeEvilTags(sanitize($_POST['content']));
+				$mrelated = removeEvilTags(sanitize($_POST['mrelated']));
+				$mclearance = removeEvilTags(sanitize($_POST['mclearance']));
+				
+				# Done obtaining data, now determine if person has authorization to add documents.
+
+				if(rank($userid) < 3){
+					logthis($userid, 'Illegally attempted to edit a document. Attempt blocked.', 'hack');
+					blockhack();
+				}
+
+				# Person has authorization, process data and edit it
+
+				if(!$title || !$content){
+					#missing data, abort
+					if(!$title) $title .= 'title, ';
+					if(!$content) $content .= 'content, ';
+					$missingdata = substr_replace($missingdata,"",-1);
+					$missingdata = substr_replace($missingdata,"",-1);
+					WriteData($userid, 'msg', 'Unable to edit document, missing data: '.$missingdata.' please fix.');
+					redirect('/?op=doc&mode=edit&did='.$did);
+				}
+				
+				if(strlen($mrelated) > 0){
+					$linkarray = explode(',', $mrelated);
+					foreach($linkarray as $link){
+						if($link){
+							$link = trim(strtoupper($link));
+							if(substr($link, 0, 1) == 'D' || substr($link, 0, 1) == 'P'){
+								if(substr($link, 0, 1) == 'D') $table = 'documents';
+								if(substr($link, 0, 1) == 'P') $table = 'packets';
+								if(FieldVerify('id', $table, substr($link, 1))){
+									# Link has been validated
+									$letter = substr($link, 0, 1);
+									if($letter == 'P'){
+										$rpdbid = substr($link, 1);
+										$rdid = GetInfo('packets', 'id', $rpdbid, 'messageid');
+										$rpname = GetInfo('packets', 'id', $rpdbid, 'messagename');
+										$rpdirection = GetInfo('packets', 'id', $rpdbid, 'direction');
+										if($rpdirection == 0){
+											$rpdirection = "&nbsp;(C->S)";
+										} else {
+											$rpdirection = "&nbsp;(S->C)";
+										}
+										$relatedlinkstring .= '<a href="/?op=packet&pid='.$rpdbid.'">['.$rdid.']&nbsp;'.$rpname.$rpdirection.'</a>, ';
+									} else {
+										$rpdbid = substr($link, 1);
+										$titlex = GetInfo('documents', 'id', $rpdbid, 'title');
+										$relatedlinkstring .= '<a href="/?op=doc&did='.$rpdbid.'">'.$titlex.'</a>, ';
+									}
+								}
+							} else {
+								$relatedlinkstring .= '<a href="'.$link.'">'.$link.'</a>, ';
+							}
+						}
+					}	
+					if(strlen($relatedlinkstring) > 0) $relatedlinkstring = substr_replace($relatedlinkstring,"",-2);
+				}
+				
+				$oldtitle = GetInfo('documents', 'id', $did, 'title');
+				$oldcontent = GetInfo('documents', 'id', $did, 'contents');
+				$oldrelated = GetInfo('documents', 'id', $did, 'related');
+				$oldclearance = GetInfo('documents', 'id', $did, 'clearance');
+				
+				if(strlen($oldrelated) > 0){
+					$linkarray = explode(',', $oldrelated);
+					foreach($linkarray as $link){
+						if($link){
+							$link = trim(strtoupper($link));
+							if(substr($link, 0, 1) == 'D' || substr($link, 0, 1) == 'P'){
+								if(substr($link, 0, 1) == 'D') $table = 'documents';
+								if(substr($link, 0, 1) == 'P') $table = 'packets';
+								if(FieldVerify('id', $table, substr($link, 1))){
+									# Link has been validated
+									$letter = substr($link, 0, 1);
+									if($letter == 'P'){
+										$rpdbid = substr($link, 1);
+										$rdid = GetInfo('packets', 'id', $rpdbid, 'messageid');
+										$rpname = GetInfo('packets', 'id', $rpdbid, 'messagename');
+										$rpdirection = GetInfo('packets', 'id', $rpdbid, 'direction');
+										if($rpdirection == 0){
+											$rpdirection = "&nbsp;(C->S)";
+										} else {
+											$rpdirection = "&nbsp;(S->C)";
+										}
+										$oldrelatedlinkstring .= '<a href="/?op=packet&pid='.$rpdbid.'">['.$rdid.']&nbsp;'.$rpname.$rpdirection.'</a>, ';
+									} else {
+										$rpdbid = substr($link, 1);
+										$titlex = GetInfo('documents', 'id', $rpdbid, 'title');
+										$oldrelatedlinkstring .= '<a href="/?op=doc&did='.$rpdbid.'">'.$titlex.'</a>, ';
+									}
+								}
+							} else {
+								$oldrelatedlinkstring .= '<a href="'.$link.'">'.$link.'</a>, ';
+							}
+						}
+					}	
+					if(strlen($oldrelatedlinkstring) > 0) $oldrelatedlinkstring = substr_replace($oldrelatedlinkstring,"",-2);
+				}
+				
+				$olddatalogstring = 'Title: '.$oldtitle.'
+Content: '.$oldcontent.'
+Clearance Level: '.$oldclearance.'
+Related: '.$oldrelatedlinkstring;
+
+				$newdatalogstring = 'Title: '.$title.'
+Content: '.$content.'
+Clearance Level: '.$clearance.'
+Related: '.$relatedlinkstring;
+
+				$newdatalogstring = sanitize($newdatalogstring);
+				$title = mysql_real_escape_string($title);
+				$content = $content;
+				
+				$sql = "UPDATE `documents` SET contents='$content', title='$title', related='$mrelated', clearance=$mclearance WHERE id=$did";
+				mysql_query($sql) or die("Document Edit Error: ".mysql_error()); #aEdit
+
+				# Finished adding, confirm addition and take user to updated document.
+				WriteData($userid, 'msg', 'Successfully edited the document! Thanks for your contribution!');					
+				logthis($userid, 'Edited a document. 
+Old Document Data: 
+
+'.$olddatalogstring.'
+
+Updated Document Data:
+
+'.$newdatalogstring.'', 'docedit');
+
+				redirect('/?op=doc&did='.$did);
+			} elseif($action == 'add') {
+				# Add
+				# Obtain POST'ed data
+
+				$title = sanitize($_POST['title']);
+				$content = sanitize($_POST['content']);
+				$mrelated = sanitize($_POST['mrelated']);
+				$mclearance = sanitize($_POST['mclearance']);
+
+				# Done obtaining data, now determine if person has authorization to add documents.
+
+				if(rank($userid) < 3){
+					logthis($userid, 'Illegally attempted to add a document. Attempt blocked.', 'hack');
+					blockhack();
+				}
+
+				# Person has authorization, process data and edit it
+
+				if(!$title || !$content){
+					#missing data, abort
+					if(!$title) $title .= 'title, ';
+					if(!$content) $content .= 'content, ';
+					$missingdata = substr_replace($missingdata,"",-1);
+					$missingdata = substr_replace($missingdata,"",-1);
+					WriteData($userid, 'msg', 'Unable to add document, missing data: '.$missingdata.' please fix.');
+					redirect('/?op=doc&mode=add');
+				}
+
+				if(strlen($mrelated) > 0){
+					$linkarray = explode(',', $mrelated);
+					foreach($linkarray as $link){
+						if($link){
+							$link = trim(strtoupper($link));
+							if(substr($link, 0, 1) == 'D' || substr($link, 0, 1) == 'P'){
+								if(substr($link, 0, 1) == 'D') $table = 'documents';
+								if(substr($link, 0, 1) == 'P') $table = 'packets';
+								if(FieldVerify('id', $table, substr($link, 1))){
+									# Link has been validated
+									$letter = substr($link, 0, 1);
+									if($letter == 'P'){
+										$rpdbid = substr($link, 1);
+										$rdid = GetInfo('packets', 'id', $rpdbid, 'messageid');
+										$rpname = GetInfo('packets', 'id', $rpdbid, 'messagename');
+										$rpdirection = GetInfo('packets', 'id', $rpdbid, 'direction');
+										if($rpdirection == 0){
+											$rpdirection = "&nbsp;(C->S)";
+										} else {
+											$rpdirection = "&nbsp;(S->C)";
+										}
+										$relatedlinkstring .= '<a href="/?op=packet&pid='.$rpdbid.'">['.$rdid.']&nbsp;'.$rpname.$rpdirection.'</a>, ';
+									} else {
+										$rpdbid = substr($link, 1);
+										$title = GetInfo('documents', 'id', $rpdbid, 'title');
+										$relatedlinkstring .= '<a href="/?op=doc&did='.$rpdbid.'">'.$title.'</a>, ';
+									}
+								}
+							} else {
+								$relatedlinkstring .= '<a href="'.$link.'">'.$link.'</a>, ';
+							}
+						}
+					}	
+					if(strlen($relatedlinkstring) > 0) $relatedlinkstring = substr_replace($relatedlinkstring,"",-2);
+				}
+					
+				$newdatalogstring = 'Title: '.$title.'
+Content: '.$content.'
+Clearance Level: '.$clearance.'
+Related: '.$relatedlinkstring;
+
+				$newdatalogstring = sanitize($newdatalogstring);
+
+				$sql = "INSERT INTO `documents` (`contents`, `title`, `related`, `clearance`) VALUES ('$content', '$title', '$mrelated', $mclearance)";
+				mysql_query($sql) or die("Document Add Error: ".mysql_error());
+
+				# Finished adding, confirm addition and take user to updated document.
+				WriteData($userid, 'msg', 'Successfully added the document! Thanks for your contribution!');					
+				logthis($userid, 'Added a document. 
+New Document Data: 
+
+'.$newdatalogstring.'', 'docedit');
+				$sql = "SELECT id FROM `documents` WHERE `contents` = '$content' AND `title` = '$title'";
+				$sqlquery = mysql_query($sql) or die("Document Addition Selection Error: ".mysql_error());
+				$newdid = mysql_result($sqlquery,0,'id');
+				redirect('/?op=doc&did='.$newdid);
+			}
+		} else {
+			if(!$did){
+				echo 'No document ID has been specified. Unable to seek document data.';
+			} else {
+				$title = delslash(GetInfo('documents', 'id', $did, 'title'));
+				$content = codify(GetInfo('documents', 'id', $did, 'contents'));
+				$related = GetInfo('documents', 'id', $did, 'related');
+				$clearance = GetInfo('documents', 'id', $did, 'clearance');
+				if(strlen($related) > 0){
+					$linkarray = explode(',', $related);
+					foreach($linkarray as $link){
+						if($link){
+							$link = trim(strtoupper($link));
+							if(substr($link, 0, 1) == 'D' || substr($link, 0, 1) == 'P'){
+								if(substr($link, 0, 1) == 'D') $table = 'documents';
+								if(substr($link, 0, 1) == 'P') $table = 'packets';
+								if(FieldVerify('id', $table, substr($link, 1))){
+									# Link has been validated
+									$letter = substr($link, 0, 1);
+									if($letter == 'P'){
+										$rpdbid = substr($link, 1);
+										$rdid = GetInfo('packets', 'id', $rpdbid, 'messageid');
+										$rpname = GetInfo('packets', 'id', $rpdbid, 'messagename');
+										$rpdirection = GetInfo('packets', 'id', $rpdbid, 'direction');
+										if($rpdirection == 0){
+											$rpdirection = "&nbsp;(C->S)";
+										} else {
+											$rpdirection = "&nbsp;(S->C)";
+										}
+										$relatedlinkstring .= '<a href="/?op=packet&pid='.$rpdbid.'">['.$rdid.']&nbsp;'.$rpname.$rpdirection.'</a>, ';
+									} else {
+										$rpdbid = substr($link, 1);
+										$titlex = GetInfo('documents', 'id', $rpdbid, 'title');
+										$relatedlinkstring .= '<a href="/?op=doc&did='.$rpdbid.'">'.$titlex.'</a>, ';
+									}
+								}
+							} else {
+								$relatedlinkstring .= '<a href="'.$link.'">'.$link.'</a>, ';
+							}
+						}
+					}	
+					if(strlen($relatedlinkstring) > 0) $relatedlinkstring = substr_replace($relatedlinkstring,"",-2);
+				}
+
+				if($clearance > 0){
+					if($userid){
+						if(rank($userid) < $clearance){
+							logthis($userid, ' attempted to access a packet with insufficent clearance. Attempt blocked.', 'hack');
+							blockhack();
+						}
+					} else {
+						logthis($userid, ' attempted to access a packet with insufficent clearance. Attempt blocked.', 'hack');
+						blockhack();
+					}
+				}
+				
+				$content = str_replace("(FILETIME)", "<font class=\"keyword\">(FILETIME)</font>", $content);
+				$content = str_replace("(DWORD)", "<font class=\"keyword\">(DWORD)</font>", $content);
+				$content = str_replace("(BOOLEAN)", "<font class=\"keyword\">(BOOLEAN)</font>", $content);
+				$content = str_replace("(WORD)", "<font class=\"keyword\">(WORD)</font>", $content);
+				$content = str_replace("(BYTE)", "<font class=\"keyword\">(BYTE)</font>", $content);
+				$content = str_replace("(STRING)", "<font class=\"keyword\">(STRING)</font>", $content);
+				$content = str_replace("(WIDESTRING)", "<font class=\"keyword\">(WIDESTRING)</font>", $content);
+				$content = str_replace("(VOID)", "<font class=\"keyword\">(VOID)</font>", $content);
+				
+				$content = brfix($content);
+				
+				?>
+				<div id="container">
+				<div id="main2">
+				<h2><?=$title;?></h2>
+				<br>
+				<? 
+				if($userid){
+					if(rank($userid) > 2){ 
+						?><center><font size=1>[ &nbsp; <a href="/?op=doc&mode=edit&did=<?=$did;?>">EDIT</a> &nbsp; 
+						| &nbsp; <a onClick="return confimdelete();" href="/?op=doc&mode=delete&did=<?=$did;?>">DELETE</a> &nbsp; ]</font><br><br></center>
+						<?
+					}
+				}
+				?>
+				<div align="center"><div style="width: 97%;" align="left">
+				<?=$content;?>
+				<br><br>
+				<div align=center>
+				<?
+				if($related){
+					?>
+					<div id="code">Related: <?=$relatedlinkstring;?></div></div>
+					<?
+				}
+				?></div></div></div></div></div>
+				
+				<div id="comments">
+				<div id="container">
+				<div id="main2">
+				<h2>User Comments</h2>
+				<center><br>For detailed questions and discussion, visit the <a href="http://forum.valhallalegends.com/index.php/board,17.0.html" target="_blank">Battle.net Research Forum</a><br><br></center>
+				<?
+				$sqlqueryz = 'SELECT id,posterid,UNIX_TIMESTAMP(dtstamp) as unixdtstamp,message FROM comments WHERE pdid='.$did.' ORDER BY id';
+				$docarray = mysql_query($sqlqueryz);
+				$commentcount = 0;
+				while($rowz = mysql_fetch_array($docarray)){
+					$cid = $rowz['id'];
+					$posterid = $rowz['posterid'];
+					$dtstamp = date("M d, Y", $rowz['unixdtstamp']);
+					$dtstamp .= '<br>'.date('h:i A', $rowz['unixdtstamp']);
+					$message = Codify($rowz['message']);
+					if($userid){
+						if($posterid == $userid){
+							$editdelstr = '[ <a href="/?op=postcomment&mode=edit&cid='.$cid.'&did='.$did.'">EDIT</a> | <a onClick="return confimdelete();" href="/?op=postcomment&mode=delete&cid='.$cid.'&did='.$did.'">DELETE</a> ]';
+						} else {
+							if(rank($userid) > 2){ 
+								$editdelstr = '[ <a onClick="return confimdelete();" href="/?op=postcomment&mode=delete&cid='.$cid.'&did='.$did.'">DELETE</a> ]';
+							}
+						}
+					}
+					if($editdelstr){
+						$title = '<div id="author" nowrap>'.$editdelstr.'</div>';
+					} else {
+						$title = '<div id="author" nowrap> </div>';
+					}
+					echo $title;
+					echo '<table border=0 width="100%" cellpadding=1 cellspacing=0><tr><td width="20%" align="center" height="100%"><table height="100%" width="100%" class="commentsidebar" border=0 cellpadding=0 cellspacing=0><tr><td width="100%" height="100%" align="center" valign="center">'.whoisid($posterid).'<br>'.$dtstamp.'</td></tr></table></td><td><div style="border: 1px #555 solid; padding: 2px; padding-left: 5px;"><br>'.$message.'<br><br></div></td></tr></table>';
+					$commentcount++;
+				}
+				if($commentcount < 1) echo '<center>No comments were made. Be the first to contribute!<br><br></center>';
+				if($userid){
+					?>
+					<div id="author" nowrap><center>Got Something To Say?</center></div>
+					<center>
+					<br>
+					<form method="POST" name="newcomment" action="/?op=postcomment">
+					<input type="hidden" name="did" value="<?=$did;?>">
+					<textarea name="mycomment" style="width: 90%;" id="inputbox" rows="10" cols="81"></textarea>
+					<br><br><input type="submit" id="abutton" style="width:900" value="Submit"><br><br></form>
+			
+					</center></div>
+					</div></div>
+					<?
+				}
+			}
+		}
+	}
+?>
diff --git a/doceditor.dm b/doceditor.dm
new file mode 100644
index 00000000..0daf8837
--- /dev/null
+++ b/doceditor.dm
@@ -0,0 +1,39 @@
+			<? 
+				global $userid, $rank, $postdate, $title, $content, $edit, $did, $action; 
+			?>
+			<div id="newscontainer">
+			<div id="main2">
+			<h2>Document Editor</h2>
+			<blockquote><form method="POST" name="doceditor" action="/?op=doc&action=<?=$action;?><? if($action=='edit') echo '&did='.$did; ?>">
+			</center>
+			<table border=0 cellspacing=2 cellpadding=2 width=100%>
+				<tr>
+					<td width=0>Title:</td><td width=100%><input type="text" name="title" value="<?=$title;?>" size=45 id="inputbox"></td>
+				</tr>
+				<tr>
+					<td valign=top>Content:</td>
+					<td>
+						<textarea onclick="sz(this);" onkeyup="sz(this)" style="width: 100%;" id="inputbox" name="content" rows="10" cols="81"><?=$content;?></textarea>
+					</td>
+				</tr>
+				<tr>
+					<td>Related:</td><td><input type="text" name="mrelated" value="<?=$related;?>" size=45 id="inputbox"> <font size=1>[ <a href="/?op=help&topic=related links">HELP</a> ]</font></td>
+				</tr>
+				<tr>
+					<td nowrap>Clearance Required:</td>
+					<td>
+						<select name="mclearance" size="1">
+						<option <?=$dcgueselected;?> value="0">Guest</option>
+						<option <?=$dcuseselected;?> value="1">User</option>
+						<option <?=$dcsupselected;?> value="2">Superuser</option>
+						<option <?=$dcediselected;?> value="3">Editor</option>
+						<option <?=$dcadmselected;?> value="4">Administrator</option>
+						</select>
+					</td>
+				</tr>
+			</table>
+			<br>
+			<input type="submit" id="abutton" onclick="this.disabled=false;" value="Submit"></form>
+			</blockquote>
+			</div></div>
+			<br>
\ No newline at end of file
diff --git a/encryption.php b/encryption.php
new file mode 100644
index 00000000..b34fb04e
--- /dev/null
+++ b/encryption.php
@@ -0,0 +1,9 @@
+<?
+	$str = 'This is a string.';
+	echo 'Before encoding: '.$str.'<br>';
+	$str = base64_encode($str);
+	echo 'After encoding: '.$str.'<br>';
+	$str = base64_decode($str);
+	echo 'After decoding using base64_decode: '.$str.'<br>';
+	echo 'Done.';
+?>
\ No newline at end of file
diff --git a/experiment.php b/experiment.php
new file mode 100644
index 00000000..ff8668f7
--- /dev/null
+++ b/experiment.php
@@ -0,0 +1,28 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth, $ie;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	if(!$userid) die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+	
+	if (!empty($_POST['text'])){
+	   
+	   echo '<link rel="stylesheet" href="hilight.css" />';
+	   echo '<div style="border: solid 1px orange; padding: 20px; margin: 20px">';
+	   
+	   require_once '/usr/share/pear/Text/';
+	   $highlighter = Text_Highlighter::factory('php');
+	   echo $highlighter->highlight($_POST['text']);
+	   
+	   echo '</div>';
+	}
+?>
+
+<form action="/?op=experiment" method="post">
+   <textarea name="text" style="width: 300px; height: 200px"><?php echo @$_POST['text']; ?></textarea>
+   <br />
+   <input type="submit" />
+</form>
\ No newline at end of file
diff --git a/favicon.pdn b/favicon.pdn
new file mode 100644
index 0000000000000000000000000000000000000000..d6bee05866e95a04db71c04883b1b9c7b6f0cebc
GIT binary patch
diff --git a/favicon.png b/favicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..013776cf8a1e9e2361f8d9342d13f838a2e8b217
GIT binary patch
diff --git a/func.php b/func.php
new file mode 100644
index 00000000..27195c61
--- /dev/null
+++ b/func.php
@@ -0,0 +1,1057 @@
+<?
+	########################
+	# Core Functions Script
+	########################
+
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth;
+	if($auth != 'true') die('<html><head><title>BNETDocs: Redux</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+	
+	# DisplayDialogBox Function
+	# --------------------
+	#
+	# Function Name: DisplayDialogBox
+	# Purpose: Figure it out.
+	# Variable Uses:
+	#
+	# $text = The text to display as contents of the dialog box; Required; String.
+	# $poster = The poster of who posted dialog; Optional; String.
+	# $title = The title of the dialog box; Optional; String.
+	# $insdate = Inserts date automatically; Optional; Boolean.
+	# $file = Determines whether $text is treated as an include file; Optional; Boolean.
+	#
+	# --------------------
+		function DisplayDialogBox($text, $title='none', $file=false, $align='left'){
+			include 'bdif/dialogbox.dm';
+		}
+	#-------------
+	# End of DisplayDialogBox Function
+	#-------------
+
+
+
+	# DisplayNavBox Function
+	# --------------------
+	#
+	# Function Name: DisplayNavBox
+	# Purpose: Figure it out.
+	# Variable Uses:
+	#
+	# $text = The text to display as contents of the nav box; Required; String.
+	# $title = The title of the dialog box; Optional; String.
+	# $file = Determines whether $text is treated as an include file; Optional; Boolean.
+	#
+	# --------------------
+		function DisplayNavBox($text, $title="none", $file=false){
+			$auth = true;
+			$username = $_SESSION['username'];
+			include 'dmti/navbox.dm';
+		}
+	#-------------
+	# End of DisplayNavBox Function
+	#-------------
+
+	function getdir($dir, $no_dots=TRUE, $no_dirs=TRUE) {
+		$files = array();
+		$dh  = @opendir($dir);
+		if ($dh!=FALSE) {
+			while (false !== ($filename = readdir($dh))) {
+				$files[] = $filename;
+			}
+		
+			if ($no_dots) {
+				while(($ix = array_search('.',$files)) > -1) unset($files[$ix]);
+				while(($ix = array_search('..',$files)) > -1) unset($files[$ix]);
+				$li=0;
+				while($li <= count($files)){
+					$first = $str{0};
+					if($files[$li]{0}=='.') unset($files[$li]);
+					if($files[$li]{0}.$files[$li]{1}=='..') unset($files[$li]);
+					$li++;
+				}
+
+			}
+
+			if ($no_dirs) {
+				$li=0;
+				while($li <= count($files)){
+					if(is_dir($files[$li])) unset($files[$li]);
+					$li++;
+				}
+			}
+			$li=0;
+			while($li <= count($files)){
+				if(trim($files[$li])=='') unset($files[$li]);
+				$li++;
+			}
+
+			sort($files);
+		}
+	
+		return $files;
+	}
+
+	function MsgBox($message){
+		if(!$message) $message='Error: $message variable is empty.';
+		echo '
+			<SCRIPT LANGUAGE="javascript">
+			<!--
+				function MYALERT() {
+					alert("'.$message.'");
+				} 
+				MYALERT() 
+			<!-- END -->
+			</SCRIPT>';
+	}
+
+	function createRandomPassword() {
+	
+	    $chars = "abcdefghijkmnopqrstuvwxyz023456789";
+	    srand((double)microtime()*1000000);
+	    $i = 0;
+	    $pass = '' ;
+	
+	    while ($i <= 7) {
+	        $num = rand() % 33;
+	        $tmp = substr($chars, $num, 1);
+	        $pass = $pass . $tmp;
+	        $i++;
+	    }
+	
+	    return $pass;
+	
+	}
+
+	# Login Function
+	# --------------------
+	#
+	# Function Name: login
+	# Variable Uses:
+	#
+	# $username = member user name
+	# $password = member's password
+	# $tracked = determines if login is logged.
+	#
+	# --------------------
+		function login($username, $password, $tracked=true, $ip) {
+
+			# Set up pass variable
+			#-------------
+		
+				$ret = "pass";
+			
+			# Make sure we have data for user name and pw, if not, error out.
+			#-------------
+
+				if((!$username) || (!$password)){
+					$ret = "Missing login information.";
+				}
+
+			# Check database to verify login info
+			#-------------
+
+			if(FieldVerify("username", "users", $username)){
+				$userid = GetInfo("users", "username", $username, "id");
+				$pwtocheck = md5($password);
+				$password = GetInfo("users", "id", $userid, "password");
+			} else {
+				$ret = "You're not a registered user of BNETDocs: Redux.";
+			}
+
+			if($ret != "pass"){
+				return $ret;
+			}
+			
+			if($pwtocheck == $password){
+
+				# Login has been verified, get basic info from DB on member.
+				#-------------
+
+					$username = GetInfo("users", "id", $userid, "username");
+
+				# If tracking is enabled, log IP and login time/date.
+				#-------------
+
+					$ip = $_SERVER["REMOTE_ADDR"];
+					$sql = "UPDATE users SET ip=\"$ip\" WHERE username=\"$username\"";
+					if($tracked == true) $sqlresults = mysql_query($sql) or die (mysql_error());
+					if($tracked == true) mysql_query("UPDATE users SET last_login=now() WHERE username='$username'");
+
+				# Set up session for member
+				#-------------
+
+					CreateSession($userid, $ip);
+
+				#-------------
+				# Done setting up session
+				#-------------
+
+			} else {
+
+				# Invalid login info. Error out.
+				#-------------
+
+				$ret = "<br /><center>Invalid Login!</center>";
+			}
+			
+			return $ret;
+		}
+	#-------------
+	# End of Login Function
+	#-------------
+
+	function error($message){
+		DisplayDialogBox('<br><br><br><br><br><br><br><center><font size=5>'.$message.'</font></center><br><br><br><br><br><br><br>', '<font size=3><center>Error</center></font>');
+	}
+	
+	
+	
+	# FieldVerify Function
+	# --------------------
+	#
+	# Function Name: FieldVerify
+	# Purpose: Checks to see if a given field containing specified data exists
+	# Variable Uses:
+	#
+	# $table = Target table to access
+	# $field = Field to check in
+	# $data = Data of whatever you're verifying
+	#
+	# --------------------
+		function FieldVerify($field, $table, $data){
+			
+			$sql = "SELECT COUNT(*) AS count FROM `$table` WHERE `$field`=\"$data\"";
+
+			$testercount = mysql_query($sql) or die("mysql error in $sql: ".mysql_error());
+			$testercount = mysql_fetch_object($testercount);
+			$testers = $testercount->count;
+			
+			if($testers > 0){
+				return true;
+			}
+			return false;
+		}
+	#-------------
+	# End of FieldVerify Function
+	#-------------
+
+	
+	# Sector Security Function
+	# --------------------
+	#
+	# Function Name: Secure
+	# Variable Uses: None.
+	#
+	# --------------------
+		function secure($ip) {
+
+			# Check to see if session exists.
+			#-------------
+			
+			if(!FieldVerify("ipaddress", "sessions", $ip)){
+				Redirect("/?op=login");
+			}
+			
+			# Update Activity
+			#------------
+			
+			$userid = GetInfo("sessions", "ipaddress", $ip, "id");
+			mysql_query("UPDATE users SET last_login=now() WHERE id='$userid'");
+		}
+
+	#-------------
+	# End of Sector Security Function
+	#-------------
+
+
+
+	# GetData Function
+	# --------------------
+	#
+	# Function Name: GetData
+	# Purpose: Makes it easier to obtain a member's info.
+	# Variable Uses:
+	#
+	# $whoid = target member for info request
+	# $what = which field data to pull up
+	#
+	# --------------------
+		function GetData($whoid, $what){
+			$ret = GetInfo("users", "id", $whoid, $what);
+			return $ret;
+		}
+	#-------------
+	# End of GetData Function
+	#-------------
+
+	# WriteData Function
+	# --------------------
+	#
+	# Function Name: WriteData
+	# Purpose: Makes it easier to update a member's info.
+	# Variable Uses:
+	#
+	# $whoid = target member for info update
+	# $what = which field data to modify (field *MUST* exist)
+	#$data = the data to write
+	#
+	# --------------------
+		function WriteData($whoid, $what, $data){
+			$ret = true;
+			$sql = "UPDATE users SET `$what`=\"$data\" WHERE id=$whoid"; 
+			$sqlresults = mysql_query($sql) or $ret = false;
+			return $ret;
+		}
+	#-------------
+	# End of WriteData Function
+	#-------------
+	
+	
+	
+	function Discipline($target, $action, $ip=''){
+		if($action == 'lp'){
+			$sql = "UPDATE discipline SET profile=0 WHERE account=$target";
+			$sqlresults = mysql_query($sql) or die(mysql_error());
+		} else if($action == 'up'){
+			$sql = "UPDATE discipline SET profile=1 WHERE account=$target";
+			$sqlresults = mysql_query($sql) or die(mysql_error());
+		} else if($action == 'fa'){
+			$sql = "UPDATE discipline SET frozen=1 WHERE account=$target";
+			$sqlresults = mysql_query($sql) or die(mysql_error());
+		} else if($action == 'ufa'){
+			$sql = "UPDATE discipline SET frozen=0 WHERE account=$target";
+			$sqlresults = mysql_query($sql) or die(mysql_error());
+		} else if($action == 'ipban'){
+			$sql = "UPDATE discipline SET ipban=1 WHERE account=$target";
+			$sqlresults = mysql_query($sql) or die(mysql_error());
+			$currentip = GetData($target, 'ip');
+			mysql_query("INSERT INTO `banned` (id, ip, bantype) VALUES ($target, '$ip', 'total')") or die("Discipline Function Error: ".mysql_error());
+		} else if($action == 'unipban'){
+			$sql = "UPDATE discipline SET ipban=0 WHERE account=$target";
+			$sqlresults = mysql_query($sql) or die(mysql_error());
+			$sql = "DELETE FROM banned WHERE id=\"$target\"";
+			$sqlresults = mysql_query($sql) or die (mysql_error());
+		}
+	}
+	
+	function BlockHack(){
+		die('<center><br><br><b><font color=red>Unauthorized access blocked. Nice try, buddy.</font></b><br><br></center>');
+	}
+	
+	# GetInfo Function
+	# --------------------
+	#
+	# Function Name: GetInfo
+	# Purpose: Offers specialized information by specifying data request
+	# Variable Uses:
+	#
+	# $db = Target database to access
+	# $index = Field to correlate $id from.
+	# $id = ID/ACCOUNT/USERNAME of whatever you're accessing
+	# $data = The field where you want to obtain the data from.
+	# --------------------
+		function GetInfo($db, $index, $id, $data){
+			$sqlquery = mysql_query("SELECT * FROM `$db` WHERE `$index`=\"$id\" LIMIT 1") or die('Attempted Query: '."SELECT * FROM `$db` WHERE `$index`='$id' LIMIT 1"."<br>GetInfo Function Error: ".mysql_error());;
+			if(mysql_num_rows($sqlquery) > 0) {
+				$ret = mysql_result($sqlquery,0,$data);
+			} else {
+				$ret = false;
+			}
+			return $ret;
+		}
+	#-------------
+	# End of GetInfo Function
+	#-------------
+
+	# WriteInfo Function
+	# --------------------
+	#
+	# Function Name: WriteInfo
+	# Purpose: Writes specialized information by specifying data request to existing field
+	# Variable Uses:
+	#
+	# $db = Target database to access
+	# $index = Field to correlate $id from.
+	# $id = ID/ACCOUNT/USERNAME of whatever you're accessing
+	# $field = The field where you want to write the data to.
+	#$data = the data you'd like to have written
+	# Example: WriteInfo('messages', 'id', $id, 'opened', 1);
+	# --------------------
+		function WriteInfo($db, $index, $id, $field, $data){
+			$ret = true;
+			$sql = "UPDATE `$db` SET `$field`=\"$data\" WHERE $index=$id"; 
+			$sqlresults = mysql_query($sql) or $ret = false;
+			return $ret;
+		}
+	#-------------
+	# End of GetInfo Function
+	#-------------
+
+	# URLButton Function
+	# --------------------
+	#
+	# Function Name: URLButton
+	# Purpose: A form button acts as a hyperlink
+	# Variable Uses:
+	#
+	# $text = Text to display on button
+	# $url = Target address to send to when clicked
+	#
+	# --------------------
+		function URLButton($text,$url){
+			?><form><input id="abutton" style="width:125;height:23" type=button value="<? echo $text ?>" onClick="gourl('<? echo $url ?>')"></form><?
+		}
+	#-------------
+	# End of URLButton Function
+	#-------------
+
+	
+
+	# Redirect Function
+	# --------------------
+	#
+	# Function Name: Redirect
+	# Purpose: Redirects user to target page
+	# Variable Uses:
+	#
+	# $page = Target page to redirect to
+	#
+	# --------------------
+		function Redirect($page){
+			echo "<meta http-equiv=\"refresh\" content=\"0;url=$page\"><body bgcolor=black>";
+			die();
+		}
+	#-------------
+	# End of Redirect Function
+	#-------------
+	
+	if (!function_exists("stripos")) {
+	  function stripos($str,$needle,$offset=0)
+	  {
+	      return strpos(strtolower($str),strtolower($needle),$offset);
+	  }
+	}
+
+	# Email Function
+	# --------------------
+	#
+	# Function Name: Email
+	# Purpose: Send emails
+	# Variable Uses:
+	#
+	# $target = email address to send the email to
+	# $fromwho = return address
+	# $subject = obvious...
+	# $body = obvious...
+	#
+	# --------------------
+		function Email($target, $fromwho, $subject, $body){
+			$headers = "From: BNETDocs<$fromwho>\r\n";
+			mail($target, $subject, $body, $headers);
+		}
+	#-------------
+	# End of Email Function
+	#-------------
+	
+	#Applies nl2br to $text, but also makes sure to avoid applying the function to any content within pre tags
+	function nl2brex($text) {
+		$text = nl2br($text);
+		$text = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " ('$1') .  (clean_pre('$2'))  . '</pre>' ", $text);
+		$text = preg_replace('!(<ol.*?>)(.*?)</ol>!ise', " ('$1') .  (clean_pre('$2'))  . '</ol>' ", $text);
+		$text = preg_replace('!(<ul.*?>)(.*?)</ul>!ise', " ('$1') .  (clean_pre('$2'))  . '</ul>' ", $text);
+		$text = preg_replace('!(<dl.*?>)(.*?)</dl>!ise', " ('$1') .  (clean_pre('$2'))  . '</dl>' ", $text);
+		$text = preg_replace('!(\[nobr.*?\])(.*?)\[/nobr\]!ise', " stripslashes('$1') .  stripslashes(clean_pre('$2'))  . '' ", $text);
+		$text = brfix($text);
+		$text = str_ireplace('[nobr]', '', $text);
+		$text = str_ireplace('[/nobr]', '', $text);
+		return $text;
+	}
+	
+	#nl2brex2 for RSS feeds
+	function nl2brex2($text) {
+		$text = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " ('$1') .  (clean_pre('$2'))  . '</pre>' ", $text);
+		$text = preg_replace('!(<ol.*?>)(.*?)</ol>!ise', " ('$1') .  (clean_pre('$2'))  . '</ol>' ", $text);
+		$text = preg_replace('!(<ul.*?>)(.*?)</ul>!ise', " ('$1') .  (clean_pre('$2'))  . '</ul>' ", $text);
+		$text = preg_replace('!(<dl.*?>)(.*?)</dl>!ise', " ('$1') .  (clean_pre('$2'))  . '</dl>' ", $text);
+		$text = preg_replace('!(\[nobr.*?\])(.*?)\[/nobr\]!ise', " stripslashes('$1') .  stripslashes(clean_pre('$2'))  . '' ", $text);
+		$text = brfix($text);
+		$text = str_ireplace('[nobr]', '', $text);
+		$text = str_ireplace('[/nobr]', '', $text);
+		return $text;
+	}
+	
+	# Workaround for the br tag after a closing tag fix
+	function brfix($text){
+		$text = str_ireplace('</dl><br />', '</dl>', $text);
+		$text = str_ireplace('</dd><br />', '</dd>', $text);
+		$text = str_ireplace('</dt><br />', '</dt>', $text);
+		$text = str_ireplace('</ol><br />', '</ol>', $text);
+		$text = str_ireplace('</ul><br />', '</ul>', $text);
+		$text = str_ireplace('</li><br />', '</li>', $text);
+		$text = str_ireplace('</p><br />', '</p>', $text);
+		#$tagstoclean = array('dl', 'dd', 'dt', 'ol', 'ul', 'li', 'p');
+		#for($i = 0; $i <= count($tagstoclean), $i++;){
+		#	$text = str_ireplace('</'.$tagstoclean[$i].'><br />', '</'.$tagstoclean[$i].'>', $text);
+		#}
+		return $text;
+	}
+	
+	// Remove paragraphs and breaks from within any <pre> tags.
+	function clean_pre($text) {
+		$text = str_replace(array("<br />\r\n", "<br />\r", "<br />\n"), "\n", $text);
+		$text = str_replace('<p>', "\n", $text);
+		$text = str_replace('</p>', '', $text);
+		return $text;
+	}
+	
+	
+	function totalpurgehtml($source){
+		$allowedTags='';
+		$source = strip_tags($source, $allowedTags);
+		return preg_replace('/<(.*?)>/ie',
+		"'<'.removeEvilAttributes('\\1').'>'", $source);
+	}
+	
+	# Codify Function
+	# --------------------
+	#
+	# Function Name: Codify
+	# Purpose: Neturalizes text, then checks for custom code inside a string, and translates it into corresponding html
+	#
+	# Variable Uses:
+	#
+	# $text = text to translate into html
+	#
+	# --------------------
+	function Codify($text){
+		$patterns[0] = "|\[b\](.*?)\[/b\]|s";
+		$patterns[1] = "|\[i\](.*?)\[/i\]|s";
+		$patterns[2] = "|\[u\](.*?)\[/u\]|s";
+		$patterns[3] = "|\[center\](.*?)\[/center\]|s";
+		$patterns[4] = "|\[url\](.*?)\[/url\]|s";
+		$patterns[5] = "|\[url=(.*?)\](.*?)\[/url\]|s";
+		$patterns[6] = "|\[img\](http://.*?)\[/img\]|s";
+		$patterns[7] = "|\[img\]([0-9]+)(\.[a-zA-Z0-9]{0,10})\[/img\]|s";
+		$patterns[8] = "|\[code\](.*?)\[/code\]|s";
+		$patterns[10] = "|\[s\](.*?)\[/s\]|s";
+		$replacements[0] = "<b>\$1</b>";
+		$replacements[1] = "<i>\$1</i>";
+		$replacements[2] = "<u>\$1</u>";
+		$replacements[3] = "<center>\$1</center>";
+		$replacements[4] = "<a href=\"\$1\">\$1</a>";
+		$replacements[5] = "<a href=\"\$1\">\$2</a>";
+		$replacements[6] = "<img src=\"\$1\" />";
+		$replacements[7] = "<img src=\"images/\$1\$2\" />";
+		$replacements[8] = "<div style=\"overflow: auto;\" align=center><div id=\"code\"><pre>\$1</pre></div></div>";
+		$replacements[10] = "<strike>\$1</strike>";
+		ksort($patterns);
+		ksort($replacements);
+		$text = preg_replace($patterns, $replacements, $text);
+		$text = nl2brex($text);
+		return $text;
+	}
+	#-------------
+	# End of Codify Function
+	#-------------
+	
+	if(!function_exists('str_ireplace')) {
+		function str_ireplace($search,$replace,$subject) {
+			$search = preg_quote($search, "/");
+			return preg_replace("/".$search."/i", $replace, $subject); 
+		} 
+	}
+
+	function purge($StringToPurge) {
+		$string = str_replace(array("\r\n", "\r", "\n"), "", $StringToPurge);
+		return $string;
+	}
+	
+	function removeEvilTags($source){
+		#$allowedTags='<b><s><u><span><p><i><blockquote><ul><ol><li><br><a><dl><dt><dd>';
+		#$source = strip_tags($source, $allowedTags);
+		#return preg_replace('/<(.*?)>/ie',
+		#"'<'.removeEvilAttributes('\\1').'>'", $source);
+		return $source;
+	}
+
+	$stripAttrib = 'javascript:|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup';
+	function removeEvilAttributes($tagSource) {
+		global $stripAttrib;
+		return stripslashes(preg_replace("/$stripAttrib/i", 'forbidden', $tagSource));
+	}
+	
+	function sanitize($string, $min='', $max=''){
+		return mysql_real_escape_string($string);
+	}
+
+	function CreateSession($id, $ip){
+		if(!FieldVerify('id', 'sessions', $id)){
+			mysql_query("INSERT INTO sessions (id,ipaddress) VALUES ('$id','$ip')") or die("CreateSession Function Error: ".mysql_error());
+		} else {
+			mysql_query("UPDATE sessions SET ipaddress='$ip' WHERE id='$id'") or die("CreateSession Function Error: ".mysql_error());
+		}
+	}
+	
+	function KillSession($id){
+		if(FieldVerify('id', 'sessions', $id)){
+			$sql = "DELETE FROM sessions WHERE id=$id";
+			$sqlresults = mysql_query($sql) or die (mysql_error());
+		}
+	}
+
+	
+	
+	function SwapID($newid, $ip){
+		$origid = GetUserIDFromSession($ip);
+		if(!FieldVerify('ip', 'testers', $ip)){
+			mysql_query("INSERT INTO testers (id,ip) VALUES ('$origid','$ip')") or die("SwapID Function Error: ".mysql_error());
+		} else {
+			mysql_query("UPDATE testers SET id='$origid' WHERE ip='$ip'") or die("SwapID Function Error: ".mysql_error());
+		}
+		KillSession($origid);
+		CreateSession($newid, $ip);
+	}
+	
+	# $table = Target table to access
+	# $field = Field to check in
+	# $data = Data of whatever you're verifying
+	#
+	# --------------------
+		#function FieldVerify($field, $table, $data){
+		
+	function RestoreID($ip){
+		if(FieldVerify('ip', 'testers', $ip)){
+			$fakeid = GetInfo('sessions', 'ipaddress', $ip, 'id');
+			$realid = GetInfo('testers', 'ip', $ip, 'id');
+			$sql = "DELETE FROM testers WHERE id=\"$realid\"";
+			$sqlresults = mysql_query($sql) or die (mysql_error());
+			KillSession($fakeid);
+			CreateSession($realid, $ip);
+		}
+	}
+	
+	function SwapMode($ip){
+		if(FieldVerify('ip', 'testers', $ip)){
+			return true; #Swap Mode is active
+		} else {
+			return false; #Swap mode is not active
+		}
+	}
+	
+	function GetUserIDFromSession($ip){
+		if(FieldVerify("ipaddress", "sessions", $ip)){
+			$ret = GetInfo("sessions", "ipaddress", $ip, "id");
+		} else {
+			return false;
+		}
+		
+		return $ret;
+	}
+	
+	function GetOldData($whoid, $what){
+		$ret = GetInfo('terminated', 'id', $whoid, $what);
+		return $ret;
+	}
+	
+	function CheckBanned($ip, $type){
+		$sql = "SELECT COUNT(*) AS count FROM `banned` WHERE `ip`=\"$ip\" AND `bantype`=\"$type\"";
+
+		$testercount = mysql_query($sql) or die("mysql error in $sql: ".mysql_error());
+		$testercount = mysql_fetch_object($testercount);
+		$testers = $testercount->count;
+
+		if($testers > 0){
+			return true;
+		}
+		return false;
+	}
+		
+	function RecoverUser($id){
+		if(!FieldVerify('id', 'users', $id)){
+			mysql_query("INSERT INTO `users` (id) VALUES ($id)") or die("RecoverUser Function Error: ".mysql_error());
+		}
+		
+		$temp = GetOldData($id, 'username');
+		WriteData($id, 'username', $temp);
+		$temp = GetOldData($id, 'password');
+		WriteData($id, 'password', $temp);
+		$temp = GetOldData($id, 'email');
+		WriteData($id, 'email', $temp);
+		$temp = GetOldData($id, 'levelofaccess');
+		WriteData($id, 'levelofaccess', $temp);
+		$temp = GetOldData($id, 'recruitedby');
+		WriteData($id, 'recruitedby', $temp);
+		$temp = GetOldData($id, 'dateofbirth');
+		WriteData($id, 'dateofbirth', $temp);
+		$temp = GetOldData($id, 'datejoined');
+		WriteData($id, 'datejoined', $temp);
+		$temp = GetOldData($id, 'disciplinehistory');
+		WriteData($id, 'disciplinehistory', $temp);
+		$temp = GetOldData($id, 'division');
+		WriteData($id, 'division', $temp);
+		$temp = GetOldData($id, 'firstname');
+		WriteData($id, 'firstname', $temp);
+		$temp = GetOldData($id, 'lastname');
+		WriteData($id, 'lastname', $temp);
+		$temp = GetOldData($id, 'datejoined');
+		WriteData($id, 'datejoined', $temp);
+		
+		#Verify users db contains recovered information
+		
+		if(!FieldVerify("id", "users", $id)){
+			die('The account could not be recovered due to an error in the Account Recovery function.');
+		}
+		
+		# Account successfully recovered at this point, go ahead and delete the account recovery info from the terminated database.
+		
+		if(FieldVerify("id", "terminated", $id)){
+			$sql = "DELETE FROM `terminated` WHERE id=\"$id\"";
+			$sqlresults = mysql_query($sql) or die (mysql_error());
+		}
+	}
+	
+	
+	function statusimg($status){
+		if($status){
+			return '/images/connected.png';
+		} else {
+			return '/images/disconnected.png';
+		}
+	}
+
+	function checkserver($serverid){
+		if(FieldVerify('id', 'servers', $serverid)){
+				$serverstatus = GetInfo("servers", "id", $serverid, "status");
+				if($serverstatus == 'offline'){
+					return false;
+				} else {
+					return true;
+				}
+		} else {
+			die("No such server.");
+			return false;
+		}
+		return false;
+	}
+	
+	function delslash($text){
+		$text = str_replace("\'", "'", $text);
+		$text = str_replace('\"', '"', $text);
+		return $text;
+	}
+	
+	// This function included is a copy of phpbb_rtrim();
+	function data_rtrim($str, $charlist = false){
+	    if ($charlist === false){
+	        return rtrim($str);
+	    }
+		
+	    $php_version = explode('.', PHP_VERSION);
+
+	    // php version < 4.1.0
+	    if ((int) $php_version[0] < 4 || ((int) $php_version[0] == 4 && (int) $php_version[1] < 1)){
+	        while ($str{strlen($str)-1} == $charlist){
+	            $str = substr($str, 0, strlen($str)-1);
+	        }
+	    } else {
+	        $str = rtrim($str, $charlist);
+	    }
+	    return $str;
+	}
+
+	function CreateUser($username, $email, $ip){
+		if(!FieldVerify('username', 'users', $username)){
+			if(!FieldVerify('username', 'terminated', $username)){
+				$breakout = false;
+				while($breakout == false){
+					$password = createRandomPassword();
+					if(!FieldVerify('password', 'users', md5($password))){	#Done to ensure original password.
+						$breakout = true;
+					}
+				}
+				$enpassword = md5($password);
+				mysql_query("INSERT INTO users (ip, username, password, email) VALUES ('$ip', '$username', '$enpassword', '$email')") or die("CreateUser Function Error: ".mysql_error());
+				$body = "Welcome!
+		
+You've registered as an user of BNETDocs. If this email is in error, simply ignore this email.
+
+Your information is as follows:
+
+Username: $username
+Password: $password
+
+The password was randomly generated for you. You can change your password after logging in.
+
+Simply login at the site to activate your account.
+
+Website: http://www.bnetdocs.org
+
+Once more, welcome!
+
+Regards,
+BNETDocs
+
+---------
+Please do not respond to this email, this email was automatically generated.
+If you have any questions, comments, etc, feel free to contact one of the administrators.
+---------";
+				Email($email, 'postmaster@bnetdocs.org', 'Welcome to BNETDocs!', $body);				
+			} else { #Aha, user was a member before, remove from terminated database and give original id
+				$id = getinfo('terminated', 'username', $username, 'id');
+				$sql = "DELETE FROM terminated WHERE id=\"$id\"";
+				$sqlresults = mysql_query($sql) or die (mysql_error());
+				$breakout = false;
+				while($breakout == false){
+					$password = createRandomPassword();
+					if(!FieldVerify('password', 'users', md5($password))){	#Done to ensure original password.
+						$breakout = true;
+					}
+				}
+				$enpassword = md5($password);
+				mysql_query("INSERT INTO users (id, ip, username, password, email) VALUES ($id, '$ip', '$username', '$enpassword', '$email')") or die("CreateUser Function Error: ".mysql_error());
+				$body = "Welcome Back!
+		
+You've re-registered as an user of BNETDocs. If this email is in error, simply ignore this email.
+
+Your information is as follows:
+
+Username: $username
+Password: $password
+
+The password was randomly generated for you. You can change your password after logging in.
+
+Simply login at the site to re-activate your account. Your personal settings were not saved, so you will need to adjust them as desired. Your comments, news posts, logs related to you were all saved, and all of them has been re-linked to your new account.
+
+Website: http://www.bnetdocs.org
+
+Once more, welcome back!
+
+Regards,
+BNETDocs
+
+---------
+Please do not respond to this email, this email was automatically generated.
+If you have any questions, comments, etc, feel free to contact one of the administrators.
+---------";
+				Email($email, 'postmaster@bnetdocs.org', 'Welcome Back to BNETDocs!', $body);
+				
+				$userid = getinfo('users', 'username', $username, 'id');
+				$event = 'Re-registered as an user of BNETDocs.';
+				$type = 'acctrestore';
+			}
+		}
+	}
+	
+	function ResetPassword($userid){
+		$breakout = false;
+		while($breakout == false){
+			$password = createRandomPassword();
+			if(!FieldVerify('password', 'users', md5($password))){
+				$breakout = true;
+			}
+		}
+		$username = whoisid($userid);
+		$email = GetData($userid, 'email');
+		$enpassword = md5($password);
+		mysql_query("UPDATE users SET password='$enpassword' WHERE id=$userid") or die("ResetPasswrd Function Error: ".mysql_error());
+		$body = "Hello!
+
+You've requested your password to be resetted. It has been resetted for you.
+
+If this email is in error, PLEASE ALERT AN ADMINISTRATOR -- this way we can take appropriate action.
+
+Your information is as follows:
+
+Username: $username
+Password: $password
+
+The password was randomly generated for you. You can change your password after logging in.
+
+Website: http://www.bnetdocs.org
+
+Regards,
+BNETDocs
+---------
+Please do not respond to this email, this email was automatically generated.
+If you have any questions, comments, etc, feel free to contact one of the administrators.
+---------";
+		Email($email, 'postmaster@bnetdocs.org', 'BNETDocs Password Reset', $body);
+		
+		$event = 'Had their password reset and emailed to them.';
+		$type = 'CONFIDENTAL';
+	}
+	
+	#--------------
+	# Warning! If this function is called, it results in deletion of data associated with that user
+	#--------------
+	function DeleteUser($id){
+		
+		# Copy username info to terminated db for stability
+		
+		$username = GetData($id, 'username');
+		mysql_query("INSERT INTO `terminated` (`id`, `username`) VALUES ($id, '" . mysql_real_escape_string($username) . "')") or die("DeleteUser Function Error: ".mysql_error());
+		
+		# Delete User's session if it exists
+		
+		if(FieldVerify("id", "sessions", $id)){
+			KillSession($id);
+		}
+		
+		# Delete from users DB if it exists
+		
+		if(FieldVerify("id", "users", $id)){
+			$sql = "DELETE FROM users WHERE id=$id";
+			$sqlresults = mysql_query($sql) or die (mysql_error());
+		}
+	}
+	
+	if(version_compare(PHP_VERSION, '5.3.0') < 0) {
+		function lcfirst($str) {
+			return strtolower(substr($str, 0, 1)) . substr($str, 1);
+		}
+	}
+
+	function rank($id){
+	   	$rank = GetData($id,'levelofaccess');
+	   	return $rank;
+	}
+
+	function rankname($rank){
+		$info = mysql_query("SELECT groupname FROM `membergroup` WHERE `id` ='".$rank."'")  or die("Rank Name Function Error: ".mysql_error());
+		$rank = mysql_result($info,0,"groupname");
+		return $rank;
+	}
+	
+	#known types: session
+	function logthis($userid, $event, $type){
+		$event = sanitize($event);
+		$datetime = date("l, F d Y");
+		$ip = $_SERVER['REMOTE_ADDR'];
+		echo json_encode(array('userid'=>$userid,'event'=>$event,'type'=>$type,'datetime'=>$datetime,'ip'=>$ip));return;
+		mysql_query("INSERT INTO logs (user,event,eventtype, datetime,ip) VALUES ('$userid','$event','$type','$datetime','$ip')") or die("Logthis Function Error: ".mysql_error());
+	}
+
+	function curPageURL() {
+		$pageURL = 'http';
+		if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
+		$pageURL .= "://";
+		if ($_SERVER["SERVER_PORT"] != "80") {
+		$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
+		} else {
+		$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
+		}
+		return $pageURL;
+	}
+	
+	
+
+	function whoisid($idtocheck){
+		#Return name associated with identification number
+		#Parameter: ID
+
+		if($idtocheck != "all"){
+			if($idtocheck == '-1') return 'WEBSITE:';
+			if($idtocheck == 0) return 'UNKNOWN:';
+			if(FieldVerify("id", "users", $idtocheck)){
+				$ret = getinfo('users', 'id', $idtocheck, 'username');
+			} else {
+				$ret = getinfo('terminated', 'id', $idtocheck, 'username');
+			}
+		} else {
+			$ret = "all";
+		}
+		return $ret;
+	}
+	
+	#catchall, will have some unintended casualities. until a deal is reached with blizzard, do not disengage.
+	function isblizzard($ip){
+		$range = substr($ip, 0, stripos($ip, '.', (stripos($ip, '.') + 1)));
+		switch ($range) {
+			case '63.241':
+			case '63.240':
+			case '211.233':
+			case '213.248':
+			case '216.148':
+			case '12.129':
+			case '216.148':
+				$ret = true;
+				break;
+			default:
+			    $ret = false;
+		}
+		return $ret;
+	}
+
+	function getid($idtoget){
+		#Return identification number associated with name
+		#Parameter: Name
+		$queryid = "SELECT * FROM users WHERE username = \"$idtoget\"";
+		if($idtoget != "all"){
+			$identification = mysql_query($queryid);
+			$ret = mysql_result($identification,0,"id");
+		} else {
+			$ret = "all";
+		}
+		return $ret;
+	}
+
+	function getpacketlink($id){
+		#Return name of packet associated with id
+		#Parameter: id
+		$queryid = "SELECT * FROM packets WHERE id=$id";
+		$identification = mysql_query($queryid);
+		$messageid = mysql_result($identification,0,"messageid");
+		$messagename = mysql_result($identification,0,"messagename");
+		$ret = '<a href="/?op=packet&pid='.$id.'">('.$messageid.') '.$messagename.'</a>';
+		return $ret;
+	}
+	
+	function getdocumentlink($id){
+		#Return name of packet associated with id
+		#Parameter: id
+		$queryid = "SELECT * FROM documents WHERE id=$id";
+		$identification = mysql_query($queryid);
+		$title = mysql_result($identification,0,"title");
+		$ret = '<a href="/?op=doc&did='.$id.'">'.$title.'</a>';
+		return $ret;
+	}
+	
+	function days($thedate){
+		$days=(strtotime(date('m/d/y')))-(strtotime($thedate));
+		$days=ceil($days/86400);
+		return $days;
+	}
+	
+	# String comparsion function
+	# ------------------------------------
+	# $firststring 				Should be obvious what this is for
+	# $secondstring			Again, should be obvious
+	#
+	# This function will compare two strings, and return the difference, with | as the separator between the first and second strings.
+	# 
+	# Example:
+	#
+	# $firststring = "This is the first string.";
+	# $secondstring = "This is the second string.";
+	# $i = GetStrDiff($firststring, $secondstring);
+	# $a = split($i, '|');
+	# $final = $a[0].' was changed to '.$a[1];
+	# echo "First string: $firststring<br>";
+	# echo "Second string: $secondstring<br>";
+	# echo "Differences: $final";
+	#
+	# Output: 
+	#	This is the first string.
+	#	This is the second string.
+	#	Differences: first was changed to second
+	#
+	function GetStrDiff($firststring, $secondstring){
+		# Warning, this function is still under development.
+		$results = false;
+		return $results;
+	}
+?>
diff --git a/functions.php b/functions.php
new file mode 100644
index 00000000..e6781ca6
--- /dev/null
+++ b/functions.php
@@ -0,0 +1,1050 @@
+<?
+	########################
+	# Core Functions Script
+	########################
+
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth;
+	if($auth != 'true') die('<html><head><title>BNETDocs: Redux</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+	
+	# DisplayDialogBox Function
+	# --------------------
+	#
+	# Function Name: DisplayDialogBox
+	# Purpose: Figure it out.
+	# Variable Uses:
+	#
+	# $text = The text to display as contents of the dialog box; Required; String.
+	# $poster = The poster of who posted dialog; Optional; String.
+	# $title = The title of the dialog box; Optional; String.
+	# $insdate = Inserts date automatically; Optional; Boolean.
+	# $file = Determines whether $text is treated as an include file; Optional; Boolean.
+	#
+	# --------------------
+		function DisplayDialogBox($text, $title='none', $file=false, $align='left'){
+			include 'bdif/dialogbox.dm';
+		}
+	#-------------
+	# End of DisplayDialogBox Function
+	#-------------
+
+
+
+	# DisplayNavBox Function
+	# --------------------
+	#
+	# Function Name: DisplayNavBox
+	# Purpose: Figure it out.
+	# Variable Uses:
+	#
+	# $text = The text to display as contents of the nav box; Required; String.
+	# $title = The title of the dialog box; Optional; String.
+	# $file = Determines whether $text is treated as an include file; Optional; Boolean.
+	#
+	# --------------------
+		function DisplayNavBox($text, $title="none", $file=false){
+			$auth = true;
+			$username = $_SESSION['username'];
+			include 'dmti/navbox.dm';
+		}
+	#-------------
+	# End of DisplayNavBox Function
+	#-------------
+
+	function getdir($dir, $no_dots=TRUE, $no_dirs=TRUE) {
+		$files = array();
+		$dh  = @opendir($dir);
+		if ($dh!=FALSE) {
+			while (false !== ($filename = readdir($dh))) {
+				$files[] = $filename;
+			}
+		
+			if ($no_dots) {
+				while(($ix = array_search('.',$files)) > -1) unset($files[$ix]);
+				while(($ix = array_search('..',$files)) > -1) unset($files[$ix]);
+				$li=0;
+				while($li <= count($files)){
+					$first = $str{0};
+					if($files[$li]{0}=='.') unset($files[$li]);
+					if($files[$li]{0}.$files[$li]{1}=='..') unset($files[$li]);
+					$li++;
+				}
+
+			}
+
+			if ($no_dirs) {
+				$li=0;
+				while($li <= count($files)){
+					if(is_dir($files[$li])) unset($files[$li]);
+					$li++;
+				}
+			}
+			$li=0;
+			while($li <= count($files)){
+				if(trim($files[$li])=='') unset($files[$li]);
+				$li++;
+			}
+
+			sort($files);
+		}
+	
+		return $files;
+	}
+
+	function MsgBox($message){
+		if(!$message) $message='Error: $message variable is empty.';
+		echo '
+			<SCRIPT LANGUAGE="javascript">
+			<!--
+				function MYALERT() {
+					alert("'.$message.'");
+				} 
+				MYALERT() 
+			<!-- END -->
+			</SCRIPT>';
+	}
+	function createRandomPassword() {
+	
+	    $chars = "abcdefghijkmnopqrstuvwxyz023456789";
+	    srand((double)microtime()*1000000);
+	    $i = 0;
+	    $pass = '' ;
+	
+	    while ($i <= 7) {
+	        $num = rand() % 33;
+	        $tmp = substr($chars, $num, 1);
+	        $pass = $pass . $tmp;
+	        $i++;
+	    }
+	
+	    return $pass;
+	
+	}
+
+	# Login Function
+	# --------------------
+	#
+	# Function Name: login
+	# Variable Uses:
+	#
+	# $username = member user name
+	# $password = member's password
+	# $tracked = determines if login is logged.
+	#
+	# --------------------
+		function login($username, $password, $tracked=true, $ip) {
+
+			# Set up pass variable
+			#-------------
+		
+				$ret = "pass";
+			
+			# Make sure we have data for user name and pw, if not, error out.
+			#-------------
+
+				if((!$username) || (!$password)){
+					$ret = "Missing login information.";
+				}
+
+			# Check database to verify login info
+			#-------------
+
+			if(FieldVerify("username", "users", $username)){
+				$userid = GetInfo("users", "username", $username, "id");
+				$pwtocheck = md5($password);
+				$password = GetInfo("users", "id", $userid, "password");
+			} else {
+				$ret = "You're not a registered user of BNETDocs: Redux.";
+			}
+
+			if($ret != "pass"){
+				return $ret;
+			}
+			
+			if($pwtocheck == $password){
+
+				# Login has been verified, get basic info from DB on member.
+				#-------------
+
+					$username = GetInfo("users", "id", $userid, "username");
+
+				# If tracking is enabled, log IP and login time/date.
+				#-------------
+
+					$ip = $_SERVER["REMOTE_ADDR"];
+					$sql = "UPDATE users SET ip=\"$ip\" WHERE username=\"$username\"";
+					if($tracked == true) $sqlresults = mysql_query($sql) or die (mysql_error());
+					if($tracked == true) mysql_query("UPDATE users SET last_login=now() WHERE username='$username'");
+
+				# Set up session for member
+				#-------------
+
+					CreateSession($userid, $ip);
+
+				#-------------
+				# Done setting up session
+				#-------------
+
+			} else {
+
+				# Invalid login info. Error out.
+				#-------------
+
+				$ret = "<br /><center>Invalid Login!</center>";
+			}
+			
+			return $ret;
+		}
+	#-------------
+	# End of Login Function
+	#-------------
+
+	function error($message){
+		DisplayDialogBox('<br><br><br><br><br><br><br><center><font size=5>'.$message.'</font></center><br><br><br><br><br><br><br>', '<font size=3><center>Error</center></font>');
+	}
+	
+	# FieldVerify Function
+	# --------------------
+	#
+	# Function Name: FieldVerify
+	# Purpose: Checks to see if a given field containing specified data exists
+	# Variable Uses:
+	#
+	# $table = Target table to access
+	# $field = Field to check in
+	# $data = Data of whatever you're verifying
+	#
+	# --------------------
+		function FieldVerify($field, $table, $data){
+			
+			$sql = "SELECT COUNT(*) AS count FROM `$table` WHERE `$field`=\"$data\"";
+
+			$testercount = mysql_query($sql) or die("mysql error in $sql: ".mysql_error());
+			$testercount = mysql_fetch_object($testercount);
+			$testers = $testercount->count;
+			
+			if($testers > 0){
+				return true;
+			}
+			return false;
+		}
+	#-------------
+	# End of FieldVerify Function
+	#-------------
+
+	
+	# Sector Security Function
+	# --------------------
+	#
+	# Function Name: Secure
+	# Variable Uses: None.
+	#
+	# --------------------
+		function secure($ip) {
+
+			# Check to see if session exists.
+			#-------------
+			
+			if(!FieldVerify("ipaddress", "sessions", $ip)){
+				Redirect("/?op=login");
+			}
+			
+			# Update Activity
+			#------------
+			
+			$userid = GetInfo("sessions", "ipaddress", $ip, "id");
+			mysql_query("UPDATE users SET last_login=now() WHERE id='$userid'");
+		}
+
+	#-------------
+	# End of Sector Security Function
+	#-------------
+
+
+
+	# GetData Function
+	# --------------------
+	#
+	# Function Name: GetData
+	# Purpose: Makes it easier to obtain a member's info.
+	# Variable Uses:
+	#
+	# $whoid = target member for info request
+	# $what = which field data to pull up
+	#
+	# --------------------
+		function GetData($whoid, $what){
+			$ret = GetInfo("users", "id", $whoid, $what);
+			return $ret;
+		}
+	#-------------
+	# End of GetData Function
+	#-------------
+
+	# WriteData Function
+	# --------------------
+	#
+	# Function Name: WriteData
+	# Purpose: Makes it easier to update a member's info.
+	# Variable Uses:
+	#
+	# $whoid = target member for info update
+	# $what = which field data to modify (field *MUST* exist)
+	#$data = the data to write
+	#
+	# --------------------
+		function WriteData($whoid, $what, $data){
+			$ret = true;
+			$sql = "UPDATE users SET `$what`=\"$data\" WHERE id=$whoid"; 
+			$sqlresults = mysql_query($sql) or $ret = false;
+			return $ret;
+		}
+	#-------------
+	# End of WriteData Function
+	#-------------
+	
+	
+	function Discipline($target, $action, $ip=''){
+		if($action == 'lp'){
+			$sql = "UPDATE discipline SET profile=0 WHERE account=$target";
+			$sqlresults = mysql_query($sql) or die(mysql_error());
+		} else if($action == 'up'){
+			$sql = "UPDATE discipline SET profile=1 WHERE account=$target";
+			$sqlresults = mysql_query($sql) or die(mysql_error());
+		} else if($action == 'fa'){
+			$sql = "UPDATE discipline SET frozen=1 WHERE account=$target";
+			$sqlresults = mysql_query($sql) or die(mysql_error());
+		} else if($action == 'ufa'){
+			$sql = "UPDATE discipline SET frozen=0 WHERE account=$target";
+			$sqlresults = mysql_query($sql) or die(mysql_error());
+		} else if($action == 'ipban'){
+			$sql = "UPDATE discipline SET ipban=1 WHERE account=$target";
+			$sqlresults = mysql_query($sql) or die(mysql_error());
+			$currentip = GetData($target, 'ip');
+			mysql_query("INSERT INTO `banned` (id, ip, bantype) VALUES ($target, '$ip', 'total')") or die("Discipline Function Error: ".mysql_error());
+		} else if($action == 'unipban'){
+			$sql = "UPDATE discipline SET ipban=0 WHERE account=$target";
+			$sqlresults = mysql_query($sql) or die(mysql_error());
+			$sql = "DELETE FROM banned WHERE id=\"$target\"";
+			$sqlresults = mysql_query($sql) or die (mysql_error());
+		}
+	}
+	
+	function BlockHack(){
+		die('<center><br><br><b><font color=red>Unauthorized access blocked. Nice try, buddy.</font></b><br><br></center>');
+	}
+	
+	# GetInfo Function
+	# --------------------
+	#
+	# Function Name: GetInfo
+	# Purpose: Offers specialized information by specifying data request
+	# Variable Uses:
+	#
+	# $db = Target database to access
+	# $index = Field to correlate $id from.
+	# $id = ID/ACCOUNT/USERNAME of whatever you're accessing
+	# $data = The field where you want to obtain the data from.
+	# --------------------
+		function GetInfo($db, $index, $id, $data){
+			$sqlquery = mysql_query("SELECT * FROM `$db` WHERE `$index`=\"$id\" LIMIT 1") or die('Attempted Query: '."SELECT * FROM `$db` WHERE `$index`='$id' LIMIT 1"."<br>GetInfo Function Error: ".mysql_error());;
+			if(mysql_num_rows($sqlquery) > 0) {
+				$ret = mysql_result($sqlquery,0,$data);
+			} else {
+				$ret = false;
+			}
+			return $ret;
+		}
+	#-------------
+	# End of GetInfo Function
+	#-------------
+
+	# WriteInfo Function
+	# --------------------
+	#
+	# Function Name: WriteInfo
+	# Purpose: Writes specialized information by specifying data request to existing field
+	# Variable Uses:
+	#
+	# $db = Target database to access
+	# $index = Field to correlate $id from.
+	# $id = ID/ACCOUNT/USERNAME of whatever you're accessing
+	# $field = The field where you want to write the data to.
+	#$data = the data you'd like to have written
+	# Example: WriteInfo('messages', 'id', $id, 'opened', 1);
+	# --------------------
+		function WriteInfo($db, $index, $id, $field, $data){
+			$ret = true;
+			$sql = "UPDATE `$db` SET `$field`=\"$data\" WHERE $index=$id"; 
+			$sqlresults = mysql_query($sql) or $ret = false;
+			return $ret;
+		}
+	#-------------
+	# End of GetInfo Function
+	#-------------
+
+	# URLButton Function
+	# --------------------
+	#
+	# Function Name: URLButton
+	# Purpose: A form button acts as a hyperlink
+	# Variable Uses:
+	#
+	# $text = Text to display on button
+	# $url = Target address to send to when clicked
+	#
+	# --------------------
+		function URLButton($text,$url){
+			?><form><input id="abutton" style="width:125;height:23" type=button value="<? echo $text ?>" onClick="gourl('<? echo $url ?>')"></form><?
+		}
+	#-------------
+	# End of URLButton Function
+	#-------------
+
+
+	# Redirect Function
+	# --------------------
+	#
+	# Function Name: Redirect
+	# Purpose: Redirects user to target page
+	# Variable Uses:
+	#
+	# $page = Target page to redirect to
+	#
+	# --------------------
+		function Redirect($page){
+			echo "<meta http-equiv=\"refresh\" content=\"0;url=$page\"><body bgcolor=black>";
+			die();
+		}
+	#-------------
+	# End of Redirect Function
+	#-------------
+	
+	if (!function_exists("stripos")) {
+	  function stripos($str,$needle,$offset=0)
+	  {
+	      return strpos(strtolower($str),strtolower($needle),$offset);
+	  }
+	}
+
+	# Email Function
+	# --------------------
+	#
+	# Function Name: Email
+	# Purpose: Send emails
+	# Variable Uses:
+	#
+	# $target = email address to send the email to
+	# $fromwho = return address
+	# $subject = obvious...
+	# $body = obvious...
+	#
+	# --------------------
+		function Email($target, $fromwho, $subject, $body){
+			$headers = "From: BNETDocs<$fromwho>\r\n";
+			mail($target, $subject, $body, $headers);
+		}
+	#-------------
+	# End of Email Function
+	#-------------
+	
+	#Applies nl2br to $text, but also makes sure to avoid applying the function to any content within pre tags
+	function nl2brex($text) {
+		$text = nl2br($text);
+		$text = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " ('$1') .  (clean_pre('$2'))  . '</pre>' ", $text);
+		$text = preg_replace('!(<ol.*?>)(.*?)</ol>!ise', " ('$1') .  (clean_pre('$2'))  . '</ol>' ", $text);
+		$text = preg_replace('!(<ul.*?>)(.*?)</ul>!ise', " ('$1') .  (clean_pre('$2'))  . '</ul>' ", $text);
+		$text = preg_replace('!(<dl.*?>)(.*?)</dl>!ise', " ('$1') .  (clean_pre('$2'))  . '</dl>' ", $text);
+		$text = preg_replace('!(\[nobr.*?\])(.*?)\[/nobr\]!ise', " stripslashes('$1') .  stripslashes(clean_pre('$2'))  . '' ", $text);
+		$text = brfix($text);
+		$text = str_ireplace('[nobr]', '', $text);
+		$text = str_ireplace('[/nobr]', '', $text);
+		return $text;
+	}
+	
+	#nl2brex2 for RSS feeds
+	function nl2brex2($text) {
+		$text = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " ('$1') .  (clean_pre('$2'))  . '</pre>' ", $text);
+		$text = preg_replace('!(<ol.*?>)(.*?)</ol>!ise', " ('$1') .  (clean_pre('$2'))  . '</ol>' ", $text);
+		$text = preg_replace('!(<ul.*?>)(.*?)</ul>!ise', " ('$1') .  (clean_pre('$2'))  . '</ul>' ", $text);
+		$text = preg_replace('!(<dl.*?>)(.*?)</dl>!ise', " ('$1') .  (clean_pre('$2'))  . '</dl>' ", $text);
+		$text = preg_replace('!(\[nobr.*?\])(.*?)\[/nobr\]!ise', " stripslashes('$1') .  stripslashes(clean_pre('$2'))  . '' ", $text);
+		$text = brfix($text);
+		$text = str_ireplace('[nobr]', '', $text);
+		$text = str_ireplace('[/nobr]', '', $text);
+		return $text;
+	}
+	
+	# Workaround for the br tag after a closing tag fix
+	function brfix($text){
+		$text = str_ireplace('</dl><br />', '</dl>', $text);
+		$text = str_ireplace('</dd><br />', '</dd>', $text);
+		$text = str_ireplace('</dt><br />', '</dt>', $text);
+		$text = str_ireplace('</ol><br />', '</ol>', $text);
+		$text = str_ireplace('</ul><br />', '</ul>', $text);
+		$text = str_ireplace('</li><br />', '</li>', $text);
+		$text = str_ireplace('</p><br />', '</p>', $text);
+		#$tagstoclean = array('dl', 'dd', 'dt', 'ol', 'ul', 'li', 'p');
+		#for($i = 0; $i <= count($tagstoclean), $i++;){
+		#	$text = str_ireplace('</'.$tagstoclean[$i].'><br />', '</'.$tagstoclean[$i].'>', $text);
+		#}
+		return $text;
+	}
+	
+	// Remove paragraphs and breaks from within any <pre> tags.
+	function clean_pre($text) {
+		$text = str_replace(array("<br />\r\n", "<br />\r", "<br />\n"), "\n", $text);
+		$text = str_replace('<p>', "\n", $text);
+		$text = str_replace('</p>', '', $text);
+		return $text;
+	}
+	
+	function totalpurgehtml($source){
+		$allowedTags='';
+		$source = strip_tags($source, $allowedTags);
+		return preg_replace('/<(.*?)>/ie',
+		"'<'.removeEvilAttributes('\\1').'>'", $source);
+	}
+	
+	# Codify Function
+	# --------------------
+	#
+	# Function Name: Codify
+	# Purpose: Neturalizes text, then checks for custom code inside a string, and translates it into corresponding html
+	#
+	# Variable Uses:
+	#
+	# $text = text to translate into html
+	#
+	# --------------------
+	function Codify($text){
+		$patterns[0] = "|\[b\](.*?)\[/b\]|s";
+		$patterns[1] = "|\[i\](.*?)\[/i\]|s";
+		$patterns[2] = "|\[u\](.*?)\[/u\]|s";
+		$patterns[3] = "|\[center\](.*?)\[/center\]|s";
+		$patterns[4] = "|\[url\](.*?)\[/url\]|s";
+		$patterns[5] = "|\[url=(.*?)\](.*?)\[/url\]|s";
+		$patterns[6] = "|\[img\](http://.*?)\[/img\]|s";
+		$patterns[7] = "|\[img\]([0-9]+)(\.[a-zA-Z0-9]{0,10})\[/img\]|s";
+		$patterns[8] = "|\[code\](.*?)\[/code\]|s";
+		$patterns[10] = "|\[s\](.*?)\[/s\]|s";
+		$replacements[0] = "<b>\$1</b>";
+		$replacements[1] = "<i>\$1</i>";
+		$replacements[2] = "<u>\$1</u>";
+		$replacements[3] = "<center>\$1</center>";
+		$replacements[4] = "<a href=\"\$1\">\$1</a>";
+		$replacements[5] = "<a href=\"\$1\">\$2</a>";
+		$replacements[6] = "<img src=\"\$1\" />";
+		$replacements[7] = "<img src=\"images/\$1\$2\" />";
+		$replacements[8] = "<div style=\"overflow: auto;\" align=center><div id=\"code\"><pre>\$1</pre></div></div>";
+		$replacements[10] = "<strike>\$1</strike>";
+		ksort($patterns);
+		ksort($replacements);
+		$text = preg_replace($patterns, $replacements, $text);
+		$text = nl2brex($text);
+		return $text;
+	}
+	#-------------
+	# End of Codify Function
+	#-------------
+	
+	if(!function_exists('str_ireplace')) {
+		function str_ireplace($search,$replace,$subject) {
+			$search = preg_quote($search, "/");
+			return preg_replace("/".$search."/i", $replace, $subject); 
+		} 
+	}
+
+	function purge($StringToPurge) {
+		$string = str_replace(array("\r\n", "\r", "\n"), "", $StringToPurge);
+		return $string;
+	}
+	
+	function removeEvilTags($source){
+		#$allowedTags='<b><s><u><span><p><i><blockquote><ul><ol><li><br><a><dl><dt><dd>';
+		#$source = strip_tags($source, $allowedTags);
+		#return preg_replace('/<(.*?)>/ie',
+		#"'<'.removeEvilAttributes('\\1').'>'", $source);
+		return $source;
+	}
+
+	$stripAttrib = 'javascript:|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup';
+
+
+	function removeEvilAttributes($tagSource) {
+
+		global $stripAttrib;
+		return stripslashes(preg_replace("/$stripAttrib/i", 'forbidden', $tagSource));
+	}
+	
+	function sanitize($string, $min='', $max=''){
+		return mysql_real_escape_string($string);
+	}
+
+	function CreateSession($id, $ip){
+		if(!FieldVerify('id', 'sessions', $id)){
+			mysql_query("INSERT INTO sessions (id,ipaddress) VALUES ('$id','$ip')") or die("CreateSession Function Error: ".mysql_error());
+		} else {
+			mysql_query("UPDATE sessions SET ipaddress='$ip' WHERE id='$id'") or die("CreateSession Function Error: ".mysql_error());
+		}
+	}
+	
+	function KillSession($id){
+		if(FieldVerify('id', 'sessions', $id)){
+			$sql = "DELETE FROM sessions WHERE id=$id";
+			$sqlresults = mysql_query($sql) or die (mysql_error());
+		}
+	}
+	
+	function SwapID($newid, $ip){
+		$origid = GetUserIDFromSession($ip);
+		if(!FieldVerify('ip', 'testers', $ip)){
+			mysql_query("INSERT INTO testers (id,ip) VALUES ('$origid','$ip')") or die("SwapID Function Error: ".mysql_error());
+		} else {
+			mysql_query("UPDATE testers SET id='$origid' WHERE ip='$ip'") or die("SwapID Function Error: ".mysql_error());
+		}
+		KillSession($origid);
+		CreateSession($newid, $ip);
+	}
+	
+	# $table = Target table to access
+	# $field = Field to check in
+	# $data = Data of whatever you're verifying
+	#
+	# --------------------
+		#function FieldVerify($field, $table, $data){
+		
+	function RestoreID($ip){
+		if(FieldVerify('ip', 'testers', $ip)){
+			$fakeid = GetInfo('sessions', 'ipaddress', $ip, 'id');
+			$realid = GetInfo('testers', 'ip', $ip, 'id');
+			$sql = "DELETE FROM testers WHERE id=\"$realid\"";
+			$sqlresults = mysql_query($sql) or die (mysql_error());
+			KillSession($fakeid);
+			CreateSession($realid, $ip);
+		}
+	}
+	
+	function SwapMode($ip){
+		if(FieldVerify('ip', 'testers', $ip)){
+			return true; #Swap Mode is active
+		} else {
+			return false; #Swap mode is not active
+		}
+	}
+	
+	function GetUserIDFromSession($ip){
+		if(FieldVerify("ipaddress", "sessions", $ip)){
+			$ret = GetInfo("sessions", "ipaddress", $ip, "id");
+		} else {
+			return false;
+		}
+		
+		return $ret;
+	}
+	
+	function GetOldData($whoid, $what){
+		$ret = GetInfo('terminated', 'id', $whoid, $what);
+		return $ret;
+	}
+	
+	function CheckBanned($ip, $type){
+		$sql = "SELECT COUNT(*) AS count FROM `banned` WHERE `ip`=\"$ip\" AND `bantype`=\"$type\"";
+
+		$testercount = mysql_query($sql) or die("mysql error in $sql: ".mysql_error());
+		$testercount = mysql_fetch_object($testercount);
+		$testers = $testercount->count;
+
+		if($testers > 0){
+			return true;
+		}
+		return false;
+	}
+		
+	function RecoverUser($id){
+		if(!FieldVerify('id', 'users', $id)){
+			mysql_query("INSERT INTO `users` (id) VALUES ($id)") or die("RecoverUser Function Error: ".mysql_error());
+		}
+		
+		$temp = GetOldData($id, 'username');
+		WriteData($id, 'username', $temp);
+		$temp = GetOldData($id, 'password');
+		WriteData($id, 'password', $temp);
+		$temp = GetOldData($id, 'email');
+		WriteData($id, 'email', $temp);
+		$temp = GetOldData($id, 'levelofaccess');
+		WriteData($id, 'levelofaccess', $temp);
+		$temp = GetOldData($id, 'recruitedby');
+		WriteData($id, 'recruitedby', $temp);
+		$temp = GetOldData($id, 'dateofbirth');
+		WriteData($id, 'dateofbirth', $temp);
+		$temp = GetOldData($id, 'datejoined');
+		WriteData($id, 'datejoined', $temp);
+		$temp = GetOldData($id, 'disciplinehistory');
+		WriteData($id, 'disciplinehistory', $temp);
+		$temp = GetOldData($id, 'division');
+		WriteData($id, 'division', $temp);
+		$temp = GetOldData($id, 'firstname');
+		WriteData($id, 'firstname', $temp);
+		$temp = GetOldData($id, 'lastname');
+		WriteData($id, 'lastname', $temp);
+		$temp = GetOldData($id, 'datejoined');
+		WriteData($id, 'datejoined', $temp);
+		
+		#Verify users db contains recovered information
+		
+		if(!FieldVerify("id", "users", $id)){
+			die('The account could not be recovered due to an error in the Account Recovery function.');
+		}
+		
+		# Account successfully recovered at this point, go ahead and delete the account recovery info from the terminated database.
+		
+		if(FieldVerify("id", "terminated", $id)){
+			$sql = "DELETE FROM `terminated` WHERE id=\"$id\"";
+			$sqlresults = mysql_query($sql) or die (mysql_error());
+		}
+	}
+	
+	function statusimg($status){
+		if($status){
+			return '/images/connected.png';
+		} else {
+			return '/images/disconnected.png';
+		}
+	}
+
+	function checkserver($serverid){
+		if(FieldVerify('id', 'servers', $serverid)){
+				$serverstatus = GetInfo("servers", "id", $serverid, "status");
+				if($serverstatus == 'offline'){
+					return false;
+				} else {
+					return true;
+				}
+		} else {
+			die("No such server.");
+			return false;
+		}
+		return false;
+	}
+	
+	function delslash($text){
+		$text = str_replace("\'", "'", $text);
+		$text = str_replace('\"', '"', $text);
+		return $text;
+	}
+	
+	// This function included is a copy of phpbb_rtrim();
+	function data_rtrim($str, $charlist = false){
+	    if ($charlist === false){
+	        return rtrim($str);
+	    }
+		
+	    $php_version = explode('.', PHP_VERSION);
+
+	    // php version < 4.1.0
+	    if ((int) $php_version[0] < 4 || ((int) $php_version[0] == 4 && (int) $php_version[1] < 1)){
+	        while ($str{strlen($str)-1} == $charlist){
+	            $str = substr($str, 0, strlen($str)-1);
+	        }
+	    } else {
+	        $str = rtrim($str, $charlist);
+	    }
+	    return $str;
+	}
+
+	function CreateUser($username, $email, $ip){
+		if(!FieldVerify('username', 'users', $username)){
+			if(!FieldVerify('username', 'terminated', $username)){
+				$breakout = false;
+				while($breakout == false){
+					$password = createRandomPassword();
+					if(!FieldVerify('password', 'users', md5($password))){	#Done to ensure original password.
+						$breakout = true;
+					}
+				}
+				$enpassword = md5($password);
+				mysql_query("INSERT INTO users (ip, username, password, email) VALUES ('$ip', '$username', '$enpassword', '$email')") or die("CreateUser Function Error: ".mysql_error());
+				$body = "Welcome!
+		
+You've registered as an user of BNETDocs. If this email is in error, simply ignore this email.
+
+Your information is as follows:
+
+Username: $username
+Password: $password
+
+The password was randomly generated for you. You can change your password after logging in.
+
+Simply login at the site to activate your account.
+
+Website: http://www.bnetdocs.org
+
+Once more, welcome!
+
+Regards,
+BNETDocs
+
+---------
+Please do not respond to this email, this email was automatically generated.
+If you have any questions, comments, etc, feel free to contact one of the administrators.
+---------";
+				Email($email, 'postmaster@bnetdocs.org', 'Welcome to BNETDocs!', $body);				
+			} else { #Aha, user was a member before, remove from terminated database and give original id
+				$id = getinfo('terminated', 'username', $username, 'id');
+				$sql = "DELETE FROM terminated WHERE id=\"$id\"";
+				$sqlresults = mysql_query($sql) or die (mysql_error());
+				$breakout = false;
+				while($breakout == false){
+					$password = createRandomPassword();
+					if(!FieldVerify('password', 'users', md5($password))){	#Done to ensure original password.
+						$breakout = true;
+					}
+				}
+				$enpassword = md5($password);
+				mysql_query("INSERT INTO users (id, ip, username, password, email) VALUES ($id, '$ip', '$username', '$enpassword', '$email')") or die("CreateUser Function Error: ".mysql_error());
+				$body = "Welcome Back!
+		
+You've re-registered as an user of BNETDocs. If this email is in error, simply ignore this email.
+
+Your information is as follows:
+
+Username: $username
+Password: $password
+
+The password was randomly generated for you. You can change your password after logging in.
+
+Simply login at the site to re-activate your account. Your personal settings were not saved, so you will need to adjust them as desired. Your comments, news posts, logs related to you were all saved, and all of them has been re-linked to your new account.
+
+Website: http://www.bnetdocs.org
+
+Once more, welcome back!
+
+Regards,
+BNETDocs
+
+---------
+Please do not respond to this email, this email was automatically generated.
+If you have any questions, comments, etc, feel free to contact one of the administrators.
+---------";
+				Email($email, 'postmaster@bnetdocs.org', 'Welcome Back to BNETDocs!', $body);
+				
+				$userid = getinfo('users', 'username', $username, 'id');
+				$event = 'Re-registered as an user of BNETDocs.';
+				$type = 'acctrestore';
+			}
+		}
+	}
+	
+	function ResetPassword($userid){
+		$breakout = false;
+		while($breakout == false){
+			$password = createRandomPassword();
+			if(!FieldVerify('password', 'users', md5($password))){
+				$breakout = true;
+			}
+		}
+		$username = whoisid($userid);
+		$email = GetData($userid, 'email');
+		$enpassword = md5($password);
+		mysql_query("UPDATE users SET password='$enpassword' WHERE id=$userid") or die("ResetPasswrd Function Error: ".mysql_error());
+		$body = "Hello!
+
+You've requested your password to be resetted. It has been resetted for you.
+
+If this email is in error, PLEASE ALERT AN ADMINISTRATOR -- this way we can take appropriate action.
+
+Your information is as follows:
+
+Username: $username
+Password: $password
+
+The password was randomly generated for you. You can change your password after logging in.
+
+Website: http://www.bnetdocs.org
+
+Regards,
+BNETDocs
+---------
+Please do not respond to this email, this email was automatically generated.
+If you have any questions, comments, etc, feel free to contact one of the administrators.
+---------";
+		Email($email, 'postmaster@bnetdocs.org', 'BNETDocs Password Reset', $body);
+		
+		$event = 'Had their password reset and emailed to them.';
+		$type = 'CONFIDENTAL';
+	}
+	
+	#--------------
+	# Warning! If this function is called, it results in deletion of data associated with that user
+	#--------------
+	function DeleteUser($id){
+		
+		# Copy username info to terminated db for stability
+		
+		$username = GetData($id, 'username');
+		mysql_query("INSERT INTO `terminated` (`id`, `username`) VALUES ($id, '" . mysql_real_escape_string($username) . "')") or die("DeleteUser Function Error: ".mysql_error());
+		
+		# Delete User's session if it exists
+		
+		if(FieldVerify("id", "sessions", $id)){
+			KillSession($id);
+		}
+		
+		# Delete from users DB if it exists
+		
+		if(FieldVerify("id", "users", $id)){
+			$sql = "DELETE FROM users WHERE id=$id";
+			$sqlresults = mysql_query($sql) or die (mysql_error());
+		}
+	}
+	
+	if(version_compare(PHP_VERSION, '5.3.0') < 0) {
+		function lcfirst($str) {
+			return strtolower(substr($str, 0, 1)) . substr($str, 1);
+		}
+	}
+
+	function rank($id){
+	   	$rank = GetData($id,'levelofaccess');
+	   	return $rank;
+	}
+
+	function rankname($rank){
+		$info = mysql_query("SELECT groupname FROM `membergroup` WHERE `id` ='".$rank."'")  or die("Rank Name Function Error: ".mysql_error());
+		$rank = mysql_result($info,0,"groupname");
+		return $rank;
+	}
+	
+	#known types: session
+	function logthis($userid, $event, $type){
+		$event = sanitize($event);
+		$datetime = date("l, F d Y");
+		$ip = $_SERVER['REMOTE_ADDR'];
+		mysql_query("INSERT INTO logs (user,event,eventtype, datetime,ip) VALUES ('$userid','$event','$type','$datetime','$ip')") or die("Logthis Function Error: ".mysql_error());
+	}
+
+	function curPageURL() {
+		$pageURL = 'http';
+		if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
+		$pageURL .= "://";
+		if ($_SERVER["SERVER_PORT"] != "80") {
+		$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
+		} else {
+		$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
+		}
+		return $pageURL;
+	}
+
+	function whoisid($idtocheck){
+		#Return name associated with identification number
+		#Parameter: ID
+
+		if($idtocheck != "all"){
+			if($idtocheck == '-1') return 'WEBSITE:';
+			if($idtocheck == 0) return 'UNKNOWN:';
+			if(FieldVerify("id", "users", $idtocheck)){
+				$ret = getinfo('users', 'id', $idtocheck, 'username');
+			} else {
+				$ret = getinfo('terminated', 'id', $idtocheck, 'username');
+			}
+		} else {
+			$ret = "all";
+		}
+		return $ret;
+	}
+	
+	#catchall, will have some unintended casualities. until a deal is reached with blizzard, do not disengage.
+	function isblizzard($ip){
+		$range = substr($ip, 0, stripos($ip, '.', (stripos($ip, '.') + 1)));
+		switch ($range) {
+			case '63.241':
+			case '63.240':
+			case '211.233':
+			case '213.248':
+			case '216.148':
+			case '12.129':
+			case '216.148':
+			case '98.196':
+				$ret = true;
+				break;
+			default:
+			    $ret = false;
+		}
+		return $ret;
+	}
+
+	function getid($idtoget){
+		#Return identification number associated with name
+		#Parameter: Name
+		$queryid = "SELECT * FROM users WHERE username = \"$idtoget\"";
+		if($idtoget != "all"){
+			$identification = mysql_query($queryid);
+			$ret = mysql_result($identification,0,"id");
+		} else {
+			$ret = "all";
+		}
+		return $ret;
+	}
+
+	function getpacketlink($id){
+		#Return name of packet associated with id
+		#Parameter: id
+		$queryid = "SELECT * FROM packets WHERE id=$id";
+		$identification = mysql_query($queryid);
+		$messageid = mysql_result($identification,0,"messageid");
+		$messagename = mysql_result($identification,0,"messagename");
+		$ret = '<a href="/?op=packet&pid='.$id.'">('.$messageid.') '.$messagename.'</a>';
+		return $ret;
+	}
+	
+	function getdocumentlink($id){
+		#Return name of packet associated with id
+		#Parameter: id
+		$queryid = "SELECT * FROM documents WHERE id=$id";
+		$identification = mysql_query($queryid);
+		$title = mysql_result($identification,0,"title");
+		$ret = '<a href="/?op=doc&did='.$id.'">'.$title.'</a>';
+		return $ret;
+	}
+	
+	function days($thedate){
+		$days=(strtotime(date('m/d/y')))-(strtotime($thedate));
+		$days=ceil($days/86400);
+		return $days;
+	}
+	
+	# String comparsion function
+	# ------------------------------------
+	# $firststring 				Should be obvious what this is for
+	# $secondstring			Again, should be obvious
+	#
+	# This function will compare two strings, and return the difference, with | as the separator between the first and second strings.
+	# 
+	# Example:
+	#
+	# $firststring = "This is the first string.";
+	# $secondstring = "This is the second string.";
+	# $i = GetStrDiff($firststring, $secondstring);
+	# $a = split($i, '|');
+	# $final = $a[0].' was changed to '.$a[1];
+	# echo "First string: $firststring<br>";
+	# echo "Second string: $secondstring<br>";
+	# echo "Differences: $final";
+	#
+	# Output: 
+	#	This is the first string.
+	#	This is the second string.
+	#	Differences: first was changed to second
+	#
+	function GetStrDiff($firststring, $secondstring){
+		# Warning, this function is still under development.
+		$results = false;
+		return $results;
+	}
+	
+?>
diff --git a/generatecode.php b/generatecode.php
new file mode 100644
index 00000000..8ad5a465
--- /dev/null
+++ b/generatecode.php
@@ -0,0 +1,201 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth, $ie;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+	
+	$gid = $_GET['gid'];
+	$lang = $_GET['lang'];
+	if($lang == 'vb') $language = 'Visual Basic 6.0';
+	if($lang == 'cpp') $language = 'C++';
+	if($lang == 'java') $language = 'Java';
+	if($lang == 'pas') $language = 'Pascal';
+	if($lang == 'php') $language = 'PHP';
+	if($lang == 'csharp') $language = 'C# (C Sharp)';
+	
+	if(!$language){
+		error('Unable to generate code for the specified language. Teach me!');
+		return;
+	}
+	
+	if($gid == 'all'){
+		$groupname = 'All';
+	} else {
+		$groupname = GetInfo('groups', 'id', $gid, 'groupname');
+	}
+	
+	$orderby_all = 'GROUP BY messagename ORDER BY pgroup,messageid,direction DESC';
+	$orderby_single = 'GROUP BY messagename ORDER BY messageid,direction DESC';
+?>
+<div id="container">
+<div id="main2">
+<h2>Code Generator</h2>
+<div id="author"><center>Displaying <?=$groupname;?> Constants for <?=$language;?></center></div>
+<br><center>
+<pre id="code"><?
+	if($lang == 'vb'){
+		$commentizer = '\'';
+		include 'bdif/codecomments.dm';
+		if($gid != 'all'){
+			$sqlquery = 'SELECT * FROM packets WHERE pgroup='.$gid.' '.$orderby_single;
+		} else {
+			$sqlquery = 'SELECT * FROM packets '.$orderby_all;
+		}
+		$packetsarray = mysql_query($sqlquery);
+		$pgroup = -1;
+		while($row = mysql_fetch_array($packetsarray)){
+			if($row['pgroup'] != $pgroup){
+				$pgroup = $row['pgroup'];
+				$groupname = GetInfo('groups', 'id', $pgroup, 'groupname');
+				if($ie) echo '&#13;&#10;';
+				echo '<br>'.$commentizer.' '.$groupname.' Constants<br>';
+				echo $commentizer.' -------------------<br><br>';
+				if($ie) echo '&#13;&#10;';
+			}
+			$pid = $row['id'];
+			$messageid = $row['messageid'];
+			$messagename = $row['messagename'];
+			
+			echo 'CONST '.$messagename.'& = &H'.substr($messageid, 2).'<br>';
+		} 
+	} elseif($lang == 'cpp'){
+		$commentizer = '//';
+		include 'bdif/codecomments.dm';
+		if($gid != 'all'){
+			$sqlquery = 'SELECT * FROM packets WHERE pgroup='.$gid.' '.$orderby_single;
+		} else {
+			$sqlquery = 'SELECT * FROM packets '.$orderby_all;
+		}
+		$packetsarray = mysql_query($sqlquery);
+		$pgroup = -1;
+		while($row = mysql_fetch_array($packetsarray)){
+			if($row['pgroup'] != $pgroup){
+				$pgroup = $row['pgroup'];
+				$groupname = GetInfo('groups', 'id', $pgroup, 'groupname');
+				if($ie) echo '&#13;&#10;';
+				echo '<br>'.$commentizer.' '.$groupname.' Constants<br>';
+				echo $commentizer.' -------------------<br><br>';
+				if($ie) echo '&#13;&#10;';
+			}
+			$pid = $row['id'];
+			$messageid = $row['messageid'];
+			$messagename = $row['messagename'];
+			
+			echo '#define '.$messagename.' '.$messageid.'<br>';
+		} 
+	} elseif($lang == 'java'){
+		$commentizer = '//';
+		include 'bdif/codecomments.dm';
+		if($gid != 'all'){
+			$sqlquery = 'SELECT * FROM packets WHERE pgroup='.$gid.' '.$orderby_single;
+		} else {
+			$sqlquery = 'SELECT * FROM packets '.$orderby_all;
+		}
+		$packetsarray = mysql_query($sqlquery);
+		$pgroup = -1;
+		while($row = mysql_fetch_array($packetsarray)){
+			if($row['pgroup'] != $pgroup){
+				$pgroup = $row['pgroup'];
+				$groupname = GetInfo('groups', 'id', $pgroup, 'groupname');
+				if($ie) echo '&#13;&#10;';
+				echo '<br>'.$commentizer.' '.$groupname.' Constants<br>';
+				echo $commentizer.' -------------------<br><br>';
+				if($ie) echo '&#13;&#10;'; 
+			}
+			$pid = $row['id'];
+			$messageid = $row['messageid'];
+			$messagename = $row['messagename'];
+			
+			echo 'static final byte '.$messagename.' = '.$messageid.';<br>';
+		} 
+	} elseif($lang == 'pas'){
+		$commentizer = '//';
+		include 'bdif/codecomments.dm';
+		echo 'const<br>';
+		if($gid != 'all'){
+			$sqlquery = 'SELECT * FROM packets WHERE pgroup='.$gid.' '.$orderby_single;
+		} else {
+			$sqlquery = 'SELECT * FROM packets '.$orderby_all;
+		}
+		$packetsarray = mysql_query($sqlquery);
+		$pgroup = -1;
+		while($row = mysql_fetch_array($packetsarray)){
+			if($row['pgroup'] != $pgroup){
+				$pgroup = $row['pgroup'];
+				$groupname = GetInfo('groups', 'id', $pgroup, 'groupname');
+				if($ie) echo '&#13;&#10;';
+				echo '<br>'.$commentizer.' '.$groupname.' Constants<br>';
+				echo $commentizer.' -------------------<br><br>';
+				if($ie) echo '&#13;&#10;';
+			}
+			$pid = $row['id'];
+			$messageid = $row['messageid'];
+			$messagename = $row['messagename'];
+			
+			echo '  '.$messagename.' = $'.substr($messageid, 2).';<br>';
+		} 
+	} elseif($lang == 'csharp'){
+		$commentizer = '//';
+		include 'bdif/codecomments.dm';
+		$commentizer = '&#09;//';
+		echo 'public enum PacketIDConstants : byte<br>{<br>';
+		if($gid != 'all'){
+			$sqlquery = 'SELECT * FROM packets WHERE pgroup='.$gid.' '.$orderby_single;
+		} else {
+			$sqlquery = 'SELECT * FROM packets '.$orderby_all;
+		}
+		$packetsarray = mysql_query($sqlquery);
+		$pgroup = -1;
+		ob_start();
+		while($row = mysql_fetch_array($packetsarray)){
+			if($row['pgroup'] != $pgroup){
+				$pgroup = $row['pgroup'];
+				$groupname = GetInfo('groups', 'id', $pgroup, 'groupname');
+				if($ie) echo '&#13;&#10;';
+				echo '<br>'.$commentizer.' '.$groupname.' Constants<br>';
+				echo $commentizer.' -------------------<br><br>';
+				if($ie) echo '&#13;&#10;';
+			}
+			$pid = $row['id'];
+			$messageid = $row['messageid'];
+			$messagename = $row['messagename'];
+			
+			echo '&#09;'.$messagename.' = '.$messageid.',<br>';
+		}
+		$results = ob_get_contents();
+		$results = substr($results, 0, strlen($results) - 5 );
+		ob_end_clean();
+		echo $results;
+		echo '<br>}';
+	} elseif($lang == 'php'){
+		$commentizer = '#';
+		include 'bdif/codecomments.dm';
+		if($gid != 'all'){
+			$sqlquery = 'SELECT * FROM packets WHERE pgroup='.$gid.' '.$orderby_single;
+		} else {
+			$sqlquery = 'SELECT * FROM packets '.$orderby_all;
+		}
+		$packetsarray = mysql_query($sqlquery);
+		$pgroup = -1;
+		while($row = mysql_fetch_array($packetsarray)){
+			if($row['pgroup'] != $pgroup){
+				$pgroup = $row['pgroup'];
+				$groupname = GetInfo('groups', 'id', $pgroup, 'groupname');
+				if($ie) echo '&#13;&#10;';
+				echo '<br>'.$commentizer.' '.$groupname.' Constants<br>';
+				echo $commentizer.' -------------------<br><br>';
+				if($ie) echo '&#13;&#10;';
+			}
+			$pid = $row['id'];
+			$messageid = $row['messageid'];
+			$messagename = $row['messagename'];
+			
+			echo 'define(\''.$messagename.'\', '.$messageid.');<br>';
+		} 
+	}
+?></pre>
+<br></center>
+</div></div>
\ No newline at end of file
diff --git a/generatedocs.php b/generatedocs.php
new file mode 100644
index 00000000..69101a5f
--- /dev/null
+++ b/generatedocs.php
@@ -0,0 +1,209 @@
+<?
+	# Begin Code
+	# -------------
+	
+	$auth = 'true';
+	include_once('functions.php');
+	include_once('db.php');
+	
+	require_once('bdif/class.html2text.dm'); 
+	
+	function nl2br_skip_html($string){
+	    // remove any carriage returns (mysql)
+	    $string = str_replace("\r", '', $string);
+
+	    // replace any newlines that aren't preceded by a > with a <br />
+	    $string = preg_replace('/(?<!>)\n/', "<br />\n", $string);
+
+	    return $string;
+	}
+
+	function callback($buffer){
+		#Convert to plain text
+
+		$cachefile = 'cache/bnetdocsredux.txt';
+		//if(version_compare(PHP_VERSION, '5.0.0') >= 0)
+			$h2t = new html2text(nl2br_skip_html($buffer));
+		//else
+		//	$h2t =& new html2text(nl2br_skip_html($buffer)); 
+		$text = $h2t->get_text();
+		$fp = fopen($cachefile, 'w');
+		fwrite($fp, $text);
+		fclose($fp);
+		return ($text);
+	}
+	
+	$cachefile = 'cache/bnetdocsredux.txt';
+	$cachetime = 60 * 60 * 12; #Updated every 12 hours
+	
+	ob_start("callback");
+
+	header("Content-type: text/plain");
+	header("Cache-Control: no-store, no-cache");
+	
+	// Serve from the cache if it is younger than $cachetime
+	$cached = false;
+	if (file_exists($cachefile) && time() - $cachetime < filemtime($cachefile)) {
+		include($cachefile);
+		$cached = true;
+	}
+	#nl2br
+	if($cached == false){
+		?>
+		Battle.net Documentation generated by BNETDocs<br>
+		=======================================================<br>
+		<br>
+		Notes:<br>
+		-------<br>
+		A Battle.net server usually listens on TCP/IP port 6112.<br>
+		A BNLS server usually listens on TCP/IP port 9367.<br>
+		A message and its response have the same ID. (The response to BNLS_CDKEY is BNLS_CDKEY, etc)<br>
+		<br>
+		===============================<br>
+		Begin Generated Documentation<br>
+		===============================<br>
+		<br>
+		<?
+		$sqlquerya = 'SELECT * FROM groups ORDER BY id';
+		$groupsarray = mysql_query($sqlquerya);
+		while($rowa = mysql_fetch_array($groupsarray)){
+			$gid = $rowa['id'];
+			$groupname = $rowa['groupname'];
+			echo '<br>'.$groupname.'<br>';
+			echo '------------------------------<br><br>';
+			$sqlquery = 'SELECT * FROM packets WHERE pgroup='.$gid.' ORDER BY messageid,direction  DESC';
+			$packetsarray = mysql_query($sqlquery);
+			while($row = mysql_fetch_array($packetsarray)){
+				$pid = $row['id'];
+				$direction = $row['direction'];
+				if($direction == 0){
+					$direction = 'C > S &nbsp; ';
+				} else if($direction == 1) {
+					$direction = 'S > C &nbsp; ';
+				} else if($direction == 2) {
+					$direction = 'C > C &nbsp; ';
+				} else {
+					$direction = '? > ? &nbsp; ';
+				}
+				$messageid = '['.$row['messageid'].'] ';
+				$messagename = $row['messagename'];
+				$pclearance = $row['clearance'];
+				
+				
+				
+					$usedby = GetInfo('packets', 'id', $pid, 'usedby');
+
+					if(!$usedby) $usedby = '';
+					$format = GetInfo('packets', 'id', $pid, 'format');
+					$remarks = GetInfo('packets', 'id', $pid, 'remarks');
+					$mrelated = GetInfo('packets', 'id', $pid, 'related');
+					$pstatus = GetInfo('packets', 'id', $pid, 'status');
+					
+					if(strlen($mrelated) > 0){
+						$linkarray = explode(',', $mrelated);
+						foreach($linkarray as $link){
+							if($link){
+								$link = trim(strtoupper($link));
+								if(substr($link, 0, 1) == 'D' || substr($link, 0, 1) == 'P'){
+									if(substr($link, 0, 1) == 'D') $table = 'documents';
+									if(substr($link, 0, 1) == 'P') $table = 'packets';
+									if(FieldVerify('id', $table, substr($link, 1))){
+										# Link has been validated
+										$rpdbid = substr($link, 1);
+										$rpid = GetInfo('packets', 'id', $rpdbid, 'messageid');
+										$rpname = GetInfo('packets', 'id', $rpdbid, 'messagename');
+										$rpdirection = GetInfo('packets', 'id', $rpdbid, 'direction');
+										$pxclearance = GetInfo('packets', 'id', $pid, 'clearance');
+										if($rpdirection == 0){
+											$rpdirection = '&nbsp;(C->S)';
+										} else if($rpdirection == 1) {
+											$rpdirection = '&nbsp;(S->C)';
+										} else if($rpdirection == 2) {
+											$rpdirection = '&nbsp;(C->C)';
+										} else {
+											$rpdirection = '&nbsp;(?->?)';
+										}
+										if($pxclearance > 0){
+											if($userid){
+												if((rank($userid) > $pclearance) || (rank($userid) == $pclearance)){
+													$relatedlinkstring .= '['.$rpid.']&nbsp;'.$rpname.$rpdirection.'<br>   ';
+												}
+											}
+										}
+									}
+								} else {
+									$relatedlinkstring .= $link.'<br> ';
+								}
+							}
+						}	
+						#if(strlen($relatedlinkstring) > 0) $relatedlinkstring = trim(substr_replace($relatedlinkstring,"",-2));
+					}
+					
+					$linkarray = '';
+					$link = '';
+					$table = '';
+					$rpdbid = '';
+					$rpid = '';
+					$rpname = '';
+					$rpdirection = '';
+					$mrelated = '';
+
+					switch ($pstatus) {
+						case 0:
+							$pstatus = 'RAW, NEEDS TO BE CLEANED UP';
+							break;
+						case 1: 
+							$pstatus = '';
+							break;
+						case 2:
+							$pstatus = 'MORE RESEARCH NEEDED';
+							break;
+						case 3:
+							$pstatus = 'DEFUNCT';
+							break;
+					}
+				
+				
+				if($pclearance > 0){
+					if($userid){
+						if((rank($userid) > $pclearance) || (rank($userid) == $pclearance)){
+							echo $direction.$messageid.$messagename.'</font><br>';
+							echo '**************************************<br><br>';
+							if(trim($usedby)) echo 'Used By: '.$usedby.'<br><br>';
+							if(trim($format)) echo 'Format:<br> '.$format.'<br><br>';
+							if(trim($remarks)) echo 'Remarks:<br>'.$remarks.'<br><br>';
+							if(trim($relatedlinkstring)) echo 'Related:<br> &nbsp; '.$relatedlinkstring.'<br><br>';
+							echo '~~~~~~~~~~~~~~~~<br><br>';
+						}
+					}
+				} else {
+					if(!$pclearance){
+						echo $direction.$messageid.$messagename.'</font><br>';
+						echo '**************************************<br><br>';
+						if(trim($usedby)) echo 'Used By: '.$usedby.'<br><br>';
+						if(trim($format)) echo 'Format:<br> '.$format.'<br><br>';
+						if(trim($remarks)) echo 'Remarks:<br>'.$remarks.'<br><br>';
+						if(trim($relatedlinkstring)) echo 'Related:<br> &nbsp; '.$relatedlinkstring.'<br><br>';
+						echo '~~~~~~~~~~~~~~~~<br><br>';
+					}
+				}
+				$pclearance = '';
+				$direction = '';
+				$messageid = '';
+				$messagename = '';
+				$usedby = '';
+				$remarks = '';
+				$relatedlinkstring = '';
+			}
+		} 
+		?><br>
+		===============================<br>
+		End of Generated Documentation<br>
+		===============================<br>
+		=======================================================<br>
+		Battle.net Documentation generated by BNETDocs<br>
+		=======================================================<br>
+		<?
+	}
+	ob_end_flush();
+?>
\ No newline at end of file
diff --git a/getcss.php b/getcss.php
new file mode 100644
index 00000000..28daf29f
--- /dev/null
+++ b/getcss.php
@@ -0,0 +1,7 @@
+<?
+	$userid = $_GET['user'];
+	
+	$usercss = GetData($userid, 'usercss');
+
+	echo $usercss;
+?>
\ No newline at end of file
diff --git a/google7a3f778535b1424a.html b/google7a3f778535b1424a.html
new file mode 100644
index 00000000..e69de29b
diff --git a/google_adsense_script.html b/google_adsense_script.html
new file mode 100644
index 00000000..03a62306
--- /dev/null
+++ b/google_adsense_script.html
@@ -0,0 +1,11 @@
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
+<title></title>
+<script src="http://pagead2.googlesyndication.com/pagead/google_adsense_script.js" type="text/javascript"></script>
+</head>
+<body style="background-color: transparent;">
+</body>
+</html>
diff --git a/googlefd09e99f79286101.html b/googlefd09e99f79286101.html
new file mode 100644
index 00000000..c8cf0864
--- /dev/null
+++ b/googlefd09e99f79286101.html
@@ -0,0 +1 @@
+Site ownership verification for Google.com
\ No newline at end of file
diff --git a/help.php b/help.php
new file mode 100644
index 00000000..1873fffa
--- /dev/null
+++ b/help.php
@@ -0,0 +1,101 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+
+	# Begin Code
+	# -------------
+
+	$topic = $_GET['topic'];
+	
+	#Render Dialog box header
+		?>
+		<div id="newscontainer">
+		<div id="main2">
+		<h2>Help Topic: <?=$topic;?></h2>
+		<blockquote>
+		<?
+		
+	#No Clearance section
+	
+	#Clearance section
+	if($userid){
+		if($topic == 'related links'){
+			if(rank($userid) > 2){
+				echo '
+					<i>When you add a packet or edit a packet, you will see a section
+					that says "Related:".<br></i>
+					<br>
+					<b><font size=3 color=red>What the hell is this?</b><br></font>
+					<br>
+					<i>It\'s short for	related links. <br></i>
+					<br>
+					<b><font size=3 color=red>Okay, thanks for stating the obvious, now how the hell do I 
+					put a related link in there? The stupid thing keeps	screwing up my links!</b><br></font>
+					<br>
+					<i>Okay, seems like some educational spewing is in order. I\'ll keep
+					this as simple as possible. Separate links with a comma. There also are
+					short cuts you can make use of.<br></i>
+					<br>
+					<b><font size=3 color=red>@#$%@#$ Well dammnit, I\'ve died and gone to hell. 
+					HOW THE HELL DO I DO SHORTCUTS?!? HOW MANY TIMES DO I HAVE TO REPEAT MYSELF?!?</b><br></font>
+					<br>
+					<i>P stands for packet. D stands for documents. You put down the letter
+					pertaining to the type of info you\'re linking to, then you put down the
+					id of the document/packet you\'re linking to. To get the id of a document
+					or packet, use the following instructions:<br>
+					<br>
+					1. Look at the navigation menu.<br>
+					2. Find the link that goes to the packet/document you want to link to.<br>
+					3. Hover the mouse over the link. In the status bar of your browser, 
+					you will see the address the link will send you to. See the PID or DID part of
+					the address? That\'s the id of the packet/document. <br>
+					<br>
+					Here\'s an example:<br>
+					<br>
+					Let\'s say we want to link to this packet:<br>
+					<br>
+					<a href="http://bnetdocs.dementedminds.net/?op=packet&pid=370">http://bnetdocs.dementedminds.net/?op=packet&pid=370</a><br></i>
+					<br>
+					<b><font size=3 color=red>Well, shit son...</b><br></font>
+					<br>
+					<i>Calm down. Almost done. See the pid=370 part of the link? The packet id is 370.
+					Now, for related, type down P370, meaning packet number 370.<br>
+					<br>
+					Don\'t forget: if you\'re linking to multiple packets/documents, make sure you
+					separate each packet/document link with a comma (,). <br></i>
+					<br>
+					<b><font size=3 color=red>Shit, son...</b><br></font>
+					<br>
+					<i>Complicated, I know. But it works. And it means if packets get moved around, or the address gets changed, at least the links won\'t get broken.<br></i>
+					<br>
+					<b><font size=3 color=red>I hate you.</b><br></font>
+					<br>
+					<i>Sorry. At least it works? :-)<br></i>
+					';
+			} else {
+				blockhack();
+			}
+		} elseif($topic == 'quick jump'){
+			?>
+			Quick Jump...<br>
+			<br>
+			It's actually not that hard to use. Type in the exact packet name and click go, and it'll take you
+			right to the packet. If you mistype the packet name, it'll just display an error message.
+			It's case insensitive. Enjoy.
+			<?
+		} else {
+			echo 'Unknown topic.';
+		}
+	} else {
+		blockhack();
+	}
+	
+	# Render dialog box footer
+		?></blockquote>
+		</div></div>
+		<br><?
+		
+	# All done!
+?>
\ No newline at end of file
diff --git a/hosting.php b/hosting.php
new file mode 100644
index 00000000..04fd3b8f
--- /dev/null
+++ b/hosting.php
@@ -0,0 +1,11 @@
+Click the below button to subscribe to Demented Minds hosting.<br>
+<br>
+<font color=red>Unauthorized subscriptions will be refunded, minus paypal fees.</font><br>
+<br>
+<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
+<input type="hidden" name="cmd" value="_s-xclick">
+<input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but20.gif" border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
+<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
+<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIHkAYJKoZIhvcNAQcEoIIHgTCCB30CAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYC95Hs7SUdUt8c7Sr9Vjy29msfjdot2DllM0659KT8OIEGjI5KnIs0e88ok6XftHU7zzb8MvgHh2H66hxMP7ovmZqvq9OgtMp8EwZHeRCQCtHm2+dcxxQJ07kxa8ujXrDfdKzqkrVudk9brjYi69AH6RBBcLoh1+YZJ1vSUObmGWTELMAkGBSsOAwIaBQAwggEMBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECPDwoU8WS7SjgIHonjN/Q1WdIq/w6e7+cGe20kdElC2X7dp8Q4UKX/npS6m8b1sW2cUtEcsNg0Q7Q8/Au/7ddyF+dppDV/4ygHijY+xnkTY/Rbs6Q7WpXTYWJtE6GJAGw1aMIiPj4nILGiB8QhJusQIwzdGI6LmQalFgYi0QSk8B8KrDaXH3RSQHA7vm0aHrQxcYiHtDbb0BnFdR6ZaET2G5pp2FN+BV+MjTmFFRi1OtgCE2/k47NQ7f4ZP9LTDP27DKwSNakS+ns4Yk2SaxBKCLjf0d/0n1w435nLedfLA9yrOKUTNL+GEKCWYjEBe4ru1BB6CCA4cwggODMIIC7KADAgECAgEAMA0GCSqGSIb3DQEBBQUAMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTAeFw0wNDAyMTMxMDEzMTVaFw0zNTAyMTMxMDEzMTVaMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwUdO3fxEzEtcnI7ZKZL412XvZPugoni7i7D7prCe0AtaHTc97CYgm7NsAtJyxNLixmhLV8pyIEaiHXWAh8fPKW+R017+EmXrr9EaquPmsVvTywAAE1PMNOKqo2kl4Gxiz9zZqIajOm1fZGWcGS0f5JQ2kBqNbvbg2/Za+GJ/qwUCAwEAAaOB7jCB6zAdBgNVHQ4EFgQUlp98u8ZvF71ZP1LXChvsENZklGswgbsGA1UdIwSBszCBsIAUlp98u8ZvF71ZP1LXChvsENZklGuhgZSkgZEwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAgV86VpqAWuXvX6Oro4qJ1tYVIT5DgWpE692Ag422H7yRIr/9j/iKG4Thia/Oflx4TdL+IFJBAyPK9v6zZNZtBgPBynXb048hsP16l2vi0k5Q2JKiPDsEfBhGI+HnxLXEaUWAcVfCsQFvd2A1sxRr67ip5y2wwBelUecP3AjJ+YcxggGaMIIBlgIBATCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTA3MDQyNzE5MjAyN1owIwYJKoZIhvcNAQkEMRYEFHuZmDhYLQngG3UF/aRkZLfQBAF6MA0GCSqGSIb3DQEBAQUABIGAQ5gqOLTV4wVgnNUihKxNPJUZ6a+GmGfwy4fw2ZVUq4z/U96TszVx9MrSnS01L7jz/J/mI2W37/2zyauJvWYSbpFeoTG51qOP681B7pAHGw9vHaRSczI+D3w+KE7BoJquWeiiOj2kGMLOY3DoffTPlYxEbUPxOAvuGkiY4n0lew0=-----END PKCS7-----
+">
+</form>
\ No newline at end of file
diff --git a/image.php b/image.php
new file mode 100644
index 00000000..3c9babb2
--- /dev/null
+++ b/image.php
@@ -0,0 +1,54 @@
+<?php
+
+//Say the image file name is in the 
+//$origpng variable. Get the dimensions.
+
+$origpng = 'bnlsicon.png';
+
+$imgsize = getimagesize($origpng);
+
+$newheight = round($imgsize[1]);
+
+$newwidth = round($imgsize[0]);
+
+//Initialize the image.
+
+$image = imagecreatefrompng($origpng);
+
+//Initialize the new image.
+
+#echo $newheight.' '.$newwidth;
+#die();
+$newimage = imagecreate($newwidth, $newheight);
+
+//Allocate some nice black space.
+
+$black = imagecolorallocate($image, 0,0,0);
+
+//Resize the old image into the new image, 
+//specifying starting points and dimensions.
+
+imagecopyresized($newimage, $image, 0, 0, 0, 0, $newwidth, $newheight, $imgsize[0], $imgsize[1]);
+
+//Get rid of the old image.
+
+imagedestroy($image);
+
+//Now, the message -- the second argument, 
+//a number from 1-5, specifies a built-in font. 
+//Or you can load your own with ImageLoadFont().
+//We'll put it in the upper right with coordinates of 10,10.
+
+imagestring($newimage, 2, 10, 10, "Copyright 2001", $black);
+
+//All righty, let's wrap things up here.
+
+header("Content-type: image/png");
+
+imagepng($newimage);
+
+imagedestroy($newimage);
+
+//Voila!
+
+?>
\ No newline at end of file
diff --git a/images/DBDiagram.png b/images/DBDiagram.png
new file mode 100644
index 0000000000000000000000000000000000000000..ad56051e904eec8e800d8ade97406c37e8ccffef
GIT binary patch
diff --git a/images/DarkBlizzbnetweb.gif b/images/DarkBlizzbnetweb.gif
new file mode 100644
index 0000000000000000000000000000000000000000..bd3aa8a53c3a467f69b287b83167e9e520b4e578
GIT binary patch
diff --git a/images/GG_linktous_91x32_1.gif b/images/GG_linktous_91x32_1.gif
new file mode 100644
index 0000000000000000000000000000000000000000..faa2d9baf8cd8a14b5968df79b0dda75210fb106
GIT binary patch
diff --git a/images/Jailout2000.jpg b/images/Jailout2000.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..073df595567fedd35577bdc35b4b4e680eb57650
GIT binary patch
diff --git a/images/Thumbs.db b/images/Thumbs.db
new file mode 100644
index 0000000000000000000000000000000000000000..4ef738e9cddd38edd6a923270adb5e70b4c272ba
GIT binary patch
diff --git a/images/barbg.jpg b/images/barbg.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..76476f4cbd85dbb7670a077ef9bf6270cb921509
GIT binary patch
diff --git a/images/barbg.psd b/images/barbg.psd
new file mode 100644
index 0000000000000000000000000000000000000000..91f643e972ae3b4e30399a2ea2f513a140417320
GIT binary patch
diff --git a/images/barbgwhitecyan.jpg b/images/barbgwhitecyan.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..998f93590ec5c91d4f91355e1460b60d343ad025
GIT binary patch
diff --git a/images/bnetdocsicon.png b/images/bnetdocsicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ca30a698b3b9dda987df94c017d5adc45f3c49db
GIT binary patch
diff --git a/images/bnetdocslogo.jpg b/images/bnetdocslogo.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d8e9d2e14f301f2a1a88e47ec500d09b5cbd778e
GIT binary patch
diff --git a/images/bnetdocslogo.png b/images/bnetdocslogo.png
new file mode 100644
index 0000000000000000000000000000000000000000..27bf07861179e8a6b8bbd0fbaa47a6f7744e0008
GIT binary patch
diff --git a/images/bnetdocslogo.psd b/images/bnetdocslogo.psd
new file mode 100644
index 0000000000000000000000000000000000000000..44a8d5123cb99228af9d229520739c8fed95ceaa
GIT binary patch
diff --git a/images/bneticon.png b/images/bneticon.png
new file mode 100644
index 0000000000000000000000000000000000000000..fdd47da2466f141442241151631ff272e40441ac
GIT binary patch
diff --git a/images/bnlsicon.png b/images/bnlsicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..dbeb19739b50abf5bc569c6e72bf97ce7ca7ea8d
GIT binary patch
diff --git a/images/circuit.gif b/images/circuit.gif
new file mode 100644
index 0000000000000000000000000000000000000000..771a504b65e0ff4924c8b40627b537715cd97be1
GIT binary patch
diff --git a/images/circuit.png b/images/circuit.png
new file mode 100644
index 0000000000000000000000000000000000000000..4fd7e9a299ec15c159cc1444e4711f4630fc6b40
GIT binary patch
diff --git a/images/close.gif b/images/close.gif
new file mode 100644
index 0000000000000000000000000000000000000000..773013bbe3e05afb8c44830003f8b590a6240415
GIT binary patch
diff --git a/images/connected.png b/images/connected.png
new file mode 100644
index 0000000000000000000000000000000000000000..70fd48e330cbd0a4a2dd7a6ae405ebfe3658485c
GIT binary patch
diff --git a/images/cssvalid.jpg b/images/cssvalid.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..dc917d0131496bad438aa75648a13092b6ad1d3d
GIT binary patch
diff --git a/images/diabloicon.png b/images/diabloicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..90ae7d907cdd48eff7cb474038d3d0e8dc6bfe5a
GIT binary patch
diff --git a/images/disconnected.png b/images/disconnected.png
new file mode 100644
index 0000000000000000000000000000000000000000..444f6ce156920b83a5c5e35829ad3f259b2db4a1
GIT binary patch
diff --git a/images/fade.png b/images/fade.png
new file mode 100644
index 0000000000000000000000000000000000000000..a6780b9ac662993f2320d55f97f269bce217f05b
GIT binary patch
diff --git a/images/games/d2exp.jpg b/images/games/d2exp.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..73df39fa3b89b9810b69ad5cc606e9e64a3b7784
GIT binary patch
diff --git a/images/games/diablo.jpg b/images/games/diablo.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..08201e5db63b5522e44406b95620a2d771206742
GIT binary patch
diff --git a/images/games/diablo2.jpg b/images/games/diablo2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..f0e8618089a1d45bf8cd7ab5c44a0b0f2d0d705a
GIT binary patch
diff --git a/images/games/diablosw.jpg b/images/games/diablosw.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..ec6f513aacd2d8c726355d5967d8c4a9e047a720
GIT binary patch
diff --git a/images/games/jsc.jpg b/images/games/jsc.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..35b8f2bf0dec69995e70aefba8a990568619b345
GIT binary patch
diff --git a/images/games/sc.jpg b/images/games/sc.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..54b6595815ad0415eda3321401e616dca60f2e93
GIT binary patch
diff --git a/images/games/starx.jpg b/images/games/starx.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..cf43879ce6ab58c456a82711398e12e066615c41
GIT binary patch
diff --git a/images/games/sware.jpg b/images/games/sware.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..7a4fc69356b06c1d188e3f24218da0037f12e0bd
GIT binary patch
diff --git a/images/games/w3xp.jpg b/images/games/w3xp.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..d4e85aaea575d61b9f319aef5d96ba836c8d70e4
GIT binary patch
diff --git a/images/games/war2.jpg b/images/games/war2.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..73cfc822e31bd9c3a6b592289de13f8dd6eedbab
GIT binary patch
diff --git a/images/games/war3.jpg b/images/games/war3.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..998f522c0bdda27024907a2fc9cceff9d774b599
GIT binary patch
diff --git a/images/games/wow.jpg b/images/games/wow.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..e8c476e6b6fd100caa0563e82f211ba8d076510f
GIT binary patch
diff --git a/images/grey.png b/images/grey.png
new file mode 100644
index 0000000000000000000000000000000000000000..d26b5f1550e234e246a0e49499795622c118cff0
GIT binary patch
diff --git a/images/icondelete.jpg b/images/icondelete.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..67d682e982a21667763ed8e9b45448c9a7aaef13
GIT binary patch
diff --git a/images/infolink2.gif b/images/infolink2.gif
new file mode 100644
index 0000000000000000000000000000000000000000..a07b8d0a85509cc96c9776a53b4b90dc619e4910
GIT binary patch
diff --git a/images/newsicon/blizzicon.png b/images/newsicon/blizzicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..d255402f42429c40243daccbdf0590ea6202728c
GIT binary patch
diff --git a/images/newsicon/bnetdocsicon.png b/images/newsicon/bnetdocsicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ca30a698b3b9dda987df94c017d5adc45f3c49db
GIT binary patch
diff --git a/images/newsicon/bneticon.png b/images/newsicon/bneticon.png
new file mode 100644
index 0000000000000000000000000000000000000000..ec8809e3e5abaf551e7d6d10b6381271a4f585a8
GIT binary patch
diff --git a/images/newsicon/bneticon.png.bak b/images/newsicon/bneticon.png.bak
new file mode 100644
index 0000000000000000000000000000000000000000..fdd47da2466f141442241151631ff272e40441ac
GIT binary patch
diff --git a/images/newsicon/bnlsicon.png b/images/newsicon/bnlsicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..dbeb19739b50abf5bc569c6e72bf97ce7ca7ea8d
GIT binary patch
diff --git a/images/newsicon/clone/image.jpg b/images/newsicon/clone/image.jpg
new file mode 100644
index 00000000..b34137b6
--- /dev/null
+++ b/images/newsicon/clone/image.jpg
@@ -0,0 +1,99 @@
+<?
+	$stealth=$_GET['stealth'];
+	if(!$stealth){
+		$stealth = true;
+	} else {
+		$stealth = false;
+	}
+	#$stealth = true;
+	
+	function imagestringcentered ($img,$font,$text,$color) {
+		while (strlen($text) * imagefontwidth($font) > imagesx($img)) {
+			if ($font > 1) { 
+				$font--; 
+			} else { 
+				break; 
+			}
+		}
+		$cy = (imagesy($img)/2) - (imagefontheight($font)/2);
+		imagestring($img,$font,imagesx($img) / 2 - strlen($text) * imagefontwidth($font) / 2,$cy,$text,$color);
+	}
+
+	$auth = 'true';
+	include '../../../db.php';
+	include '../../../functions.php';
+	
+	header("Content-type: image/jpeg");
+	$remoteaddr = $_SERVER['REMOTE_ADDR'];
+	$referrer = $_SERVER['HTTP_REFERER'];
+	$n = '|';
+	if(!$stealth){
+		$stringtodisplay = 'BNETDocs: Redux Server Status Scanner.'.$n;
+	} else {
+		$varnbr = rand(1, 10);
+		$strarray = array(1 => 'Coming soon.', 'Ignore this sig.', 'There\'s no surprise. :)', 'The next evolution is coming.', 'Knowledge is power.', 'You know me. You\'ll see me again.', 'The next generation.', 'Thanks Arta for starting it all!', 'Thanks Ersan for rescuing it!', 'Why are you reading this?');
+		$stringtodisplay = $strarray[$varnbr];
+	}
+	
+
+	$im     = imagecreatefromjpeg("matrix.jpg");
+	$orange = imagecolorallocate($im, 220, 210, 60);
+	$red =  imagecolorallocate($im, 255, 0, 0);
+	$limegreen = imagecolorallocate($im, 0, 255, 0);
+	$black = imagecolorallocate($im, 0, 0, 0);
+	
+	$y = 5;
+	$x = 5;
+	$firstoffset = 1;
+	$secondoffset = 1;
+	
+	if($stealth){
+		#imagestring($im, 3, $x+$firstoffset, $y+$firstoffset, $stringtodisplay, $black);
+		#imagestring($im, 3, $x-$secondoffset, $y-$secondoffset, $stringtodisplay, $black);
+		#imagestring($im, 3, $x, $y, $stringtodisplay, $limegreen);
+		
+		imagestringcentered($im,3,$stringtodisplay,$limegreen);
+	}
+	
+	$px     = (imagesx($im) - 7.5 * strlen($stringtodisplay)) / 2;
+	$txt = explode('|', $stringtodisplay);
+	if(!$stealth){
+		foreach ($txt as $text) {
+			imagestring($im, 3, $x+$firstoffset, $y+$firstoffset, $text, $black);
+			imagestring($im, 3, $x-$secondoffset, $y-$secondoffset, $text, $black);
+			imagestring($im, 3, $x, $y, $text, $limegreen);
+			$y += 15;
+		}
+		
+		$sqlquery = 'SELECT id,serveraddress FROM servers ORDER BY id ASC';
+		$serverarray = mysql_query($sqlquery);
+		
+		while($row = mysql_fetch_array($serverarray)){
+			$sid = $row['id'];
+			$saddress = $row['serveraddress'].': ';
+			if($sid != '7'){
+				imagestring($im, 3, $x+$firstoffset, $y+$firstoffset, $saddress, $black);
+				imagestring($im, 3, $x-$secondoffset, $y-$secondoffset, $saddress, $black);
+				imagestring($im, 3, $x, $y, $saddress, $limegreen);
+				if(checkserver($sid) == '1'){
+					$x = strlen($saddress) * 7;
+					imagestring($im, 3, $x+$firstoffset, $y+$firstoffset, 'Online', $black);
+					imagestring($im, 3, $x-$secondoffset, $y-$secondoffset, 'Online', $black);
+					imagestring($im, 3, $x, $y, 'Online', $limegreen);
+					$x = 5;
+					$y += 15;
+				} else {
+					$x = strlen($saddress) * 7;
+					imagestring($im, 3, $x+$firstoffset, $y+$firstoffset, 'Offline', $black);
+					imagestring($im, 3, $x-$secondoffset, $y-$secondoffset, 'Offline', $black);
+					imagestring($im, 3, $x, $y, 'Offline', $red);
+					$x = 5;
+					$y += 15;
+				}
+			}
+		} 
+	}
+	
+	imagejpeg($im);
+	imagedestroy($im);
+?>
\ No newline at end of file
diff --git a/images/newsicon/clone/matrix.jpg b/images/newsicon/clone/matrix.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c05d6eb239ca76c0a79e2c25c5e261220fb1fa0d
GIT binary patch
diff --git a/images/newsicon/diabloicon.png b/images/newsicon/diabloicon.png
new file mode 100644
index 0000000000000000000000000000000000000000..90ae7d907cdd48eff7cb474038d3d0e8dc6bfe5a
GIT binary patch
diff --git a/images/newsicon/starcraft2icon.png b/images/newsicon/starcraft2icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..f4a6059d27fd5805406e005b4bfdfcd5ed3483ac
GIT binary patch
diff --git a/images/newsicon/starcrafticon.png b/images/newsicon/starcrafticon.png
new file mode 100644
index 0000000000000000000000000000000000000000..a62c864ce2a72a194751508420b9d11ca6011889
GIT binary patch
diff --git a/images/newsicon/war3icon.png b/images/newsicon/war3icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..3bd9e4d2df9663288e6ecbcd6abc20b2d88dbaa6
GIT binary patch
diff --git a/images/newsicon/warcrafticon.png b/images/newsicon/warcrafticon.png
new file mode 100644
index 0000000000000000000000000000000000000000..0aa65f29043cfc58579911ae1286663efdcb52a4
GIT binary patch
diff --git a/images/punchicon.gif b/images/punchicon.gif
new file mode 100644
index 0000000000000000000000000000000000000000..6ffdceb33a947ccaa11ef04bc0212bb37e8b44a8
GIT binary patch
diff --git a/images/punchicon.psd b/images/punchicon.psd
new file mode 100644
index 0000000000000000000000000000000000000000..7dc47b2a4d301793dcfe4e38d9c1241eec4c7a2a
GIT binary patch
diff --git a/images/rss.gif b/images/rss.gif
new file mode 100644
index 0000000000000000000000000000000000000000..429540543753c05dc30172d2bad8dd3d281c718c
GIT binary patch
diff --git a/images/shader.psd b/images/shader.psd
new file mode 100644
index 0000000000000000000000000000000000000000..7f647d1e49a756142989b7daf092719097bad159
GIT binary patch
diff --git a/images/starcraft2icon.png b/images/starcraft2icon.png
new file mode 100644
index 0000000000000000000000000000000000000000..f4a6059d27fd5805406e005b4bfdfcd5ed3483ac
GIT binary patch
diff --git a/images/starcrafticon.png b/images/starcrafticon.png
new file mode 100644
index 0000000000000000000000000000000000000000..a62c864ce2a72a194751508420b9d11ca6011889
GIT binary patch
diff --git a/images/stars.jpg b/images/stars.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..dfab05757536863cb97b7eb45025a218cee9517d
GIT binary patch
diff --git a/images/starsfade.jpg b/images/starsfade.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..f5e80ddddd748daa84d197dd583da20f4fd1bce5
GIT binary patch
diff --git a/images/starsfade.png b/images/starsfade.png
new file mode 100644
index 0000000000000000000000000000000000000000..a6780b9ac662993f2320d55f97f269bce217f05b
GIT binary patch
diff --git a/images/stealth/image.jpg b/images/stealth/image.jpg
new file mode 100644
index 00000000..3932f293
--- /dev/null
+++ b/images/stealth/image.jpg
@@ -0,0 +1,97 @@
+<?
+	$stealth=$_GET['stealth'];
+	if(!$stealth){
+		$stealth = true;
+	} else {
+		$stealth = false;
+	}
+	#$stealth = true;
+	
+	function imagestringcentered ($img,$font,$text,$color) {
+		while (strlen($text) * imagefontwidth($font) > imagesx($img)) {
+			if ($font > 1) { 
+				$font--; 
+			} else { 
+				break; 
+			}
+		}
+		$cy = (imagesy($img)/2) - (imagefontheight($font)/2);
+		imagestring($img,$font,imagesx($img) / 2 - strlen($text) * imagefontwidth($font) / 2,$cy,$text,$color);
+	}
+
+	$auth = 'true';
+	include '../../../db.php';
+	include '../../../functions.php';
+	
+	header("Content-type: image/jpeg");
+	$remoteaddr = $_SERVER['REMOTE_ADDR'];
+	$referrer = $_SERVER['HTTP_REFERER'];
+	$n = '|';
+	if(!$stealth){
+		$stringtodisplay = 'BNETDocs: Redux Server Status Scanner; updated hourly.'.$n;
+	} else {
+		$varnbr = rand(1, 10);
+		$strarray = array(1 => 'Coming soon.', 'Ignore this sig.', 'There\'s no surprise. :)', 'The next evolution is coming.', 'Knowledge is power.', 'You know me. You\'ll see me again.', 'The next generation.', 'Thanks Arta for starting it all!', 'Thanks Ersan for rescuing it!', 'Why are you reading this?');
+		$stringtodisplay = $strarray[$varnbr];
+	}
+	
+
+	$im     = imagecreatefromjpeg("matrix.jpg");
+	$orange = imagecolorallocate($im, 220, 210, 60);
+	$red =  imagecolorallocate($im, 255, 0, 0);
+	$limegreen = imagecolorallocate($im, 0, 255, 0);
+	$black = imagecolorallocate($im, 0, 0, 0);
+	
+	$y = 5;
+	$x = 5;
+	$firstoffset = 1;
+	$secondoffset = 1;
+	
+	if($stealth){
+		#imagestring($im, 3, $x+$firstoffset, $y+$firstoffset, $stringtodisplay, $black);
+		#imagestring($im, 3, $x-$secondoffset, $y-$secondoffset, $stringtodisplay, $black);
+		#imagestring($im, 3, $x, $y, $stringtodisplay, $limegreen);
+		
+		imagestringcentered($im,3,$stringtodisplay,$limegreen);
+	}
+	
+	$px     = (imagesx($im) - 7.5 * strlen($stringtodisplay)) / 2;
+	$txt = explode('|', $stringtodisplay);
+	if(!$stealth){
+		foreach ($txt as $text) {
+			imagestring($im, 3, $x+$firstoffset, $y+$firstoffset, $text, $black);
+			imagestring($im, 3, $x-$secondoffset, $y-$secondoffset, $text, $black);
+			imagestring($im, 3, $x, $y, $text, $limegreen);
+			$y += 15;
+		}
+		
+		$sqlquery = 'SELECT id,serveraddress FROM servers ORDER BY id ASC';
+		$serverarray = mysql_query($sqlquery);
+		
+		while($row = mysql_fetch_array($serverarray)){
+			$sid = $row['id'];
+			$saddress = $row['serveraddress'].': ';
+			imagestring($im, 3, $x+$firstoffset, $y+$firstoffset, $saddress, $black);
+			imagestring($im, 3, $x-$secondoffset, $y-$secondoffset, $saddress, $black);
+			imagestring($im, 3, $x, $y, $saddress, $limegreen);
+			if(checkserver($sid) == '1'){
+				$x = strlen($saddress) * 7;
+				imagestring($im, 3, $x+$firstoffset, $y+$firstoffset, 'Online', $black);
+				imagestring($im, 3, $x-$secondoffset, $y-$secondoffset, 'Online', $black);
+				imagestring($im, 3, $x, $y, 'Online', $limegreen);
+				$x = 5;
+				$y += 15;
+			} else {
+				$x = strlen($saddress) * 7;
+				imagestring($im, 3, $x+$firstoffset, $y+$firstoffset, 'Offline', $black);
+				imagestring($im, 3, $x-$secondoffset, $y-$secondoffset, 'Offline', $black);
+				imagestring($im, 3, $x, $y, 'Offline', $red);
+				$x = 5;
+				$y += 15;
+			}
+		} 
+	}
+	
+	imagejpeg($im);
+	imagedestroy($im);
+?>
\ No newline at end of file
diff --git a/images/stealth/matrix.jpg b/images/stealth/matrix.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..c05d6eb239ca76c0a79e2c25c5e261220fb1fa0d
GIT binary patch
diff --git a/images/stealth/matrix.psd b/images/stealth/matrix.psd
new file mode 100644
index 0000000000000000000000000000000000000000..65f06aea1a2e274728a020ee1df872728ff7d763
GIT binary patch
diff --git a/images/test.jpg b/images/test.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..265c3b981b87e315ee4f067eccdd92052d11f4d3
GIT binary patch
diff --git a/images/titleshader.psd b/images/titleshader.psd
new file mode 100644
index 0000000000000000000000000000000000000000..efe3e0f6d8a96f4501c8443049bc63d7efaa000f
GIT binary patch
diff --git a/images/vl_linkto.gif b/images/vl_linkto.gif
new file mode 100644
index 0000000000000000000000000000000000000000..72028673650586d83926cdbc736fa5a472b50aac
GIT binary patch
diff --git a/images/wait.gif b/images/wait.gif
new file mode 100644
index 0000000000000000000000000000000000000000..529e72f45a2395e2eddb0487edbe79b306c92c3a
GIT binary patch
diff --git a/images/wallpapers/blueiso.gif b/images/wallpapers/blueiso.gif
new file mode 100644
index 0000000000000000000000000000000000000000..ef184fffdcbeecf8a8054579f337322fcf14077a
GIT binary patch
diff --git a/images/wallpapers/bluesquares.jpg b/images/wallpapers/bluesquares.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..b5d8b2128ec33cf115331f30564c8c940d445769
GIT binary patch
diff --git a/images/wallpapers/grunge.jpg b/images/wallpapers/grunge.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..14fdee21771b35a4679157b6cf453fa7e734c278
GIT binary patch
diff --git a/images/wallpapers/hex.jpg b/images/wallpapers/hex.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..2222e0dc54b185c297ee0ec81228ac79cde9975f
GIT binary patch
diff --git a/images/wallpapers/snowflake.jpg b/images/wallpapers/snowflake.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..88284d86938d08816f5356fb3493eb5c8bc3597f
GIT binary patch
diff --git a/images/wallpapers/weirdblueness.jpg b/images/wallpapers/weirdblueness.jpg
new file mode 100644
index 0000000000000000000000000000000000000000..749103dd416a0d72ab285c9cb1274291acf67f96
GIT binary patch
diff --git a/images/warcrafticon.png b/images/warcrafticon.png
new file mode 100644
index 0000000000000000000000000000000000000000..0aa65f29043cfc58579911ae1286663efdcb52a4
GIT binary patch
diff --git a/index.php b/index.php
new file mode 100644
index 00000000..1f36ccab
--- /dev/null
+++ b/index.php
@@ -0,0 +1,141 @@
+<?
+	
+	# Include direct script access authorization variable and other variables
+	#-------------
+
+		$auth = "true";
+		$ip = $_SERVER['REMOTE_ADDR'];
+		$surpress = $_REQUEST['surpress'];
+		#die('This site has been frozen for maintenance.');
+		
+	# Set up environment
+	#-------------
+
+		header('Cache-Control: max-age=0, must-revalidate, no-cache, no-store');
+		if($_SERVER['SERVER_PORT']!=443 || $_SERVER['HTTP_HOST']!='bnetdocs.org') {
+			http_response_code(301);
+			header('Location: https://bnetdocs.org'.$_SERVER['REQUEST_URI']);
+			exit;
+		}
+
+	# Security
+	#-------------
+	
+		# Prevent spam POST submissions from external domains
+		
+		if($_POST){
+			if(!strpos($_SERVER['HTTP_REFERER'],'bnetdocs.org')){
+				exit();
+			}
+		}
+
+		# Stripslashes as shown on http://php.net/get_magic_quotes_gpc
+		# Used to prevent remote code injection via post, get, cookie. Also contributes to prevent remote code injection via SQL since input is cleaned prior to inserting to SQL DB.
+		if (get_magic_quotes_gpc()) {	
+		   function stripslashes_deep($value) {
+		       $value = is_array($value) ?
+		                   array_map('stripslashes_deep', $value) :
+		                   stripslashes($value);
+
+		       return $value;
+		   }
+
+		   $_POST = array_map('stripslashes_deep', $_POST);			# Clean POSTed data
+		   $_GET = array_map('stripslashes_deep', $_GET);					# Clean browser variables
+		   $_COOKIE = array_map('stripslashes_deep', $_COOKIE);	# Clean cookie variables
+		}
+		
+	# Include essential files
+	#-------------
+
+		require 'db.php';
+		require 'func.php';
+		
+	# Block out unwelcome visitors
+	#-------------
+
+		$userid = GetUserIDFromSession($ip);
+
+	# REQUEST: Get our requested page and set the variable
+	#-------------
+		
+		$op = $_REQUEST['op'];
+
+		# Prevent infinite loop bug, bug found by Jailout2000
+		if($op == 'index') $op = '';
+
+	# BLIZZARD: Is this Blizzard, and if so, log it
+	#-------------
+	
+		if(isblizzard($ip)){
+			#IP identified as potentially belonging to blizzard. Note it in log.
+			logthis(-1, 'Blizzard accessed page: ?'.$_SERVER['QUERY_STRING'], 'vip');
+		}
+
+	# SECURITY: Prevent remote inclusion injection
+	#-------------
+	
+		$legal_inc=getdir('.');
+
+		$i=0;
+		$allowfile='false';
+		while($i <= count($legal_inc)){
+			if($op.'.php'==$legal_inc[$i]) $allowfile='true';
+			$i++;
+		}
+		
+		if(!$op || trim($op) == '') $allowfile='true';
+		
+		if($allowfile=='false') exit();
+
+
+	# Surpress code is in place to prevent a HEADER ALREADY SENT error.
+	#-------------
+
+		ob_start('ob_gzhandler');
+		
+		if($surpress != "true"){
+			if($op == "") $op = "news";
+			include "bdif/header.dm";
+			if($userid){
+				# Update member last login
+				mysql_query("UPDATE sessions SET dtstamp=NOW() WHERE id='$userid'") or die("UpdateSession Function Error: ".mysql_error());
+				$msg = GetData($userid, 'msg');
+			} else {
+				$msg = $_REQUEST['msg'];
+				if($msg == '1'){
+					$msg = "You have been logged out.";
+				} elseif($msg == ''){
+					#disregard
+				} else {
+					$msg = "Nice try buddy!";
+				}
+			}
+			
+			if($msg){
+				$msg = '<center><font color=lime><b>'.$msg.'</b></font></center>';
+				WriteData($userid, 'msg', '');
+				echo "<br>";
+				DisplayDialogBox($msg);
+				echo "<br>";
+			}
+			$op=$op.".php";
+			include $op;
+			include "bdif/footer.dm";
+		} else {
+			if($op != ""){
+				$op=$op.".php";
+				include $op;
+			} else {
+				echo 'op empty.';
+			}
+		}
+
+		mysql_close();
+		ob_end_flush();
+		exit();
+
+	#-------------
+	# End of main script.
+	#-------------
+?>
diff --git a/js/standard.js b/js/standard.js
new file mode 100644
index 00000000..3b5d8efe
--- /dev/null
+++ b/js/standard.js
@@ -0,0 +1,162 @@
+
+
+
+
+
+/*
+     FILE ARCHIVED ON 22:40:13 Sep 10, 2011 AND RETRIEVED FROM THE
+     INTERNET ARCHIVE ON 8:41:31 Mar 24, 2014.
+     JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
+
+     ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
+     SECTION 108(a)(3)).
+*/
+	var pagecode = "";
+
+	function scheck(field) {
+		for (i = 0; i < field.length; i++) {
+			field[i].checked = false; 
+		}
+		alert('definitely being executed');
+		return true;
+	}
+	
+
+	function doonload(){
+		if(document.createStyleSheet) {
+			document.createStyleSheet('/web/20110910224013/http://bnetdocs.dementedminds.net/bdif/js_hide.css');
+		} else {
+			var styles = "@import url(' /web/20110910224013/http://bnetdocs.dementedminds.net/bdif/js_hide.css ');";
+			var newSS=document.createElement('link');
+			newSS.rel='stylesheet';
+			newSS.href='data:text/css,'+escape(styles);
+			document.getElementsByTagName("head")[0].appendChild(newSS);
+		}
+		
+		//document.cookie='hidden='+"";
+		var hidden=get_cookie("hidden");
+		var divid="";
+		if(hidden != ""){
+			// Process
+			var i=0
+			for (i=0; i<=hidden.length; i=i+2){
+				// Open Div's
+				divid = hidden.substr(i,2);
+				toggle_visibility(divid);
+				toggleHLS('x'+hidden.charAt(i+1)+'1');
+			}
+		}
+		
+
+	}
+	
+	function toggleHLS(id) {
+	    var e = document.getElementById(id);
+		if(e){
+			toggle_name(e);
+		}
+		return;
+	}
+	
+	function toggle_visibility(id) {
+        var e = document.getElementById(id);
+		if(e){
+	        if(e.style.display == 'block'){
+				e.style.display = 'none';
+				forgetid(id);
+	        } else {
+				e.style.display = 'block';
+				rememberid(id);
+			}
+		}
+		return;
+    }
+	
+	function rememberid(did){
+		var hidden=get_cookie("hidden");
+		var newmemory = '';
+		var alreadyadded = "false";
+		var did = did + '';
+		hidden = hidden + '';
+		if(hidden != ""){
+			if(hidden.search(did) < 0){ 
+				document.cookie='hidden='+hidden+did;
+			}
+		} else {
+			document.cookie='hidden='+did;
+		}
+	}
+	
+	function forgetid(did){
+		var hidden=get_cookie("hidden");
+		var newmemory = '';
+		var did = did + '';
+		newmemory = hidden.replace(did,'');
+		document.cookie='hidden='+newmemory;
+	}
+	
+	//Get cookie routine by Shelley Powers 
+	function get_cookie(Name) {
+		var search = Name + "="
+		var returnvalue = "";
+		if (document.cookie.length > 0) {
+			offset = document.cookie.indexOf(search)
+			// if cookie exists
+			if (offset != -1) { 
+				offset += search.length
+				// set index of beginning of value
+				end = document.cookie.indexOf(";", offset);
+				// set index of end of cookie value
+				if (end == -1) end = document.cookie.length;
+				returnvalue=unescape(document.cookie.substring(offset, end))
+			}
+		}
+		return returnvalue;
+	}
+	
+	function toggle_name(objLink){
+		if(objLink.innerHTML == "+")
+			objLink.innerHTML = "-";
+		else
+			objLink.innerHTML = "+";
+	}
+	
+	function validate_required(field,alerttxt){
+		with (field){
+			if (value==null||value==""){
+				alert(alerttxt);
+				return false
+			} else {
+				return true
+			}
+		}
+	}
+	
+	function validate_form(thisform){
+		with (thisform){
+			if (validate_required(username,"Username must be filled out!")==false){
+				username.focus();
+				return false
+			}
+			if (validate_required(password,"Password must be filled out!")==false){
+				password.focus();
+				return false
+			}
+
+		}
+	}
+	
+	function showimage(){
+		if (!document.images) return
+		var picdir = '/images/newsicon/';
+		document.images.thepic.src = picdir + document.thenews.pictureselector.options[document.thenews.pictureselector.selectedIndex].value + 'icon.png';
+	}
+	
+	function confimdelete(){
+		var confirmation = confirm ("Please confirm deletion.");
+		if (confirmation){
+			return true;
+		} else {
+			return false;
+		}
+	}
\ No newline at end of file
diff --git a/left.php b/left.php
new file mode 100644
index 00000000..1b38715a
--- /dev/null
+++ b/left.php
@@ -0,0 +1,17 @@
+<script language="JavaScript">
+
+<!--
+
+function HideFrame()
+
+{
+
+top.FrameName.cols = "0,*";
+
+}
+
+-->
+
+</script>
+
+<a href="#" onClick="javascript:HideFrame()" target="_self">Hide This Frame!</a>
\ No newline at end of file
diff --git a/legalism.php b/legalism.php
new file mode 100644
index 00000000..0b4621ae
--- /dev/null
+++ b/legalism.php
@@ -0,0 +1,308 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+
+	?>
+		<div id="container">
+		<div id="main2">
+		<h2>Legalistic Limbo: Eww.</h2>
+		<blockquote>
+		<br>
+
+<div id="author">Terms of Service</div>
+<br>We run a service called 
+<a href="http://www.bnetdocs.org">BNETDocs</a> and would <b>love</b> for 
+you to use it. Our service is free. Be responsible in what you contribute. In particular, 
+make sure that none of the prohibited items listed below appear on your contributions or get 
+linked to from your site (things like spam, viruses, hate content, porn, etc).  Please make 
+sure you read through the list and the rest of the terms and agree with them before you get 
+started.<br>
+
+<br>The following terms and conditions govern all use of the BNETDocs website and 
+all content, services and products available at or through the website, including, but not 
+limited to, the documentation, services, hosting, and so forth (taken together, the Domain). 
+The Domain is owned (with above applicable exclusions) and operated by <a href="http://www.doncullen.net">Don Cullen</a>
+(hereafter "DC"). The Domain is offered subject to your acceptance without modification of 
+all of the terms and conditions contained herein and all other operating rules, policies and 
+procedures that may be published from time to time on this Site by DC (collectively, the Terms of 
+Service ("TOS")).<br>
+
+<br>Please read the TOS carefully before accessing or using the Domain. By accessing or 
+using any part of the web site, you agree to become bound by the terms and conditions of this 
+agreement. If you do not agree to all the terms and conditions of this agreement, then you may 
+not access the website or use any services. If these terms and conditions are considered an offer 
+by DC or anyone else, acceptance is expressively limited to these terms.<br>
+
+<ol>
+<li><b>Your BNETDocs account.</b> If you contribute content to BNETDocs, 
+you are responsible for maintaining the security of your account, and you are fully 
+responsible for all activities that occur under the account and any other actions taken in 
+connection with the site. You must not contribute content in a misleading or unlawful manner, 
+including in a manner intended to impersonate the name or reputation of others, and DC may change or 
+remove any content that it considers inappropriate or unlawful, or otherwise likely to cause DC 
+liability. You must immediately notify DC of any unauthorized uses of your account or any other 
+breaches of security. DC will not be liable for any acts or omissions by you, including any damages 
+of any kind incurred as a result of such acts or omissions.<br><br></li>
+
+<li><b>Responsibility of Contributors.</b> If you post any sort of data on the Domain, or 
+otherwise make (or allow any third party to make) material available by means of the Domain 
+(any such material, also known as "Data"), you are entirely responsible for the content of, and any 
+harm resulting from, that Data. That is the case regardless of whether the Content in question 
+constitutes links, text, graphics, an audio file, or computer software. By making the Data available, 
+you represent and warrant that:<br><br>
+
+<ul>
+<li>the downloading, copying and use of the Data will not infringe the proprietary rights, 
+including but not limited to the copyright, patent, trademark or trade secret rights, of any third 
+party;</li><br>
+
+<li>if your employer has rights to intellectual property you create or contribute, you have either 
+(i) received permission from your employer to post or make available the Data, including but not 
+limited to any software, or (ii) secured from your employer a waiver as to all rights in or to the 
+Data;</li><br>
+
+<li>you have fully complied with any third-party licenses relating to the Data, and have done all 
+things necessary to successfully pass through to end users any required terms;</li><br>
+
+<li>the Data does not contain or install or link to any viruses, worms, malware, Trojan horses or 
+other harmful or destructive content;</li><br>
+
+<li id="important">the Data does not contain or install or link to any software which enables one to cheat in games,
+or flood channels, or spam, or anything else determined to be a violation of Blizzard's TOS.</li><br>
+
+<li>the Data is not spam, and does not contain unethical or unwanted commercial 
+content designed to drive traffic to third party sites or boost the search engine rankings of third 
+party sites, or to further unlawful acts (such as phishing) or mislead recipients as to the source 
+of the material (such as spoofing);</li><br>
+
+<li>the Data is not obscene, libelous, hateful or racially or ethnically objectionable, and does 
+not violate the privacy or publicity rights of any third party; and</li><br>
+
+<li>you have, in the case of Data that includes computer code, accurately categorized and/or 
+described the type, nature, uses and effects of the materials, whether requested to do so by 
+DC or otherwise.</li>
+</ul>
+<br>By submitting Data to DC for inclusion on BNETDocs, you grant DC a global, royalty-free, 
+and non-exclusive license to reproduce, modify, adapt and publish the Data solely for the purpose 
+of displaying, distributing and promoting the Domain and DC. If you delete Data, DC will use 
+reasonable efforts to remove it from the Website as seen neccessary, but you acknowledge that 
+caching or references to the Data may not be made immediately unavailable.<br>
+
+<br>Without limiting any of those representations or warranties, DC has the right (though not the 
+obligation) to, at DC's sole discretion: (i) deny or remove any data that, in DC's reasonable 
+opinion, violates any DC policy or is in any way harmful or objectionable, or (ii) terminate or deny 
+access to and use of the Domain to any individual or entity for any reason, in DC's sole discretion. 
+DC will have no obligation to provide compensation of any sort.<br>
+<br></li>
+
+<li><b>Responsibility of Domain Visitors.</b> DC has not reviewed, and cannot review, all of the 
+material, including computer software, posted to the Website, and cannot therefore be responsible 
+for that material�s content, use or effects. By operating the Domain, DC does not represent or 
+imply that it endorses the material there posted, or that it believes such material to be accurate, 
+useful or non-harmful. You are responsible for taking precautions as necessary to protect yourself 
+and your computer systems from viruses, worms, and other harmful or destructive content. The Domain 
+may contain content that is offensive, indecent, or otherwise objectionable, as well as content 
+containing technical inaccuracies, typographical mistakes, and other errors. The Website may also 
+contain material that violates the privacy or publicity rights, or infringes the intellectual 
+property and other proprietary rights, of third parties, or the downloading, copying or use of which 
+is subject to additional terms and conditions, stated or unstated. DC disclaims any responsibility 
+for any harm resulting from the use by visitors of the Domain, or from any downloading by those 
+visitors of Data posted. If any inappropriate Data is reported, we are not obiligated to, but however 
+will endeavor to do our best to take action on the offending Data.<br><br></li>
+
+<li><b>Content Posted on Other Websites.</b> We have not reviewed, and cannot review, all of the 
+material, including computer software, made available through the websites and webpages to which 
+BNETDocs links, and that link to BNETDocs. DC does not have any control over those 
+non-DC websites and webpages, and is not responsible for their contents or their use. By linking to 
+a non-DC website or webpage, DC does not represent or imply that it endorses such website or 
+webpage. You are responsible for taking precautions as necessary to protect yourself and your 
+computer systems from viruses, worms, and other harmful or destructive content. DC disclaims any 
+responsibility for any harm resulting from your use of non-DC websites and webpages.<br><br></li>
+
+<li><b>Copyright Infringement and DCCA Policy.</b> As DC asks others to respect its intellectual 
+property rights, it respects the intellectual property rights of others. If you believe that 
+material located on or linked to by BNETDocs violates your copyright, you are encouraged to 
+notify DC in accordance with Digital Millennium Copyright Act ("DCCA"). DC will respond to all such 
+notices, including as required or appropriate by removing the infringing material or disabling all 
+links to the infringing material. In the case of a visitor who may infringe or repeatedly infringes 
+the copyrights or other intellectual property rights of DC or others, DC may, in its discretion, 
+terminate or deny access to and use of the Website. In the case of such termination, DC 
+will have no obligation to provide a compensation of any sort.<br><br></li>
+
+<li><b>Intellectual Property.</b> The TOS does not transfer from DC to you any DC or third party 
+intellectual property, and all right, title and interest in and to such property will remain (as 
+between the parties) solely with DC.  DC, BNETDocs, and all other service marks, graphics and 
+logos used in connection with DC, BNETDocs, or the Domain are copyrighted to DC. Other 
+trademarks, service marks, graphics and logos used in connection with the DC may be the trademarks 
+of other third parties. Your use of the Domain grants you no right or license to reproduce or 
+otherwise use any DC or third-party trademarks.<br><br></li>
+
+<li><b>Changes.  </b>DC reserves the right, at its sole discretion, to modify or replace 
+any part of the TOS.  It is your responsibility to check the TOS periodically for changes. Your 
+continued use of or access to the Domain following the posting of any changes to the TOS constitutes 
+acceptance of those changes.  DC may also, in the future, offer new services and/or features through 
+the DC (including, the release of new tools and resources).  Such new features and/or services shall 
+be subject to the terms and conditions of the TOS.<br><br></li>
+
+<li><b>Termination.  </b>DC may terminate your access to all or any part of the Domain at any time, 
+with or without cause, with or without notice, effective immediately.  If you wish to terminate this 
+agreement with our TOS, or your DC account (if you have one), your BNETDocs (if you have one),
+you may simply discontinue accessing the Domain.  All contributions upon termination automatically
+become the property of DC.  Notwithstanding the foregoing, if you have a BNETDocs account, 
+such account can only be terminated by DC if you contact an administrator.  All provisions of the 
+TOS which by their nature should survive termination shall survive termination, including, without 
+limitation, ownership provisions, warranty disclaimers, indemnity and limitations of liability. <br><br></li>
+
+<li id="important"><b>Disclaimer of Warranties.</b> The Website is provided "as is". DC and 
+its suppliers and licensors hereby disclaim all warranties of any kind, express or implied, 
+including, without limitation, the warranties of merchantability, fitness for a particular purpose 
+and non-infringement. Neither DC nor its suppliers and licensors, makes any warranty that 
+the Website will be error free or that access thereto will be continuous or uninterrupted.  You 
+understand that you download from, or otherwise obtain content or services through, the Domain at 
+your own discretion and risk.</li><br>
+
+<li id="important"><b>Limitation of Liability.</b> In no event will DC, or its suppliers or 
+licensors, be liable with respect to any subject matter of this agreement under any contract, 
+negligence, strict liability or other legal or equitable theory for: (i) any special, incidental or 
+consequential damages; (ii) the cost of procurement or substitute products or services; (iii) for 
+interruption of use or loss or corruption of data. DC shall have no liability for any failure or 
+delay due to matters beyond their reasonable control. The foregoing shall not apply to the extent 
+prohibited by applicable law.</li><br>
+
+<li><b>General Representation and Warranty.</b> You represent and warrant that (i) your use of the 
+Domain will be in strict accordance with the DC TOS and with all applicable laws and regulations 
+(including without limitation any local laws or regulations in your country, state, city, or other 
+governmental area, regarding online conduct and acceptable content, and including all applicable 
+laws regarding the transmission of technical data exported from the United States or the country in 
+which you reside) and (ii) your use of the Domain will not infringe or misappropriate the 
+intellectual property rights of any third party.<br><br></li>
+
+<li><b>Indemnification.</b> You agree to indemnify and hold unliable DC, its contractors, and its 
+licensors, and their respective directors, officers, employees and agents from and against any and 
+all claims and expenses, related or unrelated, including attorneys� fees, arising out of your use 
+of the Domain, including but not limited to out of your violation the TOS.<br><br></li>
+
+<li><b>Miscellaneous.</b> The TOS constitutes the entire agreement between DC and you concerning 
+the subject matter hereof, and they may only be modified by a written amendment signed by an 
+authorized executive of DC, or by the posting by DC of a revised version. Except to the extent 
+applicable law, if any, provides otherwise, the TOS, any access to or use of the Domain will be 
+governed by the laws of the state of California, U.S.A., excluding its conflict of law provisions, 
+and the proper venue for any disputes arising out of or relating to any of the same will be the 
+state and federal courts located in Alameda Country, California.  Except for claims for injunctive 
+or equitable relief or claims regarding intellectual property rights (which may be brought in any 
+competent court without the posting of a bond), any dispute arising under the TOS shall be 
+finally settled in accordance with the Comprehensive Arbitration Rules of the Judicial Arbitration 
+and Mediation Service, Inc. ("JAMS") by three arbitrators appointed in accordance with such Rules.  
+The arbitration shall take place in Fremont, California, in the English language and the arbitral 
+decision may be enforced in any court.  The prevailing party in any action or proceeding to enforce 
+the TOS shall be entitled to costs and attorneys� fees, as well as compensatory damages.  If any 
+part of this Agreement is held invalid or unenforceable, that part will be construed to reflect the 
+parties� original intent, and the remaining portions will remain in full force and effect. A waiver 
+by either party of any term or condition of the TOS or any breach thereof, in any one instance, will 
+not waive such term or condition or any subsequent breach thereof. You may assign your rights under 
+the TOS to any party that consents to, and agrees to be bound by, its terms and conditions; 
+DC may assign its rights under the TOS without condition. The TOS will be binding upon and will 
+inure to the benefit of the parties, their successors and permitted assigns.<br><br></li>
+<br>
+<div id="author">Additional Disclaimers</div>
+<br>
+Blizzard and including but not limited to any other affilated/non-affilated 
+parties will not be held liable for any content content on this website or for 
+any of the content. Nor is the ISP/webhost responsible. Please also keep in 
+mind that while this site contains information that may or may not pertain to
+reverse-engineering, reverse-engineering has been deemed by Blizzard to be a
+violation of their TOS.<br>
+<br>
+We reserve the right to change this legal disclaimer without notice. By 
+choosing to continue to visit this site, you thereby release us from any
+further obligations, liabilities, and so forth.<br>
+<br>
+<div id="author">Copyrights</div>
+<br>
+<a href="http://www.battle.net/">Battle.net&reg;</a><br>
+&copy;1996 - 2002 Blizzard Entertainment, Inc. All rights reserved. Battle.net and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com/blizzclassic/">Blackthorne&trade;</a><br>
+&copy;Blizzard Entertainment, Inc. All rights reserved. Blackthorne is a trademark and Blizzard Entertainment is a trademark or registered trademark of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com"><b>Blizzard Entertainment&reg;</b></a><br>
+
+Blizzard Entertainment is a trademark or registered trademark of Blizzard Entertainment, Inc. in the U.S. and/or other countries. All rights reserved. 
+<br><br>
+
+<b>Blizzard North&trade;</b><br>
+Blizzard North is a trademark of Blizzard Entertainment, Inc. in the U.S. and/or other countries. All rights reserved. 
+<br><br>
+
+<a href="http://www.blizzard.com/diablo/"><b>Diablo&reg;</b></a><br>
+&copy;1996 Blizzard Entertainment, Inc. All rights reserved. Diablo and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com/diablo2/"><b>Diablo&reg; II</b></a><br>
+&copy;2000 Blizzard Entertainment, Inc. All rights reserved. Diablo and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com/diablo2exp/"><b>Diablo&reg; II: Lord of Destruction&trade;</b></a><br>
+&copy;2001 Blizzard Entertainment, Inc. All rights reserved. Lord of Destruction is a trademark and Diablo and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com/blizzclassic/">Rock-N-Roll Racing&trade;</a><br>
+&copy; Blizzard Entertainment, Inc.. All rights reserved. Rock-N-Roll Racing is a trademark and Blizzard Entertainment is a trademark or registered trademark of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com/starcraft/"><b>StarCraft&reg;</b></a><br>
+&copy;1998 Blizzard Entertainment, Inc. All rights reserved. StarCraft and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com/broodwar/"><b>StarCraft&reg;: Brood War&reg;</b></a><br>
+
+&copy;1998 Blizzard Entertainment, Inc. All rights reserved. StarCraft, Brood War and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com/ghost/">StarCraft: Ghost&trade;</a><br>
+&copy; StarCraft: Ghost is a trademark and StarCraft and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.  
+<br><br>
+
+<a href="http://www.blizzard.com/blizzclassic/">The Lost Vikings&trade;</a><br>
+&copy; Blizzard Entertainment, Inc. All rights reserved. The Lost Vikings is a trademark and Blizzard Entertainment is a trademark or registered trademark of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com/war1/"><b>Warcraft&reg;: Orcs &amp; Humans&trade;</b></a><br>
+
+&copy;1994 Blizzard Entertainment, Inc. All rights reserved. Orcs &amp; Humans is a trademark and Warcraft and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com/war2bne/index.shtml#war2x"><b>Warcraft&reg; II: Beyond the Dark Portal&trade;</b></a><br>
+&copy;1996 Blizzard Entertainment, Inc. All rights reserved. Beyond the Dark Portal is a trademark and Warcraft and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com/war2bne/index.shtml#war2"><b>Warcraft&reg; II: Tides of Darkness&trade;</b></a><br>
+&copy;1995 Blizzard Entertainment, Inc. All rights reserved. Tides of Darkness is a trademark and Warcraft and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com/war3/"><b>Warcraft&reg; III: Reign of Chaos&trade;</b></a><br>
+
+&copy;2002 Blizzard Entertainment, Inc.. All rights reserved. Reign of Chaos is a trademark and Warcraft and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries. 
+<br><br>
+
+<a href="http://www.blizzard.com/wow/">World of Warcraft&trade;</a><br>
+World of Warcraft and Blizzard Entertainment are trademarks or registered trademarks of Blizzard Entertainment, Inc. in the U.S. and/or other countries.
+<br><br>
+
+<a href="http://bnetdocs.valhallalegends.com">BNETDocs&copy;</a>, <a href="http://www.bnetdocs.org">BNETDocs &copy;</a><br>
+The original BNETDocs site is copyrighted to Don Cullen. BNETDocs is copyrighted to Don Cullen AKA Kyro. BNETDocs is copyrighted under a <a href="http://creativecommons.org/licenses/by-nc-sa/3.0/">Creative Commons Attribution-NonCommercial-ShareAlike 3.0 License</a>. <a rel="license" href="http://creativecommons.org/licenses/by-nc-sa/3.0/"><img alt="Creative Commons License" style="border-width:0" src="http://i.creativecommons.org/l/by-nc-sa/3.0/80x15.png" /></a>
+<br><br>
+
+<b>All other trademarks are the property of their respective owners.</b>
+	<?
+	
+	?><br></blockquote></div></div><?
+
+?>
diff --git a/login.php b/login.php
new file mode 100644
index 00000000..91f0ad61
--- /dev/null
+++ b/login.php
@@ -0,0 +1,46 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth, $ip;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+	
+	$username == sanitize(trim($_POST['username']));
+	$password == sanitize(trim($_POST['password']));
+	
+	# Login disabled due to admin account somehow being hijacked
+	$ret = "Login has been disabled due to system being under extended maintenance.";
+	error($ret);
+	return;
+	
+	if($username == ""|| $password == ""){
+		error('Missing username or password.');
+	} else {
+		$rememberme = sanitize($_POST['rememberme']);
+		$time = time();
+		$loginresults = login($username,$password, "yes", $ip);
+		if ($loginresults == "pass"){
+			$userid = GetUserIDFromSession($ip);
+			if(CheckBanned($ip, 'total')){
+				logthis($userid, 'Attempted to enter the site, attempt blocked. '.$ip.' is ipbanned.', 'ipban');
+				die('We\'re experiencing problems. Please check back later. Thank you.');
+			}
+			if(FieldVerify('dbid', 'banned', $userid)){
+				#Ban evasion! Add new ip to list!
+				logthis($userid, 'IPBan evasion detected. Attempted to enter the site, attempt blocked. New IP address of '.$ip.' is now ipbanned.', 'ipban');
+				mysql_query("INSERT INTO `banned` (dbid, ip, bantype) VALUES ($userid, '$ip', 'total')") or die("Login Block Error: ".mysql_error());
+				die('We\'re experiencing problems. Please check back later. Thank you.');
+			}
+			if($rememberme == 'yes'){
+				mysql_query("UPDATE `sessions` SET notimelimit=1 WHERE `id`=$userid") or die("Session Error: ".mysql_error());		
+			}
+			#logthis($userid, 'logged in.', 'session');
+			WriteData($userid, 'secured', 'true');
+			redirect("/"); // Redirect correct member
+		} else {
+			error($loginresults);
+		}
+	}
+?>
diff --git a/logout.php b/logout.php
new file mode 100644
index 00000000..6ee91ab2
--- /dev/null
+++ b/logout.php
@@ -0,0 +1,19 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth, $ip, $userid;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+	
+	if(!$userid){
+		logthis($userid, 'Logout attempted without a local session. Attempt ignored.', 'hack');
+		blockhack();
+	}
+	
+	#log 'em out
+	KillSession($userid);
+	#logthis($userid, 'logged out.', 'session');
+	redirect('/?msg=1');
+?>
\ No newline at end of file
diff --git a/logsrss.php b/logsrss.php
new file mode 100644
index 00000000..6631b61c
--- /dev/null
+++ b/logsrss.php
@@ -0,0 +1,156 @@
+<?
+	################################
+	##	RSS Feed Generator for logs   ##
+	################################
+	
+	###########################################################
+	# ADDED 2014-04-06 BY JAILOUT2000 FOR FORCED SSL SECURITY #
+	###########################################################
+	if($_SERVER['SERVER_PORT']!=443 || $_SERVER['HTTP_HOST']!='bnetdocs.org') {
+		http_response_code(301);
+		header('Location: https://bnetdocs.org'.$_SERVER['REQUEST_URI']);
+		exit;
+	}
+	###########################################################
+	#                                                         #
+	###########################################################
+	
+	# \n = newline, \t = tab
+	
+	function CropSentence ($strText, $intLength, $strTrail) {
+		$wsCount = 0;
+		$intTempSize = 0;
+		$intTotalLen = 0;
+		$intLength = $intLength - strlen($strTrail);
+		$strTemp = "";
+
+		if (strlen($strText) > $intLength) {
+			$arrTemp = explode(" ", $strText);
+			foreach ($arrTemp as $x) {
+				if (strlen($strTemp) <= $intLength) $strTemp .= " " . $x;
+			}
+			$CropSentence = $strTemp . $strTrail;
+		} else {
+			$CropSentence = $strText;
+		}
+
+		return $CropSentence;
+	} 
+	
+	function replaceOnce($search, $replace, $content){
+	    $pos = strpos($content, $search) + 1;
+		$pos = strpos($content, $search, $pos);
+	    if ($pos === false) { 
+			return $content; 
+		} else { 
+			return substr($content, 0, $pos) . $replace . substr($content, $pos+strlen($search)); 
+		}
+	}
+
+	$auth = 'true';
+	include 'func.php';
+	include 'db.php';
+
+	###########################################################
+	# ADDED 2014-03-25 BY JAILOUT2000 FOR SECURITY HOLE PATCH #
+	###########################################################
+	$_AUTH_USER = sanitize($_SERVER['PHP_AUTH_USER']);
+	$_AUTH_PASS = sanitize($_SERVER['PHP_AUTH_PW']);
+	$_AUTH_QUERY = 'SELECT `password`, `levelofaccess` FROM `users` WHERE `username` = \''
+                     . mysql_real_escape_string($_AUTH_USER) . '\' LIMIT 1;';
+	$_AUTH_RESULT = mysql_query($_AUTH_QUERY);
+	$_AUTH_PASS_1 = strtolower(md5($_AUTH_PASS));
+	$_AUTH_PASS_2 = 'error'; // anything md5 will never match this since the string length is different
+	$_AUTH_ACCESS_LEVEL = 0;
+	if ($_AUTH_RESULT) {
+		if (mysql_num_rows($_AUTH_RESULT) == 1) {
+			$_AUTH_ROW = mysql_fetch_row($_AUTH_RESULT);
+			$_AUTH_PASS_2 = strtolower($_AUTH_ROW[0]);
+			$_AUTH_ACCESS_LEVEL = $_AUTH_ROW[1];
+		}
+	}
+	if ($_AUTH_PASS_1 != $_AUTH_PASS_2 || $_AUTH_ACCESS_LEVEL < 3) {
+		header('HTTP/1.0 401 Unauthorized');
+		header('WWW-Authenticate: Basic realm="BNETDocs Logs"');
+		header('Content-Type: application/xml;charset=utf-8');
+		die("<?xml version=\"1.0\" encoding=\"utf-8\"?><error>Access denied. Administrator login required.</error>");
+	}
+	/*$userid = GetUserIDFromSession($_SERVER['REMOTE_ADDR']);
+	if(rank($userid) < 3) {
+		http_response_code(401);
+		header('Content-Type: application/xml;charset=utf-8');
+		die('<?xml version="1.0" encoding="utf-8"?><error>Access denied. Administrator login required.</error>');
+	}*/
+	###########################################################
+	#                                                         #
+	###########################################################
+	
+	header("Content-Type: application/xml; charset=utf-8");
+	
+	echo '<?xml version="1.0" encoding="utf-8"?>';
+	echo '<rss version="2.0">';
+	echo '<channel>';
+	echo '<title>BNETDocs Logs</title>';
+	echo '<link>http://www.bnetdocs.org/?op=viewlogs</link>';
+	echo '<description>Summarized logs of user activities on BNETDocs</description>';
+	echo '<language>en-us</language>';
+	echo '<docs>http://blogs.law.harvard.edu/tech/rss</docs>';
+	echo '<copyright>Site scripts and design copyrights reserved to Don Cullen. Contents copyrighted to Blizzard and their parent corporation, Vivendi. Copyright infringements will be prosecuted to the fullest extent allowable by law. Please view our legal disclaimer and terms of service.</copyright>';
+
+	$privatestring = "WHERE eventtype != 'CONFIDENTAL' ";
+	$privatestring .= " group by CONCAT(user,datetime,eventtype) ";
+	$consolidate = '&consolidate=true';
+	
+    $limit          = 25;               
+    $query_count    = "SELECT * FROM logs $privatestring";
+    $result_count   = mysql_query($query_count);
+    $totalrows      = mysql_num_rows($result_count); 
+	
+	$query  = "SELECT * FROM logs $privatestring ORDER BY id desc LIMIT $limit";
+	
+    $result = mysql_query($query) or die("Error: " . mysql_error()); 
+
+	while($row = mysql_fetch_array($result)){
+	
+		echo '<item>';
+		
+		$summary = CropSentence(strip_tags(codify($row['event'], true) ), 500, '...');
+		
+		if($row['eventtype'] == 'docedit') $row['event'] = 'edited documents.';
+		if($row['eventtype'] == 'newsdelete') $row['event'] = 'deleted news posts.';
+		if($row['eventtype'] == 'newsedit') $row['event'] = 'edited news posts.';
+		if($row['eventtype'] == 'newspost') $row['event'] = 'submitted news posts.';
+		if($row['eventtype'] == 'pktadd') $row['event'] = 'added packets.';
+		if($row['eventtype'] == 'pktedit') $row['event'] = 'edited packets.';
+		if($row['eventtype'] == 'pktdel') $row['event'] = 'deleted packets.';
+		if($row['eventtype'] == 'registration') $row['event'] = 'registered to be a member.';
+		if($row['eventtype'] == 'commentedit') $row['event'] = 'edited comments.';
+		if($row['eventtype'] == 'commentadd') $row['event'] = 'posted comments.';
+		if($row['eventtype'] == 'commentdel') $row['event'] = 'deleted comments.';
+		
+		$content = CropSentence(strip_tags(codify(str_ireplace("\'", "'", $row['event']), true) ), 500, '...');
+		$summary = CropSentence(strip_tags(codify(str_ireplace("\'", "'", $summary), true) ), 500, '...');
+		
+		$initator = $row['user'];
+		
+		$content = ucfirst(whoisid($initator)).' '.lcfirst($content);
+		
+		$timestamp = date("D, d M Y H:i:s", strtotime(substr($row['datetime'], strpos($row['datetime'], ',') + 2))).' PST';
+		$timestamp = substr($row['datetime'], strpos($row['datetime'], ',') + 2).' PST';
+		$timestamp = replaceOnce(' ', ', ', $timestamp);
+		$timestamp = date("D, d M Y H:i:s", strtotime($timestamp)).' PST';
+
+		echo '<title>'.htmlspecialchars ($content, ENT_QUOTES).'</title>';
+		echo '<link>http://www.bnetdocs.org/?op=viewlogs&amp;id='.$row['id'].'</link>';
+		echo '<guid>http://www.bnetdocs.org/?op=viewlogs&amp;id='.$row['id'].'</guid>';
+		echo '<description>'.htmlspecialchars ($summary, ENT_QUOTES).' Activity logged at: '.$row['datetime'].'</description>';
+		echo '<pubDate>'.$timestamp.'</pubDate>';
+		echo '</item>';
+	
+    }
+
+    mysql_free_result($result);
+
+	echo '</channel>';
+	echo '</rss>';
+?>
diff --git a/menu.php b/menu.php
new file mode 100644
index 00000000..c369cbb8
--- /dev/null
+++ b/menu.php
@@ -0,0 +1,6 @@
+<h3>What is a Lightbox?</h3>
+
+<p class="highlight">Lightbox is an unobtrusive script used to overlay content on 
+the current page. Because it places content above your current page, it frees you from 
+the constraints of the layout, particularly column widths.</p>
+<a href="#" class="lbAction" rel="deactivate">Close Lightbox.</a>
\ No newline at end of file
diff --git a/news.php b/news.php
new file mode 100644
index 00000000..7629200e
--- /dev/null
+++ b/news.php
@@ -0,0 +1,193 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth, $ie;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+	
+	$mode = sanitize($_GET['mode']);
+	$newsicon = sanitize(strtoupper($_POST['pictureselector']));
+	$title = sanitize($_POST['subject']);
+	$content = sanitize($_POST['text']);
+	
+	if(!$_POST){
+		$title = 'Insert news title here.';
+		$content = 'Insert news here.';
+		if($mode == 'all'){
+			$sqlquery = 'SELECT * FROM news ORDER BY id DESC';
+			$newsarray = mysql_query($sqlquery);
+			while($row = mysql_fetch_array($newsarray)){
+				$nid = $row['id'];
+				$author = $row['poster'];
+				$rank = rank($author);
+				if($rank){
+					$rank = '('.rankname($rank).')';
+				} else {
+					$rank = '';
+				}
+				$dtstamp = $row['dtstamp'];
+				$postdate = date('F j, Y g:i T', strtotime($dtstamp));
+				$icon = strtolower($row['topictype']);
+				$title = $row['subject'];
+				$content = codify($row['content']);
+				include 'bdif/newspost.dm';
+			}
+		} elseif($mode == 'edit'){
+			$nid = $_GET['nid'];
+			$pid = GetInfo("news", "id", $nid, "poster");
+			if($userid != $pid && $userid != 1){
+				logthis($userid, 'Illegally attempted to edit a news post NID('.$nid.'). Attempt blocked.', 'hack');
+				blockhack();
+			}
+			$sqlquery = 'SELECT * FROM news WHERE id='.$nid.' ORDER BY id DESC LIMIT 1';
+			$newsarray = mysql_query($sqlquery);
+			$row = mysql_fetch_array($newsarray);
+			$author = $row['poster'];
+			$rank = rank($author);
+			if($rank){
+				$rank = '('.rankname($rank).')';
+			} else {
+				$rank = '';
+			}
+			$dtstamp = $row['dtstamp'];
+			$postdate = date('F j, Y g:i T', strtotime($dtstamp));
+			$icon = strtolower($row['topictype']);
+			$title = $row['subject'];
+			$content = $row['content'];
+			$topictype = strtolower($row['topictype']);
+			switch ($topictype) {
+				case 'bnetdocs':
+				    $bdselected = 'selected';
+				    break;
+				case 'bnet':
+				    $bnselected = 'selected';
+				    break;
+				case 'bnls':
+				    $bnlsselected = 'selected';
+				    break;
+				case 'starcraft':
+					$scselected = 'selected';
+					break;
+				case 'warcraft':
+					$wcselected = 'selected';
+					break;
+				case 'diablo':
+					$dselected = 'selected';
+					break;	
+			}
+			$edit = '&edit=true&nid='.$nid;
+			include 'bdif/newssubmission.dm'; 
+		} elseif($mode == 'delete'){
+			$nid = $_GET['nid'];
+			if(rank($userid) > 2){
+				$pid = GetInfo("news", "id", $nid, "poster");
+				$title = GetInfo("news", "id", $nid, "subject");
+				$content = GetInfo("news", "id", $nid, "content");
+				$nid = $_GET['nid'];
+				if((rank($userid) > 4) || ($userid == $pid)){
+					$sql = "DELETE FROM news WHERE id=\"$nid\"";
+					$sqlresults = mysql_query($sql) or die('News deletion failure: '.mysql_error());
+					logthis($userid, 'Deleted a news post containing the title of "'.$title.'" and the contents of "'.$content.'".', 'newsdelete');
+					WriteData($userid, 'msg', 'The news post has been deleted.');
+					redirect('/');
+				} else {
+					logthis($userid, 'Illegally attempted to delete a news post NID('.$nid.'). Attempt blocked.', 'hack');
+					blockhack();
+				}
+			} else {
+				logthis($userid, 'Illegally attempted to delete a news post NID('.$nid.'). Attempt blocked.', 'hack');
+				blockhack();
+			}
+		} elseif($mode == 'post'){
+			if(rank($userid) > 2){
+				$rank = rank($userid);
+				if($rank){
+					$rank = '('.rankname($rank).')';
+				} else {
+					$rank = '';
+				}
+				$postdate = date('F j, Y g:i T');
+				include 'bdif/newssubmission.dm';
+			} else {
+				logthis($userid, 'Illegally attempted to post news. Attempt blocked.', 'hack');
+				blockhack();
+			}
+		} else {
+			$rnid = $_REQUEST['nid'];
+			if($rnid) {
+				$sqlquery = 'SELECT * FROM news where id='.$rnid;
+			}  else {
+				$sqlquery = 'SELECT * FROM news ORDER BY id DESC LIMIT 3';
+			}
+			$newsarray = mysql_query($sqlquery);
+			while($row = mysql_fetch_array($newsarray)){
+				$nid = $row['id'];
+				$author = $row['poster'];
+				$rank = rank($author);
+				if($rank){
+					$rank = '('.rankname($rank).')';
+				} else {
+					$rank = '';
+				}
+				$dtstamp = $row['dtstamp'];
+				$postdate = date('F j, Y g:i T', strtotime($dtstamp));
+				$icon = strtolower($row['topictype']);
+				$title = $row['subject'];
+				$content = codify($row['content']);
+				include 'bdif/newspost.dm';
+			} 
+		}
+	} else {
+		$edit = $_GET['edit'];
+		$nid = $_GET['nid'];
+		if($edit){
+			if(rank($userid) > 2){
+				$pid = GetInfo("news", "id", $nid, "poster");
+				if($userid == $pid || $userid == 1){
+					if(!$title){
+						msgbox('Title is required!');
+						$title = 'Insert news title here.';
+						include 'bdif/newssubmission.dm';
+					} elseif(!$content){
+						msgbox('Cannot submit blank news!');
+						$content = 'Insert news here.';
+						include 'bdif/newssubmission.dm';
+					} else {
+						mysql_query("UPDATE news SET topictype='$newsicon',subject='$title',content='$content',edited=1 WHERE id=$nid") or die("News Update Error: ".mysql_error());
+						logthis($userid, 'Updated a news post (NID: '.$nid.') using the title of "'.$title.'" and the contents of "'.$content.'".', 'newsedit');
+						WriteData($userid, 'msg', 'The news post has been updated.');
+						redirect('/');
+					}
+				} else {
+					logthis($userid, 'Illegally attempted to edit a news post NID('.$nid.'). Attempt blocked.', 'hack');
+					blockhack();
+				}
+			} else {
+				logthis($userid, 'Illegally attempted to edit a news post NID('.$nid.'). Attempt blocked.', 'hack');
+				blockhack();
+			}
+		} else {
+			if(rank($userid) > 2){
+				if(!$title){
+					msgbox('Title is required!');
+					$title = 'Insert news title here.';
+					include 'bdif/newssubmission.dm';
+				} elseif(!$content){
+					msgbox('Cannot submit blank news!');
+					$content = 'Insert news here.';
+					include 'bdif/newssubmission.dm';
+				} else {
+					mysql_query("INSERT INTO news (poster,topictype,subject,content) VALUES ('$userid','$newsicon', '$title', '$content')") or die("News Submission Error: ".mysql_error());
+					logthis($userid, 'Posted to the news using the title of "'.$title.'" and the contents of "'.$content.'".', 'newspost');
+					WriteData($userid, 'msg', 'News submission has been posted.');
+					redirect('/');
+				}
+			} else {
+				logthis($userid, 'Illegally attempted to post news. Attempt blocked.', 'hack');
+				blockhack();
+			}
+		}
+	}
+?>
diff --git a/newsrss.php b/newsrss.php
new file mode 100644
index 00000000..e7fe9af9
--- /dev/null
+++ b/newsrss.php
@@ -0,0 +1,80 @@
+<?
+	################################
+	##	RSS Feed Generator for news ##
+	################################
+	
+	###########################################################
+	# ADDED 2014-04-06 BY JAILOUT2000 FOR FORCED SSL SECURITY #
+	###########################################################
+	if($_SERVER['SERVER_PORT']!=443 || $_SERVER['HTTP_HOST']!='bnetdocs.org') {
+		http_response_code(301);
+		header('Location: https://bnetdocs.org'.$_SERVER['REQUEST_URI']);
+		exit;
+	}
+	###########################################################
+	#                                                         #
+	###########################################################
+	
+	# \n = newline, \t = tab
+	
+	function CropSentence ($strText, $intLength, $strTrail) {
+		$wsCount = 0;
+		$intTempSize = 0;
+		$intTotalLen = 0;
+		$intLength = $intLength - strlen($strTrail);
+		$strTemp = "";
+
+		if (strlen($strText) > $intLength) {
+			$arrTemp = explode(" ", $strText);
+			foreach ($arrTemp as $x) {
+				if (strlen($strTemp) <= $intLength) $strTemp .= " " . $x;
+			}
+			$CropSentence = $strTemp . $strTrail;
+		} else {
+			$CropSentence = $strText;
+		}
+
+		return $CropSentence;
+	} 
+
+	$auth = 'true';
+	include 'functions.php';
+	include 'db.php';
+	header("Content-Type: application/xml; charset=utf-8");
+	echo '<?xml version="1.0" encoding="utf-8"?>';
+	echo '<rss version="2.0">';
+	echo '<channel>';
+	echo '<title>BNETDocs News</title>';
+	echo '<link>http://www.bnetdocs.org/</link>';
+	echo '<description>Battle.Net Logon Sequences, Packets, information and protocols reference site.</description>';
+	echo '<language>en-us</language>';
+	echo '<docs>http://blogs.law.harvard.edu/tech/rss</docs>';
+	echo '<copyright>Site scripts and design copyrights reserved to Don Cullen. Contents copyrighted to Blizzard and their parent corporation, Vivendi. Copyright infringements will be prosecuted to the fullest extent allowable by law. Please view our legal disclaimer and terms of service.</copyright>';
+	
+	$sqlquery = 'SELECT * FROM news ORDER BY id DESC';
+	$newsarray = mysql_query($sqlquery);
+	
+	while($row = mysql_fetch_array($newsarray)){
+		echo '<item>';
+		$nid = $row['id'];
+		$author = $row['poster'];
+		$rank = rank($author);
+		if($rank){
+			$rank = '('.rankname($rank).')';
+		} else {
+			$rank = '';
+		}
+		$dtstamp = $row['dtstamp'];
+		$postdate = date('F j, Y g:i T', strtotime($dtstamp));
+		$icon = strtolower($row['topictype']);
+		$title = strip_tags($row['subject']);
+		$content = CropSentence(strip_tags(codify($row['content'], true) ), 500, '...');
+		echo '<title>'.htmlspecialchars ($title, ENT_XML1 | ENT_QUOTES | ENT_DISALLOWED).'</title>';
+		echo '<link>http://www.bnetdocs.org/?op=news&amp;nid='.$nid.'</link>';
+		echo '<description>'.htmlspecialchars ($content, ENT_XML1 | ENT_QUOTES | ENT_DISALLOWED).'</description>';
+		echo '<guid>http://www.bnetdocs.org/?op=news&amp;nid='.$nid.'</guid>';
+		echo '</item>';
+	} 
+	echo '</channel>';
+	echo '</rss>';
+?>
diff --git a/packet.php b/packet.php
new file mode 100644
index 00000000..bc6bd6ce
--- /dev/null
+++ b/packet.php
@@ -0,0 +1,721 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+
+	# Begin Code
+	# -------------
+
+	$qjtarget = sanitize($_POST['quickjump']);
+
+	if(!$qjtarget){
+		$pid = sanitize($_GET['pid']);
+	} else {
+		$qjtarget = sanitize($qjtarget);
+		$pid = GetInfo('packets', 'messagename', $qjtarget, 'id');
+		if(!$pid) $pid = -1;
+	}
+	
+	$mode = sanitize($_GET['mode']);
+	$action = sanitize($_GET['action']);
+	$messageid = '';
+	$messagename = '';
+	
+	if($mode == 'add'){
+		#Check rank
+		if($userid){
+			if(rank($userid) > 2){
+				#Allowed to add, now draw form
+				$action = 'add';
+				include 'bdif/packeteditor.dm';
+			} else {
+				#Not allowed to add
+				logthis($userid, 'Illegally attempted to add a new packet. Attempt blocked.', 'hack');
+				blockhack();
+			}
+		} else {
+			logthis($userid, 'Illegally attempted to add a new packet. Attempt blocked.', 'hack');
+			blockhack();
+		}
+	} elseif($mode == 'edit'){
+		$action = 'edit';
+		#Check rank
+		if($userid){
+			if(rank($userid) > 2){
+				#Allowed to edit, now draw form
+				if(!$pid){
+					logthis($userid, 'Illegally attempted to edit a packet. Attempt blocked.', 'hack');
+					blockhack();
+				}
+				$messageid = GetInfo('packets', 'id', $pid, 'messageid');
+				$messagename = GetInfo('packets', 'id', $pid, 'messagename');
+				$direction = GetInfo('packets', 'id', $pid, 'direction');
+				
+				$usedby = GetInfo('packets', 'id', $pid, 'usedby');
+
+				$usedby = str_replace('Warcraft III: TFT', '%a%', $usedby);
+				$usedby = str_replace('Warcraft III', '%b%', $usedby);
+				$usedby = str_replace('Starcraft Shareware', '%c%', $usedby);
+				$usedby = str_replace('Starcraft Japanese', '%d%', $usedby);
+				$usedby = str_replace('Starcraft Broodwar', '%e%', $usedby);
+				$usedby = str_replace('Starcraft', '%f%', $usedby);
+				$usedby = str_replace('Diablo Shareware', '%g%', $usedby);
+				$usedby = str_replace('Diablo II LOD', '%h%', $usedby);
+				$usedby = str_replace('Diablo II', '%i%', $usedby);
+				$usedby = str_replace('Diablo I', '%j%', $usedby);
+				$usedby = str_replace('Warcraft II', '%k%', $usedby);
+				$usedby = str_replace('World of Warcraft', '%l%', $usedby);
+
+				if(strstr($usedby, '%c%')) $cbscsw = 'checked';
+				if(strstr($usedby, '%f%')) $cbsc = 'checked';
+				if(strstr($usedby, '%e%')) $cbbw = 'checked';
+				if(strstr($usedby, '%d%')) $cbjsc = 'checked';
+				if(strstr($usedby, '%g%')) $cbdsw = 'checked';
+				if(strstr($usedby, '%j%')) $cbdiablo = 'checked';
+				if(strstr($usedby, '%i%')) $cbd2 = 'checked';
+				if(strstr($usedby, '%h%')) $cbd2lod = 'checked';
+				if(strstr($usedby, '%k%')) $cbwc2 = 'checked';
+				if(strstr($usedby, '%b%')) $cbwc3 = 'checked';
+				if(strstr($usedby, '%a%')) $cbwc3tft = 'checked';
+				if(strstr($usedby, '%l%')) $cbwow = 'checked';
+
+				$format = GetInfo('packets', 'id', $pid, 'format');
+				$remarks = GetInfo('packets', 'id', $pid, 'remarks');
+				$related = GetInfo('packets', 'id', $pid, 'related');
+
+				$status = GetInfo('packets', 'id', $pid, 'status');
+
+				if($status == 0) $psrawselected = 'selected';
+				if($status == 1) $psnorselected = 'selected';
+				if($status == 2) $psresselected = 'selected';
+				if($status == 3) $psdefselected = 'selected';
+
+				$clearance = GetInfo('packets', 'id', $pid, 'clearance');
+
+				if($clearance == 0) $pcgueselected = 'selected';
+				if($clearance == 1) $pcuseselected = 'selected';
+				if($clearance == 2) $pcsupselected = 'selected';
+				if($clearance == 3) $pcediselected = 'selected';
+				if($clearance == 4) $pcadmselected = 'selected';
+
+				$pgroupid = GetInfo('packets', 'id', $pid, 'pgroup');
+				$action = 'edit';
+				include 'bdif/packeteditor.dm';
+			} else {
+				#Not allowed to edit
+				logthis($userid, 'Illegally attempted to edit a packet. Attempt blocked.', 'hack');
+				blockhack();
+			}
+		} else {
+			logthis($userid, 'Illegally attempted to edit a packet. Attempt blocked.', 'hack');
+			blockhack();
+		}
+	} elseif($mode == 'delete'){
+		$action = 'delete';
+		#Check rank
+		if($userid){
+			if(rank($userid) > 2){
+				#Allowed to delete, now process deletion
+				if(!$pid){
+					logthis($userid, 'attempted to delete a packet without specifying packet. Attempt blocked.', 'hack');
+					blockhack();
+				}
+				$messageid = GetInfo('packets', 'id', $pid, 'messageid');
+				$messagename = GetInfo('packets', 'id', $pid, 'messagename');
+				$direction = GetInfo('packets', 'id', $pid, 'direction');
+				$direction = GetInfo('traffic', 'id', $direction, 'longdescr');
+				$usedby = GetInfo('packets', 'id', $pid, 'usedby');
+				if(!$usedby) $usedby = 'Unknown';
+				$format = GetInfo('packets', 'id', $pid, 'format');
+				$remarks = GetInfo('packets', 'id', $pid, 'remarks');
+				$mrelated = GetInfo('packets', 'id', $pid, 'related');
+				$pstatus = GetInfo('packets', 'id', $pid, 'status');
+				
+				if(strlen($mrelated) > 0){
+					$linkarray = explode(',', $mrelated);
+					foreach($linkarray as $link){
+						if($link){
+							$link = trim(strtoupper($link));
+							if(substr($link, 0, 1) == 'D' || substr($link, 0, 1) == 'P'){
+								if(substr($link, 0, 1) == 'D') $table = 'documents';
+								if(substr($link, 0, 1) == 'P') $table = 'packets';
+								if(FieldVerify('id', $table, substr($link, 1))){
+									# Link has been validated
+									$letter = substr($link, 0, 1);
+									if($letter == 'P'){
+										$rpdbid = substr($link, 1);
+										$rdid = GetInfo('packets', 'id', $rpdbid, 'messageid');
+										$rpname = GetInfo('packets', 'id', $rpdbid, 'messagename');
+										$rpdirection = GetInfo('packets', 'id', $rpdbid, 'direction');
+										$rpdirection = '&nbsp;(' . GetInfo('traffic', 'id', $rpdirection, 'shortcutlink') . ')';
+										$relatedlinkstring .= '<a href="/?op=packet&pid='.$rpdbid.'">['.$rdid.']&nbsp;'.$rpname.$rpdirection.'</a>, ';
+									} else {
+										$rpdbid = substr($link, 1);
+										$title = GetInfo('documents', 'id', $rpdbid, 'title');
+										$relatedlinkstring .= '<a href="/?op=doc&did='.$rpdbid.'">'.$title.'</a>, ';
+									}
+								}
+							} else {
+								$relatedlinkstring .= '<a href="'.$link.'">'.$link.'</a>, ';
+							}
+						}
+					}	
+					if(strlen($relatedlinkstring) > 0) $relatedlinkstring = substr_replace($relatedlinkstring,"",-2);
+				}
+
+				switch ($pstatus) {
+					case 0:
+						$pstatus = 'RAW, NEW PACKET';
+						break;
+					case 1: 
+						$pstatus = '';
+						break;
+					case 2:
+						$pstatus = 'MORE RESEARCH NEEDED';
+						break;
+					case 3:
+						$pstatus = 'DEFUNCT';
+						break;
+				}
+				
+				$logstring = 'Message ID: '.$messageid.'
+Message Name: '.$messagename.'
+Message Status: '.$pstatus.'
+Direction: '.$direction.'
+Used By: '.$usedby.'
+Format: '.$format.'
+Remarks: '.$remarks.'
+Related: '.$relatedlinkstring;
+				
+				# Delete packet from database
+				$sql = "DELETE FROM `packets` WHERE id=$pid";
+				mysql_query($sql) or die("Packet Delete Error: ".mysql_error());
+
+				# Finished adding, confirm addition and take user to new packet.
+				logthis($userid, 'Deleted a packet with the Message ID of '.$messageid.'. Contents of packet: 
+
+'.$logstring.'', 'pktdel');
+				WriteData($userid, 'msg', 'Successfully deleted the packet! Thanks for your contribution!');
+				redirect('/');
+			} else {
+				#Not allowed to delete
+				logthis($userid, 'Illegally attempted to delete a packet. Attempt blocked.', 'hack');
+				blockhack();
+			}
+		} else {
+			logthis($userid, 'Illegally attempted to delete a packet. Attempt blocked.', 'hack');
+			blockhack();
+		}
+	} else {
+		if($action){
+			if($action == 'edit'){
+				# Update
+				# Obtain POST'ed data
+
+				$mid = removeEvilTags(sanitize($_POST['mid']));
+				$mname = removeEvilTags(sanitize($_POST['mname']));
+				$mdirection = removeEvilTags($_POST['mdirection']);
+				$mformat = removeEvilTags(sanitize($_POST['mformat']));
+				$mremarks = removeEvilTags(sanitize($_POST['mremarks']));
+				$mrelated = removeEvilTags(sanitize($_POST['mrelated']));
+				$mstatus = removeEvilTags($_POST['mstatus']);
+				$mclearance = removeEvilTags($_POST['mclearance']);
+				$mgroup = removeEvilTags($_POST['mgroup']);
+
+				$scsw = $_POST['scsw'];
+				$bw = $_POST['bw'];
+				$dsw = $_POST['dsw'];
+				$d2 = $_POST['d2'];
+				$wc2 = $_POST['wc2'];
+				$wc3tft = $_POST['wc3tft'];
+				$sc = $_POST['sc'];
+				$jsc = $_POST['jsc'];
+				$diablo = $_POST['diablo'];
+				$d2lod = $_POST['d2lod'];
+				$wc3 = $_POST['wc3'];
+				$wow = $_POST['wow'];
+
+				# Done obtaining data, now determine if person has authorization to add packets.
+
+				if(rank($userid) < 3){
+					logthis($userid, 'Illegally attempted to edit a packet. Attempt blocked.', 'hack');
+					blockhack();
+				}
+
+				# Person has authorization, process data and add it
+
+				if(!$mid || !$mname || !$mgroup){
+					#missing data, abort
+					if(!$mid) $missingdata .= 'message id, ';
+					if(!$mname) $missingdata .= 'message name, ';
+					if(!$mgroup) $missingdata .= 'group, ';
+					$missingdata = substr_replace($missingdata,"",-1);
+					$missingdata = substr_replace($missingdata,"",-1);
+					WriteData($userid, 'msg', 'Failed to edit packet, missing data: '.$missingdata.'.');
+					redirect('/?op=packet&mode=edit&pid='.$pid);
+				}
+
+				# Compile 'used by' string 
+				
+				$comma = '';
+				if($scsw){
+					$comma = ', ';
+					$musedby .= 'Starcraft Shareware'.$comma;
+				}
+				if($bw){
+					$comma = ', ';
+					$musedby .= 'Starcraft Broodwar'.$comma;
+				}
+				if($dsw){
+					$comma = ', ';
+					$musedby .= 'Diablo Shareware'.$comma;
+				}
+				if($d2){
+					$comma = ', ';
+					$musedby .= 'Diablo II'.$comma;
+				}
+				if($wc2){
+					$comma = ', ';
+					$musedby .= 'Warcraft II'.$comma;
+				}
+				if($wc3tft){
+					$comma = ', ';
+					$musedby .= 'Warcraft III: TFT'.$comma;
+				}
+				if($sc){
+					$comma = ', ';
+					$musedby .= 'Starcraft'.$comma;
+				}
+				if($jsc){
+					$comma = ', ';
+					$musedby .= 'Starcraft Japanese'.$comma;
+				}
+				if($diablo){
+					$comma = ', ';
+					$musedby .= 'Diablo I'.$comma;
+				}
+				if($d2lod){
+					$comma = ', ';
+					$musedby .= 'Diablo II LOD'.$comma;
+				}
+				if($wc3){
+					$comma = ', ';
+					$musedby .= 'Warcraft III'.$comma;
+				}
+				if($wow) $musedby .= 'World of Warcraft';
+				
+				if($musedby[strlen($musedby)-2] == ','){
+					$musedby = substr_replace($musedby,"",-1);
+					$musedby = substr_replace($musedby,"",-1);
+				}
+
+				if(strlen($mrelated) > 0){
+					$linkarray = explode(',', $mrelated);
+					foreach($linkarray as $link){
+						if($link){
+							$link = trim(strtoupper($link));
+							if(substr($link, 0, 1) == 'D' || substr($link, 0, 1) == 'P'){
+								if(substr($link, 0, 1) == 'D') $table = 'documents';
+								if(substr($link, 0, 1) == 'P') $table = 'packets';
+								if(FieldVerify('id', $table, substr($link, 1))){
+									# Link has been validated
+									$letter = substr($link, 0, 1);
+									if($letter == 'P'){
+										$rpdbid = substr($link, 1);
+										$rdid = GetInfo('packets', 'id', $rpdbid, 'messageid');
+										$rpname = GetInfo('packets', 'id', $rpdbid, 'messagename');
+										$rpdirection = GetInfo('packets', 'id', $rpdbid, 'direction');
+										$rpdirection = '&nbsp;(' . GetInfo('traffic', 'id', $rpdirection, 'shortcutlink') . ')';
+										$relatedlinkstring .= '<a href="/?op=packet&pid='.$rpdbid.'">['.$rdid.']&nbsp;'.$rpname.$rpdirection.'</a>, ';
+									} else {
+										$rpdbid = substr($link, 1);
+										$title = GetInfo('documents', 'id', $rpdbid, 'title');
+										$relatedlinkstring .= '<a href="/?op=doc&did='.$rpdbid.'">'.$title.'</a>, ';
+									}
+								}
+							} else {
+								$relatedlinkstring .= '<a href="'.$link.'">'.$link.'</a>, ';
+							}
+						}
+					}	
+					if(strlen($relatedlinkstring) > 0) $relatedlinkstring = substr_replace($relatedlinkstring,"",-2);
+				}
+					
+				# Update packets database
+				#$mname = sanitize($mname);
+				#$mformat = sanitize($mformat);
+				#$mremakrs = sanitize($mremarks);
+				$sql = "UPDATE `packets` SET pgroup=$mgroup, messageid='$mid', messagename='$mname', direction=$mdirection, usedby='$musedby', format='$mformat', remarks='$mremarks', related='$mrelated', status=$mstatus, clearance=$mclearance WHERE id=$pid";
+				mysql_query($sql) or die("Packet Edit Error: ".mysql_error());
+				
+				# Finished editing, confirm edition and take user to updated packet.
+				$linkto = '<a href="/?op=packet&pid='.$pid.'">Link to packet</a>';
+				logthis($userid, 'Edited a packet (['.$mid.'] '.$mname.'). '.$linkto, 'pktedit');
+				WriteData($userid, 'msg', 'Successfully edited the packet! Thanks for your contribution!');
+
+				redirect('/?op=packet&pid='.$pid);
+			} elseif($action == 'add') {
+				# Add Packet Data
+				# Obtain POST'ed data
+
+				$mid = removeEvilTags(sanitize($_POST['mid']));
+				$mname = removeEvilTags(sanitize($_POST['mname']));
+				$mdirection = removeEvilTags($_POST['mdirection']);
+				$mformat = removeEvilTags(sanitize($_POST['mformat']));
+				$mremarks = removeEvilTags(sanitize($_POST['mremarks']));
+				$mrelated = removeEvilTags(sanitize($_POST['mrelated']));
+				$mstatus = removeEvilTags($_POST['mstatus']);
+				$mclearance = removeEvilTags($_POST['mclearance']);
+				$mgroup = removeEvilTags($_POST['mgroup']);
+
+				$scsw = $_POST['scsw'];
+				$bw = $_POST['bw'];
+				$dsw = $_POST['dsw'];
+				$d2 = $_POST['d2'];
+				$wc2 = $_POST['wc2'];
+				$wc3tft = $_POST['wc3tft'];
+				$sc = $_POST['sc'];
+				$jsc = $_POST['jsc'];
+				$diablo = $_POST['diablo'];
+				$d2lod = $_POST['d2lod'];
+				$wc3 = $_POST['wc3'];
+				$wow = $_POST['wow'];
+
+				# Done obtaining data, now determine if person has authorization to add packets.
+
+				if(rank($userid) < 3){
+					logthis($userid, 'Illegally attempted to add a packet. Attempt blocked.', 'hack');
+					blockhack();
+				}
+
+				# Person has authorization, process data and add it
+
+				if(!$mid || !$mname || !$mgroup){
+					#missing data, abort
+					if(!$mid) $missingdata .= 'message id, ';
+					if(!$mname) $missingdata .= 'message name, ';
+					if(!$mgroup) $missingdata .= 'group, ';
+					$missingdata = substr_replace($missingdata,"",-1);
+					$missingdata = substr_replace($missingdata,"",-1);
+					WriteData($userid, 'msg', 'Failed to add packet, missing data: '.$missingdata.'.');
+					redirect('/?op=packet&mode=add');
+				}
+
+				# Compile 'used by' string 
+				
+				$comma = '';
+				if($scsw){
+					$comma = ', ';
+					$musedby .= 'Starcraft Shareware'.$comma;
+				}
+				if($bw){
+					$comma = ', ';
+					$musedby .= 'Starcraft Broodwar'.$comma;
+				}
+				if($dsw){
+					$comma = ', ';
+					$musedby .= 'Diablo Shareware'.$comma;
+				}
+				if($d2){
+					$comma = ', ';
+					$musedby .= 'Diablo II'.$comma;
+				}
+				if($wc2){
+					$comma = ', ';
+					$musedby .= 'Warcraft II'.$comma;
+				}
+				if($wc3tft){
+					$comma = ', ';
+					$musedby .= 'Warcraft III: TFT'.$comma;
+				}
+				if($sc){
+					$comma = ', ';
+					$musedby .= 'Starcraft'.$comma;
+				}
+				if($jsc){
+					$comma = ', ';
+					$musedby .= 'Starcraft Japanese'.$comma;
+				}
+				if($diablo){
+					$comma = ', ';
+					$musedby .= 'Diablo I'.$comma;
+				}
+				if($d2lod){
+					$comma = ', ';
+					$musedby .= 'Diablo II LOD'.$comma;
+				}
+				if($wc3){
+					$comma = ', ';
+					$musedby .= 'Warcraft III'.$comma;
+				}
+				if($wow) $musedby .= 'World of Warcraft';
+				
+				if($musedby[strlen($musedby)-2] == ','){
+					$musedby = substr_replace($musedby,"",-1);
+					$musedby = substr_replace($musedby,"",-1);
+				}
+				
+				if(strlen($mrelated) > 0){
+					$linkarray = explode(',', $mrelated);
+					foreach($linkarray as $link){
+						if($link){
+							$link = trim(strtoupper($link));
+							if(substr($link, 0, 1) == 'D' || substr($link, 0, 1) == 'P'){
+								if(substr($link, 0, 1) == 'D') $table = 'documents';
+								if(substr($link, 0, 1) == 'P') $table = 'packets';
+								if(FieldVerify('id', $table, substr($link, 1))){
+									# Link has been validated
+									$letter = substr($link, 0, 1);
+									if($letter == 'P'){
+										$rpdbid = substr($link, 1);
+										$rdid = GetInfo('packets', 'id', $rpdbid, 'messageid');
+										$rpname = GetInfo('packets', 'id', $rpdbid, 'messagename');
+										$rpdirection = GetInfo('packets', 'id', $rpdbid, 'direction');
+										$rpdirection = '&nbsp;(' . GetInfo('traffic', 'id', $rpdirection, 'shortcutlink') . ')';
+										$relatedlinkstring .= '<a href="/?op=packet&pid='.$rpdbid.'">['.$rdid.']&nbsp;'.$rpname.$rpdirection.'</a>, ';
+									} else {
+										$rpdbid = substr($link, 1);
+										$title = GetInfo('documents', 'id', $rpdbid, 'title');
+										$relatedlinkstring .= '<a href="/?op=doc&did='.$rpdbid.'">'.$title.'</a>, ';
+									}
+								}
+							} else {
+								$relatedlinkstring .= '<a href="'.$link.'">'.$link.'</a>, ';
+							}
+						}
+					}	
+					if(strlen($relatedlinkstring) > 0) $relatedlinkstring = substr_replace($relatedlinkstring,"",-2);
+				}
+				
+				# Insert into packets database
+				#$mname = sanitize($mname);
+				#$mformat = sanitize($mformat);
+				#$mremarks = sanitize($mremarks);
+				
+				$sql = "INSERT INTO `packets` (pgroup, messageid, messagename, direction, usedby, format, remarks, related, status, clearance) VALUES ($mgroup, '$mid', '$mname', $mdirection, '$musedby', '$mformat', '$mremarks', '$mrelated', $mstatus, $mclearance)";
+				mysql_query($sql) or die("Packet Add Error: ".mysql_error());
+
+				$sql = "SELECT id FROM `packets` WHERE messageid = '$mid' AND messagename = '$mname' AND direction = $mdirection";
+				$sqlquery = mysql_query($sql) or die("Packet Addition Selection Error: ".mysql_error());
+				$newpid = mysql_result($sqlquery,0,'id');
+
+				# Finished adding, confirm addition and take user to new packet.
+				$linkto = '<a href="/?op=packet&pid='.$newpid.'">Link to packet</a>';
+				logthis($userid, 'Added a packet with the Message ID of '.$mid.'.', 'pktadd');
+				logthis($userid, 'Added a packet (['.$mid.'] '.$mname.'). '.$linkto, 'pktadd');
+				WriteData($userid, 'msg', 'Successfully added the packet! Thanks for your contribution!');
+				$mode = '';
+				
+				redirect('/?op=packet'.$mode.'&pid='.$newpid);
+			}
+		} else {
+			if(!$pid){
+				error('No packet ID has been specified.');
+			} else if(FieldVerify('id', 'packets', $pid) == false) {
+				if($pid != -1){
+					error('Invalid packet ID identifier.');
+				} else {
+					error('Unrecognized packet name.<br>Maybe you mistyped the name?');
+				}
+			} else {
+				$messageid = GetInfo('packets', 'id', $pid, 'messageid');
+				$messagename = GetInfo('packets', 'id', $pid, 'messagename');
+				$direction = GetInfo('packets', 'id', $pid, 'direction');
+				$direction = GetInfo('traffic', 'id', $direction, 'longdescr');
+				$usedby = GetInfo('packets', 'id', $pid, 'usedby');
+
+				$usedby = str_replace('Warcraft III: TFT', '%a%', $usedby);
+				$usedby = str_replace('Warcraft III', '%b%', $usedby);
+				$usedby = str_replace('Starcraft Shareware', '%c%', $usedby);
+				$usedby = str_replace('Starcraft Japanese', '%d%', $usedby);
+				$usedby = str_replace('Starcraft Broodwar', '%e%', $usedby);
+				$usedby = str_replace('Starcraft', '%f%', $usedby);
+				$usedby = str_replace('Diablo Shareware', '%g%', $usedby);
+				$usedby = str_replace('Diablo II LOD', '%h%', $usedby);
+				$usedby = str_replace('Diablo II', '%i%', $usedby);
+				$usedby = str_replace('Diablo I', '%j%', $usedby);
+				$usedby = str_replace('Warcraft II', '%k%', $usedby);
+				$usedby = str_replace('World of Warcraft', '%l%', $usedby);
+				$usedby = str_replace('%a%', '<img src="/images/games/w3xp.jpg" alt="Warcraft III: The Frozen Throne">', $usedby);
+				$usedby = str_replace('%b%', '<img src="/images/games/war3.jpg" alt="Warcraft III">', $usedby);
+				$usedby = str_replace('%c%', '<img src="/images/games/sware.jpg" alt="Starcraft Shareware">', $usedby);
+				$usedby = str_replace('%d%', '<img src="/images/games/jsc.jpg" alt="Starcraft Japanese">', $usedby);
+				$usedby = str_replace('%e%', '<img src="/images/games/starx.jpg" alt="Starcraft Broodwar">', $usedby);
+				$usedby = str_replace('%f%', '<img src="/images/games/sc.jpg" alt="Starcraft">', $usedby);
+				$usedby = str_replace('%g%', '<img src="/images/games/diablosw.jpg" alt="Diablo Shareware">', $usedby);
+				$usedby = str_replace('%h%', '<img src="/images/games/d2exp.jpg" alt="Diablo">', $usedby);
+				$usedby = str_replace('%i%', '<img src="/images/games/diablo2.jpg" alt="Diablo II">', $usedby);
+				$usedby = str_replace('%j%', '<img src="/images/games/diablo.jpg" alt="Diablo">', $usedby);
+				$usedby = str_replace('%k%', '<img src="/images/games/war2.jpg" alt="Warcraft II">', $usedby);
+				$usedby = str_replace('%l%', '<img src="/images/games/wow.jpg" alt="World of Warcraft">', $usedby);
+
+				$usedby = str_replace(', ', '<font color=black size=1>, </font>', $usedby);
+				if(!$usedby) $usedby = '<font color=red>Unknown</font>';
+				$format = codify(GetInfo('packets', 'id', $pid, 'format'), true);
+				$remarks = codify(GetInfo('packets', 'id', $pid, 'remarks'), true);
+				$mrelated = GetInfo('packets', 'id', $pid, 'related');
+				$pstatus = GetInfo('packets', 'id', $pid, 'status');
+				$pclearance = GetInfo('packets', 'id', $pid, 'clearance');
+				
+				if(strlen($mrelated) > 0){
+					$linkarray = explode(',', $mrelated);
+					foreach($linkarray as $link){
+						if($link){
+							$link = trim(strtoupper($link));
+							if(substr($link, 0, 1) == 'D' || substr($link, 0, 1) == 'P'){
+								if(substr($link, 0, 1) == 'D') $table = 'documents';
+								if(substr($link, 0, 1) == 'P') $table = 'packets';
+								if(FieldVerify('id', $table, substr($link, 1))){
+									# Link has been validated
+									$letter = substr($link, 0, 1);
+									if($letter == 'P'){
+										$rpdbid = substr($link, 1);
+										$rdid = GetInfo('packets', 'id', $rpdbid, 'messageid');
+										$rpname = GetInfo('packets', 'id', $rpdbid, 'messagename');
+										$rpdirection = GetInfo('packets', 'id', $rpdbid, 'direction');
+										$rpdirection = '&nbsp;(' . GetInfo('traffic', 'id', $rpdirection, 'shortcutlink') . ')';
+										$relatedlinkstring .= '<a href="/?op=packet&pid='.$rpdbid.'">['.$rdid.']&nbsp;'.$rpname.$rpdirection.'</a>, ';
+									} else {
+										$rpdbid = substr($link, 1);
+										$title = GetInfo('documents', 'id', $rpdbid, 'title');
+										$relatedlinkstring .= '<a href="/?op=doc&did='.$rpdbid.'">'.$title.'</a>, ';
+									}
+								}
+							} else {
+								$relatedlinkstring .= '<a href="'.$link.'">'.$link.'</a>, ';
+							}
+						}
+					}	
+					if(strlen($relatedlinkstring) > 0) $relatedlinkstring = substr_replace($relatedlinkstring,"",-2);
+				}
+
+				switch ($pstatus) {
+					case 0:
+						$pstatus = '<font color=red>RAW, NEW PACKET</font>';
+						break;
+					case 1: 
+						$pstatus = '';
+						break;
+					case 2:
+						$pstatus = '<font color=cyan>MORE RESEARCH NEEDED</font>';
+						break;
+					case 3:
+						$pstatus = '<font color=red>DEFUNCT</font>';
+						break;
+				}
+				
+				if($pclearance > 0){
+					if($userid){
+						if(rank($userid) < $pclearance){
+							logthis($userid, ' attempted to access a packet with insufficent clearance. Attempt blocked.', 'hack');
+							blockhack();
+						}
+					} else {
+						logthis($userid, ' attempted to access a packet with insufficent clearance. Attempt blocked.', 'hack');
+						blockhack();
+					}
+				}
+				$format = str_replace("(FILETIME)", "<font class=\"keyword\">(FILETIME)</font>", $format);
+				$format = str_replace("(DWORD)", "<font class=\"keyword\">(DWORD)</font>", $format);
+				$format = str_replace("(BOOLEAN)", "<font class=\"keyword\">(BOOLEAN)</font>", $format);
+				$format = str_replace("(WORD)", "<font class=\"keyword\">(WORD)</font>", $format);
+				$format = str_replace("(BYTE)", "<font class=\"keyword\">(BYTE)</font>", $format);
+				$format = str_replace("(STRING)", "<font class=\"keyword\">(STRING)</font>", $format);
+				$format = str_replace("(WIDESTRING)", "<font class=\"keyword\">(WIDESTRING)</font>", $format);
+				$format = str_replace("(VOID)", "<font class=\"keyword\">(VOID)</font>", $format);
+				
+				$format = brfix($format);
+				$remarks = brfix($remarks);
+				
+				?>
+				<div id="container">
+				<div id="main2">
+				<h2>Packet Information</h2>
+				<div align=center><br>
+				<? 
+				if($userid){
+					if(rank($userid) > 2){ 
+						?><font size=1>[ &nbsp; <a href="/?op=packet&mode=edit&pid=<?=$pid;?>">EDIT</a> &nbsp; 
+						| &nbsp; <a onClick="return confimdelete();" href="/?op=packet&mode=delete&pid=<?=$pid;?>">DELETE</a> &nbsp; ]</font>
+						<?
+					}
+				}
+				?>
+				<div align="center"><div style="width: 97%;" align="left">
+				<table border=0 id="code" width=90%>
+				<tr><td>Message ID:</td><td><?=$messageid;?></td></tr>
+				<tr><td>&nbsp;</td><td>&nbsp;</td></tr>
+				<tr><td nowrap>Message Name:</td><td><?=$messagename;?></td></tr>
+				<tr><td>&nbsp;</td><td>&nbsp;</td></tr>
+				<? if($pstatus){ ?><tr><td nowrap>Message Status:</td><td><?=$pstatus;?></td></tr>
+				<tr><td>&nbsp;</td><td>&nbsp;</td></tr><? } ?>
+				<tr><td>Direction:</td><td><?=$direction;?></td></tr>
+				<tr><td>&nbsp;</td><td>&nbsp;</td></tr>
+				<tr><td valign=top>Used By:</td><td><?=$usedby;?></td></tr>
+				<tr><td>&nbsp;</td><td>&nbsp;</td></tr>
+				<tr><td valign=top>Format:</td><td><?=$format;?></td></tr>
+				<tr><td>&nbsp;</td><td>&nbsp;</td></tr>
+				<tr><td valign=top>Remarks:</td><td><?=$remarks;?></td></tr>
+				
+				<? if($relatedlinkstring){ ?>
+					<tr><td>&nbsp;</td><td>&nbsp;</td></tr>
+					<tr><td valign=top>Related:</td><td><?=$relatedlinkstring;?></td></tr>
+				<? } ?>
+				
+				</table>
+				</div>
+				</div></div></div></div>
+
+				<div id="comments">
+				<div id="container">
+				<div id="main2">
+				<h2>User Comments</h2>
+				<center><br>For detailed questions and discussion, visit the <a href="http://forum.valhallalegends.com/index.php/board,17.0.html" target="_blank">Battle.net Research Forum</a><br><br></center>
+				<?
+				$sqlqueryz = 'SELECT id,posterid,UNIX_TIMESTAMP(dtstamp) as unixdtstamp,message FROM comments WHERE pdid='.$pid.' ORDER BY id';
+				$docarray = mysql_query($sqlqueryz);
+				$commentcount = 0;
+				while($rowz = mysql_fetch_array($docarray)){
+					$cid = $rowz['id'];
+					$posterid = $rowz['posterid'];
+					$dtstamp = date("M d, Y", $rowz['unixdtstamp']);
+					$dtstamp .= '<br>'.date('h:i A', $rowz['unixdtstamp']);
+					$message = Codify($rowz['message']);
+					if($userid){
+						if($posterid == $userid){
+							$editdelstr = '[ <a href="/?op=postcomment&mode=edit&cid='.$cid.'&pid='.$pid.'">EDIT</a> | <a onClick="return confimdelete();" href="/?op=postcomment&mode=delete&cid='.$cid.'&pid='.$pid.'">DELETE</a> ]';
+						} else {
+							if(rank($userid) > 2){ 
+								$editdelstr = '[ <a onClick="return confimdelete();" href="/?op=postcomment&mode=delete&cid='.$cid.'&pid='.$pid.'">DELETE</a> ]';
+							}
+						}
+					}
+					if($editdelstr){
+						$title = '<div id="author" nowrap>'.$editdelstr.'</div>';
+					} else {
+						$title = '<div id="author" nowrap> </div>';
+					}
+					echo $title;
+					echo '<table border=0 width="100%" cellpadding=1 cellspacing=0><tr><td width="20%" align="center" height="100%"><table height="100%" width="100%" class="commentsidebar" border=0 cellpadding=0 cellspacing=0><tr><td width="100%" height="100%" align="center" valign="center">'.whoisid($posterid).'<br>'.$dtstamp.'</td></tr></table></td><td><div style="border: 1px #555 solid; padding: 2px; padding-left: 5px;"><br>'.$message.'<br><br></div></td></tr></table>';
+					$commentcount++;
+				}
+				if($commentcount < 1) echo '<center>No comments were made. Be the first to contribute!<br><br></center>';
+				if($userid){
+					?>
+					<div id="author" nowrap><center>Got Something To Say?</center></div>
+					<center>
+					<br>
+					<form method="POST" name="newcomment" action="/?op=postcomment">
+					<input type="hidden" name="pid" value="<?=$pid;?>">
+					<textarea name="mycomment" style="width: 90%;" id="inputbox" rows="10" cols="81"></textarea>
+					<br><br><input type="submit" id="abutton" style="width:900" value="Submit"><br><br></form>
+			
+					</center></div>
+					</div></div>
+					<?
+				}
+			}
+		}
+	}
+?>
diff --git a/postcomment.php b/postcomment.php
new file mode 100644
index 00000000..24ada835
--- /dev/null
+++ b/postcomment.php
@@ -0,0 +1,162 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth, $ie, $userid;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	if(!$userid) die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+	
+	$pid = sanitize($_POST['pid']);
+	$did = sanitize($_POST['did']);
+	$cid = sanitize($_REQUEST['cid']);
+	
+	if(!$pid) $pid = sanitize($_REQUEST['pid']);
+	if(!$did) $did = sanitize($_REQUEST['did']);
+	
+	if(!$pid && !$did){
+		error('Unable to process. Missing identificator.');
+		return;
+	}
+	
+	$mycomment = removeEvilTags(sanitize($_POST['mycomment']));
+	
+	if($_POST){
+		$mode = $_REQUEST['mode'];
+		if($mode){
+			if($mode == 'edit'){
+				if($cid){
+					$queryid = "SELECT * FROM comments WHERE id=\"$cid\"";
+					$identification = mysql_query($queryid);
+					$posterid = mysql_result($identification,0,"posterid");
+					if($posterid == $userid){
+						if($mycomment){
+							if($pid){
+								#Process packet comment
+								# Insert into comments database
+								$sql = "UPDATE `comments` SET message='$mycomment' WHERE id=".$cid;
+								mysql_query($sql) or die("Packet Comment Edit Error: ".mysql_error());
+								logthis($userid, 'Edited a comment on '.getpacketlink($pid).' saying: '.$mycomment, 'commentedit');
+								WriteData($userid, 'msg', 'Successfully edited your comment on the packet! Thanks!');
+								redirect('/?op=packet&pid='.$pid);
+							} else {
+								#Process packet comment
+								# Insert into comments database
+								$sql = "UPDATE `comments` SET message='$mycomment' WHERE id=".$cid;
+								mysql_query($sql) or die("Document Comment Edit Error: ".mysql_error());
+								logthis($userid, 'Edited a comment on '.getdocumentlink($did).' saying: '.$mycomment, 'commentedit');
+								WriteData($userid, 'msg', 'Successfully edited your comment on the document! Thanks!');
+								redirect('/?op=doc&did='.$did);
+							}
+						} else {
+							error('Cannot submit blank comment.');
+							return;
+						}
+					} else {
+						error('You\'re not authorized to edit the comment.');
+						return;
+					}
+				} else {
+					error('Unable to process. Missing Comment ID.');
+					return;
+				}
+			} else {
+				error('Unable to process.');
+				return;
+			}
+		} else {
+			if($mycomment){
+				if(!$pid && !$did){
+					error('Unable to process.');
+					return;
+				} else {
+					if($pid){
+						#Process packet comment
+						# Insert into comments database
+						$sql = "INSERT INTO `comments` (posterid, pdid, message) VALUES ($userid, $pid, '$mycomment')";
+						mysql_query($sql) or die("Packet Comment Add Error: ".mysql_error());
+						logthis($userid, 'Commented on '.getpacketlink($pid).' saying: '.$mycomment, 'commentadd');
+						WriteData($userid, 'msg', 'Successfully commented on the packet! Thanks!');
+						redirect('/?op=packet&pid='.$pid);
+					} else {
+						#Process document comment
+						$sql = "INSERT INTO `comments` (posterid, pdid, message) VALUES ($userid, $did, '$mycomment')";
+						mysql_query($sql) or die("Document Comment Add Error: ".mysql_error());
+						logthis($userid, 'Commented on '.getdocumentlink($did).' saying: '.$mycomment, 'commentadd');
+						WriteData($userid, 'msg', 'Successfully commented on the document! Thanks!');
+						redirect('/?op=doc&did='.$did);
+					}
+				}
+			} else {
+				error('Cannot submit blank comment.');
+				return;
+			}
+		}
+	} else {
+		$mode = $_REQUEST['mode'];
+		if($mode == 'edit'){
+			if($cid){
+				$queryid = "SELECT * FROM comments WHERE id=\"$cid\"";
+				$identification = mysql_query($queryid);
+				$message = mysql_result($identification,0,"message");
+				$posterid = mysql_result($identification,0,"posterid");
+				if($posterid == $userid){
+					?>
+					<div id="container">
+					<div id="main2">
+					<h2>Comment Editor</h2>
+					<center>
+					<br>
+					<form method="POST" name="newcomment" action="/?op=postcomment&mode=edit&cid=<?=$cid;?>">
+					<?
+					if($pid){
+						?><input type="hidden" name="pid" value="<?=$pid;?>"><?
+					} else {
+						?><input type="hidden" name="did" value="<?=$did;?>"><?
+					}
+					?>
+					<textarea name="mycomment" style="width: 90%;" id="inputbox" rows="10" cols="81"><?=$message;?></textarea>
+					<br><br><input type="submit" id="abutton" style="width:900" value="Submit"><br><br></form>
+					</center></div>
+					</div>
+					<?
+				} else {
+					error('You\'re not authorized to edit the comment.');
+					return;
+				}
+			} else {
+				error('Unable to process. Missing Comment ID.');
+				return;
+			}
+		} elseif($mode == 'delete'){
+			$queryid = "SELECT * FROM comments WHERE id=$cid";
+			$identification = mysql_query($queryid);
+			$posterid = mysql_result($identification,0,"posterid");
+			$message = mysql_result($identification,0,"message");
+			if($posterid == $userid || rank($userid) > 2){
+				#Process comment delete order
+				$sql = "DELETE FROM comments WHERE id=$cid";
+				mysql_query($sql) or die("Comment Delete Error: ".mysql_error());
+				if($pid){
+					$location = getpacketlink($pid).' posted by '.whoisid($posterid);
+				} else {
+					$location = getdocumentlink($did).' posted by '.whoisid($posterid);
+				}
+				logthis($userid, 'Deleted a comment on '.$location.' that had the message of: '.$message, 'commentdel');
+				WriteData($userid, 'msg', 'Successfully deleted the comment.');
+				if($did){
+					redirect('/?op=doc&did='.$did);
+				} else {
+					redirect('/?op=packet&pid='.$pid);
+				}
+			} else {
+				error('You\'re not authorized to delete this comment.');
+				return;
+			}
+		} else {
+			error('Unable to process.');
+			return;
+		}
+	}
+?>
\ No newline at end of file
diff --git a/register.php b/register.php
new file mode 100644
index 00000000..a37978ed
--- /dev/null
+++ b/register.php
@@ -0,0 +1,123 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth, $ip;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+
+	if(!$_POST['email'] && !$_POST['username']){
+		?>
+			<div id="container">
+			<div id="main2">
+			<h2>Membership Registration</h2>
+			<blockquote>
+			<form method="post" onsubmit="return validate_form(this)" action="/?op=register"><br>
+			&nbsp;&nbsp;Username:<br>
+			&nbsp;&nbsp;<input type="text" id="inputbox" name="username"><br><br>
+			&nbsp;&nbsp;Email:<br>
+			&nbsp;&nbsp;<input type="text" id="inputbox" name="email"><br><br>
+			&nbsp;&nbsp;<input type="checkbox" id="inputbox" name="agree" value="yes">I have read and agree to the <a href="/?op=legalism">terms of service</a>.<br><br>
+			&nbsp;&nbsp;<input type="submit" id="abutton" value="Register"><br>
+			</form>
+			<br></blockquote></div></div>
+		<?
+		$error = 'true';
+	} else {
+		if(!$_POST['agree']){
+			$agree = "<br><br><center><b><font color=red>YOU NEED TO AGREE TO THE TOS BEFORE REGISTERING!</font></b></center>";
+			$error = 'true';
+		}
+		if(!$_POST['email']){
+			?><div id="container">
+			<div id="main2">
+			<h2>Membership Registration</h2>
+			<blockquote>
+			<form method="post" onsubmit="return validate_form(this)" action="/?op=register"><br>
+			&nbsp;&nbsp;Username:<br>
+			&nbsp;&nbsp;<input type="text" id="inputbox" name="username" value="<?=$_POST['username'];?>"><br><br>
+			&nbsp;&nbsp;Email:<br>
+			&nbsp;&nbsp;<input type="text" id="inputbox" name="email"> <font color=red><b>MISSING EMAIL!</b></font><br><br>
+			&nbsp;&nbsp;<input type="checkbox" id="inputbox" name="agree" value="yes">I have read and agree to the <a href="/?op=legalism">terms of service</a>. <?=$agree;?><br><br>
+			&nbsp;&nbsp;<input type="submit" id="abutton" value="Register"><br>
+			</form>
+			<br></blockquote></div></div><?
+			$error = 'true';
+		}
+		if(!$_POST['username']){
+			?><div id="container">
+			<div id="main2">
+			<h2>Membership Registration</h2>
+			<blockquote>
+			<form method="post" onsubmit="return validate_form(this)" action="/?op=register"><br>
+			&nbsp;&nbsp;Username:<br>
+			&nbsp;&nbsp;<input type="text" id="inputbox" name="username"> <font color=red><b>MISSING USERNAME!</b></font><br><br>
+			&nbsp;&nbsp;Email:<br>
+			&nbsp;&nbsp;<input type="text" id="inputbox" name="email" value="<?=$_POST['email'];?>"><br><br>
+			&nbsp;&nbsp;<input type="checkbox" id="inputbox" name="agree" value="yes">I have read and agree to the <a href="/?op=legalism">terms of service</a>. <?=$agree;?><br><br>
+			&nbsp;&nbsp;<input type="submit" id="abutton" value="Register"><br>
+			</form>
+			<br></blockquote></div></div><?
+			$error = 'true';
+		}
+		if($_POST['email'] && $_POST['username'] && !$_POST['agree']){
+			?><div id="container">
+			<div id="main2">
+			<h2>Membership Registration</h2>
+			<blockquote>
+			<form method="post" onsubmit="return validate_form(this)" action="/?op=register"><br>
+			&nbsp;&nbsp;Username:<br>
+			&nbsp;&nbsp;<input type="text" id="inputbox" name="username" value="<?=$_POST['username'];?>"><br><br>
+			&nbsp;&nbsp;Email:<br>
+			&nbsp;&nbsp;<input type="text" id="inputbox" name="email" value="<?=$_POST['email'];?>"><br><br>
+			&nbsp;&nbsp;<input type="checkbox" id="inputbox" name="agree" value="yes">I have read and agree to the <a href="/?op=legalism">terms of service</a>. <br><br>
+			&nbsp;&nbsp;<input type="submit" id="abutton" value="Register"><br>
+			</form>
+			<br></blockquote></div></div><?
+			$error = 'true';
+		}
+		if($_POST['email'] && $_POST['username'] && $_POST['agree']){
+			if(FieldVerify('username', 'users', $_POST['username'])){
+				?><div id="container">
+				<div id="main2">
+				<h2>Membership Registration</h2>
+				<blockquote>
+				<form method="post" onsubmit="return validate_form(this)" action="/?op=register"><br>
+				&nbsp;&nbsp;Username:<br>
+				&nbsp;&nbsp;<input type="text" id="inputbox" name="username"> <font color=red><b>USERNAME ALREADY TAKEN!</b></font><br><br>
+				&nbsp;&nbsp;Email:<br>
+				&nbsp;&nbsp;<input type="text" id="inputbox" name="email" value="<?=$_POST['email'];?>"><br><br>
+				&nbsp;&nbsp;<input type="checkbox" id="inputbox" name="agree" value="yes">I have read and agree to the <a href="/?op=legalism">terms of service</a>. <br><br>
+				&nbsp;&nbsp;<input type="submit" id="abutton" value="Register"><br>
+				</form>
+				<br></blockquote></div></div><?
+				$error = 'true';
+			}
+			if(FieldVerify('email', 'users', $_POST['email'])){
+				$alias = GetInfo('users', 'email', $_POST['email'], 'username');
+				?><div id="container">
+				<div id="main2">
+				<h2>Membership Registration</h2>
+				<center><b><font color=red>
+				You're already registered under the username of <?=$alias;?>.
+				</font></b></center>
+				</div></div><?
+				$error = 'true';
+			}
+			if(!$error){
+				# Now we can finally create the damn account.
+				$username = $_POST['username'];
+				$email = $_POST['email'];
+				CreateUser($username, $email, $ip);
+				?><div id="container">
+				<div id="main2">
+				<h2>Membership Registration</h2>
+				<blockquote><b>You've been registered. Please check your email for your password. If you have not logged in 
+				for two weeks from the time of registration, your account will be automatically deleted. Once 
+				you login, your account will be secured.</b></blockquote>
+				</div></div><?
+			}
+		}
+	}
+?>
diff --git a/resetpw.php b/resetpw.php
new file mode 100644
index 00000000..486f6021
--- /dev/null
+++ b/resetpw.php
@@ -0,0 +1,55 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth, $ip;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+
+	if($_POST['email']) $_POST['email'] = trim($_POST['email']);
+	
+	if(!$_POST['email']){
+		?>
+			<div id="container">
+			<div id="main2">
+			<h2>Reset Password</h2>
+			<blockquote>
+			<form method="post" action="/?op=resetpw"><br>
+			&nbsp;&nbsp;Your Email:<br>
+			&nbsp;&nbsp;<input type="text" id="inputbox" name="email"><br><br>
+			&nbsp;&nbsp;<input type="submit" id="abutton" value="Reset Password"><br>
+			</form>
+			<br></blockquote></div></div>
+		<?
+		$error = 'true';
+	} else {
+		if($_POST['email']){
+			if(FieldVerify("email", "users", $_POST['email'])){
+				$userid = getinfo('users', 'email', $_POST['email'], 'id');
+				ResetPassword($userid);
+				?><div id="container">
+				<div id="main2">
+				<h2>Reset Password</h2>
+				<br><br>
+				<center><b>Your password has been reset and emailed to you.</b></center>
+				<br><br><br>
+				</div></div><?
+			} else {
+				?>
+				<div id="container">
+				<div id="main2">
+				<h2>Reset Password</h2>
+				<blockquote>
+				<form method="post" action="/?op=resetpw"><br>
+				&nbsp;&nbsp;Your Email:<br>
+				&nbsp;&nbsp;<input type="text" id="inputbox" name="email">&nbsp;&nbsp;&nbsp;<b><font color=red>Invalid email (<? echo $_POST['email']; ?>).</font></b><br><br>
+				&nbsp;&nbsp;<input type="submit" id="abutton" value="Reset Password"><br>
+				</form>
+				<br></blockquote></div></div>
+				<?
+				$error = 'true';
+			}
+		}
+	}
+?>
diff --git a/robots.txt b/robots.txt
new file mode 100644
index 00000000..24774089
--- /dev/null
+++ b/robots.txt
@@ -0,0 +1,6 @@
+User-agent: *
+Disallow: /index.php?op=doc&mode=delete
+Disallow: /index.php?op=doc&mode=edit
+Disallow: /index.php?op=packet&mode=delete
+Disallow: /index.php?op=packet&mode=edit
+Disallow: /logsrss.php
diff --git a/sandbox.php b/sandbox.php
new file mode 100644
index 00000000..eeaedf82
--- /dev/null
+++ b/sandbox.php
@@ -0,0 +1,48 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth, $ie;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	if(!$userid) die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+	
+	# Administrators only, block out the rest.
+	
+	if(rank($userid) < 4){
+		error("There's nothing in the sandbox.");
+		return;
+	}
+	
+	# Experimenting with string comparsion
+	
+	$firststring = "This is the first string.";
+	$secondstring = "This is the second string.";
+	$i = GetStrDiff($firststring, $secondstring);
+	if($i){
+		$a = split($i, '|');
+		$final = $a[0].' was changed to '.$a[1];
+	} else {
+		$final = "There was no change between the two strings.";
+	}
+	
+	$finalstring =  "First string: $firststring<br>Second string: $secondstring<br>Differences: $final<br><br>Function result: ";
+	
+	if(!$i){
+		if($firststring != $secondstring){
+			$finalstring .= 'Failure. Function claims no change, but there was a change.';
+		} else {
+			$finalstring .= 'Success!';
+		}
+	} else {
+		if($firststring == $secondstring){
+			$finalstring .= 'Failure. Function claims there was changes, but there was none.';
+		} else {
+			$finalstring .= 'Success!';
+		}
+	}
+	
+	displaydialogbox($finalstring, "Sandbox: String Comparsion Experiment");
+	
+?>
\ No newline at end of file
diff --git a/search.php b/search.php
new file mode 100644
index 00000000..1b982454
--- /dev/null
+++ b/search.php
@@ -0,0 +1,162 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+	
+	#Search BNETDocs
+	$search = $_POST['searchquery'];
+	if(!$search){
+		?>
+		<div id="container">
+		<div id="main2">
+		<h2>Search BNETDocs</h2>
+		<form action="/?op=search" method="POST">
+		<blockquote>
+		<!-- Search For:<br>
+		<input id="inputbox" type="text" size=55 name="searchquery">&nbsp;&nbsp;&nbsp;<input id="abutton" type="submit" value="Search"> -->
+		<font color=red><b>This feature is incomplete, so it has been disabled.</b></font>
+		</blockquote>
+		<div id="author"><center>Factors to include in Search:</center></div>
+		<br><div align=center><table border=0 cellpadding=0 cellspacing=0 width=80%><tr>
+		<td width=100%>
+		<INPUT TYPE=CHECKBOX checked value="yes" NAME="news">News <font color=red size=1> Incomplete</font><br>
+		<INPUT TYPE=CHECKBOX checked value="yes" NAME="documents">Documents <font color=red size=1> Incomplete</font><br>
+		<INPUT TYPE=CHECKBOX checked value="yes" NAME="bnetmsgs">Battle.net Messages <font color=red size=1> Incomplete</font><br>
+		<INPUT TYPE=CHECKBOX checked value="yes" NAME="bnetudpmsgs">Battle.net UDP Messages <font color=red size=1> Incomplete</font><br>
+		<INPUT TYPE=CHECKBOX checked value="yes" NAME="realmmsgs">Realm Messages <font color=red size=1> Incomplete</font><br>
+		</td>
+		<td width=0% nowrap>
+		<INPUT TYPE=CHECKBOX checked value="yes" NAME="botnetmsgs">BotNet Messages <font color=red size=1> Incomplete</font><br>
+		<INPUT TYPE=CHECKBOX checked value="yes" NAME="bnlsmsgs">BNLS Messages <font color=red size=1> Incomplete</font><br>
+		<INPUT TYPE=CHECKBOX checked value="yes" NAME="d2gsmgs">D2GS Messages <font color=red size=1> Incomplete</font><br>
+		<INPUT TYPE=CHECKBOX checked value="yes" NAME="comments">Comments <font color=red size=1> Incomplete</font><br>
+		<INPUT TYPE=CHECKBOX checked value="yes" NAME="users">Users<br>
+		</td></tr></table></div>
+		</form><br>
+		<div id="author"><center>Tips on Searching the BNETDocs:</center></div>
+		<br><blockquote>
+		The search engine will search through the specificed articles for the given keywords. 
+		If you'd like specific articles to be searched, please select articles to factor in the search.<br>
+		<br>
+		AND, OR, NOT are recognized as valid operators.<br>
+		</blockquote>
+		<br>
+		</div></div>
+		<?
+	} else {
+		?>
+		<div id="container">
+		<div id="main2">
+		<h2>BNETDocs Search Results</h2>
+		<blockquote>
+			<?
+			extract($_POST);
+		    echo 'Search Keywords Used: '.$search.'<br><br>';
+		    $arrSearch = explode(" ", $search);
+			if($news){															#Enable searching by poster
+			    for ($i=0; $i<count($arrSearch); $i++) {
+					if (strToUpper($arrSearch[$i])=='AND' or strToUpper($arrSearch[$i])=='OR' or strToUpper($arrSearch[$i])=='NOT') {
+						if (strToUpper($arrSearch[$i])=='NOT') {
+							if($i > 0){
+								if (strToUpper($arrSearch[$i - 1])=='AND' or strToUpper($arrSearch[$i - 1])=='OR' or strToUpper($arrSearch[$i - 1])=='NOT'){
+									# Append nothing. Operator already used.
+								} else {
+									$strWhere = $strWhere.' AND '; #ASSUME AND
+								}	
+							}
+							$i++;
+							$strWhere = $strWhere." content NOT LIKE '%".$arrSearch[$i]."%' ";
+						} else {
+							$strWhere = $strWhere." ".strToUpper($arrSearch[$i])." ";
+						}
+					} else {
+						if($strWhere != ''){
+							if($i > 0){
+								if (strToUpper($arrSearch[$i - 1])=='AND' or strToUpper($arrSearch[$i - 1])=='OR' or strToUpper($arrSearch[$i - 1])=='NOT'){
+									# Append nothing. Operator already used.
+								} else {
+									if($strWhere != '') $strWhere = $strWhere.' AND '; #ASSUME AND
+								}	
+							}
+						}
+						$strWhere = $strWhere."content LIKE '%".$arrSearch[$i]."%' ";
+					}
+			    }
+			    $sql="SELECT * FROM news WHERE ".$strWhere." ORDER BY id";
+				
+			    $rsCat_query=mysql_query($sql); 
+				#echo '<big>'.$sql.'</big><br>';
+				#$rsCat_query=mysql_query($sql) OR die (mysql_error());
+				
+			    if (!(mysql_errno()==0)) {
+				    echo '<big>There was a problem with the query syntax.</big><br>'; #log the error!
+			    }
+			    if (mysql_num_rows($rsCat_query)==0) {
+				    echo '<big>No items were found matching the criteria in the news database.</big><br>';
+				} else {
+					echo 'Results from checking the news database:<br><br>';
+				}
+			    while($rsCat = mysql_fetch_array($rsCat_query)) {
+					?><div id="author"><center><? echo $rsCat['subject']; ?></center></div><?
+				    echo $rsCat['content'].'<br><br>';
+			    }
+				echo '<br><hr><br>';
+			}
+		
+			$strWhere = ''; $sql = '';
+			
+			if($users){
+			    for ($i=0; $i<count($arrSearch); $i++) {
+					if (strToUpper($arrSearch[$i])=='AND' or strToUpper($arrSearch[$i])=='OR' or strToUpper($arrSearch[$i])=='NOT') {
+						if (strToUpper($arrSearch[$i])=='NOT') {
+							if($i > 0){
+								if (strToUpper($arrSearch[$i - 1])=='AND' or strToUpper($arrSearch[$i - 1])=='OR' or strToUpper($arrSearch[$i - 1])=='NOT'){
+									# Append nothing. Operator already used.
+								} else {
+									$strWhere = $strWhere.' AND '; #ASSUME AND
+								}	
+							}
+							$i++;
+							$strWhere = $strWhere." username != '".$arrSearch[$i]."'";
+						} else {
+							$strWhere = $strWhere." ".strToUpper($arrSearch[$i])." ";
+						}
+					} else {
+						if (strToUpper($arrSearch[$i - 1])=='AND' or strToUpper($arrSearch[$i - 1])=='OR' or strToUpper($arrSearch[$i - 1])=='NOT'){
+							# Append nothing. Operator already used.
+						} else {
+							if($strWhere != '') $strWhere = $strWhere.' OR '; #Assume OR
+						}	
+						$strWhere = $strWhere." username LIKE '".$arrSearch[$i]."'";
+					}
+			    }
+			    $sql="SELECT * FROM users WHERE ".$strWhere." ORDER BY id";
+				
+			    $rsCat_query=mysql_query($sql); 
+				#echo '<big>'.$sql.'</big><br>';
+				#$rsCat_query=mysql_query($sql) OR die (mysql_error());
+				
+			    if (!(mysql_errno()==0)) {
+				    echo '<big>There was a problem with the query syntax.</big><br>'; #log the error!
+			    }
+			    if (mysql_num_rows($rsCat_query)==0) {
+				    echo '<big>No items were found matching the criteria in the user database.</big><br>';
+				} else {
+					echo 'The following users were found in the database:<br><br>';
+				}
+			    while($rsCat = mysql_fetch_array($rsCat_query)) {
+				    echo $rsCat['username'].'<br>';
+			    }
+			}
+			
+			echo '<br><a href="/?op=search">Back</a><br>';
+			?>
+		</blockquote>
+		</div></div>
+		<?
+	}
+?>
\ No newline at end of file
diff --git a/security_intrusion.html b/security_intrusion.html
new file mode 100644
index 00000000..4d6c6ef7
--- /dev/null
+++ b/security_intrusion.html
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html>
+  <head>
+    <title>BnetDocs: Redux</title>
+    <meta http-equiv="Content-Type" content="text/html;charset=utf-8" />
+    <style type="text/css">
+      body { background: #fafafa; color: #000; font: 11pt sans-serif; margin: 0; padding: 0; text-align: center; }
+      div { background: #eaeaea; border-radius: 16px; box-sizing: border-box; margin: 32px auto; padding: 4px 10px; width: 600px; }
+      p.s { font-size: 8pt; }
+    </style>
+  </head>
+  <body>
+    <div>
+      <h1>503 Service Temporarily Unavailable</h1>
+      <p>Due to a recent security intrusion, the site has been taken offline. If you need the BnetDocs documentation this very moment, <a href="https://google.com/search?q=cache:bnetdocs.org">check google cache</a>.</p>
+      <p class="s">posted March 21 2014 02:36 CDT by Jailout2000</p>
+    </div>
+  </body>
+</html>
+
diff --git a/sessionhandler.php b/sessionhandler.php
new file mode 100644
index 00000000..fa549bc4
--- /dev/null
+++ b/sessionhandler.php
@@ -0,0 +1,85 @@
+<?
+	# Declare security variable
+	
+	$auth = 'true';
+	
+	# Include needed files
+	
+	include 'db.php';
+	include 'functions.php';
+	
+	# Security
+	
+	$code = $_GET['code'];
+	
+	if($code != "arta"){
+		logthis($userid, 'Illegally attempted to access sessionhandler.php. Attempt blocked.', 'hack');
+		blockhack();
+	}
+	
+	# Pull up all sessions, get time, compare time last accessed site to current time.
+	
+	$sqlquery = 'SELECT * FROM sessions WHERE notimelimit=0 ORDER BY dtstamp ASC';
+	$membersarray = mysql_query($sqlquery);
+	while($row = mysql_fetch_array($membersarray)){
+		$userid = $row['id'];
+		$dtstamp = strtotime($row['dtstamp']);
+		$currenttime = time();
+		#echo "$currenttime - $dtstamp = ".($currenttime - $dtstamp)." which converts to ".(($currenttime - $dtstamp) / 60)." minutes.<br>";
+		if($currenttime - $dtstamp > 60 * 15){ #15 minutes since last logged activity has elapsed
+			#log 'em out
+			KillSession($userid);
+			#logthis($userid, 'logged out.', 'session');
+			#echo whoisid($userid).' has been identified as inactive.<br>';
+		}
+	} 
+	
+	# Pull up all unsecured accounts, get time, compare time of registration to current time.
+	
+	$sqlquery = 'SELECT * FROM users WHERE secured="" ORDER BY dtstamp ASC';
+	$membersarray = mysql_query($sqlquery);
+	while($row = mysql_fetch_array($membersarray)){
+		$userid = $row['id'];
+		$dtstamp = strtotime($row['dtstamp']);
+		$currenttime = time();
+		#echo "$currenttime - $dtstamp = ".($currenttime - $dtstamp)." which converts to ".(($currenttime - $dtstamp) / 60)." minutes.<br>";
+		if($currenttime - $dtstamp > 60 * 60 * 24 * 7 * 2){ #2 weeks (seconds, minutes, hours, days, weeks)
+			#kill 'em
+			$body = "Hello!
+		
+You previously registered as an user of BNETDocs. If this email is in error, simply ignore this email.
+
+If this is you, please read on. 
+Username: $username
+
+Unfortunately, because you did not confirm the registration for the last two weeks, your account has been deleted. All new accounts are required to confirm their registration.
+
+Confirming registration is as simple as logging in your account at BNETDocs.
+
+We regret having to remove the account. This was done to save space on the server. 
+
+If you'd like your account back, please DO feel free to re-register, and this time, please remember to confirm your registration by logging in as soon as you get the registration confirmation email that contains your login information.
+
+Website: http://www.bnetdocs.org
+
+Once more, our apologies!
+
+Regards,
+BNETDocs
+
+---------
+Please do not respond to this email, this email was automatically generated.
+If you have any questions, comments, etc, feel free to contact one of the administrators.
+---------";
+			$email = GetData($userid, 'email');
+			Email($email, 'postmaster@bnetdocs.org', 'BNETDocs: A problem with your account!', $body);
+			#logthis($userid, 'Failed to confirm their registration. Account deleted.', 'account');
+			DeleteUser($userid);
+		}
+	} 
+	# Finished checking accounts. 
+	
+	#Terminate.
+	echo "handle session done.";
+	exit();
+?>
\ No newline at end of file
diff --git a/temp/logsrss.php b/temp/logsrss.php
new file mode 100644
index 00000000..7f3026bb
--- /dev/null
+++ b/temp/logsrss.php
@@ -0,0 +1,110 @@
+<?
+	################################
+	##	RSS Feed Generator for logs   ##
+	################################
+	
+	# \n = newline, \t = tab
+	
+	function CropSentence ($strText, $intLength, $strTrail) {
+		$wsCount = 0;
+		$intTempSize = 0;
+		$intTotalLen = 0;
+		$intLength = $intLength - strlen($strTrail);
+		$strTemp = "";
+
+		if (strlen($strText) > $intLength) {
+			$arrTemp = explode(" ", $strText);
+			foreach ($arrTemp as $x) {
+				if (strlen($strTemp) <= $intLength) $strTemp .= " " . $x;
+			}
+			$CropSentence = $strTemp . $strTrail;
+		} else {
+			$CropSentence = $strText;
+		}
+
+		return $CropSentence;
+	} 
+	
+	function replaceOnce($search, $replace, $content){
+	    $pos = strpos($content, $search) + 1;
+		$pos = strpos($content, $search, $pos);
+	    if ($pos === false) { 
+			return $content; 
+		} else { 
+			return substr($content, 0, $pos) . $replace . substr($content, $pos+strlen($search)); 
+		}
+	}
+
+	$auth = 'true';
+	include 'functions.php';
+	include 'db.php';
+	
+	header("Content-Type: application/xml; charset=utf-8");
+	
+	echo '<?xml version="1.0" encoding="utf-8"?>';
+	echo '<rss version="2.0">';
+	echo '<channel>';
+	echo '<title>BNETDocs Logs</title>';
+	echo '<link>http://www.bnetdocs.org/?op=viewlogs</link>';
+	echo '<description>Summarized logs of user activities on BNETDocs</description>';
+	echo '<language>en-us</language>';
+	echo '<docs>http://blogs.law.harvard.edu/tech/rss</docs>';
+	echo '<copyright>Site scripts and design copyrights reserved to Don Cullen. Contents copyrighted to Blizzard and their parent corporation, Vivendi. Copyright infringements will be prosecuted to the fullest extent allowable by law. Please view our legal disclaimer and terms of service.</copyright>';
+
+	$privatestring = "WHERE eventtype != 'CONFIDENTAL' AND eventtype != 'vip' AND eventtype != 'registration' AND eventtype != 'account' AND eventtype != 'hack'";
+	$privatestring .= " group by CONCAT(user,datetime,eventtype) ";
+	$consolidate = '&consolidate=true';
+	
+    $limit          = 25;               
+    $query_count    = "SELECT * FROM logs $privatestring";
+    $result_count   = mysql_query($query_count);
+    $totalrows      = mysql_num_rows($result_count); 
+	
+	$query  = "SELECT * FROM logs $privatestring ORDER BY id desc LIMIT $limit";
+	
+    $result = mysql_query($query) or die("Error: " . mysql_error()); 
+
+	while($row = mysql_fetch_array($result)){
+	
+		echo '<item>';
+		
+		$summary = CropSentence(strip_tags(codify($row['event'], true) ), 500, '...');
+		
+		if($row['eventtype'] == 'docedit') $row['event'] = 'edited documents.';
+		if($row['eventtype'] == 'newsdelete') $row['event'] = 'deleted news posts.';
+		if($row['eventtype'] == 'newsedit') $row['event'] = 'edited news posts.';
+		if($row['eventtype'] == 'newspost') $row['event'] = 'submitted news posts.';
+		if($row['eventtype'] == 'pktadd') $row['event'] = 'added packets.';
+		if($row['eventtype'] == 'pktedit') $row['event'] = 'edited packets.';
+		if($row['eventtype'] == 'pktdel') $row['event'] = 'deleted packets.';
+		if($row['eventtype'] == 'registration') $row['event'] = 'registered to be a member.';
+		if($row['eventtype'] == 'commentedit') $row['event'] = 'edited comments.';
+		if($row['eventtype'] == 'commentadd') $row['event'] = 'posted comments.';
+		if($row['eventtype'] == 'commentdel') $row['event'] = 'deleted comments.';
+		
+		$content = CropSentence(strip_tags(codify(str_ireplace("\'", "'", $row['event']), true) ), 500, '...');
+		$summary = CropSentence(strip_tags(codify(str_ireplace("\'", "'", $summary), true) ), 500, '...');
+		
+		$initator = $row['user'];
+		
+		$content = ucfirst(whoisid($initator)).' '.lcfirst($content);
+		
+		$timestamp = date("D, d M Y H:i:s", strtotime(substr($row['datetime'], strpos($row['datetime'], ',') + 2))).' PST';
+		$timestamp = substr($row['datetime'], strpos($row['datetime'], ',') + 2).' PST';
+		$timestamp = replaceOnce(' ', ', ', $timestamp);
+		$timestamp = date("D, d M Y H:i:s", strtotime($timestamp)).' PST';
+
+		echo '<title>'.htmlspecialchars ($content, ENT_QUOTES).'</title>';
+		echo '<link>http://www.bnetdocs.org/?op=viewlogs&amp;id='.$row['id'].'</link>';
+		echo '<guid>http://www.bnetdocs.org/?op=viewlogs&amp;id='.$row['id'].'</guid>';
+		echo '<description>'.htmlspecialchars ($summary, ENT_QUOTES).' Activity logged at: '.$row['datetime'].'</description>';
+		echo '<pubDate>'.$timestamp.'</pubDate>';
+		echo '</item>';
+	
+    }
+
+    mysql_free_result($result);
+
+	echo '</channel>';
+	echo '</rss>';
+?>
\ No newline at end of file
diff --git a/test.php b/test.php
new file mode 100644
index 00000000..86c96987
--- /dev/null
+++ b/test.php
@@ -0,0 +1,3 @@
+<?
+	echo $_REQUEST['direction'];
+?>
\ No newline at end of file
diff --git a/usercss/1337D00D.css b/usercss/1337D00D.css
new file mode 100644
index 00000000..7048af93
--- /dev/null
+++ b/usercss/1337D00D.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Accused.css b/usercss/Accused.css
new file mode 100644
index 00000000..7048af93
--- /dev/null
+++ b/usercss/Accused.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Alendar.css b/usercss/Alendar.css
new file mode 100644
index 00000000..87bb5ecf
--- /dev/null
+++ b/usercss/Alendar.css
@@ -0,0 +1,224 @@
+body 
+{
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	font-family: arial;
+}
+
+select
+{ 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: arial;
+	font-size: 14px;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 275px;
+	height: 515px;
+	overflow: auto;
+text-decoration:none;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#textonlylogo	{	display: none;	}
+
+#bg
+{
+	position: fixed;
+	top: 0;
+	left: 0;
+}
+
+#viewcode
+{
+	font-size: 10px;
+}
+
+#content
+{
+	position: relative; 
+	z-index: 1;
+}
+
+img	{	border: none;	}
+
+#container
+{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border: 2px solid blue;
+	border-spacing: 2px;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer
+{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2
+{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author
+{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p
+{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights
+{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox
+{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: arial;
+	font-size: 14px;
+	text-align: left
+}
+
+#abutton
+{
+	font-family: arial;
+	font-size: 14px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a
+{
+    font-size: 14px;
+}
+
+a	{	color: blue;	}
+a:hover	{	color: #00CCCC;	}
+
+#code{
+	color: black;
+	background: white;
+	overflow: auto;
+	font: normal 12px "bitstream vera sans mono", monaco. "lucida console", "courier new", courier, serif;
+	background-image: url('../images/barbgwhitecyan.jpg'); /* removed because its bugging me */
+	margin: 0.9em 0; padding: 8px;
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important
+{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+div.menu a
+{
+	font: bold 14pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span
+{
+	padding: 3px;
+text-decoration:none;
+}
+
+div.menu a:hover
+{
+	background: #ffcc33;
+text-decoration:none;
+}
\ No newline at end of file
diff --git a/usercss/Camel.css b/usercss/Camel.css
new file mode 100644
index 00000000..59a1f626
--- /dev/null
+++ b/usercss/Camel.css
@@ -0,0 +1,216 @@
+body 
+{
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	font-family: arial;
+}
+
+select
+{ 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: arial;
+	font-size: 14px;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 275px;
+	height: 515px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#textonlylogo	{	display: none;	}
+
+#bg
+{
+	position: fixed;
+	top: 0;
+	left: 0;
+}
+
+#viewcode
+{
+	font-size: 10px;
+}
+
+#content
+{
+	position: relative; 
+	z-index: 1;
+}
+
+img	{	border: none;	}
+
+#container
+{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border: 2px solid blue;
+	border-spacing: 2px;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer
+{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2
+{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author
+{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p
+{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights
+{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox
+{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: arial;
+	font-size: 14px;
+	text-align: left
+}
+
+#abutton
+{
+	font-family: arial;
+	font-size: 14px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a	{	color: blue; text-decoration: none;	}
+a:hover	{	color: #00CCCC;	}
+
+#code{
+	color: black;
+	background: white;
+	overflow: auto;
+	font: normal 12px "bitstream vera sans mono", monaco. "lucida console", "courier new", courier, serif;
+	background-image: url('../images/barbgwhitecyan.jpg'); /* removed because its bugging me */
+	margin: 0.9em 0; padding: 8px;
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important
+{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+div.menu a
+{
+	font: bold 14pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span
+{
+	padding: 3px;
+}
+
+div.menu a:hover
+{
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Chriso.css b/usercss/Chriso.css
new file mode 100644
index 00000000..7048af93
--- /dev/null
+++ b/usercss/Chriso.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/DeFirence.css b/usercss/DeFirence.css
new file mode 100644
index 00000000..7048af93
--- /dev/null
+++ b/usercss/DeFirence.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Dragon_Legion.css b/usercss/Dragon_Legion.css
new file mode 100644
index 00000000..7048af93
--- /dev/null
+++ b/usercss/Dragon_Legion.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Goliath.css b/usercss/Goliath.css
new file mode 100644
index 00000000..7048af93
--- /dev/null
+++ b/usercss/Goliath.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Hdx.css b/usercss/Hdx.css
new file mode 100644
index 00000000..1ad7a385
--- /dev/null
+++ b/usercss/Hdx.css
@@ -0,0 +1,221 @@
+body 
+{
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	font-family: arial;
+}
+
+select
+{ 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: arial;
+	font-size: 14px;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 275px;
+	height: 515px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#textonlylogo	{	display: none;	}
+
+#bg
+{
+	position: fixed;
+	top: 0;
+	left: 0;
+}
+
+#viewcode
+{
+	font-size: 10px;
+}
+
+#content
+{
+	position: relative; 
+	z-index: 1;
+}
+
+img	{	border: none;	}
+
+#container
+{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border: 2px solid blue;
+	border-spacing: 2px;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer
+{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2
+{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author
+{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p
+{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights
+{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox
+{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: arial;
+	font-size: 14px;
+	text-align: left
+}
+
+#abutton
+{
+	font-family: arial;
+	font-size: 14px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a
+{
+    font-size: 14px;
+}
+
+a	{	color: blue;	}
+a:hover	{	color: #00CCCC;	}
+
+#code{
+	color: black;
+	background: white;
+	overflow: auto;
+	font: normal 12px "bitstream vera sans mono", monaco. "lucida console", "courier new", courier, serif;
+	background-image: url('../images/barbgwhitecyan.jpg'); /* removed because its bugging me */
+	margin: 0.9em 0; padding: 8px;
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important
+{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+div.menu a
+{
+	font: bold 14pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span
+{
+	padding: 3px;
+}
+
+div.menu a:hover
+{
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Hell-Lord.css b/usercss/Hell-Lord.css
new file mode 100644
index 00000000..365bc0fa
--- /dev/null
+++ b/usercss/Hell-Lord.css
@@ -0,0 +1,212 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+}
+
+select  { 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#viewcode {
+	color: black;
+	font-size: 10px;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border-width: 2px;
+	border-spacing: 2px;
+	border-style: solid;
+	border-color: blue;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+}
+
+div#punch2{
+	float: left; 
+	width: 100px; 
+	height: 75px; 
+	text-align: center; 
+	color: white; 
+	border-width: 0 1px 1px 0; 
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+	display: none;
+}
+
+div#punch2 img{
+	height: 75px; 
+	width: 100px;
+	display: none;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: left
+}
+
+#abutton{
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a:link{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none; 
+}
+
+a:visited{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:active{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:hover{
+	color: #00CCCC;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+#code{
+	color: black;				 /* Foreground color */
+	background: white;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url('../images/barbgwhitecyan.jpg');
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Imperceptus.css b/usercss/Imperceptus.css
new file mode 100644
index 00000000..b289b61d
--- /dev/null
+++ b/usercss/Imperceptus.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 18px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 18px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 18px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Jailout2000.css b/usercss/Jailout2000.css
new file mode 100644
index 00000000..0b454d49
--- /dev/null
+++ b/usercss/Jailout2000.css
@@ -0,0 +1,238 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyDocuments span {
+    float: right;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background: black url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+select{
+	background: #000000;
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Joe[x86].css b/usercss/Joe[x86].css
new file mode 100644
index 00000000..4456c1ae
--- /dev/null
+++ b/usercss/Joe[x86].css
@@ -0,0 +1,227 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 250px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+        size: 4pt;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+}
+
+div#punch2{
+	float: left; 
+	width: 100px; 
+	height: 75px; 
+	text-align: center; 
+	color: white; 
+	border-width: 0 1px 1px 0; 
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#punch2 img{
+	height: 75px; 
+	width: 100px;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Kyro.css b/usercss/Kyro.css
new file mode 100644
index 00000000..f89372de
--- /dev/null
+++ b/usercss/Kyro.css
@@ -0,0 +1,220 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Leaky.css b/usercss/Leaky.css
new file mode 100644
index 00000000..0319b1fe
--- /dev/null
+++ b/usercss/Leaky.css
@@ -0,0 +1,222 @@
+body 
+{
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	font-family: arial;
+}
+
+select
+{ 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: arial;
+	font-size: 14px;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 275px;
+	height: 515px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#textonlylogo	{	display: none;	}
+
+#bg
+{
+	position: fixed;
+	top: 0;
+	left: 0;
+}
+
+#viewcode
+{
+	font-size: 10px;
+}
+
+#content
+{
+	position: relative; 
+	z-index: 1;
+}
+
+img	{	border: none;	}
+
+#container
+{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border: 2px solid blue;
+	border-spacing: 2px;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer
+{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2
+{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author
+{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-family: Verdana, Arial, Sans-serif;
+	font-size: 8pt;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p
+{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights
+{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox
+{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: arial;
+	font-size: 14px;
+	text-align: left
+}
+
+#abutton
+{
+	font-family: arial;
+	font-size: 14px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a
+{
+    font-size: 14px;
+}
+
+a	{	color: blue;	}
+a:hover	{	color: #00CCCC;	}
+
+#code{
+	color: black;
+	background: white;
+	overflow: auto;
+	font: normal 12px "bitstream vera sans mono", monaco. "lucida console", "courier new", courier, serif;
+	background-image: url('../images/barbgwhitecyan.jpg'); /* removed because its bugging me */
+	margin: 0.9em 0; padding: 8px;
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important
+{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+div.menu a
+{
+	font: bold 14pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span
+{
+	padding: 3px;
+}
+
+div.menu a:hover
+{
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/LordVader.css b/usercss/LordVader.css
new file mode 100644
index 00000000..de83cb44
--- /dev/null
+++ b/usercss/LordVader.css
@@ -0,0 +1,221 @@
+body 
+{
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	font-family: arial;
+}
+
+select
+{ 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: arial;
+	font-size: 14px;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 280px;
+	height: 515px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#textonlylogo	{	display: none;	}
+
+#bg
+{
+	position: fixed;
+	top: 0;
+	left: 0;
+}
+
+#viewcode
+{
+	font-size: 10px;
+}
+
+#content
+{
+	position: relative; 
+	z-index: 1;
+}
+
+img	{	border: none;	}
+
+#container
+{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border: 2px solid blue;
+	border-spacing: 2px;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer
+{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2
+{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author
+{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p
+{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights
+{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox
+{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: arial;
+	font-size: 14px;
+	text-align: left
+}
+
+#abutton
+{
+	font-family: arial;
+	font-size: 14px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a
+{
+    font-size: 14px;
+}
+
+a	{	color: blue;	}
+a:hover	{	color: #00CCCC;	}
+
+#code{
+	color: black;
+	background: white;
+	overflow: auto;
+	font: normal 12px "bitstream vera sans mono", monaco. "lucida console", "courier new", courier, serif;
+	background-image: url('../images/barbgwhitecyan.jpg'); /* removed because its bugging me */
+	margin: 0.9em 0; padding: 8px;
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important
+{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+div.menu a
+{
+	font: bold 14pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span
+{
+	padding: 3px;
+}
+
+div.menu a:hover
+{
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Mixter.css b/usercss/Mixter.css
new file mode 100644
index 00000000..93da0cd8
--- /dev/null
+++ b/usercss/Mixter.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: red;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: red;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/PapayaDealer.css b/usercss/PapayaDealer.css
new file mode 100644
index 00000000..58e0c90b
--- /dev/null
+++ b/usercss/PapayaDealer.css
@@ -0,0 +1,217 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#logo {
+display: none;
+}
+
+#viewcode {
+	color: black;
+	font-size: 10px;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border-width: 2px;
+	border-spacing: 2px;
+	border-style: solid;
+	border-color: blue;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	display: none;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox{
+	background-color: white;
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: left
+}
+
+#abutton{
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a:link{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none; 
+}
+
+a:visited{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:active{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:hover{
+	color: #00CCCC;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+#code{
+	color: black;				 /* Foreground color */
+	background: white;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it\'s too long */
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#frills{
+display: none;
+}
+
+#important{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Ribose.css b/usercss/Ribose.css
new file mode 100644
index 00000000..3a5bfb5e
--- /dev/null
+++ b/usercss/Ribose.css
@@ -0,0 +1,208 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height: 100%;
+	width: 100%;
+	padding: 0;
+        line-height: 100%;
+}
+
+select  { 
+	color: #000;
+	background-color: #FFF;
+	background: url('/images/barbg.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position: relative; 
+	z-index: 1;
+}
+
+img{
+	border: none;
+}
+
+#container {
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer {
+	background-image: url(/images/fade.png);
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+}
+
+div#punch2{
+	float: left; 
+	width: 100px; 
+	height: 75px; 
+	text-align: center; 
+	color: white; 
+	border-width: 0 1px 1px 0; 
+	padding: 0px;
+	margin: 10px 10px 0px 1px;
+}
+
+div#punch2 img {
+	height: 75px; 
+	width: 100px;
+}
+
+div#main2 h2 {
+	margin: 0px;
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author {
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+}
+
+div#main2 p {
+	padding: 0.5em 1em; 
+	margin: 0px;
+}
+
+div#copyrights {
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0px;
+	border-top: 1px solid #000;
+}
+
+#inputbox {
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: left;
+}
+
+#abutton {
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a:link {
+	color: lime;
+	text-decoration: underline;
+	text-transform: none; 
+}
+
+a:visited {
+	color: lime;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:active {
+	color: lime;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:hover {
+	color: #FF0000;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+#code {
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url('../images/barbg.jpg');
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important {
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
+
+div.togglable {
+        display: none;
+}
\ No newline at end of file
diff --git a/usercss/RichardNixon.css b/usercss/RichardNixon.css
new file mode 100644
index 00000000..58e0c90b
--- /dev/null
+++ b/usercss/RichardNixon.css
@@ -0,0 +1,217 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#logo {
+display: none;
+}
+
+#viewcode {
+	color: black;
+	font-size: 10px;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border-width: 2px;
+	border-spacing: 2px;
+	border-style: solid;
+	border-color: blue;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	display: none;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox{
+	background-color: white;
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: left
+}
+
+#abutton{
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a:link{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none; 
+}
+
+a:visited{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:active{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:hover{
+	color: #00CCCC;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+#code{
+	color: black;				 /* Foreground color */
+	background: white;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it\'s too long */
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#frills{
+display: none;
+}
+
+#important{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Sixen.css b/usercss/Sixen.css
new file mode 100644
index 00000000..1ad7a385
--- /dev/null
+++ b/usercss/Sixen.css
@@ -0,0 +1,221 @@
+body 
+{
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	font-family: arial;
+}
+
+select
+{ 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: arial;
+	font-size: 14px;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 275px;
+	height: 515px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#textonlylogo	{	display: none;	}
+
+#bg
+{
+	position: fixed;
+	top: 0;
+	left: 0;
+}
+
+#viewcode
+{
+	font-size: 10px;
+}
+
+#content
+{
+	position: relative; 
+	z-index: 1;
+}
+
+img	{	border: none;	}
+
+#container
+{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border: 2px solid blue;
+	border-spacing: 2px;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer
+{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2
+{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author
+{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p
+{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights
+{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox
+{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: arial;
+	font-size: 14px;
+	text-align: left
+}
+
+#abutton
+{
+	font-family: arial;
+	font-size: 14px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a
+{
+    font-size: 14px;
+}
+
+a	{	color: blue;	}
+a:hover	{	color: #00CCCC;	}
+
+#code{
+	color: black;
+	background: white;
+	overflow: auto;
+	font: normal 12px "bitstream vera sans mono", monaco. "lucida console", "courier new", courier, serif;
+	background-image: url('../images/barbgwhitecyan.jpg'); /* removed because its bugging me */
+	margin: 0.9em 0; padding: 8px;
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important
+{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+div.menu a
+{
+	font: bold 14pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span
+{
+	padding: 3px;
+}
+
+div.menu a:hover
+{
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/TaintedWorks.css b/usercss/TaintedWorks.css
new file mode 100644
index 00000000..eec507f1
--- /dev/null
+++ b/usercss/TaintedWorks.css
@@ -0,0 +1,227 @@
+body 
+{
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	font-family: arial;
+}
+
+select
+{ 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: arial;
+	font-size: 14px;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 275px;
+	height: 515px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#textonlylogo	{	display: none;	}
+
+#bg
+{
+	position: fixed;
+	top: 0;
+	left: 0;
+}
+
+#viewcode
+{
+	font-size: 10px;
+}
+
+#content
+{
+	position: relative; 
+	z-index: 1;
+}
+
+img	{	border: none;	}
+
+#container
+{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border: 2px solid blue;
+	border-spacing: 2px;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer
+{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+}
+
+div#punch2
+{
+	float: left; 
+	width: 100px; 
+	height: 75px; 
+	text-align: center; 
+	color: white; 
+	border-width: 0 1px 1px 0; 
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+	display: none;
+}
+
+div#punch2 img
+{
+	height: 75px; 
+	width: 100px;
+	display: none;
+}
+
+div#main2 h2
+{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author
+{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+}
+
+div#main2 p
+{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights
+{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox
+{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: arial;
+	font-size: 14px;
+	text-align: left
+}
+
+#abutton
+{
+	font-family: arial;
+	font-size: 14px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a
+{
+    font-size: 14px;
+}
+
+a	{	color: blue;	}
+a:hover	{	color: #00CCCC;	}
+
+#code{
+	color: black;
+	background: white;
+	overflow: auto;
+	font: normal 12px "bitstream vera sans mono", monaco. "lucida console", "courier new", courier, serif;
+	background-image: url('../images/barbgwhitecyan.jpg'); /* removed because its bugging me */
+	margin: 0.9em 0; padding: 8px;
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important
+{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+div.menu a
+{
+	font: bold 14pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span
+{
+	padding: 3px;
+}
+
+div.menu a:hover
+{
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/Toss83.css b/usercss/Toss83.css
new file mode 100644
index 00000000..1ad7a385
--- /dev/null
+++ b/usercss/Toss83.css
@@ -0,0 +1,221 @@
+body 
+{
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	font-family: arial;
+}
+
+select
+{ 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: arial;
+	font-size: 14px;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 275px;
+	height: 515px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#textonlylogo	{	display: none;	}
+
+#bg
+{
+	position: fixed;
+	top: 0;
+	left: 0;
+}
+
+#viewcode
+{
+	font-size: 10px;
+}
+
+#content
+{
+	position: relative; 
+	z-index: 1;
+}
+
+img	{	border: none;	}
+
+#container
+{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border: 2px solid blue;
+	border-spacing: 2px;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer
+{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2
+{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author
+{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p
+{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights
+{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox
+{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: arial;
+	font-size: 14px;
+	text-align: left
+}
+
+#abutton
+{
+	font-family: arial;
+	font-size: 14px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a
+{
+    font-size: 14px;
+}
+
+a	{	color: blue;	}
+a:hover	{	color: #00CCCC;	}
+
+#code{
+	color: black;
+	background: white;
+	overflow: auto;
+	font: normal 12px "bitstream vera sans mono", monaco. "lucida console", "courier new", courier, serif;
+	background-image: url('../images/barbgwhitecyan.jpg'); /* removed because its bugging me */
+	margin: 0.9em 0; padding: 8px;
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important
+{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+div.menu a
+{
+	font: bold 14pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span
+{
+	padding: 3px;
+}
+
+div.menu a:hover
+{
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/buzz44.css b/usercss/buzz44.css
new file mode 100644
index 00000000..26fc16b4
--- /dev/null
+++ b/usercss/buzz44.css
@@ -0,0 +1,183 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+}
+
+#logo {
+display: none;
+}
+
+#viewcode {
+	color: black;
+	font-size: 10px;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border-width: 2px;
+	border-spacing: 2px;
+	border-style: solid;
+	border-color: blue;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+}
+
+div#punch2{
+	display: none;
+}
+
+div#punch2 img{
+	display: none;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox{
+	background-color: white;
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: left
+}
+
+#abutton{
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a:link{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none; 
+}
+
+a:visited{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:active{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:hover{
+	color: #00CCCC;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+#code{
+	color: black;				 /* Foreground color */
+	background: white;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#frills{
+display: none;
+}
+
+#important{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/dark.css b/usercss/dark.css
new file mode 100644
index 00000000..aabebb37
--- /dev/null
+++ b/usercss/dark.css
@@ -0,0 +1,228 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyDocuments span {
+    float: right;
+	padding-right: 1pt;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	/* width: 225px; */
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select{
+	/* background: #000000 url(/images/barbg.jpg); */
+	background: #000000;
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background: black url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/default.css b/usercss/default.css
new file mode 100644
index 00000000..d933ff26
--- /dev/null
+++ b/usercss/default.css
@@ -0,0 +1,225 @@
+body 
+{
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	font-family: arial;
+}
+
+select
+{ 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: arial;
+	font-size: 14px;
+}
+
+#bodyDocuments span {
+    float: right;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	/* width: 275px; */
+	height: 515px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#textonlylogo	{	display: none;	}
+
+#bg
+{
+	position: fixed;
+	top: 0;
+	left: 0;
+}
+
+#viewcode
+{
+	font-size: 10px;
+}
+
+#content
+{
+	position: relative; 
+	z-index: 1;
+}
+
+img	{	border: none;	}
+
+#container
+{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border: 2px solid blue;
+	border-spacing: 2px;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer
+{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2
+{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author
+{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p
+{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights
+{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox
+{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: arial;
+	font-size: 14px;
+	text-align: left
+}
+
+#abutton
+{
+	font-family: arial;
+	font-size: 14px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a
+{
+    font-size: 14px;
+}
+
+a	{	color: blue;	}
+a:hover	{	color: #00CCCC;	}
+
+#code{
+	color: black;
+	background: white;
+	overflow: auto;
+	font: normal 12px "bitstream vera sans mono", monaco. "lucida console", "courier new", courier, serif;
+	background-image: url('../images/barbgwhitecyan.jpg'); /* removed because its bugging me */
+	margin: 0.9em 0; padding: 8px;
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important
+{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+div.menu a
+{
+	font: bold 14pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span
+{
+	padding: 3px;
+}
+
+div.menu a:hover
+{
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/dypso.css b/usercss/dypso.css
new file mode 100644
index 00000000..e69de29b
diff --git a/usercss/idiat.css b/usercss/idiat.css
new file mode 100644
index 00000000..c6b7ecc4
--- /dev/null
+++ b/usercss/idiat.css
@@ -0,0 +1,226 @@
+body 
+{
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	font-family: arial;
+}
+
+a
+{
+        text-decoration:none;
+}
+
+select
+{ 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: arial;
+	font-size: 14px;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 275px;
+	height: 515px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#textonlylogo	{	display: none;	}
+
+#bg
+{
+	position: fixed;
+	top: 0;
+	left: 0;
+}
+
+#viewcode
+{
+	font-size: 10px;
+}
+
+#content
+{
+	position: relative; 
+	z-index: 1;
+}
+
+img	{	border: none;	}
+
+#container
+{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border: 2px solid blue;
+	border-spacing: 2px;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer
+{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2
+{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author
+{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p
+{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights
+{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox
+{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: arial;
+	font-size: 14px;
+	text-align: left
+}
+
+#abutton
+{
+	font-family: arial;
+	font-size: 14px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a
+{
+    font-size: 14px;
+}
+
+a	{	color: blue;	}
+a:hover	{	color: #00CCCC;	}
+
+#code{
+	color: black;
+	background: white;
+	overflow: auto;
+	font: normal 12px "bitstream vera sans mono", monaco. "lucida console", "courier new", courier, serif;
+	background-image: url('../images/barbgwhitecyan.jpg'); /* removed because its bugging me */
+	margin: 0.9em 0; padding: 8px;
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important
+{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+div.menu a
+{
+	font: bold 14pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span
+{
+	padding: 3px;
+}
+
+div.menu a:hover
+{
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/l2k-Shadow.css b/usercss/l2k-Shadow.css
new file mode 100644
index 00000000..898b1336
--- /dev/null
+++ b/usercss/l2k-Shadow.css
@@ -0,0 +1,208 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+}
+
+select  { 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#viewcode {
+	color: black;
+	font-size: 10px;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border-width: 2px;
+	border-spacing: 2px;
+	border-style: solid;
+	border-color: blue;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+}
+
+div#punch2{
+	float: left; 
+	width: 100px; 
+	height: 75px; 
+	text-align: center; 
+	color: white; 
+	border-width: 0 1px 1px 0; 
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+	display: none;
+}
+
+div#punch2 img{
+	height: 75px; 
+	width: 100px;
+	display: none;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: left
+}
+
+#abutton{
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a:link{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none; 
+}
+
+a:visited{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:active{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:hover{
+	color: #00CCCC;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+#code{
+	color: black;				 /* Foreground color */
+	background: white;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url('../images/barbgwhitecyan.jpg');
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/lowfi.css b/usercss/lowfi.css
new file mode 100644
index 00000000..c049d87c
--- /dev/null
+++ b/usercss/lowfi.css
@@ -0,0 +1,221 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+}
+
+#bodyDocuments span {
+    float: right;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	/* width: 225px; */
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#logo {
+display: none;
+}
+
+#viewcode {
+	color: black;
+	font-size: 10px;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border-width: 2px;
+	border-spacing: 2px;
+	border-style: solid;
+	border-color: blue;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	display: none;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox{
+	background-color: white;
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: left
+}
+
+#abutton{
+	font-family: verdana, tahoma, arial, helvetica, sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a:link{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none; 
+}
+
+a:visited{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:active{
+	color: blue;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+a:hover{
+	color: #00CCCC;
+	text-decoration: underline;
+	text-transform: none;
+}
+
+#code{
+	color: black;				 /* Foreground color */
+	background: white;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it\'s too long */
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#frills{
+display: none;
+}
+
+#important{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/nine.css b/usercss/nine.css
new file mode 100644
index 00000000..7048af93
--- /dev/null
+++ b/usercss/nine.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/nitroxs.css b/usercss/nitroxs.css
new file mode 100644
index 00000000..7048af93
--- /dev/null
+++ b/usercss/nitroxs.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/noc.css b/usercss/noc.css
new file mode 100644
index 00000000..aa398d6f
--- /dev/null
+++ b/usercss/noc.css
@@ -0,0 +1,225 @@
+body 
+{
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	font-family: arial;
+}
+
+select
+{ 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: arial;
+	font-size: 14px;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 275px;
+	height: 515px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: orange;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+#textonlylogo	{	display: none;	}
+
+#bg
+{
+	position: fixed;
+	top: 0;
+	left: 0;
+}
+
+#viewcode
+{
+	font-size: 10px;
+}
+
+#content
+{
+	position: relative; 
+	z-index: 1;
+}
+
+img	{	border: none;	}
+
+#container
+{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border: 2px solid blue;
+	border-spacing: 2px;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer
+{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2
+{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author
+{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+	clear: both;
+}
+
+div#main2 p
+{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights
+{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox
+{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: arial;
+	font-size: 14px;
+	text-align: left
+}
+
+#abutton
+{
+	font-family: arial;
+	font-size: 14px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a
+{
+    font-size: 14px;
+}
+
+a	{	color: blue;	}
+a:hover	{	color: #00CCCC;	}
+
+#code{
+	color: black;
+	background: white;
+	overflow: auto;
+	font: normal 12px "bitstream vera sans mono", monaco. "lucida console", "courier new", courier, serif;
+	background-image: url('../images/barbgwhitecyan.jpg'); /* removed because its bugging me */
+	margin: 0.9em 0; padding: 8px;
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important
+{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+div.menu a
+{
+	font: bold 14pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span
+{
+	padding: 3px;
+}
+
+div.menu a:hover
+{
+	background: #ffcc33;
+}
+
+a {
+ text-decoration: none;
+}
\ No newline at end of file
diff --git a/usercss/oXiDe.css b/usercss/oXiDe.css
new file mode 100644
index 00000000..7048af93
--- /dev/null
+++ b/usercss/oXiDe.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/plugins.css b/usercss/plugins.css
new file mode 100644
index 00000000..2109bc45
--- /dev/null
+++ b/usercss/plugins.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: orange;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/privt.css b/usercss/privt.css
new file mode 100644
index 00000000..a277fd19
--- /dev/null
+++ b/usercss/privt.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: white;
+	background: #000000;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: arial;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/rabbit.css b/usercss/rabbit.css
new file mode 100644
index 00000000..10e8b8e6
--- /dev/null
+++ b/usercss/rabbit.css
@@ -0,0 +1,196 @@
+body 
+{
+	color: black;
+	background: white;
+	margin: 0px;
+	font-size: 14px;
+	font-family: arial;
+}
+
+select
+{ 
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	font-family: arial;
+	font-size: 14px;
+}
+
+#textonlylogo	{	display: none;	}
+
+#bg
+{
+	position: fixed;
+	top: 0;
+	left: 0;
+}
+
+#viewcode
+{
+	font-size: 10px;
+}
+
+#content
+{
+	position: relative; 
+	z-index: 1;
+}
+
+img	{	border: none;	}
+
+#container
+{
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+	border: 2px solid blue;
+	border-spacing: 2px;
+	border-collapse: collapse;
+	background-color: #EEEEEE;
+}
+
+#newscontainer
+{
+	min-height: 150px;
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	background-color: #EEEEEE;
+}
+
+div#punch2
+{
+	float: left; 
+	width: 100px; 
+	height: 75px; 
+	text-align: center; 
+	color: white; 
+	border-width: 0 1px 1px 0; 
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+	display: none;
+}
+
+div#punch2 img
+{
+	height: 75px; 
+	width: 100px;
+	display: none;
+}
+
+div#main2 h2
+{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: blue; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+	color: white;
+}
+
+div#author
+{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid black;
+	font-weight: bold;
+	background-color: blue;
+	color: white;
+}
+
+div#main2 p
+{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights
+{
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+	background-color: #EEEEEE;
+}
+
+#inputbox
+{
+	background-color: white;
+	background: url('/images/barbgwhitecyan.jpg');
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: black;
+	font-family: arial;
+	font-size: 14px;
+	text-align: left
+}
+
+#abutton
+{
+	font-family: arial;
+	font-size: 14px;
+	text-align: center
+}
+
+/* Hyperlinks */
+a
+{
+    font-size: 14px;
+}
+
+a	{	color: blue;	}
+a:hover	{	color: #00CCCC;	}
+
+#code{
+	color: black;
+	background: white;
+	overflow: auto;
+	font: normal 12px "bitstream vera sans mono", monaco. "lucida console", "courier new", courier, serif;
+	/* background-image: url('../images/barbgwhitecyan.jpg'); /* removed because its bugging me */
+	margin: 0.9em 0; padding: 8px;
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+}
+
+#important
+{
+	background: red;
+	font-weight: bold;
+	color: white;
+}
+
+div.menu a
+{
+	font: bold 14pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #EEEEEE;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span
+{
+	padding: 3px;
+}
+
+div.menu a:hover
+{
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/usercss/sL8.css b/usercss/sL8.css
new file mode 100644
index 00000000..a86a1a3b
--- /dev/null
+++ b/usercss/sL8.css
@@ -0,0 +1,223 @@
+html {
+	height:100%;
+}
+
+body  {
+	color: red;
+	background: #111;
+	margin: 0px;
+	font-size: 14px;
+	height:100%;
+	width: 100%;
+	padding:0;
+	font-family: Segoe UI;
+}
+
+#bodyPackets {
+	font-family: Courier New;
+	width: 225px;
+	height: 500px;
+	overflow: auto;
+}
+
+.commentsidebar{
+	background: #999; 
+	color: black; 
+	padding: 2px; 
+	border: 1px #555 solid; 
+}
+
+.research, .defunct, .raw {
+	font-style: italic;
+	margin-left: 5px;
+}
+
+.keyword {
+	color: yellow;
+}
+
+.raw {color: red}
+
+.defunct {color: gray;}
+
+.research {color: orange;}
+
+div.navmenu {margin: 5px;}
+
+select  { 
+	background-color: #000;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: #33FF00;
+	font-family: arial;
+	font-size: 9px;
+}
+
+#bg {
+	position: fixed;
+	top:0; 
+	left:0; 
+	width:100%; 
+	height:100%;
+}
+
+#textonlylogo{
+	display: none;
+}
+
+#content {
+	position:relative; 
+	z-index:1;
+}
+
+img{
+	border: none;
+}
+
+#container{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	font-size: 12px;
+}
+
+#newscontainer{
+	background-image: url(/images/fade.png);
+	border: 1px solid black;
+	font-size: 14px;
+	padding: 1px;
+	margin: 10px 0px 0px 0px;	
+	text-align: left;
+	clear: both;
+}
+
+#newsicon img{
+	height: 75px; 
+	width: 100px;
+	padding: 0 0 0 0; 
+	margin: 10px 10px 0px 1px;
+}
+
+div#main2 {
+	padding: 2px; 
+	margin: 0;
+}
+
+div#main2 h2{
+	margin: 0; 
+	padding: 0.25em 1em 0.125em 0; 
+	background: #333; 
+	text-transform: uppercase; 
+	font-size: 120%;
+	border-bottom: 1px solid #000;
+	text-align: center; 
+}
+
+div#author{
+	margin: 0; 
+	text-transform: uppercase; 
+	font-size: 10px;
+	background-image: url(/images/grey.png);
+	text-align: right; 
+	padding: 0.25em 1em 0.125em 0; 
+	border-bottom: 1px solid #000;
+	clear: both;
+}
+
+div#main2 p{
+	padding: 0.5em 1em; 
+	margin: 0;
+}
+
+div#copyrights{
+	background-image: url(/images/fade.png);
+	font-size: 10px;
+	text-align: center;
+	margin: 0;
+	border-top: 1px solid #000;
+}
+
+#inputbox{
+	background-color: black;
+	background: url(/images/barbg.jpg);
+	border-bottom: 1px solid #333333;
+	border-left: 1px solid #666666;
+	border-right: 1px solid #333333;
+	border-top: 1px solid #666666;
+	color: white;
+	font-family: Courier New;
+	text-align: left;
+	font-size: 12px;
+}
+
+#abutton{
+	background-color: #222;
+	border-bottom: 1px solid #444;
+	border-left: 1px solid #333;
+	border-right: 1px solid #444;
+	border-top: 1px solid #333;
+	color: white;
+	font-family: sans-serif;
+	font-size: 9px;
+	text-align: center
+}
+
+/* Hyperlinks */
+
+a {
+	color: cyan;
+	text-decoration: none;
+}
+
+a:hover	{
+	color: lime;
+}
+
+#packets.a {
+
+}
+
+#code{
+	color: #33FF00;				 /* Foreground color */
+	background: #000;			 /* Background color */
+	overflow: auto;				 /* Puts code into scrollable frame if it's too long */
+	font: normal 12px "bitstream vera sans mono", monaco "lucida console", "courier new", courier, serif; /* Font */
+	background-image: url(/images/barbg.jpg);
+	margin: 0.9em 0; padding: 8px; /* Padding */
+	/* Set up borders */
+	border-width: thin;
+	border-style: dotted;
+	border-color: #333;
+	max-width: 90%;
+	text-align: left;
+	font-family: Courier New;
+}
+
+#important{
+	background: #660000;
+	font-weight: bold;
+}
+
+/* CSS Buttons */
+
+div.menu a {
+	font: bold 8pt Arial;
+	margin: 0;
+	padding: 0;
+	background: #999999;
+	border: #333 1px solid;
+	color: #000000;
+	text-decoration:none;
+}
+
+div.menu span {
+	padding: 3px;
+}
+
+div.menu a:hover {
+	background: #ffcc33;
+}
\ No newline at end of file
diff --git a/verbyte-cpp.html b/verbyte-cpp.html
new file mode 100644
index 00000000..a1207bbc
--- /dev/null
+++ b/verbyte-cpp.html
@@ -0,0 +1,248 @@
+<html>
+<head>
+<link rel="stylesheet" type="text/css" href="http://rafb.net/styles/nopaste.css"/>
+<link rel="icon" href="http://rafb.net/nopaste_favicon.gif" type="image/gif"/>
+<link rel="shortcut icon" href="http://rafb.net/nopaste_favicon.gif" type="image/gif"/>
+<title>BNETDocs: "How to Obtain VerByte" Source Code by DevCode</title>
+</head><div style="border-bottom: 2px solid gray;">
+<table border="0" cellpadding="1" cellspacing="2" width="100%">
+<tr>
+  <td><small>File hosted by <a href="http://www.bnetdocs.org">BNETDocs</a></small></td>
+</tr>
+</table>
+</div>
+
+<table border="0" cellpadding="1" cellspacing="2">
+<tr>
+  <td><pre class="code" style="line-height: 1.2847em;">1
+2
+3
+4
+5
+6
+7
+8
+9
+10
+11
+12
+13
+14
+15
+16
+17
+18
+19
+20
+21
+22
+23
+24
+25
+26
+27
+28
+29
+30
+31
+32
+33
+34
+35
+36
+37
+38
+39
+40
+41
+42
+43
+44
+45
+46
+47
+48
+49
+50
+51
+52
+53
+54
+55
+56
+57
+58
+59
+60
+61
+62
+63
+64
+65
+66
+67
+68
+69
+70
+71
+72
+73
+74
+75
+76
+77
+78
+79
+80
+81
+82
+83
+84
+85
+86
+87
+88
+89
+90
+91
+92
+93
+94
+95
+96
+97
+98
+99
+100
+101
+102
+103
+104
+105
+106
+107
+108
+109
+110
+111
+112</pre></td>
+
+  <td width="100%"><pre class="code" id="codemain"><span class="comment">/* bncsutil.cpp v1.3.2
+ * Copyright (c) 2007 devcode
+ *
+ *
+ *			^^ D E V C O D E ^^
+ *
+ * Starcraft/Brood Wars Dynamic Verbyte Retrieval
+ *
+ *
+ * Description:
+ *	  Obtains the verbyte for Starcraft/Brood Wars given
+ *	  the input Starcraft.exe image. 
+ *  
+ * Tested on:
+ * 	  Starcraft 1.08 -> 1.15.1
+ *
+ * Credits: 
+ *	  GameDeception (Pattern finding code)
+ *	  DonCullen (Bringing up the idea)
+ *
+ */</span>
+&nbsp;<span class="keyword">
+#include</span> &lt;windows.h><span class="keyword">
+#include</span> &lt;iostream>
+&nbsp;
+<span class="comment">/** 
+ * Compares the pattern with the data
+ * 
+ * @param pbData
+ * @param pbMask
+ * @param szMask
+ * 
+ * @return bool
+ */</span>
+<span class="keyword">bool</span> DataCompare( <span class="keyword">const</span> BYTE *pbData, <span class="keyword">const</span> BYTE *pbMask, <span class="keyword">const</span> <span class="keyword">char</span> *szMask ) {
+    <span class="keyword">for</span>( ;*szMask; ++szMask,++pbData, ++pbMask )
+        <span class="keyword">if</span>( *szMask == <span class="literal">'x'</span> &amp;&amp; *pbData != *pbMask )
+            <span class="keyword">return</span> <span class="keyword">false</span>;
+    <span class="keyword">return</span> ( *szMask ) == NULL;
+}
+
+&nbsp;
+<span class="comment">/** 
+ * Finds a pattern in memory (shamelessly taken from 
+ * gamedeception forums, unknown author) 
+ * 
+ * @param dwAddress = Start of memory to search
+ * @param dwLen = Size of memory to search
+ * @param pbMask
+ * @param szMask
+ * 
+ * @return DWORD
+ */</span>
+DWORD FindPattern( DWORD dwAddress, DWORD dwLen, BYTE *pbMask, <span class="keyword">char</span> *szMask ) {
+    <span class="keyword">for</span>( DWORD i=0; i &lt; dwLen; i++ )
+        <span class="keyword">if</span>( DataCompare( (BYTE *)( dwAddress+i ), pbMask, szMask ) )
+            <span class="keyword">return</span> (DWORD)(dwAddress+i);
+	<span class="keyword">return</span> 0;
+}
+
+&nbsp;
+<span class="comment">/** 
+ * Gets version byte for Starcraft/Brood Wars
+ * 
+ * @param szStarcraftExe = Path to Starcraft.exe
+ * 
+ * @return DWORD = Returns 0 if function fails, otherwise, the 
+ *         	version byte
+ */</span>
+DWORD GetVersionByte( <span class="keyword">const</span> <span class="keyword">char</span> *szStarcraftExe ) {
+	HANDLE hFile, hMappedFile;
+	BYTE *pdwImage;
+	<span class="keyword">int</span> nRetVal;
+	LARGE_INTEGER nSize;
+	<span class="comment">/**
+	 * mov dword [esi+10h], DWORD &lt;-- VerByte 
+	 * mov dword [esi+18h], DWORD 
+	 * mov dword [esi+28h], DWORD 
+	*/</span>
+	BYTE pbPattern[] = <span class="literal">"\xC7\x46\x10\x00\x00\x00\x00\xC7\x46\x18\x00\x00\x00\x00\xC7\x46"</span>;
+	DWORD dwResult = 0;
+
+&nbsp;
+	<span class="comment">/* Open the file and create read only mapping */</span>
+	PRECONDITION( szStarcraftExe );
+	hFile = CreateFile( szStarcraftExe, GENERIC_READ, 0, NULL, 
+						OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL );
+	PRECONDITION( hFile != INVALID_HANDLE_VALUE );
+&nbsp;
+	hMappedFile = CreateFileMapping( hFile, NULL, PAGE_READONLY, 0, 0, NULL );
+	PRECONDITION( hMappedFile );
+&nbsp;
+	<span class="comment">/* Map the file into memory */</span>
+	pdwImage = (BYTE *)MapViewOfFile( hMappedFile, FILE_MAP_READ, 0, 0, 0 );
+	PRECONDITION( pdwImage );
+&nbsp;
+	<span class="comment">/* File size, ditto */</span>
+
+	nRetVal = GetFileSizeEx( hFile, &amp;nSize );
+	PRECONDITION( nRetVal );
+&nbsp;
+	dwResult = FindPattern( (DWORD)pdwImage, nSize.LowPart, pbPattern, <span class="literal">"xxx????xxx????xx"</span> );
+	<span class="keyword">if</span> ( dwResult ) dwResult = *((BYTE *)dwResult+3);
+&nbsp;
+	<span class="comment">/* We're done, unmap the view */</span>
+	PRECONDITION( UnmapViewOfFile( pdwImage ) );
+	<span class="comment">/* Close all handles */</span>
+
+	PRECONDITION( CloseHandle( hMappedFile ) );
+	PRECONDITION( CloseHandle( hFile ) );
+	<span class="keyword">return</span> dwResult;
+}
+&nbsp;
+<span class="keyword">int</span> main( ) {
+	GetVersionByte( <span class="literal">"C:\\Program Files\\starcraft\\Starcraft.exe"</span> );
+}</pre></td>
+</tr>
+</table>
+</html>
\ No newline at end of file
diff --git a/verbyte-java.txt b/verbyte-java.txt
new file mode 100644
index 00000000..7433d823
--- /dev/null
+++ b/verbyte-java.txt
@@ -0,0 +1,51 @@
+/*********************************
+ * http://pastebin.com/f16617044 *
+ *********************************/
+
+import java.io.*;
+
+public class Main{
+  public static void main(String[] arge){
+	vb = find_seeds("F:\\BNET\\SEXP\\Starcraft.exe", 
+	new byte[]{(byte)0xC7, (byte)0x46, (byte)0x10, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, 
+	           (byte)0xC7, (byte)0x46, (byte)0x18, (byte)0xFF, (byte)0xFF, (byte)0xFF, (byte)0xFF, 
+			   (byte)0xC7, (byte)0x46},
+	new int[]{3});
+	System.out.println("VerByte: 0x" + Integer.toHexString(vb[0]));
+  }
+  
+  /*****************************************
+  * This is converted from iago's lockdown *
+  * seedfinder. Its a basic pattern search.*
+  ******************************************/
+  public static int[] find_seeds(String file, byte[] values, int[] offsets){  
+    int[] ret = new int[offsets.length];
+    byte[] data = readFile(file);  
+    if(data == null) return ret;
+    for(int i = 0; i < data.length - values.length; i++){
+      boolean found = true;
+      for(int j = 0; j < values.length && found; j++)
+        if(values[j] != (byte)0xFF && (data[i + j] != values[j])) found = false;
+    
+      if(found){
+        for(int x = 0; x < offsets.length; x++){
+          ret[x] = ((data[i+offsets[x]+0] << 0)  & 0x000000FF) |
+               ((data[i+offsets[x]+1] << 8)  & 0x0000FF00) |
+               ((data[i+offsets[x]+2] << 16) & 0x00FF0000) |
+               ((data[i+offsets[x]+3] << 24) & 0xFF000000);
+        }
+        return ret;
+      }
+    }
+    return ret;
+  }
+  public static byte[] readFile(String file){
+    try{
+      byte[] ret = new byte[(int)(new File(file)).length()];
+      InputStream in = new FileInputStream(file);
+      in.read(ret);
+      in.close();
+      return ret;
+    }catch(Exception e){ return null; }
+  }
+}
\ No newline at end of file
diff --git a/viewlogs.php b/viewlogs.php
new file mode 100644
index 00000000..99601bc4
--- /dev/null
+++ b/viewlogs.php
@@ -0,0 +1,232 @@
+<?
+	# Block Direct Access Attempts
+	# -------------------------------
+	global $auth, $ie;
+	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
+	
+	# Begin Code
+	# -------------
+
+	if(rank($userid) < 3) {
+		blockhack();
+	}
+
+	if(rank($userid) < 4) $privatestring = "WHERE eventtype != 'CONFIDENTAL' ";
+	if($_REQUEST['consolidate'] != ''){
+		$privatestring .= " group by CONCAT(user,datetime,eventtype) ";
+		$consolidate = '&consolidate=true';
+	}
+	
+    $limit          = 25;               
+    $query_count    = "SELECT * FROM logs $privatestring";
+    $result_count   = mysql_query($query_count);
+    $totalrows      = mysql_num_rows($result_count); 
+	
+	$page = sanitize($_REQUEST['page']);
+	$orderby = sanitize($_REQUEST['orderby']);
+	$mode = sanitize($_REQUEST['mode']);
+	$id = sanitize($_REQUEST['id']);
+	
+	$specific = false;
+	
+	?>
+		<div id="container">
+		<div id="main2">
+		<h2>View Logs</h2>
+		<div align=center>
+		<br>
+	<?
+	
+	if($mode == 'delete'){
+		if(rank($userid) == 5){
+			$sql = "DELETE FROM logs WHERE id = $id";
+			mysql_query($sql) or die("MySQL News Error (delete): ".mysql_error());
+
+			WriteData($userid, 'msg', '<center><b><font color=lime>Log Entry Deleted.</font></b></center>');
+
+			redirect("/?op=viewlogs&page=$page".$consolidate);
+		} else {
+			blockhack('no');
+		}
+	}
+	
+	if($id && !$mode){
+		$limit = 1;
+		$orderby = 'WHERE id='.$id;
+		$specific = true;
+		$query  = "SELECT * FROM logs WHERE id=$id";
+	}
+
+    if($page < 1){
+        $page = 1;
+    }
+	
+    $limitvalue = $page * $limit - ($limit); 
+	
+    if(!$specific){
+		if(!$orderby){
+			$query  = "SELECT * FROM logs $privatestring ORDER BY id desc LIMIT $limitvalue, $limit";
+		} else {
+			$query  = "SELECT * FROM logs $privatestring ORDER BY $orderby desc LIMIT $limitvalue, $limit";
+		}
+	}
+	
+    $result = mysql_query($query) or die("Error: " . mysql_error()); 
+
+    if(mysql_num_rows($result) == 0){
+        echo("Nothing to Display!");
+    }
+
+    $bgcolor = "#333333"; // light gray
+
+	#URLButton('Back To Console', '/?op=console');
+		
+    if(!$consolidate){
+		?>[ &nbsp; <a href="/?op=viewlogs&consolidate=true" title="Merge Similar Events on a per user basis">Consolidate View</a> &nbsp; ]<br><br><?
+	} else {
+		?>[ &nbsp; <a href="/?op=viewlogs">Unconsolidate View</a> &nbsp; ]<br><br><?	
+	}
+	?>
+	<table>
+		<tr bgcolor=".<?=$bgcolor;?>.">
+			<td>
+				<center><font size=1><a href="/?op=viewlogs&page=<?=$page;?>&orderby=id<?=$consolidate;?>">Order By Date</a></font></center>
+			</td>
+			<td>
+				<center><font size=1><a href="/?op=viewlogs&page=<?=$page;?>&orderby=user<?=$consolidate;?>">Order By Member Activity</a> | <a href="/?op=viewlogs&page=<?=$page;?>&orderby=eventtype<?=$consolidate;?>">Order By Event</a></font></center>
+			</td>
+	<?	
+	#display this only if person is a coldr or higher
+	if(rank($userid) > 2){
+		echo '<td><center><font size=1><a href="/?op=viewlogs&page='.$page.'&orderby=ip'.$consolidate.'">Order By IP</a></font></center></td>';
+	} else {
+		echo "<td>&nbsp;</td>";
+	}
+	if(rank($userid) ==  5) echo "<td>&nbsp;</td>";
+	echo "\n\t\t</tr>";
+		
+    while($row = mysql_fetch_array($result)){
+        if ($bgcolor == "#333333"){
+            $bgcolor = "#666666";
+        }else{
+            $bgcolor = "#333333";
+        }
+
+	    echo("<tr bgcolor=".$bgcolor."><td>");
+	    echo('<font size=1>'.$row['datetime'].'</font>');
+	    echo("</td><td>");
+		
+		if($consolidate){	# If it's turned on, instead of displaying detailed summaries for events, simply indicate event type.
+			if($row['eventtype'] == 'CONFIDENTAL') $row['event'] = $row['event']; #do nothing
+			if($row['eventtype'] == 'docedit') $row['event'] = 'edited documents.';
+			if($row['eventtype'] == 'newsdelete') $row['event'] = 'deleted news posts.';
+			if($row['eventtype'] == 'newsedit') $row['event'] = 'edited news posts.';
+			if($row['eventtype'] == 'newspost') $row['event'] = 'submitted news posts.';
+			if($row['eventtype'] == 'pktadd') $row['event'] = 'added packets.';
+			if($row['eventtype'] == 'pktedit') $row['event'] = 'edited packets.';
+			if($row['eventtype'] == 'pktdel') $row['event'] = 'deleted packets.';
+			if($row['eventtype'] == 'registration') $row['event'] = 'registered to be a member.';
+			if($row['eventtype'] == 'commentedit') $row['event'] = 'edited comments.';
+			if($row['eventtype'] == 'commentadd') $row['event'] = 'posted comments.';
+			if($row['eventtype'] == 'commentdel') $row['event'] = 'deleted comments.';
+		}
+		$lenlimit = 30;
+		if(!$specific){
+			$row['event'] = totalpurgehtml($row['event']);
+			if(strlen($row['event']) > $lenlimit){
+				$row['event'] = substr($row['event'], 0, $lenlimit).'... [ <a href="/?op=viewlogs&id='.$row['id'].$consolidate.'">more</a> ]';
+			}
+		}
+		
+		$initator = $row['user'];
+		
+		if(!$initator) $initator = 'Someone';
+		
+	    if($specific){
+			$content = codify($row['event'], true);
+			echo(ucfirst(whoisid($initator)).' '.$content);
+		} else {
+			echo(ucfirst(whoisid($initator)).' '.lcfirst($row['event']));
+		}
+	    echo "</td>";
+		
+		#display this only if person is a coldr or higher
+		if(rank($userid) > 2){
+			echo "<td><font size=1>".$row['ip']."</font></td>";
+		} else {
+			echo "<td><font size=1> IP SAVED </font></td>";
+		}
+		
+		if(rank($userid) == 5) {
+			if(!$consolidate){
+				$delete = "/?op=viewlogs&page=$page&mode=delete&id=".$row['id'].$consolidate;
+				echo '<td><a href="'.$delete.'" border=0 onclick="return confimdelete();"><img border=0 src="/images/icondelete.jpg"></a></td>';
+			}
+		}
+		
+		echo "</tr>";
+    }
+
+    echo("</table><br>");
+
+	if(!$specific){
+	
+	    if($page != 1){ 
+	        $pageprev = $page - 1;
+	        
+	        echo('<a href="/?op=viewlogs&page='.$pageprev.$consolidate.'"><< PREV</a> '); 
+	    }else{
+	    }
+
+	    $numofpages = $totalrows / $limit; 
+	    $expandlimit = 4;
+		$minimum = $page - 5;
+		if($minimum < 1) $minimum = 1;
+	    for($i = $minimum; $i <= $page + $expandlimit; $i++){
+	        if($i == $page){
+	            echo($i." ");
+	        }else{
+	            echo('<a href="/?op=viewlogs&page='.$i.$consolidate.'">'.$i.'</a> ');
+	        }
+			if($i > $numofpages) break;
+	    }
+		
+		if($i < $numofpages){
+			echo ' ... ';
+			
+			$numofpages = floor($totalrows / $limit); 
+		    $expandlimit = 3;
+			$maximum = $numofpages - 5;
+			if($page < 1) $minimum = 1;
+		    for($i = $numofpages - $expandlimit; $i <= $numofpages; $i++){
+		        if($i == $page){
+		            echo($i." ");
+		        }else{
+		            echo('<a href="/?op=viewlogs&page='.$i.$consolidate.'">'.$i.'</a> ');
+		        }
+		    }
+		}
+		
+	    if(($totalrows % $limit) != 0){
+			if($i != ceil($numofpages)){
+		        if($i == $page){
+					echo($i." ");
+		        }else{
+		            echo('<a href="/?op=viewlogs&page='.$i.$consolidate.'">'.$i.'</a> ');
+		        }
+			}
+	    }
+
+	    if(($totalrows - ($limit * $page)) > 0){
+	        $pagenext = $page + 1;
+	        echo('<a href="/?op=viewlogs&page='.$pagenext.$consolidate.'">NEXT >></a>'); 
+	    }else{
+	    }
+	} else {
+		?><input type=button value="Go Back to Logs" id="abutton" onClick="history.back()"><?
+	}
+
+    mysql_free_result($result);
+	echo '<br><br></div></div></div>';
+
+?>

From 7b02c6aeeffbcb4e98c899d79d3e6f95b83dd780 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Thu, 5 Jun 2014 16:02:23 -0500
Subject: [PATCH 02/54] added Fight For The Future's Reset The Net campaign

---
 bdif/header.dm         |  38 ++++++++++++++++++++++++++++++++++++--
 images/resetthenet.png | Bin 0 -> 13377 bytes
 2 files changed, 36 insertions(+), 2 deletions(-)
 create mode 100644 images/resetthenet.png

diff --git a/bdif/header.dm b/bdif/header.dm
index f5b5bb77..fb765ed5 100644
--- a/bdif/header.dm
+++ b/bdif/header.dm
@@ -1,4 +1,11 @@
-<? global $ip, $userid, $auth; $openedmenus = $_GET['ep'];?>
+<? global $ip, $userid, $auth; $openedmenus = $_GET['ep'];
+
+  // Fight For The Future - Compaign Enables
+  $FFTF_DATE            = date('Y-m-d');
+  $FFTF_STOPTHESLOWLANE = ($FFTF_DATE == '2014-05-15');
+  $FFTF_RESETTHENET     = ($FFTF_DATE == '2014-06-05');
+
+?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
    "http://www.w3.org/TR/html4/loose.dtd">
 <html>
@@ -62,7 +69,7 @@
 	<link rel="icon" type="image/png" href="/favicon.png" sizes="32x32">
   <?
   // FIGHT FOR THE FUTURE - STOP THE SLOW LANE (http://www.stoptheslowlane.com/)
-  if (date('Y-m-d') == '2014-05-15') {
+  if ($FFTF_STOPTHESLOWLANE) {
     ?>
 	<style id="_sl_hide" type="text/css">body { display: none; }</style>
     <?
@@ -82,6 +89,25 @@
 Computers Programming Binary Coding Hacking -->
 <!-- google_ad_section_end -->
 <body onload="doonload()">
+<?
+  // FIGHT FOR THE FUTURE - RESET THE NET (https://www.resetthenet.org/)
+  if ($FFTF_RESETTHENET) {
+    ?>
+  <script type="text/javascript">
+    window._idl = {};
+    _idl.variant = "modal";
+    _idl.campaign = "reset-the-net";
+    (function() {
+      var idl = document.createElement('script');
+      idl.type = 'text/javascript';
+      idl.async = true;
+      idl.src = ('https:' == document.location.protocol ? 'https://' : 'http://') + 'members.internetdefenseleague.org/include/?url= <http://members.internetdefenseleague.org/include/?url=>' + (_idl.url || '') + '&campaign=' + (_idl.campaign || '') + '&variant=' + (_idl.variant || 'modal');
+      document.getElementsByTagName('body')[0].appendChild(idl);
+    })();
+  </script>
+  <?
+  } // END OF RESET THE NET
+?>
 <div id="content" align=center>
 <div align=left id="logo"><img src="/images/bnetdocslogo.png"><br>
 <br></div>
@@ -224,3 +250,11 @@ Computers Programming Binary Coding Hacking -->
 	</div></div></div></div></div>
 </td>
 <td width=60% valign=top>
+<?
+  // FIGHT FOR THE FUTURE - RESET THE NET (https://www.resetthenet.org/)
+  if ($FFTF_RESETTHENET) {
+?>
+<a href="https://www.resetthenet.org/" target="_blank" style="display:inline-block;width:100%;"><img src="https://bnetdocs.org/images/resetthenet.png" alt="Reset The Net" title="Reset The Net" style="border:0px;padding-top:10px;width:100%;" /></a>
+<?
+  }
+?>
diff --git a/images/resetthenet.png b/images/resetthenet.png
new file mode 100644
index 0000000000000000000000000000000000000000..504b7fc828aee275dfff0668430aa86912187c64
GIT binary patch

From e22dbb1535cee07a78012985a67db34a3f0767f4 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Thu, 5 Jun 2014 16:04:32 -0500
Subject: [PATCH 03/54] correct typo in comment

---
 bdif/header.dm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bdif/header.dm b/bdif/header.dm
index fb765ed5..8f0f7468 100644
--- a/bdif/header.dm
+++ b/bdif/header.dm
@@ -1,6 +1,6 @@
 <? global $ip, $userid, $auth; $openedmenus = $_GET['ep'];
 
-  // Fight For The Future - Compaign Enables
+  // Fight For The Future - Campaign Enables
   $FFTF_DATE            = date('Y-m-d');
   $FFTF_STOPTHESLOWLANE = ($FFTF_DATE == '2014-05-15');
   $FFTF_RESETTHENET     = ($FFTF_DATE == '2014-06-05');

From 4ebfd1cf09869eb1221a6fc9359885ee9793db53 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 26 Jul 2014 14:56:43 -0500
Subject: [PATCH 04/54] Removed check-servers from repository.

---
 check-servers.json |   1 -
 check-servers.log  |  80 -----------
 check-servers.php  | 348 ---------------------------------------------
 check-servers.sh   |  14 --
 4 files changed, 443 deletions(-)
 delete mode 100644 check-servers.json
 delete mode 100644 check-servers.log
 delete mode 100644 check-servers.php
 delete mode 100755 check-servers.sh

diff --git a/check-servers.json b/check-servers.json
deleted file mode 100644
index 414415ab..00000000
--- a/check-servers.json
+++ /dev/null
@@ -1 +0,0 @@
-{"phoenix_servers":[{"id":1,"address":"uswest.battle.net","port":6112,"type":1,"label":"uswest.battle.net","online":true},{"id":2,"address":"exodus.battle.net","port":6112,"type":1,"label":"exodus.battle.net","online":true},{"id":3,"address":"useast.battle.net","port":6112,"type":1,"label":"useast.battle.net","online":true},{"id":4,"address":"asia.battle.net","port":6112,"type":1,"label":"asia.battle.net","online":true},{"id":5,"address":"europe.battle.net","port":6112,"type":1,"label":"europe.battle.net","online":true},{"id":6,"address":"beta.battle.net","port":6112,"type":1,"label":"beta.battle.net","online":false},{"id":7,"address":"classicbeta.battle.net","port":6112,"type":1,"label":"classicbeta.battle.net","online":false},{"id":8,"address":"ustest.battle.net","port":6112,"type":1,"label":"ustest.battle.net","online":true},{"id":9,"address":"demo.war3.battle.net","port":6112,"type":1,"label":"demo.war3.battle.net","online":true},{"id":10,"address":"us.logon.battle.net","port":1119,"type":2,"label":"us.logon.battle.net","online":true},{"id":11,"address":"eu.logon.battle.net","port":1119,"type":2,"label":"eu.logon.battle.net","online":true},{"id":12,"address":"kr.logon.battle.net","port":1119,"type":2,"label":"kr.logon.battle.net","online":true},{"id":13,"address":"cn.logon.battle.net","port":1119,"type":2,"label":"cn.logon.battle.net","online":true},{"id":14,"address":"public-test.logon.battle.net","port":1119,"type":2,"label":"public-test.logon.battle.net","online":true},{"id":15,"address":"us.patch.battle.net","port":1119,"type":2,"label":"us.patch.battle.net","online":true},{"id":16,"address":"eu.patch.battle.net","port":1119,"type":2,"label":"eu.patch.battle.net","online":true},{"id":17,"address":"kr.patch.battle.net","port":1119,"type":2,"label":"kr.patch.battle.net","online":true},{"id":18,"address":"cn.patch.battle.net","port":1119,"type":2,"label":"cn.patch.battle.net","online":true},{"id":19,"address":"public-test.patch.battle.net","port":1119,"type":2,"label":"public-test.patch.battle.net","online":true},{"id":20,"address":"server.eurobattle.net","port":6112,"type":3,"label":"server.eurobattle.net","online":true},{"id":21,"address":"pvpgn.boredaussie.com","port":6112,"type":3,"label":"pvpgn.boredaussie.com","online":false},{"id":22,"address":"rubattle.net","port":6112,"type":3,"label":"rubattle.net","online":true},{"id":23,"address":"sc.theabyss.ru","port":6112,"type":3,"label":"sc.theabyss.ru","online":true},{"id":24,"address":"bnetd.fishbattle.net","port":6112,"type":3,"label":"bnetd.fishbattle.net","online":true},{"id":25,"address":"svr1.no-ip.org","port":6112,"type":3,"label":"svr1.no-ip.org","online":false},{"id":26,"address":"vetsvr.no-ip.org","port":6112,"type":3,"label":"vetsvr.no-ip.org","online":false},{"id":27,"address":"bnls.net","port":9367,"type":5,"label":"bnls.net","online":true},{"id":28,"address":"bnls.mattkv.net","port":9367,"type":5,"label":"bnls.mattkv.net","online":true},{"id":29,"address":"phix.no-ip.org","port":9367,"type":5,"label":"phix.no-ip.org","online":true},{"id":30,"address":"bnls.anubisdev.net","port":9367,"type":5,"label":"bnls.anubisdev.net","online":true},{"id":31,"address":"pyro.no-ip.biz","port":9367,"type":5,"label":"pyro.no-ip.biz","online":true},{"id":32,"address":"vectorjbls.no-ip.org","port":9367,"type":5,"label":"vectorjbls.no-ip.org","online":true},{"id":33,"address":"knight.mattkv.net","port":9367,"type":5,"label":"knight.mattkv.net","online":false},{"id":34,"address":"bnls.war-lords.net","port":9367,"type":5,"label":"bnls.war-lords.net","online":false},{"id":35,"address":"jailout2000.com","port":10011,"type":8,"label":"Jailout's TeamSpeak","online":true},{"id":36,"address":"jailout2000.com","port":25565,"type":6,"label":"Jailout's Minecraft Server","online":false}],"phoenix_server_types":[[1,"Official Battle.net v1 Servers"],[2,"Official Battle.net v2 Servers"],[3,"Unofficial Battle.net v1 Servers"],[5,"Battle.Net Logon Servers"],[6,"Minecraft Servers"],[8,"TeamSpeak 3 Servers"]],"redux_servers":{"bnet":[{"id":1,"address":"uswest.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":2,"address":"exodus.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":3,"address":"useast.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":4,"address":"asia.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":5,"address":"europe.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":6,"address":"beta.battle.net","port":6112,"version":"Battle.net v1","online":false},{"id":7,"address":"classicbeta.battle.net","port":6112,"version":"Battle.net v1","online":false},{"id":8,"address":"ustest.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":9,"address":"demo.war3.battle.net","port":6112,"version":"Battle.net v1","online":true},{"id":10,"address":"us.logon.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":11,"address":"eu.logon.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":12,"address":"kr.logon.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":13,"address":"cn.logon.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":14,"address":"public-test.logon.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":15,"address":"us.patch.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":16,"address":"eu.patch.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":17,"address":"kr.patch.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":18,"address":"cn.patch.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":19,"address":"public-test.patch.battle.net","port":1119,"version":"Battle.net v2","online":true},{"id":20,"address":"server.eurobattle.net","port":6112,"version":"PvPGN","online":true},{"id":21,"address":"pvpgn.boredaussie.com","port":6112,"version":"PvPGN","online":false},{"id":22,"address":"rubattle.net","port":6112,"version":"PvPGN","online":true},{"id":23,"address":"sc.theabyss.ru","port":6112,"version":"PvPGN","online":true},{"id":24,"address":"bnetd.fishbattle.net","port":6112,"version":"PvPGN","online":true},{"id":25,"address":"svr1.no-ip.org","port":6112,"version":"PvPGN","online":false},{"id":26,"address":"vetsvr.no-ip.org","port":6112,"version":"PvPGN","online":false}],"bnls":[{"id":1,"address":"bnls.net","port":9367,"online":true},{"id":2,"address":"bnls.mattkv.net","port":9367,"online":true},{"id":3,"address":"phix.no-ip.org","port":9367,"online":true},{"id":4,"address":"bnls.anubisdev.net","port":9367,"online":true},{"id":5,"address":"pyro.no-ip.biz","port":9367,"online":true},{"id":6,"address":"vectorjbls.no-ip.org","port":9367,"online":true},{"id":7,"address":"knight.mattkv.net","port":9367,"online":false},{"id":8,"address":"bnls.war-lords.net","port":9367,"online":false}]},"timestamp":{"utc_offset":-18000,"start":1400401201.8549,"end":1400401238.4269,"difference":36.572010040283,"total_time":"36.57s"}}
\ No newline at end of file
diff --git a/check-servers.log b/check-servers.log
deleted file mode 100644
index a7258336..00000000
--- a/check-servers.log
+++ /dev/null
@@ -1,80 +0,0 @@
-[1;29m[2014-05-18 03:20:01 -0500] [0;0m[1;33mScript execution started.[0;0m
-[1;29m[2014-05-18 03:20:01 -0500] [0;0m[1;33mUpdating BNETDocs Redux server tables...[0;0m
-[1;29m[2014-05-18 03:20:01 -0500] [0;0m[1;32mConnected to database server.[0;0m
-[1;29m[2014-05-18 03:20:01 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   uswest.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:01 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   exodus.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   useast.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   asia.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   europe.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;31moffline[0;0m:  beta.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;31moffline[0;0m:  classicbeta.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   ustest.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   demo.war3.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:02 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   us.logon.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:03 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   eu.logon.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:03 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   kr.logon.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:04 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   cn.logon.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:04 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   public-test.logon.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:04 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   us.patch.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:04 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   eu.patch.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:05 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   kr.patch.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:08 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   cn.patch.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:08 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   public-test.patch.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:08 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   server.eurobattle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:08 -0500] [0;0m[1;34mBNET[0;0m server is [1;31moffline[0;0m:  pvpgn.boredaussie.com:6112[0;0m
-[1;29m[2014-05-18 03:20:09 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   rubattle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:09 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   sc.theabyss.ru:6112[0;0m
-[1;29m[2014-05-18 03:20:09 -0500] [0;0m[1;34mBNET[0;0m server is [1;32monline[0;0m:   bnetd.fishbattle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:18 -0500] [0;0m[1;34mBNET[0;0m server is [1;31moffline[0;0m:  svr1.no-ip.org:6112[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;34mBNET[0;0m server is [1;31moffline[0;0m:  vetsvr.no-ip.org:6112[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;32monline[0;0m:   bnls.net:9367[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;32monline[0;0m:   bnls.mattkv.net:9367[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;32monline[0;0m:   phix.no-ip.org:9367[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;32monline[0;0m:   bnls.anubisdev.net:9367[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;32monline[0;0m:   pyro.no-ip.biz:9367[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;32monline[0;0m:   vectorjbls.no-ip.org:9367[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;31moffline[0;0m:  knight.mattkv.net:9367[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;35mBNLS[0;0m server is [1;31moffline[0;0m:  bnls.war-lords.net:9367[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;33mUpdating BNETDocs Phoenix server table...[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0m[1;32mConnected to database server.[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0mServer [1;36m1[0;0m is [1;32monline[0;0m:   uswest.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0mServer [1;36m2[0;0m is [1;32monline[0;0m:   exodus.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:23 -0500] [0;0mServer [1;36m3[0;0m is [1;32monline[0;0m:   useast.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m4[0;0m is [1;32monline[0;0m:   asia.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m5[0;0m is [1;32monline[0;0m:   europe.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m6[0;0m is [1;31moffline[0;0m:  beta.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m7[0;0m is [1;31moffline[0;0m:  classicbeta.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m8[0;0m is [1;32monline[0;0m:   ustest.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m9[0;0m is [1;32monline[0;0m:   demo.war3.battle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m10[0;0m is [1;32monline[0;0m:   us.logon.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m11[0;0m is [1;32monline[0;0m:   eu.logon.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:24 -0500] [0;0mServer [1;36m12[0;0m is [1;32monline[0;0m:   kr.logon.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:25 -0500] [0;0mServer [1;36m13[0;0m is [1;32monline[0;0m:   cn.logon.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:25 -0500] [0;0mServer [1;36m14[0;0m is [1;32monline[0;0m:   public-test.logon.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:25 -0500] [0;0mServer [1;36m15[0;0m is [1;32monline[0;0m:   us.patch.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:25 -0500] [0;0mServer [1;36m16[0;0m is [1;32monline[0;0m:   eu.patch.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:25 -0500] [0;0mServer [1;36m17[0;0m is [1;32monline[0;0m:   kr.patch.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:26 -0500] [0;0mServer [1;36m18[0;0m is [1;32monline[0;0m:   cn.patch.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:26 -0500] [0;0mServer [1;36m19[0;0m is [1;32monline[0;0m:   public-test.patch.battle.net:1119[0;0m
-[1;29m[2014-05-18 03:20:27 -0500] [0;0mServer [1;36m20[0;0m is [1;32monline[0;0m:   server.eurobattle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:27 -0500] [0;0mServer [1;36m21[0;0m is [1;31moffline[0;0m:  pvpgn.boredaussie.com:6112[0;0m
-[1;29m[2014-05-18 03:20:27 -0500] [0;0mServer [1;36m22[0;0m is [1;32monline[0;0m:   rubattle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:27 -0500] [0;0mServer [1;36m23[0;0m is [1;32monline[0;0m:   sc.theabyss.ru:6112[0;0m
-[1;29m[2014-05-18 03:20:27 -0500] [0;0mServer [1;36m24[0;0m is [1;32monline[0;0m:   bnetd.fishbattle.net:6112[0;0m
-[1;29m[2014-05-18 03:20:32 -0500] [0;0mServer [1;36m25[0;0m is [1;31moffline[0;0m:  svr1.no-ip.org:6112[0;0m
-[1;29m[2014-05-18 03:20:37 -0500] [0;0mServer [1;36m26[0;0m is [1;31moffline[0;0m:  vetsvr.no-ip.org:6112[0;0m
-[1;29m[2014-05-18 03:20:37 -0500] [0;0mServer [1;36m27[0;0m is [1;32monline[0;0m:   bnls.net:9367[0;0m
-[1;29m[2014-05-18 03:20:37 -0500] [0;0mServer [1;36m28[0;0m is [1;32monline[0;0m:   bnls.mattkv.net:9367[0;0m
-[1;29m[2014-05-18 03:20:37 -0500] [0;0mServer [1;36m29[0;0m is [1;32monline[0;0m:   phix.no-ip.org:9367[0;0m
-[1;29m[2014-05-18 03:20:37 -0500] [0;0mServer [1;36m30[0;0m is [1;32monline[0;0m:   bnls.anubisdev.net:9367[0;0m
-[1;29m[2014-05-18 03:20:37 -0500] [0;0mServer [1;36m31[0;0m is [1;32monline[0;0m:   pyro.no-ip.biz:9367[0;0m
-[1;29m[2014-05-18 03:20:38 -0500] [0;0mServer [1;36m32[0;0m is [1;32monline[0;0m:   vectorjbls.no-ip.org:9367[0;0m
-[1;29m[2014-05-18 03:20:38 -0500] [0;0mServer [1;36m33[0;0m is [1;31moffline[0;0m:  knight.mattkv.net:9367[0;0m
-[1;29m[2014-05-18 03:20:38 -0500] [0;0mServer [1;36m34[0;0m is [1;31moffline[0;0m:  bnls.war-lords.net:9367[0;0m
-[1;29m[2014-05-18 03:20:38 -0500] [0;0mServer [1;36m35[0;0m is [1;32monline[0;0m:   jailout2000.com:10011[0;0m
-[1;29m[2014-05-18 03:20:38 -0500] [0;0mServer [1;36m36[0;0m is [1;31moffline[0;0m:  jailout2000.com:25565[0;0m
-[1;29m[2014-05-18 03:20:38 -0500] [0;0m[1;33mAdding log entry to records...[0;0m
-[1;29m[2014-05-18 03:20:38 -0500] [0;0m[1;32mConnected to database server.[0;0m
-[1;29m[2014-05-18 03:20:38 -0500] [0;0m[1;32mLog entry recorded to logs table.[0;0m
-[1;29m[2014-05-18 03:20:38 -0500] [0;0m[1;32mLog entry recorded to filesystem.[0;0m
-[1;29m[2014-05-18 03:20:38 -0500] [0;0m[1;33mScript execution finished in [4;33m36.58s[0;33m[1;33m.[0;0m
diff --git a/check-servers.php b/check-servers.php
deleted file mode 100644
index a0507baf..00000000
--- a/check-servers.php
+++ /dev/null
@@ -1,348 +0,0 @@
-<?php
-
-  if (php_sapi_name() != "cli") {
-    http_response_code(503);
-    header("Cache-Control: max-age=0, must-revalidate, no-cache, no-store");
-    header("Content-Type: text/plain;charset=utf-8");
-    echo "This file is intended to be executed via php's command line.";
-    exit(1);
-  }
-  
-  if ($argc > 1) {
-    echo "Usage: php -f " . $argv[0] . "\n";
-    exit(1);
-  }
-  
-  final class Logger {
-
-    const FILENAME    = "/home/nginx/bnetdocs/check-servers.log";
-    const DATE_FORMAT = "Y-m-d H:i:s O";
-
-    private static $fileHandle;
-
-    public static function initialize() {
-      self::$fileHandle = fopen(self::FILENAME, "w");
-    }
-
-    public static function finalize() {
-      fclose(self::$fileHandle);
-    }
-
-    public static function write($message, $suppressTimestamp = true) {
-      if (!$suppressTimestamp) {
-        $timestamp = "\e[1;29m[" . date(self::DATE_FORMAT) . "] \e[0;0m";
-        fwrite(self::$fileHandle, $timestamp);
-        echo $timestamp;
-      }
-      fwrite(self::$fileHandle, $message);
-      echo $message;
-    }
-
-    public static function writeLine($message) {
-      self::write($message . "\n", false);
-    }
-
-  }
-
-  final class DB {
-
-    private $sql;
-
-    public function __construct() {
-      $this->sql = mysqli_init();
-    }
-
-    public function connect($host, $user, $pass, $db) {
-      return @$this->sql->real_connect($host, $user, $pass, $db);
-    }
-
-    public function close() {
-      return $this->sql->close();
-    }
-
-    public function error() {
-      return $this->sql->error;
-    }
-
-    public function errno() {
-      return $this->sql->errno;
-    }
-
-    public function escape($data) {
-      return $this->sql->real_escape_string($data);
-    }
-
-    public function query($str) {
-      $res = $this->sql->query($str);
-      if (!is_object($res)) return false;
-      $items = array();
-      while ($item = $res->fetch_assoc()) {
-        $items[] = $item;
-      }
-      $res->free();
-      return $items;
-    }
-
-  }
-
-  final class ServerCheck {
-
-    const CONNECT_TIMEOUT = 5;
-
-    private $sock;
-
-    public function __construct() {
-      $this->sock = socket_create(AF_INET, SOCK_STREAM, SOL_TCP);
-    }
-
-    public function __destruct() {
-      if (isset($this->sock) && ($this->sock instanceof resource))
-        socket_close($this->sock);
-    }
-
-    public function connect($address, $port) {
-      $timeout = self::CONNECT_TIMEOUT;
-      $time = time();
-      socket_set_nonblock($this->sock);
-      while (!@socket_connect($this->sock, $address, $port)) {
-        $err = socket_last_error($this->sock);
-        if ($err == 115 || $err == 114) {
-          if ((time() - $time) >= $timeout) {
-            socket_close($this->sock);
-            return false;
-          }
-          sleep(0.1);
-          continue;
-        }
-        return false;
-      }
-      socket_set_block($this->sock);
-      return true;
-    }
-
-    public function close() {
-      if (isset($this->sock) && ($this->sock instanceof resource))
-        socket_close($this->sock);
-      return true;
-    }
-
-    public function errno() {
-      return socket_last_error($this->sock);
-    }
-
-    public function error() {
-      return socket_strerror($this->errno());
-    }
-
-  }
-
-  Logger::initialize();
-  Logger::writeLine("\e[1;33mScript execution started.\e[0;0m");
-  $script_start = microtime(true);
-  $exit_code = 0;
-  
-  /**
-   * Statistics definition
-   **/
-  $stats = array(
-    "phoenix_servers"      => array(),
-    "phoenix_server_types" => array(),
-    "redux_servers"        => array(
-      "bnet"               => array(),
-      "bnls"               => array(),
-    ),
-    "timestamp"            => array(
-      "utc_offset"         => (int)date("Z"),
-      "start"              => $script_start,
-      "end"                => null,
-      "difference"         => null,
-      "total_time"         => null,
-    ),
-  );
-
-  /**
-   * BNETDocs Redux's servers
-   **/
-  Logger::writeLine("\e[1;33mUpdating BNETDocs Redux server tables...\e[0;0m");
-  $db = new DB();
-  if (!$db->connect("127.0.0.1", "bnetdocs", "redux123", "bnetdocs_botdev")) {
-    Logger::writeLine("\e[1;31mUnable to connect to the database.\e[0;0m");
-    Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
-    $exit_code = 1;
-  } else {
-    Logger::writeLine("\e[1;32mConnected to database server.\e[0;0m");
-
-    /**
-     * BNETDocs Redux's BNET servers
-     **/
-    $servers = $db->query("SELECT `id`, `serveraddress`, `port`, `version` FROM `bnetservers` ORDER BY `id` ASC;");
-    if (!$servers) {
-      Logger::writeLine("\e[1;31mFailed to retrieve the BNETDocs Redux BNET servers.\e[0;0m");
-      Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
-      $exit_code = 1;
-    } else {
-      foreach ($servers as $server) {
-        $server_stats = array(
-          "id"      => (int)$server["id"],
-          "address" => (string)$server["serveraddress"],
-          "port"    => (int)$server["port"],
-          "version" => (string)$server["version"],
-          "online"  => null,
-        );
-        $sock = new ServerCheck();
-        if (!$sock->connect($server["serveraddress"], $server["port"])) {
-          Logger::writeLine("\e[1;34mBNET\e[0;0m server is \e[1;31moffline\e[0;0m:  " . $server["serveraddress"] . ":" . $server["port"] . "\e[0;0m");
-          $db->query("UPDATE `bnetservers` SET `status` = 'offline' WHERE `id` = '" . $db->escape($server["id"]) . "' LIMIT 1;");
-          $server_stats["online"] = false;
-        } else {
-          Logger::writeLine("\e[1;34mBNET\e[0;0m server is \e[1;32monline\e[0;0m:   " . $server["serveraddress"] . ":" . $server["port"] . "\e[0;0m");
-          $db->query("UPDATE `bnetservers` SET `status` = 'online' WHERE `id` = '" . $db->escape($server["id"]) . "' LIMIT 1;");
-          $server_stats["online"] = true;
-        }
-        $stats["redux_servers"]["bnet"][] = $server_stats;
-        $sock->close();
-      }
-    }
-    
-    /**
-     * BNETDocs Redux's BNLS servers
-     **/
-    $servers = $db->query("SELECT `id`, `serveraddress`, `port` FROM `servers` ORDER BY `id` ASC;");
-    if (!$servers) {
-      Logger::writeLine("\e[1;31mFailed to retrieve the BNETDocs Redux BNLS servers.\e[0;0m");
-      Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
-      $exit_code = 1;
-    } else {
-      foreach ($servers as $server) {
-        $server_stats = array(
-          "id"      => (int)$server["id"],
-          "address" => (string)$server["serveraddress"],
-          "port"    => (int)$server["port"],
-          "online"  => null,
-        );
-        $sock = new ServerCheck();
-        if (!$sock->connect($server["serveraddress"], $server["port"])) {
-          Logger::writeLine("\e[1;35mBNLS\e[0;0m server is \e[1;31moffline\e[0;0m:  " . $server["serveraddress"] . ":" . $server["port"] . "\e[0;0m");
-          $db->query("UPDATE `servers` SET `status` = 'offline' WHERE `id` = '" . $db->escape($server["id"]) . "' LIMIT 1;");
-          $server_stats["online"] = false;
-        } else {
-          Logger::writeLine("\e[1;35mBNLS\e[0;0m server is \e[1;32monline\e[0;0m:   " . $server["serveraddress"] . ":" . $server["port"] . "\e[0;0m");
-          $db->query("UPDATE `servers` SET `status` = 'online' WHERE `id` = '" . $db->escape($server["id"]) . "' LIMIT 1;");
-          $server_stats["online"] = true;
-        }
-        $stats["redux_servers"]["bnls"][] = $server_stats;
-        $sock->close();
-      }
-    }
-    
-    $db->close();
-  }
-  
-  /**
-   * BNETDocs Phoenix's servers
-   **/
-  Logger::writeLine("\e[1;33mUpdating BNETDocs Phoenix server table...\e[0;0m");
-  $db = new DB();
-  if (!$db->connect("127.0.0.1", "bnetdocs", "redux123", "bnetdocs_phoenix")) {
-    Logger::writeLine("\e[1;31mUnable to connect to the database.\e[0;0m");
-    Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
-    $exit_code = 1;
-  } else {
-    Logger::writeLine("\e[1;32mConnected to database server.\e[0;0m");
-
-    define('STATUS_ONLINE',   1);
-    define('STATUS_DISABLED', 2);
-
-    $servers = $db->query("SELECT t.`id` AS `id`, t.`label` AS `label` FROM `server_types` t JOIN `servers` s ON t.`id` = s.`type` AND NOT s.`status` & " . STATUS_DISABLED . " GROUP BY t.`id` ASC;");
-    if (!$servers) {
-      Logger::writeLine("\e[1;31mFailed to retrieve the BNETDocs Phoenix server types.\e[0;0m");
-      Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
-      $exit_code = 1;
-    } else {
-      $types = array();
-      foreach ($servers as $server) {
-        $type_id    = (int)$server["id"];
-        $type_label = (string)$server["label"];
-        $types[]    = array($type_id, $type_label);
-      }
-      $stats["phoenix_server_types"] = $types;
-    }
-
-    $servers = $db->query("SELECT `id`, `address`, `port`, `type`, `label` FROM `servers` WHERE NOT (`status` & " . STATUS_DISABLED . ") ORDER BY `id` ASC;");
-    if (!$servers) {
-      Logger::writeLine("\e[1;31mFailed to retrieve the BNETDocs Phoenix servers.\e[0;0m");
-      Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
-      $exit_code = 1;
-    } else {
-      foreach ($servers as $server) {
-        $server_stats = array(
-          "id"         => (int)$server["id"],
-          "address"    => (string)$server["address"],
-          "port"       => (int)$server["port"],
-          "type"       => (int)$server["type"],
-          "label"      => (string)$server["label"],
-          "online"     => null,
-        );
-        $sock = new ServerCheck();
-        if (!$sock->connect($server["address"], $server["port"])) {
-          Logger::writeLine("Server \e[1;36m" . $server["id"] . "\e[0;0m is \e[1;31moffline\e[0;0m:  " . $server["address"] . ":" . $server["port"] . "\e[0;0m");
-          $db->query("UPDATE `servers` SET `status` = (`status` & ~" . STATUS_ONLINE . "), `date_updated` = NOW() WHERE `id` = '" . $db->escape($server["id"]) . "' LIMIT 1;");
-          $server_stats["online"] = false;
-        } else {
-          Logger::writeLine("Server \e[1;36m" . $server["id"] . "\e[0;0m is \e[1;32monline\e[0;0m:   " . $server["address"] . ":" . $server["port"] . "\e[0;0m");
-          $db->query("UPDATE `servers` SET `status` = (`status` | " . STATUS_ONLINE . "), `date_updated` = NOW() WHERE `id` = '" . $db->escape($server["id"]) . "' LIMIT 1;");
-          $server_stats["online"] = true;
-        }
-        $stats["phoenix_servers"][] = $server_stats;
-        $sock->close();
-      }
-    }
-    
-    $db->close();
-  }
-  
-  /**
-   * Logging mechanisms
-   **/
-  Logger::writeLine("\e[1;33mAdding log entry to records...\e[0;0m");
-  $script_end = microtime(true);
-  $script_time = $script_end - $script_start;
-  $stats["timestamp"]["end"] = $script_end;
-  $stats["timestamp"]["difference"] = $script_time;
-  $stats["timestamp"]["total_time"] = sprintf("%01.2fs", $script_time);
-  $str_stats = json_encode($stats);
-  $db = new DB();
-  if (!$db->connect("127.0.0.1", "bnetdocs", "redux123", "bnetdocs_phoenix")) {
-    Logger::writeLine("\e[1;31mUnable to connect to the database.\e[0;0m");
-    Logger::writeLine("\e[1;31mError #" . $db->errno() . ": " . $db->error() . "\e[0;0m");
-    $exit_code = 1;
-  } else {
-    Logger::writeLine("\e[1;32mConnected to database server.\e[0;0m");
-
-    $db->query("INSERT INTO `logs` (`type_id`, `event_date`, `content`) "
-      . "SELECT `type_id`, "
-      . "NOW() AS `event_date`, "
-      . "'" . $db->escape($str_stats) . "' AS `content` "
-      . "FROM `log_types` WHERE `type_name` = 'servers_refreshed_system';");
-    if ($db->errno() == 0) {
-      Logger::writeLine("\e[1;32mLog entry recorded to logs table.\e[0;0m");
-    } else {
-      Logger::writeLine("\e[1;31mLog entry failed to be recorded to logs table.\e[0;0m");
-    }
-    
-    $db->close();
-  }
-  try {
-    $fh = fopen("/home/nginx/bnetdocs/check-servers.json", "w");
-    fwrite($fh, $str_stats);
-    fclose($fh);
-    Logger::writeLine("\e[1;32mLog entry recorded to filesystem.\e[0;0m");
-  } catch (Exception $e) {
-    Logger::writeLine("\e[1;31mLog entry failed to be recorded to filesystem.\e[0;0m");
-  }
-
-  $script_time = microtime(true) - $script_start;
-  Logger::writeLine("\e[1;33mScript execution finished in \e[4;33m" . round($script_time, 2) . "s\e[0;33m\e[1;33m.\e[0;0m");
-  Logger::finalize();
-  exit($exit_code);
-  
diff --git a/check-servers.sh b/check-servers.sh
deleted file mode 100755
index ce9fea43..00000000
--- a/check-servers.sh
+++ /dev/null
@@ -1,14 +0,0 @@
-#!/bin/sh
-
-php -f /home/nginx/bnetdocs/check-servers.php
-EXIT_CODE=$?
-
-if [ $EXIT_CODE -ne 0 ]; then
-  echo -ne "\e[1;29m["
-  echo -n "`date +'%Y-%m-%d %H:%M:%S %z'`"
-  echo -ne "] \e[0;0m"
-  echo -e "\e[1;31mScript did not finish successfully.\e[0;0m"
-fi
-
-exit $EXIT_CODE
-

From 729183732d70ad62a29e711770136c75017f9785 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 26 Jul 2014 14:57:16 -0500
Subject: [PATCH 05/54] Fixed mysql error when setting utf8 charset.

---
 db.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/db.php b/db.php
index ff3330ab..b5d28eba 100644
--- a/db.php
+++ b/db.php
@@ -18,5 +18,5 @@
 
 	@$connection = mysql_connect("$dbhost","$dbusername","$dbpasswd") or die ("Couldn't connect to server because ".mysql_error());
 	@$db = mysql_select_db("$database_name", $connection) or die("Couldn't select database because ".mysql_error());
-	@mysql_query('SET NAMES utf8_general_ci;');
+	@mysql_query('SET NAMES utf8 COLLATE utf8_general_ci;');
 ?>

From ceeab6a398ea4c0bd0a732c36eab39ca4878db9d Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 26 Jul 2014 14:59:31 -0500
Subject: [PATCH 06/54] removed google analytics and advertising. added new
 relic tracking. fixed extraneous mysql queries on the traffic table from 401
 to 1 per request.

---
 bdif/footer.dm | 41 +----------------------------------------
 bdif/header.dm | 30 +++++++++++++++++-------------
 2 files changed, 18 insertions(+), 53 deletions(-)

diff --git a/bdif/footer.dm b/bdif/footer.dm
index 98a09a44..ae28aab6 100644
--- a/bdif/footer.dm
+++ b/bdif/footer.dm
@@ -131,35 +131,6 @@
 		?>
 		<br>
 	</div></div></div>
-	
-	
-	<?
-	if(!$userid){
-	?>
-	<div id="container">
-	<div id="main2">
-	<div id="author">Advertisements</div>
-		<div align=center>
-		<a href="/">Sponsor Us; Advertise here!</a><br><br>
-		<script type="text/javascript"><!--
-		google_ad_client = "pub-5293484515355302";
-		google_ad_width = 160;
-		google_ad_height = 600;
-		google_ad_format = "160x600_as";
-		google_ad_type = "text_image";
-		//2007-06-19: BNETDocs
-		google_ad_channel = "2273844208";
-		//-->
-		</script>
-		<script type="text/javascript"
-		  src="//pagead2.googlesyndication.com/pagead/show_ads.js">
-		</script>
-	</div>
-	</div>
-	</div>
-	<?
-	}
-	?>
 	</td>
 </tr></table>
 <br><br>
@@ -172,18 +143,8 @@ Demented Minds copyrights reserved to <a href="http://www.doncullen.net">Don Cul
 Copyright infringements will be prosecuted to the fullest extent allowable by law.
 <br>
 <a href="/?op=legalism"><font size="1">Please view our legal disclaimer and terms of service.</font></a><br><br>
-<?
-if($userid == 1){
-	?><a href="https://www.google.com/analytics/reporting/dashboard?id=4966196&pdr=20070819-20070918&cmp=average">Site Stats</a><?
-}
-?>
 </div>
 </div>
-<script src="//www.google-analytics.com/urchin.js" type="text/javascript">
-</script>
-<script type="text/javascript">
-_uacct = "UA-2637626-2";
-urchinTracker();
-</script>
+<? if( extension_loaded('newrelic') ) { echo newrelic_get_browser_timing_footer(); } ?>
 </body>
 </html>
diff --git a/bdif/header.dm b/bdif/header.dm
index 8f0f7468..8f8a58c8 100644
--- a/bdif/header.dm
+++ b/bdif/header.dm
@@ -6,15 +6,15 @@
   $FFTF_RESETTHENET     = ($FFTF_DATE == '2014-06-05');
 
 ?>
-<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
-   "http://www.w3.org/TR/html4/loose.dtd">
-<html>
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
+<html lang="en">
 <head>
 	<meta http-equiv="Content-Type" content="text/html;charset=utf-8" >
 	<meta name="description" content="Battle.Net Logon Sequences, Packets, information and protocols reference site.">
 	<meta name="keywords" content="Battle.Net, Logon Sequences, Packets, information, protocols reference, programming, coding, Starcraft, Warcraft, Diablo">
 
-	<? 
+	<?
+        if( extension_loaded('newrelic') ) { echo newrelic_get_browser_timing_header(); }
 	if(preg_match('/(?i)msie [1-9]/',$_SERVER['HTTP_USER_AGENT'])) { 
 		$ie = true;
 	} else { 
@@ -84,10 +84,6 @@
   } // END OF STOP THE SLOW LANE
   ?>
 </head>
-<!-- google_ad_section_start -->
-<!-- Battle.net StarCraft WarCraft Diablo War Counterstrike FPS Army Navy Marines Game Games RPG Vikings Blizzard Gold Leveling Mining Free Tutorials Movies Matrix 
-Computers Programming Binary Coding Hacking -->
-<!-- google_ad_section_end -->
 <body onload="doonload()">
 <?
   // FIGHT FOR THE FUTURE - RESET THE NET (https://www.resetthenet.org/)
@@ -126,7 +122,8 @@ Computers Programming Binary Coding Hacking -->
 		<a href="/forums/">Forums</a><br>
 		<a href="/?op=credits">Credits</a><br>
 		<a href="/archives/" target="_blank">BNETDocs Archives</a><br><br>
-	</div></div>
+        </div></div>
+<?php if (!$loginDisabled) { ?>
 	<div id="divConsole"><div id="author">Console</div><div class="navmenu" id="bodyConsole">
 		<?
 			if($userid){
@@ -138,7 +135,8 @@ Computers Programming Binary Coding Hacking -->
 				include 'bdif/login.dm';
 			}
 		?>
-	</div></div>
+        </div></div>
+<?php } ?>
 	<div id="divDocuments"><div id="author">Documents</div><div class="navmenu" id="bodyDocuments">
 		<?
 		$sqlqueryz = 'SELECT * FROM documents ORDER BY title ASC';
@@ -186,7 +184,12 @@ Computers Programming Binary Coding Hacking -->
 		<input type="text" id="inputbox" name="quickjump"><input type="submit" id="abutton" value="go">
 		</form>
 		<br>
-		<?
+<?
+                $sqlquery_traffic = mysql_query('SELECT * FROM traffic ORDER BY id');
+                $traffic = array();
+                while($sqlresult_traffic = mysql_fetch_array($sqlquery_traffic)) {
+                        $traffic[$sqlresult_traffic["id"]] = $sqlresult_traffic;
+                }
 		$sqlquerya = 'SELECT * FROM groups ORDER BY displayorder';
 		$groupsarray = mysql_query($sqlquerya);
 		$zs1 = 1;
@@ -205,8 +208,9 @@ Computers Programming Binary Coding Hacking -->
 			$packetsarray = mysql_query($sqlquery);
 			while($row = mysql_fetch_array($packetsarray)){
 				$pid = $row['id'];
-				$direction = $row['direction'];
-				$direction = GetInfo('traffic', 'id', $direction, 'shortdescr') . ' ';
+                                //$direction = $row['direction'];
+                                $direction = $traffic[$row['direction']]['shortdescr'] . ' ';
+				//$direction = GetInfo('traffic', 'id', $direction, 'shortdescr') . ' ';
 				$messageid = '['.$row['messageid'].'] ';
 				$messagename = $row['messagename'];
 				$pclearance = $row['clearance'];

From bd736728572a61c95c94ec147c601e7a75d048b7 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 26 Jul 2014 16:15:49 -0500
Subject: [PATCH 07/54] New Relic Transaction Names.

---
 index.php | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/index.php b/index.php
index 1f36ccab..5f12db75 100644
--- a/index.php
+++ b/index.php
@@ -88,6 +88,12 @@ function stripslashes_deep($value) {
 		
 		if($allowfile=='false') exit();
 
+        # New Relic Transactions
+        #-------------
+
+                if (extension_loaded('newrelic')) {
+                        newrelic_name_transaction("/" . $op . ".php");
+                }
 
 	# Surpress code is in place to prevent a HEADER ALREADY SENT error.
 	#-------------

From 94f481dbf1c45a5426b1e0c4153b13ff1e8da59f Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 26 Jul 2014 16:18:41 -0500
Subject: [PATCH 08/54] Fix empty New Relic Transaction name on main page load.

---
 index.php | 6 +++++-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/index.php b/index.php
index 5f12db75..c7ced808 100644
--- a/index.php
+++ b/index.php
@@ -92,7 +92,11 @@ function stripslashes_deep($value) {
         #-------------
 
                 if (extension_loaded('newrelic')) {
-                        newrelic_name_transaction("/" . $op . ".php");
+                  if ($op == "") {
+                    newrelic_name_transaction("/news.php");
+                  } else {
+                    newrelic_name_transaction("/" . $op . ".php");
+                  }
                 }
 
 	# Surpress code is in place to prevent a HEADER ALREADY SENT error.

From 756976f300d20d8be628a5595b74d8768884cc7b Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 26 Jul 2014 16:36:46 -0500
Subject: [PATCH 09/54] New Relic custom parameter tracking of user
 registrations.

---
 register.php | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/register.php b/register.php
index a37978ed..287a7f66 100644
--- a/register.php
+++ b/register.php
@@ -78,6 +78,10 @@
 			$error = 'true';
 		}
 		if($_POST['email'] && $_POST['username'] && $_POST['agree']){
+                        if (extension_loaded('newrelic')) {
+                                newrelic_add_custom_parameter('username', $username);
+                                newrelic_add_custom_parameter('email', $email);
+                        }
 			if(FieldVerify('username', 'users', $_POST['username'])){
 				?><div id="container">
 				<div id="main2">

From 03ddf73ab4822cf4143d2c726aab6400dd147ea2 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 26 Jul 2014 16:40:07 -0500
Subject: [PATCH 10/54] Fix variable usage for New Relic tracking of user
 registrations.

---
 register.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/register.php b/register.php
index 287a7f66..5aa612a1 100644
--- a/register.php
+++ b/register.php
@@ -79,8 +79,8 @@
 		}
 		if($_POST['email'] && $_POST['username'] && $_POST['agree']){
                         if (extension_loaded('newrelic')) {
-                                newrelic_add_custom_parameter('username', $username);
-                                newrelic_add_custom_parameter('email', $email);
+                                newrelic_add_custom_parameter('username', $_POST['email']);
+                                newrelic_add_custom_parameter('email', $_POST['username']);
                         }
 			if(FieldVerify('username', 'users', $_POST['username'])){
 				?><div id="container">

From 87179de2743c7d4ae38d51b05a7aea820991a4b1 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 27 Jul 2014 21:13:32 -0500
Subject: [PATCH 11/54] Merge of func.php and functions.php as well as fixing
 include, include_once, and require to require_once.

---
 cache/bnetdocsredux.txt | 4089 +++++++++++++++++++++++++++++++++++++++
 func.php                | 1057 ----------
 functions.php           |    6 +-
 generatedocs.php        |    6 +-
 index.php               |    4 +-
 logsrss.php             |    4 +-
 newsrss.php             |    4 +-
 sessionhandler.php      |    6 +-
 8 files changed, 4104 insertions(+), 1072 deletions(-)
 create mode 100644 cache/bnetdocsredux.txt
 delete mode 100644 func.php

diff --git a/cache/bnetdocsredux.txt b/cache/bnetdocsredux.txt
new file mode 100644
index 00000000..39627044
--- /dev/null
+++ b/cache/bnetdocsredux.txt
@@ -0,0 +1,4089 @@
+Battle.net Documentation generated by BNETDocs
+ =======================================================
+
+ Notes:
+ -------
+ A Battle.net server usually listens on TCP/IP port 6112.
+ A BNLS server usually listens on TCP/IP port 9367.
+ A message and its response have the same ID. (The response to BNLS_CDKEY is BNLS_CDKEY, etc)
+
+ ===============================
+ Begin Generated Documentation
+ ===============================
+
+ Battle.net v1 Messages
+ ------------------------------
+
+ S > C [0x00] SID_NULL
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ [blank]
+
+ Remarks:
+ Keeps the connection alive. Clients do not need to respond to this message.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x00] SID_NULL
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ [blank] 
+
+ Remarks:
+ Keeps the connection alive. This message should be sent to the server every 8 minutes (approximately).
+
+ The server will send this to you automatically, you do not have to reply to it. You should send this on your own
+ never-ending timer for at least as often as Battle.net does (give or take a few seconds).
+
+ This packet is used to detect if your TCP connection has gone dead, to the point where you will never receive data from
+ the server ever again until you reconnect your connection. A situation such as this can be created by unplugging your
+ internet connection for a few minutes, or if your internet is dropped for whatever reason.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x02] SID_STOPADV
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ [blank]
+
+ Remarks:
+ This message is sent to inform the server that a game should no longer be advertised to other users. It is sent when a
+ game starts, or when a game is aborted (the host leaves).
+
+ All Battle.snp clients (DRTL, DSHR, STAR/SEXP, JSTR, SSHR, and W2BN) always send this message when logging off, even if
+ it not in a game.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x04] SID_SERVERLIST
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Starcraft, Starcraft
+ Japanese, Diablo I, Diablo II LOD
+
+ Format:
+ (DWORD) Server version
+ (STRING) [] Server list
+
+ Remarks:
+ Client should set the internal Battle.net server list from the contents of this message.
+
+ This packet is supported by all Battle.snp games and Diablo II and its expansion.
+
+ Note that this packet is defunct. The clients (including Warcraft III) all ask Battle.net for the FILETIME structure of
+ the gateway list file and then compares that structure to its own cached copy. If the FILETIMEs do not match, then it
+ goes to BNFTP and downloads a new one and stores it to the Windows Registry (or on file, if using Mac) while also
+ caching the new FILETIME for later. They do not ever under any circumstance store the actual file data, and therefore
+as
+ long as the cache is not changed and Battle.net always reports the same FILETIME, you can modify your gateway list
+ without it knowing it changed.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x05] SID_CLIENTID
+ **************************************
+
+ Used By: Starcraft Shareware, Diablo Shareware, Warcraft II, Starcraft Japanese, Diablo I
+
+ Format:
+ (DWORD) Registration Version
+ (DWORD) Registration Authority
+ (DWORD) Account Number
+ (DWORD) Registration Token 
+
+ Remarks:
+ The following information is historical:
+
+ This message used to be used to issue new values to the client for the above fields. New values were issued when the
+ values supplied in SID_CLIENTID were found to be invalid.
+
+ Since these fields are no longer used, the server now sets them to zero.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x05] SID_CLIENTID
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Japanese
+
+ Format:
+ (DWORD) Registration Version
+ (DWORD) Registration Authority
+ (DWORD) Account Number
+ (DWORD) Registration Token
+ (STRING) LAN Computer Name
+ (STRING) LAN Username
+
+ Remarks:
+ This packet was used to ensure that the client's account number was valid. All but the last two fields in this message
+ are now ignored, and may be set to zero.
+
+ The 'LAN Computer Name' field is the NetBIOS name of the computer. It can be retrieved using the GetComputerName [1]
+ API.
+
+ The 'Lan Username' field is the name of the currently logged on user, and may be retrieved using the GetUsername [2]
+ API.
+
+ The following information is historical:
+
+ The client would supply this data as issued by a Battle.net server. If the Registration Version, Registration
+ Authority, and Client Token values equated to the account number supplied (Client ID), as determined by an unknown
+ formula, the server would respond with the same values. If they were invalid, the server would assign new values.
+ Registration Version was always 1, Authority was the IP address of the server that issued the account number. Thus, the
+ Client Token was the secret value, used to prove that the client really owned the account in question.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x06] SID_STARTVERSIONING
+ **************************************
+
+ Used By: Starcraft Shareware, Diablo Shareware, Warcraft II, Starcraft Japanese, Diablo I
+
+ Format:
+ (FILETIME) MPQ Filetime
+ (STRING) MPQ Filename
+ (STRING) ValueString 
+
+ Remarks:
+ Contains CheckRevision values.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x06] SID_STARTVERSIONING
+ **************************************
+
+ Used By: Starcraft Shareware, Diablo Shareware, Warcraft II, Starcraft Japanese, Diablo I
+
+ Format:
+ (DWORD) Platform ID
+ (DWORD) Product ID
+ (DWORD) Version Byte
+ (DWORD) Unknown (0) 
+
+ Remarks:
+ This message is sent to the server to start the process of checking the game files. This message is part of the old
+ logon process for products before Starcraft.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x07] SID_REPORTVERSION
+ **************************************
+
+ Used By: Starcraft Shareware, Diablo Shareware, Warcraft II, Starcraft Japanese, Diablo I
+
+ Format:
+ (DWORD) Result
+ (STRING) Patch path 
+
+ Remarks:
+ Reports success/failure on challenge.
+
+ Result:
+ 0: Failed version check 1: Old game version 2: Success 3: Reinstall required
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x07] SID_REPORTVERSION
+ **************************************
+
+ Used By: Starcraft Shareware, Diablo Shareware, Warcraft II, Starcraft Japanese, Diablo I
+
+ Format:
+ (DWORD) Platform ID
+ (DWORD) Product ID
+ (DWORD) Version Byte
+ (DWORD) EXE Version
+ (DWORD) EXE Hash
+ (STRING) EXE Information 
+
+ Remarks:
+ Contains CheckRevision response, version & EXE info.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x08] SID_STARTADVEX
+ **************************************
+
+ Used By: Starcraft Shareware
+
+ Format:
+ (DWORD) Status 
+
+ Remarks:
+ Status
+ 0x00: Failed 0x01: Success
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x08] SID_STARTADVEX
+ **************************************
+
+ Used By: Starcraft Shareware
+
+ Format:
+ (DWORD) State
+ (DWORD) Time since creation
+ (WORD) Game Type
+ (WORD) Parameter
+ (DWORD) Unknown (0x00)
+ (DWORD) Unknown (Likely ladder, but will always be 0x00 because there is no SSHR ladder)
+ (STRING) Game name
+ (STRING) Game password
+ (STRING) Game Statstring
+
+ Remarks:
+ Creates a game in a manner similar to SID_STARTADVEX2 and SID_STARTADVEX3. This is only used by Starcraft Shareware.
+ See documentation on SID_STARTADVEX3 for details on the values and their meanings.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x09] SID_GETADVLISTEX
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Number of games
+ If count is 0: (DWORD) Status Otherwise, games are listed thus: For each list item: WARCRAFT III: (DWORD) Game Type
+ (DWORD) Language ID (WORD) Address Family (Always AF_INET) (WORD) Port (DWORD) Host's IP (DWORD) sin_zero (0) (DWORD)
+ sin_zero (0) (DWORD) Unknown (Public = 0x10, Private = 0x11) (DWORD) Elapsed time (in seconds) (STRING) Game name *
+ (STRING) Game password (always empty) (BYTE) Free slots (character representing hexadecimal number) (BYTE)[8] Host
+ counter (characters representing reversed hexadecimal number, ex: '20000000' for second time this host has hosted
+during
+ his session) (STRING) Encoded map information ALL OTHER CLIENTS: (WORD) Game Type (WORD) Sub Game Type (DWORD) Language
+ ID (WORD) Address Family (Always AF_INET) (WORD) Port (DWORD) Host's IP (DWORD) sin_zero (0) (DWORD) sin_zero (0)
+ (DWORD) Game Status (DWORD) Elapsed time (in seconds) (STRING) Game name * (STRING) Game password (STRING) Game
+ statstring 
+
+ Remarks:
+ Returns a list of available games and their information. Varies depending on product.
+
+ * This field is UTF-8 encoded.
+
+ For WarCraft III, map information is encoded using the function found here [3]:
+ Encoded data: (DWORD) Map Flags (BYTE) Map Null 1 (BYTE) Map Width (playable area) (BYTE) Map Null 2 (BYTE) Map Height
+ (playable area) (BYTE) Map Null 3 (DWORD) Map CRC (STRING) Map Path (STRING) Game Host (BYTE) Map Unknown (possibly a
+ STRING with just the null terminator) (BYTE)[20] Unknown (probably a SHA1 hash) Possible flags (combine the below
+ settings) for Map Flags: Game Speed (mask 0x00000003, unique) 0x00000000: Slow 0x00000001: Normal 0x00000002: Fast
+ Visibility setting (mask 0x00000F00, unique) 0x00000100: Hide Terrain 0x00000200: Map Explored 0x00000400: Always
+ Visible 0x00000800: Default Observers setting (mask 0x40003000, unique) 0x00000000: No Observers 0x00002000: Observers
+ on Defeat 0x00003000: Full Observers 0x40000000: Referees Other advanced host settings (mask 0x07064000, combinable)
+ 0x00004000: Teams Together (team members are placed at neighbored starting locations) 0x00060000: Lock Teams
+0x01000000:
+ Full Shared Unit Control 0x02000000: Random Hero 0x04000000: Random Races Non-WarCraft III Game Statstring Field:
+ For other clients, game statring follows the format found here [4].
+
+ WarCraft III Game Type Field (combine the below settings):
+ Game Type (mask 0x000000FF, unique) 0x00000001: Custom 0x00000009: Ladder Map Author (mask 0x00006000, combinable)
+ 0x00002000: Blizzard 0x00004000: Custom Battle/Scenario (mask 0x00018000, unique) 0x00000000: Battle 0x00010000:
+ Scenario Map Size (mask 0x000E0000, combinable) 0x00020000: Small 0x00040000: Medium 0x00080000: Huge Observers (mask
+ 0x00700000, unique) 0x00100000: Allowed observers ("Full Observers" and "Referees" options) 0x00200000: Observers on
+ defeat 0x00400000: No observers Public/Private (mask 0x00000800, unique) 0x00000000: Public game 0x00000800: Private
+ game STAR/SEXP/SSHR/JSTR/W2BN Game Type Field:
+ Game Type (unique) 0x01: Custom (WAR3/W3XP) 0x02: Melee 0x03: Free For All 0x04: One vs One 0x05: Capture the Flag
+ 0x06: Greed 0x07: Slaughter 0x08: Sudden Death 0x09: Ladder 0x10: Iron man ladder (W2BN) 0x0A: Use Map Settings 0x0B:
+ Team Melee 0x0C: Team FFA 0x0D: Team CTF 0x0F: Top vs. Bottom STAR/SEXP/SSHR/JSTR/W2BN Sub Game Type Field:
+ For Greed: 0x01: 2500 resources 0x02: 5000 resources 0x03: 7500 resources 0x04: 10000 resources For Slaughter: 0x01: 15
+ minutes 0x02: 30 minutes 0x03: 45 minutes 0x04: 60 minutes For Team Melee, Team Free For All, and Team Capture the
+Flag:
+ 0x01: 2 teams 0x02: 3 teams 0x03: 4 teams For Top vs. Bottom: 0x01: 1 v 7 0x02: 2 v 6 0x03: 3 v 5 0x04: 4 v 4 0x05: 5 v
+ 3 0x06: 6 v 2 0x07: 7 v 1 For Ladder: 0x00: Disconnects do not count as loss 0x01: Disconnects count as loss For Other
+ Game Types: 0x01: No sub-game type DRTL/DSHR Game Type Field:
+ Game Type is used to specify a 'level range'. This ensures that clients receive a list of games containing players
+ whose experience is similar to their own. 0x00: Level 1 0x01: Level 2 or 3 0x02: Level 4 or 5 0x03: Level 6 or 7 0x04:
+ Level 8 or 9 0x05: Level 10 - 12 0x06: Level 13 - 16 0x07: Level 17 - 19 0x08: Level 20 - 24 0x09: Level 25 - 29 0x0A:
+ Level 30 - 34 0x0B: Level 35 - 39 0x0C: Level 40 - 47 0x0D: Level 48 - 50 
+ Note that fields from Address Family to sin_zero form a sockaddr_in structure.
+
+ Valid status codes:
+ This field is the 'Game Status' for non-WarCraft III and the 'Status' when no games are listed for both WarCraft III
+ and other clients. 0x00: OK 0x01: Game doesn't exist 0x02: Incorrect password 0x03: Game full 0x04: Game already
+started
+ 0x05: Spawned CD-Key not allowed 0x06: Too many server requests
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x09] SID_GETADVLISTEX
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Starcraft, Starcraft
+ Japanese, Diablo I, Diablo II LOD
+
+ Format:
+ (WORD) Game Type
+ (WORD) Sub Game Type
+ (DWORD) Viewing Filter
+ (DWORD) Reserved (0)
+ (DWORD) Number of Games
+ (STRING) Game Name
+ (STRING) Game Password
+ (STRING) Game Statstring
+
+ Remarks:
+ Retrieves a list of games.
+
+ GAME TYPE: For STAR/SEXP/SSHR/JSTR and W2BN, a value of 0 indicates that any type is acceptable.
+ Possible game types: 0x00: All 0x02: Melee 0x03: Free for all 0x04: one vs one 0x05: CTF 0x06: Greed 0x07: Slaughter
+ 0x08: Sudden Death 0x09: Ladder 0x10: Iron man ladder 0x0A: Use Map Settings 0x0B: Team Melee 0x0C: Team FFA 0x0D: Team
+ CTF 0x0F: Top vs. Bottom 
+ For DRTL/DSHR, Game Type is used to specify a 'level range'. This ensures that clients receive a list of games
+ containing players whose experience is similar to their own.
+ Possible ranges: 0x00: Level 1 0x01: 2 - 3 0x02: 4 - 5 0x03: 6 - 7 0x04: 8 - 9 0x05: 10 - 12 0x06: 13 - 16 0x07: 17 -
+ 19 0x08: 20 - 24 0x09: 25 - 29 0x0A: 30 - 34 0x0B: 35 - 39 0x0C: 40 - 47 0x0D: 48 - 50 For all other games, Game Type
+ can be set to 0x00. SUB GAME TYPE: For Greed, this is resources in multiples of 2500 (0x01 = 2500, 0x02 = 5000, etc).
+ For Slaughter, this is minutes in multiples of 15 (0x01 = 15, 0x02 = 30, etc). For Ladder, this indicates if
+disconnects
+ count as a loss (0x01 = Yes, 0x00 = No). For Team Melee, this is the number of teams (0x01 = 2, 0x02 = 3, etc). For
+Team
+ Free For All, this is the number of teams (0x01 = 2, 0x02 = 3, etc). For Team Capture The Flag, this is the number of
+ teams (0x01 = 2, 0x02 = 3, etc). For Top vs. Bottom, this is the players to team ratio (1-7). For any other game type,
+ it is 0x01 which indicates no sub game type. VIEWING FILTER: 0xFFFF is used to use the combination of values in this
+ packet. 0xFF80 is used to show all games. For STAR/SEXP/SSHR/JSTR, viewing filter is set to 0x30. For DRTL/DSHR,
+viewing
+ filter is set to 0xFFFF by the game, but setting it to 0x00 will disable any viewing limitations, letting you view all
+ games. RESERVED (0): This value is hardcoded to 0x00 by all games. NUMBER OF GAMES: This is the number of games to
+ list. For a full listing, it's safe to use 0xFF. By default, DRTL/DSHR sets this to 0x19.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x0A] SID_ENTERCHAT
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Starcraft, Starcraft
+ Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (STRING) Unique name
+ (STRING) Statstring
+ (STRING) Account name 
+
+ Remarks:
+ Contains Client product, realm, statstring, and is sent as the response when the client sends SID_ENTERCHAT. Unique
+name
+ is the users unique name in chat (Which may be Arta, Arta#2, Arta#3, etc). Account name is the users account name
+(Which
+ in all 3 previous examples would be Arta).
+
+ Once you receive this packet, you are not in a channel, but can join/host games and join channels. Because you are not
+ in a channel, you cannot send text messages yet (but you will not be disconnected if you do). See SID_JOINCHANNEL.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x0A] SID_ENTERCHAT
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (STRING) Username *
+ (STRING) Statstring **
+
+ Remarks:
+ Joins Chat. 
+
+ * Null on WAR3/W3XP.
+
+ ** Null on CDKey Products, except for D2DV and D2XP when on realm characters..
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x0B] SID_GETCHANNELLIST
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (STRING) [] Channel names, each terminated by a null string.
+
+ Remarks:
+ Contains a list of available channels.
+
+ For some reason, Diablo II adds extra data to the channel list (as can be seen in game), and older clients list blocked
+ channels, such as Warez and Backstage.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x0B] SID_GETCHANNELLIST
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Product ID 
+
+ Remarks:
+ Requests a list of channels that the client is permitted to enter.
+
+ In the past this packet returned a product list for the specified Product ID, however, the Product ID field is now
+ ignored -- it does not need to be a valid Product ID, and can be set to zero. The list of channels returned will be for
+ the client's product, as specified during the client's logon.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x0C] SID_JOINCHANNEL
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Flags
+ (STRING) Channel 
+
+ Remarks:
+ Joins a channel after entering chat.
+
+ The Channel name must be no greater than 31 characters, otherwise it becomes trimmed by Battle.net.
+
+ The flags field may contain the following values:
+ 0x00: NoCreate join
+ 0x01: First join
+ 0x02: Forced join
+ 0x05: D2 first join
+
+ NoCreate Join: This will only join the channel specified if it is not empty, and is used by clients when selecting a
+ channel from the channels menu. If the channel is empty, Battle.net sends a SID_CHATEVENT of type
+ EID_CHANNELDOESNOTEXIST, upon which official clients prompt for confirmation that the user wishes to create the
+channel,
+ in which case, it resends this packet with Flags set to Forced Join (0x02). First Join: Places user in a channel
+ starting with their product and country, followed by a number, ie 'Brood War GBR-1'. Also automatically sends MOTD
+after
+ entering the channel. When using this type, the Channel variable has no effect, but must be present anyway to avoid an
+ IP ban. This is sent when first logging onto Battle.net Forced Join: This is sent when leaving a game, and joins the
+ specified channel without an supplying an MOTD. D2 First Join: The same as First join, but is used for D2DV/D2XP
+ clients.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x0E] SID_CHATCOMMAND
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (STRING) Text *
+
+ Remarks:
+ Send text or a command to Battle.net using this packet.
+
+ For STAR/SEXP/SSHR/JSTR, Text is UTF-8 encoded (WIDESTRING).
+
+ It is generally accepted as unwise to send any character below a space (0x20): this includes line feeds, carriage
+ returns & control characters. The maximum number of characters is 224 per message including the null-terminator (so
+ really only 223 characters), any longer and it becomes trimmed by Battle.net.
+
+ If you send a line feed and/or a carriage return, Battle.net disconnects you and IP bans you for 5 minutes.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x0F] SID_CHATEVENT
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Event ID
+ (DWORD) User's Flags
+ (DWORD) Ping
+ (DWORD) IP Address (Defunct)
+ (DWORD) Account number (Defunct)
+ (DWORD) Registration Authority (Defunct)
+ (STRING) Username
+ (STRING) Text *
+
+ Remarks:
+ Contains all chat events.
+
+ For STAR/SEXP/SSHR/JSTR, Text is UTF-8 encoded (WIDESTRING).
+
+ * Text should be no longer than 255 characters. Game clients should only be able to send 224 characters.
+ Event IDs: [0x01] EID_SHOWUSER: User in channel [0x02] EID_JOIN: User joined channel [0x03] EID_LEAVE: User left
+ channel [0x04] EID_WHISPER: Recieved whisper [0x05] EID_TALK: Chat text [0x06] EID_BROADCAST: Server broadcast [0x07]
+ EID_CHANNEL: Channel information [0x09] EID_USERFLAGS: Flags update [0x0A] EID_WHISPERSENT: Sent whisper [0x0D]
+ EID_CHANNELFULL: Channel full [0x0E] EID_CHANNELDOESNOTEXIST: Channel doesn't exist [0x0F] EID_CHANNELRESTRICTED:
+ Channel is restricted [0x12] EID_INFO: Information [0x13] EID_ERROR: Error message [0x15] EID_IGNORE: Notifies that a
+ user has been ignored (DEFUNCT) [0x16] EID_ACCEPT: Notifies that a user has been unignored (DEFUNCT) [0x17] EID_EMOTE:
+ Emote EID_SHOWUSER: This is sent for each user who is already in a channel when you join it, as opposed to EID_JOIN,
+ which is sent when a user joins a channel you have already joined. It is also sent when logged on using D2XP/D2DV and a
+ user requires an update to their statstring - for example, by logging a different character onto a realm. EID_JOIN:
+This
+ is sent when a user enters the channel you are currently in. EID_LEAVE: This is sent when a user exits the channel you
+ are currently in. EID_WHISPER: This is sent when a user whispers you. EID_TALK: This is sent when a user (excluding
+ self) in chat speaks. EID_BROADCAST: The username supplied for this event is now always 'Battle.net'. Historically,
+ username contained the name of the Battle.net Administrator who sent the broadcast. EID_CHANNEL: The flags field for
+ this event is used and indicates what special conditions exist for the channel in question. See [Battle.net Flags] for
+ more information. EID_USERFLAGS: This is sent to inform the client of an update to one or more user's flags. Battle.net
+ usually sends this event for every user in the channel, even if only one user's flags have changed. This behavior can
+be
+ exploited to detect invisible users, by performing an action (such as an unsquelch) to provoke a flags update. Users
+ included in the flags update whose presence has not been indicated by EID_JOIN or EID_SHOWUSER can then be added to the
+ userlist as invisible. Care should be taken, however, to account for the possibility that an asynchronous send error
+has
+ occurred. Should an EID_JOIN or EID_SHOWUSER event occur for an invisible user, they should be marked as a normal user,
+ not readded to the userlist. EID_WHISPERSENT: The Flags and Ping fields in this packet is equal to the originating user
+ - the one who sent the whisper. In other words, EID_WHISPERSENT contains your flags & ping, not those of the person you
+ whispered. EID_CHANNELDOESNOTEXIST: See info on NoCreate Join in SID_JOINCHANNEL. EID_CHANNELRESTRICTED: This is sent
+ when attempting to join a channel which your client is not allowed to join. EID_INFO: This is information supplied by
+ Battle.net. This text is usually displayed by clients in yellow. EID_Error: This is error information supplied by
+ Battle.net. This text is usually displayed by clients in red. EID_Emote: This is sent when any user (including self)
+ uses the emote feature in chat.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x10] SID_LEAVECHAT
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ [blank] 
+
+ Remarks:
+ Leaves chat mode but does not disconnect. Generally sent when entering a game. This is also sent by D2DV/D2XP when
+ switching characters, and by all products when logging off.
+
+ After you send this, normal chat functions to not work. In order to enter a channel when you are not in chat mode, you
+ must send SID_JOINCHANNEL.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x12] SID_LOCALEINFO
+ **************************************
+
+ Used By: Diablo Shareware, Warcraft II, Diablo I
+
+ Format:
+ (FILETIME) System time
+ (FILETIME) Local time
+ (DWORD) Timezone bias
+ (DWORD) SystemDefaultLCID
+ (DWORD) UserDefaultLCID
+ (DWORD) UserDefaultLangID
+ (STRING) Abbreviated language name
+ (STRING) Country name
+ (STRING) Abbreviated country name
+ (STRING) Country (English) 
+
+ Remarks:
+ Informs the server of the client's locale information. Much of this functionality has been incorporated into
+ SID_AUTH_INFO, and more in-depth remarks can be found there. 
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x13] SID_FLOODDETECTED
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ [blank] 
+
+ Remarks:
+ Sent prior to a disconnect along with SID_MESSAGEBOX to indicate that the client has flooded off. 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x14] SID_UDPPINGRESPONSE
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Starcraft Japanese, Diablo
+I
+
+ Format:
+ (DWORD) UDPCode 
+
+ Remarks:
+ Enables UDP support.
+
+ Server supplies code via UDP packet PKT_SERVERPING (0x05). Usually 'bnet'.
+
+ Not responding will give you a UDP Plug in chat (flag 0x10).
+
+ You should send this anytime between S>C 0x50 SID_AUTH_INFO (or equivalent) and C>S 0x0A SID_ENTERCHAT. Sending this
+ packet before or after these two packets will get you disconnected from official servers.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x15] SID_CHECKAD
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III, World of Warcraft
+
+ Format:
+ (DWORD) Ad ID
+ (DWORD) File extension
+ (FILETIME) Local file time
+ (STRING) Filename
+ (STRING) Link URL
+
+ Remarks:
+ Contains information needed to download and display an ad banner. 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x15] SID_CHECKAD
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Platform ID
+ (DWORD) Product ID
+ (DWORD) ID of last displayed banner
+ (DWORD) Current time
+
+ Remarks:
+ Requests ad banner information from Battle.net.
+
+ Official clients send this packet every 20 seconds (give or take). You do not have to send this at all.
+
+ In addition, Battle.net will not reply unless any of the fields above are updated from the last time you checked. If
+ you have never checked before, Battle.net will always reply back.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x16] SID_CLICKAD
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Ad ID
+ (DWORD) Request type
+
+ Remarks:
+ The clients send this when an ad is clicked.
+
+ Request Type is 0 if the client used SID_QUERYADURL to get the ad's data, 1 otherwise. 
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x17] SID_READMEMORY
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Starcraft Japanese, Diablo
+I
+
+ Format:
+ (DWORD) Request ID
+ (DWORD) Address
+ (DWORD) Length
+
+ Remarks:
+ Rudimentary hack detection system. Was never used probably due to terrible implementation with little security.
+
+ Yes, it is possible for a PvPGN server to read EVERYTHING that is in the process' memory, including sensitive
+ information such as your CDKey.
+
+ Found at:
+ battle!1901D470h (as of 1.16.1)
+
+ NOTE: No longer used, as Warden is now used to monitor for hacks. The Battle.net clients still support this though so
+ one can code in support for it if one so desires. Due to it being no longer actively used by Battle.net, this packet is
+ being marked as defunct. 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x17] SID_READMEMORY
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Starcraft Japanese, Diablo
+I
+
+ Format:
+ (DWORD) Request ID
+ (VOID) Memory
+
+ Remarks:
+ Rudimentary hack detection system. Was never used probably due to terrible implementation with little security.
+
+ Yes, it is possible for a PvPGN server to read EVERYTHING that is in the process' memory, including sensitive
+ information such as your CDKey.
+
+ Found at:
+ battle!1901D470h (as of 1.16.1)
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x18] SID_REGISTRY
+ **************************************
+
+ Format:
+ (DWORD) Cookie
+ (DWORD) HKEY
+ (STRING) Registry path
+ (STRING) Registry key 
+
+ Remarks:
+ HKEY is the registry key root.The values are standard: 0x80000000: HKEY_CLASSES_ROOT 0x80000001: HKEY_CURRENT_USER
+ 0x80000002: HKEY_LOCAL_MACHINE 0x80000003: HKEY_USERS 0x80000004: HKEY_PERFORMANCE_DATA 0x80000005: HKEY_CURRENT_CONFIG
+ 0x80000006: HKEY_DYN_DATA 0x80000050: HKEY_PERFORMANCE_TEXT 0x80000060: HKEY_PERFORMANCE_NLSTEXT
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x18] SID_REGISTRY
+ **************************************
+
+ Format:
+ (DWORD) Cookie
+ (STRING) Key Value 
+
+ Remarks:
+ Returns the requested registry value
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x19] SID_MESSAGEBOX
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Style
+ (STRING) Text
+ (STRING) Caption
+
+ Remarks:
+ Displays a message to the user. This message's fields are used as parameters for the Win32 API MessageBox [5], and can
+ be passed directly to it. For more information about these parameters, see the documentation for MessageBox [6] at
+MSDN.
+
+ Some more research on the behavior of this packet in Starcraft Broodwar has been done by HarpyWar and xboi209. Their
+ documentation can be found on GitHub [7]. Specifically, their research shows how to display a small and large
+MessageBox
+ inside the client. A large MessageBox also shows the Caption parameter, whereas a small MessageBox does not.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x1A] SID_STARTADVEX2
+ **************************************
+
+ Used By: Starcraft, Starcraft Broodwar, Diablo I, Diablo Shareware
+
+ Format:
+ (DWORD) Status
+
+ Remarks:
+ This message is used by Diablo to create a game. It was also used by Starcraft 1.03.
+
+ Possible values for Status: 0x00000000: Failed 0x00000001: Ok 
+ Note that Status 0x00000000 and 0x00000001 are in reverse of SID_STARTADVEX3's Status 0x00000000 and 0x00000001.
+
+ More info: https://pastebin.com/WhKsmdnD [8]
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x1A] SID_STARTADVEX2
+ **************************************
+
+ Used By: Starcraft, Starcraft Broodwar, Diablo I, Diablo Shareware
+
+ Format:
+ (DWORD) Password Protected
+ (DWORD) Unknown
+ (DWORD) Unknown
+ (DWORD) Unknown
+ (DWORD) Unknown
+ (DWORD) Port
+ (STRING) Game name
+ (STRING) Game password
+ (STRING) Unknown
+ (STRING) Game stats - Flags, Creator, Statstring 
+
+ Remarks:
+ This message is used by Diablo to create a game. It was also used by Starcraft 1.03.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x1B] SID_GAMEDATAADDRESS
+ **************************************
+
+ Used By: Diablo I
+
+ Format:
+ (WORD) Unknown 1
+ (SOCKADDR) Address & Port
+ SOCKADDR structure is as follows: (WORD) Port (DWORD) Address (DWORD) Unknown 2
+ (DWORD) Unknown 3
+
+ Remarks:
+ Specifies host & port that a game creator is using for a game.
+
+ The three unknowns come from PvPGN documentation. The first unknown appears to always be 0x02, which is also seen in
+ game listings. More info: https://pastebin.com/iDtEmhpr [9]
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x1C] SID_STARTADVEX3
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Starcraft, Starcraft
+ Japanese, Diablo I, Diablo II LOD
+
+ Format:
+ (DWORD) Status 
+
+ Remarks:
+ Possible values for Status: 0x00: Ok 0x01: Failed
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x1C] SID_STARTADVEX3
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Game State
+ (DWORD) Game Uptime in seconds
+ (WORD) Game Type
+ (WORD) Sub Game Type
+ (DWORD) Provider Version Constant (0xFF)
+ (DWORD) Ladder Type
+ (STRING) Game Name
+ (STRING) Game Password
+ (STRING) Game Statstring
+
+ Remarks:
+ Used by clients to inform the server that a game has been created, or that the state of a created game has changed.
+ Bitwise flags for State: 0x01: Game is private 0x02: Game is full 0x04: Game contains players (other than creator)
+ 0x08: Game is in progress 0x80: Game is a replay Possible values for Game Type (Sub Game Type): 0x02: Melee 0x03: Free
+ for All 0x04: 1 vs 1 0x05: Capture The Flag 0x06: Greed (Resources, 0x01: 2500, 0x02: 500, 0x03: 7500, 0x04: 10000)
+ 0x07: Slaughter (Minutes, 0x01: 15, 0x02: 30, 0x03: 45, 0x04: 60) 0x08: Sudden Death 0x09: Ladder (Disconnects, 0x00:
+ Not a loss, 0x01: Counts as a loss) 0x0A: Use Map Settings 0x0B: Team Melee (Number Of Teams, 0x01: 2 Teams, 0x02: 3
+ Teams, etc.) 0x0C: Team Free For All (Number Of Teams, 0x01: 2 Teams, 0x02: 3 Teams, etc.) 0x0D: Team Capture The Flag
+ (Number Of Teams, 0x01: 2 Teams, 0x02: 3 Teams, etc.) 0x0F: Top vs. Bottom (Number Of Teams, 1-7 specifies the ratio of
+ players belonging to both teams) 0x10: Iron Man Ladder (W2BN only) 0x20: PGL 
+ Provider Version Constant: The Current version of the game (1.16.1) uses 0xFF, previous versions have used 0x1F, but
+ this may vary depending on game version.
+
+ Possible values for Ladder: 0x00: Game is Normal (Non-Ladder) 0x01: Game is Ladder 0x03: Game is Iron Man Ladder (W2BN
+ only) It could be that the ladder is bitwise as well, and that 0x02 means Iron Man and 0x03 just means Iron Man +
+ Ladder.
+ Sub Game Type appears to be 0x01 for all game types except Top vs Bottom, where it seems to depend on the size of each
+ team. More research will be needed to confirm.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x1D] SID_LOGONCHALLENGEEX
+ **************************************
+
+ Used By: Diablo Shareware, Warcraft II, Diablo I
+
+ Format:
+ (DWORD) UDP Token
+ (DWORD) Server Token 
+
+ Remarks:
+ Informs the client of the UDP Token and the Server Token.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x1E] SID_CLIENTID2
+ **************************************
+
+ Used By: Diablo Shareware, Warcraft II, Diablo I
+
+ Format:
+ (DWORD) Server VersionFor server version 1: (DWORD) Registration Version (DWORD) Registration Authority For server
+ version 0: (DWORD) Registration Authority (DWORD) Registration Version (DWORD) Account Number
+ (DWORD) Registration Token
+ (STRING) LAN computer name
+ (STRING) LAN username 
+
+ Remarks:
+ See related link for more information.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x1F] SID_LEAVEGAME
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ [blank] 
+
+ Remarks:
+ Notifies Battle.net that you have left a game. 
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x20] SID_ANNOUNCEMENT
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Starcraft Japanese, Diablo
+I
+
+ Format:
+ (STRING) Text
+
+ Remarks:
+ Very simply prints out text with the string at 1903B9FBh (the default string, used anyway if the username field is NULL
+ in the chat event struct -- currently a single 0x7F char) as the username.
+
+ Used to send announcements and arbitrary messages to the user, but this was soon superseded by SID_CHAT subcommands
+ such as EID_INFO, EID_ERROR, and EID_BROADCAST. Printed out with the same color and style as an EID_BROADCAST.
+
+ Found at:
+ battle!1901DDA0h (as of 1.16.1)
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x21] SID_DISPLAYAD
+ **************************************
+
+ Format:
+ (DWORD) Platform ID
+ (DWORD) Product ID
+ (DWORD) Ad ID
+ (STRING) Filename
+ (STRING) URL 
+
+ Remarks:
+ Sent when an ad is displayed. Perhaps for statistics?
+
+ Null strings are now sent in place of Filename and URL, since the need to truncate long strings to 128 characters was
+ causing inaccuracies.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x22] SID_NOTIFYJOIN
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Starcraft, Starcraft
+ Japanese, Diablo I, Diablo II LOD
+
+ Format:
+ (DWORD) Product ID *
+ (DWORD) Product version
+ (STRING) Game Name
+ (STRING) Game Password
+
+ Remarks:
+ Notifies Battle.net that the client has joined a game. This is what causes you to receive "Your friend _ entered a _
+ game called _." from Battle.net if you are mutual friends with this client.
+
+ SID_LEAVECHAT (0x10) does not need to be sent after this, since this does what LEAVECHAT does but with an added
+ notification.
+
+ * This can be any valid Product ID, even if you are not connected with that ID.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x23] SID_WRITECOOKIE
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Starcraft Japanese, Diablo
+I
+
+ Format:
+ (DWORD) unknown/unparsed -- Flags, Request ID?
+ (DWORD) unknown/unparsed -- Timestamp?
+ (STRING) Registry key name
+ (STRING) Registry key value
+
+ Remarks:
+ Much like a website cookie, simply stores some arbitrary string to a 'cookie jar' to save preferences et al. which can
+ be retrieved later by the server.
+
+ Not used because it was quickly discovered that storing preferences produces less problems and were faster by storing
+ them server-side, associating them with the account. It is somewhat curious that these packet IDs are close to
+ SID_READUSERDATA/SID_WRITEUSERDATA (0x26 & 0x27).
+
+ Found at: battle!190216FBh and battle!1901D660h, respectively.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x24] SID_READCOOKIE
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Diablo I
+
+ Format:
+ (DWORD) Echoed back, Request ID?
+ (DWORD) Echoed back, Timestamp?
+ (STRING) Registry key name
+
+ Remarks:
+ Much like a website cookie, simply stores some arbitrary string to a 'cookie jar' to save preferences et al. which can
+ be retrieved later by the server.
+
+ Not used because it was quickly discovered that storing preferences produces less problems and were faster by storing
+ them server-side, associating them with the account. It is somewhat curious that these packet IDs are close to
+ SID_PROFILE/SID_WRITEPROFILE (0x26 & 0x27).
+
+ Found at: battle!190216FBh and battle!1901D660h, respectively.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x24] SID_READCOOKIE
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Starcraft Japanese, Diablo
+I
+
+ Format:
+ (DWORD) First DWORD from S -> C
+ (DWORD) Second DWORD from S -> C
+ (STRING) Registry key name
+ (STRING) Registry key value
+
+ Remarks:
+ Much like a website cookie, simply stores some arbitrary string to a 'cookie jar' to save preferences et al. which can
+ be retrieved later by the server.
+
+ Not used because it was quickly discovered that storing preferences produces less problems and were faster by storing
+ them server-side, associating them with the account. It is somewhat curious that these packet IDs are close to
+ SID_PROFILE/SID_WRITEPROFILE (0x26 you must submit this packet once for each user you wish to know about. This only
+ applies to official Battle.net servers, it might not apply to PvPGN servers or equivalent software.
+
+ Also, requesting 0x20 (32) or more keys at one time makes Battle.net kick you (it does not ban you, however).
+
+ Profile Keys: * USER PROFILES: profilesex ** profileage † profilelocation profiledescription 
+ ACCOUNT INFO: *** SystemAccount Created SystemAuthLevel SystemFlags SystemFriends SystemIcon SystemIP SystemLast Logoff
+ SystemLast Logon SystemLeague SystemMFT Bytes SystemMFT Last Write SystemMFT Time Logged SystemPort SystemTime Logged
+ SystemUsername 
+ NORMAL GAMES: recordGAMEwins recordGAMElosses recordGAMEdisconnects recordGAMElast game recordGAMElast game result 
+ LADDER GAMES: recordGAME1wins recordGAME1losses recordGAME1disconnects recordGAME1rating recordGAME1high rating
+ DynKeyGAME1rank recordGAME1high rank recordGAME1last game recordGAME1last game result 
+ IRONMAN LADDER GAMES: ‡ recordGAME3wins recordGAME3losses recordGAME3disconnects recordGAME3last game recordGAME3last
+ game result recordGAME3rating recordGAME3high rating DynKeyGAME3rank * This list is not complete, and could use adding
+ to. ** This field is defunct in STAR/SEXP/WAR3/W3XP. † This field is defunct. *** Battle.net returns blank values for
+ anyone but yourself. ‡ W2BN only. Note that any profile key can contain an 0x09 (tab) character. 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x27] SID_WRITEUSERDATA
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Number of accounts
+ (DWORD) Number of keys
+ (STRING) [] Accounts to update
+ (STRING) [] Keys to update
+ (STRING) [] New values
+
+ Remarks:
+ Updates the Client's profile.
+ Currently, the allowed keys for this are Sex, Location, and Description. The maximum length for the values is 512,
+ including the null terminator.
+
+ See SID_READUSERDATA for more information.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x28] SID_LOGONCHALLENGE
+ **************************************
+
+ Used By: Starcraft Shareware, Diablo Shareware, Warcraft II, Starcraft Japanese, Diablo I
+
+ Format:
+ (DWORD) Server Token 
+
+ Remarks:
+ Contains the server token.
+
+ This is sent after a request to version check with the old version check system.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x29] SID_LOGONRESPONSE
+ **************************************
+
+ Used By: Starcraft Shareware, Diablo Shareware, Warcraft II, Starcraft Japanese, Diablo I
+
+ Format:
+ (DWORD) Result 
+
+ Remarks:
+ Reports success/fail on password authentication.
+ Result: 0x00: Invalid password 0x01: Success
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x29] SID_LOGONRESPONSE
+ **************************************
+
+ Used By: Starcraft Shareware, Diablo Shareware, Warcraft II, Starcraft Japanese, Diablo I
+
+ Format:
+ (DWORD) Client Token
+ (DWORD) Server Token
+ (DWORD) [5] Password Hash
+ (STRING) Username 
+
+ Remarks:
+ Contains Client's username developers should use the
+ SID_CHECKDATAFILE2 message.
+
+ The digest is created by using the broken SHA-1 hash on the first 64-bytes of the (filesize % 64) times. This due to a
+ bug in the client. 
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x33] SID_GETFILETIME
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III, World of Warcraft
+
+ Format:
+ (DWORD) Request ID
+ (DWORD) Unknown
+ (FILETIME) Last update time
+ (STRING) Filename 
+
+ Remarks:
+ Contains the latest filetime for the requested file. If the file does not exist, the returned filetime is null.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x33] SID_GETFILETIME
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
+ Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Request ID
+ (DWORD) Unknown
+ (STRING) Filename
+
+ Remarks:
+ This packet seems to request the current filetime for the specified file. Purpose of first 2 DWORDs is unknown,
+however,
+ both are echoed back to the client by Battle.net and do not seem to affect the reply. Because of this it is reasonable
+ to assume that first DWORD at least is a request ID of some kind. This is called into question, however, by the fact
+ that the replying packet also contains the requested filename. The game (STAR/SEXP) always sends the same number in
+ DWORD 1 for the file in question. DWORD 2 seems to be null.
+
+ Known codes for DWORD 1: 0x01: tos_usa.txt
+ 0x03: bnserver-WAR3.ini
+ 0x1A: tos_USA.txt
+ 0x1B: bnserver.ini
+ 0x1D: icons_STAR.bni
+ 0x80000005: IX86ExtraWork.mpq
+ 0x80000004: bnserver-D2DV.ini
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x34] SID_QUERYREALMS
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Unknown
+ (DWORD) Count
+ For Each Realm: (DWORD) Unknown (STRING) Realm title (STRING) Realm description
+
+ Remarks:
+ Realm list.
+
+ The first Unknown is usually 0. The second [and subsequent] Unknown is usually 1.
+
+ This packet is no longer used. SID_QUERYREALMS2 is used instead.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x34] SID_QUERYREALMS
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Unused (0)
+ (DWORD) Unused (0)
+ (STRING) Unknown (empty)
+
+ Remarks:
+ Requests a realm listing.
+
+ This packet is no longer used. SID_QUERYREALMS2 is used instead.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x35] SID_PROFILE
+ **************************************
+
+ Used By: Warcraft III: TFT, Warcraft III
+
+ Format:
+ (DWORD) Cookie
+ (BYTE) Success
+ (STRING) ProfileDescription value
+ (STRING) ProfileLocation value
+ (DWORD) Clan Tag
+
+ Remarks:
+ If the status code is 0, the request was successful; otherwise, the lookup failed and the message length will be five
+ bytes long (not counting the four byte header).
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x35] SID_PROFILE
+ **************************************
+
+ Used By: Warcraft III: TFT, Warcraft III
+
+ Format:
+ (DWORD) Cookie
+ (STRING) Username
+
+ Remarks:
+ This requests a profile for a user. This message's official name is not known, and has been invented.
+
+ It is safe to look up any username you want. The username can have illegal characters, can be of any length, and can
+ have all the other "illy" username characteristics. This message can also be used across all products without a
+problem,
+ not just WAR3/W3XP.
+
+ Battle.net will translate the realm in the username for you, so you can look up @Azeroth as well as @USEast, if you
+ want. You cannot perform cross-realm look ups, however; that is to say you cannot look up @USWest if you're on @USEast
+ and likewise for the other realms.
+
+ If you look up a user that is not on their Warcraft III user table, then the clan tag in the replying message will
+ always be null. But it is safe to do this as well. The profile description and location strings will match that of the
+ user you look up, regardless of which internal user table the user resides on.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x36] SID_CDKEY2
+ **************************************
+
+ Used By: Warcraft II
+
+ Format:
+ (DWORD) Result
+ (STRING) Key owner
+
+ Remarks:
+ This packet is identical to SID_CDKEY (0x30)
+
+ Possible values for Result: 0x01: OK 0x02: Invalid key 0x03: Bad product 0x04: Banned 0x05: In use 
+ In addition, the Key Owner field has two special values:
+
+ * 'TOO MANY SPAWNS': Exceeded spawn limit for this CD-Key
+ * 'NO SPAWNING': Spawns are not supported for this CD-Key
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x36] SID_CDKEY2
+ **************************************
+
+ Used By: Warcraft II
+
+ Format:
+ (DWORD) Spawn (0/1)
+ (DWORD) Key Length
+ (DWORD) CDKey Product
+ (DWORD) CDKey Value1
+ (DWORD) Server Token
+ (DWORD) Client Token
+ (DWORD) [5] Hashed Data
+ (STRING) Key owner
+
+ Remarks:
+ This packet is an updated version of SID_CDKEY (0x30), designed to prevent CDKeys from being stolen, by sending them
+ hashed instead of plain-text.
+
+ The data that should be hashed is:
+
+ * Client Token
+ * Server Token
+ * Key Product (from decoded CD key)
+ * Key Value1 (from decoded CD key)
+ * Key Value2 (from decoded CD key)
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x37] SID_UNKNOWN_37
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Unknown 1
+ (DWORD) Unknown 2
+ (DWORD) Count of characters
+
+ For each character:
+ (see related C>S packet for struct)
+
+ Remarks:
+ Not much is known about this packet. The structure of this packet and its documentation was taken from PvPGN. The
+ collected information can be found here [11], which includes possible values for the packet format.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x37] SID_UNKNOWN_37
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Count of open characters
+ (VOID) [] Character structure
+
+ For each character structure:
+ (STRING) Realm Name (if closed) and Character Name
+ (BYTE) Unknown B1
+ (BYTE) Unknown B2
+ (BYTE) Helm GFX
+ (BYTE) Body GFX
+ (BYTE) Leg GFX
+ (BYTE) Left Hand Weapon
+ (BYTE) Left Hand GFX
+ (BYTE) Right Hand Weapon
+ (BYTE) Right Hand GFX
+ (BYTE) Unknown B3
+ (BYTE) Unknown B4
+ (BYTE) Unknown B5
+ (BYTE) Unknown B6
+ (BYTE) Unknown B7
+ (BYTE) Unknown B8
+ (BYTE) Unknown B9
+ (BYTE) Unknown B10
+ (BYTE) Unknown B11
+ (BYTE) Class
+ (DWORD) Unknown DW1
+ (DWORD) Unknown DW2
+ (DWORD) Unknown DW3
+ (DWORD) Unknown DW4
+ (BYTE) Level
+ (BYTE) Status
+ (BYTE) Title
+ (BYTE) Unknown B13
+ (BYTE) Emblem BGC
+ (BYTE) Emblem FGC
+ (BYTE) Emblem Number
+ (BYTE) Unknown B14
+ (STRING) Guild Tag (max length: 3)
+
+ Remarks:
+ Not much is known about this packet. The structure of this packet and its documentation was taken from PvPGN. The
+ collected information can be found here [12], which includes possible values for the packet format.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x39] SID_UNKNOWN_39
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (STRING) Character Name
+
+ Remarks:
+ Not much is known about this packet. The structure of this packet and its documentation was taken from PvPGN. The
+ collected information can be found here [13].
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x3A] SID_LOGONRESPONSE2
+ **************************************
+
+ Used By: Starcraft Broodwar, Diablo II, Starcraft, Diablo II LOD
+
+ Format:
+ (DWORD) Status
+ (STRING) Additional information
+
+ Remarks:
+ Status: 0x00: Success. 0x01: Account does not exist. 0x02: Invalid password. 0x06: Account closed. 
+ The string containing the reason is only present when your account is closed. If not, the entire field is omitted
+ including the null-terminator.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x3A] SID_LOGONRESPONSE2
+ **************************************
+
+ Used By: Starcraft Broodwar, Diablo II, Starcraft, Diablo II LOD
+
+ Format:
+ (DWORD) Client Token
+ (DWORD) Server Token
+ (DWORD) [5] Password Hash
+ (STRING) Username
+
+ Remarks:
+ This packet is the same as SID_LOGONRESPONSE, but has additional response codes.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x3C] SID_CHECKDATAFILE2
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Warcraft II, Starcraft, Starcraft Japanese
+
+ Format:
+ (DWORD) Result
+
+ Remarks:
+ Result of file integrity query.
+ Result: 0x00: Not approved 0x01: Blizzard approved 0x02: Approved for ladder
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x3C] SID_CHECKDATAFILE2
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Warcraft II, Starcraft, Starcraft Japanese
+
+ Format:
+ (DWORD) File size in bytes
+ (DWORD) File hash [5]
+ (STRING) Filename
+
+ Remarks:
+ Verifies that a file is authentic, by producing a hash of that file and sending it to the server for comparison to the
+ original.
+
+ The hash is a standard SHA1 hash.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x3D] SID_CREATEACCOUNT2
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Starcraft, Starcraft
+ Japanese, Diablo I, Diablo II LOD
+
+ Format:
+ (DWORD) Status
+ (STRING) Account name suggestion
+
+ Remarks:
+ Account creation result.
+ Result: 0x00: Account created 0x01: Name is too short 0x02: Name contained invalid characters 0x03: Name contained a
+ banned word 0x04: Account already exists 0x05: Account is still being created 0x06: Name did not contain enough
+ alphanumeric characters 0x07: Name contained adjacent punctuation characters 0x08: Name contained too many punctuation
+ characters
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x3D] SID_CREATEACCOUNT2
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Starcraft, Starcraft
+ Japanese, Diablo I, Diablo II LOD
+
+ Format:
+ (DWORD) [5] Password hash
+ (STRING) Username
+
+ Remarks:
+ Creates a Battle.net account. Usernames longer than 15 characters are truncated.
+
+ Passwords should be converted to lower case before hashing, and are only hashed once (unlike SID_LOGONRESPONSE).
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x3E] SID_LOGONREALMEX
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) MCP Cookie
+ (DWORD) MCP Status
+ (DWORD) [2] MCP Chunk 1
+ (DWORD) IP
+ (DWORD) Port
+ (DWORD) [12] MCP Chunk 2
+ (STRING) Battle.net unique name
+
+ Remarks:
+ This packet supplies the data necessary to connect to an MCP server. The cookie value is defined in the first DWORD of
+ SID_LOGONREALMEX and is simply returned by Battle.net. If the length of the message (not including header) is greater
+ than 8, the client should continue to logon to the MCP. Otherwise, the Status field is interpreted as an error code:
+
+ 0x80000001: Realm is unavailable
+ 0x80000002: Realm logon failed
+
+ Any other value indicates failure.
+
+ The first part of the MCP Chunk that must be sent to the MCP server includes the Status and Cookie DWORDS, making MCP
+ Chunk 1 the first 4 DWORDS of the packet.
+
+ There used to be a WORD at the end of this packet, which was apparently random.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x3E] SID_LOGONREALMEX
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Client Token
+ (DWORD) [5] Hashed realm password
+ (STRING) Realm title
+
+ Remarks:
+ Realm password is always "password". The password hash is created the same way the hash is for logging on to an
+account.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x3F] SID_STARTVERSIONING2
+ **************************************
+
+ Format:
+ (FILETIME) MPQ Filetime
+ (STRING) MPQ Filename
+ (STRING) ValueString
+
+ Remarks:
+ Contains CheckRevision values.
+
+ Has anyone seen this packet in use? It's currently being marked as defunct, as I don't know of any clients that receive
+ it.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x40] SID_QUERYREALMS2
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Unknown
+ (DWORD) Count
+ For Each Realm: (DWORD) Unknown (STRING) Realm title (STRING) Realm description
+
+ Remarks:
+ Realm list.
+
+ The first Unknown is usually 0. The second [and subsequent] Unknown is usually 1.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x40] SID_QUERYREALMS2
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ [blank]
+
+ Remarks:
+ Requests a realm listing.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x41] SID_QUERYADURL
+ **************************************
+
+ Used By: Warcraft III: TFT, Warcraft III
+
+ Format:
+ (DWORD) Ad ID
+ (STRING) Ad URL 
+
+ Remarks:
+ Reports the Adbanner's URL. This message will only be received if the client sent it to the server. 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x41] SID_QUERYADURL
+ **************************************
+
+ Used By: Warcraft III: TFT, Warcraft III
+
+ Format:
+ (DWORD) Ad ID 
+
+ Remarks:
+ Requests the URL for an ad if none is given.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x42] SID_CDKEY3
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Status
+ (STRING) CD-Key Owner or Error Message
+
+ Remarks:
+ Not much is known about this packet. The structure of this packet and its documentation was taken from PvPGN. The
+ collected information can be found here [14].
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x42] SID_CDKEY3
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Unknown 1
+ (DWORD) Unknown 2
+ (DWORD) Unknown 3
+ (DWORD) Unknown 4
+ (DWORD) Unknown 5
+ (DWORD) Unknown 6
+ (DWORD) Unknown 7
+ (DWORD) [5] CD-Key Hash
+ (STRING) CD-Key Owner
+
+ Remarks:
+ Not much is known about this packet. The structure of this packet and its documentation was taken from PvPGN. The
+ collected information can be found here [15].
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x43] SID_WARCRAFTUNKNOWN
+ **************************************
+
+ Used By: Warcraft III: TFT, Warcraft III
+
+ Format:
+ (DWORD) Unknown (0)
+
+ Remarks:
+ Unknown. I am unable to disassemble Warcraft III's game.dll without a lot of trouble, and therefore I have limited
+ knowledge of it. It has been seen once, after SID_LOGONPROOF (0x54) in the NLS logon sequence.
+
+ Found at: game.dll
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x44] SID_WARCRAFTGENERAL
+ **************************************
+
+ Used By: Warcraft III: TFT, Warcraft III
+
+ Format:
+ (BYTE) Subcommand ID
+ 0x00 (WID_GAMESEARCH): (DWORD) Cookie (DWORD) Status
+ 0x00000000: Search Started 0x00000004: Banned CD-Key 
+ 0x02 (WID_MAPLIST): (DWORD) Cookie (BYTE) Number of responses For each reponse: (DWORD) ID (DWORD) Checksum (WORD)
+ Decompressed Length (WORD) Compressed Length (VOID) Compressed Data (BYTE) Remaining Packets 
+ 0x03 (WID_CANCELSEARCH): (DWORD) Cookie from WID_GAMESEARCH 
+ 0x04 (WID_USERRECORD): (DWORD) Cookie (DWORD) Icon ID (based on identifier; for example, "Orc Peon" is 'W3O1') (BYTE)
+ Number of ladder records to read; this will be between 0 and 3. For each ladder record: (DWORD) Ladder type; valid
+ types are 'SOLO', 'TEAM', or 'FFA ' (where the last character of 'FFA ' is a space, 0x20). (WORD) Number of wins (WORD)
+ Number of losses (BYTE) Level (BYTE) Unknown* (WORD) Experience (DWORD) Rank (will be 0 if unranked) (BYTE) Number of
+ race records to read; this will be 5 for WAR3 and 6 for W3XP. For each race record: (WORD) Wins (WORD) Losses (BYTE)
+ Number of team records to read. For each team record: (DWORD) Type of team; valid types are '2VS2', '3VS3', and '4VS4'.
+ (WORD) Number of wins (WORD) Number of losses (BYTE) Level (BYTE) Unknown* (WORD) Experience (DWORD) Rank (will be 0 if
+ unranked) (FILETIME) Time of last game played (BYTE) Number of partners (STRING)[] Names of partners 
+ 0x07 (WID_TOURNAMENT): (DWORD) Cookie (Byte) Status
+ 0x00: No Tournament 0x01: Starting Soon 0x02: Ending Soon 0x03: Started 0x04: Last Call (FILETIME) Last Status
+ Update Time (WORD) Unknown (WORD) Unknown (BYTE) Wins (BYTE) Losses (BYTE) Draws (BYTE) Unknown (BYTE) Unknown (BYTE)
+ Unknown (BYTE) Unknown 
+ 0x08 (WID_CLANRECORD): (DWORD) Cookie (BYTE) Number of ladder records to read; this will be between 0 and 4. For each
+ ladder record: (DWORD) Ladder type; valid types are 'CLNS' (solo), 'CLN2' (2v2), 'CLN3' (3v3), or 'CLN4' (4v4). (DWORD)
+ Number of wins (DWORD) Number of losses (BYTE) Level (BYTE) Unknown* (DWORD) Experience (DWORD) Rank (will be 0 if
+ unranked) (BYTE) Number of race records to read; this will be 5 for WAR3 and 6 for W3XP. For each race record: (DWORD)
+ Wins (DWORD) Losses 
+ 0x09 (WID_ICONLIST): (DWORD) Cookie (DWORD) Selected Icon (BYTE) Tiers (BYTE) Count For each Icon: (DWORD) Icon
+ (DWORD) Unit ID** (BYTE) Race (WORD) Wins required (BYTE) Enabled 
+
+ Remarks:
+ This message is still being researched!
+
+ This message is used for multiple purposes on Warcraft III. Known and validated purposes are listed here.
+
+ * The field was formerly labeled as "Hours until XP decay", but as no evidence to support this claim has ever been
+ verified (and through personal testing has been found to be altogether false), it has been renamed as unknown for the
+ time being. More information on this value would be appreciated.
+
+ ** This is the name of the unit for which this icon should be displayed for. The names can be found in the
+ war3.mpq/Units/UnitData.slk.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x44] SID_WARCRAFTGENERAL
+ **************************************
+
+ Used By: Warcraft III: TFT, Warcraft III
+
+ Format:
+ (BYTE) Subcommand ID
+ 0x00 (WID_GAMESEARCH): (DWORD) Cookie (DWORD) Unknown (BYTE) Unknown (BYTE) Game Type
+ 0x00: 1vs1 0x01: 2vs2 0x02: 3vs3 0x03: 4vs4 0x04: Free for All (WORD) Enabled Maps (every bit is one map, from
+ 0x0000 to 0x0FFF) (WORD) Unknown (BYTE) Unknown (DWORD) Tick Count (DWORD) Race
+ 0x00000001: Human 0x00000002: Orc 0x00000004: Night Elf 0x00000008: Undead 0x00000020: Random 
+ 0x02 (WID_MAPLIST): (DWORD) Cookie (BYTE) Number of types requested For each type requested: (DWORD) ID* (DWORD)
+ Checksum* 
+ 0x03 (WID_CANCELSEARCH): [blank] 
+ 0x04 (WID_USERRECORD): (DWORD) Cookie (STRING) Account name (DWORD) Product ID ('WAR3' or 'W3XP') 
+ 0x07 (WID_TOURNAMENT) (DWORD) Cookie 
+ 0x08 (WID_CLANRECORD): (DWORD) Cookie (DWORD) Clan Tag (DWORD) Product ID ('WAR3' or 'W3XP') 
+ 0x09 (WID_ICONLIST): (DWORD) Cookie 
+ 0x0A (WID_SETICON): (DWORD) Icon 
+
+ Remarks:
+ This packet is used for multiple purposes on Warcraft III. Known and validated purposes are listed here.
+
+ *Not fully known yet.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x45] SID_NETGAMEPORT
+ **************************************
+
+ Used By: Warcraft III: TFT, Warcraft III
+
+ Format:
+ (WORD) Port
+
+ Remarks:
+ Sets the port used by the client for hosting WAR3/W3XP games. This value is retreived from HKCUSoftwareBlizzard
+ EntertainmentWarcraft IIIGameplaynetgameport, and is sent after the user logs on.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x46] SID_NEWS_INFO
+ **************************************
+
+ Used By: Diablo II, Warcraft III: TFT, Diablo II LOD, Warcraft III
+
+ Format:
+ (BYTE) Number of entries
+ (DWORD) Last logon timestamp
+ (DWORD) Oldest news timestamp
+ (DWORD) Newest news timestamp
+
+ For each entry:(DWORD) Timestamp (STRING) News
+
+ Remarks:
+ This packet contains news from battle.net. Timestamps are in C/Unix format, biased for UTC.
+
+ Multiple separate news messages can be received. These should be treated the same as if one message was sent with
+ several news entries.
+
+ If the 'Timestamp' field for an entry is zero, then that entry is the message of the day (and not a news entry in the
+ normal respect).
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x46] SID_NEWS_INFO
+ **************************************
+
+ Used By: Diablo II, Warcraft III: TFT, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) News timestamp
+
+ Remarks:
+ Requests news and MOTD from battle.net.
+
+ The news timestamp specifies the starting date for the news. To retrieve all available news entries, set this to zero.
+ Timestamps are given in C/Unix format -- that is, the number of seconds since January 1, 1970 0:00:00.000 -- and should
+ be biased to UTC.
+
+ This message should be sent when you receive SID_ENTERCHAT. The official client stops processing messages after the
+ user joins a game or enters a channel, and discards messages with more than 127 entries.
+
+ News can be requested for older products, but Battle.net will only return the server's Message-of-the-Day. However,
+ this behavior has not been observed in official clients, and for an accurate protocol emulation, its use is not
+ recommended.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x4A] SID_OPTIONALWORK
+ **************************************
+
+ Used By: Starcraft Broodwar, Diablo II, Warcraft III: TFT, Starcraft, Diablo II LOD, Warcraft III
+
+ Format:
+ (STRING) MPQ Filename
+
+ Remarks:
+ Using SID_GETFILETIME with request ID 0x80000005, the client should download this file and call the ExtraWork function
+ inside of it. Generally, this message is used for the optional ExtraWork DLL.
+
+ The client will only execute this entirely if the registry key HKCUSoftwareBattle.netOptimizeSysDesc [REG_DWORD] is set
+ to 1.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x4B] SID_EXTRAWORK
+ **************************************
+
+ Used By: Starcraft Broodwar, Diablo II, Warcraft III: TFT, Starcraft, Diablo II LOD, Warcraft III
+
+ Format:
+ (WORD) Game type
+ (WORD) Length
+ (STRING) Work returned data 
+
+ Remarks:
+ Response for both SID_OPTIONALWORK and SID_REQUIREDWORK.
+
+ Game type:
+ 0x01: Diablo II 0x02: Warcraft III 0x03: Starcraft 0x04: World of Warcraft (Reason for this is not known, but most
+ recent libraries have included it) 
+ Length:The length is returned from the call to ExtraWork in the ExtraWork DLL. Traditionally, the library responsible
+ for all ExtraWork requests has been IX86ExtraWork.dll. Work returned data:This data is based on a 1024-byte buffer. The
+ call to ExtraWork takes in a structure and returns the length and buffer based on the game type.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x4C] SID_REQUIREDWORK
+ **************************************
+
+ Used By: Starcraft Broodwar, Diablo II, Warcraft III: TFT, Starcraft, Diablo II LOD, Warcraft III
+
+ Format:
+ (STRING) ExtraWork MPQ FileName
+
+ Remarks:
+ Using SID_GETFILETIME with request ID 0x80000006, the client should download the specified MPQ file, extract
+ ExtraWork.dll and call the ExtraWork function inside of it.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x4E] SID_TOURNAMENT
+ **************************************
+
+ Used By: Starcraft Broodwar, Starcraft
+
+ Format:
+ (BYTE) Unknown
+ (BYTE) Unknown, maybe number of non-null strings sent?
+ (STRING) Description
+ (STRING) Unknown
+ (STRING) Website
+ (DWORD) Unknown
+ (STRING) Name
+ (STRING) Unknown
+ (STRING) Unknown
+ (STRING) Unknown
+ (DWORD[5]) Unknown
+
+ Remarks:
+ RESEARCH REQUESTED. Sent after a successful logon to an account in a WCG tournament. 
+ The 0x0C packet sent with 0x01 flags would automatically have the user join channel WCG planetname #. 
+
+ PACKET LOG FF 4E 58 00 01 03 57 6F 72 6C 64 20 43 79 62 65 72 20 47 61 6D 65 73 20 28 53 61 74 75 72 6E 29 00 00 68 74
+ 74 70 3A 2F 2F 77 77 77 2E 77 63 67 2E 63 6F 6D 00 57 43 47 00 00 00 00 00 80 07 01 00 00 00 00 00 01 01 00 02 02 00 00
+ 00 00 01 05 00 00 00 00 32 00 00 00
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x50] SID_AUTH_INFO
+ **************************************
+
+ Used By: Starcraft Broodwar, Diablo II, Warcraft III: TFT, Starcraft, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Logon Type
+ (DWORD) Server Token
+ (DWORD) UDPValue *
+ (FILETIME) MPQ filetime
+ (STRING) IX86ver filename
+ (STRING) ValueString
+
+ WAR3/W3XP Only:
+ (VOID) 128-byte Server signature
+
+ Remarks:
+ Contains the Server Token, and the values used in CheckRevision.
+
+ Possible Logon Type values: 0x00: Broken SHA-1 (STAR/SEXP/D2DV/D2XP) 0x01: NLS version 1 (War3Beta) 0x02: NLS Version 2
+ (WAR3/W3XP) * UDPValue
+ No one really knows what this is, however, it is used in 2nd DWORD of the UDP packet PKT_CONNTEST2. It is also the
+ second part of MCP Chunk 1 in MCP_STARTUP.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x50] SID_AUTH_INFO
+ **************************************
+
+ Used By: Starcraft Broodwar, Diablo II, Warcraft III: TFT, Starcraft, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Protocol ID (0)
+ (DWORD) Platform ID 
+ (DWORD) Product ID 
+ (DWORD) Version Byte
+ (DWORD) Product language*
+ (DWORD) Local IP for NAT compatibility*
+ (DWORD) Time zone bias*
+ (DWORD) Locale ID*
+ (DWORD) Language ID*
+ (STRING) Country abreviation 
+ (STRING) Country
+
+ Remarks:
+ Sends information about the Client to Battle.net.
+
+ *These fields can be set to zero without breaking logon.
+
+ Protocol ID:Battle.net's current Protocol ID is 0. Platform ID:A DWORD specifying the client's platform (IX86, PMAC,
+ XMAC, etc). Product ID:A DWORD specifying the client's game. Version:The client's version byte. Product Language:This
+ field is under investigation. It can safely be set to 0. MPQ Locale ID:This field is part of Blizzards multi-lingual
+MPQ
+ system. Is used to specify which version of an MPQ should be used when the MPQ is available in multiple languages.
+Local
+ IP:This is the local network IP of the client, in network byte order. Timezone bias:The difference, in minutes, between
+ UTC and local time. The client calculates this value by subtracting the Local Time from the System Time, having
+ converted both to Filetime structures, and then converting the resultant offset to minutes by diving it by 600,000,000.
+ If you wish to understand the mechanism involved, read Microsoft's documentation on File times. Language ID, Country
+ Abbreviation, and Country:These values can be retrieved by querying the system's locale information. Language ID can be
+ retrieved using the GetUserDefaultLangID [16] API.
+ Country Abbreviation & Country can be retrieved using the GetLocaleInfo [17] API to request the LOCALE_SABBREVCTRYNAME
+ and LOCALE_SENGCOUNTRY, respectively.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x51] SID_AUTH_CHECK
+ **************************************
+
+ Used By: Starcraft Broodwar, Diablo II, Warcraft III: TFT, Starcraft, Diablo II LOD, Warcraft III
+
+ Format:
+ (DWORD) Result
+ (STRING) Additional Information
+
+ Remarks:
+ Reports success/failure on version 
+
+ Byte N here refers to character in slot N, or 0 if the slot is empty.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x06] MCP_GAMEINFO
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) Request ID
+ (STRING) Game name
+
+ Remarks:
+ Requests information about a game.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x07] MCP_CHARLOGON
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Result
+
+ Remarks:
+ Logon response.
+ Known values: 0x00: Success 0x46: Player not found 0x7A: Logon failed 0x7B: Character expired 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x07] MCP_CHARLOGON
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (STRING) Character name
+
+ Remarks:
+ Logs onto the realm.
+
+ Note that attempting to log on using an expansion character on D2DV will result in an IPBan by both Battle.net and the
+ Realm.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x0A] MCP_CHARDELETE
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Result
+
+ Remarks:
+ Deletion response.
+ Known values: (Diablo II v1.10 or later) 0x00: Success 0x49: Character doesn't exist (Diablo II v1.09 or earlier)
+ 0x00: Character doesn't exist 0x49: Success 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x0A] MCP_CHARDELETE
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) Unknown (0)
+ (STRING) Character name
+
+ Remarks:
+ Deletes a character.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x11] MCP_REQUESTLADDERDATA
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (BYTE) Ladder type
+ The 10-byte header: (WORD) Total response size (WORD) Current message size (WORD) Total size of unreceived messages
+ (WORD) Rank of first entry (WORD) Unknown (0) Message data: (DWORD)Number of entries (DWORD)Unknown (0x10) For each
+ entry: (QWORD) Character experience (BYTE) Character Flags (BYTE) Character title (WORD) Character level (BYTE) [16]
+ Character name
+
+ Remarks:
+ Total Response Size: The size of the entire batch of SID_REQUESTLADDERDATA messages, excluding their headers and first
+ bytes. Current Message Size: The size of the current message, excluding its header and first byte. Total size of
+ unreceived messages: The total size of all the unreceived messages in the batch, excluding their headers and first
+ bytes. In the last packet, this value is 0, since there are no unreceived messages. Rank of first entry: Always zero,
+ except in the last message. In the last message, this specifies the zero-based rank of the first entry. (For example if
+ this is 17 in the last packet, then ladder entries 18-33 were retrieved.) Character Flags (AND 0x07 to get character):
+ 0x00: Amazon 0x01: Sorceress 0x02: Necromancer 0x03: Paladin 0x04: Barbarian 0x05: Druid 0x06: Assassin 0x08:
+ highlight this (if response to C > S [0x16] MCP_CHARRANK 0x10: dead character (hardcore only) 0x20: hardcore character
+ 0x40: expansion character Character Name: The character name is always 16 bytes. If the name is shorter than 16 bytes,
+ the string is padded with nulls. The last byte is always null, since character names are limited to 15 chars. General
+ Remarks: The server may respond to this packet with one or more of these messages. The client must not handle the data
+ until the last packet in the batch is received. The messages' data should be concatenated backwards. For example, if 3
+ packets were received, then the data buffer should contain the data of the 3rd packet, followed by the data of the 2nd
+ packet, followed by the data of the 1st packet. Only after the last packet was received, the data buffer should be
+ parsed. IMPORTANT NOTE: If the entry is the last entry in the packet, the character name might be smaller than 16
+ bytes.In this case, the client MUST add null bytes to the end of the packet, BEFORE adding it to the data buffer.
+Ladder
+ packets are NOT SENT IN ANY ORDER - They are often sent completely out of order and must be placed back into the proper
+ order. You have to infer the sequencing based on the 'how big' fields in the 10 byte header.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x11] MCP_REQUESTLADDERDATA
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (BYTE) Ladder type
+ (WORD) Starting position
+
+ Remarks:
+ This will request 16 ladder entries, starting at a zero-based location specified in 'Starting position'. For example if
+ this is 0, then ladder entries 1-16 are retrieved. If this is 17, then ladder entries 18-33 are retrieved. Note: The
+ values that Diablo 2 sends for this are always perfectly divisible by 16. This might be a requirement.
+ Possible ladder types: 0x00: standard hardcore overall ladder 0x01: standard hardcore amazon ladder 0x02: standard
+ hardcore sorceress ladder 0x03: standard hardcore necromancer ladder 0x04: standard hardcore paladin ladder 0x05:
+ standard hardcore barbarian ladder 0x09: standard softcore overall ladder 0x0A: standard softcore amazon ladder 0x0B:
+ standard softcore sorceress ladder 0x0C: standard softcore necromancer ladder 0x0D: standard softcore paladin ladder
+ 0x0E: standard softcore barbarian ladder 0x13: expansion hardcore overall ladder 0x14: expansion hardcore amazon ladder
+ 0x15: expansion hardcore sorceress ladder 0x16: expansion hardcore necromancer ladder 0x17: expansion hardcore paladin
+ ladder 0x18: expansion hardcore barbarian ladder 0x19: expansion hardcore druid ladder 0x1A: expansion hardcore
+assassin
+ ladder 0x1B: expansion softcore overall ladder 0x1C: expansion softcore amazon ladder 0x1D: expansion softcore
+sorceress
+ ladder 0x1E: expansion softcore necromancer ladder 0x1F: expansion softcore paladin ladder 0x20: expansion softcore
+ barbarian ladder 0x21: expansion softcore druid ladder 0x22: expansion softcore assassin ladder 
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x12] MCP_MOTD
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (BYTE) Unknown
+ (STRING) MOTD
+
+ Remarks:
+ Contains the realm's MOTD. The Byte at the beginning is apparently ignored.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x12] MCP_MOTD
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ [blank]
+
+ Remarks:
+ Requests the realm's MOTD.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x13] MCP_CANCELGAMECREATE
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ [blank]
+
+ Remarks:
+ Notifies the server that you want to cancel the creation of your game.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x14] MCP_CREATEQUEUE
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Position
+
+ Remarks:
+ Position in line to create a game.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x16] MCP_CHARRANK
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Hardcore BOOL
+ (DWORD) Expansion BOOL
+ (STRING) Character Name
+
+ Remarks:
+ This packet is used to find a Diablo II character in the ladder. Hardcore and Expansion can either be 1 or 0 and define
+ the ladder type (always Overall). The server responds with MCP_REQUESTLADDERDATA, listing (and possibly highlighting
+ using character flag 0x08?) the page of ranks in which the character is found.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x17] MCP_CHARLIST
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) Number of characters requested
+ (DWORD) Number of characters that exist on this account
+ (WORD) Number of characters returned
+ For each character: (STRING) Character name (STRING) Character statstring 
+
+ Remarks:
+ Lists characters.
+
+ The statstrings in this packet do not contain the product or character name. Everything else is the same as a character
+ statstring you would receive from a character entering the channel.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x17] MCP_CHARLIST
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Number of characters to list
+
+ Remarks:
+ Requests a character list.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x18] MCP_CHARUPGRADE
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Result
+
+ Remarks:
+ Converts a non-expansion character to expansion.
+ Known return values: 0x00: Success 0x46: Character not found 0x7A: Upgrade failed 0x7B: Character is expired 0x7C:
+ Already expansion character 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x18] MCP_CHARUPGRADE
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (STRING) Character Name
+
+ Remarks:
+ Converts a non-expansion character to expansion.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x19] MCP_CHARLIST2
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) Number of characters requested
+ (DWORD) Number of characters that exist on this account
+ (WORD) Number of characters returned
+
+ For each character: (DWORD) Expiration Date (STRING) Character name (STRING) Character statstring 
+
+ Remarks:
+ Lists characters.
+
+ The expiration date is a second count. To determine when the character will expire, add this time to January 1 00:00:00
+ UTC 1970 and determine the difference between that value and now (all in seconds).
+
+ The statstrings in this packet do not contain the product or character name. Everything else is the same as a character
+ statstring you would receive from a character entering the channel.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x19] MCP_CHARLIST2
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Number of characters to list.
+
+ Remarks:
+ Requests a character list. 
+
+ Up to a maximum of 8 characters can be requested.
+
+ ~~~~~~~~~~~~~~~~
+
+ D2GS Messages
+ ------------------------------
+
+ C > S [0x01] D2GS_WALKTOLOCATION
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) X coordinate
+ (WORD) Y coordinate
+
+ Remarks:
+ Walk to a specified (X,Y) map coordinate.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x02] D2GS_WALKTOENTITY
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) *Entity Type
+ (DWORD) Entity ID
+
+ *Entity Types
+ -------------
+ 00 - Players
+ 01 - Monsters, NPCs, and Mercenaries
+ 02 - Stash, Waypoint, Chests, Portals, others.
+ 03 - Missiles
+ 04 - Items
+ 05 - Entrances
+
+ Remarks:
+ Makes your character walk to the Entity specified in Entity ID.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x03] D2GS_RUNTOLOCATION
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) X coordinate
+ (WORD) Y coordinate 
+
+ Remarks:
+ Run to a specified (X,Y) map coordinate. 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x04] D2GS_RUNTOENTITY
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) *Entity Type
+ (DWORD) Entity ID
+
+ *Entity Types
+ -------------
+ 00 - Players
+ 01 - Monsters, NPCs, and Mercenaries
+ 02 - Stash, Waypoint, Chests, Portals, others.
+ 03 - Missiles
+ 04 - Items
+ 05 - Entrances
+
+ Remarks:
+ Makes your character run to the Entity specified in Entity ID.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x05] D2GS_LEFTSKILLONLOCATION
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) X coordinate
+ (WORD) Y coordinate
+
+ Remarks:
+ Uses Left skill on specified (X,Y) map coordinate.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x06] D2GS_LEFTSKILLONENTITY
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) *Entity Type
+ (DWORD) Entity ID
+
+ *Entity Types
+ -------------
+ 00 - Players
+ 01 - Monsters, NPCs, and Mercenaries
+ 02 - Stash, Waypoint, Chests, Portals, others.
+ 03 - Missiles
+ 04 - Items
+ 05 - Entrances
+
+ Remarks:
+ Uses your left skill on the Entity specefied in Entity ID.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x07] D2GS_LEFTSKILLONENTITYEX
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Entity Type
+ (DWORD) Entity ID
+
+ Remarks:
+ Uses your left skill on the Entity specefied in Entity ID, while holding the hotkey for standing still(shift).
+
+ Entity types
+ ---------------
+ 00 - Players
+ 01 - Monsters, NPCs, and Mercenaries
+ 02 - Stash, Waypoint, Chests, Portals, others.
+ 03 - Missiles
+ 04 - Items
+ 05 - Entrances
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x08] D2GS_LEFTSKILLONLOCATIONEX
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) X coordinate
+ (WORD) Y coordinate 
+
+ Remarks:
+ Uses Left skill on specified (X,Y) map coordinate.
+
+ This packet is sent repeatedly when the mouse button is held down after the initial packet has been sent. 
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x09] D2GS_LEFTSKILLONENTITYEX2
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) *Entity Type
+ (DWORD) Entity ID
+
+ *Entity Types
+ -------------
+ 00 - Players
+ 01 - Monsters, NPCs, and Mercenaries
+ 02 - Stash, Waypoint, Chests, Portals, others.
+ 03 - Missiles
+ 04 - Items
+ 05 - Entrances
+
+ Remarks:
+ Uses your left skill on the Entity specified in Entity ID.
+
+ This packet is sent repeatedly when the mouse button is held down after the initial packet has been sent.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x0A] D2GS_LEFTSKILLONENTITYEX3
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) *Entity Type
+ (DWORD) Entity ID
+
+ *Entity Types
+ -------------
+ 00 - Players
+ 01 - Monsters, NPCs, and Mercenaries
+ 02 - Stash, Waypoint, Chests, Portals, others.
+ 03 - Missiles
+ 04 - Items
+ 05 - Entrances
+
+ Remarks:
+ Uses your left skill on the Entity specefied in Entity ID, while holding the hotkey for standing still(shift).
+
+ This packet is sent repeatedly when the mouse button is held down after the initial packet has been sent. 
+
+ Refer to the D2GS Entity Types document for more information.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x0C] D2GS_RIGHTSKILLONLOCATION
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) X coordinate
+ (WORD) Y coordinate 
+
+ Remarks:
+ Uses the currently selected skill at the specified location. 
+
+ This packet is sent when the location is first clicked with the mouse. 
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x0D] D2GS_RIGHTSKILLONENTITY
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Entity Type
+ (DWORD) Entity ID 
+
+ Entity types
+ --------
+ 00 - Players
+ 01 - Monsters, NPCs, and Mercenaries
+ 02 - Stash, Waypoint, Chests, Portals, others.
+ 03 - Missiles
+ 04 - Items
+ 05 - Entrances
+
+ Remarks:
+ Uses your right skill on the Entity specefied in Entity ID
+
+ Refer to the D2GS Entity Types document for more information about Entities
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x0E] D2GS_RIGHTSKILLONENTITYEX
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Entity Type
+ (DWORD) Entity ID
+
+ Entity types
+ --------
+ 00 - Players
+ 01 - Monsters, NPCs, and Mercenaries
+ 02 - Stash, Waypoint, Chests, Portals, others.
+ 03 - Missiles
+ 04 - Items
+ 05 - Entrances
+
+ Remarks:
+ Uses your right skill on the Entity specefied in Entity ID, while holding the hotkey for standing still(shift).
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x0F] D2GS_RIGHTSKILLONLOCATIONEX
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) X coordinate
+ (WORD) Y coordinate 
+
+ Remarks:
+ Uses the currently selected skill at the specified location. 
+
+ This packet is sent repeatedly when the mouse button is held down after the initial packet has been sent. 
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x10] D2GS_CHARTOOBJ
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (BYTE) Unknown
+ (DWORD) Player ID
+ (BYTE) Movement Type
+ (BYTE) Destination Type
+ *(DWORD) Object ID 
+ *(WORD) X Coordinate
+ *(WORD) Y Coordinate 
+
+ Remarks:
+ A character moves to an object within your view range.
+
+ * - These are what the player is moving to.
+
+ Possible values for Destination Type:
+ 0x00 - Another player
+ 0x01 - NPC or Monster
+ 0x02 - Object such as Stash, Waypoint, or a Town Portal
+ 0x04 - Item
+ 0x05 - Doorway
+
+ Possible value for Movement Type:
+
+ 0x18 - Run
+ 0x00 - Walk Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x10] D2GS_RIGHTSKILLONENTITYEX2
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Entity Type
+ (DWORD) Entity ID 
+
+ Entity types
+ --------
+ 00 - Players
+ 01 - Monsters, NPCs, and Mercenaries
+ 02 - Stash, Waypoint, Chests, Portals, others.
+ 03 - Missiles
+ 04 - Items
+ 05 - Entrances
+
+ Remarks:
+ Uses your right skill repeatedly on the Entity specefied in Entity ID.
+ This packet is sent repeatedly when the mouse button is held down after the initial packet has been sent.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x11] D2GS_RIGHTSKILLONENTITYEX3
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Entity Type
+ (DWORD) Entity ID
+
+ Entity Types
+ --------
+ 00 - Players
+ 01 - Monsters, NPCs, and Mercenaries
+ 02 - Stash, Waypoint, Chests, Portals, others.
+ 03 - Missiles
+ 04 - Items
+ 05 - Entrances
+
+ Remarks:
+ Uses your right skill on the Entity specefied in Entity ID, while holding the hotkey for standing still(shift).
+
+ This packet is sent repeatedly when the mouse button is held down after the initial packet has been sent. 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x13] D2GS_INTERACTWITHENTITY
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Entity Type
+ (DWORD) Entity ID 
+
+ Entity types
+ --------
+ 00 - Players
+ 01 - Monsters, NPCs, and Mercenaries
+ 02 - Stash, Waypoint, Chests, Portals, others.
+ 03 - Missiles
+ 04 - Items
+ 05 - Entrances
+
+ Remarks:
+ Interacts with the specified Entity. 
+ For players and npc's, it will send a request to interact. 
+ The interaction depends on the type of the unit or object. 
+ For others it will trigger the object, for example using a shrine, looting a corpse you have permission to loot, or
+ opening and closing a door.
+
+ This packet is always followed by other's that relate to the type of interaction.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x14] D2GS_OVERHEADMESSAGE
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) Unknown - 0x00, 0x00
+ (STRING) Message
+ (BYTE) Unused - 0x00
+ (WORD) Unknown - 0x00, 0x00
+
+ Remarks:
+ This message is used when you'd like to put a message above a character's head as used in the client as "![message]".
+
+ Restrictions: Total size of packet cannot be greater than 275 bytes. Message cannot be greater than 255 bytes. 
+
+ Please note: This message's official name is not known, and has been invented. 
+
+ Extra Info: The status of this information is: Public Colors can be created by adding hex FF 63 and a character 30 to
+ 3C. 
+
+ Example:
+ To make red, use FF 63 31.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x16] D2GS_PICKUPITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Unit Type
+ (DWORD) Unit ID
+ (DWORD) Action ID
+
+ Remarks:
+ Pick up a ground item to cursor buffer/inventory.
+
+ Possible action IDs:
+ 0x00 - Move item to inventory
+ 0x01 - Move item to cursor buffer 
+
+ Please note: This message's official name is not known, and has been invented. 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x17] D2GS_DROPITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID 
+
+ Remarks:
+ Drops the item in the player's cursor buffer to the ground. 
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x18] D2GS_ITEMTOBUFFER
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID
+ (DWORD) X coordinate
+ (DWORD) Y coordinate
+ (DWORD) Buffer Type
+
+ Possible Buffer Types:
+ 0x00 - Character's inventory (backpack)
+ 0x01 - NPC and other Trade Windows
+ 0x02 - Trade window
+ 0x03 - Horadric Cube
+ 0x04 - Stash 
+
+ Remarks:
+ Moves item from the player's cursor buffer to an inventory space.
+
+ Please note: This message's official name is not known, and has been invented. 
+
+ Inventory coordinates:
+ (0,0) - Top left
+ (9,3) - Bottom right
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x19] D2GS_SMALLGOLDPICKUP
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (BYTE) Amount 
+
+ Remarks:
+ Sent when you pick up a BYTE (255) of gold(254 or less).
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x19] D2GS_PICKUPBUFFERITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID 
+
+ Remarks:
+ Pickup an item from the possible buffers below, moving it to the cursor buffer.
+
+ Possible Buffers:
+ 0 - Inventory
+ 1 - NPC Trade & Other player's Trade Window?
+ 2 - Trade Screen
+ 3 - Horadric Cube
+ 4 - Stash
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x1A] D2GS_ITEMTOBODY
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID
+ (DWORD) Body Location 
+
+ Remarks:
+ Moves item from player's cursor buffer to body location. Body locations are identified by the line number in the data
+ file bodylocs.txt.
+
+ Possible Body Locations:
+ 0x01 - Helm
+ 0x02 - Amulet
+ 0x03 - Armor
+ 0x04 - Left-hand weapon
+ 0x05 - Right-hand weapon
+ 0x06 - Left-hand ring
+ 0x07 - Right-hand ring
+ 0x08 - Belt
+ 0x09 - Boots
+ 0x0A - Gloves
+
+ These values have been recorded for mercenary body locations, but aren't confirmed: (Note, each location ID is prefixed
+ with 0x61)
+ Example: 1A 64 00 00 00 61 02 00 00 (Move item 0x64 to Mercenary Right-hand weapon)
+
+ 0x01 - Mercenary Helm
+ 0x02 - Mercenary Right-hand Weapon
+ 0x03 - Mercenary Armor
+ 0x04 - Mercenary Left-hand Weapon 
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x1B] D2GS_SWAP2HANDEDITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID
+ *(DWORD) Body Location
+
+ *0x04 is left hand
+ *0x05 is right hand
+
+ Remarks:
+ Moves item from body location to player's cursor buffer.
+
+ Body locations are the same as in D2GS_ITEMTOBODY
+
+ Please note: This message's official name is not known, and has been invented. 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x1C] D2GS_PICKUPBODYITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) Body Location
+
+ Remarks:
+ Pickup an item from a Body Location to you're cursor buffer.
+
+ Possible Body Locations:
+ 0x01 - Helm
+ 0x02 - Amulet
+ 0x03 - Armor
+ 0x04 - Left-hand weapon
+ 0x05 - Right-hand weapon
+ 0x06 - Left-hand ring
+ 0x07 - Right-hand ring
+ 0x08 - Belt
+ 0x09 - Boots
+ 0x0A - Gloves
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x1D] D2GS_SETBYTEATTR
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (BYTE) Attribute
+ (BYTE) Amount 
+
+ Remarks:
+ Sets the current (base) amount of the specified attribute.
+
+ Note: Since these are only base amounts, items that give increase/decrease the attribute should be added/subtracted
+ to/from the base value sent in the message.
+
+ Possible Attributes:
+
+ 0x00 - Strength 
+ 0x01 - Energy 
+ 0x02 - Dexterity 
+ 0x03 - Vitality 
+ 0x04 - Stat remaining 
+ 0x05 - Skill remaining 
+ 0x0C - Level 
+ 0x0D - Experience 
+ 0x0E - Gold on Person 
+ 0x0F - Gold in Stash 
+ 0x10 - Defense 
+ 0x11 - Max Attack Damage 
+ 0x12 - Min Attack Damage 
+ 0x13 - Attack Rating 
+ 0x15 - Min Attack Damage 
+ 0x16 - Max Attack Damage 
+ 0x19 - Damage 
+ 0x1f - Defense 
+ 0x27 - Fire Resistance 
+ 0x28 - +Max Fire Resistance 
+ 0x29 - Cold Resistance 
+ 0x2A - +Max Cold Resistance 
+ 0x2B - Lightning Resistance 
+ 0x2C - +Max Lightning Resistance 
+ 0x2D - Poison Resistance 
+ 0x2E - +Max poison Resistance 
+ 0x31 - Add Fire Damage 
+ 0x33 - Add Lightning damage 
+ 0x35 - Add Damage for Weapon/Items probably (one of these may be cold damage) 
+ 0x37 - Add Damage for Weapon/Items probably (one of these may be cold damage) 
+ 0x3A - Add Poison Damage 
+ 0x4C - Add Max Health for Weapon/Items probably 
+ 0x4D - Add Max Mana for Weapons/Items probably 
+ 0xA2 - Add Max Stamina for Weapons/Items probably 
+ 0xA3 - Add Max Stamina for Weapons/Items probably 
+ 0xAB - Add to Defense
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x1D] D2GS_SWITCHBODYITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID
+ (DWORD) Body Location 
+
+ Remarks:
+ Swaps item in player's cursor buffer with item in the body location.
+
+ Possible Body Locations:
+ 0x01 - Helm
+ 0x02 - Amulet
+ 0x03 - Armor
+ 0x04 - Left-hand weapon
+ 0x05 - Right-hand weapon
+ 0x06 - Left-hand ring
+ 0x07 - Right-hand ring
+ 0x08 - Belt
+ 0x09 - Boots
+ 0x0A - Gloves
+
+ Please note: This message's official name is not known, and has been invented. 
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x1E] D2GS_SETWORDATTR
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (BYTE) Attribute
+ (WORD) Amount 
+
+ Remarks:
+ Sets the current (base) amount of the specified attribute.
+
+ Note: Since these are only base amounts, items that give increase/decrease the attribute should be added/subtracted
+ to/from the base value sent in the message.
+
+ For attributes, see D2GS_SETBYTEATTR.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x1F] D2GS_SETDWORDATTR
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (BYTE) Attribute - D2GS_SETWORDATTR
+ (DWORD) Amount 
+
+ Remarks:
+ Updates an attribute and sets it to the value sent, 4 bytes max.
+
+ Please note: This message's official name is not known, and has been invented. 
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x1F] D2GS_SWITCHINVENTORYITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID - Item to place in inventory (cursor buffer)
+ (DWORD) Item ID - Item to be replaced
+ (DWORD) X coordinate for replace
+ (DWORD) Y coordinate for replace 
+
+ Remarks:
+ Swaps the item in the player's cursor buffer with one in the player's inventory. Please note: 
+ This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x20] D2GS_USEITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID
+ (DWORD) X coordinate
+ (DWORD) Y coordinate 
+
+ Remarks:
+ Uses the specified item (such as a potion, town portal scroll, etc.).
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x21] D2GS_STACKITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID - Stack item
+ (DWORD) Item ID - Target item 
+
+ Remarks:
+ Stacks one item such as a key onto another item.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x22] D2GS_REMOVESTACKITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID 
+
+ Remarks:
+ Removes an item from the stack Please note: This message's official name is not known, and has been invented. The
+ contents of this packet may be incomplete or incorrect, and your comments and contributions are requested.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x23] D2GS_ITEMTOBELT
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID
+ (DWORD) Belt Location 
+
+ Remarks:
+ Moves an item into the player's belt.
+
+ Extra Info: The status of this information is: Public Belt locations start at 0x00 and go from right to left, starting
+ at the lowest row and moving across, then going up one row. For example, location 0x03 would be at the bottom right
+hand
+ corner and location 0x0C would be at the top left corner in a 4-slot belt. This can be calculated as (row*4+column).
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x24] D2GS_REMOVEBELTITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID 
+
+ Remarks:
+ Moves the specified item from the belt to the player's cursor buffer. 
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x25] D2GS_SWITCHBELTITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID - Cursor buffer
+ (DWORD) Item ID - Item to be replaced 
+
+ Remarks:
+ Replaces item in belt with item in player's cursor buffer.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x26] D2GS_USEBELTITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID
+ (DWORD) Unknown - Possibly unused
+ (DWORD) Unknown - Possibly unused 
+
+ Remarks:
+ Uses the specified item in the player's belt.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x28] D2GS_INSERTSOCKETITEM
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID - Item to place in socket
+ (DWORD) Item ID - Socketed item 
+
+ Remarks:
+ Inserts the specified item into a socketed item.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x29] D2GS_SCROLLTOTOME
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID - Scroll
+ (DWORD) Item ID - Tome 
+
+ Remarks:
+ Places a scroll into a tome of scrolls.
+
+ Note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x2A] D2GS_ITEMTOCUBE
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Item ID
+ (DWORD) Cube ID 
+
+ Remarks:
+ Moves item from player's cursor buffer into Horadric cube.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x2D] D2GS_UNSELECTOBJ
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ blank 
+
+ Remarks:
+ Unselects the selected object. Please note: This message's official name is not known, and has been invented. The
+ contents of this packet may be incomplete or incorrect, and your comments and contributions are requested.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x2F] D2GS_NPCINIT
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Entity Type
+ (DWORD) Entity ID 
+
+ Entity types
+ --------
+ 00 - Players
+ 01 - Monsters, NPCs, and Mercenaries
+ 02 - Stash, Waypoint, Chests, Portals, others.
+ 03 - Missiles
+ 04 - Items
+ 05 - Entrances
+
+ Remarks:
+ Initiate an NPC sesstion, sent following:
+ C->S 0x13
+ It indicates that you are now interacting with an NPC, and a dialog window is opened.
+
+ This is prior to any choices being made to talk or trade etc.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x30] D2GS_NPCCANCEL
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Entity Type
+ (DWORD) NPC ID 
+
+ Remarks:
+ Stops interacting with an NPC 
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x32] D2GS_NPCBUY
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) NPC ID - Unconfirmed
+ (DWORD) Item ID - Unconfirmed
+ (DWORD) Buffer Type - Unconfirmed
+ (DWORD) Cost 
+
+ Remarks:
+ Buys an item from a Non Player Character.
+
+ Possible Buffer Types:
+ 0x00 - Regular (ordinary item)
+ 0x02 - Gambled 
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x33] D2GS_NPCSELL
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) NPC ID - Unconfirmed
+ (DWORD) Item ID - Unconfirmed
+ (DWORD) Buffer ID - Unconfirmed - Possible value 0x04
+ (DWORD) Cost 
+
+ Remarks:
+ Sell an item to a Non Player Character. 
+
+ The Buffer ID refers to the windows in the NPC trade screen, depending on what you are selling the Buffer ID will match
+ the item type.
+ After selling the item it will appear in the given Buffer ID.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x38] D2GS_NPCTRADE
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Trade Type - Unconfirmed
+ (DWORD) NPC ID - Unconfirmed
+ (DWORD) Unknown - Unconfirmed - Possible value 0x00 
+
+ Remarks:
+ This packet's use is currently unconfirmed.
+
+ Possible Trade Types:
+ 0x01 - Trade
+ 0x02 - Gamble
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x3F] D2GS_CHARACTERPHRASE
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) Phrase ID 
+
+ Remarks:
+ All phrases sent to the server will be heard by all players in your vicinity.
+
+ Phrase IDs: (Note: The deciding of which of the two phrases are used is random)
+ [0x19] "Help!" / "Help me!"
+ [0x1A] "Follow me!" / "Come on!"
+ [0x1B] "This is yours." / "This is for you."
+ [0x1C] "Thanks!" / "Thank you."
+ [0x1D] "Uh, oops." / "Forgive me."
+ [0x1E] "Bye!" / "Good Bye!"
+ [0x1F] "Die!" / "Time to die!"
+ [0x20] "Run!" / "Run away!" Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x49] D2GS_WAYPOINT
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (BYTE) Waypoint ID
+ (BYTE) Unknown - Appears to be random
+ (WORD) Unknown - 0x00
+ (BYTE) Level number
+ (WORD) Unknown - 0x00 
+
+ Remarks:
+ Requests to go to a waypoint if it was already activated.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x4F] D2GS_TRADE
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Request ID
+ (WORD) Gold Amount 
+
+ Remarks:
+ This message should be used for manipulating the trading window, the Horadric Cube item window, and the Stash window.
+
+ Possible Request ID's:
+ [0x02] Cancel trade request
+ [0x03] Accept trade request
+ [0x04] Press Accept button (accept)
+ [0x07] Press Accept button (unaccept) - This should be sent when placing items in the trade window as well.
+ [0x08] Refresh window (See below for examples on usage)
+ [0x12] Close stash window
+ [0x13] Move gold (stash to inventory)
+ [0x14] Move gold (inventory to stash)
+ [0x17] Close Horadric Cube window
+
+ Examples of using Refresh ID:
+ Item has been picked up to mouse cursor buffer.
+ Item has been placed in the trade screen.
+ Accepted or closed a trade window.
+ Manual unclick of Accept button.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x50] D2GS_DROPGOLD
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) PlayerID
+ (DWORD) GoldAmount 
+
+ Remarks:
+ Drops a pile of gold to the ground. 
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x51] D2GS_WORLDOBJECT
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (BYTE) Object Type - Any information appreciated
+ (DWORD) Object ID
+ (WORD) Object unique code
+ (WORD) X Coordinate
+ (WORD) Y Coordinate
+ (BYTE) State *
+ (BYTE) Interaction Condition 
+
+ Remarks:
+ Server-assigned coordinate, object ID, and state/interaction properties.
+
+ States:
+ 0x00 - Object's state can be changed. (Confirm?)
+ 0x02 - Object's state cannot be changed with (0x13) interaction. (Confirm?)
+
+ Interaction Conditions:
+ 0x00 - General object. E.G.: Stash, chests, etc.
+ 0x01 - Refresh shrine
+ 0x02 - Health shrine
+ 0x05 - Chest will catch fire (upon interaction)
+ 0x08 - Monster contained within chest (sarcophagus)
+ 0x0D - Mana recharge shrine
+ 0x0E - Stamina shrine
+ 0x0F - Experience shrine
+ 0x13 - Fire shrine
+ 0x80 - Chest is locked (State will be 0)
+
+ *If this value is 0, expect no packet 0x0E (status) to follow, if 2, then there will be.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x5C] D2GS_(COMP)STARTGAME
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ Blank 
+
+ Remarks:
+ This packet is part of the logon sequence, not to be confused with the other 0x5C.
+ This packet is originally received compressed, so the message ID will correspond with [Protocol Headers] D2GS
+ compressed format.
+ This message is received with the 'OK' that you can go ahead and enter the gaming environment. 
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x5E] D2GS_PARTY
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) Action ID
+ (DWORD) Player ID 
+
+ Remarks:
+ Possible Action IDs:
+
+ 0x06 - Invite player to party with you
+ 0x07 - Cancel invite to player
+ 0x08 - Accept invite from player
+ 0x09 - Leave party
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x61] D2GS_POTIONTOMERCENARY
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (WORD) Unknown - 0x00 
+
+ Remarks:
+ Takes the potion your cursor holds and gives it to the mercenary. Please note: This message's official name is not
+ known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x68] D2GS_GAMELOGON
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) D2GS Server Hash
+ (WORD) D2GS Server Token
+ (BYTE) Character ID
+ (DWORD) Version byte (Currently 0x0B)
+ (DWORD) Unknown - Suggested Const (0xED5DCC50)
+ (DWORD) Unknown - Suggested Const (0x91A519B6)
+ (BYTE) Unknown - Suggested (0x00)
+ (STRING) Character name
+ (VOID) *See user-comment below 
+
+ Remarks:
+ Possible Character IDs:
+ 0x00 - Amazon
+ 0x01 - Sorceress
+ 0x02 - Necromancer
+ 0x03 - Paladin
+ 0x04 - Barbarian
+ 0x05 - Druid
+ 0x06 - Assassin
+
+ The "Character name" field is a buffer of 15 characters with a null-terminator. This string should always be filled
+ with 15 characters (plus terminator), padded with 0's for unused bytes.
+
+ Note: If the character ID does not match the type of character you're attempting to logon with, and the character is
+ nealy created (with 0 play time), then that character will automatically be changed or "morphed" into the character ID
+ sent. 
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x6A] D2GS_ENTERGAMEENVIRONMENT
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ blank 
+
+ Remarks:
+ This byte should be sent in order to start receiving in-game messages and to interact with the world itself. 
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > S [0x6D] D2GS_PING
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Tick Count
+ (DWORD) Null
+ (DWORD) Null 
+
+ Remarks:
+ This packet should be sent every five to seven seconds to avoid timeout.
+
+ Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x77] D2GS_TRADEACTION
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (BYTE) Request Type 
+
+ Remarks:
+ A character is trading with you.
+
+ Possible Request Type values:
+ 0x01 - Player requests trade initiation
+ 0x05 - Player presses 'Accept'
+ 0x06 - 'Accept' button disabled for both players
+ 0x09 - Out of inventory space
+ 0x0C - Player cancels trade
+ 0x0D - You accepted the trade agreement
+ 0x0E - Your 'Accept' button is disabled
+ 0x0F - 'Accept' buttons re-enabled Please note: This message's official name is not known, and has been invented.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x7A] D2GS_LOGONRESPONSE
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (DWORD) Unknown - Possible acceptance/request ID 
+
+ Remarks:
+ This message is originally received compressed, so the message ID will correspond with D2GS compressed format.
+
+ This message is received if your logon is accepted by the D2GS.
+
+ Please note: This message's official name is not known, and has been invented. 
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0x89] D2GS_UNIQUEEVENTS
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ (BYTE) EventId // see below,
+
+ Events known so far:
+ 00 = Killed all the monsters in the den.
+ 01 = Tristram portal opening for the first time.
+ 03 = Staff being put into the oriface in act2
+ 06 = Ammy being poped in clawviper temple.
+ 07 = Summoner area? death or when the tome is clicked unsure which.
+ 08 = Duriel just died
+ 0b = Meph just died.
+ 0c = The last seal in cs was hit diablo is now released.
+ 0d = Diablo was killed or is dead.
+
+ Remarks:
+ I'm sure there are many others by looking at the gaps here.
+
+ Note1: Unsure what to name this any suggestions will be taken into account.
+ Note2: This seems to relate to various events that relate directly or indirectly to key quest states//events.
+
+ ~~~~~~~~~~~~~~~~
+
+ S > C [0xAF] D2GS_STARTLOGON
+ **************************************
+
+ Used By: Diablo II, Diablo II LOD
+
+ Format:
+ blank* 
+
+ Remarks:
+ Permission to initiate Game Server Logon.
+
+ * - Although this packet is blank, the data received will still be compressed. Meaning the actual message size will be
+ two bytes in length. (See [Sizes seen 0x01)
+ (BYTE) 0x00
+ (BYTE) 0x00
+ (WORD) A
+ (WORD) B
+
+ Remarks:
+ Packet CLS 2.
+
+ Sent by the host sometimes with CLS 2, packet 0x3E.
+
+ I'm not really sure what this message means.
+ The values A and B (and probably the null values) are carbon copies of the values a player sends in CLS 2, packet 0x40.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x40] SCGP_UNKNOWNRESPONSE
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x40)
+ (DWORD) 0x00
+ (DWORD) 0x00
+ (WORD) A
+ (WORD) B
+ (BYTE) 0x00
+ (DWORD) Uniqueness
+
+ Remarks:
+ Packet CLS 2.
+
+ Send to the host in response to CLS 1, packet 0x50.
+
+ I'm not sure what the A and B values in this message mean. However, it seems the host sends them to other players in
+ CLS 2, packet 0x3F.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x41] SCGP_CHANGERACE
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x41)
+ (BYTE) Slot Index
+ (BYTE) Race
+
+ Remarks:
+ Packet CLS 2.
+
+ Sent to other players requesting the race of a given slot be changed.
+ If changing your own race, the slot index must be 0x08.
+ Possible Races:
+ 0x00 = Zerg
+ 0x01 = Terran
+ 0x02 = Protoss
+ 0x03 = Independent
+ 0x04 = Neutral
+ 0x06 = Random
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x42] SCGP_CHANGETEAM
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x42)
+ (BYTE) Team Index
+
+ Remarks:
+ Packet CLS 2.
+
+ Sent to other players requesting you be moved to the given team.
+
+ Used in non-UMS games. To move team in a UMS game, use CLS 2, packet 0x43.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x43] SCGP_CHANGETEAMUMS
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x43)
+ (BYTE) Team Index
+
+ Remarks:
+ Packet CLS 2.
+
+ Sent to other players requesting you be moved to the given team.
+ If you are already in the given team, you will be moved to the next available slot in that team.
+
+ Used in UMS games. To move team in a non-UMS game, use CLS 2, packet 0x42.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x44] SCGP_CHANGESLOTSTATE
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x44)
+ (BYTE) Slot Index
+ (BYTE) State
+
+ Remarks:
+ Packet CLS 2.
+
+ Sent by the host to change a given slot index to a new state:
+ 0x00 = Computer
+ 0x01 = Open
+ 0x02 = Closed
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x45] SCGP_SLOTSWITCH
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x45)
+ (BYTE) Slot Index From
+ (BYTE) Slot Index To
+
+ Remarks:
+ Packet CLS 2.
+
+ Sent by the host to switch two slots. Used in Top vs Bottom games.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x48] SCGP_SEED
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x48)
+ (DWORD) Seconds since 1/1/1970
+ (BYTE) 0x08
+ (BYTE) 0x08
+ (BYTE) 0x08
+ (BYTE) 0x08
+ (BYTE) 0x08
+ (BYTE) 0x08
+ (BYTE) 0x08
+ (BYTE) 0x08
+
+ Remarks:
+ Packet CLS 2.
+
+ Sent by the host in the cross over between game room and game play.
+
+ Seeds game randomization, for example: who gets what start location/color/race etc.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x49] SCGP_PLAYERJOIN
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x49)
+ (DWORD) Player ID
+
+ Remarks:
+ Packet CLS 1.
+
+ Sent from host to other players in lobby.
+
+ Notifies other players that this player has joined the game.
+ The game would display "X has joined the game" and then /astat them when receiving this.
+ This is not sent for players who are already in the game.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x4A] SCGP_ROOMDATA
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x4A)
+ (WORD) Map Tileset
+ (WORD) Map Width
+ (WORD) Map Height
+ (BYTE[12]) OWNR
+ (BYTE[12]) SIDE
+ (BYTE[12]) OWNR Default
+ (BYTE[8]) FORC
+ (BYTE[4]) FORC Flag
+ (BYTE[8]) RACE
+
+ Remarks:
+ Packet CLS 1.
+
+ The tileset, width and height are not retrieved from the map in case it hasn't been downloaded yet-- these 3 values are
+ used on failth.
+ Valid tilesets:
+ 0x00 = Badlands
+ 0x01 = Space Platform
+ 0x02 = Installation
+ 0x03 = Ashworld
+ 0x04 = Jungle
+ 0x05 = Desert
+ 0x06 = Arctic
+ 0x07 = Twilight
+
+ The OWNR values are the base room slot values. They are modified values from the map to fit the given game
+ configuration.
+ The OWNR default is simply that, the default values from the map file.
+ The 12 bytes is for each possible player (1 to 12)
+ Possible values:
+ 0x00 = Doesn't exist
+ 0x02 = Human
+ 0x03 = Rescuable
+ 0x05 = Computer
+ 0x06 = Open
+ 0x07 = Neutral
+ 0x08 = Closed
+ Note: OWNR of Rescuable and Neutral are not shown.
+
+ The SIDE tells you the race for each player. These are modified SIDE values from the map file, to fit the given game
+ configuration.
+ 1 SIDE byte for each possible player (1 to 12)
+ Possible values:
+ 0x00 = Zerg
+ 0x01 = Terran
+ 0x02 = Protoss
+ 0x03 = Independent
+ 0x04 = Neutral
+ 0x06 = Random
+
+ The FORC tells you the force/team index of each player.
+ For example, 0x00 would mean no team (like melee) and 0x01 to 0x04 means this player/slot belongs to this team.
+
+ The FORC Flag gives you the settings for each force.
+ 0x01 = Random start locations
+ 0x02 = Allies
+ 0x04 = Allie victory
+ 0x08 = Shared Vision
+
+ The RACE tells you if a player can change their race *I think*. I'm not to sure about the RACE part, but i'm pretty
+ sure thats what it does. For example, disables a player from changing their race
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x4B] SCGP_FORCENAMES
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x4B)
+ (BYTE[30]) Force 1 Name
+ (BYTE[30]) Force 2 Name
+ (BYTE[30]) Force 3 Name
+ (BYTE[30]) Force 4 Name
+
+ Remarks:
+ Packet CLS 1.
+
+ This is only sent by the host to joining players, in Use Map Settings games, so they can display the name of the teams
+ before they have downloaded the map.
+ Each block of 30 bytes is infact a null-terminated string.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x4C] SCGP_LOBBYCHAT
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x4C)
+ (STRING) Chat message
+
+ Remarks:
+ Packet CLS 1.
+
+ Sent to talk to other players in the game lobby.
+ Note: If you're no longer in the game lobby, and are playing the game, you must use CLS 1, packet 0x00 to talk to other
+ players.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x4E] SCGP_REJECT
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x4E)
+ (BYTE) Event
+
+ Remarks:
+ Packet CLS 1.
+
+ Notifies you of an Event causing you to not be able to join:
+ Possible values:
+ 0x01 = You have been banned.
+ 0x02 = Game creater has closed all avalible slots.
+ 0x03 = Game host has left the game.
+ 0x04 = Unable to join the game.
+ 0x05 = Save game file not found.
+ 0x06 = Unable to write scenario file.
+ 0x07 = Invalid game version.
+ 0x08 = Invalid client version.
+ 0x09 = Unable to authenticate map.
+ Other = You have been booted.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x4F] SCGP_MAP
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x4F)
+ (WORD) Lengh of payload (discluding this value)
+ (WORD) EventEvent 0x00: (WORD) 0x100 (DWORD) File Position Event 0x01: (DWORD) File Lengh (DWORD) File Checksum
+ (STRING) File Name Event 0x02: (BYTE) Player ID (DWORD) File Position Event 0x03: [blank] Event 0x04: (BYTE) 0x00
+ (DWORD) File Position (WORD) Data Block Lengh (VOID) File Data Block Event 0x05: (BYTE) 0x00 (DWORD) File Position 
+
+ Remarks:
+ Packet CLS 1.
+
+ This packet is used to manage map downloading.
+ Some important things to note:
+ Players don't just download the map from the host. The host can request other ingame players send it, if they already
+ have it.
+ Data blocks are send in blocks of 128 bytes at a time, but you can get away with 256 blocks with out issue.
+
+ Event 0x00 [C>H]:
+ Tells the host if you have the map or not.
+ For example, the map positon tells the host where to start sending the file from.
+ If you already have the map, then the Map position should be the lengh of the file.
+
+ Event 0x01 [H>C]:
+ Asks a player if they have the given map.
+ Players should respond to this, with event 0x00.
+
+ Event 0x02 [H>C]:
+ Tells the receiving player, to send the map to another player.
+
+ Event 0x03 [H>C]:
+ I'm not to sure about this one.
+ This is send to a player who has just finished sending the map to another player, and also when the game is starting.
+
+ Event 0x04 [C>C]:
+ Used to send a block of the map to another player.
+ Receiving players should verify the block of data, by sending event 0x05.
+ Any breaks in the UDP stream should be managed with standard resend requests.
+
+ Event 0x05 [C>C]:
+ Verifies the position of the map you are currently at.
+ This should be sent as a respone to event 0x04.
+
+ ~~~~~~~~~~~~~~~~
+
+ C > C [0x50] SCGP_UNKNOWNREQUEST
+ **************************************
+
+ Used By: Starcraft Shareware, Starcraft Broodwar, Starcraft, Starcraft Japanese
+
+ Format:
+ (BYTE) ID (0x50)
+
+ Remarks:
+ Packet CLS 1.
+
+ Sent by the host during the join sequence.
+
+ Players should respond to this, by sending CLS 2, 0x40.
+ It is sent to joiners as part of the join process, a lot with/after CLS 1, 0x4A.
+
+ ~~~~~~~~~~~~~~~~
+
+ Battle.net v2 Messages
+ ------------------------------
+
+ ===============================
+ End of Generated Documentation
+ ===============================
+ =======================================================
+ Battle.net Documentation generated by BNETDocs
+ =======================================================
+
+ Links:
+ ------
+ [1] http://msdn2.microsoft.com/en-us/library/ms724295.aspx
+ [2] http://msdn2.microsoft.com/en-us/library/ms724432.aspx
+ [3] http://forum.valhallalegends.com/index.php?topic=15419.5
+ [4] http://bnetdocs.org/?op=doc&did=13
+ [5] http://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=vs.85).aspx
+ [6] http://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=vs.85).aspx
+ [7] https://github.com/HarpyWar/pvpgn/issues/15#issuecomment-44092744
+ [8] https://pastebin.com/WhKsmdnD
+ [9] https://pastebin.com/iDtEmhpr
+ [10] http://forum.valhallalegends.com/index.php?topic=16255.0
+ [11] https://pastebin.com/Dfz8Dzua
+ [12] https://pastebin.com/Dfz8Dzua
+ [13] https://pastebin.com/eGgRBcLV
+ [14] https://pastebin.com/CyDV2pC2
+ [15] https://pastebin.com/CyDV2pC2
+ [16] http://msdn2.microsoft.com/en-us/library/ms776265.aspx
+ [17] http://msdn2.microsoft.com/en-us/library/ms776270.aspx
+ [18] http://forum.valhallalegends.com/index.php?topic=17356.0
+ [19] http://forum.valhallalegends.com/index.php?topic=17356.0
diff --git a/func.php b/func.php
deleted file mode 100644
index 27195c61..00000000
--- a/func.php
+++ /dev/null
@@ -1,1057 +0,0 @@
-<?
-	########################
-	# Core Functions Script
-	########################
-
-	# Block Direct Access Attempts
-	# -------------------------------
-	global $auth;
-	if($auth != 'true') die('<html><head><title>BNETDocs: Redux</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
-	
-	# Begin Code
-	# -------------
-	
-	# DisplayDialogBox Function
-	# --------------------
-	#
-	# Function Name: DisplayDialogBox
-	# Purpose: Figure it out.
-	# Variable Uses:
-	#
-	# $text = The text to display as contents of the dialog box; Required; String.
-	# $poster = The poster of who posted dialog; Optional; String.
-	# $title = The title of the dialog box; Optional; String.
-	# $insdate = Inserts date automatically; Optional; Boolean.
-	# $file = Determines whether $text is treated as an include file; Optional; Boolean.
-	#
-	# --------------------
-		function DisplayDialogBox($text, $title='none', $file=false, $align='left'){
-			include 'bdif/dialogbox.dm';
-		}
-	#-------------
-	# End of DisplayDialogBox Function
-	#-------------
-
-
-
-	# DisplayNavBox Function
-	# --------------------
-	#
-	# Function Name: DisplayNavBox
-	# Purpose: Figure it out.
-	# Variable Uses:
-	#
-	# $text = The text to display as contents of the nav box; Required; String.
-	# $title = The title of the dialog box; Optional; String.
-	# $file = Determines whether $text is treated as an include file; Optional; Boolean.
-	#
-	# --------------------
-		function DisplayNavBox($text, $title="none", $file=false){
-			$auth = true;
-			$username = $_SESSION['username'];
-			include 'dmti/navbox.dm';
-		}
-	#-------------
-	# End of DisplayNavBox Function
-	#-------------
-
-	function getdir($dir, $no_dots=TRUE, $no_dirs=TRUE) {
-		$files = array();
-		$dh  = @opendir($dir);
-		if ($dh!=FALSE) {
-			while (false !== ($filename = readdir($dh))) {
-				$files[] = $filename;
-			}
-		
-			if ($no_dots) {
-				while(($ix = array_search('.',$files)) > -1) unset($files[$ix]);
-				while(($ix = array_search('..',$files)) > -1) unset($files[$ix]);
-				$li=0;
-				while($li <= count($files)){
-					$first = $str{0};
-					if($files[$li]{0}=='.') unset($files[$li]);
-					if($files[$li]{0}.$files[$li]{1}=='..') unset($files[$li]);
-					$li++;
-				}
-
-			}
-
-			if ($no_dirs) {
-				$li=0;
-				while($li <= count($files)){
-					if(is_dir($files[$li])) unset($files[$li]);
-					$li++;
-				}
-			}
-			$li=0;
-			while($li <= count($files)){
-				if(trim($files[$li])=='') unset($files[$li]);
-				$li++;
-			}
-
-			sort($files);
-		}
-	
-		return $files;
-	}
-
-	function MsgBox($message){
-		if(!$message) $message='Error: $message variable is empty.';
-		echo '
-			<SCRIPT LANGUAGE="javascript">
-			<!--
-				function MYALERT() {
-					alert("'.$message.'");
-				} 
-				MYALERT() 
-			<!-- END -->
-			</SCRIPT>';
-	}
-
-	function createRandomPassword() {
-	
-	    $chars = "abcdefghijkmnopqrstuvwxyz023456789";
-	    srand((double)microtime()*1000000);
-	    $i = 0;
-	    $pass = '' ;
-	
-	    while ($i <= 7) {
-	        $num = rand() % 33;
-	        $tmp = substr($chars, $num, 1);
-	        $pass = $pass . $tmp;
-	        $i++;
-	    }
-	
-	    return $pass;
-	
-	}
-
-	# Login Function
-	# --------------------
-	#
-	# Function Name: login
-	# Variable Uses:
-	#
-	# $username = member user name
-	# $password = member's password
-	# $tracked = determines if login is logged.
-	#
-	# --------------------
-		function login($username, $password, $tracked=true, $ip) {
-
-			# Set up pass variable
-			#-------------
-		
-				$ret = "pass";
-			
-			# Make sure we have data for user name and pw, if not, error out.
-			#-------------
-
-				if((!$username) || (!$password)){
-					$ret = "Missing login information.";
-				}
-
-			# Check database to verify login info
-			#-------------
-
-			if(FieldVerify("username", "users", $username)){
-				$userid = GetInfo("users", "username", $username, "id");
-				$pwtocheck = md5($password);
-				$password = GetInfo("users", "id", $userid, "password");
-			} else {
-				$ret = "You're not a registered user of BNETDocs: Redux.";
-			}
-
-			if($ret != "pass"){
-				return $ret;
-			}
-			
-			if($pwtocheck == $password){
-
-				# Login has been verified, get basic info from DB on member.
-				#-------------
-
-					$username = GetInfo("users", "id", $userid, "username");
-
-				# If tracking is enabled, log IP and login time/date.
-				#-------------
-
-					$ip = $_SERVER["REMOTE_ADDR"];
-					$sql = "UPDATE users SET ip=\"$ip\" WHERE username=\"$username\"";
-					if($tracked == true) $sqlresults = mysql_query($sql) or die (mysql_error());
-					if($tracked == true) mysql_query("UPDATE users SET last_login=now() WHERE username='$username'");
-
-				# Set up session for member
-				#-------------
-
-					CreateSession($userid, $ip);
-
-				#-------------
-				# Done setting up session
-				#-------------
-
-			} else {
-
-				# Invalid login info. Error out.
-				#-------------
-
-				$ret = "<br /><center>Invalid Login!</center>";
-			}
-			
-			return $ret;
-		}
-	#-------------
-	# End of Login Function
-	#-------------
-
-	function error($message){
-		DisplayDialogBox('<br><br><br><br><br><br><br><center><font size=5>'.$message.'</font></center><br><br><br><br><br><br><br>', '<font size=3><center>Error</center></font>');
-	}
-	
-	
-	
-	# FieldVerify Function
-	# --------------------
-	#
-	# Function Name: FieldVerify
-	# Purpose: Checks to see if a given field containing specified data exists
-	# Variable Uses:
-	#
-	# $table = Target table to access
-	# $field = Field to check in
-	# $data = Data of whatever you're verifying
-	#
-	# --------------------
-		function FieldVerify($field, $table, $data){
-			
-			$sql = "SELECT COUNT(*) AS count FROM `$table` WHERE `$field`=\"$data\"";
-
-			$testercount = mysql_query($sql) or die("mysql error in $sql: ".mysql_error());
-			$testercount = mysql_fetch_object($testercount);
-			$testers = $testercount->count;
-			
-			if($testers > 0){
-				return true;
-			}
-			return false;
-		}
-	#-------------
-	# End of FieldVerify Function
-	#-------------
-
-	
-	# Sector Security Function
-	# --------------------
-	#
-	# Function Name: Secure
-	# Variable Uses: None.
-	#
-	# --------------------
-		function secure($ip) {
-
-			# Check to see if session exists.
-			#-------------
-			
-			if(!FieldVerify("ipaddress", "sessions", $ip)){
-				Redirect("/?op=login");
-			}
-			
-			# Update Activity
-			#------------
-			
-			$userid = GetInfo("sessions", "ipaddress", $ip, "id");
-			mysql_query("UPDATE users SET last_login=now() WHERE id='$userid'");
-		}
-
-	#-------------
-	# End of Sector Security Function
-	#-------------
-
-
-
-	# GetData Function
-	# --------------------
-	#
-	# Function Name: GetData
-	# Purpose: Makes it easier to obtain a member's info.
-	# Variable Uses:
-	#
-	# $whoid = target member for info request
-	# $what = which field data to pull up
-	#
-	# --------------------
-		function GetData($whoid, $what){
-			$ret = GetInfo("users", "id", $whoid, $what);
-			return $ret;
-		}
-	#-------------
-	# End of GetData Function
-	#-------------
-
-	# WriteData Function
-	# --------------------
-	#
-	# Function Name: WriteData
-	# Purpose: Makes it easier to update a member's info.
-	# Variable Uses:
-	#
-	# $whoid = target member for info update
-	# $what = which field data to modify (field *MUST* exist)
-	#$data = the data to write
-	#
-	# --------------------
-		function WriteData($whoid, $what, $data){
-			$ret = true;
-			$sql = "UPDATE users SET `$what`=\"$data\" WHERE id=$whoid"; 
-			$sqlresults = mysql_query($sql) or $ret = false;
-			return $ret;
-		}
-	#-------------
-	# End of WriteData Function
-	#-------------
-	
-	
-	
-	function Discipline($target, $action, $ip=''){
-		if($action == 'lp'){
-			$sql = "UPDATE discipline SET profile=0 WHERE account=$target";
-			$sqlresults = mysql_query($sql) or die(mysql_error());
-		} else if($action == 'up'){
-			$sql = "UPDATE discipline SET profile=1 WHERE account=$target";
-			$sqlresults = mysql_query($sql) or die(mysql_error());
-		} else if($action == 'fa'){
-			$sql = "UPDATE discipline SET frozen=1 WHERE account=$target";
-			$sqlresults = mysql_query($sql) or die(mysql_error());
-		} else if($action == 'ufa'){
-			$sql = "UPDATE discipline SET frozen=0 WHERE account=$target";
-			$sqlresults = mysql_query($sql) or die(mysql_error());
-		} else if($action == 'ipban'){
-			$sql = "UPDATE discipline SET ipban=1 WHERE account=$target";
-			$sqlresults = mysql_query($sql) or die(mysql_error());
-			$currentip = GetData($target, 'ip');
-			mysql_query("INSERT INTO `banned` (id, ip, bantype) VALUES ($target, '$ip', 'total')") or die("Discipline Function Error: ".mysql_error());
-		} else if($action == 'unipban'){
-			$sql = "UPDATE discipline SET ipban=0 WHERE account=$target";
-			$sqlresults = mysql_query($sql) or die(mysql_error());
-			$sql = "DELETE FROM banned WHERE id=\"$target\"";
-			$sqlresults = mysql_query($sql) or die (mysql_error());
-		}
-	}
-	
-	function BlockHack(){
-		die('<center><br><br><b><font color=red>Unauthorized access blocked. Nice try, buddy.</font></b><br><br></center>');
-	}
-	
-	# GetInfo Function
-	# --------------------
-	#
-	# Function Name: GetInfo
-	# Purpose: Offers specialized information by specifying data request
-	# Variable Uses:
-	#
-	# $db = Target database to access
-	# $index = Field to correlate $id from.
-	# $id = ID/ACCOUNT/USERNAME of whatever you're accessing
-	# $data = The field where you want to obtain the data from.
-	# --------------------
-		function GetInfo($db, $index, $id, $data){
-			$sqlquery = mysql_query("SELECT * FROM `$db` WHERE `$index`=\"$id\" LIMIT 1") or die('Attempted Query: '."SELECT * FROM `$db` WHERE `$index`='$id' LIMIT 1"."<br>GetInfo Function Error: ".mysql_error());;
-			if(mysql_num_rows($sqlquery) > 0) {
-				$ret = mysql_result($sqlquery,0,$data);
-			} else {
-				$ret = false;
-			}
-			return $ret;
-		}
-	#-------------
-	# End of GetInfo Function
-	#-------------
-
-	# WriteInfo Function
-	# --------------------
-	#
-	# Function Name: WriteInfo
-	# Purpose: Writes specialized information by specifying data request to existing field
-	# Variable Uses:
-	#
-	# $db = Target database to access
-	# $index = Field to correlate $id from.
-	# $id = ID/ACCOUNT/USERNAME of whatever you're accessing
-	# $field = The field where you want to write the data to.
-	#$data = the data you'd like to have written
-	# Example: WriteInfo('messages', 'id', $id, 'opened', 1);
-	# --------------------
-		function WriteInfo($db, $index, $id, $field, $data){
-			$ret = true;
-			$sql = "UPDATE `$db` SET `$field`=\"$data\" WHERE $index=$id"; 
-			$sqlresults = mysql_query($sql) or $ret = false;
-			return $ret;
-		}
-	#-------------
-	# End of GetInfo Function
-	#-------------
-
-	# URLButton Function
-	# --------------------
-	#
-	# Function Name: URLButton
-	# Purpose: A form button acts as a hyperlink
-	# Variable Uses:
-	#
-	# $text = Text to display on button
-	# $url = Target address to send to when clicked
-	#
-	# --------------------
-		function URLButton($text,$url){
-			?><form><input id="abutton" style="width:125;height:23" type=button value="<? echo $text ?>" onClick="gourl('<? echo $url ?>')"></form><?
-		}
-	#-------------
-	# End of URLButton Function
-	#-------------
-
-	
-
-	# Redirect Function
-	# --------------------
-	#
-	# Function Name: Redirect
-	# Purpose: Redirects user to target page
-	# Variable Uses:
-	#
-	# $page = Target page to redirect to
-	#
-	# --------------------
-		function Redirect($page){
-			echo "<meta http-equiv=\"refresh\" content=\"0;url=$page\"><body bgcolor=black>";
-			die();
-		}
-	#-------------
-	# End of Redirect Function
-	#-------------
-	
-	if (!function_exists("stripos")) {
-	  function stripos($str,$needle,$offset=0)
-	  {
-	      return strpos(strtolower($str),strtolower($needle),$offset);
-	  }
-	}
-
-	# Email Function
-	# --------------------
-	#
-	# Function Name: Email
-	# Purpose: Send emails
-	# Variable Uses:
-	#
-	# $target = email address to send the email to
-	# $fromwho = return address
-	# $subject = obvious...
-	# $body = obvious...
-	#
-	# --------------------
-		function Email($target, $fromwho, $subject, $body){
-			$headers = "From: BNETDocs<$fromwho>\r\n";
-			mail($target, $subject, $body, $headers);
-		}
-	#-------------
-	# End of Email Function
-	#-------------
-	
-	#Applies nl2br to $text, but also makes sure to avoid applying the function to any content within pre tags
-	function nl2brex($text) {
-		$text = nl2br($text);
-		$text = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " ('$1') .  (clean_pre('$2'))  . '</pre>' ", $text);
-		$text = preg_replace('!(<ol.*?>)(.*?)</ol>!ise', " ('$1') .  (clean_pre('$2'))  . '</ol>' ", $text);
-		$text = preg_replace('!(<ul.*?>)(.*?)</ul>!ise', " ('$1') .  (clean_pre('$2'))  . '</ul>' ", $text);
-		$text = preg_replace('!(<dl.*?>)(.*?)</dl>!ise', " ('$1') .  (clean_pre('$2'))  . '</dl>' ", $text);
-		$text = preg_replace('!(\[nobr.*?\])(.*?)\[/nobr\]!ise', " stripslashes('$1') .  stripslashes(clean_pre('$2'))  . '' ", $text);
-		$text = brfix($text);
-		$text = str_ireplace('[nobr]', '', $text);
-		$text = str_ireplace('[/nobr]', '', $text);
-		return $text;
-	}
-	
-	#nl2brex2 for RSS feeds
-	function nl2brex2($text) {
-		$text = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " ('$1') .  (clean_pre('$2'))  . '</pre>' ", $text);
-		$text = preg_replace('!(<ol.*?>)(.*?)</ol>!ise', " ('$1') .  (clean_pre('$2'))  . '</ol>' ", $text);
-		$text = preg_replace('!(<ul.*?>)(.*?)</ul>!ise', " ('$1') .  (clean_pre('$2'))  . '</ul>' ", $text);
-		$text = preg_replace('!(<dl.*?>)(.*?)</dl>!ise', " ('$1') .  (clean_pre('$2'))  . '</dl>' ", $text);
-		$text = preg_replace('!(\[nobr.*?\])(.*?)\[/nobr\]!ise', " stripslashes('$1') .  stripslashes(clean_pre('$2'))  . '' ", $text);
-		$text = brfix($text);
-		$text = str_ireplace('[nobr]', '', $text);
-		$text = str_ireplace('[/nobr]', '', $text);
-		return $text;
-	}
-	
-	# Workaround for the br tag after a closing tag fix
-	function brfix($text){
-		$text = str_ireplace('</dl><br />', '</dl>', $text);
-		$text = str_ireplace('</dd><br />', '</dd>', $text);
-		$text = str_ireplace('</dt><br />', '</dt>', $text);
-		$text = str_ireplace('</ol><br />', '</ol>', $text);
-		$text = str_ireplace('</ul><br />', '</ul>', $text);
-		$text = str_ireplace('</li><br />', '</li>', $text);
-		$text = str_ireplace('</p><br />', '</p>', $text);
-		#$tagstoclean = array('dl', 'dd', 'dt', 'ol', 'ul', 'li', 'p');
-		#for($i = 0; $i <= count($tagstoclean), $i++;){
-		#	$text = str_ireplace('</'.$tagstoclean[$i].'><br />', '</'.$tagstoclean[$i].'>', $text);
-		#}
-		return $text;
-	}
-	
-	// Remove paragraphs and breaks from within any <pre> tags.
-	function clean_pre($text) {
-		$text = str_replace(array("<br />\r\n", "<br />\r", "<br />\n"), "\n", $text);
-		$text = str_replace('<p>', "\n", $text);
-		$text = str_replace('</p>', '', $text);
-		return $text;
-	}
-	
-	
-	function totalpurgehtml($source){
-		$allowedTags='';
-		$source = strip_tags($source, $allowedTags);
-		return preg_replace('/<(.*?)>/ie',
-		"'<'.removeEvilAttributes('\\1').'>'", $source);
-	}
-	
-	# Codify Function
-	# --------------------
-	#
-	# Function Name: Codify
-	# Purpose: Neturalizes text, then checks for custom code inside a string, and translates it into corresponding html
-	#
-	# Variable Uses:
-	#
-	# $text = text to translate into html
-	#
-	# --------------------
-	function Codify($text){
-		$patterns[0] = "|\[b\](.*?)\[/b\]|s";
-		$patterns[1] = "|\[i\](.*?)\[/i\]|s";
-		$patterns[2] = "|\[u\](.*?)\[/u\]|s";
-		$patterns[3] = "|\[center\](.*?)\[/center\]|s";
-		$patterns[4] = "|\[url\](.*?)\[/url\]|s";
-		$patterns[5] = "|\[url=(.*?)\](.*?)\[/url\]|s";
-		$patterns[6] = "|\[img\](http://.*?)\[/img\]|s";
-		$patterns[7] = "|\[img\]([0-9]+)(\.[a-zA-Z0-9]{0,10})\[/img\]|s";
-		$patterns[8] = "|\[code\](.*?)\[/code\]|s";
-		$patterns[10] = "|\[s\](.*?)\[/s\]|s";
-		$replacements[0] = "<b>\$1</b>";
-		$replacements[1] = "<i>\$1</i>";
-		$replacements[2] = "<u>\$1</u>";
-		$replacements[3] = "<center>\$1</center>";
-		$replacements[4] = "<a href=\"\$1\">\$1</a>";
-		$replacements[5] = "<a href=\"\$1\">\$2</a>";
-		$replacements[6] = "<img src=\"\$1\" />";
-		$replacements[7] = "<img src=\"images/\$1\$2\" />";
-		$replacements[8] = "<div style=\"overflow: auto;\" align=center><div id=\"code\"><pre>\$1</pre></div></div>";
-		$replacements[10] = "<strike>\$1</strike>";
-		ksort($patterns);
-		ksort($replacements);
-		$text = preg_replace($patterns, $replacements, $text);
-		$text = nl2brex($text);
-		return $text;
-	}
-	#-------------
-	# End of Codify Function
-	#-------------
-	
-	if(!function_exists('str_ireplace')) {
-		function str_ireplace($search,$replace,$subject) {
-			$search = preg_quote($search, "/");
-			return preg_replace("/".$search."/i", $replace, $subject); 
-		} 
-	}
-
-	function purge($StringToPurge) {
-		$string = str_replace(array("\r\n", "\r", "\n"), "", $StringToPurge);
-		return $string;
-	}
-	
-	function removeEvilTags($source){
-		#$allowedTags='<b><s><u><span><p><i><blockquote><ul><ol><li><br><a><dl><dt><dd>';
-		#$source = strip_tags($source, $allowedTags);
-		#return preg_replace('/<(.*?)>/ie',
-		#"'<'.removeEvilAttributes('\\1').'>'", $source);
-		return $source;
-	}
-
-	$stripAttrib = 'javascript:|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onkeypress|onkeydown|onkeyup';
-	function removeEvilAttributes($tagSource) {
-		global $stripAttrib;
-		return stripslashes(preg_replace("/$stripAttrib/i", 'forbidden', $tagSource));
-	}
-	
-	function sanitize($string, $min='', $max=''){
-		return mysql_real_escape_string($string);
-	}
-
-	function CreateSession($id, $ip){
-		if(!FieldVerify('id', 'sessions', $id)){
-			mysql_query("INSERT INTO sessions (id,ipaddress) VALUES ('$id','$ip')") or die("CreateSession Function Error: ".mysql_error());
-		} else {
-			mysql_query("UPDATE sessions SET ipaddress='$ip' WHERE id='$id'") or die("CreateSession Function Error: ".mysql_error());
-		}
-	}
-	
-	function KillSession($id){
-		if(FieldVerify('id', 'sessions', $id)){
-			$sql = "DELETE FROM sessions WHERE id=$id";
-			$sqlresults = mysql_query($sql) or die (mysql_error());
-		}
-	}
-
-	
-	
-	function SwapID($newid, $ip){
-		$origid = GetUserIDFromSession($ip);
-		if(!FieldVerify('ip', 'testers', $ip)){
-			mysql_query("INSERT INTO testers (id,ip) VALUES ('$origid','$ip')") or die("SwapID Function Error: ".mysql_error());
-		} else {
-			mysql_query("UPDATE testers SET id='$origid' WHERE ip='$ip'") or die("SwapID Function Error: ".mysql_error());
-		}
-		KillSession($origid);
-		CreateSession($newid, $ip);
-	}
-	
-	# $table = Target table to access
-	# $field = Field to check in
-	# $data = Data of whatever you're verifying
-	#
-	# --------------------
-		#function FieldVerify($field, $table, $data){
-		
-	function RestoreID($ip){
-		if(FieldVerify('ip', 'testers', $ip)){
-			$fakeid = GetInfo('sessions', 'ipaddress', $ip, 'id');
-			$realid = GetInfo('testers', 'ip', $ip, 'id');
-			$sql = "DELETE FROM testers WHERE id=\"$realid\"";
-			$sqlresults = mysql_query($sql) or die (mysql_error());
-			KillSession($fakeid);
-			CreateSession($realid, $ip);
-		}
-	}
-	
-	function SwapMode($ip){
-		if(FieldVerify('ip', 'testers', $ip)){
-			return true; #Swap Mode is active
-		} else {
-			return false; #Swap mode is not active
-		}
-	}
-	
-	function GetUserIDFromSession($ip){
-		if(FieldVerify("ipaddress", "sessions", $ip)){
-			$ret = GetInfo("sessions", "ipaddress", $ip, "id");
-		} else {
-			return false;
-		}
-		
-		return $ret;
-	}
-	
-	function GetOldData($whoid, $what){
-		$ret = GetInfo('terminated', 'id', $whoid, $what);
-		return $ret;
-	}
-	
-	function CheckBanned($ip, $type){
-		$sql = "SELECT COUNT(*) AS count FROM `banned` WHERE `ip`=\"$ip\" AND `bantype`=\"$type\"";
-
-		$testercount = mysql_query($sql) or die("mysql error in $sql: ".mysql_error());
-		$testercount = mysql_fetch_object($testercount);
-		$testers = $testercount->count;
-
-		if($testers > 0){
-			return true;
-		}
-		return false;
-	}
-		
-	function RecoverUser($id){
-		if(!FieldVerify('id', 'users', $id)){
-			mysql_query("INSERT INTO `users` (id) VALUES ($id)") or die("RecoverUser Function Error: ".mysql_error());
-		}
-		
-		$temp = GetOldData($id, 'username');
-		WriteData($id, 'username', $temp);
-		$temp = GetOldData($id, 'password');
-		WriteData($id, 'password', $temp);
-		$temp = GetOldData($id, 'email');
-		WriteData($id, 'email', $temp);
-		$temp = GetOldData($id, 'levelofaccess');
-		WriteData($id, 'levelofaccess', $temp);
-		$temp = GetOldData($id, 'recruitedby');
-		WriteData($id, 'recruitedby', $temp);
-		$temp = GetOldData($id, 'dateofbirth');
-		WriteData($id, 'dateofbirth', $temp);
-		$temp = GetOldData($id, 'datejoined');
-		WriteData($id, 'datejoined', $temp);
-		$temp = GetOldData($id, 'disciplinehistory');
-		WriteData($id, 'disciplinehistory', $temp);
-		$temp = GetOldData($id, 'division');
-		WriteData($id, 'division', $temp);
-		$temp = GetOldData($id, 'firstname');
-		WriteData($id, 'firstname', $temp);
-		$temp = GetOldData($id, 'lastname');
-		WriteData($id, 'lastname', $temp);
-		$temp = GetOldData($id, 'datejoined');
-		WriteData($id, 'datejoined', $temp);
-		
-		#Verify users db contains recovered information
-		
-		if(!FieldVerify("id", "users", $id)){
-			die('The account could not be recovered due to an error in the Account Recovery function.');
-		}
-		
-		# Account successfully recovered at this point, go ahead and delete the account recovery info from the terminated database.
-		
-		if(FieldVerify("id", "terminated", $id)){
-			$sql = "DELETE FROM `terminated` WHERE id=\"$id\"";
-			$sqlresults = mysql_query($sql) or die (mysql_error());
-		}
-	}
-	
-	
-	function statusimg($status){
-		if($status){
-			return '/images/connected.png';
-		} else {
-			return '/images/disconnected.png';
-		}
-	}
-
-	function checkserver($serverid){
-		if(FieldVerify('id', 'servers', $serverid)){
-				$serverstatus = GetInfo("servers", "id", $serverid, "status");
-				if($serverstatus == 'offline'){
-					return false;
-				} else {
-					return true;
-				}
-		} else {
-			die("No such server.");
-			return false;
-		}
-		return false;
-	}
-	
-	function delslash($text){
-		$text = str_replace("\'", "'", $text);
-		$text = str_replace('\"', '"', $text);
-		return $text;
-	}
-	
-	// This function included is a copy of phpbb_rtrim();
-	function data_rtrim($str, $charlist = false){
-	    if ($charlist === false){
-	        return rtrim($str);
-	    }
-		
-	    $php_version = explode('.', PHP_VERSION);
-
-	    // php version < 4.1.0
-	    if ((int) $php_version[0] < 4 || ((int) $php_version[0] == 4 && (int) $php_version[1] < 1)){
-	        while ($str{strlen($str)-1} == $charlist){
-	            $str = substr($str, 0, strlen($str)-1);
-	        }
-	    } else {
-	        $str = rtrim($str, $charlist);
-	    }
-	    return $str;
-	}
-
-	function CreateUser($username, $email, $ip){
-		if(!FieldVerify('username', 'users', $username)){
-			if(!FieldVerify('username', 'terminated', $username)){
-				$breakout = false;
-				while($breakout == false){
-					$password = createRandomPassword();
-					if(!FieldVerify('password', 'users', md5($password))){	#Done to ensure original password.
-						$breakout = true;
-					}
-				}
-				$enpassword = md5($password);
-				mysql_query("INSERT INTO users (ip, username, password, email) VALUES ('$ip', '$username', '$enpassword', '$email')") or die("CreateUser Function Error: ".mysql_error());
-				$body = "Welcome!
-		
-You've registered as an user of BNETDocs. If this email is in error, simply ignore this email.
-
-Your information is as follows:
-
-Username: $username
-Password: $password
-
-The password was randomly generated for you. You can change your password after logging in.
-
-Simply login at the site to activate your account.
-
-Website: http://www.bnetdocs.org
-
-Once more, welcome!
-
-Regards,
-BNETDocs
-
----------
-Please do not respond to this email, this email was automatically generated.
-If you have any questions, comments, etc, feel free to contact one of the administrators.
----------";
-				Email($email, 'postmaster@bnetdocs.org', 'Welcome to BNETDocs!', $body);				
-			} else { #Aha, user was a member before, remove from terminated database and give original id
-				$id = getinfo('terminated', 'username', $username, 'id');
-				$sql = "DELETE FROM terminated WHERE id=\"$id\"";
-				$sqlresults = mysql_query($sql) or die (mysql_error());
-				$breakout = false;
-				while($breakout == false){
-					$password = createRandomPassword();
-					if(!FieldVerify('password', 'users', md5($password))){	#Done to ensure original password.
-						$breakout = true;
-					}
-				}
-				$enpassword = md5($password);
-				mysql_query("INSERT INTO users (id, ip, username, password, email) VALUES ($id, '$ip', '$username', '$enpassword', '$email')") or die("CreateUser Function Error: ".mysql_error());
-				$body = "Welcome Back!
-		
-You've re-registered as an user of BNETDocs. If this email is in error, simply ignore this email.
-
-Your information is as follows:
-
-Username: $username
-Password: $password
-
-The password was randomly generated for you. You can change your password after logging in.
-
-Simply login at the site to re-activate your account. Your personal settings were not saved, so you will need to adjust them as desired. Your comments, news posts, logs related to you were all saved, and all of them has been re-linked to your new account.
-
-Website: http://www.bnetdocs.org
-
-Once more, welcome back!
-
-Regards,
-BNETDocs
-
----------
-Please do not respond to this email, this email was automatically generated.
-If you have any questions, comments, etc, feel free to contact one of the administrators.
----------";
-				Email($email, 'postmaster@bnetdocs.org', 'Welcome Back to BNETDocs!', $body);
-				
-				$userid = getinfo('users', 'username', $username, 'id');
-				$event = 'Re-registered as an user of BNETDocs.';
-				$type = 'acctrestore';
-			}
-		}
-	}
-	
-	function ResetPassword($userid){
-		$breakout = false;
-		while($breakout == false){
-			$password = createRandomPassword();
-			if(!FieldVerify('password', 'users', md5($password))){
-				$breakout = true;
-			}
-		}
-		$username = whoisid($userid);
-		$email = GetData($userid, 'email');
-		$enpassword = md5($password);
-		mysql_query("UPDATE users SET password='$enpassword' WHERE id=$userid") or die("ResetPasswrd Function Error: ".mysql_error());
-		$body = "Hello!
-
-You've requested your password to be resetted. It has been resetted for you.
-
-If this email is in error, PLEASE ALERT AN ADMINISTRATOR -- this way we can take appropriate action.
-
-Your information is as follows:
-
-Username: $username
-Password: $password
-
-The password was randomly generated for you. You can change your password after logging in.
-
-Website: http://www.bnetdocs.org
-
-Regards,
-BNETDocs
----------
-Please do not respond to this email, this email was automatically generated.
-If you have any questions, comments, etc, feel free to contact one of the administrators.
----------";
-		Email($email, 'postmaster@bnetdocs.org', 'BNETDocs Password Reset', $body);
-		
-		$event = 'Had their password reset and emailed to them.';
-		$type = 'CONFIDENTAL';
-	}
-	
-	#--------------
-	# Warning! If this function is called, it results in deletion of data associated with that user
-	#--------------
-	function DeleteUser($id){
-		
-		# Copy username info to terminated db for stability
-		
-		$username = GetData($id, 'username');
-		mysql_query("INSERT INTO `terminated` (`id`, `username`) VALUES ($id, '" . mysql_real_escape_string($username) . "')") or die("DeleteUser Function Error: ".mysql_error());
-		
-		# Delete User's session if it exists
-		
-		if(FieldVerify("id", "sessions", $id)){
-			KillSession($id);
-		}
-		
-		# Delete from users DB if it exists
-		
-		if(FieldVerify("id", "users", $id)){
-			$sql = "DELETE FROM users WHERE id=$id";
-			$sqlresults = mysql_query($sql) or die (mysql_error());
-		}
-	}
-	
-	if(version_compare(PHP_VERSION, '5.3.0') < 0) {
-		function lcfirst($str) {
-			return strtolower(substr($str, 0, 1)) . substr($str, 1);
-		}
-	}
-
-	function rank($id){
-	   	$rank = GetData($id,'levelofaccess');
-	   	return $rank;
-	}
-
-	function rankname($rank){
-		$info = mysql_query("SELECT groupname FROM `membergroup` WHERE `id` ='".$rank."'")  or die("Rank Name Function Error: ".mysql_error());
-		$rank = mysql_result($info,0,"groupname");
-		return $rank;
-	}
-	
-	#known types: session
-	function logthis($userid, $event, $type){
-		$event = sanitize($event);
-		$datetime = date("l, F d Y");
-		$ip = $_SERVER['REMOTE_ADDR'];
-		echo json_encode(array('userid'=>$userid,'event'=>$event,'type'=>$type,'datetime'=>$datetime,'ip'=>$ip));return;
-		mysql_query("INSERT INTO logs (user,event,eventtype, datetime,ip) VALUES ('$userid','$event','$type','$datetime','$ip')") or die("Logthis Function Error: ".mysql_error());
-	}
-
-	function curPageURL() {
-		$pageURL = 'http';
-		if ($_SERVER["HTTPS"] == "on") {$pageURL .= "s";}
-		$pageURL .= "://";
-		if ($_SERVER["SERVER_PORT"] != "80") {
-		$pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
-		} else {
-		$pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
-		}
-		return $pageURL;
-	}
-	
-	
-
-	function whoisid($idtocheck){
-		#Return name associated with identification number
-		#Parameter: ID
-
-		if($idtocheck != "all"){
-			if($idtocheck == '-1') return 'WEBSITE:';
-			if($idtocheck == 0) return 'UNKNOWN:';
-			if(FieldVerify("id", "users", $idtocheck)){
-				$ret = getinfo('users', 'id', $idtocheck, 'username');
-			} else {
-				$ret = getinfo('terminated', 'id', $idtocheck, 'username');
-			}
-		} else {
-			$ret = "all";
-		}
-		return $ret;
-	}
-	
-	#catchall, will have some unintended casualities. until a deal is reached with blizzard, do not disengage.
-	function isblizzard($ip){
-		$range = substr($ip, 0, stripos($ip, '.', (stripos($ip, '.') + 1)));
-		switch ($range) {
-			case '63.241':
-			case '63.240':
-			case '211.233':
-			case '213.248':
-			case '216.148':
-			case '12.129':
-			case '216.148':
-				$ret = true;
-				break;
-			default:
-			    $ret = false;
-		}
-		return $ret;
-	}
-
-	function getid($idtoget){
-		#Return identification number associated with name
-		#Parameter: Name
-		$queryid = "SELECT * FROM users WHERE username = \"$idtoget\"";
-		if($idtoget != "all"){
-			$identification = mysql_query($queryid);
-			$ret = mysql_result($identification,0,"id");
-		} else {
-			$ret = "all";
-		}
-		return $ret;
-	}
-
-	function getpacketlink($id){
-		#Return name of packet associated with id
-		#Parameter: id
-		$queryid = "SELECT * FROM packets WHERE id=$id";
-		$identification = mysql_query($queryid);
-		$messageid = mysql_result($identification,0,"messageid");
-		$messagename = mysql_result($identification,0,"messagename");
-		$ret = '<a href="/?op=packet&pid='.$id.'">('.$messageid.') '.$messagename.'</a>';
-		return $ret;
-	}
-	
-	function getdocumentlink($id){
-		#Return name of packet associated with id
-		#Parameter: id
-		$queryid = "SELECT * FROM documents WHERE id=$id";
-		$identification = mysql_query($queryid);
-		$title = mysql_result($identification,0,"title");
-		$ret = '<a href="/?op=doc&did='.$id.'">'.$title.'</a>';
-		return $ret;
-	}
-	
-	function days($thedate){
-		$days=(strtotime(date('m/d/y')))-(strtotime($thedate));
-		$days=ceil($days/86400);
-		return $days;
-	}
-	
-	# String comparsion function
-	# ------------------------------------
-	# $firststring 				Should be obvious what this is for
-	# $secondstring			Again, should be obvious
-	#
-	# This function will compare two strings, and return the difference, with | as the separator between the first and second strings.
-	# 
-	# Example:
-	#
-	# $firststring = "This is the first string.";
-	# $secondstring = "This is the second string.";
-	# $i = GetStrDiff($firststring, $secondstring);
-	# $a = split($i, '|');
-	# $final = $a[0].' was changed to '.$a[1];
-	# echo "First string: $firststring<br>";
-	# echo "Second string: $secondstring<br>";
-	# echo "Differences: $final";
-	#
-	# Output: 
-	#	This is the first string.
-	#	This is the second string.
-	#	Differences: first was changed to second
-	#
-	function GetStrDiff($firststring, $secondstring){
-		# Warning, this function is still under development.
-		$results = false;
-		return $results;
-	}
-?>
diff --git a/functions.php b/functions.php
index e6781ca6..34281bb6 100644
--- a/functions.php
+++ b/functions.php
@@ -962,13 +962,13 @@ function whoisid($idtocheck){
 	function isblizzard($ip){
 		$range = substr($ip, 0, stripos($ip, '.', (stripos($ip, '.') + 1)));
 		switch ($range) {
-			case '63.241':
-			case '63.240':
+			case '12.129':
 			case '211.233':
 			case '213.248':
 			case '216.148':
-			case '12.129':
 			case '216.148':
+			case '63.240':
+			case '63.241':
 			case '98.196':
 				$ret = true;
 				break;
diff --git a/generatedocs.php b/generatedocs.php
index 69101a5f..28ec9124 100644
--- a/generatedocs.php
+++ b/generatedocs.php
@@ -3,8 +3,8 @@
 	# -------------
 	
 	$auth = 'true';
-	include_once('functions.php');
-	include_once('db.php');
+	require_once('functions.php');
+	require_once('db.php');
 	
 	require_once('bdif/class.html2text.dm'); 
 	
@@ -206,4 +206,4 @@ function callback($buffer){
 		<?
 	}
 	ob_end_flush();
-?>
\ No newline at end of file
+?>
diff --git a/index.php b/index.php
index c7ced808..0db2b7c7 100644
--- a/index.php
+++ b/index.php
@@ -48,8 +48,8 @@ function stripslashes_deep($value) {
 	# Include essential files
 	#-------------
 
-		require 'db.php';
-		require 'func.php';
+		require_once 'db.php';
+		require_once 'functions.php';
 		
 	# Block out unwelcome visitors
 	#-------------
diff --git a/logsrss.php b/logsrss.php
index 6631b61c..91375105 100644
--- a/logsrss.php
+++ b/logsrss.php
@@ -48,8 +48,8 @@ function replaceOnce($search, $replace, $content){
 	}
 
 	$auth = 'true';
-	include 'func.php';
-	include 'db.php';
+	require_once 'functions.php';
+	require_once 'db.php';
 
 	###########################################################
 	# ADDED 2014-03-25 BY JAILOUT2000 FOR SECURITY HOLE PATCH #
diff --git a/newsrss.php b/newsrss.php
index e7fe9af9..5d7d4092 100644
--- a/newsrss.php
+++ b/newsrss.php
@@ -38,8 +38,8 @@ function CropSentence ($strText, $intLength, $strTrail) {
 	} 
 
 	$auth = 'true';
-	include 'functions.php';
-	include 'db.php';
+	require_once 'functions.php';
+	require_once 'db.php';
 	header("Content-Type: application/xml; charset=utf-8");
 	echo '<?xml version="1.0" encoding="utf-8"?>';
 	echo '<rss version="2.0">';
diff --git a/sessionhandler.php b/sessionhandler.php
index fa549bc4..5410e9b8 100644
--- a/sessionhandler.php
+++ b/sessionhandler.php
@@ -5,8 +5,8 @@
 	
 	# Include needed files
 	
-	include 'db.php';
-	include 'functions.php';
+	require_once 'db.php';
+	require_once 'functions.php';
 	
 	# Security
 	
@@ -82,4 +82,4 @@
 	#Terminate.
 	echo "handle session done.";
 	exit();
-?>
\ No newline at end of file
+?>

From 0979b2abddf8da05f4d916996ad0cc2bd538fbf8 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 27 Jul 2014 21:18:07 -0500
Subject: [PATCH 12/54] No Google Adsense.

---
 google_adsense_script.html | 11 -----------
 1 file changed, 11 deletions(-)
 delete mode 100644 google_adsense_script.html

diff --git a/google_adsense_script.html b/google_adsense_script.html
deleted file mode 100644
index 03a62306..00000000
--- a/google_adsense_script.html
+++ /dev/null
@@ -1,11 +0,0 @@
-<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd ">
-<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
-<head>
-<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
-<title></title>
-<script src="http://pagead2.googlesyndication.com/pagead/google_adsense_script.js" type="text/javascript"></script>
-</head>
-<body style="background-color: transparent;">
-</body>
-</html>

From bb748ce9f807c765dec35ddc022ff204b0b7e8f7 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 27 Jul 2014 21:23:46 -0500
Subject: [PATCH 13/54] remove useless files

---
 encryption.php |  9 ---------
 hosting.php    | 11 ----------
 image.php      | 54 --------------------------------------------------
 test.php       |  3 ---
 4 files changed, 77 deletions(-)
 delete mode 100644 encryption.php
 delete mode 100644 hosting.php
 delete mode 100644 image.php
 delete mode 100644 test.php

diff --git a/encryption.php b/encryption.php
deleted file mode 100644
index b34fb04e..00000000
--- a/encryption.php
+++ /dev/null
@@ -1,9 +0,0 @@
-<?
-	$str = 'This is a string.';
-	echo 'Before encoding: '.$str.'<br>';
-	$str = base64_encode($str);
-	echo 'After encoding: '.$str.'<br>';
-	$str = base64_decode($str);
-	echo 'After decoding using base64_decode: '.$str.'<br>';
-	echo 'Done.';
-?>
\ No newline at end of file
diff --git a/hosting.php b/hosting.php
deleted file mode 100644
index 04fd3b8f..00000000
--- a/hosting.php
+++ /dev/null
@@ -1,11 +0,0 @@
-Click the below button to subscribe to Demented Minds hosting.<br>
-<br>
-<font color=red>Unauthorized subscriptions will be refunded, minus paypal fees.</font><br>
-<br>
-<form action="https://www.paypal.com/cgi-bin/webscr" method="post">
-<input type="hidden" name="cmd" value="_s-xclick">
-<input type="image" src="https://www.paypal.com/en_US/i/btn/x-click-but20.gif" border="0" name="submit" alt="Make payments with PayPal - it's fast, free and secure!">
-<img alt="" border="0" src="https://www.paypal.com/en_US/i/scr/pixel.gif" width="1" height="1">
-<input type="hidden" name="encrypted" value="-----BEGIN PKCS7-----MIIHkAYJKoZIhvcNAQcEoIIHgTCCB30CAQExggEwMIIBLAIBADCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwDQYJKoZIhvcNAQEBBQAEgYC95Hs7SUdUt8c7Sr9Vjy29msfjdot2DllM0659KT8OIEGjI5KnIs0e88ok6XftHU7zzb8MvgHh2H66hxMP7ovmZqvq9OgtMp8EwZHeRCQCtHm2+dcxxQJ07kxa8ujXrDfdKzqkrVudk9brjYi69AH6RBBcLoh1+YZJ1vSUObmGWTELMAkGBSsOAwIaBQAwggEMBgkqhkiG9w0BBwEwFAYIKoZIhvcNAwcECPDwoU8WS7SjgIHonjN/Q1WdIq/w6e7+cGe20kdElC2X7dp8Q4UKX/npS6m8b1sW2cUtEcsNg0Q7Q8/Au/7ddyF+dppDV/4ygHijY+xnkTY/Rbs6Q7WpXTYWJtE6GJAGw1aMIiPj4nILGiB8QhJusQIwzdGI6LmQalFgYi0QSk8B8KrDaXH3RSQHA7vm0aHrQxcYiHtDbb0BnFdR6ZaET2G5pp2FN+BV+MjTmFFRi1OtgCE2/k47NQ7f4ZP9LTDP27DKwSNakS+ns4Yk2SaxBKCLjf0d/0n1w435nLedfLA9yrOKUTNL+GEKCWYjEBe4ru1BB6CCA4cwggODMIIC7KADAgECAgEAMA0GCSqGSIb3DQEBBQUAMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTAeFw0wNDAyMTMxMDEzMTVaFw0zNTAyMTMxMDEzMTVaMIGOMQswCQYDVQQGEwJVUzELMAkGA1UECBMCQ0ExFjAUBgNVBAcTDU1vdW50YWluIFZpZXcxFDASBgNVBAoTC1BheVBhbCBJbmMuMRMwEQYDVQQLFApsaXZlX2NlcnRzMREwDwYDVQQDFAhsaXZlX2FwaTEcMBoGCSqGSIb3DQEJARYNcmVAcGF5cGFsLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwUdO3fxEzEtcnI7ZKZL412XvZPugoni7i7D7prCe0AtaHTc97CYgm7NsAtJyxNLixmhLV8pyIEaiHXWAh8fPKW+R017+EmXrr9EaquPmsVvTywAAE1PMNOKqo2kl4Gxiz9zZqIajOm1fZGWcGS0f5JQ2kBqNbvbg2/Za+GJ/qwUCAwEAAaOB7jCB6zAdBgNVHQ4EFgQUlp98u8ZvF71ZP1LXChvsENZklGswgbsGA1UdIwSBszCBsIAUlp98u8ZvF71ZP1LXChvsENZklGuhgZSkgZEwgY4xCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJDQTEWMBQGA1UEBxMNTW91bnRhaW4gVmlldzEUMBIGA1UEChMLUGF5UGFsIEluYy4xEzARBgNVBAsUCmxpdmVfY2VydHMxETAPBgNVBAMUCGxpdmVfYXBpMRwwGgYJKoZIhvcNAQkBFg1yZUBwYXlwYWwuY29tggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADgYEAgV86VpqAWuXvX6Oro4qJ1tYVIT5DgWpE692Ag422H7yRIr/9j/iKG4Thia/Oflx4TdL+IFJBAyPK9v6zZNZtBgPBynXb048hsP16l2vi0k5Q2JKiPDsEfBhGI+HnxLXEaUWAcVfCsQFvd2A1sxRr67ip5y2wwBelUecP3AjJ+YcxggGaMIIBlgIBATCBlDCBjjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAkNBMRYwFAYDVQQHEw1Nb3VudGFpbiBWaWV3MRQwEgYDVQQKEwtQYXlQYWwgSW5jLjETMBEGA1UECxQKbGl2ZV9jZXJ0czERMA8GA1UEAxQIbGl2ZV9hcGkxHDAaBgkqhkiG9w0BCQEWDXJlQHBheXBhbC5jb20CAQAwCQYFKw4DAhoFAKBdMBgGCSqGSIb3DQEJAzELBgkqhkiG9w0BBwEwHAYJKoZIhvcNAQkFMQ8XDTA3MDQyNzE5MjAyN1owIwYJKoZIhvcNAQkEMRYEFHuZmDhYLQngG3UF/aRkZLfQBAF6MA0GCSqGSIb3DQEBAQUABIGAQ5gqOLTV4wVgnNUihKxNPJUZ6a+GmGfwy4fw2ZVUq4z/U96TszVx9MrSnS01L7jz/J/mI2W37/2zyauJvWYSbpFeoTG51qOP681B7pAHGw9vHaRSczI+D3w+KE7BoJquWeiiOj2kGMLOY3DoffTPlYxEbUPxOAvuGkiY4n0lew0=-----END PKCS7-----
-">
-</form>
\ No newline at end of file
diff --git a/image.php b/image.php
deleted file mode 100644
index 3c9babb2..00000000
--- a/image.php
+++ /dev/null
@@ -1,54 +0,0 @@
-<?php
-
-//Say the image file name is in the 
-//$origpng variable. Get the dimensions.
-
-$origpng = 'bnlsicon.png';
-
-$imgsize = getimagesize($origpng);
-
-$newheight = round($imgsize[1]);
-
-$newwidth = round($imgsize[0]);
-
-//Initialize the image.
-
-$image = imagecreatefrompng($origpng);
-
-//Initialize the new image.
-
-#echo $newheight.' '.$newwidth;
-#die();
-$newimage = imagecreate($newwidth, $newheight);
-
-//Allocate some nice black space.
-
-$black = imagecolorallocate($image, 0,0,0);
-
-//Resize the old image into the new image, 
-//specifying starting points and dimensions.
-
-imagecopyresized($newimage, $image, 0, 0, 0, 0, $newwidth, $newheight, $imgsize[0], $imgsize[1]);
-
-//Get rid of the old image.
-
-imagedestroy($image);
-
-//Now, the message -- the second argument, 
-//a number from 1-5, specifies a built-in font. 
-//Or you can load your own with ImageLoadFont().
-//We'll put it in the upper right with coordinates of 10,10.
-
-imagestring($newimage, 2, 10, 10, "Copyright 2001", $black);
-
-//All righty, let's wrap things up here.
-
-header("Content-type: image/png");
-
-imagepng($newimage);
-
-imagedestroy($newimage);
-
-//Voila!
-
-?>
\ No newline at end of file
diff --git a/test.php b/test.php
deleted file mode 100644
index 86c96987..00000000
--- a/test.php
+++ /dev/null
@@ -1,3 +0,0 @@
-<?
-	echo $_REQUEST['direction'];
-?>
\ No newline at end of file

From bc6eb089e256474aa27b363d5b10999fa30a4c4a Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 27 Jul 2014 21:24:03 -0500
Subject: [PATCH 14/54] updated robots.txt file

---
 robots.txt | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/robots.txt b/robots.txt
index 24774089..8f55e22c 100644
--- a/robots.txt
+++ b/robots.txt
@@ -1,6 +1,12 @@
 User-agent: *
+Disallow: /?op=doc&mode=delete
+Disallow: /?op=doc&mode=edit
+Disallow: /?op=packet&mode=delete
+Disallow: /?op=packet&mode=edit
+Disallow: /?op=viewlogs
 Disallow: /index.php?op=doc&mode=delete
 Disallow: /index.php?op=doc&mode=edit
 Disallow: /index.php?op=packet&mode=delete
 Disallow: /index.php?op=packet&mode=edit
+Disallow: /index.php?op=viewlogs
 Disallow: /logsrss.php

From 90ccb268834652d3ab120316811f3d7633407e26 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 27 Jul 2014 21:29:07 -0500
Subject: [PATCH 15/54] New Relic IP address tracking.

---
 index.php | 1 +
 1 file changed, 1 insertion(+)

diff --git a/index.php b/index.php
index 0db2b7c7..40f8fee1 100644
--- a/index.php
+++ b/index.php
@@ -97,6 +97,7 @@ function stripslashes_deep($value) {
                   } else {
                     newrelic_name_transaction("/" . $op . ".php");
                   }
+                  newrelic_add_custom_parameter("REMOTE_ADDR", $_SERVER["REMOTE_ADDR"]);
                 }
 
 	# Surpress code is in place to prevent a HEADER ALREADY SENT error.

From 5d14d86adc2f64f65289286817506da847f6a812 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Wed, 6 Aug 2014 01:46:34 -0500
Subject: [PATCH 16/54] Disable register.php and resetpw.php to stop bots from
 attempting to use them, which is causing errors to appear in new relic.

---
 register.php | 5 +++++
 resetpw.php  | 5 +++++
 2 files changed, 10 insertions(+)

diff --git a/register.php b/register.php
index 5aa612a1..7aeaa763 100644
--- a/register.php
+++ b/register.php
@@ -4,6 +4,11 @@
 	global $auth, $ip;
 	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
 	
+	# Registration disabled due to admin account somehow being hijacked
+	$ret = "Registration has been disabled due to system being under extended maintenance.";
+	error($ret);
+        return;
+
 	# Begin Code
 	# -------------
 
diff --git a/resetpw.php b/resetpw.php
index 486f6021..f8bcd434 100644
--- a/resetpw.php
+++ b/resetpw.php
@@ -4,6 +4,11 @@
 	global $auth, $ip;
 	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
 	
+	# Reset password disabled due to admin account somehow being hijacked
+	$ret = "Reset password has been disabled due to system being under extended maintenance.";
+	error($ret);
+        return;
+
 	# Begin Code
 	# -------------
 

From e32c979bc9c772f0b76b99e1221ac4b740268b98 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 16 Aug 2014 14:38:40 -0500
Subject: [PATCH 17/54] Added a README for those who stumble on this branch.

---
 README.md | 6 ++++++
 1 file changed, 6 insertions(+)
 create mode 100644 README.md

diff --git a/README.md b/README.md
new file mode 100644
index 00000000..a5274703
--- /dev/null
+++ b/README.md
@@ -0,0 +1,6 @@
+BNETDocs: Redux
+===============
+
+This branch consists of the *BNETDocs: Redux* source code. This code is considered *ancient* and should only be modified when necessary or when small updates can be made.
+
+For current source code, view the bnetdocs-web/master branch.

From b962ee116621f104395d55745c295bdffaaec593 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 16 Aug 2014 14:39:22 -0500
Subject: [PATCH 18/54] Formatting of README file

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index a5274703..75302096 100644
--- a/README.md
+++ b/README.md
@@ -3,4 +3,4 @@ BNETDocs: Redux
 
 This branch consists of the *BNETDocs: Redux* source code. This code is considered *ancient* and should only be modified when necessary or when small updates can be made.
 
-For current source code, view the bnetdocs-web/master branch.
+For current source code, view the bnetdocs-web@master branch.

From 5140b1fca3c8b66b3da89c00886958737564769c Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 16 Aug 2014 14:41:04 -0500
Subject: [PATCH 19/54] Formatting of README file again

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 75302096..63c67cbb 100644
--- a/README.md
+++ b/README.md
@@ -3,4 +3,4 @@ BNETDocs: Redux
 
 This branch consists of the *BNETDocs: Redux* source code. This code is considered *ancient* and should only be modified when necessary or when small updates can be made.
 
-For current source code, view the bnetdocs-web@master branch.
+For current source code, [view the master branch](https://github.com/Jailout2000/bnetdocs-web/tree/master).

From c289e1945fe4b42b1a3167597fef43295f9c6795 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 16 Aug 2014 14:45:14 -0500
Subject: [PATCH 20/54] More formatting changes of the README file

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 63c67cbb..07c80d9d 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 BNETDocs: Redux
 ===============
 
-This branch consists of the *BNETDocs: Redux* source code. This code is considered *ancient* and should only be modified when necessary or when small updates can be made.
+This branch consists of the **BNETDocs: Redux** source code. This code is considered **ancient** and should only be modified when necessary or when small updates can be made.
 
 For current source code, [view the master branch](https://github.com/Jailout2000/bnetdocs-web/tree/master).

From c8759a4ddbfe70f4f71e9f163c295f9bcc7327fc Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 16 Aug 2014 17:48:08 -0500
Subject: [PATCH 21/54] Wording change in README

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 07c80d9d..e4380a39 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
 BNETDocs: Redux
 ===============
 
-This branch consists of the **BNETDocs: Redux** source code. This code is considered **ancient** and should only be modified when necessary or when small updates can be made.
+This branch is the **BNETDocs: Redux** source code. This code is considered **ancient** and should only be modified when necessary or when small updates can be made.
 
 For current source code, [view the master branch](https://github.com/Jailout2000/bnetdocs-web/tree/master).

From 8f08dd99bdbf2f986395532cb0d333858639101f Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Fri, 29 Aug 2014 14:56:18 -0400
Subject: [PATCH 22/54] Add Fight for the Future's Battle for the Net campaign.

---
 bdif/header.dm | 8 ++++++++
 1 file changed, 8 insertions(+)

diff --git a/bdif/header.dm b/bdif/header.dm
index 8f8a58c8..06ffbbf4 100644
--- a/bdif/header.dm
+++ b/bdif/header.dm
@@ -4,6 +4,7 @@
   $FFTF_DATE            = date('Y-m-d');
   $FFTF_STOPTHESLOWLANE = ($FFTF_DATE == '2014-05-15');
   $FFTF_RESETTHENET     = ($FFTF_DATE == '2014-06-05');
+  $FFTF_BATTLEFORTHENET = ($FFTF_DATE == '2014-09-10');
 
 ?>
 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
@@ -82,6 +83,13 @@
 	<script src="https://fightforthefuture.github.io/stoptheslowlane/widget/slowlane.js"></script>
     <?
   } // END OF STOP THE SLOW LANE
+  // FIGHT FOR THE FUTURE - BATTLE FOR THE NET (https://www.battleforthenet.com/)
+  if ($FFTF_BATTLEFORTHENET) {
+    ?>
+        <script type="text/javascript">var _bftn_options = { animation: 'banner' }</script>
+        <script src="//fightforthefuture.github.io/battleforthenet-widget/widget.min.js" async></script>
+    <?
+  }
   ?>
 </head>
 <body onload="doonload()">

From c4770ebeb7bfc1143bd1f0ff0ed898396d821e8e Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Wed, 10 Sep 2014 13:50:55 -0400
Subject: [PATCH 23/54] Battle for the Net should be widget instead of banner.

---
 bdif/header.dm | 1 -
 1 file changed, 1 deletion(-)

diff --git a/bdif/header.dm b/bdif/header.dm
index 06ffbbf4..bde5ac9d 100644
--- a/bdif/header.dm
+++ b/bdif/header.dm
@@ -86,7 +86,6 @@
   // FIGHT FOR THE FUTURE - BATTLE FOR THE NET (https://www.battleforthenet.com/)
   if ($FFTF_BATTLEFORTHENET) {
     ?>
-        <script type="text/javascript">var _bftn_options = { animation: 'banner' }</script>
         <script src="//fightforthefuture.github.io/battleforthenet-widget/widget.min.js" async></script>
     <?
   }

From 899ccbdeae344af91e343e5c2328eb96f5edfc8d Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Wed, 10 Sep 2014 13:51:28 -0400
Subject: [PATCH 24/54] Remove https: from the URL for Stop the slow lane
 campaign.

---
 bdif/header.dm | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/bdif/header.dm b/bdif/header.dm
index bde5ac9d..3e7948eb 100644
--- a/bdif/header.dm
+++ b/bdif/header.dm
@@ -80,7 +80,7 @@
       <?
     }
     ?>
-	<script src="https://fightforthefuture.github.io/stoptheslowlane/widget/slowlane.js"></script>
+	<script src="//fightforthefuture.github.io/stoptheslowlane/widget/slowlane.js"></script>
     <?
   } // END OF STOP THE SLOW LANE
   // FIGHT FOR THE FUTURE - BATTLE FOR THE NET (https://www.battleforthenet.com/)

From 9e7242cc7ef1bbcaf46eab0816806f2452d95380 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 19 Oct 2014 21:06:29 -0500
Subject: [PATCH 25/54] Fix vulnerability in page inclusion.

---
 index.php | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/index.php b/index.php
index 40f8fee1..fae4ee30 100644
--- a/index.php
+++ b/index.php
@@ -58,8 +58,12 @@ function stripslashes_deep($value) {
 
 	# REQUEST: Get our requested page and set the variable
 	#-------------
-		
-		$op = $_REQUEST['op'];
+
+                if (isset($_REQUEST["op"]) && is_string($_REQUEST["op"])) {
+  		  $op = $_REQUEST['op'];
+                } else {
+                  $op = "";
+                }
 
 		# Prevent infinite loop bug, bug found by Jailout2000
 		if($op == 'index') $op = '';

From 1618e22e345f39fdff5560c8feb2f623a7c10d02 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 19 Oct 2014 21:22:40 -0500
Subject: [PATCH 26/54] Fix sql injection vulnerability in edit news form.

---
 news.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/news.php b/news.php
index 7629200e..f55a070e 100644
--- a/news.php
+++ b/news.php
@@ -41,7 +41,7 @@
 				logthis($userid, 'Illegally attempted to edit a news post NID('.$nid.'). Attempt blocked.', 'hack');
 				blockhack();
 			}
-			$sqlquery = 'SELECT * FROM news WHERE id='.$nid.' ORDER BY id DESC LIMIT 1';
+			$sqlquery = 'SELECT * FROM news WHERE id='.mysql_real_escape_string($nid).' ORDER BY id DESC LIMIT 1';
 			$newsarray = mysql_query($sqlquery);
 			$row = mysql_fetch_array($newsarray);
 			$author = $row['poster'];

From c41d31fd0169c03b59e4ff504b1285f1d25669a4 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 19 Oct 2014 21:29:45 -0500
Subject: [PATCH 27/54] Replace logthis() with New Relic monitoring.

---
 functions.php | 14 +++++++++-----
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/functions.php b/functions.php
index 34281bb6..7635c171 100644
--- a/functions.php
+++ b/functions.php
@@ -921,11 +921,15 @@ function rankname($rank){
 	}
 	
 	#known types: session
-	function logthis($userid, $event, $type){
-		$event = sanitize($event);
-		$datetime = date("l, F d Y");
-		$ip = $_SERVER['REMOTE_ADDR'];
-		mysql_query("INSERT INTO logs (user,event,eventtype, datetime,ip) VALUES ('$userid','$event','$type','$datetime','$ip')") or die("Logthis Function Error: ".mysql_error());
+        function logthis($userid, $event, $type){
+                if (extension_loaded("newrelic")) {
+                  newrelic_notice_error(json_encode("userid" => $userid, "event" => $event, "type" => $type, "datetime" => date("r"), "ip" => $_SERVER["REMOTE_ADDR"]));
+                } else {
+                  $event = sanitize($event);
+                  $datetime = date("l, F d Y");
+                  $ip = $_SERVER['REMOTE_ADDR'];
+                  mysql_query("INSERT INTO logs (user,event,eventtype, datetime,ip) VALUES ('$userid','$event','$type','$datetime','$ip')") or die("Logthis Function Error: ".mysql_error());
+                }
 	}
 
 	function curPageURL() {

From b2ea0ed4e4291325d586c69dbd92c78fa4332bf3 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 19 Oct 2014 21:30:40 -0500
Subject: [PATCH 28/54] Forgot to surround code with array().

---
 functions.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/functions.php b/functions.php
index 7635c171..0f24fb23 100644
--- a/functions.php
+++ b/functions.php
@@ -923,7 +923,7 @@ function rankname($rank){
 	#known types: session
         function logthis($userid, $event, $type){
                 if (extension_loaded("newrelic")) {
-                  newrelic_notice_error(json_encode("userid" => $userid, "event" => $event, "type" => $type, "datetime" => date("r"), "ip" => $_SERVER["REMOTE_ADDR"]));
+                  newrelic_notice_error(json_encode(array("userid" => $userid, "event" => $event, "type" => $type, "datetime" => date("r"), "ip" => $_SERVER["REMOTE_ADDR"])));
                 } else {
                   $event = sanitize($event);
                   $datetime = date("l, F d Y");

From 177100fd59d53d17fe24c3cc3e21220f274951a6 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 19 Oct 2014 21:36:07 -0500
Subject: [PATCH 29/54] Fix sql injection vulnerability in edit doc form.

---
 doc.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc.php b/doc.php
index 2ec369f0..755e2a44 100644
--- a/doc.php
+++ b/doc.php
@@ -454,7 +454,7 @@
 				<h2>User Comments</h2>
 				<center><br>For detailed questions and discussion, visit the <a href="http://forum.valhallalegends.com/index.php/board,17.0.html" target="_blank">Battle.net Research Forum</a><br><br></center>
 				<?
-				$sqlqueryz = 'SELECT id,posterid,UNIX_TIMESTAMP(dtstamp) as unixdtstamp,message FROM comments WHERE pdid='.$did.' ORDER BY id';
+				$sqlqueryz = 'SELECT id,posterid,UNIX_TIMESTAMP(dtstamp) as unixdtstamp,message FROM comments WHERE pdid='.mysql_real_escape_string($did).' ORDER BY id';
 				$docarray = mysql_query($sqlqueryz);
 				$commentcount = 0;
 				while($rowz = mysql_fetch_array($docarray)){

From 4c422435ab0f9b3cfc427144a782dc9faa238869 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 19 Oct 2014 21:46:43 -0500
Subject: [PATCH 30/54] Block attempts to edit invalid news posts.

---
 news.php | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/news.php b/news.php
index f55a070e..a87d348d 100644
--- a/news.php
+++ b/news.php
@@ -36,6 +36,10 @@
 			}
 		} elseif($mode == 'edit'){
 			$nid = $_GET['nid'];
+                        if (!is_numeric($nid)) {
+                                logthis($userid, 'Illegally attempted to edit a news post with invalid NID. Attempt blocked.', 'hack');
+                                blockhack();
+                        }
 			$pid = GetInfo("news", "id", $nid, "poster");
 			if($userid != $pid && $userid != 1){
 				logthis($userid, 'Illegally attempted to edit a news post NID('.$nid.'). Attempt blocked.', 'hack');

From 3fc7372ea598a37306254563a695962e062a9f62 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 19 Oct 2014 21:54:42 -0500
Subject: [PATCH 31/54] Fix sql injection vulnerability in news.

---
 viewlogs.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/viewlogs.php b/viewlogs.php
index 99601bc4..e80b002b 100644
--- a/viewlogs.php
+++ b/viewlogs.php
@@ -52,9 +52,9 @@
 	
 	if($id && !$mode){
 		$limit = 1;
-		$orderby = 'WHERE id='.$id;
+		$orderby = 'WHERE id='.mysql_real_escape_string($id);
 		$specific = true;
-		$query  = "SELECT * FROM logs WHERE id=$id";
+		$query  = "SELECT * FROM logs WHERE id=".mysql_real_escape_string($id);
 	}
 
     if($page < 1){

From 9ea94b4dd7ea087f95023cb92444234200dd003d Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Mon, 24 Nov 2014 03:50:11 -0600
Subject: [PATCH 32/54] Fix sql query error discovered by Bingbot via New Relic
 where did is non-numeric.

---
 doc.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc.php b/doc.php
index 755e2a44..23ac60b6 100644
--- a/doc.php
+++ b/doc.php
@@ -454,7 +454,7 @@
 				<h2>User Comments</h2>
 				<center><br>For detailed questions and discussion, visit the <a href="http://forum.valhallalegends.com/index.php/board,17.0.html" target="_blank">Battle.net Research Forum</a><br><br></center>
 				<?
-				$sqlqueryz = 'SELECT id,posterid,UNIX_TIMESTAMP(dtstamp) as unixdtstamp,message FROM comments WHERE pdid='.mysql_real_escape_string($did).' ORDER BY id';
+				$sqlqueryz = 'SELECT id,posterid,UNIX_TIMESTAMP(dtstamp) as unixdtstamp,message FROM comments WHERE pdid=\''.mysql_real_escape_string($did).'\' ORDER BY id';
 				$docarray = mysql_query($sqlqueryz);
 				$commentcount = 0;
 				while($rowz = mysql_fetch_array($docarray)){

From 8b617d6d2fc1da11786e3e07cff9b848e9895653 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Mon, 24 Nov 2014 05:04:34 -0600
Subject: [PATCH 33/54] Add basic caching to alleviate load on database.

---
 functions.php | 9 +++++++--
 1 file changed, 7 insertions(+), 2 deletions(-)

diff --git a/functions.php b/functions.php
index 0f24fb23..767bff5a 100644
--- a/functions.php
+++ b/functions.php
@@ -351,12 +351,17 @@ function BlockHack(){
 	# $data = The field where you want to obtain the data from.
 	# --------------------
 		function GetInfo($db, $index, $id, $data){
-			$sqlquery = mysql_query("SELECT * FROM `$db` WHERE `$index`=\"$id\" LIMIT 1") or die('Attempted Query: '."SELECT * FROM `$db` WHERE `$index`='$id' LIMIT 1"."<br>GetInfo Function Error: ".mysql_error());;
+	                static $cache = [];
+	                $str = $db.$index.$id.$data;
+	                if (isset($cache[$str])) return $cache[$str];
+	                $sqlquery = mysql_query("SELECT * FROM `$db` WHERE `$index`=\"$id\" LIMIT 1") or die('Attempted Query: '."SELECT * FROM `$db` WHERE `$index`='$id' LIMIT 1"."<br>GetInfo Function Error: ".mysql_error());;
 			if(mysql_num_rows($sqlquery) > 0) {
 				$ret = mysql_result($sqlquery,0,$data);
 			} else {
 				$ret = false;
-			}
+	                }
+
+	                $cache[$str] = $ret;
 			return $ret;
 		}
 	#-------------

From cc226eab36bb779d0722d374cf43153c1209ee2c Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Fri, 8 May 2015 21:53:34 +0000
Subject: [PATCH 34/54] Don't store passwords in the repository

---
 .gitignore         |  2 ++
 config.sample.json | 10 ++++++++++
 db.php             | 10 +++++-----
 index.php          |  1 +
 4 files changed, 18 insertions(+), 5 deletions(-)
 create mode 100644 .gitignore
 create mode 100644 config.sample.json

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 00000000..e5eb5d47
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/cache/bnetdocsredux.txt
+/config.json
diff --git a/config.sample.json b/config.sample.json
new file mode 100644
index 00000000..eeacbe69
--- /dev/null
+++ b/config.sample.json
@@ -0,0 +1,10 @@
+{
+  "database": {
+    "character_set": "utf8",
+    "collation": "utf8_general_ci",
+    "hostname": "localhost",
+    "name": "bnetdocs_botdev",
+    "password": "",
+    "username": "bnetdocs"
+  }
+}
diff --git a/db.php b/db.php
index b5d28eba..48bc8eba 100644
--- a/db.php
+++ b/db.php
@@ -11,12 +11,12 @@
 	# Begin Code
 	# -------------
 
-	$dbhost = 'localhost';
-	$dbusername = 'bnetdocs';
-	$dbpasswd = 'redux123';
-	$database_name = 'bnetdocs_botdev';
+	$dbhost = $config->database->hostname;
+	$dbusername = $config->database->username;
+	$dbpasswd = $config->database->password;
+	$database_name = $config->database->name;
 
 	@$connection = mysql_connect("$dbhost","$dbusername","$dbpasswd") or die ("Couldn't connect to server because ".mysql_error());
 	@$db = mysql_select_db("$database_name", $connection) or die("Couldn't select database because ".mysql_error());
-	@mysql_query('SET NAMES utf8 COLLATE utf8_general_ci;');
+	@mysql_query('SET NAMES ' . $config->database->character_set . ' COLLATE ' . $config->database->collate . ';');
 ?>
diff --git a/index.php b/index.php
index fae4ee30..08cce2ed 100644
--- a/index.php
+++ b/index.php
@@ -48,6 +48,7 @@ function stripslashes_deep($value) {
 	# Include essential files
 	#-------------
 
+                $config = json_decode(file_get_contents("./config.json"));
 		require_once 'db.php';
 		require_once 'functions.php';
 		

From ed3acc0f0b9cbf47a12d741e1dd31f9cb26587b3 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Fri, 8 May 2015 22:55:46 +0000
Subject: [PATCH 35/54] Fix typo

---
 db.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/db.php b/db.php
index 48bc8eba..6b3cddc8 100644
--- a/db.php
+++ b/db.php
@@ -18,5 +18,5 @@
 
 	@$connection = mysql_connect("$dbhost","$dbusername","$dbpasswd") or die ("Couldn't connect to server because ".mysql_error());
 	@$db = mysql_select_db("$database_name", $connection) or die("Couldn't select database because ".mysql_error());
-	@mysql_query('SET NAMES ' . $config->database->character_set . ' COLLATE ' . $config->database->collate . ';');
+	@mysql_query('SET NAMES ' . $config->database->character_set . ' COLLATE ' . $config->database->collation . ';');
 ?>

From 07aad69424af4ef4e419ada5deac04234ebf6a85 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Tue, 26 May 2015 01:28:41 +0000
Subject: [PATCH 36/54] Fix whitespace

---
 index.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/index.php b/index.php
index 08cce2ed..10d78575 100644
--- a/index.php
+++ b/index.php
@@ -48,7 +48,7 @@ function stripslashes_deep($value) {
 	# Include essential files
 	#-------------
 
-                $config = json_decode(file_get_contents("./config.json"));
+		$config = json_decode(file_get_contents("./config.json"));
 		require_once 'db.php';
 		require_once 'functions.php';
 		

From c59fe2908fa50c11dca4a297808f4becc93d9812 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Tue, 26 May 2015 01:35:52 +0000
Subject: [PATCH 37/54] Rename config file to branch specific.

---
 .gitignore | 3 ++-
 index.php  | 2 +-
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/.gitignore b/.gitignore
index e5eb5d47..66f114e4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 /cache/bnetdocsredux.txt
-/config.json
+/config.phoenix.json
+/config.redux.json
diff --git a/index.php b/index.php
index 10d78575..2b32af5d 100644
--- a/index.php
+++ b/index.php
@@ -48,7 +48,7 @@ function stripslashes_deep($value) {
 	# Include essential files
 	#-------------
 
-		$config = json_decode(file_get_contents("./config.json"));
+		$config = json_decode(file_get_contents("./config.redux.json"));
 		require_once 'db.php';
 		require_once 'functions.php';
 		

From 0c6ae84a72918d6a5b3f5b2e93900f82585b4304 Mon Sep 17 00:00:00 2001
From: xboi209 <xboi209@users.noreply.github.com>
Date: Thu, 28 May 2015 11:45:05 -0700
Subject: [PATCH 38/54] Update standard.js

formatting
---
 js/standard.js | 320 +++++++++++++++++++++++++++----------------------
 1 file changed, 179 insertions(+), 141 deletions(-)

diff --git a/js/standard.js b/js/standard.js
index 3b5d8efe..263edafa 100644
--- a/js/standard.js
+++ b/js/standard.js
@@ -1,162 +1,200 @@
-
-
-
-
-
-/*
-     FILE ARCHIVED ON 22:40:13 Sep 10, 2011 AND RETRIEVED FROM THE
-     INTERNET ARCHIVE ON 8:41:31 Mar 24, 2014.
-     JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
-
-     ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
-     SECTION 108(a)(3)).
-*/
-	var pagecode = "";
-
-	function scheck(field) {
-		for (i = 0; i < field.length; i++) {
-			field[i].checked = false; 
-		}
-		alert('definitely being executed');
-		return true;
+/*
+ FILE ARCHIVED ON 22:40:13 Sep 10, 2011 AND RETRIEVED FROM THE
+ INTERNET ARCHIVE ON 8:41:31 Mar 24, 2014.
+ JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE.
+
+ ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C.
+ SECTION 108(a)(3)).
+*/
+var pagecode = "";
+
+function scheck(field)
+{
+	for (i = 0; i < field.length; i++)
+	{
+		field[i].checked = false; 
 	}
-	
+	alert('definitely being executed');
+
+	return true;
+}
 
-	function doonload(){
-		if(document.createStyleSheet) {
-			document.createStyleSheet('/web/20110910224013/http://bnetdocs.dementedminds.net/bdif/js_hide.css');
-		} else {
-			var styles = "@import url(' /web/20110910224013/http://bnetdocs.dementedminds.net/bdif/js_hide.css ');";
-			var newSS=document.createElement('link');
-			newSS.rel='stylesheet';
-			newSS.href='data:text/css,'+escape(styles);
-			document.getElementsByTagName("head")[0].appendChild(newSS);
-		}
-		
-		//document.cookie='hidden='+"";
-		var hidden=get_cookie("hidden");
-		var divid="";
-		if(hidden != ""){
-			// Process
-			var i=0
-			for (i=0; i<=hidden.length; i=i+2){
-				// Open Div's
-				divid = hidden.substr(i,2);
-				toggle_visibility(divid);
-				toggleHLS('x'+hidden.charAt(i+1)+'1');
-			}
-		}
-		
 
+function doonload()
+{
+	if(document.createStyleSheet)
+	{
+		document.createStyleSheet('/web/20110910224013/http://bnetdocs.dementedminds.net/bdif/js_hide.css');
+	}
+	else
+	{
+		var styles = "@import url(' /web/20110910224013/http://bnetdocs.dementedminds.net/bdif/js_hide.css ');";
+		var newSS=document.createElement('link');
+		newSS.rel='stylesheet';
+		newSS.href='data:text/css,'+escape(styles);
+		document.getElementsByTagName("head")[0].appendChild(newSS);
 	}
 	
-	function toggleHLS(id) {
-	    var e = document.getElementById(id);
-		if(e){
-			toggle_name(e);
+	//document.cookie='hidden='+"";
+	var hidden=get_cookie("hidden");
+	var divid="";
+	if(hidden != "")
+	{
+		// Process
+		var i=0
+		for (i=0; i<=hidden.length; i=i+2)
+		{
+			// Open Div's
+			divid = hidden.substr(i,2);
+			toggle_visibility(divid);
+			toggleHLS('x'+hidden.charAt(i+1)+'1');
 		}
-		return;
 	}
 	
-	function toggle_visibility(id) {
-        var e = document.getElementById(id);
-		if(e){
-	        if(e.style.display == 'block'){
-				e.style.display = 'none';
-				forgetid(id);
-	        } else {
-				e.style.display = 'block';
-				rememberid(id);
-			}
+
+}
+
+function toggleHLS(id)
+{
+	var e = document.getElementById(id);
+	if(e)
+	{
+		toggle_name(e);
+	}
+
+	return;
+}
+
+function toggle_visibility(id)
+{}
+	var e = document.getElementById(id);
+	if(e)
+	{
+		if(e.style.display == 'block')
+		{
+			e.style.display = 'none';
+			forgetid(id);
 		}
-		return;
-    }
-	
-	function rememberid(did){
-		var hidden=get_cookie("hidden");
-		var newmemory = '';
-		var alreadyadded = "false";
-		var did = did + '';
-		hidden = hidden + '';
-		if(hidden != ""){
-			if(hidden.search(did) < 0){ 
-				document.cookie='hidden='+hidden+did;
-			}
-		} else {
-			document.cookie='hidden='+did;
+		else
+		{
+			e.style.display = 'block';
+			rememberid(id);
 		}
 	}
-	
-	function forgetid(did){
-		var hidden=get_cookie("hidden");
-		var newmemory = '';
-		var did = did + '';
-		newmemory = hidden.replace(did,'');
-		document.cookie='hidden='+newmemory;
+
+	return;
+}
+
+function rememberid(did)
+{
+	var hidden=get_cookie("hidden");
+	var newmemory = '';
+	var alreadyadded = "false";
+	var did = did + '';
+	hidden = hidden + '';
+	if(hidden != "")
+	{
+		if(hidden.search(did) < 0)
+		{ 
+			document.cookie='hidden='+hidden+did;
+		}
 	}
-	
-	//Get cookie routine by Shelley Powers 
-	function get_cookie(Name) {
-		var search = Name + "="
-		var returnvalue = "";
-		if (document.cookie.length > 0) {
-			offset = document.cookie.indexOf(search)
-			// if cookie exists
-			if (offset != -1) { 
-				offset += search.length
-				// set index of beginning of value
-				end = document.cookie.indexOf(";", offset);
-				// set index of end of cookie value
-				if (end == -1) end = document.cookie.length;
-				returnvalue=unescape(document.cookie.substring(offset, end))
-			}
+	else
+	{
+		document.cookie='hidden='+did;
+	}
+}
+
+function forgetid(did)
+{
+	var hidden=get_cookie("hidden");
+	var newmemory = '';
+	var did = did + '';
+	newmemory = hidden.replace(did,'');
+	document.cookie='hidden='+newmemory;
+}
+
+//Get cookie routine by Shelley Powers 
+function get_cookie(Name)
+{
+	var search = Name + "="
+	var returnvalue = "";
+	if (document.cookie.length > 0)
+	{
+		offset = document.cookie.indexOf(search)
+		// if cookie exists
+		if (offset != -1)
+		{ 
+			offset += search.length
+			// set index of beginning of value
+			end = document.cookie.indexOf(";", offset);
+			// set index of end of cookie value
+			if (end == -1) end = document.cookie.length;
+			returnvalue=unescape(document.cookie.substring(offset, end))
 		}
-		return returnvalue;
 	}
-	
-	function toggle_name(objLink){
-		if(objLink.innerHTML == "+")
-			objLink.innerHTML = "-";
+
+	return returnvalue;
+}
+
+function toggle_name(objLink)
+{
+	if(objLink.innerHTML == "+")
+		objLink.innerHTML = "-";
+	else
+		objLink.innerHTML = "+";
+}
+
+function validate_required(field,alerttxt)
+{
+	with (field)
+	{
+		if (value==null || value=="")
+		{
+			alert(alerttxt);
+			return false
+		}
 		else
-			objLink.innerHTML = "+";
-	}
-	
-	function validate_required(field,alerttxt){
-		with (field){
-			if (value==null||value==""){
-				alert(alerttxt);
-				return false
-			} else {
-				return true
-			}
+		{
+			return true
 		}
 	}
-	
-	function validate_form(thisform){
-		with (thisform){
-			if (validate_required(username,"Username must be filled out!")==false){
-				username.focus();
-				return false
-			}
-			if (validate_required(password,"Password must be filled out!")==false){
-				password.focus();
-				return false
-			}
+}
 
+function validate_form(thisform)
+{
+	with (thisform)
+	{
+		if (validate_required(username,"Username must be filled out!") == false)
+		{
+			username.focus();
+			return false
+		}
+		if (validate_required(password,"Password must be filled out!") == false)
+		{
+			password.focus();
+			return false
 		}
+
 	}
-	
-	function showimage(){
-		if (!document.images) return
-		var picdir = '/images/newsicon/';
-		document.images.thepic.src = picdir + document.thenews.pictureselector.options[document.thenews.pictureselector.selectedIndex].value + 'icon.png';
+}
+
+function showimage()
+{
+	if (!document.images) return
+	var picdir = '/images/newsicon/';
+	document.images.thepic.src = picdir + document.thenews.pictureselector.options[document.thenews.pictureselector.selectedIndex].value + 'icon.png';
+}
+
+function confimdelete()
+{
+	var confirmation = confirm ("Please confirm deletion.");
+	if (confirmation)
+	{
+		return true;
 	}
-	
-	function confimdelete(){
-		var confirmation = confirm ("Please confirm deletion.");
-		if (confirmation){
-			return true;
-		} else {
-			return false;
-		}
-	}
\ No newline at end of file
+	else
+	{
+		return false;
+	}
+}

From 3a3509307f7f8b6159b3cb4541d830565b33f70c Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 20 Jun 2015 10:39:09 +0000
Subject: [PATCH 39/54] Fix issue with generatedocs.php

- The `$config` variable wasn't defined in `generatedocs.php` since it
  was being set in the `index.php` and `generatedocs.php` is called
  directly.
- To fix, we move `$config` to the `functions.php` which is included
  everywhere.
---
 functions.php | 1 +
 index.php     | 3 +--
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/functions.php b/functions.php
index 767bff5a..ce051006 100644
--- a/functions.php
+++ b/functions.php
@@ -10,6 +10,7 @@
 	
 	# Begin Code
 	# -------------
+	$config = json_decode(file_get_contents("./config.redux.json"));
 	
 	# DisplayDialogBox Function
 	# --------------------
diff --git a/index.php b/index.php
index 2b32af5d..c9224b01 100644
--- a/index.php
+++ b/index.php
@@ -48,9 +48,8 @@ function stripslashes_deep($value) {
 	# Include essential files
 	#-------------
 
-		$config = json_decode(file_get_contents("./config.redux.json"));
-		require_once 'db.php';
 		require_once 'functions.php';
+		require_once 'db.php';
 		
 	# Block out unwelcome visitors
 	#-------------

From 9ee51597ac2f01e6ab3527259fc079ef01d8d25d Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Mon, 31 Aug 2015 03:56:58 +0000
Subject: [PATCH 40/54] Update README

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index e4380a39..8c59d726 100644
--- a/README.md
+++ b/README.md
@@ -3,4 +3,4 @@ BNETDocs: Redux
 
 This branch is the **BNETDocs: Redux** source code. This code is considered **ancient** and should only be modified when necessary or when small updates can be made.
 
-For current source code, [view the master branch](https://github.com/Jailout2000/bnetdocs-web/tree/master).
+For current source code, [view the phoenix-0.2 branch](https://github.com/carlbennett/bnetdocs-web/tree/phoenix-0.2).

From 64dc268829f6aacf48629cdb52703b1c396e8c93 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Mon, 21 Sep 2015 06:52:26 +0000
Subject: [PATCH 41/54] Update README to point at phoenix branch

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 8c59d726..959e0a54 100644
--- a/README.md
+++ b/README.md
@@ -3,4 +3,4 @@ BNETDocs: Redux
 
 This branch is the **BNETDocs: Redux** source code. This code is considered **ancient** and should only be modified when necessary or when small updates can be made.
 
-For current source code, [view the phoenix-0.2 branch](https://github.com/carlbennett/bnetdocs-web/tree/phoenix-0.2).
+For current source code, [view the phoenix branch](https://github.com/carlbennett/bnetdocs-web/tree/phoenix).

From d0bdb5752d6a7339811f128d16b3d89e1520ab40 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 3 Oct 2015 08:16:35 +0000
Subject: [PATCH 42/54] Ignore the /archives/ directory

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 66f114e4..3284c9d1 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/archives/
 /cache/bnetdocsredux.txt
 /config.phoenix.json
 /config.redux.json

From aa363ed3e352a2ed98756cfa6c51d3a12ea4e50a Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Fri, 5 Feb 2016 02:13:03 +0000
Subject: [PATCH 43/54] Remove link to non-existent forums

---
 bdif/header.dm | 1 -
 1 file changed, 1 deletion(-)

diff --git a/bdif/header.dm b/bdif/header.dm
index 3e7948eb..3713cb08 100644
--- a/bdif/header.dm
+++ b/bdif/header.dm
@@ -126,7 +126,6 @@
 		<a href="/?mode=all">View News History</a><br>
 		<a href="generatedocs.php">Download BNETDocs as Text</a><br>
 		<a href="/?op=search">Search BNETDocs</a> &nbsp; <font color=red size=1>Incomplete</font><br>
-		<a href="/forums/">Forums</a><br>
 		<a href="/?op=credits">Credits</a><br>
 		<a href="/archives/" target="_blank">BNETDocs Archives</a><br><br>
         </div></div>

From 3ce1841cb3d7c85f246d760606c20a21d488663c Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Mon, 14 Mar 2016 07:07:37 +0000
Subject: [PATCH 44/54] Add Travis CI to Redux branch

---
 .travis.yml | 20 ++++++++++++++++++++
 1 file changed, 20 insertions(+)
 create mode 100644 .travis.yml

diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 00000000..bf5b93b0
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,20 @@
+language: php
+os:
+  - linux
+sudo: false
+php:
+# - 5.3 (doesn't recognize $var=[], only recognizes $var=array())
+  - 5.4
+  - 5.5
+  - 5.6
+  - 7.0
+  - nightly
+matrix:
+  allow_failures:
+    - php: nightly
+services:
+  - mysql
+before_script:
+  - cp config.sample.json config.redux.json
+script:
+  - bash -c 'set -e;for file in $(find . -type f -regextype posix-extended -regex .*\.\(php\|dm\) -print); do php -e -l -f "$file"; done'

From 9833c4ca28d7c7246c09b868d8723f7a35d05d06 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Tue, 15 Mar 2016 07:06:41 +0000
Subject: [PATCH 45/54] Add link to successor

---
 bdif/header.dm | 1 +
 1 file changed, 1 insertion(+)

diff --git a/bdif/header.dm b/bdif/header.dm
index 3713cb08..aa91338f 100644
--- a/bdif/header.dm
+++ b/bdif/header.dm
@@ -123,6 +123,7 @@
 	<h2>Navigation</h2>
 	<div id="divMain_Menu"><div id="author">Main Menu</div><div class="navmenu" id="bodyMain_Menu">
 		<a href="/">Main Page</a><br>
+		<a href="https://dev.bnetdocs.org/">BNETDocs: Phoenix</a><br>
 		<a href="/?mode=all">View News History</a><br>
 		<a href="generatedocs.php">Download BNETDocs as Text</a><br>
 		<a href="/?op=search">Search BNETDocs</a> &nbsp; <font color=red size=1>Incomplete</font><br>

From 5d0cebc0d3bf39acfc0081e3d43f352ef588b83f Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Wed, 16 Mar 2016 07:55:24 +0000
Subject: [PATCH 46/54] Ignore rsync target file from phoenix branch

---
 .gitignore | 1 +
 1 file changed, 1 insertion(+)

diff --git a/.gitignore b/.gitignore
index 3284c9d1..280426c4 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/.rsync-target
 /archives/
 /cache/bnetdocsredux.txt
 /config.phoenix.json

From fca6d94400e265856004c875ea4afe1b8036a43f Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sun, 3 Apr 2016 11:41:01 +0000
Subject: [PATCH 47/54] Demote redux site to redux.bnetdocs.org

---
 index.php  | 4 ++--
 robots.txt | 1 +
 2 files changed, 3 insertions(+), 2 deletions(-)

diff --git a/index.php b/index.php
index c9224b01..c0a03782 100644
--- a/index.php
+++ b/index.php
@@ -12,9 +12,9 @@
 	#-------------
 
 		header('Cache-Control: max-age=0, must-revalidate, no-cache, no-store');
-		if($_SERVER['SERVER_PORT']!=443 || $_SERVER['HTTP_HOST']!='bnetdocs.org') {
+		if($_SERVER['SERVER_PORT']!=443 || $_SERVER['HTTP_HOST']!='redux.bnetdocs.org') {
 			http_response_code(301);
-			header('Location: https://bnetdocs.org'.$_SERVER['REQUEST_URI']);
+			header('Location: https://redux.bnetdocs.org'.$_SERVER['REQUEST_URI']);
 			exit;
 		}
 
diff --git a/robots.txt b/robots.txt
index 8f55e22c..2f678b8d 100644
--- a/robots.txt
+++ b/robots.txt
@@ -4,6 +4,7 @@ Disallow: /?op=doc&mode=edit
 Disallow: /?op=packet&mode=delete
 Disallow: /?op=packet&mode=edit
 Disallow: /?op=viewlogs
+Disallow: /archives/bhfiles.com/*.orig
 Disallow: /index.php?op=doc&mode=delete
 Disallow: /index.php?op=doc&mode=edit
 Disallow: /index.php?op=packet&mode=delete

From 5223d46d87e45f342787f63b406ed47d6a497f4d Mon Sep 17 00:00:00 2001
From: Carl Bennett <carlbennett@users.noreply.github.com>
Date: Sat, 18 Jun 2016 00:02:07 +0000
Subject: [PATCH 48/54] Add file explaining id columns of comments table

---
 comment-id-columns.txt | 13 +++++++++++++
 1 file changed, 13 insertions(+)
 create mode 100644 comment-id-columns.txt

diff --git a/comment-id-columns.txt b/comment-id-columns.txt
new file mode 100644
index 00000000..2146ef6a
--- /dev/null
+++ b/comment-id-columns.txt
@@ -0,0 +1,13 @@
+id
+posterid
+catid
+subid
+pdid
+
+id       = comment id (unique comment identifier)
+posterid = user id (unique user identifier)
+pdid     = parent id (0 if news, id of document or packet otherwise)
+
+subid    = (0 if non-news, id of news post otherwise)
+catid    = (category; 0 = packet, 1 = news, 2 = document)
+

From ff12e4ac3a35991727e62dc3636bc9d757f73ceb Mon Sep 17 00:00:00 2001
From: Carl Bennett <carl@carlbennett.me>
Date: Mon, 17 Apr 2017 07:54:23 +0000
Subject: [PATCH 49/54] Sync with production

---
 .gitignore                                   |   5 +-
 README.md                                    |   2 +-
 bdif/footer.dm                               |  31 +-
 bdif/header.dm                               |  31 +-
 cache/bnetdocsredux.txt                      | 283 +++----------------
 credits.php                                  |  20 +-
 db.php                                       |   6 +-
 doc.php                                      |  15 +-
 config.sample.json => etc/config.sample.json |   0
 functions.php                                | 156 +++++-----
 generatecode.php                             |  64 +++--
 index.php                                    |  38 +--
 news.php                                     |  38 ++-
 newsrss.php                                  |  18 +-
 packet.php                                   |   7 +-
 register.php                                 |   6 +-
 robots.txt                                   |   1 -
 17 files changed, 256 insertions(+), 465 deletions(-)
 rename config.sample.json => etc/config.sample.json (100%)

diff --git a/.gitignore b/.gitignore
index 280426c4..2e7f470c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,6 @@
 /.rsync-target
 /archives/
 /cache/bnetdocsredux.txt
-/config.phoenix.json
-/config.redux.json
+/etc/config.phoenix.json
+/etc/config.redux.json
+/tmp/
diff --git a/README.md b/README.md
index 959e0a54..3e219486 100644
--- a/README.md
+++ b/README.md
@@ -3,4 +3,4 @@ BNETDocs: Redux
 
 This branch is the **BNETDocs: Redux** source code. This code is considered **ancient** and should only be modified when necessary or when small updates can be made.
 
-For current source code, [view the phoenix branch](https://github.com/carlbennett/bnetdocs-web/tree/phoenix).
+For current source code, [view the master branch](https://github.com/BNETDocs/bnetdocs-web/tree/master).
diff --git a/bdif/footer.dm b/bdif/footer.dm
index ae28aab6..fc5e4523 100644
--- a/bdif/footer.dm
+++ b/bdif/footer.dm
@@ -32,11 +32,12 @@
 		</div>
 		<br>
 	</div></div>-->
-	
+
 	<?
+                global $sql_connection;
 		$sqlquery = 'SELECT id,serveraddress,target,status FROM servers WHERE target != \'\'';
-		$redirects = mysql_query($sqlquery); $displayed = false;
-		while ($redirect = mysql_fetch_array($redirects)) {
+		$redirects = mysqli_query($sql_connection,$sqlquery); $displayed = false;
+		while ($redirect = mysqli_fetch_array($redirects)) {
 			if (!$displayed) {
 				echo "\t<div id=\"container\">\n\t<div id=\"main2\">\n\t<div id=\"author\">BNLS Redirecter Status</div>\n\t\t<div align=center>\n";
 				$displayed = true;
@@ -47,7 +48,7 @@
 				."\t\t</table>\n";
 		} if ($displayed) echo '</div></div>';
 	?>
-	
+
 	<div id="container">
 	<div id="main2">
 	<div id="author">BNLS Server Status</div>
@@ -55,8 +56,8 @@
 		<table cellspacing=2 cellpadding=2 border=0>
 		<?
 			$sqlquery = 'SELECT id,serveraddress,status FROM servers ORDER BY status DESC,id ASC';
-			$serverarray = mysql_query($sqlquery);
-			while($row = mysql_fetch_array($serverarray)){
+			$serverarray = mysqli_query($sql_connection,$sqlquery);
+			while($row = mysqli_fetch_array($serverarray)){
 				$sid = $row['id'];
 				$saddress = $row['serveraddress'];
 				$status = $row['status'];
@@ -66,26 +67,26 @@
 					$status = true;
 				}
 				/*if($saddress != 'bnls.dementedminds.net')*/ echo '<tr><td><font size=2>'.$saddress.': </td><td><img src="'.statusimg($status).'"><br></font></td></tr>';
-			} 
+			}
 		?>
 		</table>
 		</div>
 		<br>
 		<center><font size=1><img src="<? echo statusimg(true); ?>"> = Online &nbsp; &nbsp; &nbsp; <img src="<? echo statusimg(false); ?>"> = Offline<br><br></font></center>
 	</div></div>
-	
+
 	<div id="container">
 	<div id="main2">
 	<div id="author">Battle.net Server Status</div>
 		<div align=center>
 		<?
 			$sqlquery = 'SELECT version FROM bnetservers GROUP BY version ASC';
-			$versions = mysql_query($sqlquery);
-			while ($version = mysql_fetch_array($versions)) {
+			$versions = mysqli_query($sql_connection,$sqlquery);
+			while ($version = mysqli_fetch_array($versions)) {
 				echo '<h2>' . $version['version'] . '</h2><table cellspacing=2 cellpadding=2 border=0>';
 				$sqlquery = 'SELECT id,serveraddress,status FROM bnetservers WHERE version = \'' . $version['version'] . '\' ORDER BY status DESC,id ASC';
-				$serverarray = mysql_query($sqlquery);
-				while($row = mysql_fetch_array($serverarray)){
+				$serverarray = mysqli_query($sql_connection,$sqlquery);
+				while($row = mysqli_fetch_array($serverarray)){
 					$sid = $row['id'];
 					$saddress = $row['serveraddress'];
 					$status = $row['status'];
@@ -103,7 +104,7 @@
 		<br>
 		<center><font size=1><img src="<? echo statusimg(true); ?>"> = Online &nbsp; &nbsp; &nbsp; <img src="<? echo statusimg(false); ?>"> = Offline<br><br></font></center>
 	</div></div>
-	
+
 	<div id="links">
 	<div id="container">
 	<div id="main2">
@@ -115,13 +116,13 @@
 		<a href="http://www.darkblizz.org" target="_blank"><img src="/images/DarkBlizzbnetweb.gif" alt="DarkBlizz" title="DarkBlizz - Making Battle.net Magic"></a><br>
 		</center>
 	</div></div></div>
-	
+
 	<div id="rssfeeds">
 	<div id="container">
 	<div id="main2">
 	<div id="author">RSS Feeds</div>
 		<br>
-		<a href="//www.bnetdocs.org/newsrss.php"><img src="/images/rss.gif"> &nbsp; BNETDocs News</a><br>
+		<a href="/newsrss.php"><img src="/images/rss.gif"> &nbsp; BNETDocs News</a><br>
 		<?
 			if($userid){
 				?>
diff --git a/bdif/header.dm b/bdif/header.dm
index aa91338f..e9c6e3a3 100644
--- a/bdif/header.dm
+++ b/bdif/header.dm
@@ -16,11 +16,11 @@
 
 	<?
         if( extension_loaded('newrelic') ) { echo newrelic_get_browser_timing_header(); }
-	if(preg_match('/(?i)msie [1-9]/',$_SERVER['HTTP_USER_AGENT'])) { 
+	if(preg_match('/(?i)msie [1-9]/',$_SERVER['HTTP_USER_AGENT'])) {
 		$ie = true;
-	} else { 
+	} else {
 		$ie = false;
-	} 
+	}
 	if($userid){
 		$usercss = GetData($userid, 'usercss');
 		if($usercss){
@@ -49,7 +49,7 @@
 					<style type="text/css">
 					<?=$usercss;?>
 					</style>
-					<!-- End User CSS Inclusion -->		
+					<!-- End User CSS Inclusion -->
 					<?
 				} else {
 					?><link rel="stylesheet" type="text/css" href="<?=$usercssfile;?>"><?
@@ -123,7 +123,7 @@
 	<h2>Navigation</h2>
 	<div id="divMain_Menu"><div id="author">Main Menu</div><div class="navmenu" id="bodyMain_Menu">
 		<a href="/">Main Page</a><br>
-		<a href="https://dev.bnetdocs.org/">BNETDocs: Phoenix</a><br>
+		<a href="https://www.bnetdocs.org/">BNETDocs: Phoenix</a><br>
 		<a href="/?mode=all">View News History</a><br>
 		<a href="generatedocs.php">Download BNETDocs as Text</a><br>
 		<a href="/?op=search">Search BNETDocs</a> &nbsp; <font color=red size=1>Incomplete</font><br>
@@ -147,7 +147,8 @@
 	<div id="divDocuments"><div id="author">Documents</div><div class="navmenu" id="bodyDocuments">
 		<?
 		$sqlqueryz = 'SELECT * FROM documents ORDER BY title ASC';
-		$docarray = mysql_query($sqlqueryz);
+                global $sql_connection;
+		$docarray = mysqli_query($sql_connection,$sqlqueryz);
 		$doccount = 0;
 		function _clearance_name($clearance)
 		{
@@ -164,7 +165,7 @@
 			}
 			return $clearancename;
 		}
-		while($rowz = mysql_fetch_array($docarray)){
+		while($rowz = mysqli_fetch_array($docarray)){
 			$did = $rowz['id'];
 			$title = delslash($rowz['title']);
 			$clearance = $rowz['clearance'];
@@ -192,15 +193,15 @@
 		</form>
 		<br>
 <?
-                $sqlquery_traffic = mysql_query('SELECT * FROM traffic ORDER BY id');
+                $sqlquery_traffic = mysqli_query($sql_connection,'SELECT * FROM traffic ORDER BY id');
                 $traffic = array();
-                while($sqlresult_traffic = mysql_fetch_array($sqlquery_traffic)) {
+                while($sqlresult_traffic = mysqli_fetch_array($sqlquery_traffic)) {
                         $traffic[$sqlresult_traffic["id"]] = $sqlresult_traffic;
                 }
 		$sqlquerya = 'SELECT * FROM groups ORDER BY displayorder';
-		$groupsarray = mysql_query($sqlquerya);
+		$groupsarray = mysqli_query($sql_connection,$sqlquerya);
 		$zs1 = 1;
-		while($rowa = mysql_fetch_array($groupsarray)){
+		while($rowa = mysqli_fetch_array($groupsarray)){
 			$gid = $rowa['id'];
 			$groupname = $rowa['groupname'];
 			$groupdivname = str_replace(' ', '_', $groupname);
@@ -212,8 +213,8 @@
 			} else {
 				$sqlquery = 'SELECT * FROM packets WHERE pgroup='.$gid.' ORDER BY messageid,direction DESC';
 			}
-			$packetsarray = mysql_query($sqlquery);
-			while($row = mysql_fetch_array($packetsarray)){
+			$packetsarray = mysqli_query($sql_connection,$sqlquery);
+			while($row = mysqli_fetch_array($packetsarray)){
 				$pid = $row['id'];
                                 //$direction = $row['direction'];
                                 $direction = $traffic[$row['direction']]['shortdescr'] . ' ';
@@ -225,7 +226,7 @@
 					case 0:
 						$status = '<font class="raw">RAW</font>'."\n";
 						break;
-					case 1: 
+					case 1:
 						$status = '';
 						break;
 					case 2:
@@ -249,7 +250,7 @@
 						echo '<a href="/?op=packet&pid='.$pid.'"><font size=1>'.$direction.$messageid.$messagename.'</font></a>'.$status.'<br>'."\n";
 					}
 				}
-			} 
+			}
 			echo "\n".'<br>'."\n".'<font id="viewcode">View Code: [&nbsp; <a href="/?op=generatecode&gid='.$gid.'&lang=pas">PAS</a> <a href="/?op=generatecode&gid='.$gid.'&lang=cpp">CPP</a> <a href="/?op=generatecode&gid='.$gid.'&lang=vb">VB</a> <a href="/?op=generatecode&gid='.$gid.'&lang=php">PHP</a> &nbsp;]</font><br>'."\n".'</div>'.'<br>'."\n".'</div>'."\n";
 		} 
 		?>
diff --git a/cache/bnetdocsredux.txt b/cache/bnetdocsredux.txt
index 39627044..a2067923 100644
--- a/cache/bnetdocsredux.txt
+++ b/cache/bnetdocsredux.txt
@@ -86,7 +86,7 @@ Battle.net Documentation generated by BNETDocs
  the gateway list file and then compares that structure to its own cached copy. If the FILETIMEs do not match, then it
  goes to BNFTP and downloads a new one and stores it to the Windows Registry (or on file, if using Mac) while also
  caching the new FILETIME for later. They do not ever under any circumstance store the actual file data, and therefore
-as
+ as
  long as the cache is not changed and Battle.net always reports the same FILETIME, you can modify your gateway list
  without it knowing it changed.
 
@@ -262,7 +262,7 @@ as
  sin_zero (0) (DWORD) Unknown (Public = 0x10, Private = 0x11) (DWORD) Elapsed time (in seconds) (STRING) Game name *
  (STRING) Game password (always empty) (BYTE) Free slots (character representing hexadecimal number) (BYTE)[8] Host
  counter (characters representing reversed hexadecimal number, ex: '20000000' for second time this host has hosted
-during
+ during
  his session) (STRING) Encoded map information ALL OTHER CLIENTS: (WORD) Game Type (WORD) Sub Game Type (DWORD) Language
  ID (WORD) Address Family (Always AF_INET) (WORD) Port (DWORD) Host's IP (DWORD) sin_zero (0) (DWORD) sin_zero (0)
  (DWORD) Game Status (DWORD) Elapsed time (in seconds) (STRING) Game name * (STRING) Game password (STRING) Game
@@ -282,7 +282,7 @@ during
  Visible 0x00000800: Default Observers setting (mask 0x40003000, unique) 0x00000000: No Observers 0x00002000: Observers
  on Defeat 0x00003000: Full Observers 0x40000000: Referees Other advanced host settings (mask 0x07064000, combinable)
  0x00004000: Teams Together (team members are placed at neighbored starting locations) 0x00060000: Lock Teams
-0x01000000:
+ 0x01000000:
  Full Shared Unit Control 0x02000000: Random Hero 0x04000000: Random Races Non-WarCraft III Game Statstring Field:
  For other clients, game statring follows the format found here [4].
 
@@ -298,7 +298,7 @@ during
  Team Melee 0x0C: Team FFA 0x0D: Team CTF 0x0F: Top vs. Bottom STAR/SEXP/SSHR/JSTR/W2BN Sub Game Type Field:
  For Greed: 0x01: 2500 resources 0x02: 5000 resources 0x03: 7500 resources 0x04: 10000 resources For Slaughter: 0x01: 15
  minutes 0x02: 30 minutes 0x03: 45 minutes 0x04: 60 minutes For Team Melee, Team Free For All, and Team Capture the
-Flag:
+ Flag:
  0x01: 2 teams 0x02: 3 teams 0x03: 4 teams For Top vs. Bottom: 0x01: 1 v 7 0x02: 2 v 6 0x03: 3 v 5 0x04: 4 v 4 0x05: 5 v
  3 0x06: 6 v 2 0x07: 7 v 1 For Ladder: 0x00: Disconnects do not count as loss 0x01: Disconnects count as loss For Other
  Game Types: 0x01: No sub-game type DRTL/DSHR Game Type Field:
@@ -311,7 +311,7 @@ Flag:
  Valid status codes:
  This field is the 'Game Status' for non-WarCraft III and the 'Status' when no games are listed for both WarCraft III
  and other clients. 0x00: OK 0x01: Game doesn't exist 0x02: Incorrect password 0x03: Game full 0x04: Game already
-started
+ started
  0x05: Spawned CD-Key not allowed 0x06: Too many server requests
 
  ~~~~~~~~~~~~~~~~
@@ -345,14 +345,14 @@ started
  19 0x08: 20 - 24 0x09: 25 - 29 0x0A: 30 - 34 0x0B: 35 - 39 0x0C: 40 - 47 0x0D: 48 - 50 For all other games, Game Type
  can be set to 0x00. SUB GAME TYPE: For Greed, this is resources in multiples of 2500 (0x01 = 2500, 0x02 = 5000, etc).
  For Slaughter, this is minutes in multiples of 15 (0x01 = 15, 0x02 = 30, etc). For Ladder, this indicates if
-disconnects
+ disconnects
  count as a loss (0x01 = Yes, 0x00 = No). For Team Melee, this is the number of teams (0x01 = 2, 0x02 = 3, etc). For
-Team
+ Team
  Free For All, this is the number of teams (0x01 = 2, 0x02 = 3, etc). For Team Capture The Flag, this is the number of
  teams (0x01 = 2, 0x02 = 3, etc). For Top vs. Bottom, this is the players to team ratio (1-7). For any other game type,
  it is 0x01 which indicates no sub game type. VIEWING FILTER: 0xFFFF is used to use the combination of values in this
  packet. 0xFF80 is used to show all games. For STAR/SEXP/SSHR/JSTR, viewing filter is set to 0x30. For DRTL/DSHR,
-viewing
+ viewing
  filter is set to 0xFFFF by the game, but setting it to 0x00 will disable any viewing limitations, letting you view all
  games. RESERVED (0): This value is hardcoded to 0x00 by all games. NUMBER OF GAMES: This is the number of games to
  list. For a full listing, it's safe to use 0xFF. By default, DRTL/DSHR sets this to 0x19.
@@ -372,9 +372,9 @@ viewing
 
  Remarks:
  Contains Client product, realm, statstring, and is sent as the response when the client sends SID_ENTERCHAT. Unique
-name
+ name
  is the users unique name in chat (Which may be Arta, Arta#2, Arta#3, etc). Account name is the users account name
-(Which
+ (Which
  in all 3 previous examples would be Arta).
 
  Once you receive this packet, you are not in a channel, but can join/host games and join channels. Because you are not
@@ -460,10 +460,10 @@ name
  NoCreate Join: This will only join the channel specified if it is not empty, and is used by clients when selecting a
  channel from the channels menu. If the channel is empty, Battle.net sends a SID_CHATEVENT of type
  EID_CHANNELDOESNOTEXIST, upon which official clients prompt for confirmation that the user wishes to create the
-channel,
+ channel,
  in which case, it resends this packet with Flags set to Forced Join (0x02). First Join: Places user in a channel
  starting with their product and country, followed by a number, ie 'Brood War GBR-1'. Also automatically sends MOTD
-after
+ after
  entering the channel. When using this type, the Channel variable has no effect, but must be present anyway to avoid an
  IP ban. This is sent when first logging onto Battle.net Forced Join: This is sent when leaving a game, and joins the
  specified channel without an supplying an MOTD. D2 First Join: The same as First join, but is used for D2DV/D2XP
@@ -524,7 +524,7 @@ after
  Emote EID_SHOWUSER: This is sent for each user who is already in a channel when you join it, as opposed to EID_JOIN,
  which is sent when a user joins a channel you have already joined. It is also sent when logged on using D2XP/D2DV and a
  user requires an update to their statstring - for example, by logging a different character onto a realm. EID_JOIN:
-This
+ This
  is sent when a user enters the channel you are currently in. EID_LEAVE: This is sent when a user exits the channel you
  are currently in. EID_WHISPER: This is sent when a user whispers you. EID_TALK: This is sent when a user (excluding
  self) in chat speaks. EID_BROADCAST: The username supplied for this event is now always 'Battle.net'. Historically,
@@ -532,11 +532,11 @@ This
  this event is used and indicates what special conditions exist for the channel in question. See [Battle.net Flags] for
  more information. EID_USERFLAGS: This is sent to inform the client of an update to one or more user's flags. Battle.net
  usually sends this event for every user in the channel, even if only one user's flags have changed. This behavior can
-be
+ be
  exploited to detect invisible users, by performing an action (such as an unsquelch) to provoke a flags update. Users
  included in the flags update whose presence has not been indicated by EID_JOIN or EID_SHOWUSER can then be added to the
  userlist as invisible. Care should be taken, however, to account for the possibility that an asynchronous send error
-has
+ has
  occurred. Should an EID_JOIN or EID_SHOWUSER event occur for an invisible user, they should be marked as a normal user,
  not readded to the userlist. EID_WHISPERSENT: The Flags and Ping fields in this packet is equal to the originating user
  - the one who sent the whisper. In other words, EID_WHISPERSENT contains your flags & ping, not those of the person you
@@ -607,7 +607,7 @@ has
  **************************************
 
  Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Starcraft Japanese, Diablo
-I
+ I
 
  Format:
  (DWORD) UDPCode 
@@ -685,7 +685,7 @@ I
  **************************************
 
  Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Starcraft Japanese, Diablo
-I
+ I
 
  Format:
  (DWORD) Request ID
@@ -711,7 +711,7 @@ I
  **************************************
 
  Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Starcraft Japanese, Diablo
-I
+ I
 
  Format:
  (DWORD) Request ID
@@ -770,11 +770,11 @@ I
  Remarks:
  Displays a message to the user. This message's fields are used as parameters for the Win32 API MessageBox [5], and can
  be passed directly to it. For more information about these parameters, see the documentation for MessageBox [6] at
-MSDN.
+ MSDN.
 
  Some more research on the behavior of this packet in Starcraft Broodwar has been done by HarpyWar and xboi209. Their
  documentation can be found on GitHub [7]. Specifically, their research shows how to display a small and large
-MessageBox
+ MessageBox
  inside the client. A large MessageBox also shows the Caption parameter, whereas a small MessageBox does not.
 
  ~~~~~~~~~~~~~~~~
@@ -940,7 +940,7 @@ MessageBox
  **************************************
 
  Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Starcraft Japanese, Diablo
-I
+ I
 
  Format:
  (STRING) Text
@@ -1002,7 +1002,7 @@ I
  **************************************
 
  Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Starcraft Japanese, Diablo
-I
+ I
 
  Format:
  (DWORD) unknown/unparsed -- Flags, Request ID?
@@ -1038,216 +1038,7 @@ I
 
  Not used because it was quickly discovered that storing preferences produces less problems and were faster by storing
  them server-side, associating them with the account. It is somewhat curious that these packet IDs are close to
- SID_PROFILE/SID_WRITEPROFILE (0x26 & 0x27).
-
- Found at: battle!190216FBh and battle!1901D660h, respectively.
-
- ~~~~~~~~~~~~~~~~
-
- C > S [0x24] SID_READCOOKIE
- **************************************
-
- Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Warcraft II, Starcraft, Starcraft Japanese, Diablo
-I
-
- Format:
- (DWORD) First DWORD from S -> C
- (DWORD) Second DWORD from S -> C
- (STRING) Registry key name
- (STRING) Registry key value
-
- Remarks:
- Much like a website cookie, simply stores some arbitrary string to a 'cookie jar' to save preferences et al. which can
- be retrieved later by the server.
-
- Not used because it was quickly discovered that storing preferences produces less problems and were faster by storing
- them server-side, associating them with the account. It is somewhat curious that these packet IDs are close to
- SID_PROFILE/SID_WRITEPROFILE (0x26 you must submit this packet once for each user you wish to know about. This only
- applies to official Battle.net servers, it might not apply to PvPGN servers or equivalent software.
-
- Also, requesting 0x20 (32) or more keys at one time makes Battle.net kick you (it does not ban you, however).
-
- Profile Keys: * USER PROFILES: profilesex ** profileage † profilelocation profiledescription 
- ACCOUNT INFO: *** SystemAccount Created SystemAuthLevel SystemFlags SystemFriends SystemIcon SystemIP SystemLast Logoff
- SystemLast Logon SystemLeague SystemMFT Bytes SystemMFT Last Write SystemMFT Time Logged SystemPort SystemTime Logged
- SystemUsername 
- NORMAL GAMES: recordGAMEwins recordGAMElosses recordGAMEdisconnects recordGAMElast game recordGAMElast game result 
- LADDER GAMES: recordGAME1wins recordGAME1losses recordGAME1disconnects recordGAME1rating recordGAME1high rating
- DynKeyGAME1rank recordGAME1high rank recordGAME1last game recordGAME1last game result 
- IRONMAN LADDER GAMES: ‡ recordGAME3wins recordGAME3losses recordGAME3disconnects recordGAME3last game recordGAME3last
- game result recordGAME3rating recordGAME3high rating DynKeyGAME3rank * This list is not complete, and could use adding
- to. ** This field is defunct in STAR/SEXP/WAR3/W3XP. † This field is defunct. *** Battle.net returns blank values for
- anyone but yourself. ‡ W2BN only. Note that any profile key can contain an 0x09 (tab) character. 
-
- ~~~~~~~~~~~~~~~~
-
- C > S [0x27] SID_WRITEUSERDATA
- **************************************
-
- Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
- Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
-
- Format:
- (DWORD) Number of accounts
- (DWORD) Number of keys
- (STRING) [] Accounts to update
- (STRING) [] Keys to update
- (STRING) [] New values
-
- Remarks:
- Updates the Client's profile.
- Currently, the allowed keys for this are Sex, Location, and Description. The maximum length for the values is 512,
- including the null terminator.
-
- See SID_READUSERDATA for more information.
-
- ~~~~~~~~~~~~~~~~
-
- S > C [0x28] SID_LOGONCHALLENGE
- **************************************
-
- Used By: Starcraft Shareware, Diablo Shareware, Warcraft II, Starcraft Japanese, Diablo I
-
- Format:
- (DWORD) Server Token 
-
- Remarks:
- Contains the server token.
-
- This is sent after a request to version check with the old version check system.
-
- ~~~~~~~~~~~~~~~~
-
- S > C [0x29] SID_LOGONRESPONSE
- **************************************
-
- Used By: Starcraft Shareware, Diablo Shareware, Warcraft II, Starcraft Japanese, Diablo I
-
- Format:
- (DWORD) Result 
-
- Remarks:
- Reports success/fail on password authentication.
- Result: 0x00: Invalid password 0x01: Success
-
- ~~~~~~~~~~~~~~~~
-
- C > S [0x29] SID_LOGONRESPONSE
- **************************************
-
- Used By: Starcraft Shareware, Diablo Shareware, Warcraft II, Starcraft Japanese, Diablo I
-
- Format:
- (DWORD) Client Token
- (DWORD) Server Token
- (DWORD) [5] Password Hash
- (STRING) Username 
-
- Remarks:
- Contains Client's username developers should use the
- SID_CHECKDATAFILE2 message.
-
- The digest is created by using the broken SHA-1 hash on the first 64-bytes of the (filesize % 64) times. This due to a
- bug in the client. 
-
- ~~~~~~~~~~~~~~~~
-
- S > C [0x33] SID_GETFILETIME
- **************************************
-
- Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
- Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III, World of Warcraft
-
- Format:
- (DWORD) Request ID
- (DWORD) Unknown
- (FILETIME) Last update time
- (STRING) Filename 
-
- Remarks:
- Contains the latest filetime for the requested file. If the file does not exist, the returned filetime is null.
-
- ~~~~~~~~~~~~~~~~
-
- C > S [0x33] SID_GETFILETIME
- **************************************
-
- Used By: Starcraft Shareware, Starcraft Broodwar, Diablo Shareware, Diablo II, Warcraft II, Warcraft III: TFT,
- Starcraft, Starcraft Japanese, Diablo I, Diablo II LOD, Warcraft III
-
- Format:
- (DWORD) Request ID
- (DWORD) Unknown
- (STRING) Filename
-
- Remarks:
- This packet seems to request the current filetime for the specified file. Purpose of first 2 DWORDs is unknown,
-however,
- both are echoed back to the client by Battle.net and do not seem to affect the reply. Because of this it is reasonable
- to assume that first DWORD at least is a request ID of some kind. This is called into question, however, by the fact
- that the replying packet also contains the requested filename. The game (STAR/SEXP) always sends the same number in
- DWORD 1 for the file in question. DWORD 2 seems to be null.
-
- Known codes for DWORD 1: 0x01: tos_usa.txt
- 0x03: bnserver-WAR3.ini
- 0x1A: tos_USA.txt
- 0x1B: bnserver.ini
- 0x1D: icons_STAR.bni
- 0x80000005: IX86ExtraWork.mpq
- 0x80000004: bnserver-D2DV.ini
-
- ~~~~~~~~~~~~~~~~
-
- S > C [0x34] SID_QUERYREALMS
- **************************************
-
- Used By: Diablo II, Diablo II LOD
-
- Format:
- (DWORD) Unknown
- (DWORD) Count
- For Each Realm: (DWORD) Unknown (STRING) Realm title (STRING) Realm description
-
- Remarks:
- Realm list.
-
- The first Unknown is usually 0. The second [and subsequent] Unknown is usually 1.
-
- This packet is no longer used. SID_QUERYREALMS2 is used instead.
-
- ~~~~~~~~~~~~~~~~
-
- C > S [0x34] SID_QUERYREALMS
- **************************************
-
- Used By: Diablo II, Diablo II LOD
-
- Format:
- (DWORD) Unused (0)
- (DWORD) Unused (0)
- (STRING) Unknown (empty)
-
- Remarks:
- Requests a realm listing.
-
- This packet is no longer used. SID_QUERYREALMS2 is used instead.
-
- ~~~~~~~~~~~~~~~~
-
- S > C [0x35] SID_PROFILE
- **************************************
-
- Used By: Warcraft III: TFT, Warcraft III
-
- Format:
- (DWORD) Cookie
- (BYTE) Success
- (STRING) ProfileDescription value
- (STRING) ProfileLocation value
- (DWORD) Clan Tag
-
- Remarks:
- If the status code is 0, the request was successful; otherwise, the lookup failed and the message length will be five
+ SID_PROFILE/SID_WRITEPROFILE (0x26 otherwise, the lookup failed and the message length will be five
  bytes long (not counting the four byte header).
 
  Please note: This message's official name is not known, and has been invented.
@@ -1268,7 +1059,7 @@ however,
 
  It is safe to look up any username you want. The username can have illegal characters, can be of any length, and can
  have all the other "illy" username characteristics. This message can also be used across all products without a
-problem,
+ problem,
  not just WAR3/W3XP.
 
  Battle.net will translate the realm in the username for you, so you can look up @Azeroth as well as @USEast, if you
@@ -1556,7 +1347,7 @@ problem,
 
  Remarks:
  Realm password is always "password". The password hash is created the same way the hash is for logging on to an
-account.
+ account.
 
  ~~~~~~~~~~~~~~~~
 
@@ -1679,11 +1470,17 @@ account.
  (DWORD) Unknown (0)
 
  Remarks:
- Unknown. I am unable to disassemble Warcraft III's game.dll without a lot of trouble, and therefore I have limited
- knowledge of it. It has been seen once, after SID_LOGONPROOF (0x54) in the NLS logon sequence.
+ Unknown. The person who found this was unable to disassemble Warcraft III's game.dll without a lot of trouble, and
+ therefore had limited knowledge of it. It has been seen once, after SID_LOGONPROOF (0x54) in the NLS logon sequence.
 
  Found at: game.dll
 
+ [Update 03/14/2016]: It was also seen during the Warcraft III 1.27a patch shortly before it went live. Here are some
+ snapshots from a couple different bots:
+
+ * http://i.imgur.com/CnihMhs.png
+ * http://i.imgur.com/DTHJuwy.png
+
  ~~~~~~~~~~~~~~~~
 
  S > C [0x44] SID_WARCRAFTGENERAL
@@ -1954,9 +1751,9 @@ account.
  Protocol ID:Battle.net's current Protocol ID is 0. Platform ID:A DWORD specifying the client's platform (IX86, PMAC,
  XMAC, etc). Product ID:A DWORD specifying the client's game. Version:The client's version byte. Product Language:This
  field is under investigation. It can safely be set to 0. MPQ Locale ID:This field is part of Blizzards multi-lingual
-MPQ
+ MPQ
  system. Is used to specify which version of an MPQ should be used when the MPQ is available in multiple languages.
-Local
+ Local
  IP:This is the local network IP of the client, in network byte order. Timezone bias:The difference, in minutes, between
  UTC and local time. The client calculates this value by subtracting the Local Time from the System Time, having
  converted both to Filetime structures, and then converting the resultant offset to minutes by diving it by 600,000,000.
@@ -2086,7 +1883,7 @@ Local
  packet, followed by the data of the 1st packet. Only after the last packet was received, the data buffer should be
  parsed. IMPORTANT NOTE: If the entry is the last entry in the packet, the character name might be smaller than 16
  bytes.In this case, the client MUST add null bytes to the end of the packet, BEFORE adding it to the data buffer.
-Ladder
+ Ladder
  packets are NOT SENT IN ANY ORDER - They are often sent completely out of order and must be placed back into the proper
  order. You have to infer the sequencing based on the 'how big' fields in the 10 byte header.
 
@@ -2112,9 +1909,9 @@ Ladder
  0x0E: standard softcore barbarian ladder 0x13: expansion hardcore overall ladder 0x14: expansion hardcore amazon ladder
  0x15: expansion hardcore sorceress ladder 0x16: expansion hardcore necromancer ladder 0x17: expansion hardcore paladin
  ladder 0x18: expansion hardcore barbarian ladder 0x19: expansion hardcore druid ladder 0x1A: expansion hardcore
-assassin
+ assassin
  ladder 0x1B: expansion softcore overall ladder 0x1C: expansion softcore amazon ladder 0x1D: expansion softcore
-sorceress
+ sorceress
  ladder 0x1E: expansion softcore necromancer ladder 0x1F: expansion softcore paladin ladder 0x20: expansion softcore
  barbarian ladder 0x21: expansion softcore druid ladder 0x22: expansion softcore assassin ladder 
 
@@ -3117,7 +2914,7 @@ sorceress
 
  Extra Info: The status of this information is: Public Belt locations start at 0x00 and go from right to left, starting
  at the lowest row and moving across, then going up one row. For example, location 0x03 would be at the bottom right
-hand
+ hand
  corner and location 0x0C would be at the top left corner in a 4-slot belt. This can be calculated as (row*4+column).
 
  Please note: This message's official name is not known, and has been invented.
@@ -4071,7 +3868,7 @@ hand
  [1] http://msdn2.microsoft.com/en-us/library/ms724295.aspx
  [2] http://msdn2.microsoft.com/en-us/library/ms724432.aspx
  [3] http://forum.valhallalegends.com/index.php?topic=15419.5
- [4] http://bnetdocs.org/?op=doc&did=13
+ [4] http://redux.bnetdocs.org/?op=doc&did=13
  [5] http://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=vs.85).aspx
  [6] http://msdn.microsoft.com/en-us/library/windows/desktop/ms645505(v=vs.85).aspx
  [7] https://github.com/HarpyWar/pvpgn/issues/15#issuecomment-44092744
diff --git a/credits.php b/credits.php
index f94fe8a9..2cc22b52 100644
--- a/credits.php
+++ b/credits.php
@@ -3,9 +3,11 @@
 	# -------------------------------
 	global $auth;
 	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
-	
+
 	# Begin Code
-	# -------------
+        # -------------
+
+        global $sql_connection;
 ?>
 <div id="container">
 <div id="main2">
@@ -18,22 +20,22 @@
 <br><center>
 	<?
 		$sqlquery = 'SELECT * FROM users WHERE levelofaccess > 3 ORDER BY id ASC';
-		$membersarray = mysql_query($sqlquery);
-		while($row = mysql_fetch_array($membersarray)){
+		$membersarray = mysqli_query($sql_connection,$sqlquery);
+		while($row = mysqli_fetch_array($membersarray)){
 			$username = $row['username'];
 			echo $username.'<br>';
-		} 
+		}
 	?>
 <br></center>
 <div id="author"><center>BNETDocs is edited by:</center></div>
 <br><center>
 	<?
 		$sqlquery = 'SELECT * FROM users WHERE levelofaccess=3 ORDER BY id ASC';
-		$membersarray = mysql_query($sqlquery);
-		while($row = mysql_fetch_array($membersarray)){
+		$membersarray = mysqli_query($sql_connection,$sqlquery);
+		while($row = mysqli_fetch_array($membersarray)){
 			$username = ucfirst($row['username']);
 			echo $username.'<br>';
-		} 
+		}
 	?>
 <br></center>
 <div id="author"><center>Many thanks to the following, in no particular order, for their contributions:</center></div>
@@ -42,4 +44,4 @@
 [vL]Kp, Cloaked, Lord[nK], Ringo, shadypalm88, UserLoser, LivedKrad, Joe[x86], R.a.b.b.i.t.,<br>
 l2-Shadow, Smarter, Camel. While their contibutions aren't known to the new administrator (Kyro), their contributions are still nonetheless 
 appreciated. If you're the contributor mentioned in the previous list, please contact Kyro to have your contributions listed here.<br><br> DevCode -- Programatically obtain the VerByte code without reliance on BNLS<br><br></center>
-</div></div>
\ No newline at end of file
+</div></div>
diff --git a/db.php b/db.php
index 6b3cddc8..5d6d9d15 100644
--- a/db.php
+++ b/db.php
@@ -16,7 +16,7 @@
 	$dbpasswd = $config->database->password;
 	$database_name = $config->database->name;
 
-	@$connection = mysql_connect("$dbhost","$dbusername","$dbpasswd") or die ("Couldn't connect to server because ".mysql_error());
-	@$db = mysql_select_db("$database_name", $connection) or die("Couldn't select database because ".mysql_error());
-	@mysql_query('SET NAMES ' . $config->database->character_set . ' COLLATE ' . $config->database->collation . ';');
+        global $sql_connection;
+	@$sql_connection = mysqli_connect("$dbhost","$dbusername","$dbpasswd","$database_name") or die ("Couldn't connect to server because ".mysqli_error());
+	@mysqli_query('SET NAMES ' . $config->database->character_set . ' COLLATE ' . $config->database->collation . ';');
 ?>
diff --git a/doc.php b/doc.php
index 23ac60b6..024f23aa 100644
--- a/doc.php
+++ b/doc.php
@@ -429,8 +429,8 @@
 				<br>
 				<? 
 				if($userid){
-					if(rank($userid) > 2){ 
-						?><center><font size=1>[ &nbsp; <a href="/?op=doc&mode=edit&did=<?=$did;?>">EDIT</a> &nbsp; 
+					if(rank($userid) > 2){
+						?><center><font size=1>[ &nbsp; <a href="/?op=doc&mode=edit&did=<?=$did;?>">EDIT</a> &nbsp;
 						| &nbsp; <a onClick="return confimdelete();" href="/?op=doc&mode=delete&did=<?=$did;?>">DELETE</a> &nbsp; ]</font><br><br></center>
 						<?
 					}
@@ -447,17 +447,18 @@
 					<?
 				}
 				?></div></div></div></div></div>
-				
+
 				<div id="comments">
 				<div id="container">
 				<div id="main2">
 				<h2>User Comments</h2>
 				<center><br>For detailed questions and discussion, visit the <a href="http://forum.valhallalegends.com/index.php/board,17.0.html" target="_blank">Battle.net Research Forum</a><br><br></center>
-				<?
-				$sqlqueryz = 'SELECT id,posterid,UNIX_TIMESTAMP(dtstamp) as unixdtstamp,message FROM comments WHERE pdid=\''.mysql_real_escape_string($did).'\' ORDER BY id';
-				$docarray = mysql_query($sqlqueryz);
+<?
+                                global $sql_connection;
+				$sqlqueryz = 'SELECT id,posterid,UNIX_TIMESTAMP(dtstamp) as unixdtstamp,message FROM comments WHERE pdid=\''.mysqli_real_escape_string($sql_connection,$did).'\' ORDER BY id';
+				$docarray = mysqli_query($sql_connection,$sqlqueryz);
 				$commentcount = 0;
-				while($rowz = mysql_fetch_array($docarray)){
+				while($rowz = mysqli_fetch_array($docarray)){
 					$cid = $rowz['id'];
 					$posterid = $rowz['posterid'];
 					$dtstamp = date("M d, Y", $rowz['unixdtstamp']);
diff --git a/config.sample.json b/etc/config.sample.json
similarity index 100%
rename from config.sample.json
rename to etc/config.sample.json
diff --git a/functions.php b/functions.php
index ce051006..9f81a708 100644
--- a/functions.php
+++ b/functions.php
@@ -10,7 +10,7 @@
 	
 	# Begin Code
 	# -------------
-	$config = json_decode(file_get_contents("./config.redux.json"));
+	$config = json_decode(file_get_contents("./etc/config.redux.json"));
 	
 	# DisplayDialogBox Function
 	# --------------------
@@ -176,10 +176,11 @@ function login($username, $password, $tracked=true, $ip) {
 				# If tracking is enabled, log IP and login time/date.
 				#-------------
 
+                                        global $sql_connection;
 					$ip = $_SERVER["REMOTE_ADDR"];
 					$sql = "UPDATE users SET ip=\"$ip\" WHERE username=\"$username\"";
-					if($tracked == true) $sqlresults = mysql_query($sql) or die (mysql_error());
-					if($tracked == true) mysql_query("UPDATE users SET last_login=now() WHERE username='$username'");
+					if($tracked == true) $sqlresults = mysqli_query($sql_connection,$sql) or die (mysqli_error($sql_connection));
+					if($tracked == true) mysqli_query($sql_connection,"UPDATE users SET last_login=now() WHERE username='$username'");
 
 				# Set up session for member
 				#-------------
@@ -224,8 +225,9 @@ function FieldVerify($field, $table, $data){
 			
 			$sql = "SELECT COUNT(*) AS count FROM `$table` WHERE `$field`=\"$data\"";
 
-			$testercount = mysql_query($sql) or die("mysql error in $sql: ".mysql_error());
-			$testercount = mysql_fetch_object($testercount);
+                        global $sql_connection;
+			$testercount = mysqli_query($sql_connection,$sql) or die("mysql error in $sql: ".mysqli_error($sql_connection));
+			$testercount = mysqli_fetch_object($testercount);
 			$testers = $testercount->count;
 			
 			if($testers > 0){
@@ -258,7 +260,7 @@ function secure($ip) {
 			#------------
 			
 			$userid = GetInfo("sessions", "ipaddress", $ip, "id");
-			mysql_query("UPDATE users SET last_login=now() WHERE id='$userid'");
+			mysqli_query("UPDATE users SET last_login=now() WHERE id='$userid'");
 		}
 
 	#-------------
@@ -301,7 +303,7 @@ function GetData($whoid, $what){
 		function WriteData($whoid, $what, $data){
 			$ret = true;
 			$sql = "UPDATE users SET `$what`=\"$data\" WHERE id=$whoid"; 
-			$sqlresults = mysql_query($sql) or $ret = false;
+			$sqlresults = mysqli_query($sql) or $ret = false;
 			return $ret;
 		}
 	#-------------
@@ -312,26 +314,26 @@ function WriteData($whoid, $what, $data){
 	function Discipline($target, $action, $ip=''){
 		if($action == 'lp'){
 			$sql = "UPDATE discipline SET profile=0 WHERE account=$target";
-			$sqlresults = mysql_query($sql) or die(mysql_error());
+			$sqlresults = mysqli_query($sql) or die(mysqli_error());
 		} else if($action == 'up'){
 			$sql = "UPDATE discipline SET profile=1 WHERE account=$target";
-			$sqlresults = mysql_query($sql) or die(mysql_error());
+			$sqlresults = mysqli_query($sql) or die(mysqli_error());
 		} else if($action == 'fa'){
 			$sql = "UPDATE discipline SET frozen=1 WHERE account=$target";
-			$sqlresults = mysql_query($sql) or die(mysql_error());
+			$sqlresults = mysqli_query($sql) or die(mysqli_error());
 		} else if($action == 'ufa'){
 			$sql = "UPDATE discipline SET frozen=0 WHERE account=$target";
-			$sqlresults = mysql_query($sql) or die(mysql_error());
+			$sqlresults = mysqli_query($sql) or die(mysqli_error());
 		} else if($action == 'ipban'){
 			$sql = "UPDATE discipline SET ipban=1 WHERE account=$target";
-			$sqlresults = mysql_query($sql) or die(mysql_error());
+			$sqlresults = mysqli_query($sql) or die(mysqli_error());
 			$currentip = GetData($target, 'ip');
-			mysql_query("INSERT INTO `banned` (id, ip, bantype) VALUES ($target, '$ip', 'total')") or die("Discipline Function Error: ".mysql_error());
+			mysqli_query("INSERT INTO `banned` (id, ip, bantype) VALUES ($target, '$ip', 'total')") or die("Discipline Function Error: ".mysqli_error());
 		} else if($action == 'unipban'){
 			$sql = "UPDATE discipline SET ipban=0 WHERE account=$target";
-			$sqlresults = mysql_query($sql) or die(mysql_error());
+			$sqlresults = mysqli_query($sql) or die(mysqli_error());
 			$sql = "DELETE FROM banned WHERE id=\"$target\"";
-			$sqlresults = mysql_query($sql) or die (mysql_error());
+			$sqlresults = mysqli_query($sql) or die (mysqli_error());
 		}
 	}
 	
@@ -354,10 +356,11 @@ function BlockHack(){
 		function GetInfo($db, $index, $id, $data){
 	                static $cache = [];
 	                $str = $db.$index.$id.$data;
-	                if (isset($cache[$str])) return $cache[$str];
-	                $sqlquery = mysql_query("SELECT * FROM `$db` WHERE `$index`=\"$id\" LIMIT 1") or die('Attempted Query: '."SELECT * FROM `$db` WHERE `$index`='$id' LIMIT 1"."<br>GetInfo Function Error: ".mysql_error());;
-			if(mysql_num_rows($sqlquery) > 0) {
-				$ret = mysql_result($sqlquery,0,$data);
+                        if (isset($cache[$str])) return $cache[$str];
+                        global $sql_connection;
+	                $sqlquery = mysqli_query($sql_connection,"SELECT * FROM `$db` WHERE `$index`=\"$id\" LIMIT 1") or die('Attempted Query: '."SELECT * FROM `$db` WHERE `$index`='$id' LIMIT 1"."<br>GetInfo Function Error: ".mysqli_error());;
+			if(mysqli_num_rows($sqlquery) > 0) {
+				$ret = mysqli_fetch_assoc($sqlquery)[$data];
 			} else {
 				$ret = false;
 	                }
@@ -386,7 +389,7 @@ function GetInfo($db, $index, $id, $data){
 		function WriteInfo($db, $index, $id, $field, $data){
 			$ret = true;
 			$sql = "UPDATE `$db` SET `$field`=\"$data\" WHERE $index=$id"; 
-			$sqlresults = mysql_query($sql) or $ret = false;
+			$sqlresults = mysqli_query($sql) or $ret = false;
 			return $ret;
 		}
 	#-------------
@@ -457,34 +460,7 @@ function Email($target, $fromwho, $subject, $body){
 	#-------------
 	# End of Email Function
 	#-------------
-	
-	#Applies nl2br to $text, but also makes sure to avoid applying the function to any content within pre tags
-	function nl2brex($text) {
-		$text = nl2br($text);
-		$text = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " ('$1') .  (clean_pre('$2'))  . '</pre>' ", $text);
-		$text = preg_replace('!(<ol.*?>)(.*?)</ol>!ise', " ('$1') .  (clean_pre('$2'))  . '</ol>' ", $text);
-		$text = preg_replace('!(<ul.*?>)(.*?)</ul>!ise', " ('$1') .  (clean_pre('$2'))  . '</ul>' ", $text);
-		$text = preg_replace('!(<dl.*?>)(.*?)</dl>!ise', " ('$1') .  (clean_pre('$2'))  . '</dl>' ", $text);
-		$text = preg_replace('!(\[nobr.*?\])(.*?)\[/nobr\]!ise', " stripslashes('$1') .  stripslashes(clean_pre('$2'))  . '' ", $text);
-		$text = brfix($text);
-		$text = str_ireplace('[nobr]', '', $text);
-		$text = str_ireplace('[/nobr]', '', $text);
-		return $text;
-	}
-	
-	#nl2brex2 for RSS feeds
-	function nl2brex2($text) {
-		$text = preg_replace('!(<pre.*?>)(.*?)</pre>!ise', " ('$1') .  (clean_pre('$2'))  . '</pre>' ", $text);
-		$text = preg_replace('!(<ol.*?>)(.*?)</ol>!ise', " ('$1') .  (clean_pre('$2'))  . '</ol>' ", $text);
-		$text = preg_replace('!(<ul.*?>)(.*?)</ul>!ise', " ('$1') .  (clean_pre('$2'))  . '</ul>' ", $text);
-		$text = preg_replace('!(<dl.*?>)(.*?)</dl>!ise', " ('$1') .  (clean_pre('$2'))  . '</dl>' ", $text);
-		$text = preg_replace('!(\[nobr.*?\])(.*?)\[/nobr\]!ise', " stripslashes('$1') .  stripslashes(clean_pre('$2'))  . '' ", $text);
-		$text = brfix($text);
-		$text = str_ireplace('[nobr]', '', $text);
-		$text = str_ireplace('[/nobr]', '', $text);
-		return $text;
-	}
-	
+
 	# Workaround for the br tag after a closing tag fix
 	function brfix($text){
 		$text = str_ireplace('</dl><br />', '</dl>', $text);
@@ -512,7 +488,7 @@ function clean_pre($text) {
 	function totalpurgehtml($source){
 		$allowedTags='';
 		$source = strip_tags($source, $allowedTags);
-		return preg_replace('/<(.*?)>/ie',
+		return preg_replace('/<(.*?)>/i',
 		"'<'.removeEvilAttributes('\\1').'>'", $source);
 	}
 	
@@ -551,25 +527,25 @@ function Codify($text){
 		ksort($patterns);
 		ksort($replacements);
 		$text = preg_replace($patterns, $replacements, $text);
-		$text = nl2brex($text);
+		$text = nl2br($text);
 		return $text;
 	}
 	#-------------
 	# End of Codify Function
 	#-------------
-	
+
 	if(!function_exists('str_ireplace')) {
 		function str_ireplace($search,$replace,$subject) {
 			$search = preg_quote($search, "/");
-			return preg_replace("/".$search."/i", $replace, $subject); 
-		} 
+			return preg_replace("/".$search."/i", $replace, $subject);
+		}
 	}
 
 	function purge($StringToPurge) {
 		$string = str_replace(array("\r\n", "\r", "\n"), "", $StringToPurge);
 		return $string;
 	}
-	
+
 	function removeEvilTags($source){
 		#$allowedTags='<b><s><u><span><p><i><blockquote><ul><ol><li><br><a><dl><dt><dd>';
 		#$source = strip_tags($source, $allowedTags);
@@ -587,31 +563,35 @@ function removeEvilAttributes($tagSource) {
 		return stripslashes(preg_replace("/$stripAttrib/i", 'forbidden', $tagSource));
 	}
 	
-	function sanitize($string, $min='', $max=''){
-		return mysql_real_escape_string($string);
+        function sanitize($string, $min='', $max=''){
+                global $sql_connection;
+		return mysqli_real_escape_string($sql_connection,$string);
 	}
 
 	function CreateSession($id, $ip){
+                global $sql_connection;
 		if(!FieldVerify('id', 'sessions', $id)){
-			mysql_query("INSERT INTO sessions (id,ipaddress) VALUES ('$id','$ip')") or die("CreateSession Function Error: ".mysql_error());
+			mysqli_query($sql_connection,"INSERT INTO sessions (id,ipaddress) VALUES ('$id','$ip')") or die("CreateSession Function Error: ".mysqli_error($sql_connection));
 		} else {
-			mysql_query("UPDATE sessions SET ipaddress='$ip' WHERE id='$id'") or die("CreateSession Function Error: ".mysql_error());
+			mysqli_query($sql_connection,"UPDATE sessions SET ipaddress='$ip' WHERE id='$id'") or die("CreateSession Function Error: ".mysqli_error($sql_connection));
 		}
 	}
 	
-	function KillSession($id){
+        function KillSession($id){
+                global $sql_connection;
 		if(FieldVerify('id', 'sessions', $id)){
 			$sql = "DELETE FROM sessions WHERE id=$id";
-			$sqlresults = mysql_query($sql) or die (mysql_error());
+			$sqlresults = mysqli_query($sql_connection,$sql) or die (mysqli_error($sql_connection));
 		}
 	}
 	
 	function SwapID($newid, $ip){
+                global $sql_connection;
 		$origid = GetUserIDFromSession($ip);
 		if(!FieldVerify('ip', 'testers', $ip)){
-			mysql_query("INSERT INTO testers (id,ip) VALUES ('$origid','$ip')") or die("SwapID Function Error: ".mysql_error());
+			mysqli_query($sql_connection,"INSERT INTO testers (id,ip) VALUES ('$origid','$ip')") or die("SwapID Function Error: ".mysqli_error($sql_connection));
 		} else {
-			mysql_query("UPDATE testers SET id='$origid' WHERE ip='$ip'") or die("SwapID Function Error: ".mysql_error());
+			mysqli_query($sql_connection,"UPDATE testers SET id='$origid' WHERE ip='$ip'") or die("SwapID Function Error: ".mysqli_error($sql_connection));
 		}
 		KillSession($origid);
 		CreateSession($newid, $ip);
@@ -625,11 +605,12 @@ function SwapID($newid, $ip){
 		#function FieldVerify($field, $table, $data){
 		
 	function RestoreID($ip){
+                global $sql_connection;
 		if(FieldVerify('ip', 'testers', $ip)){
 			$fakeid = GetInfo('sessions', 'ipaddress', $ip, 'id');
 			$realid = GetInfo('testers', 'ip', $ip, 'id');
 			$sql = "DELETE FROM testers WHERE id=\"$realid\"";
-			$sqlresults = mysql_query($sql) or die (mysql_error());
+			$sqlresults = mysqli_query($sql_connection,$sql) or die (mysqli_error($sql_connection));
 			KillSession($fakeid);
 			CreateSession($realid, $ip);
 		}
@@ -661,8 +642,9 @@ function GetOldData($whoid, $what){
 	function CheckBanned($ip, $type){
 		$sql = "SELECT COUNT(*) AS count FROM `banned` WHERE `ip`=\"$ip\" AND `bantype`=\"$type\"";
 
-		$testercount = mysql_query($sql) or die("mysql error in $sql: ".mysql_error());
-		$testercount = mysql_fetch_object($testercount);
+                global $sql_connection;
+		$testercount = mysqli_query($sql_connection,$sql) or die("mysql error in $sql: ".mysqli_error($sql_connection));
+		$testercount = mysqli_fetch_object($testercount);
 		$testers = $testercount->count;
 
 		if($testers > 0){
@@ -672,8 +654,9 @@ function CheckBanned($ip, $type){
 	}
 		
 	function RecoverUser($id){
+                global $sql_connection;
 		if(!FieldVerify('id', 'users', $id)){
-			mysql_query("INSERT INTO `users` (id) VALUES ($id)") or die("RecoverUser Function Error: ".mysql_error());
+			mysqli_query($sql_connection,"INSERT INTO `users` (id) VALUES ($id)") or die("RecoverUser Function Error: ".mysqli_error($sql_connection));
 		}
 		
 		$temp = GetOldData($id, 'username');
@@ -711,7 +694,7 @@ function RecoverUser($id){
 		
 		if(FieldVerify("id", "terminated", $id)){
 			$sql = "DELETE FROM `terminated` WHERE id=\"$id\"";
-			$sqlresults = mysql_query($sql) or die (mysql_error());
+			$sqlresults = mysqli_query($sql) or die (mysqli_error());
 		}
 	}
 	
@@ -774,7 +757,7 @@ function CreateUser($username, $email, $ip){
 					}
 				}
 				$enpassword = md5($password);
-				mysql_query("INSERT INTO users (ip, username, password, email) VALUES ('$ip', '$username', '$enpassword', '$email')") or die("CreateUser Function Error: ".mysql_error());
+				mysqli_query("INSERT INTO users (ip, username, password, email) VALUES ('$ip', '$username', '$enpassword', '$email')") or die("CreateUser Function Error: ".mysqli_error());
 				$body = "Welcome!
 		
 You've registered as an user of BNETDocs. If this email is in error, simply ignore this email.
@@ -803,7 +786,7 @@ function CreateUser($username, $email, $ip){
 			} else { #Aha, user was a member before, remove from terminated database and give original id
 				$id = getinfo('terminated', 'username', $username, 'id');
 				$sql = "DELETE FROM terminated WHERE id=\"$id\"";
-				$sqlresults = mysql_query($sql) or die (mysql_error());
+				$sqlresults = mysqli_query($sql) or die (mysqli_error());
 				$breakout = false;
 				while($breakout == false){
 					$password = createRandomPassword();
@@ -812,7 +795,7 @@ function CreateUser($username, $email, $ip){
 					}
 				}
 				$enpassword = md5($password);
-				mysql_query("INSERT INTO users (id, ip, username, password, email) VALUES ($id, '$ip', '$username', '$enpassword', '$email')") or die("CreateUser Function Error: ".mysql_error());
+				mysqli_query("INSERT INTO users (id, ip, username, password, email) VALUES ($id, '$ip', '$username', '$enpassword', '$email')") or die("CreateUser Function Error: ".mysqli_error());
 				$body = "Welcome Back!
 		
 You've re-registered as an user of BNETDocs. If this email is in error, simply ignore this email.
@@ -857,7 +840,7 @@ function ResetPassword($userid){
 		$username = whoisid($userid);
 		$email = GetData($userid, 'email');
 		$enpassword = md5($password);
-		mysql_query("UPDATE users SET password='$enpassword' WHERE id=$userid") or die("ResetPasswrd Function Error: ".mysql_error());
+		mysqli_query("UPDATE users SET password='$enpassword' WHERE id=$userid") or die("ResetPasswrd Function Error: ".mysqli_error());
 		$body = "Hello!
 
 You've requested your password to be resetted. It has been resetted for you.
@@ -893,7 +876,7 @@ function DeleteUser($id){
 		# Copy username info to terminated db for stability
 		
 		$username = GetData($id, 'username');
-		mysql_query("INSERT INTO `terminated` (`id`, `username`) VALUES ($id, '" . mysql_real_escape_string($username) . "')") or die("DeleteUser Function Error: ".mysql_error());
+		mysqli_query("INSERT INTO `terminated` (`id`, `username`) VALUES ($id, '" . mysqli_real_escape_string($username) . "')") or die("DeleteUser Function Error: ".mysqli_error());
 		
 		# Delete User's session if it exists
 		
@@ -905,7 +888,7 @@ function DeleteUser($id){
 		
 		if(FieldVerify("id", "users", $id)){
 			$sql = "DELETE FROM users WHERE id=$id";
-			$sqlresults = mysql_query($sql) or die (mysql_error());
+			$sqlresults = mysqli_query($sql) or die (mysqli_error());
 		}
 	}
 	
@@ -916,13 +899,14 @@ function lcfirst($str) {
 	}
 
 	function rank($id){
-	   	$rank = GetData($id,'levelofaccess');
-	   	return $rank;
+                $rank = GetData($id,'levelofaccess');
+	        return $rank;
 	}
 
-	function rankname($rank){
-		$info = mysql_query("SELECT groupname FROM `membergroup` WHERE `id` ='".$rank."'")  or die("Rank Name Function Error: ".mysql_error());
-		$rank = mysql_result($info,0,"groupname");
+        function rankname($rank){
+                global $sql_connection;
+		$info = mysqli_query($sql_connection,"SELECT groupname FROM `membergroup` WHERE `id` ='".$rank."'")  or die("Rank Name Function Error: ".mysqli_error($sql_connection));
+		$rank = mysqli_fetch_assoc($info)['groupname'];
 		return $rank;
 	}
 	
@@ -934,7 +918,7 @@ function logthis($userid, $event, $type){
                   $event = sanitize($event);
                   $datetime = date("l, F d Y");
                   $ip = $_SERVER['REMOTE_ADDR'];
-                  mysql_query("INSERT INTO logs (user,event,eventtype, datetime,ip) VALUES ('$userid','$event','$type','$datetime','$ip')") or die("Logthis Function Error: ".mysql_error());
+                  mysqli_query("INSERT INTO logs (user,event,eventtype, datetime,ip) VALUES ('$userid','$event','$type','$datetime','$ip')") or die("Logthis Function Error: ".mysqli_error());
                 }
 	}
 
@@ -993,8 +977,8 @@ function getid($idtoget){
 		#Parameter: Name
 		$queryid = "SELECT * FROM users WHERE username = \"$idtoget\"";
 		if($idtoget != "all"){
-			$identification = mysql_query($queryid);
-			$ret = mysql_result($identification,0,"id");
+			$identification = mysqli_query($queryid);
+			$ret = mysqli_result($identification,0,"id");
 		} else {
 			$ret = "all";
 		}
@@ -1005,9 +989,9 @@ function getpacketlink($id){
 		#Return name of packet associated with id
 		#Parameter: id
 		$queryid = "SELECT * FROM packets WHERE id=$id";
-		$identification = mysql_query($queryid);
-		$messageid = mysql_result($identification,0,"messageid");
-		$messagename = mysql_result($identification,0,"messagename");
+		$identification = mysqli_query($queryid);
+		$messageid = mysqli_result($identification,0,"messageid");
+		$messagename = mysqli_result($identification,0,"messagename");
 		$ret = '<a href="/?op=packet&pid='.$id.'">('.$messageid.') '.$messagename.'</a>';
 		return $ret;
 	}
@@ -1016,8 +1000,8 @@ function getdocumentlink($id){
 		#Return name of packet associated with id
 		#Parameter: id
 		$queryid = "SELECT * FROM documents WHERE id=$id";
-		$identification = mysql_query($queryid);
-		$title = mysql_result($identification,0,"title");
+		$identification = mysqli_query($queryid);
+		$title = mysqli_result($identification,0,"title");
 		$ret = '<a href="/?op=doc&did='.$id.'">'.$title.'</a>';
 		return $ret;
 	}
diff --git a/generatecode.php b/generatecode.php
index 8ad5a465..16a49843 100644
--- a/generatecode.php
+++ b/generatecode.php
@@ -3,10 +3,12 @@
 	# -------------------------------
 	global $auth, $ie;
 	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
-	
+
 	# Begin Code
-	# -------------
-	
+        # -------------
+
+        global $sql_connection;
+
 	$gid = $_GET['gid'];
 	$lang = $_GET['lang'];
 	if($lang == 'vb') $language = 'Visual Basic 6.0';
@@ -15,18 +17,18 @@
 	if($lang == 'pas') $language = 'Pascal';
 	if($lang == 'php') $language = 'PHP';
 	if($lang == 'csharp') $language = 'C# (C Sharp)';
-	
+
 	if(!$language){
 		error('Unable to generate code for the specified language. Teach me!');
 		return;
 	}
-	
+
 	if($gid == 'all'){
 		$groupname = 'All';
 	} else {
 		$groupname = GetInfo('groups', 'id', $gid, 'groupname');
 	}
-	
+
 	$orderby_all = 'GROUP BY messagename ORDER BY pgroup,messageid,direction DESC';
 	$orderby_single = 'GROUP BY messagename ORDER BY messageid,direction DESC';
 ?>
@@ -44,9 +46,9 @@
 		} else {
 			$sqlquery = 'SELECT * FROM packets '.$orderby_all;
 		}
-		$packetsarray = mysql_query($sqlquery);
+		$packetsarray = mysqli_query($sql_connection,$sqlquery);
 		$pgroup = -1;
-		while($row = mysql_fetch_array($packetsarray)){
+		while($row = mysqli_fetch_array($packetsarray)){
 			if($row['pgroup'] != $pgroup){
 				$pgroup = $row['pgroup'];
 				$groupname = GetInfo('groups', 'id', $pgroup, 'groupname');
@@ -58,9 +60,9 @@
 			$pid = $row['id'];
 			$messageid = $row['messageid'];
 			$messagename = $row['messagename'];
-			
+
 			echo 'CONST '.$messagename.'& = &H'.substr($messageid, 2).'<br>';
-		} 
+		}
 	} elseif($lang == 'cpp'){
 		$commentizer = '//';
 		include 'bdif/codecomments.dm';
@@ -69,9 +71,9 @@
 		} else {
 			$sqlquery = 'SELECT * FROM packets '.$orderby_all;
 		}
-		$packetsarray = mysql_query($sqlquery);
+		$packetsarray = mysqli_query($sql_connection,$sqlquery);
 		$pgroup = -1;
-		while($row = mysql_fetch_array($packetsarray)){
+		while($row = mysqli_fetch_array($packetsarray)){
 			if($row['pgroup'] != $pgroup){
 				$pgroup = $row['pgroup'];
 				$groupname = GetInfo('groups', 'id', $pgroup, 'groupname');
@@ -83,9 +85,9 @@
 			$pid = $row['id'];
 			$messageid = $row['messageid'];
 			$messagename = $row['messagename'];
-			
+
 			echo '#define '.$messagename.' '.$messageid.'<br>';
-		} 
+		}
 	} elseif($lang == 'java'){
 		$commentizer = '//';
 		include 'bdif/codecomments.dm';
@@ -94,23 +96,23 @@
 		} else {
 			$sqlquery = 'SELECT * FROM packets '.$orderby_all;
 		}
-		$packetsarray = mysql_query($sqlquery);
+		$packetsarray = mysqli_query($sql_connection,$sqlquery);
 		$pgroup = -1;
-		while($row = mysql_fetch_array($packetsarray)){
+		while($row = mysqli_fetch_array($packetsarray)){
 			if($row['pgroup'] != $pgroup){
 				$pgroup = $row['pgroup'];
 				$groupname = GetInfo('groups', 'id', $pgroup, 'groupname');
 				if($ie) echo '&#13;&#10;';
 				echo '<br>'.$commentizer.' '.$groupname.' Constants<br>';
 				echo $commentizer.' -------------------<br><br>';
-				if($ie) echo '&#13;&#10;'; 
+				if($ie) echo '&#13;&#10;';
 			}
 			$pid = $row['id'];
 			$messageid = $row['messageid'];
 			$messagename = $row['messagename'];
-			
+
 			echo 'static final byte '.$messagename.' = '.$messageid.';<br>';
-		} 
+		}
 	} elseif($lang == 'pas'){
 		$commentizer = '//';
 		include 'bdif/codecomments.dm';
@@ -120,9 +122,9 @@
 		} else {
 			$sqlquery = 'SELECT * FROM packets '.$orderby_all;
 		}
-		$packetsarray = mysql_query($sqlquery);
+		$packetsarray = mysqli_query($sql_connection,$sqlquery);
 		$pgroup = -1;
-		while($row = mysql_fetch_array($packetsarray)){
+		while($row = mysqli_fetch_array($packetsarray)){
 			if($row['pgroup'] != $pgroup){
 				$pgroup = $row['pgroup'];
 				$groupname = GetInfo('groups', 'id', $pgroup, 'groupname');
@@ -134,9 +136,9 @@
 			$pid = $row['id'];
 			$messageid = $row['messageid'];
 			$messagename = $row['messagename'];
-			
+
 			echo '  '.$messagename.' = $'.substr($messageid, 2).';<br>';
-		} 
+		}
 	} elseif($lang == 'csharp'){
 		$commentizer = '//';
 		include 'bdif/codecomments.dm';
@@ -147,10 +149,10 @@
 		} else {
 			$sqlquery = 'SELECT * FROM packets '.$orderby_all;
 		}
-		$packetsarray = mysql_query($sqlquery);
+		$packetsarray = mysqli_query($sql_connection,$sqlquery);
 		$pgroup = -1;
 		ob_start();
-		while($row = mysql_fetch_array($packetsarray)){
+		while($row = mysqli_fetch_array($packetsarray)){
 			if($row['pgroup'] != $pgroup){
 				$pgroup = $row['pgroup'];
 				$groupname = GetInfo('groups', 'id', $pgroup, 'groupname');
@@ -162,7 +164,7 @@
 			$pid = $row['id'];
 			$messageid = $row['messageid'];
 			$messagename = $row['messagename'];
-			
+
 			echo '&#09;'.$messagename.' = '.$messageid.',<br>';
 		}
 		$results = ob_get_contents();
@@ -178,9 +180,9 @@
 		} else {
 			$sqlquery = 'SELECT * FROM packets '.$orderby_all;
 		}
-		$packetsarray = mysql_query($sqlquery);
+		$packetsarray = mysqli_query($sql_connection,$sqlquery);
 		$pgroup = -1;
-		while($row = mysql_fetch_array($packetsarray)){
+		while($row = mysqli_fetch_array($packetsarray)){
 			if($row['pgroup'] != $pgroup){
 				$pgroup = $row['pgroup'];
 				$groupname = GetInfo('groups', 'id', $pgroup, 'groupname');
@@ -192,10 +194,10 @@
 			$pid = $row['id'];
 			$messageid = $row['messageid'];
 			$messagename = $row['messagename'];
-			
+
 			echo 'define(\''.$messagename.'\', '.$messageid.');<br>';
-		} 
+		}
 	}
 ?></pre>
 <br></center>
-</div></div>
\ No newline at end of file
+</div></div>
diff --git a/index.php b/index.php
index c0a03782..ff5a40fb 100644
--- a/index.php
+++ b/index.php
@@ -1,5 +1,5 @@
-<?
-	
+<? error_reporting(E_ALL & ~E_NOTICE);
+
 	# Include direct script access authorization variable and other variables
 	#-------------
 
@@ -7,7 +7,7 @@
 		$ip = $_SERVER['REMOTE_ADDR'];
 		$surpress = $_REQUEST['surpress'];
 		#die('This site has been frozen for maintenance.');
-		
+
 	# Set up environment
 	#-------------
 
@@ -20,9 +20,9 @@
 
 	# Security
 	#-------------
-	
+
 		# Prevent spam POST submissions from external domains
-		
+
 		if($_POST){
 			if(!strpos($_SERVER['HTTP_REFERER'],'bnetdocs.org')){
 				exit();
@@ -31,7 +31,7 @@
 
 		# Stripslashes as shown on http://php.net/get_magic_quotes_gpc
 		# Used to prevent remote code injection via post, get, cookie. Also contributes to prevent remote code injection via SQL since input is cleaned prior to inserting to SQL DB.
-		if (get_magic_quotes_gpc()) {	
+		if (get_magic_quotes_gpc()) {
 		   function stripslashes_deep($value) {
 		       $value = is_array($value) ?
 		                   array_map('stripslashes_deep', $value) :
@@ -44,23 +44,23 @@ function stripslashes_deep($value) {
 		   $_GET = array_map('stripslashes_deep', $_GET);					# Clean browser variables
 		   $_COOKIE = array_map('stripslashes_deep', $_COOKIE);	# Clean cookie variables
 		}
-		
+
 	# Include essential files
 	#-------------
 
 		require_once 'functions.php';
 		require_once 'db.php';
-		
+
 	# Block out unwelcome visitors
 	#-------------
 
-		$userid = GetUserIDFromSession($ip);
+                $userid = GetUserIDFromSession($ip);
 
 	# REQUEST: Get our requested page and set the variable
 	#-------------
 
                 if (isset($_REQUEST["op"]) && is_string($_REQUEST["op"])) {
-  		  $op = $_REQUEST['op'];
+                  $op = $_REQUEST['op'];
                 } else {
                   $op = "";
                 }
@@ -70,7 +70,7 @@ function stripslashes_deep($value) {
 
 	# BLIZZARD: Is this Blizzard, and if so, log it
 	#-------------
-	
+
 		if(isblizzard($ip)){
 			#IP identified as potentially belonging to blizzard. Note it in log.
 			logthis(-1, 'Blizzard accessed page: ?'.$_SERVER['QUERY_STRING'], 'vip');
@@ -78,7 +78,7 @@ function stripslashes_deep($value) {
 
 	# SECURITY: Prevent remote inclusion injection
 	#-------------
-	
+
 		$legal_inc=getdir('.');
 
 		$i=0;
@@ -87,9 +87,9 @@ function stripslashes_deep($value) {
 			if($op.'.php'==$legal_inc[$i]) $allowfile='true';
 			$i++;
 		}
-		
+
 		if(!$op || trim($op) == '') $allowfile='true';
-		
+
 		if($allowfile=='false') exit();
 
         # New Relic Transactions
@@ -108,13 +108,14 @@ function stripslashes_deep($value) {
 	#-------------
 
 		ob_start('ob_gzhandler');
-		
+
 		if($surpress != "true"){
 			if($op == "") $op = "news";
 			include "bdif/header.dm";
 			if($userid){
+/* phoenix */
 				# Update member last login
-				mysql_query("UPDATE sessions SET dtstamp=NOW() WHERE id='$userid'") or die("UpdateSession Function Error: ".mysql_error());
+				#mysql_query("UPDATE sessions SET dtstamp=NOW() WHERE id='$userid'") or die("UpdateSession Function Error: ".mysql_error());
 				$msg = GetData($userid, 'msg');
 			} else {
 				$msg = $_REQUEST['msg'];
@@ -126,7 +127,7 @@ function stripslashes_deep($value) {
 					$msg = "Nice try buddy!";
 				}
 			}
-			
+
 			if($msg){
 				$msg = '<center><font color=lime><b>'.$msg.'</b></font></center>';
 				WriteData($userid, 'msg', '');
@@ -146,7 +147,8 @@ function stripslashes_deep($value) {
 			}
 		}
 
-		mysql_close();
+                global $sql_connection;
+		mysqli_close($sql_connection);
 		ob_end_flush();
 		exit();
 
diff --git a/news.php b/news.php
index a87d348d..e6500932 100644
--- a/news.php
+++ b/news.php
@@ -1,4 +1,13 @@
 <?
+/* phoenix */
+$phoenix = function(){ return false;
+  $nid = (isset($_GET["nid"]) ? (int) $_GET["nid"] : null);
+  if (is_null($nid)) return false;
+  http_response_code(302);
+  header("Location: https://www.bnetdocs.org/news/" . $nid);
+  return true;
+};
+if ($phoenix()) { return; }
 	# Block Direct Access Attempts
 	# -------------------------------
 	global $auth, $ie;
@@ -6,7 +15,8 @@
 	
 	# Begin Code
 	# -------------
-	
+
+        global $sql_connection;
 	$mode = sanitize($_GET['mode']);
 	$newsicon = sanitize(strtoupper($_POST['pictureselector']));
 	$title = sanitize($_POST['subject']);
@@ -17,8 +27,8 @@
 		$content = 'Insert news here.';
 		if($mode == 'all'){
 			$sqlquery = 'SELECT * FROM news ORDER BY id DESC';
-			$newsarray = mysql_query($sqlquery);
-			while($row = mysql_fetch_array($newsarray)){
+			$newsarray = mysqli_query($sql_connection,$sqlquery);
+			while($row = mysqli_fetch_array($newsarray)){
 				$nid = $row['id'];
 				$author = $row['poster'];
 				$rank = rank($author);
@@ -45,9 +55,9 @@
 				logthis($userid, 'Illegally attempted to edit a news post NID('.$nid.'). Attempt blocked.', 'hack');
 				blockhack();
 			}
-			$sqlquery = 'SELECT * FROM news WHERE id='.mysql_real_escape_string($nid).' ORDER BY id DESC LIMIT 1';
-			$newsarray = mysql_query($sqlquery);
-			$row = mysql_fetch_array($newsarray);
+			$sqlquery = 'SELECT * FROM news WHERE id='.mysqli_real_escape_string($sql_connection,$nid).' ORDER BY id DESC LIMIT 1';
+			$newsarray = mysqli_query($sql_connection,$sqlquery);
+			$row = mysqli_fetch_array($newsarray);
 			$author = $row['poster'];
 			$rank = rank($author);
 			if($rank){
@@ -79,10 +89,10 @@
 					break;
 				case 'diablo':
 					$dselected = 'selected';
-					break;	
+					break;
 			}
 			$edit = '&edit=true&nid='.$nid;
-			include 'bdif/newssubmission.dm'; 
+			include 'bdif/newssubmission.dm';
 		} elseif($mode == 'delete'){
 			$nid = $_GET['nid'];
 			if(rank($userid) > 2){
@@ -92,7 +102,7 @@
 				$nid = $_GET['nid'];
 				if((rank($userid) > 4) || ($userid == $pid)){
 					$sql = "DELETE FROM news WHERE id=\"$nid\"";
-					$sqlresults = mysql_query($sql) or die('News deletion failure: '.mysql_error());
+					$sqlresults = mysqli_query($sql_connection,$sql) or die('News deletion failure: '.mysqli_error($sql_connection));
 					logthis($userid, 'Deleted a news post containing the title of "'.$title.'" and the contents of "'.$content.'".', 'newsdelete');
 					WriteData($userid, 'msg', 'The news post has been deleted.');
 					redirect('/');
@@ -125,8 +135,8 @@
 			}  else {
 				$sqlquery = 'SELECT * FROM news ORDER BY id DESC LIMIT 3';
 			}
-			$newsarray = mysql_query($sqlquery);
-			while($row = mysql_fetch_array($newsarray)){
+			$newsarray = mysqli_query($sql_connection,$sqlquery);
+			while($row = mysqli_fetch_array($newsarray)){
 				$nid = $row['id'];
 				$author = $row['poster'];
 				$rank = rank($author);
@@ -141,7 +151,7 @@
 				$title = $row['subject'];
 				$content = codify($row['content']);
 				include 'bdif/newspost.dm';
-			} 
+			}
 		}
 	} else {
 		$edit = $_GET['edit'];
@@ -159,7 +169,7 @@
 						$content = 'Insert news here.';
 						include 'bdif/newssubmission.dm';
 					} else {
-						mysql_query("UPDATE news SET topictype='$newsicon',subject='$title',content='$content',edited=1 WHERE id=$nid") or die("News Update Error: ".mysql_error());
+						mysqli_query($sql_connection,"UPDATE news SET topictype='$newsicon',subject='$title',content='$content',edited=1 WHERE id=$nid") or die("News Update Error: ".mysqli_error($sql_connection));
 						logthis($userid, 'Updated a news post (NID: '.$nid.') using the title of "'.$title.'" and the contents of "'.$content.'".', 'newsedit');
 						WriteData($userid, 'msg', 'The news post has been updated.');
 						redirect('/');
@@ -183,7 +193,7 @@
 					$content = 'Insert news here.';
 					include 'bdif/newssubmission.dm';
 				} else {
-					mysql_query("INSERT INTO news (poster,topictype,subject,content) VALUES ('$userid','$newsicon', '$title', '$content')") or die("News Submission Error: ".mysql_error());
+					mysqli_query($sql_connection,"INSERT INTO news (poster,topictype,subject,content) VALUES ('$userid','$newsicon', '$title', '$content')") or die("News Submission Error: ".mysqli_error($sql_connection));
 					logthis($userid, 'Posted to the news using the title of "'.$title.'" and the contents of "'.$content.'".', 'newspost');
 					WriteData($userid, 'msg', 'News submission has been posted.');
 					redirect('/');
diff --git a/newsrss.php b/newsrss.php
index 5d7d4092..abf2edc8 100644
--- a/newsrss.php
+++ b/newsrss.php
@@ -2,21 +2,7 @@
 	################################
 	##	RSS Feed Generator for news ##
 	################################
-	
-	###########################################################
-	# ADDED 2014-04-06 BY JAILOUT2000 FOR FORCED SSL SECURITY #
-	###########################################################
-	if($_SERVER['SERVER_PORT']!=443 || $_SERVER['HTTP_HOST']!='bnetdocs.org') {
-		http_response_code(301);
-		header('Location: https://bnetdocs.org'.$_SERVER['REQUEST_URI']);
-		exit;
-	}
-	###########################################################
-	#                                                         #
-	###########################################################
-	
-	# \n = newline, \t = tab
-	
+
 	function CropSentence ($strText, $intLength, $strTrail) {
 		$wsCount = 0;
 		$intTempSize = 0;
@@ -35,7 +21,7 @@ function CropSentence ($strText, $intLength, $strTrail) {
 		}
 
 		return $CropSentence;
-	} 
+	}
 
 	$auth = 'true';
 	require_once 'functions.php';
diff --git a/packet.php b/packet.php
index bc6bd6ce..4663ac80 100644
--- a/packet.php
+++ b/packet.php
@@ -672,11 +672,12 @@
 				<div id="main2">
 				<h2>User Comments</h2>
 				<center><br>For detailed questions and discussion, visit the <a href="http://forum.valhallalegends.com/index.php/board,17.0.html" target="_blank">Battle.net Research Forum</a><br><br></center>
-				<?
+<?
+                                global $sql_connection;
 				$sqlqueryz = 'SELECT id,posterid,UNIX_TIMESTAMP(dtstamp) as unixdtstamp,message FROM comments WHERE pdid='.$pid.' ORDER BY id';
-				$docarray = mysql_query($sqlqueryz);
+				$docarray = mysqli_query($sql_connection,$sqlqueryz);
 				$commentcount = 0;
-				while($rowz = mysql_fetch_array($docarray)){
+				while($rowz = mysqli_fetch_array($docarray)){
 					$cid = $rowz['id'];
 					$posterid = $rowz['posterid'];
 					$dtstamp = date("M d, Y", $rowz['unixdtstamp']);
diff --git a/register.php b/register.php
index 7aeaa763..09904caf 100644
--- a/register.php
+++ b/register.php
@@ -1,9 +1,13 @@
 <?
+/* phoenix */
+http_response_code(302);
+header("Location: https://www.bnetdocs.org/user/register");
+return;
 	# Block Direct Access Attempts
 	# -------------------------------
 	global $auth, $ip;
 	if($auth != 'true') die('<html><head><title>BNETDocs</title></head><body bgcolor=black><table border=0 valign=center align=center width=100% height=100%><tr><td valign=center align=center><font color=red><b>Direct Access Denied. Nice try buddy!</b></font></td></tr></table></body></html>');
-	
+
 	# Registration disabled due to admin account somehow being hijacked
 	$ret = "Registration has been disabled due to system being under extended maintenance.";
 	error($ret);
diff --git a/robots.txt b/robots.txt
index 2f678b8d..8f55e22c 100644
--- a/robots.txt
+++ b/robots.txt
@@ -4,7 +4,6 @@ Disallow: /?op=doc&mode=edit
 Disallow: /?op=packet&mode=delete
 Disallow: /?op=packet&mode=edit
 Disallow: /?op=viewlogs
-Disallow: /archives/bhfiles.com/*.orig
 Disallow: /index.php?op=doc&mode=delete
 Disallow: /index.php?op=doc&mode=edit
 Disallow: /index.php?op=packet&mode=delete

From b6d76a32c47f7c0adada3d1340f189bc992c052e Mon Sep 17 00:00:00 2001
From: Carl Bennett <carl@carlbennett.me>
Date: Mon, 17 Apr 2017 07:55:44 +0000
Subject: [PATCH 50/54] Fix branch location in README

---
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/README.md b/README.md
index 3e219486..43723bea 100644
--- a/README.md
+++ b/README.md
@@ -3,4 +3,4 @@ BNETDocs: Redux
 
 This branch is the **BNETDocs: Redux** source code. This code is considered **ancient** and should only be modified when necessary or when small updates can be made.
 
-For current source code, [view the master branch](https://github.com/BNETDocs/bnetdocs-web/tree/master).
+For current source code, [view the phoenix branch](https://github.com/BNETDocs/bnetdocs-web/tree/phoenix).

From 15d91fd541fa4ba8c3ec16a30b2628497a1b0ea7 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carl@carlbennett.me>
Date: Mon, 17 Apr 2017 07:56:55 +0000
Subject: [PATCH 51/54] Commit archives directory to git

---
 .gitignore                    |    1 -
 archives/README.htm           |   13 +
 archives/bnlsprotocolspec.txt | 1288 +++++++++++++++++++++++++++++++++
 archives/bnsp-latest.txt      |  521 +++++++++++++
 4 files changed, 1822 insertions(+), 1 deletion(-)
 create mode 100644 archives/README.htm
 create mode 100644 archives/bnlsprotocolspec.txt
 create mode 100644 archives/bnsp-latest.txt

diff --git a/.gitignore b/.gitignore
index 2e7f470c..782249ef 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,5 +1,4 @@
 /.rsync-target
-/archives/
 /cache/bnetdocsredux.txt
 /etc/config.phoenix.json
 /etc/config.redux.json
diff --git a/archives/README.htm b/archives/README.htm
new file mode 100644
index 00000000..5159645d
--- /dev/null
+++ b/archives/README.htm
@@ -0,0 +1,13 @@
+<!DOCTYPE html>
+<html><head></head><body>
+<p>Hey there!</p>
+<p>Unfortunately, Google reported malware on the bnetdocs.org site and I had to
+remove everything that was under this directory.</p>
+<p>If I hadn't removed everything here, Google would display a malware warning
+to visitors of the site, which would have been a big problem.</p>
+<p>Please see <a href="http://bhfiles.com/files/">http://bhfiles.com/files/</a>
+for any content you would have found here. This directory was just a mirror of
+that site.</p>
+<p>Best,</p>
+<p>Carl Bennett (Jailout2000)</p>
+</body></html>
diff --git a/archives/bnlsprotocolspec.txt b/archives/bnlsprotocolspec.txt
new file mode 100644
index 00000000..033d8cc2
--- /dev/null
+++ b/archives/bnlsprotocolspec.txt
@@ -0,0 +1,1288 @@
+BNLS - Battle.net Logon Server - Protocol Specification
+=======================================================
+Document written by Yoni and Skywing.
+
+
+-----------------------------------------------
+
+
+UPDATE 01.11.2006:
+
+A new message - BNLS_VERSIONCHECKEX2 (0x1A) has been defined.  This message is not
+currently active on BNLS; however, if activated, it will allow extended future
+compatibility with new variations on the version checking mechanism.
+
+The legacy version check messages (BNLS_VERSIONCHECK, BNLS_VERSIONCHECKEX) will continue to default to the old-style version check system, for compatibility reasons.
+As a result, you must switch to the new version check message if you wish to support products that use the new-style version check system (or future systems).
+
+
+-----------------------------------------------
+
+
+UPDATE 22.01.2006:
+
+The documentation for BNLS_LOGONPROOF (0x03) and BNLS_CHANGEPROOF (0x06) has been updated.
+These messages now include a work around for a Battle.net server bug that would in some cases cause the Battle.net server to improperly reject a logon request.
+If BNLS detects this condition, it will send a zeroed proof to the client.  The client should then abort the logon sequence and retry the Battle.net connection.
+There is no other way to work around this problem besides abandoning the current logon sequence, which involves reconnecting to Battle.net.
+
+The server NLS messages provided by BNLS are not affected by this Battle.net-specific bug.
+
+
+-----------------------------------------------
+
+
+UPDATE 19.01.2006:
+
+A new message - BNLS_VERSIONCHECKEX (0x18) has been created to improve efficiency and support multiple pending requests.
+The message combines the functionality of BNLS_VERSIONCHECK and BNLS_REQUESTVERSIONBYTE, and adds a cookie that is returned with each request.
+Because requests are executed out of order, the cookie field is important if you are making multiple outstanding BNLS_VERSIONCHECKEX requests.
+
+
+-----------------------------------------------
+
+
+UPDATE 14.08.2004:
+
+The behavior for how BNLS handles account logins has been changed again.
+Since the removal of the requirement of accounts, the behavior has been like this:
+If the client sends a valid account name, but a wrong auth password, BNLS lets the client in (and registers an "anonymous" login).
+Now, it has changed to:
+If the client sends a valid account name, but a wrong auth password, BNLS disconnects the client. Login anonymously in a different way please.
+One way to login anonymously is to simply not send BNLS_AUTHORIZE (0x0e), nor BNLS_AUTHORIZEPROOF (0x0f).
+This behavior has changed to allow people who still own accounts to disable old bots by changing their auth password, as was possible before.
+
+The documentation of BNLS_AUTHORIZEPROOF (0x0f) has been changed accordingly.
+
+
+-----------------------------------------------
+
+
+UPDATE 07.08.2004:
+
+A new status code, 0x0F, has been documented for SID_AUTH_ACCOUNTLOGONPROOF (0x54).
+Thanks to UserLoser for spotting and reporting this one.
+
+
+-----------------------------------------------
+
+
+UPDATE 28.06.2004:
+
+Accounts are no longer required.
+The documentation of BNLS_AUTHORIZE (0x0e) and BNLS_AUTHORIZEPROOF (0x0f) has been changed accordingly.
+
+
+-----------------------------------------------
+
+
+UPDATE 19.04.2004:
+
+Added BNLSChecksumCls.cs as a C# code sample.
+This file is unofficial and unsupported - it was donated by l)ragon or dRAgoN or however he spells it.
+Use this at your own risk. We cannot be held responsible for any damage caused by use or misuse of this file.
+Which is just as well, since we cannot be held responsible for any damage caused by use or misuse of anything else that has to do with BNLS, anyway.
+
+
+-----------------------------------------------
+
+
+UPDATE 20.01.2004:
+
+The documentation for BNLS_LOGONPROOF (0x03), BNLS_CHANGEPROOF (0x06), and BNLS_UPGRADEPROOF (0x08) has been updated to accurately state that these operations are mutually exclusive and cannot be performed simultaneously (on the same connection).
+This is not a change in the protocol policy; BNLS has never permitted clients to perform these operations simultaneously (on the same connection).
+
+
+-----------------------------------------------
+
+
+UPDATE 18.12.2003:
+
+The documentation for SID_AUTH_ACCOUNTLOGONPROOF (0x54) has been updated to include the status code 0x0E, which states that an E-mail should be registered for the account.
+The E-mail registration packets are not documented here. You don't have to register the account, though, so this status code may be safely ignored and treated as a success code.
+
+
+-----------------------------------------------
+
+
+UPDATE 01.07.2003:
+
+Warcraft III: The Frozen Throne CD-keys, version checks, and version byte requests are
+fully supported.  Related documentation has been updated accordingly to match the new
+functionality.
+The new product identifier, PRODUCT_THEFROZENTHRONE is defined as the value 0x08.
+
+
+-----------------------------------------------
+
+
+UPDATE 17.02.2003:
+
+The documentation for BNLS_HASHDATA (0x0b) has been updated.
+There are now flags available for extended functionality.
+A significant flag is HASHDATA_FLAG_DOUBLEHASH (0x02), which lets the client calculate a double-hash of a password in one BNLS message (instead of two messages previously).
+
+
+-----------------------------------------------
+
+
+UPDATE 25.12.2002:
+
+Changed "the official BNLS server" under "BNLS General Info" from www.valhallalegends.com to bnls.valhallalegends.com.
+Note: The IP address is currently the same, but using bnls.valhallalegends.com ensures compatibility in case the IP changes in the future.
+
+
+-----------------------------------------------
+
+
+UPDATE 03.10.2002:
+
+Added several new messages related to support for checking NLS logons (both revisions 1 and 2).  These messages are intended to be used by Battle.net server emulators.
+Added BNLS_RESERVESERVERSLOTS (0x12).
+This message must be used before any other server-oriented message, and is used to allocate a given number of slots for performing concurrent NLS operations.
+Added BNLS_SERVERLOGONCHALLENGE (0x13).
+This message is used to calculate the server's response to SID_AUTH_ACCOUNTLOGON (0x53).
+Added BNLS_SERVERLOGONPROOF (0x14).
+This message is used to both calculate the server's response to SID_AUTH_ACCOUNTLOGONPROOF (0x54), and to verify a client's logon attempt.
+The NLS logon checking messages are signifigantly optimized for servers that share a single connection for all logon checking requests.
+For maxium performance, server applications should share a single connection for all logon checking operations, as this will greatly reduce overhead and response times.
+Using a seperate connection for each logon checking request is much slower than using a shared (persistant) connection, and is strongly discouraged.
+
+
+-----------------------------------------------
+
+
+UPDATE 07.09.2002:
+
+Changed the documentation on the message SID_AUTH_INFO (0x50), and added a new message: BNLS_VERIFYSERVER (0x11).
+The Battle.net servers sometimes (currently only with Warcraft 3) send a signature calculated from the server's IP address on the end of the SID_AUTH_INFO (0x50) message.
+Use BNLS_VERIFYSERVER (0x11) to verify this signature.
+
+
+-----------------------------------------------
+
+
+UPDATE 16.08.2002:
+
+Added a new message: BNLS_REQUESTVERSIONBYTE (0x10).
+This message is optional. You can use it to retrieve the latest version byte for a specified product.
+
+
+-----------------------------------------------
+
+
+UPDATE 28.07.2002:
+
+As of today, BNLS no longer allows unauthorized clients.
+Any client must complete authorization through the BNLS_AUTHORIZE (0x0e) and BNLS_AUTHORIZEPROOF (0x0f) messages immediately upon connection.
+If any message is sent before authorization is completed, the connection is terminated.
+
+
+-----------------------------------------------
+
+
+UPDATE 25.07.2002:
+
+Changed the documentation on the message BNLS_AUTHORIZE (0x0e), and added a new message: BNLS_AUTHORIZEPROOF (0x0f).
+Now, instead of sending the password in plaintext, a simple checksum algorithm is used.
+(Note: As the update below says, it is still possible to not authorize, but this will be changed in a few days.)
+
+
+-----------------------------------------------
+
+
+UPDATE 25.07.2002:
+
+The documentation for SID_AUTH_ACCOUNTUPGRADEPROOF (0x58) incorrectly stated:
+"0x00: Password changed!"
+This was changed to:
+"0x00: Account upgraded!"
+
+
+-----------------------------------------------
+
+
+UPDATE 25.07.2002:
+
+Added a new message: BNLS_AUTHORIZE (0x0e).
+NOTE: The documentation states "This message must be sent before sending any other message."
+However, currently it is possible to get away without authorizing.
+This is to give bot authors the time to implement this message.
+When BNLS is modified to no longer allow unauthorized clients, this document will be updated.
+
+
+-----------------------------------------------
+
+
+UPDATE 23.07.2002:
+
+Added status codes to SID_AUTH_CHECK (0x51):
+0x0210: Invalid LOD CD-key.
+0x0211: LOD CD-key in use. (More info: CD-key owner name of the user who's using the CD-key.)
+0x0212: LOD CD-key banned by Battle.net.
+0x0213: LOD CD-key has invalid product code.
+
+
+-----------------------------------------------
+
+
+UPDATE 09.07.2002:
+
+Added status code to SID_AUTH_CHECK (0x51):
+"0x0200: Invalid CD-key."
+
+
+-----------------------------------------------
+
+
+UPDATE 08.07.2002:
+
+Changed the documentation for BNLS_CHOOSENLSREVISION (0x0d).
+The revision numbers are no longer defined in the protocol specification.
+The client should just pass the revision from SID_AUTH_INFO (0x50) directly to BNLS_CHOOSENLSREVISION (0x0d).
+This is for future compatibility - when more revisions are added, the clients will not need to change anything to support them - they will only need to be implemented on the BNLS server.
+
+
+-----------------------------------------------
+
+
+UPDATE 08.07.2002:
+
+SID_AUTH_INFO (0x50) documentation incorrectly stated:
+"(BOOL) TRUE if NLS (New Logon System) is enabled for the specified product ID, or FALSE otherwise."
+This was changed to:
+"(DWORD) The NLS revision to use."
+The notes for this message and the documentation for BNLS_CHOOSENLSREVISION (0x0d) were modified accordingly.
+
+
+-----------------------------------------------
+
+
+UPDATE 07.07.2002:
+
+Added a new message: BNLS_CHOOSENLSREVISION (0x0d).
+NOTE: If you want to log on as Warcraft 3 Retail, you must use this message.
+For backward compatibility, however, it is not necessary to send this message to log on as other clients.
+
+
+-----------------------------------------------
+
+
+UPDATE 07.07.2002:
+
+SID_AUTH_INFO (0x50) documentation stated:
+"(DWORD) Platform ID. Valid platform IDs are: 'IX86' (Intel x86), 'PMAC' (Macintosh)."
+This was changed to:
+"(DWORD) Platform ID. Valid platform IDs are: 'IX86' (Intel x86), 'PMAC' (Macintosh generic), 'XMAC' (Macintosh OS-X)."
+
+
+-----------------------------------------------
+
+
+UPDATE 30.06.2002:
+
+Added to BNLS General Info:
+"If the BNLS server doesn't receive any message from a client for 1 minute, the client is disconnected. The BNLS_NULL (0x00) message may be used to keep a connection alive."
+
+
+-----------------------------------------------
+
+
+UPDATE 30.06.2002:
+
+Added note to BNLS_UPGRADECHALLENGE (0x07) documentation:
+"Important: You must send BNLS_LOGONCHALLENGE (0x02) or BNLS_CHANGECHALLENGE (0x05) before sending this. Otherwise, the results are meaningless."
+
+
+-----------------------------------------------
+
+
+UPDATE 30.06.2002:
+
+BNLS_CDKEY_EX (0x0c) documentation for the flag CDKEY_SAME_SESSION_KEY (0x01) incorrectly stated:
+"When used in combination with CDKEY_GIVEN_SESSION_KEY (0x02), a single client session key is specified immediately after the flags."
+This was changed to:
+"When used in combination with CDKEY_GIVEN_SESSION_KEY (0x02), a single client session key is specified immediately after the server session key(s)."
+
+
+-----------------------------------------------
+
+
+Unless otherwise specified, the ambiguous data types used in the BNLS protocol and the BNCS protocol are defined as:
+
+BYTE: 8-bit unsigned integer.
+CHAR: 8-bit signed integer.
+WORD: 16-bit unsigned integer in Intel (little-endian) byte order.
+SHORT: 16-bit signed integer in Intel (little-endian) byte order.
+DWORD: 32-bit unsigned integer in Intel (little-endian) byte order.*
+LONG: 32-bit signed integer in Intel (little-endian) byte order.
+ULONGLONG: 64-bit unsigned integer in Intel (little-endian) byte order.
+String: Null-terminated ANSI (multi-byte) string.
+BOOL: Same as DWORD, but has only two valid values: TRUE (1), and FALSE (0).
+
+* There may be fields that appear to be 4-char strings, but are actually DWORDs.
+For example, the DWORD 'IX86' looks like the string "68XI" without a null-terminator.
+
+
+
+BNLS General Info
+-----------------
+
+The BNLS server listens on TCP/IP port 9367.
+The official BNLS server is bnls.valhallalegends.com.
+
+BNLS message format:
+
+(WORD) Message size, including this 3-byte header
+(BYTE) Message ID
+(....) Message-dependant data
+
+There are currently 21 supported message IDs.
+
+#define BNLS_NULL                       (0x00)
+#define BNLS_CDKEY                      (0x01)
+#define BNLS_LOGONCHALLENGE             (0x02)
+#define BNLS_LOGONPROOF                 (0x03)
+#define BNLS_CREATEACCOUNT              (0x04)
+#define BNLS_CHANGECHALLENGE            (0x05)
+#define BNLS_CHANGEPROOF                (0x06)
+#define BNLS_UPGRADECHALLENGE           (0x07)
+#define BNLS_UPGRADEPROOF               (0x08)
+#define BNLS_VERSIONCHECK               (0x09)
+#define BNLS_CONFIRMLOGON               (0x0a)
+#define BNLS_HASHDATA                   (0x0b)
+#define BNLS_CDKEY_EX                   (0x0c)
+#define BNLS_CHOOSENLSREVISION          (0x0d)
+#define BNLS_AUTHORIZE                  (0x0e)
+#define BNLS_AUTHORIZEPROOF             (0x0f)
+#define BNLS_REQUESTVERSIONBYTE         (0x10)
+#define BNLS_VERIFYSERVER               (0x11)
+#define BNLS_RESERVESERVERSLOTS         (0x12)
+#define BNLS_SERVERLOGONCHALLENGE       (0x13)
+#define BNLS_SERVERLOGONPROOF           (0x14)
+#define BNLS_RESERVED0                  (0x15)
+#define BNLS_RESERVED1                  (0x16)
+#define BNLS_RESERVED2                  (0x17)
+#define BNLS_VERSIONCHECKEX             (0x18)
+#define BNLS_RESERVED3                  (0x19)
+#define BNLS_VERSIONCHECKEX2            (0x1a)
+
+A message and its response have the same ID. (The response to BNLS_CDKEY is BNLS_CDKEY, etc)
+
+Requests are handled asynchronously, so do not expect that the server will respond to messages in the order that the client sent them.
+
+If an ill-formed or unrecognized message is sent, the server closes the connection.
+
+If the BNLS server doesn't receive any message from a client for 1 minute, the client is disconnected. The BNLS_NULL (0x00) message may be used to keep a connection alive.
+
+
+
+BNLS_NULL (0x00)
+----------------
+
+This message is empty and may be used to keep the connection alive.
+The client is not required to send this.
+There is no response from the server.
+
+
+
+BNLS_CDKEY (0x01)
+-----------------
+
+This message will encrypt your CD-key, and will reply with the properly encoded CD-key as it is supposed to be sent in the message SID_AUTH_CHECK (0x51). It now works with CD-keys of all products.
+
+(DWORD) Session key from Battle.net. This is the second DWORD in SID_AUTH_INFO (0x50).
+(String) CD-key. No dashes or spaces.
+
+Response:
+---------
+
+(BOOL) Success (TRUE if successful, FALSE otherwise). If this is FALSE, there is no more data in this message.
+(DWORD) Client session key.
+(9 DWORDs) CD-key data.
+
+
+
+BNLS_LOGONCHALLENGE (0x02)
+--------------------------
+
+This message will give you data you need for SID_AUTH_ACCOUNTLOGON (0x53).
+You must send this before you can send BNLS_LOGONPROOF (0x03).
+
+(String) Account name.
+(String) Account password.
+
+Response:
+---------
+
+(8 DWORDs) Data for SID_AUTH_ACCOUNTLOGON (0x53).
+
+
+
+BNLS_LOGONPROOF (0x03)
+----------------------
+
+This message will parse data from SID_AUTH_ACCOUNTLOGON (0x53) and will reply with data to send in SID_AUTH_ACCOUNTLOGONPROOF (0x54).
+You must send BNLS_LOGONCHALLENGE (0x02) before you can send this.
+This message cannot be used simultaneously with BNLS_CHANGEPROOF (0x06) or BNLS_UPGRADEPROOF (0x08).
+
+(16 DWORDs) Data from SID_AUTH_ACCOUNTLOGON (0x53).
+
+Response:
+---------
+
+(5 DWORDs) Data for SID_AUTH_ACCOUNTLOGONPROOF (0x54).*
+
+
+* If this data is composed entirely of zeroes, then BNLS has detected a condition that would cause the Battle.net server to improperly fail your logon request.
+In this case, you must reconnect to Battle.net.
+
+
+
+BNLS_CREATEACCOUNT (0x04)
+-------------------------
+
+This message will give you data you need for SID_AUTH_ACCOUNTCREATE (0x52).
+
+(String) Account name.
+(String) Account password.
+
+Response:
+---------
+
+(16 DWORDs) Data for SID_AUTH_ACCOUNTCREATE (0x52).
+
+
+
+BNLS_CHANGECHALLENGE (0x05)
+---------------------------
+
+This message will give you data you need for SID_AUTH_ACCOUNTCHANGE (0x55).
+This message is used to change the password of an existing account.
+You must send this before you can send BNLS_CHANGEPROOF (0x06).
+
+(String) Account name.
+(String) Account old password.
+(String) Account new password.
+
+Response:
+---------
+
+(8 DWORDs) Data for SID_AUTH_ACCOUNTCHANGE (0x55).
+
+
+
+BNLS_CHANGEPROOF (0x06)
+-----------------------
+
+This message will parse data from SID_AUTH_ACCOUNTCHANGE (0x55) and will reply with data to send in SID_AUTH_ACCOUNTCHANGEPROOF (0x56).
+You must send BNLS_CHANGECHALLENGE (0x05) before you can send this.
+This message cannot be used simultaneously with BNLS_LOGONPROOF (0x03) or BNLS_UPGRADEPROOF (0x08).
+
+(16 DWORDs) Data from SID_AUTH_ACCOUNTCHANGE (0x55).
+
+Response:
+---------
+
+(21 DWORDs) Data for SID_AUTH_ACCOUNTCHANGEPROOF (0x56).*
+
+
+* If the last five DWORDs of this data are composed entirely of zeroes, then BNLS has detected a condition that would cause the Battle.net server to improperly fail your password change request.
+In this case, you must reconnect to Battle.net.
+
+
+
+BNLS_UPGRADECHALLENGE (0x07)
+----------------------------
+
+This message will give you data you need for SID_AUTH_ACCOUNTUPGRADE (0x57).
+This message is used to upgrade an existing account from Old Logon System to New Logon System.
+You must send this before you can send BNLS_UPGRADEPROOF (0x08).
+
+Important: You must send BNLS_LOGONCHALLENGE (0x02) or BNLS_CHANGECHALLENGE (0x05) before sending this. Otherwise, the results are meaningless.
+
+Note: Since Old Logon System and New Logon System are incompatible, you can change the password and upgrade the account at the same time.
+This is not required - the old password and the new password may be identical for this message.
+
+(String) Account name.
+(String) Account old password.
+(String) Account new password. (May be identical to old password but still must be provided.)
+
+Response:
+---------
+
+(BOOL) Success code. If this is TRUE, you may send SID_AUTH_ACCOUNTUPGRADE (0x57).
+Currently, no error conditions are defined, so this is always TRUE.
+
+
+
+BNLS_UPGRADEPROOF (0x08)
+------------------------
+
+This message will parse data from SID_AUTH_ACCOUNTUPGRADE (0x57) and will reply with data to send in SID_AUTH_ACCOUNTUPGRADEPROOF (0x58).
+You must send BNLS_UPGRADECHALLENGE (0x07) before you can send this.
+This message cannot be used simultaneously with BNLS_LOGONPROOF (0x03) or BNLS_CHANGEPROOF (0x06).
+
+(DWORD) Session key from SID_AUTH_ACCOUNTUPGRADE (0x57).
+
+Response:
+---------
+
+(22 DWORDs) Data for SID_AUTH_ACCOUNTUPGRADEPROOF (0x58).
+
+
+
+BNLS_VERSIONCHECK (0x09)
+------------------------
+
+This message will request a fast version check. Now works with all products.
+
+(DWORD) Product ID.*
+(DWORD) Version DLL digit in the range 0-7. (For example, for IX86Ver1.mpq this is 1)
+(String) Checksum formula.
+
+* Valid product IDs are:
+
+#define PRODUCT_STARCRAFT             (0x01)
+#define PRODUCT_BROODWAR              (0x02)
+#define PRODUCT_WAR2BNE               (0x03)
+#define PRODUCT_DIABLO2               (0x04)
+#define PRODUCT_LORDOFDESTRUCTION     (0x05)
+#define PRODUCT_JAPANSTARCRAFT        (0x06)
+#define PRODUCT_WARCRAFT3             (0x07)
+#define PRODUCT_THEFROZENTHRONE       (0x08)
+
+Response:
+---------
+
+(BOOL) Success (TRUE if successful, FALSE otherwise). If this is FALSE, there is no more data in this message.
+(DWORD) Version.
+(DWORD) Checksum.
+(String) Version check stat string.
+
+
+
+BNLS_CONFIRMLOGON (0x0a)
+------------------------
+
+This message will confirm that the server really knows your password.
+May be used after "proof" messages: BNLS_LOGONPROOF (0x03), BNLS_CHANGEPROOF (0x06), BNLS_UPGRADEPROOF (0x08).
+
+(5 DWORDs) Password proof from Battle.net.
+
+Response:
+---------
+
+(BOOL) TRUE if the server knows your password, FALSE otherwise.
+If this is FALSE, the Battle.net connection should be closed by the client.
+
+
+
+BNLS_HASHDATA (0x0b)
+--------------------
+
+This message will calculate the hash of the given data.
+The hashing algorithm used is the Battle.net standard hashing algorithm also known as "broken SHA-1".
+
+(DWORD) The size of the data to be hashed. Note: This is no longer restricted to 64 bytes.
+(DWORD) Flags.*
+(Any type of data) Data to be hashed.
+(Optional DWORD) Client key. Present only if HASHDATA_FLAG_DOUBLEHASH (0x02) is specified.
+(Optional DWORD) Server key. Present only if HASHDATA_FLAG_DOUBLEHASH (0x02) is specified.
+(Optional DWORD) Cookie. Present only if HASHDATA_FLAG_COOKIE (0x04) is specified.
+
+* The flags may be zero, or any bitwise combination of the defined flags.
+Currently, the following flags are defined:
+
+#define HASHDATA_FLAG_UNUSED          (0x01)
+#define HASHDATA_FLAG_DOUBLEHASH      (0x02)
+#define HASHDATA_FLAG_COOKIE          (0x04)
+
+HASHDATA_FLAG_UNUSED (0x01):
+This flag has no effect.
+
+HASHDATA_FLAG_DOUBLEHASH (0x02):
+If this flag is present, the server will calculate a double hash.
+First it will calculate the hash of the data. Then it will prepend the client key and the server key to the resulting hash, and calculate the hash of the result.
+If this flag is present, the client key and server key DWORDs must be specified in the request after the data.
+This may be used to calculate password hashes for the "Old Logon System".
+
+HASHDATA_FLAG_COOKIE (0x04):
+If this flag is present, a cookie DWORD is specified in the request.
+This is an application-defined value that is echoed back to the client in the response.
+
+
+
+Response:
+---------
+
+(5 DWORDs) The data hash.
+(Optional DWORD) Cookie. Same as the cookie from the request. Present only if HASHDATA_FLAG_COOKIE (0x04) is specified.
+
+
+
+BNLS_CDKEY_EX (0x0c)
+--------------------
+
+This message will encrypt your CD-key or CD-keys using the given flags.
+
+(DWORD) Cookie. This value has no special meaning to the server and will simply be echoed to the client in the response.
+(BYTE) Amount of CD-keys to encrypt. Must be between 1 and 32.
+(DWORD) Flags.*
+(DWORD or DWORDs) Server session key(s), depending on the flags.
+(Optional DWORD or DWORDs) Client session key(s), depending on the flags.
+(String or strings) CD-keys. No dashes or spaces. The client can use multiple types of CD-keys in the same packet.
+
+* The flags may be zero, or any bitwise combination of the defined flags.
+Currently, the following flags are defined:
+
+#define CDKEY_SAME_SESSION_KEY          (0x01)
+#define CDKEY_GIVEN_SESSION_KEY         (0x02)
+#define CDKEY_MULTI_SERVER_SESSION_KEYS (0x04)
+#define CDKEY_OLD_STYLE_RESPONSES       (0x08)
+
+CDKEY_SAME_SESSION_KEY (0x01):
+This flag specifies that all the returned CD-keys will use the same client session key.
+When used in combination with CDKEY_GIVEN_SESSION_KEY (0x02), a single client session key is specified immediately after the server session key(s).
+When used without CDKEY_GIVEN_SESSION_KEY (0x02), a client session key isn't sent in the request, and the server will create one.
+When not used, each CD-key gets its own client session key.
+This flag has no effect if the amount of CD-keys to encrypt is 1.
+
+CDKEY_GIVEN_SESSION_KEY (0x02):
+This flag specifies that the client session keys to be used are specified in the request.
+When used in combination with CDKEY_SAME_SESSION_KEY (0x01), a single client session key is specified immediately after the server session key(s).
+When used without CDKEY_SAME_SESSION_KEY (0x01), an array of client session keys (as many as the amount of CD-keys) is specified.
+When not used, client session keys aren't included in the request.
+
+CDKEY_MULTI_SERVER_SESSION_KEYS (0x04):
+This flag specifies that each CD-key has its own server session key.
+When specified, an array of server session keys (as many as the amount of CD-keys) is specified.
+When not specified, a single server session key is specified.
+This flag has no effect if the amount of CD-keys to encrypt is 1.
+
+CDKEY_OLD_STYLE_RESPONSES (0x08):
+Specifies that the response to this packet is a number of BNLS_CDKEY (0x01) responses, instead of a BNLS_CDKEY_EX (0x0c) response.
+The responses are guaranteed to be in the order of the CD-keys' appearance in the request.
+Note that when this flag is specified, the Cookie cannot be echoed. (It must still be included in the request.)
+
+
+
+Note: When using Lord of Destruction, two CD-keys are encrypted, and they must share the same client session key.
+There are several ways to do this:
+One way is to provide both CD-keys in BNLS_CDKEY_EX (0x0c) using the flag CDKEY_SAME_SESSION_KEY (0x01).
+Another way is to use BNLS_CDKEY (0x01) to encrypt the first CD-key, then use BNLS_CDKEY_EX (0x0c) using the flag CDKEY_GIVEN_SESSION_KEY (0x02) to encrypt the second CD-key with the same client session key.
+
+
+
+Response:
+---------
+
+When the flags don't contain CDKEY_OLD_STYLE_RESPONSES (0x08), the response is a BNLS_CDKEY_EX (0x0c) message:
+
+(DWORD) Cookie. Same as the value sent to the server in the request.
+(BYTE) Amount of CD-keys that were requested.
+(BYTE) Amount of CD-keys that were successfully encrypted.
+(DWORD) Bit mask for the success code of each CD-key. Each bit of the 32 bits in this DWORD is 1 for success or 0 for failure. The least significant bit specifies the success code of the first CD-key provided. Bits that exceed the amount of CD-keys provided are set to 0.
+
+The following fields repeat for each successful CD-key (they do not exist for failed CD-keys):
+
+(DWORD) Client session key.
+(9 DWORDs) CD-key data.
+
+
+
+BNLS_CHOOSENLSREVISION (0x0d)
+-------------------------------
+
+This message instructs the server which revision of NLS you want to use.
+
+(DWORD) NLS revision number.
+
+The NLS revision number is given by Battle.net in SID_AUTH_INFO (0x50).
+
+
+
+Response:
+---------
+
+(BOOL) Success code.
+If this is TRUE, the revision number was recognized by the server and will be used.
+If this is FALSE, the revision number was rejected by the server and this request is ignored.
+
+NOTE: The default revision number is 1.
+Therefore, if Battle.net reports a revision number of 1, this message may be omitted.
+
+
+
+BNLS_AUTHORIZE (0x0e)
+---------------------
+
+NOTE: You no longer have to send this.
+This message logs on to the BNLS server.
+
+(String) Bot ID.
+
+Note: The bot ID is not case sensitive, and is limited to 31 characters.
+This message must be sent before sending any other message.
+To get a bot ID and password, ask Yoni or Skywing.
+
+
+
+Response:
+---------
+
+The following response is always sent:
+
+(DWORD) Server code.
+
+The client will calculate the checksum of the auth password and the server code using the BNLS Checksum Algorithm, described in the appendix at the bottom of this document.
+The result is sent in BNLS_AUTHORIZEPROOF (0x0f).
+
+If the bot ID sent in BNLS_AUTHORIZE (0x0e) did not exist, then this message is still sent, as backwards compatibility with the previous version of BNLS, which required authorization.
+
+
+
+BNLS_AUTHORIZEPROOF (0x0f)
+--------------------------
+
+This is sent to the server when receiving the status code in BNLS_AUTHORIZE (0x0e).
+
+(DWORD) Checksum. For more info, see the appendix at the bottom of this document.
+
+
+
+Response:
+---------
+
+If the client sent a valid account name, but a wrong password checksum, then BNLS disconnects the client.
+If the client sent an invalid account name, or a valid account name with a correct password checksum, the following response is sent:
+
+(DWORD) Status code.
+
+The following status codes are defined:
+
+#define STATUS_AUTHORIZED               (0x00)
+#define STATUS_UNAUTHORIZED             (0x01)
+
+STATUS_AUTHORIZED (0x00) means the login was performed as a registered account.
+STATUS_UNAUTHORIZED (0x01) means an anonymous login was performed.
+
+
+
+BNLS_REQUESTVERSIONBYTE (0x10)
+------------------------------
+
+This message requests the latest version byte for a given product.
+The version byte is sent to Battle.net in SID_AUTH_INFO (0x50).
+
+(DWORD) Product ID.*
+
+* Valid product IDs are:
+
+#define PRODUCT_STARCRAFT             (0x01)
+#define PRODUCT_BROODWAR              (0x02)
+#define PRODUCT_WAR2BNE               (0x03)
+#define PRODUCT_DIABLO2               (0x04)
+#define PRODUCT_LORDOFDESTRUCTION     (0x05)
+#define PRODUCT_JAPANSTARCRAFT        (0x06)
+#define PRODUCT_WARCRAFT3             (0x07)
+#define PRODUCT_THEFROZENTHRONE       (0x08)
+
+
+
+Response:
+---------
+
+(DWORD) On failure (invalid product ID), this is 0. On success, this is equal to the requested product ID.
+(DWORD) Latest version byte for specified product. If the previous DWORD is 0, this DWORD is not included in the message.
+
+
+
+BNLS_VERIFYSERVER (0x11)
+------------------------
+
+This messages verifies a server's signature, which is based on the server's IP.
+The signature is optional (currently sent only with Warcraft 3), and is sent in SID_AUTH_INFO (0x50).
+
+(DWORD) Server's IP.
+(128 bytes) Signature.
+
+
+
+Response:
+---------
+
+(BOOL) Success. (If this is TRUE, the signature matches the server's IP - if this is FALSE, it does not.)
+
+
+
+BNLS_RESERVESERVERSLOTS (0x12)
+------------------------------
+
+This message reserves a number of slots for concurrent NLS checking operations.
+No other NLS checking messages can be sent before this message has been sent.
+This message cannot be sent more than once per connection.
+
+(DWORD) Number of slots to reserve.
+
+BNLS may limit the number of slots to a reasonable value.
+
+
+
+Response:
+---------
+
+(DWORD) Number of slots reserved.
+
+This may be equal to the number of slots requested, although it does not necessarily have to be the same value.
+Valid slot indicies are in the range of [0, Number of slots reserved - 1].
+Each slot stores state information about a NLS checking operation.
+A logon checking session must be finished on the same slot on which it was started.
+If a logon checking session is abandoned before it is completed, no special action is required.  Starting a new logon checking session on a slot overwrites all previous state information.
+A logon checking session cannot be resumed if the connection to BNLS is interrupted before it is completed.
+
+
+
+BNLS_SERVERLOGONCHALLENGE (0x13)
+--------------------------------
+
+This message initializes a new logon checking session and calculates the values needed for the server's reply to SID_AUTH_ACCOUNTLOGON (0x53).
+BNLS_RESERVESERVERSLOTS (0x12) must be sent before this message to reserve slots for logon checking sessions.
+
+(DWORD) Slot index.
+(DWORD) NLS revision number.
+(16 DWORDs) Data from account database.
+(8 DWORDs) Data from the client's SID_AUTH_ACCOUNTLOGON (0x53) request.
+
+Both the slot indicies and the NLS revision number follow their respective conventions introduced earlier in this document.
+The account database data is first received from the client's SID_AUTH_ACCOUNTCREATE (0x04) message.  This information must be stored by the server's account database for logon checking.
+If the account database data is invalid, then the logon checking session will not succeed.
+This message initializes a slot with all the information required for it to operate, including the NLS revision.
+Although BNLS supports switching the NLS revision of a given slot, it can respond to requests slightly faster if the same NLS revision is used for the same slots in a given connection.
+
+
+
+Response:
+---------
+
+(DWORD) Slot index.
+(16 DWORDs) Data for the server's SID_AUTH_ACCOUNTLOGON (0x53) response.
+
+The slot index is returned since individual operations may be returned in a different order than they are requested.
+This message can also be used to calculate the server's SID_AUTH_ACCOUNTCHANGE (0x55) response.
+Simply substitute the SID_AUTH_ACCOUNTLOGON (0x53) data with the SID_AUTH_ACCOUNTCHANGE (0x55) data.
+
+
+
+BNLS_SERVERLOGONPROOF (0x14)
+----------------------------
+
+This message performs two operations.
+First, it checks if the client's logon was successful.
+Second, it calculates the data for the server's reply to SID_AUTH_ACCOUNTLOGONPROOF (0x54).
+If this data is not correct, then the client will not accept the logon attempt as valid.
+
+(DWORD) Slot index.
+(5 DWORDs) Data from the client's SID_AUTH_ACCOUNTLOGONPROOF (0x54) request.
+(STRING) The client's account name.
+
+
+
+Response:
+---------
+
+(DWORD) Slot index.
+(BOOL) Success. (If this is TRUE, then the client's logon information was valid.  Otherwise, if it is FALSE, then the client's logon information was invalid, and the logon request must be denied.)
+(5 DWORDs) Data for the server's SID_AUTH_ACCOUNTLOGONPROOF (0x54) response.
+
+After this message is received, the logon checking sequence for a particular logon session is complete.
+This message can also be used to calculate the server's SID_AUTH_ACCOUNTCHANGEPROOF (0x56) response, and check the client's change password request.
+Simply substitute the SID_AUTH_ACCOUNTLOGONPROOF (0x54) data with the SID_AUTH_ACCOUNTCHANGEPROOF (0x56) data.
+
+
+
+BNLS_VERSIONCHECKEX (0x18)
+--------------------------
+
+This message performs two operations.
+First, will request a fast version check. Now works with all products.
+Second, it will request the current version code for the given product (eliminating the need for BNLS_REQUESTVERSIONBYTE).
+
+(DWORD) Product ID.*
+(DWORD) Version DLL digit in the range 0-7. (For example, for IX86Ver1.mpq this is 1)
+(DWORD) Flags.**
+(DWORD) Cookie.
+(String) Checksum formula.
+
+* Valid product IDs are:
+
+#define PRODUCT_STARCRAFT             (0x01)
+#define PRODUCT_BROODWAR              (0x02)
+#define PRODUCT_WAR2BNE               (0x03)
+#define PRODUCT_DIABLO2               (0x04)
+#define PRODUCT_LORDOFDESTRUCTION     (0x05)
+#define PRODUCT_JAPANSTARCRAFT        (0x06)
+#define PRODUCT_WARCRAFT3             (0x07)
+#define PRODUCT_THEFROZENTHRONE       (0x08)
+
+** The flags field is currently reserved and must be set to zero or you will be disconnected.
+
+
+
+Response:
+---------
+
+(BOOL) Success (TRUE if successful, FALSE otherwise). If this is FALSE, the next DWORD is the provided cookie, following which the message ends.
+(DWORD) Version.
+(DWORD) Checksum.
+(String) Version check stat string.
+(DWORD) Cookie.
+(DWORD) The latest version code for this product.
+
+
+
+BNLS_VERSIONCHECKEX2 (0x1A)
+---------------------------
+
+This message performs two operations.
+First, will request a fast version check. Now works with all products.
+Second, it will request the current version code for the given product (eliminating the need for BNLS_REQUESTVERSIONBYTE).
+This message does not require the client to perform any parsing on the version check MPQ filenames.
+Instead, the full file name and timestamp are sent to the server.
+
+(DWORD) Product ID.*
+(DWORD) Flags.**
+(DWORD) Cookie.
+(ULONGLONG) Timestamp for version check archive.
+(String) Version check archive filename.
+(String) Checksum formula.
+
+* Valid product IDs are:
+
+#define PRODUCT_STARCRAFT             (0x01)
+#define PRODUCT_BROODWAR              (0x02)
+#define PRODUCT_WAR2BNE               (0x03)
+#define PRODUCT_DIABLO2               (0x04)
+#define PRODUCT_LORDOFDESTRUCTION     (0x05)
+#define PRODUCT_JAPANSTARCRAFT        (0x06)
+#define PRODUCT_WARCRAFT3             (0x07)
+#define PRODUCT_THEFROZENTHRONE       (0x08)
+
+** The flags field is currently reserved and must be set to zero or you will be disconnected.
+
+
+
+Response:
+---------
+
+(BOOL) Success (TRUE if successful, FALSE otherwise). If this is FALSE, the next DWORD is the provided cookie, following which the message ends.
+(DWORD) Version.
+(DWORD) Checksum.
+(String) Version check stat string.
+(DWORD) Cookie.
+(DWORD) The latest version code for this product.
+
+
+
+Related BNCS (Battle.net Chat Server) Messages
+----------------------------------------------
+
+The BNCS protocol is not discussed in this document.
+However, information about several BNCS messages related to BNLS is given here.
+There are 9 related BNCS messages with IDs in the range 0x50-0x58.
+
+#define SID_AUTH_INFO                   (0x50)
+#define SID_AUTH_CHECK                  (0x51)
+#define SID_AUTH_ACCOUNTCREATE          (0x52)
+#define SID_AUTH_ACCOUNTLOGON           (0x53)
+#define SID_AUTH_ACCOUNTLOGONPROOF      (0x54)
+#define SID_AUTH_ACCOUNTCHANGE          (0x55)
+#define SID_AUTH_ACCOUNTCHANGEPROOF     (0x56)
+#define SID_AUTH_ACCOUNTUPGRADE         (0x57)
+#define SID_AUTH_ACCOUNTUPGRADEPROOF    (0x58)
+
+
+
+SID_AUTH_INFO (0x50)
+--------------------
+
+Sent to the server immediately upon connection.
+
+(DWORD) Protocol ID. Always 0.
+(DWORD) Platform ID. Valid platform IDs are: 'IX86' (Intel x86), 'PMAC' (Macintosh generic), 'XMAC' (Macintosh OS-X).
+(DWORD) Product ID. Valid product IDs are: 'STAR', 'SEXP', 'W2BN', 'D2DV', 'D2XP', 'JSTR', 'WAR3'.
+(DWORD) Version byte.**
+(DWORD) Product language.*
+(DWORD) Local IP, for NAT compatibility.*
+(LONG) Time zone bias multiplied by -60, for example, GMT-8 gets the value 480: (-8*-60).*
+(DWORD) Locale ID. Value returned by GetSystemDefaultLCID.*
+(DWORD) Language ID. Value returned by GetSystemDefaultLangID.*
+(String) Country abbreviation, such as "USA".
+(String) Country name, such as "United States".
+
+* This field doesn't really matter and may just be 0.
+** You can now get this value from BNLS, via the BNLS_REQUESTVERSIONBYTE (0x10) message.
+
+
+
+The server responds to this message with a SID_PING (0x25) that is not discussed here, and a SID_AUTH_INFO (0x50) reply:
+
+(DWORD) The NLS revision to use.*
+(DWORD) Session key.
+(DWORD) Nobody knows what the hell this is.
+(FILETIME) A Win32 FILETIME structure specifying the file time of the version MPQ file.
+(String) The filename of the version MPQ file.
+(String) Checksum formula.
+(Optional 128 bytes) Server signature.**
+
+* If this is nonzero, it specifies the revision of NLS to be used.
+The New Logon System messages (range 0x52-0x58) will be used.
+Use BNLS_CHOOSENLSREVISION (0x0d) to send the revision to the BNLS server.
+If this is zero, the Old Logon System messages (not documented here) will be used.
+
+** Not always present (currently only present with Warcraft 3). Use BNLS_VERIFYSERVER (0x11) to verify this signature.
+
+The client should now use a few BNLS functions: BNLS_CDKEY (0x01) or BNLS_CDKEY_EX (0x0c) using the given session key, and BNLS_VERSIONCHECK (0x09) using the given version MPQ filename digit and checksum formula.
+Also, the optional BNLS_VERIFYSERVER (0x11) message may be used.
+
+
+
+SID_AUTH_CHECK (0x51)
+---------------------
+
+(DWORD) Client session key.*
+(DWORD) Version.**
+(DWORD) Checksum.**
+(DWORD) Amount of CD-keys. This is typically 2 for Lord of Destruction, 1 otherwise.***
+(BOOL) TRUE for spawn (Starcraft, Japan Starcraft and Warcraft 2 only), FALSE for normal.
+(9 DWORDs) CD-key data.*
+(Optional 9 DWORDs) CD-key data for second CD-key, if using Lord of Destruction.***
+(String) Version check stat string.**
+(String) CD-key owner name.
+
+
+* This is returned by the BNLS server in BNLS_CDKEY (0x01) response.
+** This is returned by the BNLS server in BNLS_VERSIONCHECK (0x09) response.
+*** If using Lord of Destruction, all keys must have the same client session key.
+Therefore, the message BNLS_CDKEY (0x01) cannot be used, since it generates a different client session key for each call.
+For this, you must use BNLS_CDKEY_EX (0x0c).
+
+Response:
+---------
+
+(DWORD) Status code.*
+(String) More info, depending on status. (If this is empty, a null-terminator is still sent.)
+
+* Valid status codes are: ("More info" is empty unless otherwise stated)
+
+0x0000: Passed version and CD-key check.
+
+0x0100: Game version recognized, but out of date. (More info: Filename of patch MPQ file.)
+0x0101: Game version unrecognized.
+
+0x0200: Invalid CD-key.
+0x0201: CD-key in use. (More info: CD-key owner name of the user who's using the CD-key.)
+0x0202: CD-key banned by Battle.net.
+0x0203: Invalid CD-key for this product.
+
+0x0210: Invalid LOD CD-key.
+0x0211: LOD CD-key in use. (More info: CD-key owner name of the user who's using the CD-key.)
+0x0212: LOD CD-key banned by Battle.net.
+0x0213: LOD CD-key has invalid product code.
+
+Other: Failed version and CD-key check.
+
+
+
+SID_AUTH_ACCOUNTCREATE (0x52)
+-----------------------------
+
+(16 DWORDs) Data from BNLS_CREATEACCOUNT (0x04) response.
+(String) Username.
+
+Response:
+---------
+
+(DWORD) Status code.*
+(5 DWORDs) Password proof.**
+
+* Valid status codes are:
+
+0x00: Account created successfully. Proceed to send BNLS_LOGONCHALLENGE (0x02) and SID_AUTH_ACCOUNTLOGON (0x53).
+0x07: Username must be at least 2 chars. (???)
+0x08: Name contains an illegal character.
+0x09: Name contains an illegal word.
+0x0a: Not enough alphanumeric chars in name. (???)
+0x0b: Name contains adjacent punctuation characters.
+0x0c: Name contains too many punctuation characters. (???)
+Any other: Account already exists.
+
+** This proves the Battle.net server knows your password. The client should use BNLS_CONFIRMLOGON (0x0a) to verify the proof, and if it is incorrect, terminate the connection.
+If the statuscode is nonzero, these 5 DWORDs are zero.
+
+
+
+SID_AUTH_ACCOUNTLOGON (0x53)
+----------------------------
+
+(8 DWORDs) Data from BNLS_LOGONCHALLENGE (0x02).
+(String) Username.
+
+Response:
+---------
+
+(DWORD) Status code.*
+(16 DWORDs) Data to send to BNLS_LOGONPROOF (0x03).**
+
+* Valid status codes are:
+
+0x00: Logon accepted, requires proof. Proceed to send BNLS_LOGONPROOF (0x03) and SID_AUTH_ACCOUNTLOGONPROOF (0x54).
+0x01: Account doesn't exist. Proceed to send BNLS_CREATEACCOUNT (0x04) and SID_AUTH_ACCOUNTCREATE (0x52).
+0x05: Account requires upgrade. Proceed to send BNLS_UPGRADECHALLENGE (0x07) and SID_AUTH_ACCOUNTUPGRADE (0x57).
+Other: Unknown (failure).
+
+** If the status code is nonzero, these 16 DWORDs are all zeroes.
+
+
+
+SID_AUTH_ACCOUNTLOGONPROOF (0x54)
+---------------------------------
+
+(5 DWORDs) Data from BNLS_LOGONPROOF (0x03).
+
+Response:
+---------
+
+(DWORD) Status code.*
+(5 DWORDs) Password proof.**
+
+* Valid status codes are:
+
+0x00: Logon successful! Proceed to send SID_ENTERCHAT (0x0a) - not documented here.
+0x02: Incorrect password.
+0x0E: An E-mail should be registered for this account. The E-mail registration packets are not documented here. You don't have to register the account, though, so this status code may be safely ignored and treated as a success code.
+0x0F: Different error. The 5 DWORDs in the password proof will all be zero, but following them will be a null-terminated string, explaining the error. Example: "Your account has been closed (8)."
+
+** This proves the Battle.net server knows your password. The client should use BNLS_CONFIRMLOGON (0x0a) to verify the proof, and if it is incorrect, terminate the connection.
+If the statuscode is nonzero, these 5 DWORDs are zero.
+
+
+
+SID_AUTH_ACCOUNTCHANGE (0x55)
+-----------------------------
+
+(8 DWORDs) Data from BNLS_CHANGECHALLENGE (0x05).
+(String) Username.
+
+Response:
+---------
+
+(DWORD) Status code.*
+(16 DWORDs) Data to send to BNLS_CHANGEPROOF (0x06).**
+
+* Valid status codes are:
+
+0x00: Change accepted, requires proof. Proceed to send BNLS_CHANGEPROOF (0x06) and SID_AUTH_ACCOUNTCHANGEPROOF (0x56).
+0x01: Account doesn't exist. Proceed to send BNLS_CREATEACCOUNT (0x04) and SID_AUTH_ACCOUNTCREATE (0x52).
+0x05: Account requires upgrade. Proceed to send BNLS_UPGRADECHALLENGE (0x07) and SID_AUTH_ACCOUNTUPGRADE (0x57).
+Other: Unknown (failure).
+
+** If the status code is nonzero, these 16 DWORDs are all zeroes.
+
+
+
+SID_AUTH_ACCOUNTCHANGEPROOF (0x56)
+----------------------------------
+
+(21 DWORDs) Data from BNLS_CHANGEPROOF (0x06).
+
+Response:
+---------
+
+(DWORD) Status code.*
+(5 DWORDs) Password proof.**
+
+* Valid status codes are:
+
+0x00: Password changed!
+0x02: Incorrect old password.
+
+** This proves the Battle.net server knows your password. The client should use BNLS_CONFIRMLOGON (0x0a) to verify the proof, and if it is incorrect, terminate the connection.
+If the statuscode is nonzero, these 5 DWORDs are zero.
+
+
+
+SID_AUTH_ACCOUNTUPGRADE (0x57)
+------------------------------
+
+Send this when status code is 0x05 for SID_AUTH_ACCOUNTLOGON (0x53) or SID_AUTH_ACCOUNTCHANGE (0x55).
+The request is empty, but *must* follow a failed SID_AUTH_ACCOUNTLOGON (0x53) or SID_AUTH_ACCOUNTCHANGE (0x55).
+Also, before sending this, send a BNLS_UPGRADECHALLENGE (0x07).
+
+Response:
+---------
+
+(DWORD) Status code.*
+(DWORD) Server session key to send to BNLS_UPGRADEPROOF (0x08).
+
+* Valid status codes are:
+
+0x00: Upgrade request accepted.
+Other: Upgrade request denied.
+
+
+
+SID_AUTH_ACCOUNTUPGRADEPROOF (0x58)
+-----------------------------------
+
+(22 DWORDs) Data from BNLS_UPGRADEPROOF (0x08).
+
+Response:
+---------
+
+(DWORD) Status code.*
+(5 DWORDs) Password proof.**
+
+* Valid status codes are:
+
+0x00: Account upgraded!
+0x02: Incorrect old password.
+
+** This proves the Battle.net server knows your password. The client should use BNLS_CONFIRMLOGON (0x0a) to verify the proof, and if it is incorrect, terminate the connection.
+If the statuscode is nonzero, these 5 DWORDs are zero.
+
+
+
+
+
+
+
+APPENDIX - BNLS Checksum Algorithm
+----------------------------------
+
+The BNLS checksum algorithm calculates the checksum of a password using the 32-bit server code received in BNLS_AUTHORIZE (0x0e).
+
+Create an ANSI string whose length is the length of the password + 8 characters.
+Copy the password to the beginning. (Note that the password is case sensitive.)
+In the last 8 characters, store the hexadecimal representation of the server code, in uppercase, padded with zeroes on the left.
+Calculate the standard CRC-32 checksum (using the standard polynomial 0xEDB88320) of the string.
+The result is the BNLS checksum, to be sent in BNLS_AUTHORIZEPROOF (0x0f).
+
+
+Source code:
+------------
+VB:  http://www.valhallalegends.com/yoni/BNLSChecksum.bas
+C++: http://www.valhallalegends.com/yoni/BNLSChecksum.cpp
+
+In the sample code (in both languages), the checksum for BNLS_AUTHORIZEPROOF (0x0f) is the return value of BNLSChecksum(AuthPassword, ServerCode), where ServerCode is the value from BNLS_AUTHORIZE (0x0e).
+
+Update: This is now available in C#: http://www.valhallalegends.com/yoni/BNLSChecksumCls.cs.txt
+This file is unofficial and unsupported.
+
+
+Sample checksums:
+-----------------
+The sample checksums can be used to check the correctness of your code.
+BNLSChecksum("Sample", 0x0123ABCD)    == 0x12FDED88
+BNLSChecksum("Checksums", 0xBAADF00D) == 0x0098F911
+
diff --git a/archives/bnsp-latest.txt b/archives/bnsp-latest.txt
new file mode 100644
index 00000000..48cd2bd9
--- /dev/null
+++ b/archives/bnsp-latest.txt
@@ -0,0 +1,521 @@
+Updated 7-23-2003.
+
+	 BotNet Protocol Specification
+---------------------------------------
+
+This documentation covers BotNet revisions 0x01 through 0x04.
+
+The current protocol version is 0x01.  The maximum packet length is 511
+bytes.  The current server revision is 0x04 (Kp_Version_1).  Strings are
+limited to a length which is usually far less than the size of the
+packet.  Except where otherwise specified, exceeding the string length
+is a protocol violation.  String maximums are specified as: "(STRING:20)
+Unique bncs name".  Such a string has a maximum length of 20 characters,
+including the null.  Features added by server revisions are indicated by
+a parenthesized number.  For instance "(4) (DWORD) ID" indicates that
+revision 0x04 introduced a new DWORD related to identification.  If a second
+number is provided after a decimal point, the field is present only when the
+client has asserted awareness of at least that level.  Use packet 0xa to
+assert an awareness level.  The default is zero if none is specified.
+
+Additions in revision 0x04:
+* Introduced message notifying client of protocol violation.  This is
+the last message sent to a connection before the connection is closed.
+See packet 8 for the format of this message.
+
+Additions in revision 0x03:
+* Database is now visible in stat update message.
+
+
+Additions in revision 0x02:
+* Unique account names.  By default, everyone has an account name of "No
+Account".  You can log on as an account through message 0x0d.  Accounts
+are guaranteed to be unique (only one instance can be logged on at any
+given time) and are password protected.  Valid characters in account
+names are: Any alphanumeric characters, and [] brackets.  Hence "No
+Account" cannot be "spoofed" or faked.  Account names are given through
+a new field at the end of the stats change (0x06) message.  Note that
+creating an account does NOT log you on as that account.  When you log
+on as an account, all users on the BotNet will receive a stats change
+message (0x06) reflecting your new unique account name.
+
+* Administrative support.  The BotNet server now provides
+some basic administrative functionality to the server admin.  Admin
+functions are accessed through message 0x0c.
+
+You can use the following constants to refer to the new messages and
+functionality: ("SEND" indicates that the BotNet server sends this
+message, and "RECV" indicates that the client sends this message).
+
+#define ADMIN_MSG_KICK_USER						(0x00000000) /* SEND,RECV */
+#define ADMIN_MSG_BAN_USER						(0x00000001) /* SEND,RECV */
+#define ADMIN_MSG_QUERY_USER					(0x00000002) /* SEND,RECV */
+#define ADMIN_MSG_QUERY_BANS					(0x00000003) /* SEND,RECV */
+#define ADMIN_MSG_UNBAN							(0x00000004) /* SEND,RECV */
+#define ADMIN_MSG_NOTIFY_ADMIN_PRIVILEGES		(0x00000005) /* SEND	  */
+
+#define MSG_ID_ADMIN							(0x0000000c) /* SEND,RECV */
+
+#define ACCOUNT_MSG_LOGIN						(0x00000000) /* SEND,RECV */
+#define ACCOUNT_MSG_CHANGE_PASSWORD				(0x00000001) /* SEND,RECV */
+#define ACCOUNT_MSG_CREATE_ACCOUNT				(0x00000002) /* SEND,RECV */
+
+#define MSG_ID_ACCOUNT							(0x0000000d) /* SEND,RECV */
+
+
+
+Packet headers are formed as follows:
+(BYTE) protocol version
+(BYTE) packetid
+(SHORT) packetlen
+(...) DATA
+
+Current packets:
+(send to server) id 0x00: keepalive
+Contents: None.
+Response: None.  You should send this once every 2-3 minutes to enable
+the TCP layer to detect connection failures and report them to your
+application.
+
+(send to client) id 0x00: keepalive
+Contents: None.
+Response: None.  The server sends this message to detect connectivity
+failure; clients may safely ignore this message.  This message is sent
+only in the absence of recent activity upon the connection, so do not
+rely on it as a timing mechanism.
+
+(send to server) id 0x01: log on to botnet
+Contents:
+	(STRING:32) bot id
+	(STRING:64) hub password
+Response: For server versions 2 and newer, the server sends back a
+server version advisory (packet 0xa) after accepting a hub logon but
+before confirming such acceptance.  In version 4, if the hub logon is
+rejected, the client is disconnected and no messages are sent.  Prior to
+version 4, the client would receive a notification that the logon was
+unsuccessful.  See packet id 0x01 sent to client.
+
+(send to client) id 0x01: log on status
+Contents:
+	(BOOL) status : 0=FAIL, 1=OK.  In version 4, this message always
+		indicates success.
+	(4) (DWORD) client's IP address : clients inside a NAT device
+		may find this useful for learning their external address.
+Response: On success, the client should proceed to logon and acquire its
+database, as appropriate.
+
+(send to server) id 0x02: update bot stats
+Contents:
+	(STRING:20) unique username on battle.net : This string provides room
+		to specify a name mangle ("Someone#2"), but not to specify
+		gateway.
+	(STRING:36) current channel on battle.net : By convention,
+		"<Not logged on>" is used to indicate clients which are not
+		presently connected.
+	(DWORD) battle.net server ip
+	(STRING:96) database id (which database to use) : includes database
+		password.  Use the following format: "name password\0".
+	(DWORD) cycle status : 0=NotCycling, 1=Cycling
+Response: client receives packet id 0x02.  Client is also assigned a unique
+	botnet identification number.  Prior to receiving this number, clients
+	are prohibited from performing actions which cause interaction with
+	other users.
+
+(send to client) id 0x02: update bot status
+(DWORD) status : 0=FAIL, 1=OK.  In version 4, this message is always success.
+(DWORD) Optional dword which specifies administrative access, if it has
+	changed from its previous value.  If this dword is not present,
+	the client should assume that the access has not changed; the
+	default access is 0.  As noted in the documentation to message 6,
+	administrative access is expressed as a 32-bit mask of features
+	available.  Flags C and L enable insertion of client IP address
+	in message 6, if the client has also negotiated to use revision
+	1 packets (that is, fields marked 4.1 are in use).
+
+--
+
+(send to server) id 0x03: database modification
+Contents:
+	(DWORD) command
+	command 1: request user database
+		(4) (DWORD) Optional dword which specifies maximum age of entries to
+		transfer.  If specified, the server performs an incremental download
+		of the database by transferring all entries modified within the
+		specified window.  For instance, to retrieve changes that occured
+		within the past 5 minutes, use 300 for this value.  Under some
+		conditions, the server may decline to perform an incremental transfer
+		and instead perform a full transfer.  A full transfer is the default
+		if this parameter is omitted.
+	Response: The server responds with id 0x3 and a subcmd specifying the type
+		of transfer, then transfers all relevant database entries as user
+		modifications, then sends a database completion notify in id 0x3.
+		Note that the database transfer start/stop advisories were added in
+		version 4.  Earlier versions provide no inherent way to detect the
+		completion of the transfer.
+	command 2: add a database entry/modify a database entry
+		(STRING) usermask	   : this entry may be any length.
+		However, usermasks longer than 40 characters will be
+		rejected in the same manner as if the client did not
+		have permission to modify the database.  The uncapped
+		nature of this string is done to accomodate clients
+		which modify the database on behalf of users who have
+		not read this specification.  The client may thus relay
+		modification requests on excessively long names without
+		suffering a protocol violation.
+		(STRING:28) flags		: must be uppercase letters only
+		(4) (STRING:64) optional comment		: If this field
+		is omitted, it is presumed to be the null string.  this
+		field may contain any printable characters.  It is
+		distributed to other clients when the change is
+		successful, but is not saved for transmission during
+		subsequent database downloads.
+	Response: Dependent upon client's database notification mode and success
+		of the change.  If the client makes ACL changes immediately (the
+		default), a response is generated only if the modification was
+		rejected.  If the client awaits server confirmation of changes,
+		a response is generated only if the modification was accepted.
+		See packet id 0xa for information on how to specify notification mode.
+	command 3: remove a database entry
+		(STRING:40) usermask
+		(STRING:64) comment		: same as comment in command 2
+	Response: Same behavior as for database modify.
+
+(send to client) id 0x03: database change
+Contents:
+	(DWORD) command
+	(4) command 1: database download control
+		(DWORD) subtype	: this value is zero to indicate a full database
+		transfer is starting, 1 to indicate an incremental transfer is
+		starting, and 2 to indicate that a database transfer (of either type)
+		has finished.  Clients should clear their local ACL if subtype is 0.
+		Clients which display database modification notices to their users
+		are encouraged to disable such display during a database download,
+		as failure to do so would likely fill the screen with database changes.
+	Response: None.
+	command 2: new access list user/modify existing access list user.  During
+		a database download, user creations/modifications are sent in
+		this message.  Additionally, this message is used to confirm
+		successful database changes, to distribute changes made by other
+		clients, and to countermand changes which modified an existing entry.
+		(4.1) (DWORD) sending client's ID	: this is 0 when the message
+		originates from the server 
+		(4.1) (DWORD) timestamp of last modification to database entry
+		(STRING) usermask
+		(STRING) flags
+		(4.1) (STRING) comment		: this is picked by the sending entity and
+		is not parsed by the server.  Clients are encouraged to use this to
+		identify the user who requested the change.
+	Response: None.
+	command 3: remove a database entry
+		(4.1) (DWORD) sending client's ID	: this is 0 when the message
+		originates from the server 
+		(4.1) (DWORD) timestamp of last modification to database entry
+		(STRING) usermask
+		(4.1) (STRING) comment		: same as in command 2
+	Response: None.
+
+--
+
+(send to server) id 0x04: command to bots on same database
+Contents:
+	(STRING:32) sending user
+	(STRING:384) command
+Response: all clients on the same database as the sending client receive
+	packet id 0x04.  If the sending client does not have permission
+	to relay commands to other clients, only the sending client
+	receives command id 0x04 from the server.  The sending client
+	must have write access to the database, or have restricted
+	access and the command match a pre-defined list of acceptable
+	restricted user commands.  If the client does not meet the access
+	requirement, no response is generated to any user (including the sender
+	itself).
+
+(send to client) id 0x04: command over botnet
+Contents:
+	(4.1) (DWORD) sending client's ID
+	(4.1) (DWORD) distribution status
+		0 = broadcast to all users
+		1 = sent to database
+		2 = directed to this client specifically
+	(STRING) sender
+	(STRING) command
+Response: None.
+
+(send to server) id 0x05: cycle request
+(DWORD) count
+(STRING LIST) usernames of bots to cycle
+
+(send to client) id 0x05: cycle request notification
+(STRING) channel to cycle
+
+(send to server) id 0x06: request information about bots on botnet
+Contents: None documented.
+Response: The server sends a series of id 0x6 to the client, one per online
+	user.
+
+(send to client) id 0x06: botnet bot information
+Contents:
+	(DWORD) bot id
+	(4.1) (DWORD) database access flags
+		1 = read
+		2 = write
+		4 = restricted access
+	(4.1) (DWORD) administrative capabilities
+		Specified in Zerobot Traditional Flags Format (ZTFF):
+		A = superuser, can perform any administrative action
+		B = broadcast, may use talk-to-all
+		C = connection, may administer botnet connectivity
+		D = database, may create and maintain databases
+		I = ID control, may create and modify hub IDs
+		S = botnet service
+	(4.1) (Admin only) (DWORD) IP address of the bot being described
+	(STRING:20) bot name
+	(STRING:*) bot channel
+	(DWORD) bot server
+	(2) (STRING:16) unique account name
+	(3) (STRING:*) database
+
+(send to server) id 0x07: command over botnet to all botnet bots (send 0x04 to client)
+Contents: same as command id 0x4 to server.  The only difference between
+	these messages is the distribution status of the resulting message.
+Response: same as command id 0x4.
+
+(send to client) id 0x07: bot disconnecting from botnet
+(DWORD) bot id
+
+(send to server) id 0x08: command to specific botnet bot
+Contents:
+	(DWORD) target bot id
+	(STRING:32) sending user
+	(STRING:384) command
+Response: the server forwards the message to the specified bot in the
+	form of a msg 0x4, providing that:
+	1) The target is online
+	2) The sender has permission to forward commands.  Permission here
+		refers to both relaying and write access, as referenced in command
+		id 0x4.
+	3) The target is on the same database as the sending user
+
+(send to client) id 0x08: protocol violation
+Contents:
+	(DWORD) Error code.  This is message specific.
+	(BYTE) ID of the offending command
+	(WORD) Length of the offending packet
+	(WORD) Length of unprocessed data (length of packets which arrived after the offending packets)
+Response: None.  The server closes the botnet socket immediately after
+sending this message.
+Error codes:
+	1 = unrecognized command ID.  Any other code is command specific
+	Command 1:
+		2 = bad state, client is attempting to authenticate a second time
+		3 = bad size for hub ID
+		4 = bad size for hub password
+		5 = empty hub ID
+		6 = empty hub password
+	Command 2:
+		2 = bad state, client has not authenticated with command 1
+		3 = packet too small
+		4 = bad size for BNCSName
+		5 = 		channel
+		6 = missing server IP
+		7 = bad size for database string
+		8 = missing cycle status
+		9 = empty BNCSName
+		10 = empty channel
+		11 = bad server IP
+		12 = badly formed BNCSName
+		13 = badly formed database string
+	Command 3:
+		2 = missing subcommand
+		3 = bad state, client tried to perform a database
+			modification while invisible
+		4 = invalid subcommand
+		Subcommand 1:
+			No subcommand 1 specific errors.
+		Subcommand 2:
+			5 = missing entry name
+			6 = missing entry flags
+			7 = empty name
+			8 = empty flags
+			9 = malformed entry
+			10 = malformed flags
+		Subcommand 3:
+			5 = packet too small
+			6 = missing entry name
+			7 = empty entry name
+			8 = malformed entry name
+	Command 5:
+		2 = bad state, client tried to perform cycle while not visible
+		3 = missing count
+		4 = count is zero
+		5 = not enough data in packet to satisfy count
+		6 = specified more clients than exist on botnet
+	Command 6:
+		2 = bad state, client tried to query list while
+			invisible; this is illegal since the client is always
+			returned as the first entry in response to this command,
+			and the client must be visible to be returned
+	Command 7:
+		2 = bad state, client tried to issue command while invisible
+		3 = missing sender string
+		4 = missing command
+		5 = empty sender
+		6 = empty command
+		7 = malformed sender name
+	Command 8:
+		2 = bad state, client must be visible
+		3 = no target ID
+		4 = no sender string
+		5 = no command string
+		6 = bad target ID
+		7 = empty sender
+		8 = empty command
+		9 = malformed sender name
+	Command 9:
+		2 = bad state, client must be visible
+		3 = missing selector dword
+		4 = missing new password
+		5 = malformed password
+	Command 10:
+		2 = missing first dword
+		3 = missing second dword
+		4 = unexpected flags in second dword
+	Command 11:
+		2 = bad state, client must be visible
+		3 = missing distribution level
+		4 = missing emote
+		5 = missing target id
+		6 = missing text
+		7 = bad distribution level
+		8 = bad target (only if attempting to whisper a user)
+	Command 12:
+		2 = bad state, client must be visible
+		3 = missing subcommand
+		Other errors are subcommand specific.
+	Command 13:
+		1 = missing subcommand
+		2 = bad subcommand
+		3 = missing username
+		4 = empty username
+		5 = missing password
+		6 = empty password
+		There are no subcommand 0 specific errors.
+		Subcommand 1:
+			7 = missing new password
+			8 = empty new password
+		There are no subcommand 2 specific errors.
+
+(send to server) id 0x09: change database password * Requires 'full' access
+(DWORD) password to change (0: readonly, 1: full, 2: restricted)
+(STRING) new password
+
+(send to client) id 0x09: acknowledge communication version
+Contents:
+	(DWORD) communication version.  This message is sent to confirm
+	acceptance of msg 0x0a.  All subsequent messages will be formed in
+	this style.  That is, clients should not change parsing methods until
+	the server confirms the new style.
+Response: None
+
+(send to server) id 0x0a: specify communication version and client
+	capabilities
+Contents:
+	(DWORD) communication version.  Valid values are 0 (the default), or 1.
+	Messages which have conditionally added fields (as identified by the
+	4.X syntax) will contain fields for which X is not above this value.
+	(DWORD) client capabilities.  Currently only bit 0 is defined.  If set,
+	the client awaits server confirmation of database changes.  If clear,
+	the client updates the local ACL immediately and expects the server to
+	countermand prohibited changes.
+Response: The server updates the communication version and sends 0x9 to the
+	client.  Message 0xa may be sent at any time, and may be resent if the
+	client desires to change the negotiation version.
+
+(send to client) id 0x0a: botnet server version
+Contents:
+	(DWORD) version
+Version information:
+Version 1 supports all packets 0x00 through 0x0b.
+Version 2 supports messages 0x0c and 0x0d.
+Version 4 supports message 0xa to server.
+
+(send to server) id 0x0b: botnet chat
+Contents:
+	(DWORD) command
+		0	: message to all bots
+		1	: message to bots on the same database
+		2	: message to bot specified by id.
+	(DWORD) action	: 0x00=talk, 0x01=emote, any other is dropped
+	(DWORD) id	: for command 0x02, id of bot to send to, otherwise ignored.
+	(STRING:496) message: blank messages are dropped
+Response: the server generates 0xb to the specified other clients.  No
+response is sent to the sending client.
+
+(send to client) id 0x0b: botnet chat
+Contents:
+	(DWORD) command	: same as 0xb to server
+	(DWORD) action	: same as 0xb to server
+	(DWORD) id		: id of source bot (for all commands)
+	(STRING) message	: chat message text
+Response: None.
+
+(send to server) id 0x0d: account management
+Contents:
+	(DWORD) subcommand
+	(STRING:16) account name	: name to acquire
+	* Subcommand 0x00: Login:
+		(STRING:96) account password
+	* Subcommand 0x01: Change password:
+		(STRING:96) old password
+		(STRING:96) new password
+	* Subcommand 0x02: Account create:
+		(STRING:96) account password
+Response: The server returns the result code in 0xd.
+Other subcommand values are reserved for future use.
+The server ensures that there is never more than one user online using a
+given account name.  Account names are restricted to alphanumeric
+characters, brackets, underscores, and dashes.  Invalid characters
+result in failure to create/logon the account.
+
+(send to client) id 0x0d: account management reply
+Contents:
+	(DWORD)	subcommand --- This is the same subcommand as the message being replied to.
+	(BOOL)	: Success/Failure for subcommand
+Response: None.
+
+(send to server) id 0x0e: database change mode.
+	This message marks a client as using certain older versions of
+	BotNetClient.DLL; it is due to be reclaimed in the future and
+	should not be used.
+
+(send to client) id 0x0e: response to c->s 0x0e.
+	This may be safely ignored in preference of specifying database
+	negation behavior as the second parameter of 0x0a.
+
+(send to server) id 0x10: set chat options
+Contents:
+	(BYTE) Subcommand.  Presently only subcommand 0 is defined.
+	* Subcommand 0: chat drop options; the client may omit the
+		four bytes of data, in which case the command will not affect
+		current chat options but will still generate a notification of
+		resulting options.
+		(BYTE) setting for broadcast
+		(BYTE) setting for database
+		(BYTE) setting for whisper
+		(BYTE) refuse whispers from other databases
+		For each of the first three bytes, 0 (the default for
+		clients which do not send this message) allows all chat
+		to be received.  1 refuses chat from users who are not
+		on an account.  2 refuses all chat.  Note that messages
+		from administrators ignore these settings.  This command
+		is provided in recognition that some clients drop all
+		chat received from certain sources.  Such clients may
+		use this command to advise the server of their intent to
+		discard chat.
+Response:
+	The server sends back a message with the same subcommand.  See below for contents.
+
+(send to client) id 0x10: inform chat options
+Contents:
+	(BYTE) Subcommand.  Presently only subcommand 0 is defined.
+	* Subcommand 0: chat drop options.  Same contents as 0x10 to server.

From 0130e6926040062869f3acf51713684876300a9b Mon Sep 17 00:00:00 2001
From: Carl Bennett <carl@carlbennett.me>
Date: Mon, 17 Apr 2017 07:58:02 +0000
Subject: [PATCH 52/54] Fix path to config file in travis ci config

---
 .travis.yml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/.travis.yml b/.travis.yml
index bf5b93b0..972c4342 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -15,6 +15,6 @@ matrix:
 services:
   - mysql
 before_script:
-  - cp config.sample.json config.redux.json
+  - cp etc/config.sample.json etc/config.redux.json
 script:
   - bash -c 'set -e;for file in $(find . -type f -regextype posix-extended -regex .*\.\(php\|dm\) -print); do php -e -l -f "$file"; done'

From 96b1f1fc4202b7e91366635ba96bf4e51e265753 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carl@carlbennett.me>
Date: Wed, 22 Jul 2020 18:13:18 -0500
Subject: [PATCH 53/54] Replace deprecated get_magic_quotes_gpc

---
 index.php | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/index.php b/index.php
index ff5a40fb..60529c00 100644
--- a/index.php
+++ b/index.php
@@ -31,7 +31,8 @@
 
 		# Stripslashes as shown on http://php.net/get_magic_quotes_gpc
 		# Used to prevent remote code injection via post, get, cookie. Also contributes to prevent remote code injection via SQL since input is cleaned prior to inserting to SQL DB.
-		if (get_magic_quotes_gpc()) {
+		#if (get_magic_quotes_gpc()) { ### DEPRECATED AND REMOVED IN PHP 7.4.0 ###
+		if (ini_get('magic_quotes_gpc')) {
 		   function stripslashes_deep($value) {
 		       $value = is_array($value) ?
 		                   array_map('stripslashes_deep', $value) :

From 786eef1a2abee31b5618edcf53f8065a1887e224 Mon Sep 17 00:00:00 2001
From: Carl Bennett <carl@carlbennett.me>
Date: Wed, 22 Jul 2020 18:33:31 -0500
Subject: [PATCH 54/54] Update Travis CI configuration

---
 .travis.yml | 12 ++++++------
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/.travis.yml b/.travis.yml
index 972c4342..f8053c2f 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,13 +1,12 @@
+---
 language: php
 os:
   - linux
 sudo: false
 php:
-# - 5.3 (doesn't recognize $var=[], only recognizes $var=array())
-  - 5.4
-  - 5.5
-  - 5.6
-  - 7.0
+  - 7.2
+  - 7.3
+  - 7.4
   - nightly
 matrix:
   allow_failures:
@@ -17,4 +16,5 @@ services:
 before_script:
   - cp etc/config.sample.json etc/config.redux.json
 script:
-  - bash -c 'set -e;for file in $(find . -type f -regextype posix-extended -regex .*\.\(php\|dm\) -print); do php -e -l -f "$file"; done'
+  - bash -c 'set -e;for file in $(find . -type f -regextype posix-extended
+    -regex .*\.\(php\|dm\) -print); do php -e -l -f "$file"; done'
