Merge branch 'master' into storageareas

This commit is contained in:
Isaac Connor 2019-01-13 14:53:34 -05:00
commit fc7403fe3d
14 changed files with 121 additions and 61 deletions

View File

@ -91,7 +91,7 @@ Adjust permissions to the zm.conf file to allow web account to access it.
**Step 9:** Setup ZoneMinder service
::
::
systemctl enable zoneminder.service
@ -127,7 +127,23 @@ CTRL+o then [Enter] to save
CTRL+x to exit
**Step 12:** Start ZoneMinder
**Step 12:** Please check the configuration
Zoneminder 1.32.x
1. Check path of ZM_PATH in '/etc/zm/conf.d/zmcuston.conf' is ZM_PATH_ZMS=/zm/cgi-bin/nph-zms
::
cat /etc/zm/conf.d/zmcuston.conf
2. Check config of /etc/apache2/conf-enabled/zoneminder.conf has the same ScriptAlias /zm/cgi-bin that is configured
in ZM_PATH. The part /nph-zms has to be left out of the ScriptAlias
ScriptAlias /zm/cgi-bin "/usr/lib/zoneminder/cgi-bin"
<Directory "/usr/lib/zoneminder/cgi-bin">
::
cat /etc/apache2/conf-enabled/zoneminder.conf
**Step 13:** Start ZoneMinder
Reload Apache to enable your changes and then start ZoneMinder.
@ -136,7 +152,7 @@ Reload Apache to enable your changes and then start ZoneMinder.
systemctl reload apache2
systemctl start zoneminder
**Step 13:** Making sure ZoneMinder works
**Step 14:** Making sure ZoneMinder works
1. Open up a browser and go to ``http://hostname_or_ip/zm`` - should bring up ZoneMinder Console

View File

@ -100,12 +100,13 @@ class FfmpegCamera : public Camera {
void Initialise();
void Terminate();
static int FfmpegInterruptCallback(void*ctx);
int PrimeCapture();
int PreCapture();
int Capture( Image &image );
int CaptureAndRecord( Image &image, timeval recording, char* event_directory );
int PostCapture();
private:
static int FfmpegInterruptCallback(void*ctx);
};
#endif // ZM_FFMPEG_CAMERA_H

View File

@ -186,6 +186,8 @@ int LibvlcCamera::PrimeCapture() {
Error("Unable to create libvlc instance due to: %s", libvlc_errmsg());
return -1;
}
libvlc_log_set(mLibvlcInstance, LibvlcCamera::log_callback, NULL);
mLibvlcMedia = libvlc_media_new_location(mLibvlcInstance, mPath.c_str());
if ( mLibvlcMedia == NULL ) {
@ -214,6 +216,7 @@ int LibvlcCamera::PrimeCapture() {
return 0;
}
int LibvlcCamera::PreCapture() {
return 0;
}
@ -244,4 +247,28 @@ int LibvlcCamera::PostCapture() {
return 0;
}
void LibvlcCamera::log_callback(void *ptr, int level, const libvlc_log_t *ctx, const char *fmt, va_list vargs) {
Logger *log = Logger::fetch();
int log_level = Logger::NOLOG;
if ( level == LIBVLC_ERROR ) {
log_level = Logger::WARNING; // ffmpeg outputs a lot of errors that don't really affect anything.
//log_level = Logger::ERROR;
} else if ( level == LIBVLC_WARNING ) {
log_level = Logger::INFO;
//log_level = Logger::WARNING;
} else if ( level == LIBVLC_NOTICE ) {
log_level = Logger::DEBUG1;
//log_level = Logger::INFO;
} else if ( level == LIBVLC_DEBUG ) {
log_level = Logger::DEBUG3;
} else {
Error("Unknown log level %d", level);
}
if ( log ) {
char logString[8192];
vsnprintf(logString, sizeof(logString)-1, fmt, vargs);
log->logPrint(false, __FILE__, __LINE__, log_level, logString);
}
}
#endif // HAVE_LIBVLC

View File

@ -42,6 +42,8 @@ struct LibvlcPrivateData
};
class LibvlcCamera : public Camera {
private:
static void log_callback( void *ptr, int level, const libvlc_log_t *ctx, const char *format, va_list vargs );
protected:
std::string mPath;
std::string mMethod;
@ -59,9 +61,9 @@ public:
LibvlcCamera( int p_id, const std::string &path, const std::string &p_method, const std::string &p_options, int p_width, int p_height, int p_colours, int p_brightness, int p_contrast, int p_hue, int p_colour, bool p_capture, bool p_record_audio );
~LibvlcCamera();
const std::string &Path() const { return( mPath ); }
const std::string &Options() const { return( mOptions ); }
const std::string &Method() const { return( mMethod ); }
const std::string &Path() const { return mPath; }
const std::string &Options() const { return mOptions; }
const std::string &Method() const { return mMethod; }
void Initialise();
void Terminate();

View File

@ -942,6 +942,7 @@ void LocalCamera::Initialise() {
v4l2_std_id stdId;
memset(&input, 0, sizeof(input));
input.index = channel;
if ( vidioctl(vid_fd, VIDIOC_ENUMINPUT, &input) < 0 ) {
Fatal("Failed to enumerate input %d: %s", channel, strerror(errno));
@ -952,8 +953,8 @@ void LocalCamera::Initialise() {
}
stdId = standard;
if ( (input.std != V4L2_STD_UNKNOWN) && vidioctl( vid_fd, VIDIOC_S_STD, &stdId ) < 0 ) {
Fatal("Failed to set video standard %d: %s", standard, strerror(errno));
if ( (input.std != V4L2_STD_UNKNOWN) && (vidioctl(vid_fd, VIDIOC_S_STD, &stdId) < 0) ) {
Fatal("Failed to set video standard %d: %d %s", standard, errno, strerror(errno));
}
Contrast(contrast);

View File

@ -45,5 +45,6 @@ if ( !empty($_REQUEST['mid']) && canEdit('Monitors', $_REQUEST['mid']) ) {
$refreshParent = true;
}
} // end if action
$view = 'none';
} // end if $mid and canEdit($mid)
?>

View File

@ -61,7 +61,7 @@ span.noneCue {
}
#menuBar1 #replayControl {
margin: 0 4px 0 auto;
margin: auto 5px auto auto;
}
#menuBar1 div {

View File

@ -3,3 +3,8 @@
margin-left: 3px;
padding: 0px;
}
.SourceOptions input,
.SourcePath input {
width: 100%;
}

View File

@ -128,7 +128,7 @@ if ( ! $Event->Id() ) {
<?php
if ( canEdit('Events') ) {
?>
<div id="deleteEvent"><button type="button" onclick="deleteEvent()"><?php echo translate('Delete') ?></button></div>
<div id="deleteEvent"><button type="button" onclick="deleteEvent()" <?php echo $Event->Archived == 1 ? ' disabled="disabled" title="You cannot delete an archived event. Unarchive it first."' : '' ?>><?php echo translate('Delete') ?></button></div>
<div id="editEvent"><button type="button" onclick="editEvent()"><?php echo translate('Edit') ?></button></div>
<div id="archiveEvent"<?php echo $Event->Archived == 1 ? ' class="hidden"' : '' ?>><button type="button" onclick="archiveEvent()"><?php echo translate('Archive') ?></button></div>
<div id="unarchiveEvent"<?php echo $Event->Archived == 0 ? ' class="hidden"' : '' ?>><button type="button" onclick="unarchiveEvent()"><?php echo translate('Unarchive') ?></button></div>

View File

@ -36,7 +36,7 @@ foreach ( dbFetchAll('SELECT * FROM Filters ORDER BY Name') as $row ) {
$filterNames[$row['Id']] .= '&';
if ( isset($_REQUEST['Id']) && $_REQUEST['Id'] == $row['Id'] ) {
$filter = new Filter( $row );
$filter = new Filter($row);
}
}
if ( ! $filter ) {
@ -69,8 +69,8 @@ if (count($filter->terms()) > 0) {
if ( count($terms) ) {
for ( $i = 0; $i <= count($terms)-2; $i++ ) {
$obracketTypes[$i] = str_repeat( '(', $i );
$cbracketTypes[$i] = str_repeat( ')', $i );
$obracketTypes[$i] = str_repeat('(', $i);
$cbracketTypes[$i] = str_repeat(')', $i);
}
}
@ -130,28 +130,28 @@ $archiveTypes = array(
$focusWindow = true;
$storageareas = array( '' => 'All' );
$storageareas = array('' => 'All');
//$storageareas[0] = 'Default ' . ZM_DIR_EVENTS;
foreach ( dbFetchAll( 'SELECT Id,Name FROM Storage ORDER BY lower(Name) ASC' ) as $storage ) {
foreach ( dbFetchAll('SELECT Id,Name FROM Storage ORDER BY lower(Name) ASC') as $storage ) {
$storageareas[$storage['Id']] = $storage['Name'];
}
$weekdays = array();
for ( $i = 0; $i < 7; $i++ ) {
$weekdays[$i] = strftime( '%A', mktime( 12, 0, 0, 1, $i+1, 2001 ) );
$weekdays[$i] = strftime('%A', mktime(12, 0, 0, 1, $i+1, 2001));
}
$states = array();
foreach ( dbFetchAll( 'SELECT Id,Name FROM States ORDER BY lower(Name) ASC' ) as $state_row ) {
foreach ( dbFetchAll('SELECT Id,Name FROM States ORDER BY lower(Name) ASC') as $state_row ) {
$states[$state_row['Id']] = $state_row['Name'];
}
$servers = array();
$servers['ZM_SERVER_ID'] = 'Current Server';
$servers['NULL'] = 'No Server';
foreach ( dbFetchAll( 'SELECT Id,Name FROM Servers ORDER BY lower(Name) ASC' ) as $server ) {
foreach ( dbFetchAll('SELECT Id,Name FROM Servers ORDER BY lower(Name) ASC') as $server ) {
$servers[$server['Id']] = $server['Name'];
}
$monitors = array();
foreach ( dbFetchAll( 'select Id,Name from Monitors order by Name asc' ) as $monitor ) {
if ( visibleMonitor( $monitor['Id'] ) ) {
foreach ( dbFetchAll('SELECT Id,Name FROM Monitors ORDER BY Name ASC') as $monitor ) {
if ( visibleMonitor($monitor['Id']) ) {
$monitors[$monitor['Name']] = $monitor['Name'];
}
}
@ -168,7 +168,7 @@ xhtmlHeaders(__FILE__, translate('EventFilter') );
<div id="filterSelector"><label for="<?php echo 'Id' ?>"><?php echo translate('UseFilter') ?></label>
<?php
if ( count($filterNames) > 1 ) {
echo htmlSelect( 'Id', $filterNames, $filter->Id(), 'this.form.submit();' );
echo htmlSelect('Id', $filterNames, $filter->Id(), 'this.form.submit();');
} else {
?><select disabled="disabled"><option><?php echo translate('NoSavedFilters') ?></option></select>
<?php
@ -219,36 +219,36 @@ for ( $i=0; $i < count($terms); $i++ ) {
<?php
} else {
?>
<td><?php echo htmlSelect( "filter[Query][terms][$i][cnj]", $conjunctionTypes, $term['cnj'] ); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][cnj]", $conjunctionTypes, $term['cnj']); ?></td>
<?php
}
?>
<td><?php if ( count($terms) > 2 ) { echo htmlSelect( "filter[Query][terms][$i][obr]", $obracketTypes, $term['obr'] ); } else { ?>&nbsp;<?php } ?></td>
<td><?php echo htmlSelect( "filter[Query][terms][$i][attr]", $attrTypes, $term['attr'], "checkValue( this );" ); ?></td>
<td><?php if ( count($terms) > 2 ) { echo htmlSelect("filter[Query][terms][$i][obr]", $obracketTypes, $term['obr']); } else { ?>&nbsp;<?php } ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][attr]", $attrTypes, $term['attr'], 'checkValue(this);'); ?></td>
<?php
if ( isset($term['attr']) ) {
if ( $term['attr'] == 'Archived' ) {
?>
<td><?php echo translate('OpEq') ?><input type="hidden" name="filter[Query][terms][<?php echo $i ?>][op]" value="="/></td>
<td><?php echo htmlSelect( "filter[Query][terms][$i][val]", $archiveTypes, $term['val'] ); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $archiveTypes, $term['val']); ?></td>
<?php
} elseif ( $term['attr'] == 'DateTime' || $term['attr'] == 'StartDateTime' || $term['attr'] == 'EndDateTime') {
?>
<td><?php echo htmlSelect( "filter[Query][terms][$i][op]", $opTypes, $term['op'] ); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
<td>
<input type="text" name="filter[Query][terms][<?php echo $i ?>][val]" id="filter[Query][terms][<?php echo $i ?>][val]" value="<?php echo isset($term['val'])?validHtmlStr(str_replace('T', ' ', $term['val'])):'' ?>"/>
<script type="text/javascript">$j("[name$='\\[<?php echo $i ?>\\]\\[val\\]']").datetimepicker({timeFormat: "HH:mm:ss", dateFormat: "yy-mm-dd", maxDate: 0, constrainInput: false}); </script>
</td>
<?php
} elseif ( $term['attr'] == 'Date' || $term['attr'] == 'StartDate' || $term['attr'] == 'EndDate') {
} elseif ( $term['attr'] == 'Date' || $term['attr'] == 'StartDate' || $term['attr'] == 'EndDate' ) {
?>
<td><?php echo htmlSelect( "filter[Query][terms][$i][op]", $opTypes, $term['op'] ); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
<td>
<input type="text" name="filter[Query][terms][<?php echo $i ?>][val]" id="filter[Query][terms][<?php echo $i ?>][val]" value="<?php echo isset($term['val'])?validHtmlStr($term['val']):'' ?>"/>
<script type="text/javascript">$j("[name$='\\[<?php echo $i ?>\\]\\[val\\]']").datepicker({dateFormat: "yy-mm-dd", maxDate: 0, constrainInput: false}); </script>
<script type="text/javascript">$j("[name$='\\[<?php echo $i ?>\\]\\[val\\]']").datepicker({dateFormat: "yy-mm-dd", maxDate: 0, constrainInput: false});</script>
</td>
<?php
} elseif ( $term['attr'] == 'StartTime' || $term['attr'] == 'EndTime') {
} elseif ( $term['attr'] == 'StartTime' || $term['attr'] == 'EndTime' ) {
?>
<td><?php echo htmlSelect( "filter[Query][terms][$i][op]", $opTypes, $term['op'] ); ?></td>
<td>
@ -258,46 +258,46 @@ for ( $i=0; $i < count($terms); $i++ ) {
<?php
} elseif ( $term['attr'] == 'StateId' ) {
?>
<td><?php echo htmlSelect( "filter[Query][terms][$i][op]", $opTypes, $term['op'] ); ?></td>
<td><?php echo htmlSelect( "filter[Query][terms][$i][val]", $states, $term['val'] ); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $states, $term['val']); ?></td>
<?php
} elseif ( strpos($term['attr'], 'Weekday') !== false ) {
?>
<td><?php echo htmlSelect( "filter[Query][terms][$i][op]", $opTypes, $term['op'] ); ?></td>
<td><?php echo htmlSelect( "filter[Query][terms][$i][val]", $weekdays, $term['val'] ); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $weekdays, $term['val']); ?></td>
<?php
} elseif ( $term['attr'] == 'MonitorName' ) {
?>
<td><?php echo htmlSelect( "filter[Query][terms][$i][op]", $opTypes, $term['op'] ); ?></td>
<td><?php echo htmlSelect( "filter[Query][terms][$i][val]", $monitors, $term['val'] ); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $monitors, $term['val']); ?></td>
<?php
} elseif ( $term['attr'] == 'ServerId' || $term['attr'] == 'MonitorServerId' || $term['attr'] == 'StorageServerId' || $term['attr'] == 'FilterServerId' ) {
?>
<td><?php echo htmlSelect( "filter[Query][terms][$i][op]", $opTypes, $term['op'] ); ?></td>
<td><?php echo htmlSelect( "filter[Query][terms][$i][val]", $servers, $term['val'] ); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $servers, $term['val']); ?></td>
<?php
} elseif ( $term['attr'] == 'StorageId' ) {
?>
<td><?php echo htmlSelect( "filter[Query][terms][$i][op]", $opTypes, $term['op'] ); ?></td>
<td><?php echo htmlSelect( "filter[Query][terms][$i][val]", $storageareas, $term['val'] ); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][val]", $storageareas, $term['val']); ?></td>
<?php
} else {
?>
<td><?php echo htmlSelect( "filter[Query][terms][$i][op]", $opTypes, $term['op'] ); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
<td><input type="text" name="filter[Query][terms][<?php echo $i ?>][val]" value="<?php echo $term['val'] ?>"/></td>
<?php
}
} else {
?>
<td><?php echo htmlSelect( "filter[Query][terms][$i][op]", $opTypes, $term['op'] ); ?></td>
<td><?php echo htmlSelect("filter[Query][terms][$i][op]", $opTypes, $term['op']); ?></td>
<td><input type="text" name="filter[Query][terms][<?php echo $i ?>][val]" value="<?php echo isset($term['val'])?$term['val']:'' ?>"/></td>
<?php
}
?>
<td><?php if ( count($terms) > 2 ) { echo htmlSelect( "filter[Query][terms][$i][cbr]", $cbracketTypes, $term['cbr'] ); } else { ?>&nbsp;<?php } ?></td>
<td><?php if ( count($terms) > 2 ) { echo htmlSelect("filter[Query][terms][$i][cbr]", $cbracketTypes, $term['cbr']); } else { ?>&nbsp;<?php } ?></td>
<td>
<input type="button" onclick="addTerm( this )" value="+"/>
<input type="button" onclick="delTerm( this )" value="-" <?php echo count($terms) == 1 ? 'disabled' : '' ?>/>
<input type="button" onclick="addTerm(this)" value="+"/>
<input type="button" onclick="delTerm(this)" value="-" <?php echo count($terms) == 1 ? 'disabled' : '' ?>/>
</td>
</tr>
<?php
@ -387,7 +387,6 @@ if ( ZM_OPT_MESSAGE ) {
?>
<p>
<label><?php echo translate('FilterExecuteEvents') ?></label>
<input type="checkbox" name="filter[AutoExecute]" value="1"<?php if ( $filter->AutoExecute() ) { ?> checked="checked"<?php } ?>/>
<input type="text" name="filter[AutoExecuteCmd]" value="<?php echo (null !==$filter->AutoExecuteCmd())?$filter->AutoExecuteCmd():'' ?>" maxlength="255" onchange="updateButtons( this )"/>
</p>

View File

@ -18,42 +18,43 @@
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
if ( !canEdit( 'Monitors' ) ) {
if ( !canEdit('Monitors') ) {
$view = 'error';
return;
}
$monitor = dbFetchMonitor( $_REQUEST['mid'] );
$monitor = dbFetchMonitor($_REQUEST['mid']);
$focusWindow = true;
xhtmlHeaders(__FILE__, translate('Function')." - ".validHtmlStr($monitor['Name']) );
xhtmlHeaders(__FILE__, translate('Function').' - '.validHtmlStr($monitor['Name']));
?>
<body>
<div id="page">
<div id="header">
<h2><?php echo translate('Function')." - ".validHtmlStr($monitor['Name']) ?></h2>
<h2><?php echo translate('Function').' - '.validHtmlStr($monitor['Name']) ?></h2>
</div>
<div id="content">
<form name="contentForm" id="contentForm" method="post" action="<?php echo $_SERVER['PHP_SELF'] ?>">
<input type="hidden" name="view" value="none"/>
<input type="hidden" name="view" value="function"/>
<input type="hidden" name="action" value="function"/>
<input type="hidden" name="mid" value="<?php echo $monitor['Id'] ?>"/>
<p>
<select name="newFunction">
<?php
foreach ( getEnumValues( 'Monitors', 'Function' ) as $optFunction ) {
foreach ( getEnumValues('Monitors', 'Function') as $optFunction ) {
?>
<option value="<?php echo $optFunction ?>"<?php if ( $optFunction == $monitor['Function'] ) { ?> selected="selected"<?php } ?>><?php echo translate('Fn'.$optFunction) ?></option>
<?php
}
?>
</select>
<label for="newEnabled"><?php echo translate('Enabled') ?></label><input type="checkbox" name="newEnabled" id="newEnabled" value="1"<?php if ( !empty($monitor['Enabled']) ) { ?> checked="checked"<?php } ?>/>
<label for="newEnabled"><?php echo translate('Enabled') ?></label>
<input type="checkbox" name="newEnabled" id="newEnabled" value="1"<?php if ( !empty($monitor['Enabled']) ) { ?> checked="checked"<?php } ?>/>
</p>
<div id="contentButtons">
<input type="submit" value="<?php echo translate('Save') ?>"/>
<input type="button" value="<?php echo translate('Cancel') ?>" onclick="closeWindow()"/>
<button type="submit" value="Save"><?php echo translate('Save') ?></button>
<button type="button" onclick="closeWindow()"><?php echo translate('Cancel') ?></button>
</div>
</form>
</div>

View File

@ -879,9 +879,12 @@ include('_monitor_source_nvsocket.php');
<?php
} elseif ( $monitor->Type() == 'Ffmpeg' || $monitor->Type() == 'Libvlc' ) {
?>
<tr><td><?php echo translate('SourcePath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" size="36"/></td></tr>
<tr class="SourcePath"><td><?php echo translate('SourcePath') ?></td><td><input type="text" name="newMonitor[Path]" value="<?php echo validHtmlStr($monitor->Path()) ?>" /></td></tr>
<tr><td><?php echo translate('RemoteMethod') ?>&nbsp;(<?php echo makePopupLink('?view=optionhelp&amp;option=OPTIONS_RTSPTrans', 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><?php echo htmlSelect( "newMonitor[Method]", $rtspFFMpegMethods, $monitor->Method() ); ?></td></tr>
<tr><td><?php echo translate('Options') ?>&nbsp;(<?php echo makePopupLink( '?view=optionhelp&amp;option=OPTIONS_'.strtoupper($monitor->Type()), 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td><td><input type="text" name="newMonitor[Options]" value="<?php echo validHtmlStr($monitor->Options()) ?>" size="36"/></td></tr>
<tr class="SourceOptions">
<td><?php echo translate('Options') ?>&nbsp;(<?php echo makePopupLink( '?view=optionhelp&amp;option=OPTIONS_'.strtoupper($monitor->Type()), 'zmOptionHelp', 'optionhelp', '?' ) ?>)</td>
<td><input type="text" name="newMonitor[Options]" value="<?php echo validHtmlStr($monitor->Options()) ?>"/></td>
</tr>
<?php
}
if ( $monitor->Type() != 'NVSocket' && $monitor->Type() != 'WebSite' ) {

View File

@ -19,7 +19,11 @@
//
$optionHelpIndex = preg_replace( '/^ZM_/', '', $_REQUEST['option'] );
$optionHelpText = !empty($OLANG[$optionHelpIndex])?$OLANG[$optionHelpIndex]['Help']:$config[$_REQUEST['option']]['Help'];
if ( !empty($OLANG[$optionHelpIndex]) ) {
$optionHelpText = $OLANG[$optionHelpIndex]['Help'];
} else {
$optionHelpText = dbFetchOne('SELECT Help FROM Config WHERE Name=?', 'Help', array($_REQUEST['option']) );
}
$optionHelpText = validHtmlStr($optionHelpText);
$optionHelpText = preg_replace( "/~~/", "<br/>", $optionHelpText );
$optionHelpText = preg_replace( "/\[(.+)\]\((.+)\)/", "<a href=\"$2\" target=\"_blank\">$1</a>", $optionHelpText );