Posted on

using filebeat to watch a log

In filebeat.yml,  add the file you are watching to the ‘paths’ section as follows:

paths:
- /var/log/my.log
### Logstash as output
logstash:
# The Logstash hosts
hosts: ["192.168.0.1:5044"]

This will forward the contents of my.log to logstash.

If, like me, you like to keep traffic and  load to a minimum,  then you can add this to filebeat.yml:

scan_frequency: 180s

And if, in your logstash config, you want to be able to know which input you are handing, then define the ‘type’ as follows:

document_type:  mylog

 

Posted on

from script to service

This is a handy wrapper to make that quickly written script behave like a ‘service’.  This is reprinted here and was originally written by Tomas Nevar.

It has been amended to run watchlog.pl.

#!/bin/sh
#############################################
# AUTHOR:   Tomas Nevar (tomas@lisenet.com)
# NAME:     init-service-template
# VERSION:  1.0
# DATE:     01/02/2016 (dd/mm/yy)
# LICENCE:  Copyleft free software
#############################################
#
# init-service-template:  Starts an init daemon
#
# chkconfig: 2345 99 01
# description: This is a template daemon.
#
# processname: $PROCESS_NAME
# pidfile: /var/run/$PROCESS_NAME.pid
#

### BEGIN INIT INFO
# Provides: $PROCESS_NAME
# Required-Start: $network
# Required-Stop: $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: Starts the $PROCESS_NAME daemon
# Description: This is a template daemon.
### END INIT INFO

#############################################
# Revision History
#
# Version 1.0 - Tomas Nevar
# Change notes: Initial release, service calls a wrapper script.
#
#############################################

#
### These variables need setting
#
PROCESS_NAME="watchlog.pl";
PROCESS_USER="root";
PROCESS_PID_PATH="/var/run";
PROCESS_LOG_PATH="/var/log/"$PROCESS_NAME"";
PROCESS_SCRIPT="/usr/local/watchlog.pl";

# These are generated using the values above
PROCESS_PID=""$PROCESS_PID_PATH"/"$PROCESS_NAME".pid";
PROCESS_LOG=""$PROCESS_LOG_PATH"/"$PROCESS_NAME".log";

# Do not change this
RETVAL="0";
CLR_RED=$(tput setaf 1);
CLR_GREEN=$(tput setaf 2);
CLR_RESET=$(tput sgr0);

#############################################
#
### Sanity checks
#

# Ensure the $PROCESS_USER exists on the system
id -u "$PROCESS_USER" >/dev/null 2>&1;
RETVAL=$?;
if [ ! "$RETVAL" -eq 0 ]; then
echo -e "ERROR: "$PROCESS_USER" user does not exist on the system. Try running:
sudo useradd -m -s "$(echo $SHELL)" "$PROCESS_USER"";
exit 1;
fi

# Ensure the log folder $PROCESS_LOG_PATH exists
# and is owned by the $PROCESS_USER user.
if [ ! -d "$PROCESS_LOG_PATH" ]; then
mkdir -p "$PROCESS_LOG_PATH";
fi
chown -R "$PROCESS_USER":root "$PROCESS_LOG_PATH";

# Ensure the wrapper script $PROCESS_SCRIPT
# exists and is executable.
if [ ! -x "$PROCESS_SCRIPT" ]; then
echo "ERROR: Script "$PROCESS_SCRIPT" does not exits or is not executable.";
exit 1;
fi
#############################################
status() {
if [ -f "$PROCESS_PID" ]; then
RUNNING_PID=$(cat $PROCESS_PID);
IS_RUNNING=$(ps -ef|grep "$RUNNING_PID"|grep "$PROCESS_SCRIPT"|wc -l);
if [ "$IS_RUNNING" -gt 0 ]; then
echo ""$PROCESS_NAME" (pid "$RUNNING_PID") is running...";
else
echo "ERROR: "$PROCESS_NAME" has died but pid "$RUNNING_PID" exists. Try running:";
echo " sudo rm -f "$PROCESS_PID"";
RETVAL=1;
exit 1;
fi
else
IS_RUNNING=$(ps -ef|grep "$PROCESS_SCRIPT"|grep -v grep|wc -l);
if [ "$IS_RUNNING" -gt 0 ]; then
echo "ERROR: "$PROCESS_NAME" is running without a pid file";
RETVAL=1;
exit 1;
else
if [ "$1" == "start" ]; then
echo "ERROR: "$PROCESS_NAME" has failed to "$1"";
RETVAL=1;
exit 1;
fi
if [ "$1" == "restart" ]; then
echo "ERROR: "$PROCESS_NAME" has failed to "$1"";
RETVAL=1;
exit 1;
fi
if [ "$1" == "stop" ]; then
echo ""$PROCESS_NAME" is stopped";
RETVAL=999;
else
echo ""$PROCESS_NAME" is stopped";
RETVAL=999;
fi
fi
fi
}

start() {
# Only start the service if it is stopped.
# RETVAL is set to '999' if the service is stopped.
status >/dev/null 2>/dev/null;
if [ "$RETVAL" -eq 1 ]; then
echo "WARN: Something went wrong...";
exit 1;
fi
if [ ! "$RETVAL" -eq 999 ]; then
echo "Starting "$PROCESS_NAME": ";
exit 0;
fi

echo -n $"Starting "$PROCESS_NAME": "
MYCMD=""$PROCESS_SCRIPT" > "$PROCESS_LOG" 2>&1 & echo \$!";
#echo "$MYCMD";
su - "$PROCESS_USER" -c "$MYCMD" > "$PROCESS_PID";
RETVAL=$?;
if [ "$RETVAL" -eq 0 ]; then
echo -e "\t\t\t\t [$CLR_GREEN OK $CLR_RESET]";
fi
}

stop() {
echo -n $"Stopping "$PROCESS_NAME": "
if [ -f "$PROCESS_PID" ]; then
RUNNING_PID=$(cat $PROCESS_PID);
IS_RUNNING=$(ps -ef|grep "$RUNNING_PID"|grep "$PROCESS_SCRIPT"|wc -l);
if [ "$IS_RUNNING" -gt 0 ]; then
# Kill by program group id rather than PID
# to be sure all child processes are killed.
PGID=$(ps -o pgid= "$RUNNING_PID"|tr -d ' ');
kill -9 -"$PGID";
RETVAL=$?;
fi
rm -f "$PROCESS_PID";
if [ "$RETVAL" -eq 0 ]; then
echo -e "\t\t\t\t [$CLR_GREEN OK $CLR_RESET]";
fi
else
IS_RUNNING=$(ps -ef|grep "$PROCESS_SCRIPT"|grep -v grep|wc -l);
if [ "$IS_RUNNING" -gt 0 ]; then
echo -e "\t\t\t\t [$CLR_RED FAILED $CLR_RESET]";
echo "No pid file and "$PROCESS_NAME" is running. Try running:";
echo " sudo ps -ef|grep "$PROCESS_NAME"";
else
echo -e "\t\t\t\t [$CLR_RED FAILED $CLR_RESET]";
fi
fi
}

# See how we were called.
case "$1" in
start)
start
;;
stop)
stop
;;
status)
status
;;
restart)
stop
start
status
;;
*)
echo $"Usage: $0 {start|stop|status|restart}"
exit 1;
esac

 

Posted on

watching logs with perl

When you have a log file with lots of unpredictably formatted entries, it can be difficult to come up with a nice grok filter to parse it. This is frustrating if you only want a small amount of data from a very big log.
Below is a quickly written Perl script to watch a log file and print out a summary of the number of times a GET request, indicated with ‘q=’, was made for each 10 minute interval.
This gave me a nice summary.log which looked like this:

hits-per-10m=35,server=myservername,logdate=201701221032,year=2017,month=01,date=22,hour=10,minute=32,second=45


#!/usr/bin/perl
# Watch a log and write key-value pairs to a file

use File::Tail;
use URI::Escape ;

$file = File::Tail->new("/var/log/myfile.log");
%months = qw( Jan 1 Feb 2 Mar 3 Apr 4 May 5 Jun 6 Jul 7 Aug 8 Sep 9 Oct 10 Nov 11 Dec 12);
($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime();
$year=$year+1900;
$hold = int($min / 10);
$count=0;
$lasthour = 99;

while (defined(my $line= $file->read)) {
$line=~s/\s+/ /g;
@parts= split /[ ]/,$line;
# in my log, I could parse the values from the data line as follows
$server=$parts[3];
$month=$months{$parts[0]};
$date=$parts[1];
($hour,$min,$sec) = split /\:/, $parts[2];
($ipaddr,$port) = split /\:/,$parts[5];
# here I want to count the number of values for each 10 minute interval
# the problem with logs is that there may not be a log line for every minute
## so I use $hold to indicate whether to hold the data or write it to a file
## And in case the hour has changed since the last log entry, this is also checked
if ($lasthour != $hour) {
$hold = int($min / 10);
}
$lasthour = $hour;
if ( ($min >= 0) && ($min <=9) ){
if ($hold == 0 ) {
&printCount ;
$hold = 1;
}
}
if ( ($min >= 10) && ($min <=19) ){
if ($hold <= 1 ) {
&printCount ;
$hold = 2;
}
}
if ( ($min >= 20) && ($min <=29) ){
if ($hold <= 2 ) {
&printCount ;
$hold = 3;
}
}
if ( ($min >= 30) && ($min <=39) ){
if ($hold <= 3 ) {
&printCount ;
$hold = 4;
}
}
if ( ($min >= 40) && ($min <=49) ){
if ($hold <= 4 ) {
&printCount ;
$hold = 5;
}
}
if ( ($min >= 50) && ($min <=59) ){
if ($hold <= 5 ) {
&printCount ;
$hold = 6;
}
}
$count++;
$lastmin = $min;
# check if the log entry has the value you are counting
# in this case I was looking for the search term which followed 'q='
if ($line =~ /GET/) {
($junk,$q) = split /[[\&\?]q=/, $line;
($q, $junk) = split /[\& ]/, $q;
$q = uri_unescape($q);
# remove any commas because I will be using them as separators
$q =~s/\,/ /g;
}
} # end while

sub printCount {
# print the time and the count of searches for the 10 minute period
open (OUT,">>/var/log/summary.log");
print OUT "hits-per-10m=$count,server=$server,logdate=$year$month$date$hour$min,year=$year,month=$month,date=$date,hour=$hour,minute=$min,second=$sec\n";
close OUT;
$count = 0;
}
 

Posted on

dynamically creating thumbnails using PHP and ffmpeg

You can create a thumbnail for a video file using mod_rewrite and php.

Let’s start with a URL to your server that is expecting an image to be returned.

http://www.myserver.com:8000/Image.svc/filename.png?file=videofile.mp4&frame=7500&width=360&height=160

If the image already exists, return it, if not, then create if from the video file frame using the height and width specified.
Add a section to Apache’s config file that is like this:

Listen 192.168.101.1:8000

<VirtualHost 192.168.101.1:8000>
 DocumentRoot "/var/www/html/thumbnails"
 # LogLevel alert rewrite:trace3
 <Directory "/var/www/html/thumbnails/Image.svc">
 RewriteEngine on
 RewriteCond %{REQUEST_FILENAME} !-f
 RewriteRule ^(.+)\.png$ gen-thumbnail.php [L,QSA]

This says to call gen-thumbnail.php if the requested file does not exist.

<?php
// This script is called by Apache httpd
// using the mod_rewrite engine
// for the condition 'file not found'
// It creates an image file and passes it back to the browser
 
// Get the full url
// If this fails, check that the server has the php module enabled
 
if (!isset($_SERVER['REQUEST_URI']))
{
       $_SERVER['REQUEST_URI'] = substr($_SERVER['PHP_SELF'],1 );
       if (isset($_SERVER['QUERY_STRING'])) { $_SERVER['REQUEST_URI'].='?'.$_SERVER['QUERY_STRING']; }
}
 
// Parse the url
$url = $_SERVER['REQUEST_URI'];
$path=(parse_url($url, PHP_URL_PATH));
$src = "http://$_SERVER[HTTP_HOST]$_SERVER[REQUEST_URI]";
$query=(parse_url($url, PHP_URL_QUERY));
$query =  urldecode($query);
$query = str_replace('&amp;','&',$query);
 
// Check that there is a file name
if(isset($_GET['file'])) {
  $videofile = $_GET['file'];
} else {
  print "No source video file, exiting.";
  exit;
}
 
// Set some defaults for width and height if not specified
if(isset($_GET['width'])) {
  $width = $_GET['width'];
} else {
  $width = '350';
}
if(isset($_GET['height'])) {
  $height = $_GET['height'];
} else {
  $height = '350';
}
 
// The thumbnail is generated from this frame, or a default if not specified
if(isset($_GET['frame'])) {
  $frame = $_GET['frame'];
} else {
  $frame = '3350';
}
 
parse_str($query);
$thumbSize=$width.'x'.$height;
 
// Build the ffmpeg command to generate video thumbnail
$ffmpeg_installation_path = "/bin/ffmpeg";
$videofile =  urldecode($videofile);
// Amend videofile is the videoa are stored in a different directory to the thumbnails
$videofile = escapeshellarg($videofile);
$thumbnail = "/var/www/html/thumbnails".$path;
$frameexp = "'select=gte(n\,".$frame.")'";
 
$cmd = "{$ffmpeg_installation_path}  -i {$videofile}  -an -vf {$frameexp}  -vframes 1  -s {$thumbSize} -r 1 -y -vcodec mjpeg -f image2 {$thumbnail} 2>&1";
//echo $cmd;
 
// Execute the ffmpeg command
if ($path != '/Image.svc/gen-thumbnail.php') {
   exec($cmd, $output, $retval);
}
 
// Check if a file has been created
if (file_exists($thumbnail)) {
  if (filesize ($thumbnail)>0)
    {
     $fp = fopen($thumbnail, 'rb');
    // send the right headers
     header("Content-Type: image/png");
     header("Content-Length: " . filesize($thumbnail));
    // dump the picture and stop the script
    fpassthru($fp);
    exit;
    }
}
 
// End of script

 

Posted on

elasticsearch – updating from version 1.x to 5.x

One way to update from version 1 to version 5 is to go via version 2. Here  are some steps that can be used to achieve this:

  • Install version 2.4.3 of elasticsearch on a spare server. You can download this from elasticsearch’s website.
  • Copy the data for the indices from your version 1 server to your new version 2.4 server.  You can use rsync to do this, even if the v1 server is still running. The indices are usually found under  /var/lib/elasticsearch/ if you have the defaults.
  • Start the v2.4 elasticsearch and verify it can see the data. One way to do this is:  curl 127.0.0.1:9200/_cat/indices?v
  • Delete any index you will not be using in your version 5 elasticsearch server. For each unwanted index:  curl -XDELETE 127.0.0.1:9200/OLD-UNWANTED-INDEX
  • Now convert the index you do want to be in version 2 format. This is done by reindexing. It is useful to create the new index with the attributes that you want first:


# Create a new empty index:
curl -XPUT '127.0.0.1:9200/NEW-INDEX-v2' -d '
{
"settings" : {
"index" : {
"number_of_shards" : 1,
"number_of_replicas" : 0
}
}
}'

# Copy the contents of the v1 index into the new index using the reindex api:
curl -XPOST '127.0.0.1:9200/_reindex' -d '
{
"conflicts": "proceed",
"source": {
"index": "OLD-INDEX-v1"
},
"dest": {
"index": "NEW-INDEX-v2"
}
} '
'

  • For a large index, this is going to be slow. If it appears to have failed, it is worth checking that it is not still running in the background before you give up!
  • To check progress, use this command: curl 127.0.0.1:9200/_cat/indices?v
  • When it is complete, delete the copy of the v1 index eg curl -XDELETE 127.0.0.1:9200/OLD-INDEX-v1
  • Now install v5 of elasticsearch and copy the v2 format index files to the new server (or upgrade from v2 to v5 on the same server).
  • As before, check that the v5 elasticsearch server can see the v2 index:  curl 127.0.0.1:9200/_cat/indices?v
  • Reindex the v2 format files to v5 by repeating the steps as before


# Create a new empty index:
curl -XPUT '127.0.0.1:9200/NEW-INDEX-v5' -d '
{
"settings" : {
"index" : {
"number_of_shards" : 2,
"number_of_replicas" : 1
}
}
}'

# Copy the contents of the v2 index into the new v5 index using the reindex api:
curl -XPOST '127.0.0.1:9200/_reindex' -d '
{
"conflicts": "proceed",
"source": {
"index": "NEW-INDEX-v2"
},
"dest": {
"index": "NEW-INDEX-v5"
}
} '
'

Repeat for any other indices you are upgrading and delete the old v2 indices when this is complete.

Posted on

Send Nagios alerts to Slack

A simple Perl script to send a Slack message summarising the over-night Nagios alerts.

## Nagios to Slack reporter
# Read Nagios log and send to summary to slack
# This module should be run from crontab# eg.30 08 * * 1, 2, 3, 4, 5 / usr / local / nagios / libexec / nagios - slack.pl
# to send a message to Slack showing the overnight issues
# Note: Nagios logs usually roll at midnight# so running this at 8:30 am will send a listing of issues
# from midnight to 8:30 am to Slack.
## Martin Jones## Version 1.0.0#

$ENV { 'PERL_LWP_SSL_VERIFY_HOSTNAME'} = 0;

use Net::SSL();
use Date::Manip;
use Time::Local;
use LWP::UserAgent;

# Put your own Slack api token here
my $slackurl = 'https://slack.com/api/chat.postMessage?token=xoxp-ZZZZZZZZZZ-YYYYYYYY-XXXXXXXXXXX-5dc5ac753b&channel=operations&username=nagios&parse=full&text=';

#use current time
$epoc = time();

# or choose a set time today
# ($sec, $min, $hour, $day, $month, $year, $wday, $yday, $isdst) = localtime();
# $hour = 10;
# $min = 30;
# Calculate 10:30 am today as an epoch value
# $epoc = timelocal($sec, $min, $hour, $day, $month - 1, $year);

# Read the log looking for alerts
open(LOG, "/usr/local/nagios/var/nagios.log");
while ($line = < LOG > ) {
@values = split / /,$line;
if (substr($values[0], 0, 1) eq "[") {
$values[0] = ~s/[\[\]]//g;
}
if ($values[0] < $epoc) {
if ($line = ~/SERVICE ALERT/) {
if (($line = ~/WARNING/) || ($line = ~/CRITICAL/)) {
if ($line = ~/HARD/) {
$realTime = localtime($values[0]);
@parts = split /\s+/,$realTime;
push @alertTime, substr($parts[3], 0, -3);
push @latest, $line;
}
}
}
}
} # end while
close LOG;
# Display a maximum of 10 alerts( in case it 's been a bad day)
if ($#latest > 9) {
$size = 9;
} else {
$size = $#latest;
}

$body = "Recent alerts: ";
for ($i = 0; $i <= $size; $i++) {
$line = pop @latest;
$alertTime = pop @alertTime;
@values = split /;/,$line;
($spare, $host) = split /:/, $values[0];
$body .= $host." ".$alertTime." ".$values[1]."; ";
}
if ($body eq "'Recent alerts: ") {
$body = "'No new alerts.";
}
$slackurl .= $body;
$slackresponse = http_request($slackurl);

sub http_request {
my $ua; my $req; my $res;
my $geturl = shift;
if (not defined $geturl or $geturl eq "") {
warn "No URL defined for http_request\n";
return 0;
}
$ua = LWP::UserAgent -> new(ssl_opts => {verify_hostname => 0}, timeout => 180, );
$ua -> env_proxy;
$ua -> agent('Mozilla/5.0');
$req = HTTP::Request -> new(GET => $geturl);
# send request
$res = $ua -> request($req);
# check the outcome
if ($res -> is_success) {
return $res -> decoded_content;
} else {
print "Error: ".$res -> status_line."\n";
return 0;
}
}

Posted on

reverse your wordpress posts

This WordPress plugin was written for a blogger who kept a diary and wanted readers to be able to start viewing the posts from the beginning.

As is often the case with WordPress, finding the right hook to call is the hardest part!

 

<?php
/*
Plugin Name: mailpony_reverse
Plugin URI: http://www.mailpony.com
Description: Reverse Order of Posts
Author: Martin Jones
Author URI: http://www.mailpony.com
Version: 1.0
*/
define('mailponyPATH', plugin_dir_path(__FILE__));
define('mailponyURL', plugins_url('', __FILE__));
add_action('init', 'mailpony_reverse_init');

function mailpony_reverse_init()
{
$orderby = $_COOKIE['display_order'];
if (!(isset($_REQUEST['reverse'])))
{
$_REQUEST['reverse'] = "";
}

if ($orderby == '')
{
if ($_REQUEST['reverse'] == 'reverse')
{
$orderby = "ASC";
}
else
{
$orderby = "DESC";
}

mailpony_cookie($orderby);
return;
}

if ($_REQUEST['reverse'] == 'reverse')
{
if ($orderby == 'ASC')
{
$orderby = mailpony_cookie('DESC');
}
else
{
$orderby = mailpony_cookie('ASC');
}
}
}

add_filter('pre_get_posts', 'mailpony_pre_get_posts');

function mailpony_pre_get_posts($query)
{

// Check if the query is for home and alter only the primary query
// if($query->is_home && $query->is_main_query())
// Query was for home, then set order

$order = $_COOKIE['display_order'];

// $order="ASC";

$query->set(‘order’, $order);
}

add_filter('posts_orderby', 'mailponyOrderPosts', 1, 2);

// function mailponyOrderPosts()

function mailponyOrderPosts($orderBy, $query)
{

// global $orderBy;

$order = $_COOKIE['display_order'];
if ($order == 'DESC')
{
$orderBy = preg_replace('/ASC/', 'DESC', $orderBy);
}
else
{
$orderBy = preg_replace('/DESC/', 'ASC', $orderBy);
}

$query->set('order', $order);
return ($orderBy);
}

// Runs before the posts are fetched

add_action('widgets_init', 'mailpony_reverse_widget_register', 19);

function mailpony_reverse_widget_register()
{
register_widget('mailpony_reverse_widget');
}

class mailpony_reverse_widget extends WP_Widget

{

// process the new widget

function mailpony_reverse_widget()
{
$widget_ops = array(
'classname' => 'mailpony_reverse_widget',
'description' => 'General display widget.'
);
$this->WP_Widget('mailpony_reverse_widget', 'mailpony reverse', $widget_ops);
}

// build the widget settings form

function form($instance)
{
$reverseimage = mailponyURL . "/reverse.jpg";
echo '<p> <input type="image" src="' . $reverseimage . '" name="Reverse chronological order" />';
echo '</p>';
}

// save the widget settings

function update($new_instance, $old_instance)
{
$instance = $old_instance;

// $instance['gen_reverse'] = strip_tags($new_instance['gen_reverse']);
// $instance['gen_reverse'] = $new_instance['gen_reverse'];

return $instance;
}

// display the widget

function widget($args, $instance)
{
extract($args);

// $orderby = mailpony_cookie();

echo $before_widget;
$reverseimage = mailponyURL . "/reverse.jpg";
if (!isset($_REQUEST['p']))
{
$_REQUEST['p'] = '';
}

if (!isset($_REQUEST['page_id']))
{
$_REQUEST['page_id'] = '';
}

if ($_REQUEST['p'] == '')
{
$_REQUEST['p'] = $_REQUEST['page_id'];
}

if ($_REQUEST['page_id'] == '')
{
$_REQUEST['page_id'] = $_REQUEST['p'];
}

$page_id = $_REQUEST['p'];
$newform = home_url() . "/" . $page_id;
$output = '<form name=formreverse action=' . $newform . ' method=post>';
$output.= '<p><input type=image src="' . $reverseimage . '" alt="Reverse chronological order" onclick=submit(this.form)/>';
$output.= '<input type=hidden name="reverse" value="reverse">';
$output.= '';
$output.= '</form>';
echo $output;
echo $after_widget;
}
}

function mailpony_cookie($order)
{
$cookie_name = "display_order";
$ret = setcookie($cookie_name, $order, 0, COOKIEPATH, COOKIE_DOMAIN);
$_COOKIE['display_order'] = $order;
$_REQUEST['p'] = '';
$_REQUEST['page'] = $_REQUEST['p'];
$_REQUEST['page_id'] = $_REQUEST['p'];
return $order;
}

?>

 

Posted on

featured links wordpress widget

This is a WordPress widget, which means that when this plugin is activated, you can drag and drop this functionality in to the place in the theme where you want to see it.

You define a list and it outputs a chosen number of them, which can be in a random order and entries you want to have more exposure can be given a higher weight.

Originally, this was written to allow links to featured posts to appear on the sidebar. It has also been used to produce links to Youtube videos.  It could be used for advert links, etc.

<?php
/*
Plugin Name: mailpony_featured
Plugin URI: http://www.mailpony.com/
Description: mailpony plugin
Version: 1.0
Author: Martin Jones
Author URI: http://www.mailpony.com
License: GPL
*/
add_action('widgets_init', 'mailpony_widget_register', 19);
$GLOBALS["maxdisplay"] = 45;

function mailpony_widget_register()
{
register_widget('mailpony_widget_general');
}

class mailpony_widget_general extends WP_Widget

{

// process the new widget

function mailpony_widget_general()
{
$widget_ops = array(
'classname' => 'mailpony_widget_general',
'description' => 'General display widget.'
);
$this->WP_Widget('mailpony_widget_general', 'mailpony featured', $widget_ops);
}

// build the widget settings form

function form($instance)
{
echo '<p>Title:(or leave blank) <input class="widefat" name="';
echo $this->get_field_name('gen_title');
echo '" type="text" value="';
echo $instance['gen_title'];
echo '"/></p>';
echo '<p>Random:<select name="';
echo $this->get_field_name('gen_random');
echo '"><option value="No" ';
selected($instance['gen_random'], 'No');
echo '>No</option><option value="Yes" ';
selected($instance['gen_random'], 'Yes');
echo '>Yes</option></select></p>';
echo '<p>Layout:<select name="';
echo $this->get_field_name('gen_layout');
echo '"><option value="Wide" ';
selected($instance['gen_layout'], 'Wide');
echo '>Wide</option><option value="Narrow" ';
selected($instance['gen_layout'], 'Narrow');
echo '>Narrow</option></select></p>';
echo '<p>Links to Display:<select name="';
echo $this->get_field_name('gen_links');
echo '">';
for ($i = 1; $i < $GLOBALS["maxdisplay"]; $i++)
{
echo '<option value="';
echo $i;
echo '"';
selected($instance['gen_links'], $i);

// echo $i;

echo '>';
echo $i;
echo '</option>';
}

echo '</select></p><p>';
echo 'Links: ';
for ($i = 1; $i < $GLOBALS["maxdisplay"]; $i++)
{
echo '</p>';
echo '<p>' . $i . '. Weight(1-10) :';

// this is the weight field

echo '<input name="';
$weight = 'weight' . $i;
echo $this->get_field_name($weight);
echo ' type="text" value="';

// echo esc_attr($weight);

echo $instance[$weight];
echo '" maxlength=2 width=2/>';

// this is the link itself

echo '<input size="50" name="';
$gen_link = 'gen_link' . $i;
echo $this->get_field_name($gen_link);
echo ' type="text" value="';

// echo esc_attr($gen_link);

echo $instance[$gen_link];
echo '" maxlength=999/>';
}
}

// save the widget settings

function update($new_instance, $old_instance)
{
$instance = $old_instance;
$instance['gen_title'] = strip_tags($new_instance['gen_title']);
$instance['gen_links'] = strip_tags($new_instance['gen_links']);
for ($i = 1; $i <= $GLOBALS["maxdisplay"]; $i++)
{
$gen_link = 'gen_link' . $i;
$weight = 'weight' . $i;
$instance[$gen_link] = $new_instance[$gen_link];
$instance[$weight] = $new_instance[$weight];
}

$instance['gen_random'] = $new_instance['gen_random'];
$instance['gen_layout'] = $new_instance['gen_layout'];
return $instance;
}

// display the widget

function widget($args, $instance)
{
extract($args);
$numbers = array();
$display_me = array();
if ($instance['gen_random'] != 'Yes')
{

// just return the top n entries
// that do not have a weight of 0

for ($i = 1; $i <= $GLOBALS["maxdisplay"]; $i++)
{
if ($selected == $instance['gen_links'])
{
break;
}

$genlink = 'gen_link' . $i;
$weight = 'weight' . $i;
if ($instance[$genlink] != '')
{
if (($instance[$weight] != '') or ($instance[$weight] != 0))
{
array_push($display_me, $i);
$selected++;
}
}
}

//

}

if ($instance['gen_random'] == 'Yes')
{
for ($i = 1; $i <= $GLOBALS["maxdisplay"]; $i++)
{
$genlink = 'gen_link' . $i;

// create a weighted array

$weight = 'weight' . $i;
if ($instance[$genlink] != '')
{
if (($instance[$weight] != '') or ($instance[$weight] != 0))
{
for ($j = 1; $j <= $instance[$weight]; $j++)
{
array_push($numbers, $i);
}
}
}
}

shuffle($numbers);

// now choose n random entries from the weighted array

$display_me = array_rand($numbers, $instance['gen_links']);
$display_me = array_unique($display_me);
shuffle($display_me);
while (count($display_me) < $instance['gen_links'])
{
$r = rand(1, count($numbers));
if (!in_array($r, $display_me))
{
array_push($display_me, $r);
}
}
}

echo $before_widget;
$output = '';
$output.= '<table>';
if ($instance['gen_title'] != '')
{
$output.= '<div class="widget-title"><h3>';
$output.= "<tr><td align=center>" . $instance['gen_title'] . "</td></tr>";
$output.= '</h3></div>';
}

if ($instance['gen_layout'] == 'Narrow')
{
$tr = "<tr>";
$trclose = "</tr>";
}
else
{
$tr = "";
$trclose = "";
$output.= "<tr>";
}

foreach($display_me as $i)
{
$genlink = 'gen_link' . $i;
$output.= $tr . "<td align=center>";
$output.= $instance[$genlink];
$output.= "</td>" . $trclose;
}

if ($instance['gen_layout'] != 'Narrow')
{
$output.= '</tr>';
}

$output.= '</table>';
echo $output;
echo $after_widget;
}
}

?>