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

geeklog-devel-request at lists.geeklog.net geeklog-devel-request at lists.geeklog.net
Wed Dec 3 20:08:06 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. Re: Spelling interface ready for testing... (Blaine Lang)

--__--__--

Message: 1
From: "Blaine Lang" <geeklog at langfamily.ca>
To: <geeklog-devel at lists.geeklog.net>
Subject: Re: [geeklog-devel] Spelling interface ready for testing...
Date: Wed, 3 Dec 2003 20:08:07 -0500
Reply-To: geeklog-devel at lists.geeklog.net

This is a multi-part message in MIME format.

------=_NextPart_000_00FB_01C3B9D9.2DCB0EF0
Content-Type: text/plain;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

This is great Tony .. I tried it out.
Windows XP

I was not sure if I would see it when in story editor creating a story. =
I saw it highlight my test bad words after I posted it and tried to edit =
it.
No indication before that.

Now this was just a quick initial test. I entered this for my test:
thi is a tst
helo dos this worke

It highligted the "is" on the first line and the "is in "this" on the =
second line. These are the only correct words ;)

I took the same test and dropped it into the ispell executable and it =
caught all the miss-spelled words.


I installed the English dictionary as well.

Blaine

----- Original Message -----=20

From: Tony Bibbs=20
To: Geeklog=20
Sent: Tuesday, December 02, 2003 12:01 AM
Subject: [geeklog-devel] Spelling interface ready for testing...


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=20
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=20
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=20
version used the native PHP functions (pspell) which is a PITA to get=20
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=20
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=20
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=20
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=20
PHPSpellChecker.class.php into the /path/to/geeklog/system/classes/=20
directory.

Questions welcomed and, of course, more testers welcome. PHPDoc file=20
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 =

|=20


=
+-------------------+--------------------------------------------------+



-------------------------------------------------------------------------=
-----


* @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: * * =
setPathToAspellBinary('/usr/bin/aspell'); * =
$spellChecker->setTempDir('C:/Windows/Temp'); * echo =
$spellChecker->checkWords('This is a test, I srue hope therre are no =
mispelings'); * ?> * * * @author Tony Bibbs * */ 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 =3D 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 =3D 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 =3D 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 =3D 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 =3D 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 =3D =
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 =3D 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 =3D 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[] =3D '' * * @see checkWords() * @var array * @access private * =
*/ var $_misspellings =3D null; /** * Holds suggestions for misspelled =
words * * This array holds the suggested spellings for all misspelled =
words. The format of this * array is $myArray[] =3D ',' * * @see =
checkWords() * @var array * @access private * */ var $_suggestions =3D =
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 =3D 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 =3D 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 =3D 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 * @access public * @param array $aspellOptions Options for =
aspell in formate myArray['aspellOption'] =3D> 'aspellValue' * */ =
function PHPSpellChecker($aspellOptions =3D '') { // 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) =3D=3D 'WIN') { $this->_operatingSystem =3D =
SPELL_OS_WINDOWS; } else { $this->_operatingSystem =3D SPELL_OS_POSIX; } =
if (empty($aspellOptions)) { $this->_aspellOptions =3D array(); } else { =
$this->_aspellOptions =3D $aspellOptions; } $this->_misspellings =3D =
array(); $this->_suggestings =3D array(); $this->_positions =3D array(); =
$this->setLanguage(); $this->setMinimumWordLimit(); =
$this->setHighlight('',''); } /** * 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 * @access =
public * @param string $languageCode Code of language to use * */ =
function setLanguage($languageCode =3D 'en_US') { $this->_languageCode =
=3D $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 * @access public * @param string $absolutePath Path =
to the temporary directory * */ function setTempDir($absolutePath =3D =
'') { $this->_tempDir =3D $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 * @access =
public * @param string $absoluteFileName Location of aspell binary * */ =
function setPathToApsellBinary($absoluteFileName) { =
$this->_pathToAspellBinary =3D $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 * @access public * @param int $minWordLength Minimum =
length of a word * */ function setMinimumWordlimit($minWordLength =3D 3) =
{ $this->_skipLength =3D $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 =
* @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 * @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 * @access private * @return boolean True if =
successful otherwise false * */ function _createTempFile() { =
$this->_tempFile =3D tempnam($this->_tempDir, 'textToCheck'); if =
($this->_tempFile =3D=3D false) { trigger_error('Unable to write the =
temporary file.'); } else { if (!empty($this->_origText)) { if ($fd =3D =
fopen($this->_tempFile,'w')) { // Chop it up by line. $textarray =3D =
explode("\n",$this->_origText); fwrite($fd,"!\n"); foreach ($textarray =
as $key=3D>$value) { $value =3D 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 * @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 * @access private * =
@param string $aspellReturn Return output from aspell * */ function =
_parseReturn($aspellReturn) { //next parse $return and $text line by =
line, eh? $returnarray =3D explode("\n",$aspellReturn); $returnlines =3D =
count($returnarray); $textarray =3D explode("\n",$this->text); =
$lineindex =3D -1; $poscorrect =3D 0; $counter =3D 0; =
foreach($returnarray as $line) { $correction =3D explode(' ',$line); =
$word =3D $correction[1]; // If there is a correction here, processes =
it, else move the $textarray pointer to the next line if =
(substr($line,0,1) =3D=3D '&') { // Build the position, comma separated. =
Line, character $absposition =3D substr($correction[3],0,-1)-1; =
$position =3D $absposition + $poscorrect; $niceposition =3D $lineindex . =
"," . $absposition; // Start building the suggestion list $suggstart =3D =
strpos($line,":")+2; $suggestions =3D substr($line,$suggstart); =
$suggestionarray =3D explode(', ',$suggestions); // Set an array for the =
suggestions. $suggestions =3D array(); foreach ($suggestionarray as =
$aSuggestion) { $suggestions[] =3D $aSuggestion; } } else { if =
(substr($line,0,1) =3D=3D '#') { // Find the position. $absposition =3D =
$correction[2] - 1; $position =3D $absposition + $poscorrect; =
$niceposition =3D $lineindex .",". $absposition; // Add this word to the =
arrays. $thePositions[] =3D array($word =3D> $niceposition); =
$theSuggestions[] =3D array($word =3D> 'No Suggestions.'); } else { =
$poscorrect =3D 0; $lineindex =3D $lineindex + 1; } } =
$this->_misspellings[] =3D $word; if (count($suggestions) > 0) { =
$this->_suggestions[$word] =3D 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] =3D '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 * @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 =3D false) { $this->_origText =3D $textString; if =
($this->_createTempFile() !=3D false) { if ($isHTMLEmbedded =3D=3D true) =
{ $addOptions .=3D ' -H'; } if (!empty($this->_dictionary)) { =
$addOptions .=3D ' -d ' . $this->dictionary; } if =
(!empty($this->wordList)) { $addOptions .=3D ' -p ' . $this->wordList; } =
// Grab any other aspell options for ($i =3D 1; $i <=3D =
count($this->_aspellOptions); $i++) { $addOptions .=3D sprintf(' %s %s', =
key($this->_aspellOptions), current($this->_aspellOptions)); =
next($this->_aspellOptions); } reset($this->_aspellOptions); // Calling =
aspell differs slightly by OS if ($this->_operatingSystem =3D=3D =
SPELL_OS_WINDOWS) { $command =3D sprintf('%s -a --lang=3D%s %s < "%s" =
2>&1',$this->_pathToAspellBinary, $this->_languageCode, $addOptions, =
$this->_tempFile); } else { $command =3D sprintf('%s -a --lang=3D%s %s < =
%s',$this->_pathToAspellBinary, $this->_languageCode, $addOptions, =
$this->_tempFile); } // Execute the command. $retValue =3D =
shell_exec($command); // Delete the temporary file created. if =
(unlink($this->_tempFile) =3D=3D 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 * =
@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 =3D $beginHighlight; =
$this->_endHighlight =3D $endHighlight; } /** * Highlights misspelled =
words and returns the text * * @author Tony Bibbs * @access public * =
@return original search text with misspellings highlighted. * */ =
function highlightBadWords() { $tmpString =3D $this->_origText; foreach =
($this->_misspellings AS $curWord) { $tmpBeginHighlight =3D =
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 =3D str_replace($curWord, =
$tmpBeginHighlight . $curWord . $this->_endHighlight, $tmpString); } =
return $tmpString; } } ?>


-------------------------------------------------------------------------=
-----


'mail', // can be one of 'mail', 'sendmail', 'smtp' // sendmail =
parameters (for 'backend' =3D> 'sendmail') 'sendmail_path' =3D> =
'/usr/bin/sendmail', 'sendmail_args' =3D> '', // SMTP parameters (for =
'backend' =3D> 'smtp') 'host' =3D> 'smtp.example.com', 'port' =3D> '25', =
'auth' =3D> false, 'username' =3D> 'smtp-username', 'password' =3D> =
'smtp-password' ); // =
+------------------------------------------------------------------------=
---+ // | Email Settings | // | | // | Configure how Geeklog sends =
email: Via PHP's mail() function, sendmail, | // | or via an SMTP =
server. | // =
+------------------------------------------------------------------------=
---+ $_CONF['spelling_enabled'] =3D true; $_CONF['spelling_language'] =
=3D 'en_US'; // Must be fully qualified location of the aspell binary =
$_CONF['path_aspell'] =3D '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'] =3D =
$_CONF['path'] . 'logs'; // =
+------------------------------------------------------------------------=
---+ // | OTHER DATABASE SETTINGS | // | | // | Database type and =
database backup settings. | // =
+------------------------------------------------------------------------=
---+ $_DB_dbms =3D 'mysql'; // Do not change (currently, only MySQL is =
supported) // optional settings for making database backups from within =
Geeklog $_CONF['allow_mysqldump'] =3D 1; // 1 =3D on, 0 =3D off =
$_DB_mysqldump_path =3D '/usr/bin/mysqldump'; // path to mysqldump =
binary $_CONF['mysqldump_options'] =3D '-Q'; // additional options for =
mysqldump // =
+------------------------------------------------------------------------=
---+ // | SITE SETTINGS | // | | // | These settings help define your =
Geeklog site. | // =
+------------------------------------------------------------------------=
---+ $_CONF['theme'] =3D 'XSilver'; // default theme // you shouldn't =
need to edit the following $_CONF['layout_url'] =3D $_CONF['site_url'] . =
'/layout/' . $_CONF['theme']; $_CONF['path_themes'] =3D =
$_CONF['path_html'] . 'layout/'; $_CONF['path_layout'] =3D =
$_CONF['path_themes'] . $_CONF['theme'] .'/'; // optional settings (1 =
=3D on, 0 =3D off) $_CONF['allow_user_themes'] =3D 1; =
$_CONF['allow_user_language'] =3D 1; $_CONF['allow_user_photo'] =3D 1; =
// allow users to upload self-photo // hides the list of authors from =
the preferences $_CONF['hide_author_exclusion'] =3D 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'] =3D false; // Set to true if you have =
custom code // =
+------------------------------------------------------------------------=
---+ // | LOCALE SETTINGS | // =
+------------------------------------------------------------------------=
---+ $_CONF['language'] =3D 'english'; $_CONF['locale'] =3D 'en-gb'; =
$_CONF['date'] =3D '%A, %B %d %Y @ %I:%M %p %Z'; $_CONF['daytime'] =3D =
'%m/%d %I:%M%p'; $_CONF['shortdate'] =3D '%x'; $_CONF['dateonly'] =3D =
'%d-%b'; $_CONF['timeonly'] =3D '%I:%M %p %Z'; $_CONF['default_charset'] =
=3D 'iso-8859-1'; // =
+------------------------------------------------------------------------=
---+ // | SITE STATUS | // | | // | To disable your Geeklog site =
quickly, simply set this flag to false | // =
+------------------------------------------------------------------------=
---+ $_CONF['site_enabled'] =3D 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'] =3D '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'] =3D 'gl_session'; $_CONF['cookie_name'] =
=3D 'geeklog'; $_CONF['cookie_password'] =3D 'password'; =
$_CONF['cookie_theme'] =3D 'theme'; $_CONF['cookie_language'] =3D =
'language'; $_CONF['cookie_lastvisit'] =3D 'LastVisit'; =
$_CONF['cookie_lastvisittemp'] =3D 'LastVisitTemp'; $_CONF['cookie_ip'] =
=3D 0; $_CONF['default_perm_cookie_timeout'] =3D 604800; =
$_CONF['session_cookie_timeout'] =3D 7200; $_CONF['cookie_path'] =3D =
'/'; $_CONF['cookiedomain'] =3D ''; // e.g. '.example.com' =
$_CONF['cookiesecure'] =3D 0; // Set to false if you don't want to store =
last login data and time in the userinfo table $_CONF['lastlogin'] =3D =
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'] =3D 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 =3D =
show title with summary // false =3D title date author hits on one line =
$_CONF['expanded_search_results'] =3D true; // 0: use users max stories =
per page // 1: Show all // any other number is the # of results per page =
$_CONF['max_search_results'] =3D 1; // maximum length for the summary =
text for search results should be $_CONF['summary_length'] =3D 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'] =3D 0; // all of them, if =
set to 1 will override all else $_CONF['submitloginrequired'] =3D 0; =
$_CONF['commentsloginrequired'] =3D 0; $_CONF['linksloginrequired'] =3D =
0; $_CONF['pollsloginrequired'] =3D 0; $_CONF['calendarloginrequired'] =
=3D 0; $_CONF['statsloginrequired'] =3D 0; $_CONF['searchloginrequired'] =
=3D 0; $_CONF['profileloginrequired'] =3D 0; =
$_CONF['emailuserloginrequired'] =3D 0; =
$_CONF['emailstoryloginrequired'] =3D 0; // Submission Settings // =
enable (set to 1) or disable (set to 0) submission queues: =
$_CONF['storysubmission'] =3D 1; $_CONF['linksubmission'] =3D 1; =
$_CONF['eventsubmission'] =3D 1; $_CONF['usersubmission'] =3D 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'] =3D 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'] =3D array ('story', 'link', 'event'); // The =
email will be sent to $_CONF['site_mail'] (see above). =
$_CONF['notification'] =3D array (); $_CONF['postmode'] =3D 'plaintext'; =
// can be 'plaintext' or 'html' $_CONF['speedlimit'] =3D 45; // in =
seconds $_CONF['skip_preview'] =3D 0; // If =3D 1, allow user to submit =
comments and stories without previewing // Allow users to change their =
username (if set to 1). $_CONF['allow_username_change'] =3D 0; // Allow =
users to delete their account (if set to 1). =
$_CONF['allow_account_delete'] =3D 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'] =3D 'sortnum'; // or 'alpha' // =
Show the number of stories in a topic in Topics Block =
$_CONF['showstorycount'] =3D 1; // Show the number of story submissions =
for a topic in Topics Block $_CONF['showsubmissioncount'] =3D 1; // Hide =
'Home' link from Topics block (if set to 1) $_CONF['hide_home_link'] =3D =
0; // Show blocks for empty search results =
$_CONF['showemptysearchresults'] =3D 0; // How long an anonymous (guest) =
user session is good for $_CONF['whosonline_threshold'] =3D 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'] =3D 0; // Specify length of stories in those =
emails: // 0 =3D send only title + link, 1 =3D send entire introtext, // =
any other number =3D max. number of characters per story =
$_CONF['emailstorieslength'] =3D 1; // New users get stories emailed to =
them per default (=3D 1) or not (=3D 0) $_CONF['emailstoriesperdefault'] =
=3D 0; // When user submission is activated, allow users from these =
domains to // register without having to go through the submission =
queue. $_CONF['allow_domains'] =3D ''; // e.g. =
'mycompany.com,myothercompany.com' // Following times are in seconds =
$_CONF['newstoriesinterval'] =3D 86400; // =3D 24 hours =
$_CONF['newcommentsinterval'] =3D 172800; // =3D 48 hours =
$_CONF['newlinksinterval'] =3D 1209600; // =3D 14 days // Set to 1 to =
hide a section from the What's New block: $_CONF['hidenewstories'] =3D =
0; $_CONF['hidenewcomments'] =3D 0; $_CONF['hidenewlinks'] =3D 0; // =
Calendar Settings $_CONF['personalcalendars'] =3D 1; =
$_CONF['showupcomingevents'] =3D 1; $_CONF['upcomingeventsrange'] =3D =
14; // days $_CONF['event_types'] =3D =
'Anniversary,Appointment,Birthday,Business,Education,Holiday,Meeting,Misc=
ellaneous,Personal,Phone Call,Special Occasion,Travel,Vacation'; // =
Story Settings $_CONF['maximagesperarticle'] =3D 5; $_CONF['limitnews'] =
=3D 10; $_CONF['minnews'] =3D 1; // minimum number of stories per page =
$_CONF['contributedbyline'] =3D 1; // If 1, show contributed by line =
$_CONF['article_image_align'] =3D 'right'; // Topic icon on left or =
right. $_CONF['hideemailicon'] =3D 0; // If 1, hide "email story" option =
$_CONF['hideprintericon'] =3D 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'] =3D 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'] =3D 1; // 1 =3D activate feeds, 0 =3D off // path =
to your site's default RSS feed $_CONF['rdf_file'] =3D =
$_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'] =3D 10; // number =
of stories (10) or hours (24h) // Include the story's entire intro text =
in the feed (=3D 1) or limit the number // of characters from the intro =
text (any number > 1) or don't include the text // at all (=3D 0). =
$_CONF['rdf_storytext'] =3D 0; // Default language for the feed - may =
have to be different than the locale $_CONF['rdf_language'] =3D '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'] =3D '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'] =3D ''; // 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'] =3D =
'/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'] =3D =
'/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'] =3D 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'] =
=3D 0; // 1 =3D keep original images // Story image settings =
$_CONF['max_image_width'] =3D 300; // In pixels =
$_CONF['max_image_height'] =3D 300; // In pixels =
$_CONF['max_image_size'] =3D 1048576; // 1048576 =3D 1MB // User photo =
settings $_CONF['max_photo_width'] =3D 96; // In pixels =
$_CONF['max_photo_height'] =3D 96; // In pixels $_CONF['max_photo_size'] =
=3D 65536; // 65536 =3D 64KB // Comment Settings =
$_CONF['commentspeedlimit'] =3D 45; $_CONF['comment_limit'] =3D 100; // =
Default Number of Comments under Story $_CONF['comment_mode'] =3D =
'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'] =3D 0; // 0 =3D comments enabled, -1 =3D disabled =
// Poll Settings $_CONF['maxanswers'] =3D 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'] =3D =
'submitorder'; $_CONF['pollcookietime'] =3D 86400; =
$_CONF['polladdresstime'] =3D 604800; // Password setting: minimum time =
between two requests for a new password $_CONF['passwordspeedlimit'] =3D =
300; // seconds =3D 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'] =3D 3; // =
categories per column $_CONF['linksperpage'] =3D 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: =20

------=_NextPart_000_00FB_01C3B9D9.2DCB0EF0
Content-Type: text/html;
charset="iso-8859-1"
Content-Transfer-Encoding: quoted-printable

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML><HEAD>
<META http-equiv=3DContent-Type content=3D"text/html; =
charset=3Diso-8859-1">
<META content=3D"MSHTML 6.00.2734.1600" name=3DGENERATOR>
<STYLE></STYLE>
</HEAD>
<BODY bgColor=3D#ffffff>
<DIV><FONT face=3DArial size=3D2>This is great Tony .. I tried it =
out.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>Windows XP</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>I was not sure if I would see it when =
in story=20
editor creating a story. I saw it highlight my test bad words after I =
posted it=20
and tried to edit it.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>No indication before that.</FONT></DIV>
<DIV><FONT face=3DArial size=3D2></FONT>&nbsp;</DIV>
<DIV><FONT face=3DArial size=3D2>Now this was just a quick initial test. =
I entered=20
this for my test:</FONT></DIV>
<DIV><FONT face=3DArial size=3D2>
<P><A =
href=3D"http://localhost/geek138_3/index.php?topic=3DGeekLog"></A>thi =
<SPAN=20
title=3D"No suggestions" style=3D"BACKGROUND-COLOR: #fdd905" ;>is</SPAN> =
a=20
tst<BR>helo dos th<SPAN title=3D"No suggestions" =
style=3D"BACKGROUND-COLOR: #fdd905"=20
;><SPAN title=3D"No suggestions" style=3D"BACKGROUND-COLOR: #fdd905"=20
;>is</SPAN></SPAN> worke</P>
<P>It highligted the "is" on the first line and the "is in "this" on the =
second=20
line. These are the only correct words ;)</P>
<P>I took the same test and dropped it into the ispell executable and it =
caught=20
all the miss-spelled words.</P>
<P><BR>I installed the English dictionary as well.</P>
<P>Blaine</P>
<P></FONT>----- Original Message ----- </P></DIV>
<BLOCKQUOTE=20
style=3D"PADDING-RIGHT: 0px; PADDING-LEFT: 5px; MARGIN-LEFT: 5px; =
BORDER-LEFT: #000000 2px solid; MARGIN-RIGHT: 0px">
<DIV=20
style=3D"BACKGROUND: #e4e4e4; FONT: 10pt arial; font-color: =
black"><B>From:</B>=20
<A title=3Dtony at tonybibbs.com href=3D"mailto:tony at tonybibbs.com">Tony =
Bibbs</A>=20
</DIV>
<DIV style=3D"FONT: 10pt arial"><B>To:</B> <A=20
title=3Dgeeklog-devel at lists.geeklog.net=20
href=3D"mailto:geeklog-devel at lists.geeklog.net">Geeklog</A> </DIV>
<DIV style=3D"FONT: 10pt arial"><B>Sent:</B> Tuesday, December 02, =
2003 12:01=20
AM</DIV>
<DIV style=3D"FONT: 10pt arial"><B>Subject:</B> [geeklog-devel] =
Spelling=20
interface ready for testing...</DIV>
<DIV><BR></DIV>I have finally completed the spellchecker code I am =
planning to=20
use in <BR>Geeklog 2.&nbsp; As you might guess, there is nothing =
precluding it=20
from <BR>being used in 1.3.x so I am attaching the file along with the =

modified <BR>CVS files needed to get this working on=20
admin/story.php.<BR><BR>Dirk, if you could test it's use on another =
language=20
that would be <BR>great.&nbsp; I have already tested this on =
windows.&nbsp; If=20
you tested an alpha <BR>of what I had a few months ago, this is *much* =
easier=20
to use.&nbsp; My prior <BR>version used the native PHP functions =
(pspell)=20
which is a PITA to get <BR>working both on *nix and windows.&nbsp; =
This=20
version simply needs a working <BR>aspel binary which is called using=20
shell_exec().<BR><BR>For those needing more info here is what we=20
have:<BR><BR>1) Uses only the Aspell binary (http://aspell.net)<BR>2) =
Capable=20
of supporting multiple languages<BR>3) Able to highlight misspelled=20
words.&nbsp; By default it uses a set of span <BR>tags and the title =
attribute=20
gets the suggested spellings put into it. <BR>This allows you to see =
the=20
suggestions by hovering over it with your mouse<BR>4) I modified the =
config=20
file to have a new set of entries for spell <BR>checking.&nbsp; By =
default I=20
think we'd turn this feature off, no?<BR>5) Works regardless of the =
postmode=20
of the article<BR>6) I have implemented with little effort for=20
admin/story.php, I would <BR>think one could update all possible areas =
of use=20
in just a few hours<BR><BR>Oh, before I forget, to use the attached =
files, be=20
sure to put <BR>PHPSpellChecker.class.php into the=20
/path/to/geeklog/system/classes/ <BR>directory.<BR><BR>Questions =
welcomed and,=20
of course, more testers welcome.&nbsp; PHPDoc file <BR>forthcoming (I =
don't=20
have PHPDoc installed here at=20
=
home).<BR><BR>--Tony<BR><BR>+-------------------+------------------------=
--------------------------+<BR>|Tony=20
Bibbs&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; |[R]egardless of =
what=20
you may think of our penal&nbsp;&nbsp; |<BR>|tony at tonybibbs.com =

|system, the=20

fact is that every man in jail is one=20
=

|<BR>|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&=

nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=20
|less potential fisherman to clutter up=20
your&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=20
=

|<BR>|&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&=

nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=20
|favorite pool or pond. --Ed=20
=
Zern&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nb=
sp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;=20
|=20
=
<BR><BR>+-------------------+--------------------------------------------=
------+<BR>
<P>
<HR>

<P></P><?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 *=20
@package net.geeklog.utilities * @version $Id:$ * @todo Need to test =
the=20
personal dictionary stuff. Haven't even tried to yet. * */ /** * Used =
to=20
indicate the server is a posix-compliant one (e.g. linux/unix) * =
@const=20
SPELL_OS_POSIX */ define('SPELL_OS_POSIX',1); /** * Used to indicate =
the=20
server uses a version of windows (e.g. 98/XP) * @const SPELL_OS_POSIX =
*/=20
define('SPELL_OS_WINDOWS',2); /** * PHPSpellCheck, a simple =
spellchecking=20
class * * This class makes it easy to implement spellchecking into =
your PHP=20
applications * with minimal effort. Requirements for this class for =
Posix=20
hosts (Unix/Linux) is * an installed aspell system. On my RedHat 9 =
system=20
aspell was installed by default * which should be the case for most of =
you.=20
For Windows users, you should obtain the * Aspell setup program and =
the=20
corresponding dictionary file as none is installed by * default. =
Aspell for=20
Posix and Windows can be downloaded from @link http://aspell.net * * =
Here is a=20
most basic example of how to use this class: * <CODE>* <?php
* require_once 'PHPSpellChecker.class.php';
* $spellChecker =3D new PHPSpellChecker();
* $spellChecker->setPathToAspellBinary('/usr/bin/aspell'); *=20
$spellChecker-&gt;setTempDir('C:/Windows/Temp'); * echo=20
$spellChecker-&gt;checkWords('This is a test, I srue hope therre are =
no=20
mispelings'); * ?&gt; * </CODE>* * @author Tony Bibbs =
<TONY at GEEKLOG.NET>* */=20
class PHPSpellChecker { /** * Holds OS type that Aspell is installed =
on. * *=20
When calling the Aspell binary we will need to know what OS is being * =
used.=20
This could be potentially used for future enhancements as well. * * =
@see=20
PHPSpellChecker() * @see checkWords() * @var int * @access private * =
*/ var=20
$_operatingSystem =3D null; /** * Holds path to Aspell binary * * This =
holds the=20
fully qualified path to the actual Aspell binary. Please * specifiy =
the path=20
to the executable file, not to a directory. NOTE: windows * users may =
find=20
that aspell is picky about the format of the path. For example, * if =
you have=20
aspell located at C:|Program Files\Aspell\bin\aspell then this value * =
will=20
need to be C:\progra~1\Aspell\bin\aspell * * @see checkWords() * @var =
string *=20
@access private * */ var $_pathToAspellBinary =3D null; /** * Code for =
language=20
to spellcheck against * * As expected, this class can spellcheck =
against a=20
variety of supported languages. NOTE: * you will need to ensure that =
your=20
respective language dictionaries have been installed * otherwise this =
won't=20
work * * @see setLanguage() * @var string * @access private * */ var=20
$_languageCode =3D null; /** * Holds any additional Aspell options =
that aren't=20
supported by this * class with a setter and/or getter method. * * =
Aspell has a=20
number of options available. To support those yet keep this * class =
relatively=20
simple, we implement ways to set the most common attributes * and =
allow you to=20
specify additional options that we can include for you when * the call =
to the=20
Aspell binary is made. Please read the documentation for the * =
constructor as=20
it will explain this better * * @see PHPSpellChecker() * @var array * =
@access=20
private * */ var $_aspellOptions =3D null; /** * This holds the path =
to the=20
dictionary file we should use * * Please specify the absolute path to =
the=20
dictionary file * * @see setPersonalDictionary() * @see checkwords() * =
@var=20
string * @access private * */ var $_pathToPersonalDictionary =3D null; =
/** *=20
This holds the path to teh personal wordlist file we should use * * =
Please=20
specify the absolute path to the word list file * * @see =
setPersonalWordList()=20
* @var string * @access private * */ var $_pathToPersonalWordList =3D =
false; /**=20
* Sets the minimum size of a legitimate word * * Setting this allows=20
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=20
this * * @see checkwords * @var int * @access private * */ var =
$_skipLength =3D=20
null; /** * Name of temp dir * * This class puts the text to spell =
into a=20
temporary file before checking the spelling. This * attribute simply =
gives us=20
a directory where we can create these temporary files (e.g. * /tmp) * =
* @see=20
_createTempFile() * @var string * @access private * */ var $_tempDir =
=3D null;=20
/** * Array of the works that were misspelled * * During the =
spellchecking=20
process we keep track of all mispelled words in this * array. This =
values in=20
this array are used to index into the $_suggestions variable * below. =
Array=20
format is $myArray[<KEY>] =3D '<MISSPELLED word>' * * @see =
checkWords() * @var=20
array * @access private * */ var $_misspellings =3D null; /** * Holds=20
suggestions for misspelled words * * This array holds the suggested =
spellings=20
for all misspelled words. The format of this * array is =
$myArray[<MISSPELLED=20
word>] =3D '<SUGGESTION1>,<SUGGESTION2>' * * @see checkWords() * @var =
array *=20
@access private * */ var $_suggestions =3D null; /** * Holds the =
original text=20
we were to spellcheck against * * This simply holds the original text =
to=20
spellcheck against. It * never gets modified * * @see checkWords() * =
@var=20
string * @access private * */ var $_origText =3D null; /** * Formating =
to use to=20
begin highlighting a misspelled word * * The format string is pretty =
basic, by=20
default we use a div tag * that allows the mispellings to be show by =
using the=20
title attribute. * Doing so will show suggestions by simply hovering =
over the=20
mispelled words. * If you want to use a similar format, be sure to use =
the=20
special tag {suggested} * which will get automatically parsed. * * =
@see=20
PHPSpellChecker(); * @see checkWords(); * @see setHighlight(); * @var =
string *=20
@access private * */ var $_beginHighlight =3D null; /** * Formatting =
to use to=20
end highlighting a misspelled word * * This is similar to =
$_beginHighlight=20
above. This simply ends the highlight * * @see PHPSpellChecker(); * =
@see=20
checkWords(); * @see setHighlight(); * @var string * @access private * =
*/ var=20
$_endHighlight =3D null; /** * Constructor * * Constructor, does the =
necessary=20
pspell initialization. When setting aspell options, be sure * to use =
the=20
option names as shown by calling aspell with no options from your unix =
or dos=20
shell. * note that some of the aspell options can be overridden by =
some of the=20
methods in this class. Those * methods are: * - setMinimumWordList(), =
since=20
this is explicitly called in the constructor it will effectively =
ignore *=20
anything you put for aspell's -W or --ignore options * -=20
setPersonalWordList(), this isn't called explicitly so you can use the =

-p,--personal options or call * that function instead. * - * * @author =
Tony=20
Bibbs <TONY at GEEKLOG.NET>* @access public * @param array $aspellOptions =
Options=20
for aspell in formate myArray['aspellOption'] =3D&gt; 'aspellValue' * =
*/=20
function PHPSpellChecker($aspellOptions =3D '') { // Right now this is =
only used=20
when determining how to call aspell but I'm // adding this in case =
there are=20
other OS specific differences added in the // future. if =
(substr(PHP_OS, 0, 3)=20
=3D=3D 'WIN') { $this-&gt;_operatingSystem =3D SPELL_OS_WINDOWS; } =
else {=20
$this-&gt;_operatingSystem =3D SPELL_OS_POSIX; } if =
(empty($aspellOptions)) {=20
$this-&gt;_aspellOptions =3D array(); } else { =
$this-&gt;_aspellOptions =3D=20
$aspellOptions; } $this-&gt;_misspellings =3D array(); =
$this-&gt;_suggestings =3D=20
array(); $this-&gt;_positions =3D array(); $this-&gt;setLanguage();=20
$this-&gt;setMinimumWordLimit(); $this-&gt;setHighlight('<SPAN=20
title=3D{suggested} style=3D"BACKGROUND-COLOR: #fdd905" =
;>','</SPAN>'); } /** *=20
Sets the language that should be used. * * Allows applications to set =
the=20
language to spellcheck against. We * assume US English by default * * =
@author=20
Tony Bibbs <TONY at GEEKLOG.NET>* @access public * @param string =
$languageCode=20
Code of language to use * */ function setLanguage($languageCode =3D =
'en_US') {=20
$this-&gt;_languageCode =3D $languageCode; } /** * Sets the temporary =
directory=20
for Aspell to use * * This class pipes the text to check out of a =
temporary=20
file. This * method will set the location where we put those temporary =
files.=20
* * @author Tony Bibbs <TONY at GEEKLOG.NET>* @access public * @param =
string=20
$absolutePath Path to the temporary directory * */ function=20
setTempDir($absolutePath =3D '') { $this-&gt;_tempDir =3D =
$absolutePath; } /** *=20
Sets the location to the Aspell binary * * This sets the path to the =
actual=20
aspell binary. Note that * this must be an absolute path, don't depend =
on your=20
* operating system's path variables. * * @author Tony Bibbs=20
<TONY at GEEKLOG.NET>* @access public * @param string $absoluteFileName =
Location=20
of aspell binary * */ function =
setPathToApsellBinary($absoluteFileName) {=20
$this-&gt;_pathToAspellBinary =3D $absoluteFileName; } /** * Sets the =
minimum=20
size of what a 'word' is defined as. * * Aspell can be configured to =
ignore=20
words below a certain * length and this is facilitate in this class =
using this=20
* method. For example if you set the minimum size to 3 * then any word =
less=20
than 3 characters long. * * @author Tony Bibbs <TONY at GEEKLOG.NET>* =
@access=20
public * @param int $minWordLength Minimum length of a word * */ =
function=20
setMinimumWordlimit($minWordLength =3D 3) { $this-&gt;_skipLength =3D=20
$minWordLength; } /** * Sets the location of the personal dictionary =
to use *=20
* Aspell allows for any number of dictionary files. This can * be =
handy when=20
an application might want each of it's users to * have their own =
dictionary *=20
* @author Tony Bibbs <TONY at GEEKLOG.NET>* @access public * @param =
string=20
$absoluteFileName Exact location of dictionary to use * */ function=20
setPersonalDictionary($absoluteFileName) {=20
$this-&gt;_pathToPersonalWordList($absoluteFileName); } /** * Sets the =
file=20
where the current user's personal pspell dictionary can be found. =
Files *=20
should be of the .pws extension and must be in a directory your =
webserver to=20
write files * to. This feature is optional and disabled by default. If =
the=20
given file doesn't exist, * this function will attempt to create it. * =
*=20
@author Tony Bibbs <TONY at GEEKLOG.NET>* @access public * @param string=20
$absoluteFileName The fully qualified location of the .pws file to use =
* */=20
function setPersonalWordList($absoluteFileName) {=20
$this-&gt;_pathToPersonalWordList($absoluteFileName); } /** * Creates =
a temp=20
file for use during the spellcheck process * * Text that is being =
spellchecked=20
gets loaded into temporary file and * then it gets piped over to =
aspell for=20
checking. This method creates that * temporary file * * @author Tony =
Bibbs=20
<TONY at GEEKLOG.NET>* @access private * @return boolean True if =
successful=20
otherwise false * */ function _createTempFile() { $this-&gt;_tempFile =
=3D=20
tempnam($this-&gt;_tempDir, 'textToCheck'); if ($this-&gt;_tempFile =
=3D=3D false)=20
{ trigger_error('Unable to write the temporary file.'); } else { if=20
(!empty($this-&gt;_origText)) { if ($fd =3D =
fopen($this-&gt;_tempFile,'w')) { //=20
Chop it up by line. $textarray =3D explode("\n",$this-&gt;_origText);=20
fwrite($fd,"!\n"); foreach ($textarray as $key=3D&gt;$value) { $value =
=3D=20
ereg_replace('\\"','"',$value); fwrite($fd,"^$value\n"); } =
fclose($fd); return=20
true; } else { trigger_error('Unable to open the temporary file.'); =
return=20
false; } } else { trigger_error('No text has been set.'); return =
false; } } }=20
/** * Adds a word to a user's personal dictionary. Requires you to =
call *=20
setPersonalWordList() first * * @author Tony Bibbs <TONY at GEEKLOG.NET>* =
@access=20
public * @param string $word Word to add to personal dictionary * */ =
function=20
addWord($word) { /*if ($this-&gt;_usePersonalDicts) { return=20
pspell_add_to_personal($this-&gt;_pspellCfgHandle, $word); }*/ } /** * =
Parse=20
the return output from aspell * * Aspell's return values aren't the =
easiest to=20
work with * so this method puts the data into easy to use structures * =
that=20
can be used later by this class and, if needed, by * the calling =
application *=20
* @author Tony Bibbs <TONY at GEEKLOG.NET>* @access private * @param =
string=20
$aspellReturn Return output from aspell * */ function=20
_parseReturn($aspellReturn) { //next parse $return and $text line by =
line, eh?=20
$returnarray =3D explode("\n",$aspellReturn); $returnlines =3D=20
count($returnarray); $textarray =3D explode("\n",$this-&gt;text); =
$lineindex =3D=20
-1; $poscorrect =3D 0; $counter =3D 0; foreach($returnarray as $line) =
{=20
$correction =3D explode(' ',$line); $word =3D $correction[1]; // If =
there is a=20
correction here, processes it, else move the $textarray pointer to the =
next=20
line if (substr($line,0,1) =3D=3D '&amp;') { // Build the position, =
comma=20
separated. Line, character $absposition =3D =
substr($correction[3],0,-1)-1;=20
$position =3D $absposition + $poscorrect; $niceposition =3D $lineindex =
. "," .=20
$absposition; // Start building the suggestion list $suggstart =3D=20
strpos($line,":")+2; $suggestions =3D substr($line,$suggstart); =
$suggestionarray=20
=3D explode(', ',$suggestions); // Set an array for the suggestions.=20
$suggestions =3D array(); foreach ($suggestionarray as $aSuggestion) { =

$suggestions[] =3D $aSuggestion; } } else { if (substr($line,0,1) =
=3D=3D '#') { //=20
Find the position. $absposition =3D $correction[2] - 1; $position =3D =
$absposition=20
+ $poscorrect; $niceposition =3D $lineindex .",". $absposition; // Add =
this word=20
to the arrays. $thePositions[] =3D array($word =3D&gt; $niceposition); =

$theSuggestions[] =3D array($word =3D&gt; 'No Suggestions.'); } else { =
$poscorrect=20
=3D 0; $lineindex =3D $lineindex + 1; } } $this-&gt;_misspellings[] =
=3D $word; if=20
(count($suggestions) &gt; 0) { $this-&gt;_suggestions[$word] =3D=20
implode(',',$suggestions); } else { // Should not make this string =
english=20
dependent. For future we should // make this string configurable so it =
can be=20
overridden by calling // applications language preference.=20
$this-&gt;_suggestions[$word] =3D 'No suggestions'; } } } /** * Spell =
checks a=20
set of words by iterating through words and calling check(). * During =
the=20
check, it collects the suggested spellings of misspelled words. If =
there * are=20
mispelled words, _highlightedText is set to $textString and highlights =
all=20
misspelled words * * @author Tony Bibbs <TONY at GEEKLOG.NET>* @access =
public *=20
@param string $textString * @param boolean $isHTMLEmbedded Indicates =
if the=20
text to check has HTML in it * @return string $textString with =
misspelled=20
words highlighted, otherwise true * */ function =
checkWords($textString,=20
$isHTMLEmbedded =3D false) { $this-&gt;_origText =3D $textString; if=20
($this-&gt;_createTempFile() !=3D false) { if ($isHTMLEmbedded =3D=3D =
true) {=20
$addOptions .=3D ' -H'; } if (!empty($this-&gt;_dictionary)) { =
$addOptions .=3D '=20
-d ' . $this-&gt;dictionary; } if (!empty($this-&gt;wordList)) { =
$addOptions=20
.=3D ' -p ' . $this-&gt;wordList; } // Grab any other aspell options =
for ($i =3D=20
1; $i &lt;=3D count($this-&gt;_aspellOptions); $i++) { $addOptions =
.=3D sprintf('=20
%s %s', key($this-&gt;_aspellOptions), =
current($this-&gt;_aspellOptions));=20
next($this-&gt;_aspellOptions); } reset($this-&gt;_aspellOptions); // =
Calling=20
aspell differs slightly by OS if ($this-&gt;_operatingSystem =3D=3D=20
SPELL_OS_WINDOWS) { $command =3D sprintf('%s -a --lang=3D%s %s &lt; =
"%s"=20
2&gt;&amp;1',$this-&gt;_pathToAspellBinary, $this-&gt;_languageCode,=20
$addOptions, $this-&gt;_tempFile); } else { $command =3D sprintf('%s =
-a=20
--lang=3D%s %s &lt; %s',$this-&gt;_pathToAspellBinary, =
$this-&gt;_languageCode,=20
$addOptions, $this-&gt;_tempFile); } // Execute the command. $retValue =
=3D=20
shell_exec($command); // Delete the temporary file created. if=20
(unlink($this-&gt;_tempFile) =3D=3D false) { trigger_error('Unable to =
delete=20
temporary file.'); } // Check to see if the execute statement returned =

anything. if (empty($retValue)) { trigger_error('There was a problem =
in=20
executing the command against the Aspell binary.'); } else {=20
$this-&gt;_parseReturn($retValue); } } else { trigger_error('Unable to =
create=20
the temporary file.'); } if (count($this-&gt;_misspellings) &gt; 0) { =
return=20
$this-&gt;highlightBadWords(); } } /** * Allows ability to set a =
custom method=20
for highlight misspelled words * * @author Tony Bibbs =
<TONY at GEEKLOG.NET>*=20
@access public * @param string $beginHighlight Opening format of a =
highlighted=20
word * @param string $endHighlight Closing format of a highlighted =
word * */=20
function setHighlight($beginHighlight, $endHighlight) {=20
$this-&gt;_beginHighlight =3D $beginHighlight; $this-&gt;_endHighlight =
=3D=20
$endHighlight; } /** * Highlights misspelled words and returns the =
text * *=20
@author Tony Bibbs <TONY at GEEKLOG.NET>* @access public * @return =
original=20
search text with misspellings highlighted. * */ function =
highlightBadWords() {=20
$tmpString =3D $this-&gt;_origText; foreach ($this-&gt;_misspellings =
AS=20
$curWord) { $tmpBeginHighlight =3D str_replace('{suggested}',=20
$this-&gt;_suggestions[$curWord], $this-&gt;_beginHighlight); // Be =
sure to=20
operate on original text in case there was some HTML/XML in it =
$tmpString =3D=20
str_replace($curWord, $tmpBeginHighlight . $curWord . =
$this-&gt;_endHighlight,=20
$tmpString); } return $tmpString; } } ?&gt;
<P>
<HR>

<P></P><?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 =3D 'localhost'; // host name or IP address of your =
DB server
$_DB_name =3D 'geeklog'; // name of your database,
// must exist before running the =
installer!
$_DB_user =3D 'root'; // MySQL user name
$_DB_pass =3D '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 =3D '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'] =3D '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'] =3D '/path/to/your/public_html/';
$_CONF['path_html'] =3D $_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'] =3D =
'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'] =3D $_CONF['site_url'] . '/admin';

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

// Name and slogan of your site
$_CONF['site_name'] =3D 'Geeklog Site';
$_CONF['site_slogan'] =3D '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'] =3D $_CONF['path'] . 'system/';
$_CONF['path_log'] =3D $_CONF['path'] . 'logs/';
$_CONF['path_language'] =3D $_CONF['path'] . 'language/';
$_CONF['backup_path'] =3D $_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'] =
=3D true;
$_CONF['have_pear'] =3D false;

// Geeklog comes with the necessary PEAR packages and will pick them up =
from
// the following directory if $_CONF['have_pear'] =3D false (above).
$_CONF['path_pear'] =3D $_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'] =3D array ( =20
'backend' =3D>'mail', // can be one of 'mail', 'sendmail', 'smtp' // =

sendmail parameters (for 'backend' =3D&gt; 'sendmail') 'sendmail_path' =
=3D&gt;=20
'/usr/bin/sendmail', 'sendmail_args' =3D&gt; '', // SMTP parameters =
(for=20
'backend' =3D&gt; 'smtp') 'host' =3D&gt; 'smtp.example.com', 'port' =
=3D&gt; '25',=20
'auth' =3D&gt; false, 'username' =3D&gt; 'smtp-username', 'password' =
=3D&gt;=20
'smtp-password' ); //=20
=
+------------------------------------------------------------------------=
---+=20
// | Email Settings | // | | // | Configure how Geeklog sends email: =
Via PHP's=20
mail() function, sendmail, | // | or via an SMTP server. | //=20
=
+------------------------------------------------------------------------=
---+=20
$_CONF['spelling_enabled'] =3D true; $_CONF['spelling_language'] =3D =
'en_US'; //=20
Must be fully qualified location of the aspell binary =
$_CONF['path_aspell'] =3D=20
'c:\progra~1\Aspell\bin\aspell'; // This is just for now, we probably=20
shouldn't encourage the use of the logs // dir since the call unlink() =
will=20
happen there $_CONF['path_tempdir'] =3D $_CONF['path'] . 'logs'; //=20
=
+------------------------------------------------------------------------=
---+=20
// | OTHER DATABASE SETTINGS | // | | // | Database type and database =
backup=20
settings. | //=20
=
+------------------------------------------------------------------------=
---+=20
$_DB_dbms =3D 'mysql'; // Do not change (currently, only MySQL is =
supported) //=20
optional settings for making database backups from within Geeklog=20
$_CONF['allow_mysqldump'] =3D 1; // 1 =3D on, 0 =3D off =
$_DB_mysqldump_path =3D=20
'/usr/bin/mysqldump'; // path to mysqldump binary =
$_CONF['mysqldump_options']=20
=3D '-Q'; // additional options for mysqldump //=20
=
+------------------------------------------------------------------------=
---+=20
// | SITE SETTINGS | // | | // | These settings help define your =
Geeklog site.=20
| //=20
=
+------------------------------------------------------------------------=
---+=20
$_CONF['theme'] =3D 'XSilver'; // default theme // you shouldn't need =
to edit=20
the following $_CONF['layout_url'] =3D $_CONF['site_url'] . '/layout/' =
.=20
$_CONF['theme']; $_CONF['path_themes'] =3D $_CONF['path_html'] . =
'layout/';=20
$_CONF['path_layout'] =3D $_CONF['path_themes'] . $_CONF['theme'] =
.'/'; //=20
optional settings (1 =3D on, 0 =3D off) $_CONF['allow_user_themes'] =
=3D 1;=20
$_CONF['allow_user_language'] =3D 1; $_CONF['allow_user_photo'] =3D 1; =
// allow=20
users to upload self-photo // hides the list of authors from the =
preferences=20
$_CONF['hide_author_exclusion'] =3D 0; //=20
=
+------------------------------------------------------------------------=
---+=20
// | Support for custom user registration form and account details | =
// |=20
Requires custom functions to be written that can be placed in =
lib-custom | //=20
| Function hooks are in users.php, usersettings.php and admin/user.php =

| //=20

=
+------------------------------------------------------------------------=
---+=20
$_CONF['custom_registration'] =3D false; // Set to true if you have =
custom code=20
//=20
=
+------------------------------------------------------------------------=
---+=20
// | LOCALE SETTINGS | //=20
=
+------------------------------------------------------------------------=
---+=20
$_CONF['language'] =3D 'english'; $_CONF['locale'] =3D 'en-gb'; =
$_CONF['date'] =3D=20
'%A, %B %d %Y @ %I:%M %p %Z'; $_CONF['daytime'] =3D '%m/%d %I:%M%p';=20
$_CONF['shortdate'] =3D '%x'; $_CONF['dateonly'] =3D '%d-%b'; =
$_CONF['timeonly'] =3D=20
'%I:%M %p %Z'; $_CONF['default_charset'] =3D 'iso-8859-1'; //=20
=
+------------------------------------------------------------------------=
---+=20
// | SITE STATUS | // | | // | To disable your Geeklog site quickly, =
simply=20
set this flag to false | //=20
=
+------------------------------------------------------------------------=
---+=20
$_CONF['site_enabled'] =3D true; // true or false // Message shown =
when site is=20
down // When this starts with 'http:' visitors are redirected to that =
URL=20
$_CONF['site_disabled_msg'] =3D 'Geeklog Site is down. Please come =
back soon.';=20
//=20
=
+------------------------------------------------------------------------=
---+=20
// | SESSION SETTINGS | // | | // | cookie_ip will store md5(remoteip =
+=20
randomnum) as the session ID in the | // | cookie. This is more secure =
but=20
will more than likely require dialed up | // | users to login each and =
every=20
time. If ipbasedsessid is turned off | // | (which it is by default) =
it will=20
just store a random number as the | // | session ID in the cookie. | =
// | | //=20
| default_perm_cookie_timeout is how long you want the permanent =
cookie | // |=20
to persist for. This can be overridden by the user in their user prefs =

| // |=20

if they want. If you don't want to allow permanent cookies set the | =
// |=20
value to an empty string ''. | // | | // | session_cookie_time is how =
long you=20
want the session cookie to persist | // | for. Only really useful in =
scenarios=20
where you don't want to allow | // | permanent cookies | //=20
=
+------------------------------------------------------------------------=
---+=20
$_CONF['cookie_session'] =3D 'gl_session'; $_CONF['cookie_name'] =3D =
'geeklog';=20
$_CONF['cookie_password'] =3D 'password'; $_CONF['cookie_theme'] =3D =
'theme';=20
$_CONF['cookie_language'] =3D 'language'; $_CONF['cookie_lastvisit'] =
=3D=20
'LastVisit'; $_CONF['cookie_lastvisittemp'] =3D 'LastVisitTemp';=20
$_CONF['cookie_ip'] =3D 0; $_CONF['default_perm_cookie_timeout'] =3D =
604800;=20
$_CONF['session_cookie_timeout'] =3D 7200; $_CONF['cookie_path'] =3D =
'/';=20
$_CONF['cookiedomain'] =3D ''; // e.g. '.example.com' =
$_CONF['cookiesecure'] =3D=20
0; // Set to false if you don't want to store last login data and time =
in the=20
userinfo table $_CONF['lastlogin'] =3D true; //=20
=
+------------------------------------------------------------------------=
---+=20
// | This is really redundant but I am including this as a reminder =
that those=20
| // | people writing Geeklog Plug-ins that are OS dependent should =
check=20
either | // | the $_CONF variable below or PHP_OS directly. If you are =
writing=20
an | // | addon that is OS specific your addon should check the system =
is=20
using the | // | right OS. If not, be sure to show a friendly message =
that=20
says their GL | // | distro isn't running the right OS. Do not modify =
this=20
value | //=20
=
+------------------------------------------------------------------------=
---+=20
$_CONF['ostype'] =3D PHP_OS; //=20
=
+------------------------------------------------------------------------=
---+=20
// | SEARCH SETTINGS | // | | // | These aren't really used at the =
moment -=20
leave as is ... | //=20
=
+------------------------------------------------------------------------=
---+=20
// Indicates if we should expand search results or not. // true =3D =
show title=20
with summary // false =3D title date author hits on one line=20
$_CONF['expanded_search_results'] =3D true; // 0: use users max =
stories per page=20
// 1: Show all // any other number is the # of results per page=20
$_CONF['max_search_results'] =3D 1; // maximum length for the summary =
text for=20
search results should be $_CONF['summary_length'] =3D 250; //=20
=
+------------------------------------------------------------------------=
---+=20
// | MISCELLANEOUS SETTINGS | // | | // | These are other various =
Geeklog=20
settings. The defaults should work OK | // | for most situations. | // =

=
+------------------------------------------------------------------------=
---+=20
// this lets you select which functions are available for registered =
users=20
only $_CONF['loginrequired'] =3D 0; // all of them, if set to 1 will =
override=20
all else $_CONF['submitloginrequired'] =3D 0; =
$_CONF['commentsloginrequired'] =3D=20
0; $_CONF['linksloginrequired'] =3D 0; $_CONF['pollsloginrequired'] =
=3D 0;=20
$_CONF['calendarloginrequired'] =3D 0; $_CONF['statsloginrequired'] =
=3D 0;=20
$_CONF['searchloginrequired'] =3D 0; $_CONF['profileloginrequired'] =
=3D 0;=20
$_CONF['emailuserloginrequired'] =3D 0; =
$_CONF['emailstoryloginrequired'] =3D 0;=20
// Submission Settings // enable (set to 1) or disable (set to 0) =
submission=20
queues: $_CONF['storysubmission'] =3D 1; $_CONF['linksubmission'] =3D =
1;=20
$_CONF['eventsubmission'] =3D 1; $_CONF['usersubmission'] =3D 0; // =
When set to 1,=20
this will display an additional block on the submissions page // that =
lists=20
all stories that have the 'draft' flag set. $_CONF['listdraftstories'] =
=3D 0; //=20
Send an email notification when a new submission has been made. The =
contents=20
// of the array can be any combination of 'story', 'link', 'event', =
and=20
'user'. // Example: $_CONF['notification'] =3D array ('story', 'link', =
'event');=20
// The email will be sent to $_CONF['site_mail'] (see above).=20
$_CONF['notification'] =3D array (); $_CONF['postmode'] =3D =
'plaintext'; // can be=20
'plaintext' or 'html' $_CONF['speedlimit'] =3D 45; // in seconds=20
$_CONF['skip_preview'] =3D 0; // If =3D 1, allow user to submit =
comments and=20
stories without previewing // Allow users to change their username (if =
set to=20
1). $_CONF['allow_username_change'] =3D 0; // Allow users to delete =
their=20
account (if set to 1). $_CONF['allow_account_delete'] =3D 0; // Topic =
Settings=20
// Topics can be assigned a sort number so that you can control what =
order=20
they // appear in the 'Topics' block on the homepage. If you prefer =
you can=20
also // have this sort alphabetically by changing the value to 'alpha' =

(default is // by 'sortnum' $_CONF['sortmethod'] =3D 'sortnum'; // or =
'alpha' //=20
Show the number of stories in a topic in Topics Block =
$_CONF['showstorycount']=20
=3D 1; // Show the number of story submissions for a topic in Topics =
Block=20
$_CONF['showsubmissioncount'] =3D 1; // Hide 'Home' link from Topics =
block (if=20
set to 1) $_CONF['hide_home_link'] =3D 0; // Show blocks for empty =
search=20
results $_CONF['showemptysearchresults'] =3D 0; // How long an =
anonymous (guest)=20
user session is good for $_CONF['whosonline_threshold'] =3D 300; // in =
seconds=20
// "Daily Digest" settings // Let users get stories emailed to them // =

Requires cron and the use of php as a shell script =
$_CONF['emailstories'] =3D 0;=20
// Specify length of stories in those emails: // 0 =3D send only title =
+ link, 1=20
=3D send entire introtext, // any other number =3D max. number of =
characters per=20
story $_CONF['emailstorieslength'] =3D 1; // New users get stories =
emailed to=20
them per default (=3D 1) or not (=3D 0) =
$_CONF['emailstoriesperdefault'] =3D 0; //=20
When user submission is activated, allow users from these domains to =
//=20
register without having to go through the submission queue.=20
$_CONF['allow_domains'] =3D ''; // e.g. =
'mycompany.com,myothercompany.com' //=20
Following times are in seconds $_CONF['newstoriesinterval'] =3D 86400; =
// =3D 24=20
hours $_CONF['newcommentsinterval'] =3D 172800; // =3D 48 hours=20
$_CONF['newlinksinterval'] =3D 1209600; // =3D 14 days // Set to 1 to =
hide a=20
section from the What's New block: $_CONF['hidenewstories'] =3D 0;=20
$_CONF['hidenewcomments'] =3D 0; $_CONF['hidenewlinks'] =3D 0; // =
Calendar=20
Settings $_CONF['personalcalendars'] =3D 1; =
$_CONF['showupcomingevents'] =3D 1;=20
$_CONF['upcomingeventsrange'] =3D 14; // days $_CONF['event_types'] =
=3D=20
=
'Anniversary,Appointment,Birthday,Business,Education,Holiday,Meeting,Misc=
ellaneous,Personal,Phone=20
Call,Special Occasion,Travel,Vacation'; // Story Settings=20
$_CONF['maximagesperarticle'] =3D 5; $_CONF['limitnews'] =3D 10; =
$_CONF['minnews']=20
=3D 1; // minimum number of stories per page =
$_CONF['contributedbyline'] =3D 1; //=20
If 1, show contributed by line $_CONF['article_image_align'] =3D =
'right'; //=20
Topic icon on left or right. $_CONF['hideemailicon'] =3D 0; // If 1, =
hide "email=20
story" option $_CONF['hideprintericon'] =3D 0; // If 1, hide "printer =
friendly"=20
option // When set to 1, this will render the first story on any page =
using=20
the // templates for featured stories - even if that story is not =
featured.=20
$_CONF['showfirstasfeatured'] =3D 0; //=20
=
+------------------------------------------------------------------------=
---+=20
// | RSS feed settings | // | | // | Settings for RSS feeds (aka RDF =
feeds).=20
Please note that most of these | // | are merely default settings for =
the=20
feeds created from the "Content | // | Syndication" entry in the =
Admin's menu.=20
| //=20
=
+------------------------------------------------------------------------=
---+=20
$_CONF['backend'] =3D 1; // 1 =3D activate feeds, 0 =3D off // path to =
your site's=20
default RSS feed $_CONF['rdf_file'] =3D $_CONF['path_html'] .=20
'backend/geeklog.rdf'; // This allows a person to limit the rss feed =
to a=20
certain number of stories // (e.g. 10 or 12) or else limit the rss =
feed to all=20
stories within a certain // period of time in hours (e.g. 24h or =
168h).=20
$_CONF['rdf_limit'] =3D 10; // number of stories (10) or hours (24h) =
// Include=20
the story's entire intro text in the feed (=3D 1) or limit the number =
// of=20
characters from the intro text (any number &gt; 1) or don't include =
the text=20
// at all (=3D 0). $_CONF['rdf_storytext'] =3D 0; // Default language =
for the feed=20
- may have to be different than the locale $_CONF['rdf_language'] =3D =
'en-gb';=20
// Uncomment the following line to set the copyright year in the =
site's footer=20
// to a specific year. Otherwise, the current year will be used. //=20
$_CONF['copyrightyear'] =3D '2003'; // Optional Image Settings // If =
you set=20
$_CONF['image_lib'] below, you must supply a path for the library // =
you will=20
use. Setting this also assumes that if a photo is uploaded that is // =
too big=20
either by the image sizes below or by overriding them using the // =
upload=20
object then the library you choose will attempt to resize the image. =
//=20
Leaving this value empty disables this feature $_CONF['image_lib'] =3D =
''; //=20
can be one of 'netpbm', 'imagemagick', 'gdlib' // If you set image_lib =
to=20
imagemagick give this path otherwise comment it out // NOTE: you will =
need a=20
fairly recent version of ImageMagick for this to work. // ImageMagick =
version=20
5.4.9 (or newer) is recommended. //$_CONF['path_to_mogrify'] =3D=20
'/path/to/mogrify'; // If you set image_lib to netpbm give the path to =
the=20
netpbm directory, you // need the trailing slash here. // NOTE: if you =
use=20
NETPBM, use the latest package from the Gallery package for // your =
operating=20
system found at http://sourceforge.net/projects/gallery in // the =
download=20
section. You need to take the netpbm tarball from them and // =
uncompress the=20
file which will create a netpbm directory. If you plan to // only use =
netpbm=20
with Geeklog, put that entire folder in /path/to/geeklog and // adjust =
the=20
path below. The only programs you need from netpbm are giftopnm, // =
jpegtopnm,=20
pngtopnm, ppmtogif, ppmtojpeg, pnmtopng and pnmscale=20
//$_CONF['path_to_netpbm'] =3D '/path/to/netpbm/'; // Uncomment the =
following=20
line if you experience problems with the image // upload. Debug =
messages will=20
be added to the error.log file. // $_CONF['debug_image_upload'] =3D =
true; //=20
When set to 1, Geeklog will keep the original, unscaled images and =
make // the=20
smaller image link to the unscaled image. =
$_CONF['keep_unscaled_image'] =3D 0;=20
// 1 =3D keep original images // Story image settings =
$_CONF['max_image_width']=20
=3D 300; // In pixels $_CONF['max_image_height'] =3D 300; // In pixels =

$_CONF['max_image_size'] =3D 1048576; // 1048576 =3D 1MB // User photo =
settings=20
$_CONF['max_photo_width'] =3D 96; // In pixels =
$_CONF['max_photo_height'] =3D 96;=20
// In pixels $_CONF['max_photo_size'] =3D 65536; // 65536 =3D 64KB // =
Comment=20
Settings $_CONF['commentspeedlimit'] =3D 45; $_CONF['comment_limit'] =
=3D 100; //=20
Default Number of Comments under Story $_CONF['comment_mode'] =3D =
'threaded'; //=20
Default Comment Mode; from 'threaded','nested','nocomments',and 'flat' =
//=20
Allow / disallow comments to stories by default (can be changed =
individually=20
for every story) $_CONF['comment_code'] =3D 0; // 0 =3D comments =
enabled, -1 =3D=20
disabled // Poll Settings $_CONF['maxanswers'] =3D 10; // =
'submitorder' is order=20
answers are saved in admin/poll.php // 'voteorder' will list answers =
in order=20
of number of votes (highest-&gt;lowest); $_CONF['answerorder'] =3D=20
'submitorder'; $_CONF['pollcookietime'] =3D 86400; =
$_CONF['polladdresstime'] =3D=20
604800; // Password setting: minimum time between two requests for a =
new=20
password $_CONF['passwordspeedlimit'] =3D 300; // seconds =3D 5 =
minutes // Links=20
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=20
hide the // categories but keep the paging. Setting only linksperpage =
to 0=20
will list // all the links of the selected category on one page.=20
$_CONF['linkcols'] =3D 3; // categories per column =
$_CONF['linksperpage'] =3D 10;=20
// links per page // Parameters for checking HTML tags // *** Warning: =
Adding=20
the following tags to the list of allowable HTML can // *** make your =
site=20
vulnerable to scripting attacks! // *** Use with care: <IMG> <SPAN>
<MARQUEE>
<SCRIPT> <embed> <object> <iframe>=20

/* 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'] =3D array (=20
'p' =3D> array(),
'b' =3D> array(),
'i' =3D> array(),
'a' =3D> array('href' =3D> 1, 'title' =3D> 1),
'em' =3D> array(),
'br' =3D> array(),
'tt' =3D> array(),
'hr' =3D> array(),
'li' =3D> array(),
'ol' =3D> array(),
'ul' =3D> array(),
'code' =3D> array(),
'pre' =3D> 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'] =3D array (
'p' =3D> array('class' =3D> 1, 'id' =3D> 1, 'align' =3D> 1),
'div' =3D> array('class' =3D> 1, 'id' =3D> 1),
'span' =3D> array('class' =3D> 1, 'id' =3D> 1),
'table' =3D> array('class' =3D> 1, 'id' =3D> 1, 'width' =3D> 1, =
'border' =3D> 1,
'cellspacing' =3D> 1, 'cellpadding' =3D> 1),
'tr' =3D> array('class' =3D> 1, 'id' =3D> 1, 'align' =3D> 1, =
'valign' =3D> 1),
'th' =3D> array('class' =3D> 1, 'id' =3D> 1, 'align' =3D> 1, =
'valign' =3D> 1,
'colspan' =3D> 1, 'rowspan' =3D> 1),
'td' =3D> array('class' =3D> 1, 'id' =3D> 1, 'align' =3D> 1, =
'valign' =3D> 1,
'colspan' =3D> 1, 'rowspan' =3D> 1)
);

// Parameters for checking for "bad" words
$_CONF['censormode'] =3D 1;
$_CONF['censorreplace'] =3D '*censored*';
$_CONF['censorlist'] =3D =
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'] =3D false; // false =3D off, true =3D on

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

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

?>
<P><HR></P><?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=20
// the error log
$_STORY_VERBOSE =3D false;

$display =3D '';

if (!SEC_hasRights('story.edit')) {
$display .=3D COM_siteHeader ('menu');
$display .=3D COM_startBlock ($MESSAGE[30], '',
COM_getBlockTemplate ('_msg_block', =
'header'));=20
$display .=3D $MESSAGE[31];
$display .=3D COM_endBlock (COM_getBlockTemplate ('_msg_block', =
'footer'));
$display .=3D 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 =3D '', $mode =3D '')=20
{
global $_TABLES, $HTTP_POST_VARS, $_USER, $_CONF, $LANG24, =
$LANG_ACCESS;

$display =3D '';
=20
if ($_CONF['spelling_enabled']) {
$spellChecker =3D new PHPSpellChecker();
$spellChecker->setPathToApsellBinary($_CONF['path_aspell']);
$spellChecker->setTempDir($_CONF['path_tempdir']);
}
if (!empty($sid) && $mode =3D=3D 'edit') {
$result =3D DB_query("SELECT *,UNIX_TIMESTAMP(date) AS unixdate =
FROM {$_TABLES['stories']} WHERE sid =3D '$sid'");
$A =3D DB_fetchArray($result);
$access =3D =
SEC_hasAccess($A['owner_id'],$A['group_id'],$A['perm_owner'],$A['perm_gro=
up'],$A['perm_members'],$A['perm_anon']);
$access =3D min ($access, SEC_hasTopicAccess ($A['tid']));
if ($access =3D=3D 2) {
$display .=3D COM_startBlock($LANG24[40], '',
COM_getBlockTemplate ('_msg_block', =
'header'));
$display .=3D $LANG24[41];
$display .=3D COM_endBlock (COM_getBlockTemplate =
('_msg_block', 'footer'));
// Do this to avoid having to chance $A
$B =3D $A;
if ($_CONF['spelling_enabled']) {
if ($B['postmode'] =3D=3D 'html') {
$B['introtext'] =3D =
$spellChecker->checkWords($B['introtext'], true);
$B['bodytext'] =3D =
$spellChecker->checkWords($B['bodytext'], true);
$B['title']=3D =
$spellChecker->checkWords($B['title'], true);
} else {
$B['introtext'] =3D =
$spellChecker->checkWords($B['introtext'], false);
$B['bodytext'] =3D =
$spellChecker->checkWords($B['bodytext'], false);
$B['title']=3D =
$spellChecker->checkWords($B['title'], false);
}
}
$display .=3D COM_article($B,n);
return $display;
} else if ($access =3D=3D 0) {
$display .=3D COM_startBlock($LANG24[40], '',
COM_getBlockTemplate ('_msg_block', =
'header'));
$display .=3D $LANG24[42];
$display .=3D COM_endBlock(COM_getBlockTemplate =
('_msg_block', 'footer'));
return $display;
}
} elseif (!empty($sid) && $mode =3D=3D "editsubmission") {
$result =3D DB_query("SELECT *,UNIX_TIMESTAMP(date) AS unixdate =
FROM {$_TABLES['storysubmission']} WHERE sid =3D '$sid'");
if (DB_numRows ($result) > 0) {
$A =3D DB_fetchArray($result);
$A['show_topic_icon'] =3D 1;
$A['commentcode'] =3D $_CONF['comment_code'];
$A['featured'] =3D 0;
$A['statuscode'] =3D 0;
$A['owner_id'] =3D $A['uid'];
$result =3D DB_query ("SELECT =
group_id,perm_owner,perm_group,perm_members,perm_anon FROM =
{$_TABLES['topics']} WHERE tid =3D '{$A['tid']}'");
$T =3D DB_fetchArray ($result);
$A['group_id'] =3D $T['group_id'];
$A['perm_owner'] =3D $T['perm_owner'];
$A['perm_group'] =3D $T['perm_group'];
$A['perm_members'] =3D $T['perm_members'];
$A['perm_anon'] =3D $T['perm_anon'];
$access =3D 3;
$A['title'] =3D 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 =3D=3D "edit") {
$A['sid'] =3D COM_makesid();
$A['show_topic_icon'] =3D 1;
$A['uid'] =3D $_USER['uid'];
$A['unixdate'] =3D time();
$A['commentcode'] =3D $_CONF['comment_code'];
$A['postmode'] =3D $_CONF['postmode'];
$A['statuscode'] =3D 0;
$A['featured'] =3D 0;
$A['owner_id'] =3D $_USER['uid'];
$A['group_id'] =3D DB_getItem ($_TABLES['groups'], 'grp_id',
"grp_name =3D 'Story Admin'");
$A['perm_owner'] =3D 3;
$A['perm_group'] =3D 2;
$A['perm_members'] =3D 2;
$A['perm_anon'] =3D 2;
$access =3D 3;
} else {
$A =3D $HTTP_POST_VARS;
=20
if (empty ($A['ampm'])) {
$A['ampm'] =3D $A['publish_ampm'];
}
if ($A['draft_flag'] =3D=3D 'on') {
$A['draft_flag'] =3D 1;
} else {
$A['draft_flag'] =3D 0;
}
if ($A['show_topic_icon'] =3D=3D 'on') {
$A['show_topic_icon'] =3D 1;
} else {
$A['show_topic_icon'] =3D 0;
}
=20
// Convert array values to numeric permission values
=
list($A['perm_owner'],$A['perm_group'],$A['perm_members'],$A['perm_anon']=
) =3D =
SEC_getPermissionValues($A['perm_owner'],$A['perm_group'],$A['perm_member=
s'],$A['perm_anon']);
if ($A["postmode"] =3D=3D "html") {
$A["introtext"] =3D =
COM_checkHTML(COM_checkWords($A["introtext"]));
$A["bodytext"] =3D =
COM_checkHTML(COM_checkWords($A["bodytext"]));
$A["title"] =3D =
COM_checkHTML(htmlspecialchars(COM_checkWords($A["title"])));
} else {
$A["introtext"] =3D =
htmlspecialchars(COM_checkWords($A["introtext"]));
$A["bodytext"] =3D =
htmlspecialchars(COM_checkWords($A["bodytext"]));
$A["title"] =3D =
htmlspecialchars(COM_checkWords($A["title"]));
}
$A['title'] =3D strip_tags($A['title']);
}

// Load HTML templates
$story_templates =3D new Template($_CONF['path_layout'] . =
'admin/story');
if (($_CONF['advanced_editor'] =3D=3D 1) && file_exists =
($_CONF['path_layout'] . 'admin/story/storyeditor_advanced.thtml')) {
=
$story_templates->set_file(array('editor'=3D>'storyeditor_advanced.thtml'=
));
} else {
=
$story_templates->set_file(array('editor'=3D>'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 =3D $A['publish_hour'];
if ($publish_hour =3D=3D 12) {
if ($A['ampm'] =3D=3D 'am') {
$publish_hour =3D 0;
}
} else if ($A['ampm'] =3D=3D 'pm') {
$publish_hour +=3D 12;
}
$A['unixdate'] =3D strtotime($A['publish_year'] . '-' . =
$A['publish_month'] . '-' . $A['publish_day']
. ' ' . $publish_hour . ':' . $A['publish_minute'] . ':00');
}

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

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

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

$usergroups =3D SEC_getUserGroups();
if ($access =3D=3D 3) {
$groupdd .=3D '<select name=3D"group_id">';
for ($i =3D 0; $i < count($usergroups); $i++) {
$groupdd .=3D '<option value=3D"' . =
$usergroups[key($usergroups)] . '"';
if ($A['group_id'] =3D=3D $usergroups[key($usergroups)]) {
$groupdd .=3D ' selected=3D"selected"';
}
$groupdd .=3D '>' . key($usergroups) . '</option>';
next($usergroups);
}
$groupdd .=3D '</select>';
} else {
// they can't set the group then
$groupdd .=3D DB_getItem ($_TABLES['groups'], 'grp_name',
"grp_id =3D {$A['group_id']}");
$groupdd .=3D '<input type=3D"hidden" name=3D"group_id" =
value=3D"'
. $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 =3D COM_getUserDateTimeFormat($A['unixdate']);
$story_templates->set_var('lang_date', $LANG24[15]);
$publish_month =3D date('m', $A['unixdate']);
$publish_day =3D date('d', $A['unixdate']);
$publish_year =3D date('Y', $A['unixdate']);
$publish_hour =3D date('H', $A['unixdate']);
$publish_minute =3D date('i', $A['unixdate']);
$publish_second =3D date('s', $A['unixdate']);
$story_templates->set_var('publish_second', $publish_second);
$publish_ampm =3D '';
if ($publish_hour >=3D 12) {
if ($publish_hour > 12) {
$publish_hour =3D $publish_hour - 12;
}
$ampm =3D 'pm';
} else {
$ampm =3D 'am';
}
if ($ampm =3D=3D 'pm') {
$story_templates->set_var ('publishpm_selected', =
'selected=3D"selected"');
} else {
$story_templates->set_var ('publisham_selected', =
'selected=3D"selected"');
}
$month_options =3D COM_getMonthFormOptions($publish_month);
$story_templates->set_var('publish_month_options', $month_options);
=20
$day_options =3D COM_getDayFormOptions($publish_day);
$story_templates->set_var('publish_day_options', $day_options);

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

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

$minute_options =3D 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']);=20
$story_templates->set_var('lang_title', $LANG24[13]);
if ($A['postmode'] =3D=3D 'plaintext') {
$A['title'] =3D str_replace('$','&#36;',$A['title']);
}
=20
$A['title'] =3D str_replace('{','&#123;',$A['title']);
$A['title'] =3D str_replace('}','&#125;',$A['title']);
$A['title'] =3D 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'] =3D DB_getItem ($_TABLES['topics'], 'tid', 'is_default =
=3D 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'] =3D=3D 1) {
$story_templates->set_var('show_topic_icon_checked', =
'checked=3D"checked"');
} else {
$story_templates->set_var('show_topic_icon_checked', '');
}
$story_templates->set_var('lang_draft', $LANG24[34]);
if ($A['draft_flag'] =3D=3D 1) {
$story_templates->set_var('is_checked', 'checked=3D"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) =3D replace_images($A['sid'], =
stripslashes($A['introtext']), stripslashes($A['bodytext']));
=20
$story_templates->set_var('lang_introtext', $LANG24[16]);
if ($A['postmode'] =3D=3D 'plaintext') {
$newintro =3D str_replace('$','&#36;',$newintro);
} else {
// Insert [code] and [/code] if needed
$newintro =3D str_replace('<pre><code>','[code]',$newintro);
$newbody =3D str_replace('<pre><code>','[code]',$newbody);
$newintro =3D str_replace('</code></pre>','[/code]',$newintro);
$newbody =3D str_replace('</code></pre>','[/code]',$newbody);
}
$newintro =3D str_replace('{','&#123;',$newintro);
$newintro =3D str_replace('}','&#125;',$newintro);
$story_templates->set_var('story_introtext', $newintro);
$story_templates->set_var('lang_bodytext', $LANG24[17]);
if ($A['postmode'] =3D=3D 'plaintext') {
$newbody =3D str_replace('$','&#36;',$newbody);
}
=20
$newbody =3D str_replace('{','&#123;',$newbody);
$newbody =3D 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 =3D '';
$saved_images =3D '';
if ($_CONF['maximagesperarticle'] > 0) {
$story_templates->set_var('lang_images', $LANG24[47]);
$icount =3D DB_count($_TABLES['article_images'],'ai_sid', =
$A['sid']);
if ($icount > 0) {
$result_articles =3D DB_query("SELECT * FROM =
{$_TABLES['article_images']} WHERE ai_sid =3D '{$A['sid']}'");
for ($z =3D 1; $z <=3D $icount; $z++) {
$I =3D DB_fetchArray($result_articles);
$saved_images .=3D $z . ') <a href=3D"' . =
$_CONF['site_url'] . '/images/articles/' . $I['ai_filename'] . '" =
target=3D"_blank">' . $I['ai_filename'] . '</a>';
$saved_images .=3D '&nbsp;&nbsp;&nbsp;' . $LANG24[52] . =
': <input type=3D"checkbox" name=3D"delete[' .$I['ai_img_num'] . =
']"><br>';
}
}
=20
$newallowed =3D $_CONF['maximagesperarticle'] - $icount;
for ($z =3D $icount + 1; $z <=3D $_CONF['maximagesperarticle']; =
$z++) {
$fileinputs .=3D $z . ') <input type=3D"file" name=3D"file' =
. $z . '">';
if ($z < $_CONF['maximagesperarticle']) {
$fileinputs .=3D '<br>';
}
}
$fileinputs .=3D '<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]);=20
$story_templates->set_var('story_emails', $A['numemails']);
$story_templates->set_var('story_id', $A['sid']);
$story_templates->set_var('lang_save', $LANG24[8]);=20
$story_templates->set_var('lang_preview', $LANG24[9]);=20
$story_templates->set_var('lang_cancel', $LANG24[10]);=20
$story_templates->set_var('lang_delete', $LANG24[11]);=20
$story_templates->parse('output','editor');
$display .=3D =
$story_templates->finish($story_templates->get_var('output'));
$display .=3D 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 =3D 1)=20
{
global $_TABLES, $LANG24, $_CONF, $LANG_ACCESS, $LANG09, $_USER, =
$_GROUPS,$HTTP_POST_VARS,$HTTP_GET_VARS;

$display =3D '';

$display .=3D COM_startBlock ($LANG24[22], '',
COM_getBlockTemplate ('_admin_block', =
'header'));
$story_templates =3D new Template($_CONF['path_layout'] . =
'admin/story');
$story_templates->set_file (array ('list' =3D> 'liststories.thtml',
'row' =3D> '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]);=20

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

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

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

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

$limit =3D (50 * $page) - 50;
$result =3D DB_query("SELECT *,UNIX_TIMESTAMP(date) AS unixdate FROM =
{$_TABLES['stories']} " . $excludetopics . "ORDER BY date DESC LIMIT =
$limit,50");
$nrows =3D DB_numRows($result);
if ($nrows > 0) {
for ($i =3D 1; $i <=3D $nrows; $i++) {
$scount =3D (50 * $page) - 50 + $i;
$A =3D DB_fetchArray($result);
$access =3D =
SEC_hasAccess($A['owner_id'],$A['group_id'],$A['perm_owner'],$A['perm_gro=
up'],$A['perm_members'],$A['perm_anon']);
if ($access > 0) {
if ($access =3D=3D 3) {
if (SEC_hasTopicAccess ($A['tid']) =3D=3D 3) {
$access =3D $LANG_ACCESS['edit'];
} else {
$access =3D $LANG_ACCESS['readonly'];
}
} else {
$access =3D $LANG_ACCESS['readonly'];
}
} else {
$access =3D $LANG_ACCESS['none'];
}
$curtime =3D COM_getUserDateTimeFormat($A['unixdate']);
$story_templates->set_var('story_id', $A['sid']);
$story_templates->set_var('row_num', $scount);
$A['title'] =3D 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'] =3D=3D 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 =3D {$A['uid']}"));
$story_templates->set_var('story_date', =
strftime($_CONF['shortdate'], $curtime[1]));
$story_templates->set_var('story_topic', $A['tid']);
if ($A['featured'] =3D=3D 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 =3D DB_query ("SELECT COUNT(*) AS count FROM =
{$_TABLES['stories']}" . $excludetopics);
$N =3D DB_fetchArray ($nresult);
$numstories =3D $N['count'];
if ($numstories > 50) {
$prevpage =3D $page - 1;
$nextpage =3D $page + 1;
$pagestart =3D ($page - 1) * 50;
if ($pagestart >=3D 50) {
$story_templates->set_var ('previouspage_link', '<a =
href=3D"'
. $_CONF['site_admin_url']
. '/story.php?mode=3Dlist&amp;page=3D' . $prevpage . =
'">'
. $LANG24[1] . '</a> ');
} else {
$story_templates->set_var('previouspage_link','');
}
if ($pagestart <=3D ($numstories - 50)) {
$story_templates->set_var ('nextpage_link', '<a =
href=3D"'
. $_CONF['site_admin_url']
. '/story.php?mode=3Dlist&amp;page=3D' . $nextpage . =
'">'
. $LANG24[2] . '</a> ');
} else {
$story_templates->set_var('nextpage_link','');
}
$baseurl =3D $_CONF['site_admin_url'] . =
'/story.php?mode=3Dlist&tid=3D' .$current_topic;
$numpages =3D 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=3D"8">'
. $LANG24[6] . '</td></tr>');
$story_templates->set_var ('previouspage_link', '');
$story_templates->set_var ('nextpage_link', '');
$story_templates->set_var ('google_paging' ,'');
}
$display .=3D $story_templates->parse('output','list');
$display .=3D 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 =3D DB_query("SELECT ai_filename FROM =
{$_TABLES['article_images']} WHERE ai_sid =3D '$sid' ORDER BY =
ai_img_num");
$nrows =3D DB_numRows($result);
for ($i =3D 1; $i <=3D $nrows; $i++) {
$A =3D DB_fetchArray($result);
$dimensions =3D GetImageSize($_CONF['path_html'] . =
'images/articles/' . $A['ai_filename']);
if (!empty($dimensions[0]) AND !empty($dimensions[1])) {
$sizeattributes =3D 'width=3D"' . $dimensions[0] . '" =
height=3D"' . $dimensions[1] . '" ';
} else {
$sizeattributes =3D '';
}

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

$norm =3D $lLinkPrefix . '<img ' . $sizeattributes . 'src=3D"' . =
$_CONF['site_url'] . '/images/articles/' . $A['ai_filename'] . '" =
alt=3D"">' . $lLinkSuffix;
$left =3D $lLinkPrefix . '<img ' . $sizeattributes . =
'align=3D"left" src=3D"' . $_CONF['site_url'] . '/images/articles/' . =
$A['ai_filename'] . '" alt=3D"">' . $lLinkSuffix;
$right =3D $lLinkPrefix . '<img ' . $sizeattributes . =
'align=3D"right" src=3D"' . $_CONF['site_url'] . '/images/articles/' . =
$A['ai_filename'] . '" alt=3D"">' . $lLinkSuffix;
$fulltext =3D $intro . ' ' . $body;
$count =3D substr_count($fulltext, $norm) + =
substr_count($fulltext, $left) + substr_count($fulltext, $right);
$intro =3D str_replace($norm, '[' . $LANG24[48] . $i . ']', =
$intro);
$body =3D str_replace($norm, '[' . $LANG24[48] . $i . ']', =
$body);
$intro =3D str_replace($left, '[' . $LANG24[48] . $i . '_' . =
$LANG24[50] . ']', $intro);
$body =3D str_replace($left, '[' . $LANG24[48] . $i . '_' . =
$LANG24[50] . ']', $body);
$intro =3D str_replace($right, '[' . $LANG24[48] . $i . '_' . =
$LANG24[49] . ']', $intro);
$body =3D 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 =3D DB_query("SELECT ai_filename FROM =
{$_TABLES['article_images']} WHERE ai_sid =3D '$sid' ORDER BY =
ai_img_num");
$nrows =3D DB_numRows($result);
$errors =3D array();

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

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

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

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

/**=20
* 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=3D'',$sid,$uid,$tid,$title,$introtext,$bodytext,$hits,$=
unixdate,$comments,$featured,$commentcode,$statuscode,$postmode,$frontpag=
e,$draft_flag,$numemails,$owner_id,$group_id,$perm_owner,$perm_group,$per=
m_members,$perm_anon,$delete,$show_topic_icon)=20
{
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) =3D =
SEC_getPermissionValues($perm_owner,$perm_group,$perm_members,$perm_anon)=
;

$access =3D 0;
if (DB_count ($_TABLES['stories'], 'sid', $sid) > 0) {
$result =3D DB_query ("SELECT =
owner_id,group_id,perm_owner,perm_group,perm_members,perm_anon FROM =
{$_TABLES['stories']} WHERE sid =3D '{$sid}'");
$A =3D DB_fetchArray ($result);
$access =3D SEC_hasAccess ($A['owner_id'], $A['group_id'],
$A['perm_owner'], $A['perm_group'], $A['perm_members'],
$A['perm_anon']);
} else {
$access =3D 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 .=3D COM_siteHeader ('menu');
$display .=3D COM_startBlock ($MESSAGE[30], '',
COM_getBlockTemplate ('_msg_block', =
'header'));
$display .=3D $MESSAGE[31];
$display .=3D COM_endBlock (COM_getBlockTemplate ('_msg_block', =
'footer'));
$display .=3D 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 =3D date("Y-m-d H:i:s",$unixdate);

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

// Get draft flag value
if ($draft_flag =3D=3D 'on') {
$draft_flag =3D 1;
} else {
$draft_flag =3D 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) =3D=3D 1) {
if (DB_getItem($_TABLES['stories'],'draft_flag',"sid =3D =
'$sid'") =3D=3D 1) {
$unixdate =3D time();
}
}
}

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

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

if (empty($numemails)) {
$numemails =3D 0;
}
=20
if ($show_topic_icon =3D=3D 'on') {
$show_topic_icon =3D 1;
} else {
$show_topic_icon =3D 0;
}
=20
// Get the related URLs
$related =3D addslashes (COM_whatsRelated ("$introtext =
$bodytext", $uid, $tid));

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

// Delete any images if needed
for ($i =3D 1; $i <=3D count($delete); $i++) {
$ai_filename =3D DB_getItem =
($_TABLES['article_images'],'ai_filename', "ai_sid =
=3D '$sid' AND ai_img_num =3D " . key ($delete));
$curfile =3D $_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 =3D substr_replace ($ai_filename, =
'_original.',
strrpos ($ai_filename, '.'), 1);
$lFilename_large_complete =3D $_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 =3D '$sid' AND ai_img_num =3D " . 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 =3D =
DB_getItem($_TABLES['article_images'],'max(ai_img_num)',"ai_sid =3D =
'$sid'") + 1;
} else {
$index_start =3D 1;
}

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

$upload->setDebug(true);
$upload->setMaxFileUploads ($_CONF['maximagesperarticle']);
if (!empty($_CONF['image_lib'])) {
if ($_CONF['image_lib'] =3D=3D 'imagemagick') {
// Using imagemagick
$upload->setMogrifyPath ($_CONF['path_to_mogrify']);
} elseif ($_CONF['image_lib'] =3D=3D 'netpbm') {
// using netPBM
$upload->setNetPBM ($_CONF['path_to_netpbm']);
} elseif ($_CONF['image_lib'] =3D=3D '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'] =3D=3D 1) {
$upload->keepOriginalImage (true);
} else {
$upload->keepOriginalImage (false);
}
}
=
$upload->setAllowedMimeTypes(array('image/gif'=3D>'.gif','image/jpeg'=3D>=
'.jpg,.jpeg','image/pjpeg'=3D>'.jpg,.jpeg','image/x-png'=3D>'.png','image=
/png'=3D>'.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 =3D 1MB

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

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

reset($filenames);
for ($z =3D $index_start; $z <=3D $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) =3D insert_images($sid, =
$introtext, $bodytext);
if (count($errors) > 0) {
$display =3D COM_siteHeader ('menu');
$display .=3D COM_startBlock ($LANG24[54], '',
COM_getBlockTemplate ('_msg_block', =
'header'));
$display .=3D $LANG24[55] . '<p>';
for ($i =3D 1; $i <=3D count($errors); $i++) {
$display .=3D current($errors) . '<br>';
next($errors);
}
$display .=3D COM_endBlock (COM_getBlockTemplate =
('_msg_block', 'footer'));
$display .=3D storyeditor($sid);
$display .=3D COM_siteFooter();
echo $display;
exit;
}
}

if ($type =3D=3D 'submission') {
$return_to =3D $_CONF['site_admin_url'] . =
'/moderation.php?msg=3D9';
} else {
$return_to =3D $_CONF['site_admin_url'] . =
'/story.php?msg=3D9';
}
=
DB_save($_TABLES['stories'],'sid,uid,tid,title,introtext,bodytext,hits,da=
te,comments,related,featured,commentcode,statuscode,postmode,frontpage,dr=
aft_flag,numemails,owner_id,group_id,perm_owner,perm_group,perm_members,p=
erm_anon,show_topic_icon',"$sid,$uid,'$tid','$title','$introtext','$bodyt=
ext',$hits,'$date','$comments','$related',$featured,'$commentcode','$stat=
uscode','$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 =3D=3D 'submission') {
DB_delete($_TABLES['storysubmission'],'sid',$sid);
}
COM_rdfUpToDateCheck ();
COM_olderStuff ();
} else {
$display .=3D COM_siteHeader('menu');
$display .=3D COM_errorLog($LANG24[31],2);
$display .=3D storyeditor($sid);
$display .=3D 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 =3D DB_query ("SELECT ai_filename FROM =
{$_TABLES['article_images']} WHERE ai_sid =3D '$sid'");
$nrows =3D DB_numRows ($result);
for ($i =3D 1; $i <=3D $nrows; $i++) {
$A =3D DB_fetchArray ($result);
$filename =3D $_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 =3D substr_replace ($A['ai_filename'], =
'_original.',
strrpos ($A['ai_filename'], =
'.'), 1);
$lFilename_large_complete =3D $_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=3D10');
}

// MAIN

$display =3D '';
if (($mode =3D=3D $LANG24[11]) && !empty ($LANG24[11])) { // delete
if (!isset ($sid) || empty ($sid) || ($sid =3D=3D 0)) {
COM_errorLog ('Attempted to delete story sid=3D' . $sid);
echo COM_refresh ($_CONF['site_admin_url'] . '/story.php');
} else if ($type =3D=3D 'submission') {
DB_delete ($_TABLES['storysubmission'], 'sid', $sid,
$_CONF['site_admin_url'] . '/moderation.php');
} else {
echo deletestory ($sid);
}
} else if (($mode =3D=3D $LANG24[9]) && !empty ($LANG24[9])) { // =
preview
$display .=3D COM_siteHeader('menu');
$display .=3D storyeditor($sid,$mode);
$display .=3D COM_siteFooter();
echo $display;
} else if ($mode =3D=3D 'edit') {
$display .=3D COM_siteHeader('menu');
$display .=3D storyeditor($sid,$mode);
$display .=3D COM_siteFooter();
echo $display;
} else if ($mode =3D=3D 'editsubmission') {
$display .=3D COM_siteHeader('menu');
$display .=3D storyeditor($id,$mode);
$display .=3D COM_siteFooter();
echo $display;
} else if (($mode =3D=3D $LANG24[8]) && !empty ($LANG24[8])) { // save
if ($publish_ampm =3D=3D 'pm') {
if ($publish_hour < 12) {
$publish_hour =3D $publish_hour + 12;
}
}
if ($publish_ampm =3D=3D 'am' AND $publish_hour =3D=3D 12) {
$publish_hour =3D '00';
}
$unixdate =3D strtotime("$publish_month/$publish_day/$publish_year =
$publish_hour:$publish_minute:$publish_second");
=
submitstory($type,$sid,$uid,$tid,$title,$introtext,$bodytext,$hits,$unixd=
ate,$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 =3D=3D $LANG24[10]) && !empty ($LANG24[10]) &&
($type =3D=3D 'submission')) {
$display .=3D COM_refresh ($_CONF['site_admin_url'] . =
'/moderation.php');
} else {
$display .=3D COM_siteHeader('menu');
$display .=3D COM_showMessage($msg);
$display .=3D liststories($page);
$display .=3D COM_siteFooter();
}
echo $display;
}

?>
</SCRIPT>
</BLOCKQUOTE></SPAN></BODY></HTML>

------=_NextPart_000_00FB_01C3B9D9.2DCB0EF0--



--__--__--

_______________________________________________
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