[geeklog-devtalk] geeklog-devel digest, Vol 1 #232 - 1 msg

geeklog-devel-request at lists.geeklog.net geeklog-devel-request at lists.geeklog.net
Tue Dec 2 00:02:05 EST 2003


Send geeklog-devel mailing list submissions to
geeklog-devel at lists.geeklog.net

To subscribe or unsubscribe via the World Wide Web, visit
http://lists.geeklog.net/listinfo/geeklog-devel
or, via email, send a message with subject or body 'help' to
geeklog-devel-request at lists.geeklog.net

You can reach the person managing the list at
geeklog-devel-admin at lists.geeklog.net

When replying, please edit your Subject line so it is more specific
than "Re: Contents of geeklog-devel digest..."


Today's Topics:

1. Spelling interface ready for testing... (Tony Bibbs)

--__--__--

Message: 1
Date: Mon, 01 Dec 2003 23:01:36 -0600
From: Tony Bibbs <tony at tonybibbs.com>
To: Geeklog <geeklog-devel at lists.geeklog.net>
Subject: [geeklog-devel] Spelling interface ready for testing...
Reply-To: geeklog-devel at lists.geeklog.net

This is a multi-part message in MIME format.
--------------060409070102020704010509
Content-Type: text/plain; charset=us-ascii; format=flowed
Content-Transfer-Encoding: 7bit

I have finally completed the spellchecker code I am planning to use in
Geeklog 2. As you might guess, there is nothing precluding it from
being used in 1.3.x so I am attaching the file along with the modified
CVS files needed to get this working on admin/story.php.

Dirk, if you could test it's use on another language that would be
great. I have already tested this on windows. If you tested an alpha
of what I had a few months ago, this is *much* easier to use. My prior
version used the native PHP functions (pspell) which is a PITA to get
working both on *nix and windows. This version simply needs a working
aspel binary which is called using shell_exec().

For those needing more info here is what we have:

1) Uses only the Aspell binary (http://aspell.net)
2) Capable of supporting multiple languages
3) Able to highlight misspelled words. By default it uses a set of span
tags and the title attribute gets the suggested spellings put into it.
This allows you to see the suggestions by hovering over it with your mouse
4) I modified the config file to have a new set of entries for spell
checking. By default I think we'd turn this feature off, no?
5) Works regardless of the postmode of the article
6) I have implemented with little effort for admin/story.php, I would
think one could update all possible areas of use in just a few hours

Oh, before I forget, to use the attached files, be sure to put
PHPSpellChecker.class.php into the /path/to/geeklog/system/classes/
directory.

Questions welcomed and, of course, more testers welcome. PHPDoc file
forthcoming (I don't have PHPDoc installed here at home).

--Tony

+-------------------+--------------------------------------------------+

|Tony Bibbs |[R]egardless of what you may think of our penal |

|tony at tonybibbs.com |system, the fact is that every man in jail is one |

| |less potential fisherman to clutter up your |

| |favorite pool or pond. --Ed Zern |


+-------------------+--------------------------------------------------+

--------------060409070102020704010509
Content-Type: text/html;
name="PHPSpellChecker.class.php"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="PHPSpellChecker.class.php"

<?php

/**
* PHPSpellChecker - A Simple Spellchecking Class in PHP
*
* This source file is subject to version 2.02 of the PHP license,
* that is bundled with this package in the file LICENSE, and is
* available at through the world-wide-web at
* http://www.php.net/license/2_02.txt.
* If you did not receive a copy of the PHP license and are unable to
* obtain it through the world-wide-web, please send a note to
* license at php.net so we can mail you a copy immediately.
*
* @author Tony Bibbs <tony at geeklog.net>
* @copyright Tony Bibbs 2003
* @package net.geeklog.utilities
* @version $Id:$
* @todo Need to test the personal dictionary stuff. Haven't even tried to yet.
*
*/

/**
* Used to indicate the server is a posix-compliant one (e.g. linux/unix)
* @const SPELL_OS_POSIX
*/
define('SPELL_OS_POSIX',1);

/**
* Used to indicate the server uses a version of windows (e.g. 98/XP)
* @const SPELL_OS_POSIX
*/
define('SPELL_OS_WINDOWS',2);

/**
* PHPSpellCheck, a simple spellchecking class
*
* This class makes it easy to implement spellchecking into your PHP applications
* with minimal effort. Requirements for this class for Posix hosts (Unix/Linux) is
* an installed aspell system. On my RedHat 9 system aspell was installed by default
* which should be the case for most of you. For Windows users, you should obtain the
* Aspell setup program and the corresponding dictionary file as none is installed by
* default. Aspell for Posix and Windows can be downloaded from @link http://aspell.net
*
* Here is a most basic example of how to use this class:
* <code>
* <?php
* require_once 'PHPSpellChecker.class.php';
* $spellChecker = new PHPSpellChecker();
* $spellChecker->setPathToAspellBinary('/usr/bin/aspell');
* $spellChecker->setTempDir('C:/Windows/Temp');
* echo $spellChecker->checkWords('This is a test, I srue hope therre are no mispelings');
* ?>
* </code>
*
* @author Tony Bibbs <tony at geeklog.net>
*
*/
class PHPSpellChecker {
/**
* Holds OS type that Aspell is installed on.
*
* When calling the Aspell binary we will need to know what OS is being
* used. This could be potentially used for future enhancements as well.
*
* @see PHPSpellChecker()
* @see checkWords()
* @var int
* @access private
*
*/
var $_operatingSystem = null;

/**
* Holds path to Aspell binary
*
* This holds the fully qualified path to the actual Aspell binary. Please
* specifiy the path to the executable file, not to a directory. NOTE: windows
* users may find that aspell is picky about the format of the path. For example,
* if you have aspell located at C:|Program Files\Aspell\bin\aspell then this value
* will need to be C:\progra~1\Aspell\bin\aspell
*
* @see checkWords()
* @var string
* @access private
*
*/
var $_pathToAspellBinary = null;

/**
* Code for language to spellcheck against
*
* As expected, this class can spellcheck against a variety of supported languages. NOTE:
* you will need to ensure that your respective language dictionaries have been installed
* otherwise this won't work
*
* @see setLanguage()
* @var string
* @access private
*
*/
var $_languageCode = null;

/**
* Holds any additional Aspell options that aren't supported by this
* class with a setter and/or getter method.
*
* Aspell has a number of options available. To support those yet keep this
* class relatively simple, we implement ways to set the most common attributes
* and allow you to specify additional options that we can include for you when
* the call to the Aspell binary is made. Please read the documentation for the
* constructor as it will explain this better
*
* @see PHPSpellChecker()
* @var array
* @access private
*
*/
var $_aspellOptions = null;

/**
* This holds the path to the dictionary file we should use
*
* Please specify the absolute path to the dictionary file
*
* @see setPersonalDictionary()
* @see checkwords()
* @var string
* @access private
*
*/
var $_pathToPersonalDictionary = null;

/**
* This holds the path to teh personal wordlist file we should use
*
* Please specify the absolute path to the word list file
*
* @see setPersonalWordList()
* @var string
* @access private
*
*/
var $_pathToPersonalWordList = false;

/**
* Sets the minimum size of a legitimate word
*
* Setting this allows applications to specify how big a word has
* to be before it is really considered a real word. By default we set this
* to 3, but you can override this
*
* @see checkwords
* @var int
* @access private
*
*/
var $_skipLength = null;

/**
* Name of temp dir
*
* This class puts the text to spell into a temporary file before checking the spelling. This
* attribute simply gives us a directory where we can create these temporary files (e.g.
* /tmp)
*
* @see _createTempFile()
* @var string
* @access private
*
*/
var $_tempDir = null;

/**
* Array of the works that were misspelled
*
* During the spellchecking process we keep track of all mispelled words in this
* array. This values in this array are used to index into the $_suggestions variable
* below. Array format is $myArray[<key>] = '<misspelled word>'
*
* @see checkWords()
* @var array
* @access private
*
*/
var $_misspellings = null;

/**
* Holds suggestions for misspelled words
*
* This array holds the suggested spellings for all misspelled words. The format of this
* array is $myArray[<misspelled word>] = '<suggestion1>,<suggestion2>'
*
* @see checkWords()
* @var array
* @access private
*
*/
var $_suggestions = null;

/**
* Holds the original text we were to spellcheck against
*
* This simply holds the original text to spellcheck against. It
* never gets modified
*
* @see checkWords()
* @var string
* @access private
*
*/
var $_origText = null;

/**
* Formating to use to begin highlighting a misspelled word
*
* The format string is pretty basic, by default we use a div tag
* that allows the mispellings to be show by using the title attribute.
* Doing so will show suggestions by simply hovering over the mispelled words.
* If you want to use a similar format, be sure to use the special tag {suggested}
* which will get automatically parsed.
*
* @see PHPSpellChecker();
* @see checkWords();
* @see setHighlight();
* @var string
* @access private
*
*/
var $_beginHighlight = null;

/**
* Formatting to use to end highlighting a misspelled word
*
* This is similar to $_beginHighlight above. This simply ends the highlight
*
* @see PHPSpellChecker();
* @see checkWords();
* @see setHighlight();
* @var string
* @access private
*
*/
var $_endHighlight = null;

/**
* Constructor
*
* Constructor, does the necessary pspell initialization. When setting aspell options, be sure
* to use the option names as shown by calling aspell with no options from your unix or dos shell.
* note that some of the aspell options can be overridden by some of the methods in this class. Those
* methods are:
* - setMinimumWordList(), since this is explicitly called in the constructor it will effectively ignore
* anything you put for aspell's -W or --ignore options
* - setPersonalWordList(), this isn't called explicitly so you can use the -p,--personal options or call
* that function instead.
* -
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param array $aspellOptions Options for aspell in formate myArray['aspellOption'] => 'aspellValue'
*
*/
function PHPSpellChecker($aspellOptions = '')
{
// Right now this is only used when determining how to call aspell but I'm
// adding this in case there are other OS specific differences added in the
// future.
if (substr(PHP_OS, 0, 3) == 'WIN') {
$this->_operatingSystem = SPELL_OS_WINDOWS;
} else {
$this->_operatingSystem = SPELL_OS_POSIX;
}
if (empty($aspellOptions)) {
$this->_aspellOptions = array();
} else {
$this->_aspellOptions = $aspellOptions;
}
$this->_misspellings = array();
$this->_suggestings = array();
$this->_positions = array();
$this->setLanguage();
$this->setMinimumWordLimit();
$this->setHighlight('<span title="{suggested}" style="background-color: #fdd905";>','</span>');
}

/**
* Sets the language that should be used.
*
* Allows applications to set the language to spellcheck against. We
* assume US English by default
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param string $languageCode Code of language to use
*
*/
function setLanguage($languageCode = 'en_US')
{
$this->_languageCode = $languageCode;
}

/**
* Sets the temporary directory for Aspell to use
*
* This class pipes the text to check out of a temporary file. This
* method will set the location where we put those temporary files.
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param string $absolutePath Path to the temporary directory
*
*/
function setTempDir($absolutePath = '')
{
$this->_tempDir = $absolutePath;
}

/**
* Sets the location to the Aspell binary
*
* This sets the path to the actual aspell binary. Note that
* this must be an absolute path, don't depend on your
* operating system's path variables.
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param string $absoluteFileName Location of aspell binary
*
*/
function setPathToApsellBinary($absoluteFileName)
{
$this->_pathToAspellBinary = $absoluteFileName;
}

/**
* Sets the minimum size of what a 'word' is defined as.
*
* Aspell can be configured to ignore words below a certain
* length and this is facilitate in this class using this
* method. For example if you set the minimum size to 3
* then any word less than 3 characters long.
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param int $minWordLength Minimum length of a word
*
*/
function setMinimumWordlimit($minWordLength = 3)
{
$this->_skipLength = $minWordLength;
}

/**
* Sets the location of the personal dictionary to use
*
* Aspell allows for any number of dictionary files. This can
* be handy when an application might want each of it's users to
* have their own dictionary
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param string $absoluteFileName Exact location of dictionary to use
*
*/
function setPersonalDictionary($absoluteFileName)
{
$this->_pathToPersonalWordList($absoluteFileName);
}

/**
* Sets the file where the current user's personal pspell dictionary can be found. Files
* should be of the .pws extension and must be in a directory your webserver to write files
* to. This feature is optional and disabled by default. If the given file doesn't exist,
* this function will attempt to create it.
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param string $absoluteFileName The fully qualified location of the .pws file to use
*
*/
function setPersonalWordList($absoluteFileName)
{
$this->_pathToPersonalWordList($absoluteFileName);
}

/**
* Creates a temp file for use during the spellcheck process
*
* Text that is being spellchecked gets loaded into temporary file and
* then it gets piped over to aspell for checking. This method creates that
* temporary file
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @return boolean True if successful otherwise false
*
*/
function _createTempFile()
{
$this->_tempFile = tempnam($this->_tempDir, 'textToCheck');

if ($this->_tempFile == false) {
trigger_error('Unable to write the temporary file.');
} else {
if (!empty($this->_origText)) {
if ($fd = fopen($this->_tempFile,'w')) {
// Chop it up by line.
$textarray = explode("\n",$this->_origText);

fwrite($fd,"!\n");

foreach ($textarray as $key=>$value) {
$value = ereg_replace('\\"','"',$value);
fwrite($fd,"^$value\n");
}

fclose($fd);

return true;
} else {
trigger_error('Unable to open the temporary file.');

return false;
}
} else {
trigger_error('No text has been set.');

return false;
}
}
}

/**
* Adds a word to a user's personal dictionary. Requires you to call
* setPersonalWordList() first
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param string $word Word to add to personal dictionary
*
*/
function addWord($word)
{
/*if ($this->_usePersonalDicts) {
return pspell_add_to_personal($this->_pspellCfgHandle, $word);
}*/
}

/**
* Parse the return output from aspell
*
* Aspell's return values aren't the easiest to work with
* so this method puts the data into easy to use structures
* that can be used later by this class and, if needed, by
* the calling application
*
* @author Tony Bibbs <tony at geeklog.net>
* @access private
* @param string $aspellReturn Return output from aspell
*
*/
function _parseReturn($aspellReturn)
{
//next parse $return and $text line by line, eh?
$returnarray = explode("\n",$aspellReturn);
$returnlines = count($returnarray);

$textarray = explode("\n",$this->text);

$lineindex = -1;
$poscorrect = 0;
$counter = 0;

foreach($returnarray as $line) {
$correction = explode(' ',$line);
$word = $correction[1];

// If there is a correction here, processes it, else move the $textarray pointer to the next line
if (substr($line,0,1) == '&') {
// Build the position, comma separated. Line, character
$absposition = substr($correction[3],0,-1)-1;
$position = $absposition + $poscorrect;
$niceposition = $lineindex . "," . $absposition;

// Start building the suggestion list
$suggstart = strpos($line,":")+2;
$suggestions = substr($line,$suggstart);
$suggestionarray = explode(', ',$suggestions);

// Set an array for the suggestions.
$suggestions = array();

foreach ($suggestionarray as $aSuggestion) {
$suggestions[] = $aSuggestion;
}

} else {
if (substr($line,0,1) == '#') {
// Find the position.
$absposition = $correction[2] - 1;
$position = $absposition + $poscorrect;
$niceposition = $lineindex .",". $absposition;

// Add this word to the arrays.
$thePositions[] = array($word => $niceposition);
$theSuggestions[] = array($word => 'No Suggestions.');
} else {
$poscorrect = 0;
$lineindex = $lineindex + 1;
}
}
$this->_misspellings[] = $word;
if (count($suggestions) > 0) {
$this->_suggestions[$word] = implode(',',$suggestions);
} else {
// Should not make this string english dependent. For future we should
// make this string configurable so it can be overridden by calling
// applications language preference.
$this->_suggestions[$word] = 'No suggestions';
}
}
}

/**
* Spell checks a set of words by iterating through words and calling check().
* During the check, it collects the suggested spellings of misspelled words. If there
* are mispelled words, _highlightedText is set to $textString and highlights all misspelled words
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param string $textString
* @param boolean $isHTMLEmbedded Indicates if the text to check has HTML in it
* @return string $textString with misspelled words highlighted, otherwise true
*
*/
function checkWords($textString, $isHTMLEmbedded = false)
{
$this->_origText = $textString;

if ($this->_createTempFile() != false) {
if ($isHTMLEmbedded == true) {
$addOptions .= ' -H';
}
if (!empty($this->_dictionary)) {
$addOptions .= ' -d ' . $this->dictionary;
}
if (!empty($this->wordList)) {
$addOptions .= ' -p ' . $this->wordList;
}

// Grab any other aspell options
for ($i = 1; $i <= count($this->_aspellOptions); $i++) {
$addOptions .= sprintf(' %s %s', key($this->_aspellOptions), current($this->_aspellOptions));
next($this->_aspellOptions);
}
reset($this->_aspellOptions);

// Calling aspell differs slightly by OS
if ($this->_operatingSystem == SPELL_OS_WINDOWS) {
$command = sprintf('%s -a --lang=%s %s < "%s" 2>&1',$this->_pathToAspellBinary, $this->_languageCode, $addOptions, $this->_tempFile);
} else {
$command = sprintf('%s -a --lang=%s %s < %s',$this->_pathToAspellBinary, $this->_languageCode, $addOptions, $this->_tempFile);
}

// Execute the command.
$retValue = shell_exec($command);

// Delete the temporary file created.
if (unlink($this->_tempFile) == false) {
trigger_error('Unable to delete temporary file.');
}

// Check to see if the execute statement returned anything.
if (empty($retValue)) {
trigger_error('There was a problem in executing the command against the Aspell binary.');
} else {
$this->_parseReturn($retValue);
}
} else {
trigger_error('Unable to create the temporary file.');
}

if (count($this->_misspellings) > 0) {
return $this->highlightBadWords();
}
}

/**
* Allows ability to set a custom method for highlight misspelled words
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @param string $beginHighlight Opening format of a highlighted word
* @param string $endHighlight Closing format of a highlighted word
*
*/
function setHighlight($beginHighlight, $endHighlight)
{
$this->_beginHighlight = $beginHighlight;
$this->_endHighlight = $endHighlight;
}

/**
* Highlights misspelled words and returns the text
*
* @author Tony Bibbs <tony at geeklog.net>
* @access public
* @return original search text with misspellings highlighted.
*
*/
function highlightBadWords()
{
$tmpString = $this->_origText;
foreach ($this->_misspellings AS $curWord) {
$tmpBeginHighlight = str_replace('{suggested}', $this->_suggestions[$curWord], $this->_beginHighlight);
// Be sure to operate on original text in case there was some HTML/XML in it
$tmpString = str_replace($curWord, $tmpBeginHighlight . $curWord . $this->_endHighlight, $tmpString);
}

return $tmpString;
}
}

?>
--------------060409070102020704010509
Content-Type: text/html;
name="config.php"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="config.php"

<?php

/* Reminder: always indent with 4 spaces (no tabs). */
// +---------------------------------------------------------------------------+
// | Geeklog 1.3 |
// +---------------------------------------------------------------------------+
// | config.php |
// | |
// | Geeklog configuration file. |
// +---------------------------------------------------------------------------+
// | Copyright (C) 2001-2003 by the following authors: |
// | |
// | Authors: Tony Bibbs - tony at tonybibbs.com |
// | Dirk Haun - dirk at haun-online.de |
// +---------------------------------------------------------------------------+
// | |
// | This program is free software; you can redistribute it and/or |
// | modify it under the terms of the GNU General Public License |
// | as published by the Free Software Foundation; either version 2 |
// | of the License, or (at your option) any later version. |
// | |
// | This program is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU General Public License for more details. |
// | |
// | You should have received a copy of the GNU General Public License |
// | along with this program; if not, write to the Free Software Foundation, |
// | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
// | |
// +---------------------------------------------------------------------------+
// | See the docs/install.html and docs/config.html files for more information |
// | on configuration. |
// +---------------------------------------------------------------------------+
//
// $Id: config.php,v 1.101 2003/10/11 11:21:46 dhaun Exp $

// When setting up Geeklog for the first time, you need to make sure the
// settings in the following 3 sections are correct:
// (1) Database Settings
// (2) Paths
// (3) Site Settings
// You can adjust the other settings once your site is up and running.

// +---------------------------------------------------------------------------+
// | (1) Database Settings |
// +---------------------------------------------------------------------------+

$_DB_host = 'localhost'; // host name or IP address of your DB server
$_DB_name = 'geeklog'; // name of your database,
// must exist before running the installer!
$_DB_user = 'root'; // MySQL user name
$_DB_pass = 'foo'; // MySQL password

// The table prefix is prepended to each table used be Geeklog to avoid name
// collisions with other tables that may already exist in your database.
$_DB_table_prefix = 'gl_'; // e.g. 'gl_'


// +---------------------------------------------------------------------------+
// | (2) Paths |
// +---------------------------------------------------------------------------+

// Note for Windows users: It's safe to use the forward slash '/' instead of
// the backslash '\' in paths. Make sure each path starts with a drive letter!

// This should point to the directory where your config.php file resides.
$_CONF['path'] = 'C:/Program Files/Apache Group/Apache/htdocs/projects/geeklog-1.3/'; // should end in a slash

// You only need to change this if you moved or renamed the public_html
// directory. In that case, you should specify the complete path to the
// directory (i.e. without the $_CONF['path']) like this:
// $_CONF['path_html'] = '/path/to/your/public_html/';
$_CONF['path_html'] = $_CONF['path'] . 'public_html/';


// +---------------------------------------------------------------------------+
// | (3) Site Settings |
// +---------------------------------------------------------------------------+

// Make sure this is the correct URL to your site, i.e. to where Geeklog's
// index.php file resides (no trailing slash).
$_CONF['site_url'] = 'http://localhost/geeklog-1.3/public_html';

// Some hosting services have a preconfigured admin directory. In that case,
// you need to rename Geeklog's admin directory to something like "myadmin"
// and change the following URL as well. Leave as is until you experience any
// problems accessing Geeklog's admin menu.
$_CONF['site_admin_url'] = $_CONF['site_url'] . '/admin';

// This is the return address for all email sent by Geeklog:
$_CONF['site_mail'] = 'admin at example.com';

// Name and slogan of your site
$_CONF['site_name'] = 'Geeklog Site';
$_CONF['site_slogan'] = 'Another Nifty Geeklog Site';


// ****************************************************************************
// * If you set up Geeklog for the first time, you shouldn't need to change *
// * anything below this line. Come back here once the site is up and running.*
// ****************************************************************************


// Note: See the file docs/config.html for more information on the settings.

// +---------------------------------------------------------------------------+
// | OTHER PATH SETTINGS |
// | |
// | All paths must have a trailing slash ('/'). |
// +---------------------------------------------------------------------------+

// you shouldn't need to edit theses
$_CONF['path_system'] = $_CONF['path'] . 'system/';
$_CONF['path_log'] = $_CONF['path'] . 'logs/';
$_CONF['path_language'] = $_CONF['path'] . 'language/';
$_CONF['backup_path'] = $_CONF['path'] . 'backups/';

// +---------------------------------------------------------------------------+
// | PEAR Settings |
// | |
// | Geeklog uses PEAR to send emails (see "Email Settings" below). Here you |
// | can Geeklog wether to use the PEAR packages installed on your server or |
// | to use the included packages. |
// +---------------------------------------------------------------------------+

// If your server is running PHP 4.3.0 (or newer) then chances are that PEAR
// is already installed and you can change this to: $_CONF['have_pear'] = true;
$_CONF['have_pear'] = false;

// Geeklog comes with the necessary PEAR packages and will pick them up from
// the following directory if $_CONF['have_pear'] = false (above).
$_CONF['path_pear'] = $_CONF['path_system'] . 'pear/';

// +---------------------------------------------------------------------------+
// | Email Settings |
// | |
// | Configure how Geeklog sends email: Via PHP's mail() function, sendmail, |
// | or via an SMTP server. |
// +---------------------------------------------------------------------------+

// To send email from Geeklog, you will need to select one of the following
// email backends:
// - 'mail', i.e. use PHP's built-in mail() function
// - 'sendmail', i.e. use the sendmail utility
// - 'smtp', i.e. talk directly to your SMTP server
// The default is 'mail' and will work in most environments.

$_CONF['mail_settings'] = array (
'backend' => 'mail', // can be one of 'mail', 'sendmail', 'smtp'

// sendmail parameters (for 'backend' => 'sendmail')
'sendmail_path' => '/usr/bin/sendmail',
'sendmail_args' => '',

// SMTP parameters (for 'backend' => 'smtp')
'host' => 'smtp.example.com',
'port' => '25',
'auth' => false,
'username' => 'smtp-username',
'password' => 'smtp-password'
);

// +---------------------------------------------------------------------------+
// | Email Settings |
// | |
// | Configure how Geeklog sends email: Via PHP's mail() function, sendmail, |
// | or via an SMTP server. |
// +---------------------------------------------------------------------------+
$_CONF['spelling_enabled'] = true;
$_CONF['spelling_language'] = 'en_US';
// Must be fully qualified location of the aspell binary
$_CONF['path_aspell'] = 'c:\progra~1\Aspell\bin\aspell';
// This is just for now, we probably shouldn't encourage the use of the logs
// dir since the call unlink() will happen there
$_CONF['path_tempdir'] = $_CONF['path'] . 'logs';

// +---------------------------------------------------------------------------+
// | OTHER DATABASE SETTINGS |
// | |
// | Database type and database backup settings. |
// +---------------------------------------------------------------------------+

$_DB_dbms = 'mysql'; // Do not change (currently, only MySQL is supported)

// optional settings for making database backups from within Geeklog
$_CONF['allow_mysqldump'] = 1; // 1 = on, 0 = off
$_DB_mysqldump_path = '/usr/bin/mysqldump'; // path to mysqldump binary
$_CONF['mysqldump_options'] = '-Q'; // additional options for mysqldump

// +---------------------------------------------------------------------------+
// | SITE SETTINGS |
// | |
// | These settings help define your Geeklog site. |
// +---------------------------------------------------------------------------+
$_CONF['theme'] = 'XSilver'; // default theme

// you shouldn't need to edit the following
$_CONF['layout_url'] = $_CONF['site_url'] . '/layout/' . $_CONF['theme'];
$_CONF['path_themes'] = $_CONF['path_html'] . 'layout/';
$_CONF['path_layout'] = $_CONF['path_themes'] . $_CONF['theme'] .'/';

// optional settings (1 = on, 0 = off)
$_CONF['allow_user_themes'] = 1;
$_CONF['allow_user_language'] = 1;
$_CONF['allow_user_photo'] = 1; // allow users to upload self-photo

// hides the list of authors from the preferences
$_CONF['hide_author_exclusion'] = 0;


// +---------------------------------------------------------------------------+
// | Support for custom user registration form and account details |
// | Requires custom functions to be written that can be placed in lib-custom |
// | Function hooks are in users.php, usersettings.php and admin/user.php |
// +---------------------------------------------------------------------------+
$_CONF['custom_registration'] = false; // Set to true if you have custom code


// +---------------------------------------------------------------------------+
// | LOCALE SETTINGS |
// +---------------------------------------------------------------------------+
$_CONF['language'] = 'english';
$_CONF['locale'] = 'en-gb';
$_CONF['date'] = '%A, %B %d %Y @ %I:%M %p %Z';
$_CONF['daytime'] = '%m/%d %I:%M%p';
$_CONF['shortdate'] = '%x';
$_CONF['dateonly'] = '%d-%b';
$_CONF['timeonly'] = '%I:%M %p %Z';
$_CONF['default_charset'] = 'iso-8859-1';

// +---------------------------------------------------------------------------+
// | SITE STATUS |
// | |
// | To disable your Geeklog site quickly, simply set this flag to false |
// +---------------------------------------------------------------------------+
$_CONF['site_enabled'] = true; // true or false

// Message shown when site is down
// When this starts with 'http:' visitors are redirected to that URL
$_CONF['site_disabled_msg'] = 'Geeklog Site is down. Please come back soon.';

// +---------------------------------------------------------------------------+
// | SESSION SETTINGS |
// | |
// | cookie_ip will store md5(remoteip + randomnum) as the session ID in the |
// | cookie. This is more secure but will more than likely require dialed up |
// | users to login each and every time. If ipbasedsessid is turned off |
// | (which it is by default) it will just store a random number as the |
// | session ID in the cookie. |
// | |
// | default_perm_cookie_timeout is how long you want the permanent cookie |
// | to persist for. This can be overridden by the user in their user prefs |
// | if they want. If you don't want to allow permanent cookies set the |
// | value to an empty string ''. |
// | |
// | session_cookie_time is how long you want the session cookie to persist |
// | for. Only really useful in scenarios where you don't want to allow |
// | permanent cookies |
// +---------------------------------------------------------------------------+

$_CONF['cookie_session'] = 'gl_session';
$_CONF['cookie_name'] = 'geeklog';
$_CONF['cookie_password'] = 'password';
$_CONF['cookie_theme'] = 'theme';
$_CONF['cookie_language'] = 'language';
$_CONF['cookie_lastvisit'] = 'LastVisit';
$_CONF['cookie_lastvisittemp'] = 'LastVisitTemp';

$_CONF['cookie_ip'] = 0;
$_CONF['default_perm_cookie_timeout'] = 604800;
$_CONF['session_cookie_timeout'] = 7200;
$_CONF['cookie_path'] = '/';
$_CONF['cookiedomain'] = ''; // e.g. '.example.com'
$_CONF['cookiesecure'] = 0;

// Set to false if you don't want to store last login data and time in the userinfo table
$_CONF['lastlogin'] = true;

// +---------------------------------------------------------------------------+
// | This is really redundant but I am including this as a reminder that those |
// | people writing Geeklog Plug-ins that are OS dependent should check either |
// | the $_CONF variable below or PHP_OS directly. If you are writing an |
// | addon that is OS specific your addon should check the system is using the |
// | right OS. If not, be sure to show a friendly message that says their GL |
// | distro isn't running the right OS. Do not modify this value |
// +---------------------------------------------------------------------------+

$_CONF['ostype'] = PHP_OS;

// +---------------------------------------------------------------------------+
// | SEARCH SETTINGS |
// | |
// | These aren't really used at the moment - leave as is ... |
// +---------------------------------------------------------------------------+

// Indicates if we should expand search results or not.
// true = show title with summary
// false = title date author hits on one line
$_CONF['expanded_search_results'] = true;

// 0: use users max stories per page
// 1: Show all
// any other number is the # of results per page
$_CONF['max_search_results'] = 1;

// maximum length for the summary text for search results should be
$_CONF['summary_length'] = 250;


// +---------------------------------------------------------------------------+
// | MISCELLANEOUS SETTINGS |
// | |
// | These are other various Geeklog settings. The defaults should work OK |
// | for most situations. |
// +---------------------------------------------------------------------------+

// this lets you select which functions are available for registered users only
$_CONF['loginrequired'] = 0; // all of them, if set to 1 will override all else
$_CONF['submitloginrequired'] = 0;
$_CONF['commentsloginrequired'] = 0;
$_CONF['linksloginrequired'] = 0;
$_CONF['pollsloginrequired'] = 0;
$_CONF['calendarloginrequired'] = 0;
$_CONF['statsloginrequired'] = 0;
$_CONF['searchloginrequired'] = 0;
$_CONF['profileloginrequired'] = 0;
$_CONF['emailuserloginrequired'] = 0;
$_CONF['emailstoryloginrequired'] = 0;

// Submission Settings

// enable (set to 1) or disable (set to 0) submission queues:
$_CONF['storysubmission'] = 1;
$_CONF['linksubmission'] = 1;
$_CONF['eventsubmission'] = 1;
$_CONF['usersubmission'] = 0;

// When set to 1, this will display an additional block on the submissions page
// that lists all stories that have the 'draft' flag set.
$_CONF['listdraftstories'] = 0;

// Send an email notification when a new submission has been made. The contents
// of the array can be any combination of 'story', 'link', 'event', and 'user'.
// Example: $_CONF['notification'] = array ('story', 'link', 'event');
// The email will be sent to $_CONF['site_mail'] (see above).
$_CONF['notification'] = array ();

$_CONF['postmode'] = 'plaintext'; // can be 'plaintext' or 'html'
$_CONF['speedlimit'] = 45; // in seconds
$_CONF['skip_preview'] = 0; // If = 1, allow user to submit comments and stories without previewing

// Allow users to change their username (if set to 1).
$_CONF['allow_username_change'] = 0;

// Allow users to delete their account (if set to 1).
$_CONF['allow_account_delete'] = 0;


// Topic Settings

// Topics can be assigned a sort number so that you can control what order they
// appear in the 'Topics' block on the homepage. If you prefer you can also
// have this sort alphabetically by changing the value to 'alpha' (default is
// by 'sortnum'

$_CONF['sortmethod'] = 'sortnum'; // or 'alpha'

// Show the number of stories in a topic in Topics Block
$_CONF['showstorycount'] = 1;

// Show the number of story submissions for a topic in Topics Block
$_CONF['showsubmissioncount'] = 1;

// Hide 'Home' link from Topics block (if set to 1)
$_CONF['hide_home_link'] = 0;

// Show blocks for empty search results
$_CONF['showemptysearchresults'] = 0;

// How long an anonymous (guest) user session is good for
$_CONF['whosonline_threshold'] = 300; // in seconds


// "Daily Digest" settings

// Let users get stories emailed to them
// Requires cron and the use of php as a shell script
$_CONF['emailstories'] = 0;

// Specify length of stories in those emails:
// 0 = send only title + link, 1 = send entire introtext,
// any other number = max. number of characters per story
$_CONF['emailstorieslength'] = 1;

// New users get stories emailed to them per default (= 1) or not (= 0)
$_CONF['emailstoriesperdefault'] = 0;


// When user submission is activated, allow users from these domains to
// register without having to go through the submission queue.
$_CONF['allow_domains'] = ''; // e.g. 'mycompany.com,myothercompany.com'

// Following times are in seconds
$_CONF['newstoriesinterval'] = 86400; // = 24 hours
$_CONF['newcommentsinterval'] = 172800; // = 48 hours
$_CONF['newlinksinterval'] = 1209600; // = 14 days

// Set to 1 to hide a section from the What's New block:
$_CONF['hidenewstories'] = 0;
$_CONF['hidenewcomments'] = 0;
$_CONF['hidenewlinks'] = 0;

// Calendar Settings
$_CONF['personalcalendars'] = 1;
$_CONF['showupcomingevents'] = 1;
$_CONF['upcomingeventsrange'] = 14; // days
$_CONF['event_types'] = 'Anniversary,Appointment,Birthday,Business,Education,Holiday,Meeting,Miscellaneous,Personal,Phone Call,Special Occasion,Travel,Vacation';

// Story Settings
$_CONF['maximagesperarticle'] = 5;
$_CONF['limitnews'] = 10;
$_CONF['minnews'] = 1; // minimum number of stories per page
$_CONF['contributedbyline'] = 1; // If 1, show contributed by line
$_CONF['article_image_align'] = 'right'; // Topic icon on left or right.
$_CONF['hideemailicon'] = 0; // If 1, hide "email story" option
$_CONF['hideprintericon'] = 0; // If 1, hide "printer friendly" option

// When set to 1, this will render the first story on any page using the
// templates for featured stories - even if that story is not featured.
$_CONF['showfirstasfeatured'] = 0;

// +---------------------------------------------------------------------------+
// | RSS feed settings |
// | |
// | Settings for RSS feeds (aka RDF feeds). Please note that most of these |
// | are merely default settings for the feeds created from the "Content |
// | Syndication" entry in the Admin's menu. |
// +---------------------------------------------------------------------------+

$_CONF['backend'] = 1; // 1 = activate feeds, 0 = off

// path to your site's default RSS feed
$_CONF['rdf_file'] = $_CONF['path_html'] . 'backend/geeklog.rdf';

// This allows a person to limit the rss feed to a certain number of stories
// (e.g. 10 or 12) or else limit the rss feed to all stories within a certain
// period of time in hours (e.g. 24h or 168h).
$_CONF['rdf_limit'] = 10; // number of stories (10) or hours (24h)

// Include the story's entire intro text in the feed (= 1) or limit the number
// of characters from the intro text (any number > 1) or don't include the text
// at all (= 0).
$_CONF['rdf_storytext'] = 0;

// Default language for the feed - may have to be different than the locale
$_CONF['rdf_language'] = 'en-gb';


// Uncomment the following line to set the copyright year in the site's footer
// to a specific year. Otherwise, the current year will be used.
// $_CONF['copyrightyear'] = '2003';


// Optional Image Settings

// If you set $_CONF['image_lib'] below, you must supply a path for the library
// you will use. Setting this also assumes that if a photo is uploaded that is
// too big either by the image sizes below or by overriding them using the
// upload object then the library you choose will attempt to resize the image.
// Leaving this value empty disables this feature
$_CONF['image_lib'] = ''; // can be one of 'netpbm', 'imagemagick', 'gdlib'

// If you set image_lib to imagemagick give this path otherwise comment it out
// NOTE: you will need a fairly recent version of ImageMagick for this to work.
// ImageMagick version 5.4.9 (or newer) is recommended.
//$_CONF['path_to_mogrify'] = '/path/to/mogrify';

// If you set image_lib to netpbm give the path to the netpbm directory, you
// need the trailing slash here.
// NOTE: if you use NETPBM, use the latest package from the Gallery package for
// your operating system found at http://sourceforge.net/projects/gallery in
// the download section. You need to take the netpbm tarball from them and
// uncompress the file which will create a netpbm directory. If you plan to
// only use netpbm with Geeklog, put that entire folder in /path/to/geeklog and
// adjust the path below. The only programs you need from netpbm are giftopnm,
// jpegtopnm, pngtopnm, ppmtogif, ppmtojpeg, pnmtopng and pnmscale
//$_CONF['path_to_netpbm'] = '/path/to/netpbm/';

// Uncomment the following line if you experience problems with the image
// upload. Debug messages will be added to the error.log file.
// $_CONF['debug_image_upload'] = true;

// When set to 1, Geeklog will keep the original, unscaled images and make
// the smaller image link to the unscaled image.
$_CONF['keep_unscaled_image'] = 0; // 1 = keep original images

// Story image settings
$_CONF['max_image_width'] = 300; // In pixels
$_CONF['max_image_height'] = 300; // In pixels
$_CONF['max_image_size'] = 1048576; // 1048576 = 1MB

// User photo settings
$_CONF['max_photo_width'] = 96; // In pixels
$_CONF['max_photo_height'] = 96; // In pixels
$_CONF['max_photo_size'] = 65536; // 65536 = 64KB

// Comment Settings
$_CONF['commentspeedlimit'] = 45;
$_CONF['comment_limit'] = 100; // Default Number of Comments under Story
$_CONF['comment_mode'] = 'threaded'; // Default Comment Mode; from 'threaded','nested','nocomments',and 'flat'
// Allow / disallow comments to stories by default (can be changed individually for every story)
$_CONF['comment_code'] = 0; // 0 = comments enabled, -1 = disabled

// Poll Settings
$_CONF['maxanswers'] = 10;
// 'submitorder' is order answers are saved in admin/poll.php
// 'voteorder' will list answers in order of number of votes (highest->lowest);
$_CONF['answerorder'] = 'submitorder';
$_CONF['pollcookietime'] = 86400;
$_CONF['polladdresstime'] = 604800;

// Password setting: minimum time between two requests for a new password
$_CONF['passwordspeedlimit'] = 300; // seconds = 5 minutes

// Links Settings
// You can set both of the following to 0 to get back the old (pre-1.3.6)
// style of the links section. Setting only linkcols to 0 will hide the
// categories but keep the paging. Setting only linksperpage to 0 will list
// all the links of the selected category on one page.
$_CONF['linkcols'] = 3; // categories per column
$_CONF['linksperpage'] = 10; // links per page

// Parameters for checking HTML tags

// *** Warning: Adding the following tags to the list of allowable HTML can
// *** make your site vulnerable to scripting attacks!
// *** Use with care: <img> <span> <marquee> <script> <embed> <object> <iframe>

/* This is a list of HTML tags that users are allowed to use in their posts.
* Each tag can have a list of allowed attributes (see 'a' for an example).
* Any attributes not listed will be filtered, i.e. removed.
*/
$_CONF['user_html'] = array (
'p' => array(),
'b' => array(),
'i' => array(),
'a' => array('href' => 1, 'title' => 1),
'em' => array(),
'br' => array(),
'tt' => array(),
'hr' => array(),
'li' => array(),
'ol' => array(),
'ul' => array(),
'code' => array(),
'pre' => array()
);

/* This is a list of HTML tags that Admins (site admin and story admins) can
* use in their posts. It will be merged with the above list of user-allowable
* tags ($_CONF['user_html']). You can also add tags that have already been
* listed for the user-allowed HTML, so as to allow admins to use more
* attributes (see 'p' for an example).
*/
$_CONF['admin_html'] = array (
'p' => array('class' => 1, 'id' => 1, 'align' => 1),
'div' => array('class' => 1, 'id' => 1),
'span' => array('class' => 1, 'id' => 1),
'table' => array('class' => 1, 'id' => 1, 'width' => 1, 'border' => 1,
'cellspacing' => 1, 'cellpadding' => 1),
'tr' => array('class' => 1, 'id' => 1, 'align' => 1, 'valign' => 1),
'th' => array('class' => 1, 'id' => 1, 'align' => 1, 'valign' => 1,
'colspan' => 1, 'rowspan' => 1),
'td' => array('class' => 1, 'id' => 1, 'align' => 1, 'valign' => 1,
'colspan' => 1, 'rowspan' => 1)
);

// Parameters for checking for "bad" words
$_CONF['censormode'] = 1;
$_CONF['censorreplace'] = '*censored*';
$_CONF['censorlist'] = array('fuck','cunt','fucker','fucking','pussy','cock','c0ck',' cum ','twat','clit','bitch','fuk','fuking','motherfucker');

// EXPERIMENTAL!
// This feature when fully implemented, will make your site crawler friendly.
// Only works with staticpages right now.
//
// Note: Works with Apache (Linux and Windows successfully tested).
// Unresolvable issues with systems running IIS; known PHP CGI bug.
$_CONF['url_rewrite'] = false; // false = off, true = on

// Define a few useful things for GL
if (!defined ('LB')) {
define('LB',"\n");
}
if (!defined ('VERSION')) {
define('VERSION', '1.3.8-1');
}

$_STATES = array(
'--'=>'',
'AL'=>'Alabama',
'AK'=>'Alaska',
'AZ'=>'Arizona',
'AR'=>'Arkansas',
'CA'=>'California',
'CO'=>'Colorado',
'CT'=>'Connecticut',
'DE'=>'Delaware',
'DC'=>'District of Columbia',
'FL'=>'Florida',
'GA'=>'Georgia',
'HI'=>'Hawaii',
'ID'=>'Idaho',
'IL'=>'Illinois',
'IN'=>'Indiana',
'IA'=>'Iowa',
'KS'=>'Kansas',
'KY'=>'Kentucky',
'LA'=>'Louisiana',
'ME'=>'Maine',
'MD'=>'Maryland',
'MA'=>'Massachusetts',
'MI'=>'Michigan',
'MN'=>'Minnesota',
'MS'=>'Mississippi',
'MO'=>'Missouri',
'MT'=>'Montana',
'NE'=>'Nebraska',
'NV'=>'Nevada',
'NH'=>'New Hampshire',
'NJ'=>'New Jersey',
'NM'=>'New Mexico',
'NY'=>'New York',
'NC'=>'North Carolina',
'ND'=>'North Dakota',
'OH'=>'Ohio',
'OK'=>'Oklahoma',
'OR'=>'Oregon',
'PA'=>'Pennsylvania',
'RI'=>'Rhode Island',
'SC'=>'South Carolina',
'SD'=>'South Dakota',
'TN'=>'Tennessee',
'TX'=>'Texas',
'UT'=>'Utah',
'VT'=>'Vermont',
'VA'=>'Virginia',
'WA'=>'Washington',
'WV'=>'West Virginia',
'WI'=>'Wisconsin',
'WY'=>'Wyoming'
);

?>

--------------060409070102020704010509
Content-Type: text/html;
name="story.php"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
filename="story.php"

<?php

/* Reminder: always indent with 4 spaces (no tabs). */
// +---------------------------------------------------------------------------+
// | Geeklog 1.3 |
// +---------------------------------------------------------------------------+
// | story.php |
// | |
// | Geeklog story administration page. |
// +---------------------------------------------------------------------------+
// | Copyright (C) 2000-2003 by the following authors: |
// | |
// | Authors: Tony Bibbs - tony at tonybibbs.com |
// | Mark Limburg - mlimburg at users.sourceforge.net |
// | Jason Whittenburg - jwhitten at securitygeeks.com |
// | Dirk Haun - dirk at haun-online.de |
// +---------------------------------------------------------------------------+
// | |
// | This program is free software; you can redistribute it and/or |
// | modify it under the terms of the GNU General Public License |
// | as published by the Free Software Foundation; either version 2 |
// | of the License, or (at your option) any later version. |
// | |
// | This program is distributed in the hope that it will be useful, |
// | but WITHOUT ANY WARRANTY; without even the implied warranty of |
// | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
// | GNU General Public License for more details. |
// | |
// | You should have received a copy of the GNU General Public License |
// | along with this program; if not, write to the Free Software Foundation, |
// | Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
// | |
// +---------------------------------------------------------------------------+
//
// $Id: story.php,v 1.108 2003/09/28 13:23:42 dhaun Exp $

/**
* This is the Geeklog story administration page.
*
* @author Jason Whittenburg
* @author Tony Bibbs <tony at tonybibbs.com>
*
*/

/**
* Geeklog commong function library
*/
require_once '../lib-common.php';
require_once $_CONF['path_system'] . 'classes/PHPSpellChecker.class.php';
/**
* Security check to ensure user even belongs on this page
*/
require_once 'auth.inc.php';

// Set this to true if you want to have this code output debug messages to
// the error log
$_STORY_VERBOSE = false;

$display = '';

if (!SEC_hasRights('story.edit')) {
$display .= COM_siteHeader ('menu');
$display .= COM_startBlock ($MESSAGE[30], '',
COM_getBlockTemplate ('_msg_block', 'header'));
$display .= $MESSAGE[31];
$display .= COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'));
$display .= COM_siteFooter ();
COM_errorLog("User {$_USER['username']} tried to illegally access the story administration screen",1);
echo $display;
exit;
}

// Uncomment the line below if you need to debug the HTTP variables being passed
// to the script. This will sometimes cause errors but it will allow you to see
// the data being passed in a POST operation
// debug($HTTP_POST_VARS);

/**
* Shows story editor
*
* Displays the story entry form
*
* @param string $sid ID of story to edit
* @param string $mode ??
* @return string HTML for story editor
*
*/
function storyeditor($sid = '', $mode = '')
{
global $_TABLES, $HTTP_POST_VARS, $_USER, $_CONF, $LANG24, $LANG_ACCESS;

$display = '';

if ($_CONF['spelling_enabled']) {
$spellChecker = new PHPSpellChecker();
$spellChecker->setPathToApsellBinary($_CONF['path_aspell']);
$spellChecker->setTempDir($_CONF['path_tempdir']);
}
if (!empty($sid) && $mode == 'edit') {
$result = DB_query("SELECT *,UNIX_TIMESTAMP(date) AS unixdate FROM {$_TABLES['stories']} WHERE sid = '$sid'");
$A = DB_fetchArray($result);
$access = SEC_hasAccess($A['owner_id'],$A['group_id'],$A['perm_owner'],$A['perm_group'],$A['perm_members'],$A['perm_anon']);
$access = min ($access, SEC_hasTopicAccess ($A['tid']));
if ($access == 2) {
$display .= COM_startBlock($LANG24[40], '',
COM_getBlockTemplate ('_msg_block', 'header'));
$display .= $LANG24[41];
$display .= COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'));
// Do this to avoid having to chance $A
$B = $A;
if ($_CONF['spelling_enabled']) {
if ($B['postmode'] == 'html') {
$B['introtext'] = $spellChecker->checkWords($B['introtext'], true);
$B['bodytext'] = $spellChecker->checkWords($B['bodytext'], true);
$B['title']= $spellChecker->checkWords($B['title'], true);
} else {
$B['introtext'] = $spellChecker->checkWords($B['introtext'], false);
$B['bodytext'] = $spellChecker->checkWords($B['bodytext'], false);
$B['title']= $spellChecker->checkWords($B['title'], false);
}
}
$display .= COM_article($B,n);
return $display;
} else if ($access == 0) {
$display .= COM_startBlock($LANG24[40], '',
COM_getBlockTemplate ('_msg_block', 'header'));
$display .= $LANG24[42];
$display .= COM_endBlock(COM_getBlockTemplate ('_msg_block', 'footer'));
return $display;
}
} elseif (!empty($sid) && $mode == "editsubmission") {
$result = DB_query("SELECT *,UNIX_TIMESTAMP(date) AS unixdate FROM {$_TABLES['storysubmission']} WHERE sid = '$sid'");
if (DB_numRows ($result) > 0) {
$A = DB_fetchArray($result);
$A['show_topic_icon'] = 1;
$A['commentcode'] = $_CONF['comment_code'];
$A['featured'] = 0;
$A['statuscode'] = 0;
$A['owner_id'] = $A['uid'];
$result = DB_query ("SELECT group_id,perm_owner,perm_group,perm_members,perm_anon FROM {$_TABLES['topics']} WHERE tid = '{$A['tid']}'");
$T = DB_fetchArray ($result);
$A['group_id'] = $T['group_id'];
$A['perm_owner'] = $T['perm_owner'];
$A['perm_group'] = $T['perm_group'];
$A['perm_members'] = $T['perm_members'];
$A['perm_anon'] = $T['perm_anon'];
$access = 3;
$A['title'] = htmlspecialchars ($A['title']);
} else {
// that submission doesn't seem to be there any more (may have been
// handled by another Admin) - take us back to the moderation page
return COM_refresh ($_CONF['site_admin_url'] . '/moderation.php');
}
} elseif ($mode == "edit") {
$A['sid'] = COM_makesid();
$A['show_topic_icon'] = 1;
$A['uid'] = $_USER['uid'];
$A['unixdate'] = time();
$A['commentcode'] = $_CONF['comment_code'];
$A['postmode'] = $_CONF['postmode'];
$A['statuscode'] = 0;
$A['featured'] = 0;
$A['owner_id'] = $_USER['uid'];
$A['group_id'] = DB_getItem ($_TABLES['groups'], 'grp_id',
"grp_name = 'Story Admin'");
$A['perm_owner'] = 3;
$A['perm_group'] = 2;
$A['perm_members'] = 2;
$A['perm_anon'] = 2;
$access = 3;
} else {
$A = $HTTP_POST_VARS;

if (empty ($A['ampm'])) {
$A['ampm'] = $A['publish_ampm'];
}
if ($A['draft_flag'] == 'on') {
$A['draft_flag'] = 1;
} else {
$A['draft_flag'] = 0;
}
if ($A['show_topic_icon'] == 'on') {
$A['show_topic_icon'] = 1;
} else {
$A['show_topic_icon'] = 0;
}

// Convert array values to numeric permission values
list($A['perm_owner'],$A['perm_group'],$A['perm_members'],$A['perm_anon']) = SEC_getPermissionValues($A['perm_owner'],$A['perm_group'],$A['perm_members'],$A['perm_anon']);
if ($A["postmode"] == "html") {
$A["introtext"] = COM_checkHTML(COM_checkWords($A["introtext"]));
$A["bodytext"] = COM_checkHTML(COM_checkWords($A["bodytext"]));
$A["title"] = COM_checkHTML(htmlspecialchars(COM_checkWords($A["title"])));
} else {
$A["introtext"] = htmlspecialchars(COM_checkWords($A["introtext"]));
$A["bodytext"] = htmlspecialchars(COM_checkWords($A["bodytext"]));
$A["title"] = htmlspecialchars(COM_checkWords($A["title"]));
}
$A['title'] = strip_tags($A['title']);
}

// Load HTML templates
$story_templates = new Template($_CONF['path_layout'] . 'admin/story');
if (($_CONF['advanced_editor'] == 1) && file_exists ($_CONF['path_layout'] . 'admin/story/storyeditor_advanced.thtml')) {
$story_templates->set_file(array('editor'=>'storyeditor_advanced.thtml'));
} else {
$story_templates->set_file(array('editor'=>'storyeditor.thtml'));
}
$story_templates->set_var('site_url', $_CONF['site_url']);
$story_templates->set_var('site_admin_url', $_CONF['site_admin_url']);
$story_templates->set_var('layout_url', $_CONF['layout_url']);

if (empty($A['unixdate'])) {
$publish_hour = $A['publish_hour'];
if ($publish_hour == 12) {
if ($A['ampm'] == 'am') {
$publish_hour = 0;
}
} else if ($A['ampm'] == 'pm') {
$publish_hour += 12;
}
$A['unixdate'] = strtotime($A['publish_year'] . '-' . $A['publish_month'] . '-' . $A['publish_day']
. ' ' . $publish_hour . ':' . $A['publish_minute'] . ':00');
}

if (!empty($A['title'])) {
$display .= COM_startBlock ($LANG24[26], '',
COM_getBlockTemplate ('_admin_block', 'header'));
$A['day'] = $A['unixdate'];
if (empty ($A['hits'])) {
$A['hits'] = 0;
}
$B = $A;
if ($_CONF['spelling_enabled']) {
if ($B['postmode'] == 'html') {
$B['introtext'] = $spellChecker->checkWords($B['introtext'], true);
$B['bodytext'] = $spellChecker->checkWords($B['bodytext'], true);
$B['title']= $spellChecker->checkWords($B['title'], true);
} else {
$B['introtext'] = $spellChecker->checkWords($B['introtext'], false);
$B['bodytext'] = $spellChecker->checkWords($B['bodytext'], false);
$B['title']= $spellChecker->checkWords($B['title'], false);
}
}
$display .= COM_article($B,"n");
$display .= COM_endBlock (COM_getBlockTemplate ('_admin_block', 'footer'));
}

$display .= COM_startBlock ($LANG24[5], '',
COM_getBlockTemplate ('_admin_block', 'header'));

if ($access == 3) {
$story_templates->set_var ('delete_option',
'<input type="submit" value="' . $LANG24[11] . '" name="mode">');
}
if ($A['type'] == 'editsubmission' || $mode == 'editsubmission') {
$story_templates->set_var ('submission_option',
'<input type="hidden" name="type" value="submission">');
}
$story_templates->set_var('lang_author', $LANG24[7]);
$story_templates->set_var ('story_author', DB_getItem ($_TABLES['users'],
'username', "uid = {$A['uid']}"));
$story_templates->set_var('story_uid', $A['uid']);

// user access info
$story_templates->set_var('lang_accessrights',$LANG_ACCESS['accessrights']);
$story_templates->set_var('lang_owner', $LANG_ACCESS['owner']);
$story_templates->set_var ('owner_username', DB_getItem ($_TABLES['users'],
'username', "uid = {$A['owner_id']}"));
$story_templates->set_var('owner_id', $A['owner_id']);
$story_templates->set_var('lang_group', $LANG_ACCESS['group']);

$usergroups = SEC_getUserGroups();
if ($access == 3) {
$groupdd .= '<select name="group_id">';
for ($i = 0; $i < count($usergroups); $i++) {
$groupdd .= '<option value="' . $usergroups[key($usergroups)] . '"';
if ($A['group_id'] == $usergroups[key($usergroups)]) {
$groupdd .= ' selected="selected"';
}
$groupdd .= '>' . key($usergroups) . '</option>';
next($usergroups);
}
$groupdd .= '</select>';
} else {
// they can't set the group then
$groupdd .= DB_getItem ($_TABLES['groups'], 'grp_name',
"grp_id = {$A['group_id']}");
$groupdd .= '<input type="hidden" name="group_id" value="'
. $A['group_id'] . '">';
}
$story_templates->set_var('group_dropdown', $groupdd);
$story_templates->set_var('lang_permissions', $LANG_ACCESS['permissions']);
$story_templates->set_var('lang_perm_key', $LANG_ACCESS['permissionskey']);
$story_templates->set_var('permissions_editor', SEC_getPermissionsHTML($A['perm_owner'],$A['perm_group'],$A['perm_members'],$A['perm_anon']));
$story_templates->set_var('permissions_msg', $LANG_ACCESS['permmsg']);
$curtime = COM_getUserDateTimeFormat($A['unixdate']);
$story_templates->set_var('lang_date', $LANG24[15]);
$publish_month = date('m', $A['unixdate']);
$publish_day = date('d', $A['unixdate']);
$publish_year = date('Y', $A['unixdate']);
$publish_hour = date('H', $A['unixdate']);
$publish_minute = date('i', $A['unixdate']);
$publish_second = date('s', $A['unixdate']);
$story_templates->set_var('publish_second', $publish_second);
$publish_ampm = '';
if ($publish_hour >= 12) {
if ($publish_hour > 12) {
$publish_hour = $publish_hour - 12;
}
$ampm = 'pm';
} else {
$ampm = 'am';
}
if ($ampm == 'pm') {
$story_templates->set_var ('publishpm_selected', 'selected="selected"');
} else {
$story_templates->set_var ('publisham_selected', 'selected="selected"');
}
$month_options = COM_getMonthFormOptions($publish_month);
$story_templates->set_var('publish_month_options', $month_options);

$day_options = COM_getDayFormOptions($publish_day);
$story_templates->set_var('publish_day_options', $day_options);

$year_options = COM_getYearFormOptions($publish_year);
$story_templates->set_var('publish_year_options', $year_options);

$hour_options = COM_getHourFormOptions($publish_hour);
$story_templates->set_var('publish_hour_options', $hour_options);

$minute_options = COM_getMinuteOptions($publish_minute);
$story_templates->set_var('publish_minute_options', $minute_options);

$story_templates->set_var('publish_date_explanation', $LANG24[46]);

$story_templates->set_var('story_unixstamp', $A['unixdate']);
$story_templates->set_var('lang_title', $LANG24[13]);
if ($A['postmode'] == 'plaintext') {
$A['title'] = str_replace('$','&#36;',$A['title']);
}

$A['title'] = str_replace('{','&#123;',$A['title']);
$A['title'] = str_replace('}','&#125;',$A['title']);
$A['title'] = str_replace('"','&quot;',$A['title']);
$story_templates->set_var('story_title', stripslashes ($A['title']));
$story_templates->set_var('lang_topic', $LANG24[14]);
if (empty ($A['tid'])) {
$A['tid'] = DB_getItem ($_TABLES['topics'], 'tid', 'is_default = 1' . COM_getPermSQL ('AND'));
}
$story_templates->set_var ('topic_options', COM_topicList ('tid,topic', $A['tid']));
$story_templates->set_var('lang_show_topic_icon', $LANG24[56]);
if ($A['show_topic_icon'] == 1) {
$story_templates->set_var('show_topic_icon_checked', 'checked="checked"');
} else {
$story_templates->set_var('show_topic_icon_checked', '');
}
$story_templates->set_var('lang_draft', $LANG24[34]);
if ($A['draft_flag'] == 1) {
$story_templates->set_var('is_checked', 'checked="checked"');
}
$story_templates->set_var('lang_mode', $LANG24[3]);
$story_templates->set_var('status_options', COM_optionList($_TABLES['statuscodes'],'code,name',$A['statuscode']));
$story_templates->set_var('comment_options', COM_optionList($_TABLES['commentcodes'],'code,name',$A['commentcode']));
$story_templates->set_var('featured_options', COM_optionList($_TABLES['featurecodes'],'code,name',$A['featured']));
$story_templates->set_var('frontpage_options', COM_optionList($_TABLES['frontpagecodes'],'code,name',$A['frontpage']));
list($newintro, $newbody) = replace_images($A['sid'], stripslashes($A['introtext']), stripslashes($A['bodytext']));

$story_templates->set_var('lang_introtext', $LANG24[16]);
if ($A['postmode'] == 'plaintext') {
$newintro = str_replace('$','&#36;',$newintro);
} else {
// Insert [code] and [/code] if needed
$newintro = str_replace('<pre><code>','[code]',$newintro);
$newbody = str_replace('<pre><code>','[code]',$newbody);
$newintro = str_replace('</code></pre>','[/code]',$newintro);
$newbody = str_replace('</code></pre>','[/code]',$newbody);
}
$newintro = str_replace('{','&#123;',$newintro);
$newintro = str_replace('}','&#125;',$newintro);
$story_templates->set_var('story_introtext', $newintro);
$story_templates->set_var('lang_bodytext', $LANG24[17]);
if ($A['postmode'] == 'plaintext') {
$newbody = str_replace('$','&#36;',$newbody);
}

$newbody = str_replace('{','&#123;',$newbody);
$newbody = str_replace('}','&#125;',$newbody);
$story_templates->set_var('story_bodytext', $newbody);
$story_templates->set_var('lang_postmode', $LANG24[4]);
$story_templates->set_var('post_options', COM_optionList($_TABLES['postmodes'],'code,name',$A['postmode']));
$story_templates->set_var('lang_allowed_html', COM_allowedHTML());
$fileinputs = '';
$saved_images = '';
if ($_CONF['maximagesperarticle'] > 0) {
$story_templates->set_var('lang_images', $LANG24[47]);
$icount = DB_count($_TABLES['article_images'],'ai_sid', $A['sid']);
if ($icount > 0) {
$result_articles = DB_query("SELECT * FROM {$_TABLES['article_images']} WHERE ai_sid = '{$A['sid']}'");
for ($z = 1; $z <= $icount; $z++) {
$I = DB_fetchArray($result_articles);
$saved_images .= $z . ') <a href="' . $_CONF['site_url'] . '/images/articles/' . $I['ai_filename'] . '" target="_blank">' . $I['ai_filename'] . '</a>';
$saved_images .= '&nbsp;&nbsp;&nbsp;' . $LANG24[52] . ': <input type="checkbox" name="delete[' .$I['ai_img_num'] . ']"><br>';
}
}

$newallowed = $_CONF['maximagesperarticle'] - $icount;
for ($z = $icount + 1; $z <= $_CONF['maximagesperarticle']; $z++) {
$fileinputs .= $z . ') <input type="file" name="file' . $z . '">';
if ($z < $_CONF['maximagesperarticle']) {
$fileinputs .= '<br>';
}
}
$fileinputs .= '<br>' . $LANG24[51] . '<br>';
}
$story_templates->set_var('saved_images', $saved_images);
$story_templates->set_var('image_form_elements', $fileinputs);
$story_templates->set_var('lang_hits', $LANG24[18]);
$story_templates->set_var('story_hits', $A['hits']);
$story_templates->set_var('lang_comments', $LANG24[19]);
$story_templates->set_var('story_comments', $A['comments']);
$story_templates->set_var('lang_emails', $LANG24[39]);
$story_templates->set_var('story_emails', $A['numemails']);
$story_templates->set_var('story_id', $A['sid']);
$story_templates->set_var('lang_save', $LANG24[8]);
$story_templates->set_var('lang_preview', $LANG24[9]);
$story_templates->set_var('lang_cancel', $LANG24[10]);
$story_templates->set_var('lang_delete', $LANG24[11]);
$story_templates->parse('output','editor');
$display .= $story_templates->finish($story_templates->get_var('output'));
$display .= COM_endBlock (COM_getBlockTemplate ('_admin_block', 'footer'));

return $display;
}

/**
* List all stories in the system
*
* This lists all the stories in the database
*
* @param int $page Page to show user
* @return string HTML for story listing
*
*/
function liststories($page = 1)
{
global $_TABLES, $LANG24, $_CONF, $LANG_ACCESS, $LANG09, $_USER, $_GROUPS,$HTTP_POST_VARS,$HTTP_GET_VARS;

$display = '';

$display .= COM_startBlock ($LANG24[22], '',
COM_getBlockTemplate ('_admin_block', 'header'));
$story_templates = new Template($_CONF['path_layout'] . 'admin/story');
$story_templates->set_file (array ('list' => 'liststories.thtml',
'row' => 'listitem.thtml'));

$story_templates->set_var('layout_url', $_CONF['layout_url']);
$story_templates->set_var('site_url', $_CONF['site_url']);
$story_templates->set_var('site_admin_url', $_CONF['site_admin_url']);
$story_templates->set_var('lang_newstory', $LANG24[43]);
$story_templates->set_var('lang_adminhome', $LANG24[44]);
$story_templates->set_var('lang_instructions', $LANG24[23]);
$story_templates->set_var('lang_title', $LANG24[13]);
$story_templates->set_var('lang_access', $LANG_ACCESS['access']);
$story_templates->set_var('lang_draft', $LANG24[34]);
$story_templates->set_var('lang_author', $LANG24[7]);
$story_templates->set_var('lang_date', $LANG24[15]);
$story_templates->set_var('lang_topic', $LANG24[14]);
$story_templates->set_var('lang_featured', $LANG24[32]);

if (!empty ($HTTP_GET_VARS['tid'])) {
$current_topic = $HTTP_GET_VARS['tid'];
} elseif (!empty ($HTTP_POST_VARS['tid'])) {
$current_topic = $HTTP_POST_VARS['tid'];
} else {
$current_topic = $LANG09['9'];
}
if (empty($page)) {
$page = 1;
}

if ($current_topic == $LANG09['9']) {
$excludetopics = '';
$topicsql = "SELECT tid,topic FROM {$_TABLES['topics']}" . COM_getPermSQL ();
$tresult = DB_query( $topicsql );
$trows = DB_numRows( $tresult );
if( $trows > 0 )
{
$excludetopics .= " WHERE (";
for( $i = 1; $i <= $trows; $i++ ) {
$T = DB_fetchArray ($tresult);
if ($i > 1) {
$excludetopics .= " OR ";
}
$excludetopics .= "tid = '{$T['tid']}'";
$seltopics .= '<option value="' .$T['tid']. '"';
if ($current_topic == "{$T['tid']}") {
$seltopics .= ' selected="selected"';
}
$seltopics .= '>' . $T['topic'] . '</option>' . LB;
}
$excludetopics .= ") ";
}

} else {
$excludetopics = " WHERE tid = '$current_topic' ";
$seltopics = COM_topicList ('tid,topic', $current_topic);
}

$alltopics = '<option value="' .$LANG09['9']. '"';
if ($current_topic == $LANG09['9']) {
$alltopics .= ' selected="selected"';
}
$alltopics .= '>' .$LANG09['9']. '</option>' . LB;
$story_templates->set_var ('topic_selection', '<select name="tid" style="width: 125px" onchange="this.form.submit()">' . $alltopics . $seltopics . '</select>');

$limit = (50 * $page) - 50;
$result = DB_query("SELECT *,UNIX_TIMESTAMP(date) AS unixdate FROM {$_TABLES['stories']} " . $excludetopics . "ORDER BY date DESC LIMIT $limit,50");
$nrows = DB_numRows($result);
if ($nrows > 0) {
for ($i = 1; $i <= $nrows; $i++) {
$scount = (50 * $page) - 50 + $i;
$A = DB_fetchArray($result);
$access = SEC_hasAccess($A['owner_id'],$A['group_id'],$A['perm_owner'],$A['perm_group'],$A['perm_members'],$A['perm_anon']);
if ($access > 0) {
if ($access == 3) {
if (SEC_hasTopicAccess ($A['tid']) == 3) {
$access = $LANG_ACCESS['edit'];
} else {
$access = $LANG_ACCESS['readonly'];
}
} else {
$access = $LANG_ACCESS['readonly'];
}
} else {
$access = $LANG_ACCESS['none'];
}
$curtime = COM_getUserDateTimeFormat($A['unixdate']);
$story_templates->set_var('story_id', $A['sid']);
$story_templates->set_var('row_num', $scount);
$A['title'] = str_replace('$', '&#36;', $A['title']);
$story_templates->set_var('story_title', stripslashes($A['title']));
$story_templates->set_var('story_access', $access);
if ($A['draft_flag'] == 1) {
$story_templates->set_var('story_draft', $LANG24[35]);
} else {
$story_templates->set_var('story_draft', $LANG24[36]);
}
$story_templates->set_var('story_author', DB_getItem($_TABLES['users'],'username',"uid = {$A['uid']}"));
$story_templates->set_var('story_date', strftime($_CONF['shortdate'], $curtime[1]));
$story_templates->set_var('story_topic', $A['tid']);
if ($A['featured'] == 1) {
$story_templates->set_var('story_feature', $LANG24[35]);
} else {
$story_templates->set_var('story_feature', $LANG24[36]);
}
$story_templates->parse('storylist_item','row',true);
}

// Print prev/next page links if needed
$nresult = DB_query ("SELECT COUNT(*) AS count FROM {$_TABLES['stories']}" . $excludetopics);
$N = DB_fetchArray ($nresult);
$numstories = $N['count'];
if ($numstories > 50) {
$prevpage = $page - 1;
$nextpage = $page + 1;
$pagestart = ($page - 1) * 50;
if ($pagestart >= 50) {
$story_templates->set_var ('previouspage_link', '<a href="'
. $_CONF['site_admin_url']
. '/story.php?mode=list&amp;page=' . $prevpage . '">'
. $LANG24[1] . '</a> ');
} else {
$story_templates->set_var('previouspage_link','');
}
if ($pagestart <= ($numstories - 50)) {
$story_templates->set_var ('nextpage_link', '<a href="'
. $_CONF['site_admin_url']
. '/story.php?mode=list&amp;page=' . $nextpage . '">'
. $LANG24[2] . '</a> ');
} else {
$story_templates->set_var('nextpage_link','');
}
$baseurl = $_CONF['site_admin_url'] . '/story.php?mode=list&tid=' .$current_topic;
$numpages = ceil ($numstories / 50);
$story_templates->set_var ('google_paging',
COM_printPageNavigation ($baseurl, $page, $numpages));
} else {
$story_templates->set_var ('previouspage_link' ,'');
$story_templates->set_var ('nextpage_link' ,'');
$story_templates->set_var ('google_paging' ,'');
}

} else {
// There are no news items
$story_templates->set_var ('storylist_item', '<tr><td colspan="8">'
. $LANG24[6] . '</td></tr>');
$story_templates->set_var ('previouspage_link', '');
$story_templates->set_var ('nextpage_link', '');
$story_templates->set_var ('google_paging' ,'');
}
$display .= $story_templates->parse('output','list');
$display .= COM_endBlock (COM_getBlockTemplate ('_admin_block', 'footer'));

return $display;
}

/**
* This replaces all article image HTML in intro and body with
* GL special syntax
*
* @param string $sid ID for story to parse
* @param string $intro Intro text
* @param string $body Body text
* @return string processed text
*
*/
function replace_images($sid, $intro, $body)
{
global $_CONF, $_TABLES, $LANG24;

$result = DB_query("SELECT ai_filename FROM {$_TABLES['article_images']} WHERE ai_sid = '$sid' ORDER BY ai_img_num");
$nrows = DB_numRows($result);
for ($i = 1; $i <= $nrows; $i++) {
$A = DB_fetchArray($result);
$dimensions = GetImageSize($_CONF['path_html'] . 'images/articles/' . $A['ai_filename']);
if (!empty($dimensions[0]) AND !empty($dimensions[1])) {
$sizeattributes = 'width="' . $dimensions[0] . '" height="' . $dimensions[1] . '" ';
} else {
$sizeattributes = '';
}

$lLinkPrefix = '';
$lLinkSuffix = '';
if ($_CONF['keep_unscaled_image'] == 1) {
$lFilename_large = substr_replace ($A['ai_filename'], '_original.',
strrpos ($A['ai_filename'], '.'), 1);
$lFilename_large_complete = $_CONF['path_html'] . 'images/articles/'
. $lFilename_large;
$lFilename_large_URL = $_CONF['site_url'] . '/images/articles/'
. $lFilename_large;
if (file_exists ($lFilename_large_complete)) {
$lLinkPrefix = '<a href="' . $lFilename_large_URL
. '" title="' . $LANG24[57] . '">';
$lLinkSuffix = '</a>';
}
}

$norm = $lLinkPrefix . '<img ' . $sizeattributes . 'src="' . $_CONF['site_url'] . '/images/articles/' . $A['ai_filename'] . '" alt="">' . $lLinkSuffix;
$left = $lLinkPrefix . '<img ' . $sizeattributes . 'align="left" src="' . $_CONF['site_url'] . '/images/articles/' . $A['ai_filename'] . '" alt="">' . $lLinkSuffix;
$right = $lLinkPrefix . '<img ' . $sizeattributes . 'align="right" src="' . $_CONF['site_url'] . '/images/articles/' . $A['ai_filename'] . '" alt="">' . $lLinkSuffix;
$fulltext = $intro . ' ' . $body;
$count = substr_count($fulltext, $norm) + substr_count($fulltext, $left) + substr_count($fulltext, $right);
$intro = str_replace($norm, '[' . $LANG24[48] . $i . ']', $intro);
$body = str_replace($norm, '[' . $LANG24[48] . $i . ']', $body);
$intro = str_replace($left, '[' . $LANG24[48] . $i . '_' . $LANG24[50] . ']', $intro);
$body = str_replace($left, '[' . $LANG24[48] . $i . '_' . $LANG24[50] . ']', $body);
$intro = str_replace($right, '[' . $LANG24[48] . $i . '_' . $LANG24[49] . ']', $intro);
$body = str_replace($right, '[' . $LANG24[48] . $i . '_' . $LANG24[49] . ']', $body);
}

return array($intro, $body);
}

/**
* Replaces simple image syntax with actual HTML in the intro and body.
* If errors occur it will return all errors in $error
*
* @param string $sid ID for story to parse
* @param string $intro Intro text
* @param string $body Body text
* @return string Processed text
*
*/
function insert_images($sid, $intro, $body)
{
global $_CONF, $_TABLES, $LANG24;

$result = DB_query("SELECT ai_filename FROM {$_TABLES['article_images']} WHERE ai_sid = '$sid' ORDER BY ai_img_num");
$nrows = DB_numRows($result);
$errors = array();

for ($i = 1; $i <= $nrows; $i++) {
$A = DB_fetchArray($result);
$dimensions = GetImageSize($_CONF['path_html'] . 'images/articles/' . $A['ai_filename']);
if (!empty($dimensions[0]) AND !empty($dimensions[1])) {
$sizeattributes = 'width="' . $dimensions[0] . '" height="' . $dimensions[1] . '" ';
} else {
$sizeattributes = '';
}

$lLinkPrefix = '';
$lLinkSuffix = '';
if ($_CONF['keep_unscaled_image'] == 1) {
$lFilename_large = substr_replace ($A['ai_filename'], '_original.',
strrpos ($A['ai_filename'], '.'), 1);
$lFilename_large_complete = $_CONF['path_html'] . 'images/articles/'
. $lFilename_large;
$lFilename_large_URL = $_CONF['site_url'] . '/images/articles/'
. $lFilename_large;
if (file_exists ($lFilename_large_complete)) {
$lLinkPrefix = '<a href="' . $lFilename_large_URL
. '" title="' . $LANG24[57] . '">';
$lLinkSuffix = '</a>';
}
}

$norm = '[' . $LANG24[48] . $i . ']';
$left = '[' . $LANG24[48] . $i . '_' . $LANG24[50] . ']';
$right = '[' . $LANG24[48] . $i . '_' . $LANG24[49] . ']';
$fulltext = $intro . ' ' . $body;
$icount = substr_count($fulltext, $norm) + substr_count($fulltext, $left) + substr_count($fulltext, $right);
if ($icount == 0) {
// There is an image that wasn't used, create an error
$errors[] = $LANG24[48] . " #$i, {$A['ai_filename']}, " . $LANG24[53];
} else {
// Only parse if we haven't encountered any error to this point
if (count($errors) == 0) {
$intro = str_replace($norm, $lLinkPrefix . '<img ' . $sizeattributes . 'src="' . $_CONF['site_url'] . '/images/articles/' . $A['ai_filename'] . '" alt="">' . $lLinkSuffix, $intro);
$body = str_replace($norm, $lLinkPrefix . '<img ' . $sizeattributes . 'src="' . $_CONF['site_url'] . '/images/articles/' . $A['ai_filename'] . '" alt="">' . $lLinkSuffix, $body);
$intro = str_replace($left, $lLinkPrefix . '<img ' . $sizeattributes . 'align="left" src="' . $_CONF['site_url'] . '/images/articles/' . $A['ai_filename'] . '" alt="">' . $lLinkSuffix, $intro);
$body = str_replace($left, $lLinkPrefix . '<img ' . $sizeattributes . 'align="left" src="' . $_CONF['site_url'] . '/images/articles/' . $A['ai_filename'] . '" alt="">' . $lLinkSuffix, $body);
$intro = str_replace($right, $lLinkPrefix . '<img ' . $sizeattributes . 'align="right" src="' . $_CONF['site_url'] . '/images/articles/' . $A['ai_filename'] . '" alt="">' . $lLinkSuffix, $intro);
$body = str_replace($right, $lLinkPrefix . '<img ' . $sizeattributes . 'align="right" src="' . $_CONF['site_url'] . '/images/articles/' . $A['ai_filename'] . '" alt="">' . $lLinkSuffix, $body);
}
}
}

return array($errors, $intro, $body);
}

/**
* Saves story to database
*
* @param string $type story submission or (new) story
* @param string $sid ID of story to save
* @param int $uid ID of user that wrote the story
* @param string $tid Topic ID story belongs to
* @param string $title Title of story
* @param string $introtext Introduction text
* @param string $bodytext Text of body
* @param int $hits Number of times story has been viewed
* @param string $unixdate Date story was originally saved
* @param int $comments Number of user comments made to this story
* @param int $featured Flag on whether or not this is a featured article
* @param string $commentcode Indicates if comments are allowed to be made to article
* @param string $statuscode Status of the story
* @param string $postmode Is this HTML or plain text?
* @param string $frontpage Flag indicates if story will appear on front page and topic or just topic
* @param int $draft_flag Flag indicates if story is a draft or not
* @param int $numemails Number of times this story has been emailed to someone
* @param int $owner_id ID of owner (not necessarily the author)
* @param int $group_id ID of group story belongs to
* @param int $perm_owner Permissions the owner has on story
* @param int $perm_group Permissions the group has on story
* @param int $perm_member Permissions members have on story
* @param int $perm_anon Permissions anonymous users have on story
* @param int $delete String array of attached images to delete from article
*
*/
function submitstory($type='',$sid,$uid,$tid,$title,$introtext,$bodytext,$hits,$unixdate,$comments,$featured,$commentcode,$statuscode,$postmode,$frontpage,$draft_flag,$numemails,$owner_id,$group_id,$perm_owner,$perm_group,$perm_members,$perm_anon,$delete,$show_topic_icon)
{
global $_TABLES, $_CONF, $_USER, $LANG24, $MESSAGE, $HTTP_POST_FILES;

// Convert array values to numeric permission values
list($perm_owner,$perm_group,$perm_members,$perm_anon) = SEC_getPermissionValues($perm_owner,$perm_group,$perm_members,$perm_anon);

$access = 0;
if (DB_count ($_TABLES['stories'], 'sid', $sid) > 0) {
$result = DB_query ("SELECT owner_id,group_id,perm_owner,perm_group,perm_members,perm_anon FROM {$_TABLES['stories']} WHERE sid = '{$sid}'");
$A = DB_fetchArray ($result);
$access = SEC_hasAccess ($A['owner_id'], $A['group_id'],
$A['perm_owner'], $A['perm_group'], $A['perm_members'],
$A['perm_anon']);
} else {
$access = SEC_hasAccess ($owner_id, $group_id, $perm_owner, $perm_group,
$perm_members, $perm_anon);
}
if (($access < 3) || (SEC_hasTopicAccess ($tid) < 2) || !SEC_inGroup ($group_id)) {
$display .= COM_siteHeader ('menu');
$display .= COM_startBlock ($MESSAGE[30], '',
COM_getBlockTemplate ('_msg_block', 'header'));
$display .= $MESSAGE[31];
$display .= COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'));
$display .= COM_siteFooter ();
COM_errorLog("User {$_USER['username']} tried to illegally submit or edit story $sid",1);
echo $display;
exit;
} elseif (!empty($title) && !empty($introtext)) {
$date = date("Y-m-d H:i:s",$unixdate);

if (empty($hits)) {
$hits = 0;
}

// Get draft flag value
if ($draft_flag == 'on') {
$draft_flag = 1;
} else {
$draft_flag = 0;

// OK, if this story was already in the database and the user
// changed this from a draft to an actual story then update the
// date to be now
if (DB_count($_TABLES['stories'],'sid',$sid) == 1) {
if (DB_getItem($_TABLES['stories'],'draft_flag',"sid = '$sid'") == 1) {
$unixdate = time();
}
}
}

if ($featured == '1') {
// there can only be one non-draft featured story
if ($draft_flag == 0 AND $unixdate <= time()) {
$id[1] = 'featured';
$values[1] = 1;
$id[2] = 'draft_flag';
$values[2] = 0;
DB_change($_TABLES['stories'],'featured','0',$id,$values);
}

// if set to featured force to show on front page
$frontpage = 1;
}

if (empty($numemails)) {
$numemails = 0;
}

if ($show_topic_icon == 'on') {
$show_topic_icon = 1;
} else {
$show_topic_icon = 0;
}

// Get the related URLs
$related = addslashes (COM_whatsRelated ("$introtext $bodytext", $uid, $tid));

// Clean up the text
if ($postmode == "html") {
$introtext = addslashes(COM_checkHTML(COM_checkWords($introtext)));
$bodytext = addslashes(COM_checkHTML(COM_checkWords($bodytext)));
} else {
$introtext = addslashes(htmlspecialchars(COM_checkWords($introtext)));
$bodytext = addslashes(htmlspecialchars(COM_checkWords($bodytext)));
}
$title = addslashes(htmlspecialchars(strip_tags(COM_checkWords($title))));
$comments = DB_count($_TABLES['comments'],'sid',$sid);

// Delete any images if needed
for ($i = 1; $i <= count($delete); $i++) {
$ai_filename = DB_getItem ($_TABLES['article_images'],'ai_filename', "ai_sid = '$sid' AND ai_img_num = " . key ($delete));
$curfile = $_CONF['path_html'] . 'images/articles/' . $ai_filename;
if (!@unlink($curfile)) {
echo COM_errorLog("Unable to delete image $curfile. Please check file permissions");
}

// remove unscaled image, if it exists
$lFilename_large = substr_replace ($ai_filename, '_original.',
strrpos ($ai_filename, '.'), 1);
$lFilename_large_complete = $_CONF['path_html'] . 'images/articles/'
. $lFilename_large;
if (file_exists ($lFilename_large_complete)) {
if (!@unlink ($lFilename_large_complete)) {
echo COM_errorLog ('Unable to remove the following image from the article: ' . $lFilename_large_complete);
}
}

DB_query("DELETE FROM {$_TABLES['article_images']} WHERE ai_sid = '$sid' AND ai_img_num = " . key($delete));
next($delete);
}

// OK, let's upload any pictures with the article
if (DB_count($_TABLES['article_images'], 'ai_sid', $sid) > 0) {
$index_start = DB_getItem($_TABLES['article_images'],'max(ai_img_num)',"ai_sid = '$sid'") + 1;
} else {
$index_start = 1;
}

if (count($HTTP_POST_FILES) > 0 AND $_CONF['maximagesperarticle'] > 0) {
require_once($_CONF['path_system'] . 'classes/upload.class.php');
$upload = new upload();

$upload->setDebug(true);
$upload->setMaxFileUploads ($_CONF['maximagesperarticle']);
if (!empty($_CONF['image_lib'])) {
if ($_CONF['image_lib'] == 'imagemagick') {
// Using imagemagick
$upload->setMogrifyPath ($_CONF['path_to_mogrify']);
} elseif ($_CONF['image_lib'] == 'netpbm') {
// using netPBM
$upload->setNetPBM ($_CONF['path_to_netpbm']);
} elseif ($_CONF['image_lib'] == 'gdlib') {
// using the GD library
$upload->setGDLib ();
}
$upload->setAutomaticResize(true);
if (isset ($_CONF['debug_image_upload']) && $_CONF['debug_image_upload']) {
$upload->setLogFile ($_CONF['path'] . 'logs/error.log');
$upload->setDebug (true);
}
if ($_CONF['keep_unscaled_image'] == 1) {
$upload->keepOriginalImage (true);
} else {
$upload->keepOriginalImage (false);
}
}
$upload->setAllowedMimeTypes(array('image/gif'=>'.gif','image/jpeg'=>'.jpg,.jpeg','image/pjpeg'=>'.jpg,.jpeg','image/x-png'=>'.png','image/png'=>'.png'));
if (!$upload->setPath($_CONF['path_html'] . 'images/articles')) {
print 'File Upload Errors:<br>' . $upload->printErrors();
exit;
}

// NOTE: if $_CONF['path_to_mogrify'] is set, the call below will
// force any images bigger than the passed dimensions to be resized.
// If mogrify is not set, any images larger than these dimensions
// will get validation errors
$upload->setMaxDimensions($_CONF['max_image_width'], $_CONF['max_image_height']);
$upload->setMaxFileSize($_CONF['max_image_size']); // size in bytes, 1048576 = 1MB

// Set file permissions on file after it gets uploaded (number is in octal)
$upload->setPerms('0644');
$filenames = array();
$end_index = $index_start + $upload->numFiles() - 1;
for ($z = $index_start; $z <= $end_index; $z++) {
$curfile = current($HTTP_POST_FILES);
if (!empty($curfile['name'])) {
$pos = strrpos($curfile['name'],'.') + 1;
$fextension = substr($curfile['name'], $pos);
$filenames[] = $sid . '_' . $z . '.' . $fextension;
}
next($HTTP_POST_FILES);
}
$upload->setFileNames($filenames);
reset($HTTP_POST_FILES);
$upload->setDebug(true);
$upload->uploadFiles();

if ($upload->areErrors()) {
$retval = COM_siteHeader('menu');
$retval .= COM_startBlock ($LANG24[30], '',
COM_getBlockTemplate ('_msg_block', 'header'));
$retval .= $upload->printErrors(false);
$retval .= COM_endBlock(COM_getBlockTemplate ('_msg_block', 'footer'));
$retval .= COM_siteFooter('true');
echo $retval;
exit;
}

reset($filenames);
for ($z = $index_start; $z <= $end_index; $z++) {
DB_query("INSERT INTO {$_TABLES['article_images']} (ai_sid, ai_img_num, ai_filename) VALUES ('$sid', $z, '" . current($filenames) . "')");
next($filenames);
}
}

if ($_CONF['maximagesperarticle'] > 0) {
list($errors, $introtext, $bodytext) = insert_images($sid, $introtext, $bodytext);
if (count($errors) > 0) {
$display = COM_siteHeader ('menu');
$display .= COM_startBlock ($LANG24[54], '',
COM_getBlockTemplate ('_msg_block', 'header'));
$display .= $LANG24[55] . '<p>';
for ($i = 1; $i <= count($errors); $i++) {
$display .= current($errors) . '<br>';
next($errors);
}
$display .= COM_endBlock (COM_getBlockTemplate ('_msg_block', 'footer'));
$display .= storyeditor($sid);
$display .= COM_siteFooter();
echo $display;
exit;
}
}

if ($type == 'submission') {
$return_to = $_CONF['site_admin_url'] . '/moderation.php?msg=9';
} else {
$return_to = $_CONF['site_admin_url'] . '/story.php?msg=9';
}
DB_save($_TABLES['stories'],'sid,uid,tid,title,introtext,bodytext,hits,date,comments,related,featured,commentcode,statuscode,postmode,frontpage,draft_flag,numemails,owner_id,group_id,perm_owner,perm_group,perm_members,perm_anon,show_topic_icon',"$sid,$uid,'$tid','$title','$introtext','$bodytext',$hits,'$date','$comments','$related',$featured,'$commentcode','$statuscode','$postmode','$frontpage',$draft_flag,$numemails,$owner_id,$group_id,$perm_owner,$perm_group,$perm_members,$perm_anon,$show_topic_icon", $return_to);

// If this is done as part of the moderation then delete the submission
if ($type == 'submission') {
DB_delete($_TABLES['storysubmission'],'sid',$sid);
}
COM_rdfUpToDateCheck ();
COM_olderStuff ();
} else {
$display .= COM_siteHeader('menu');
$display .= COM_errorLog($LANG24[31],2);
$display .= storyeditor($sid);
$display .= COM_siteFooter();
echo $display;
exit;
}
}

/**
* Delete a story from the database.
*
* @param string $sid id of story to delete
* @return string HTML for a redirect to admin/story.php
*
*/
function deletestory ($sid)
{
global $_TABLES, $_CONF;

$result = DB_query ("SELECT ai_filename FROM {$_TABLES['article_images']} WHERE ai_sid = '$sid'");
$nrows = DB_numRows ($result);
for ($i = 1; $i <= $nrows; $i++) {
$A = DB_fetchArray ($result);
$filename = $_CONF['path_html'] . 'images/articles/' . $A['ai_filename'];
if (!@unlink ($filename)) {
// log the problem but don't abort the script
echo COM_errorLog ('Unable to remove the following image from the article: ' . $filename);
}

// remove unscaled image, if it exists
$lFilename_large = substr_replace ($A['ai_filename'], '_original.',
strrpos ($A['ai_filename'], '.'), 1);
$lFilename_large_complete = $_CONF['path_html'] . 'images/articles/'
. $lFilename_large;
if (file_exists ($lFilename_large_complete)) {
if (!@unlink ($lFilename_large_complete)) {
// again, log the problem but don't abort the script
echo COM_errorLog ('Unable to remove the following image from the article: ' . $lFilename_large_complete);
}
}
}
DB_delete ($_TABLES['article_images'], 'ai_sid', $sid);
DB_delete ($_TABLES['comments'], 'sid', $sid);
DB_delete ($_TABLES['stories'], 'sid', $sid);

// update RSS feed and Older Stories block
COM_rdfUpToDateCheck ();
COM_olderStuff ();

return COM_refresh ($_CONF['site_admin_url'] . '/story.php?msg=10');
}

// MAIN

$display = '';
if (($mode == $LANG24[11]) && !empty ($LANG24[11])) { // delete
if (!isset ($sid) || empty ($sid) || ($sid == 0)) {
COM_errorLog ('Attempted to delete story sid=' . $sid);
echo COM_refresh ($_CONF['site_admin_url'] . '/story.php');
} else if ($type == 'submission') {
DB_delete ($_TABLES['storysubmission'], 'sid', $sid,
$_CONF['site_admin_url'] . '/moderation.php');
} else {
echo deletestory ($sid);
}
} else if (($mode == $LANG24[9]) && !empty ($LANG24[9])) { // preview
$display .= COM_siteHeader('menu');
$display .= storyeditor($sid,$mode);
$display .= COM_siteFooter();
echo $display;
} else if ($mode == 'edit') {
$display .= COM_siteHeader('menu');
$display .= storyeditor($sid,$mode);
$display .= COM_siteFooter();
echo $display;
} else if ($mode == 'editsubmission') {
$display .= COM_siteHeader('menu');
$display .= storyeditor($id,$mode);
$display .= COM_siteFooter();
echo $display;
} else if (($mode == $LANG24[8]) && !empty ($LANG24[8])) { // save
if ($publish_ampm == 'pm') {
if ($publish_hour < 12) {
$publish_hour = $publish_hour + 12;
}
}
if ($publish_ampm == 'am' AND $publish_hour == 12) {
$publish_hour = '00';
}
$unixdate = strtotime("$publish_month/$publish_day/$publish_year $publish_hour:$publish_minute:$publish_second");
submitstory($type,$sid,$uid,$tid,$title,$introtext,$bodytext,$hits,$unixdate,$comments,$featured,$commentcode,$statuscode,$postmode,$frontpage, $draft_flag,$numemails,$owner_id,$group_id,$perm_owner,$perm_group,$perm_members,$perm_anon,$delete,$show_topic_icon);
} else { // 'cancel' or no mode at all
if (($mode == $LANG24[10]) && !empty ($LANG24[10]) &&
($type == 'submission')) {
$display .= COM_refresh ($_CONF['site_admin_url'] . '/moderation.php');
} else {
$display .= COM_siteHeader('menu');
$display .= COM_showMessage($msg);
$display .= liststories($page);
$display .= COM_siteFooter();
}
echo $display;
}

?>

--------------060409070102020704010509--



--__--__--

_______________________________________________
geeklog-devel mailing list
geeklog-devel at lists.geeklog.net
http://lists.geeklog.net/listinfo/geeklog-devel


End of geeklog-devel Digest



More information about the geeklog-devtalk mailing list