Skip navigation.

My pasteblog

This is not my Zettelkasten but a durable .bash_history

Posts tagged with "php"

lighttpd (cygwin), PHP5.2.0, Windows 2000, symfony

, , ,

I can only tolerate W2K with cygwin installed, and its package manager got me lighttpd.
This needed configuration:
cp /e^T/li^T/lighttpd.conf.default /etc/lighttpd/lighttpd.conf
vi ESC .
Only static HTML at first:
server.document-root = "/cygdrive/e/www/localhost/"
echo "test" > /cygdrive/e/www/localhost/index.php
echo "test" > /cygdrive/e/www/localhost/index.htm
/usr/sbin/lighttpd.exe -D -f /etc/lighttpd/lighttpd.conf #I could CTRL-C terminate it
#/usr/sbin/lighttpd.exe -f /etc/lighttpd/lighttpd.conf #goes to background mode, ps ux needed to get the PID
Big mistake: index.php takes precedence over index.htm and I got a 403 error. Removing the index.php helped.

Get PHP from http://www.php.net/downloads.php
Put it to C:\PHP and include the cgi version!
Version PHP5.2.0 did not work with yaz, pspell, nt$something and a 4th extension that I have already forgotten, so I excluded them.
The peardev.bat has some ^ characters in it, removed them by hand.
Double-clicking (*yuck*) to initialize PEAR, then I did the usual channel-discover etc. as per symfony docs. Then symfony installed without any problems.

Back to lighttpd: Un-commented cgi module, cgi.assign = (".php"=>"C:\PHP\php-cgi.exe")
Got a "no input file specified" error, added in php.ini a docroot E:\www\localhost as per http://www.php.net/manual/de/security.cgi-bin.php 1st comment.
A phpinfo(); in index.php worked then.
Changed BOTH php.ini and lighttpd.conf to point to a symfony-style $mypath/web/ directory, un-commented mod_rewrite, mod_redirect, mod_alias in lighttpd.conf and added
alias.url = ( "/sf/" => "/cygdrive/c/PHP/PEAR/data/symfony/web/sf/" )
url.rewrite-once = (
"^/(.*\..+(?!html))$" => "$0",
"^/(.*)\.(.*)" => "$0",
"^/([^.]+)$" => "/index.php/$1",
"^/$" => "/index.php"
)
I didn't bother to setup a vhost, as this installation is just for testing anyways. I got that above rewrite stuff from the symfony wiki IIRC (taken from another host).
Now c:\php\symfony init-project test && C:\PHP\symfony init-app frontend brought me the familiar symfony welcome screen.

I downloaded mysql-essential-5.0.27-win32.msi and installed ot as a service (for now). Configuration was done with the bundled "MySQL Server Instance Config Wizard". In cmd.com mysql -u root -pmyPassword and create databse symfony.

In the symfont directory I changed both config/database.yml AND propel.ini including username:password in both of them. I could then copy the schema.yml from the First Project tutorial and run propel-*-* to create the database tables.


Music to my ears!

I downloaded http://xdebug.org/link.php?url=xdebug200rc3-521-win although it said PHP5.2.1+ and put it in my C:\PHP\ext and added zend_extension_ts="C:/PHP/ext/php_xdebug-2.0.0rc3-5.2.1.dll" to my php.ini -- that's all to install xdebug. In cmd.com a C:\PHP\php-cgi.exe brought no error message, if the xdebug dll is too old it says something along the lines "Xdebug requires Zend Engine API version 220051025.
The Zend Engine API version 220060519 which is installed, is newer.
Contact Derick Rethans at http://xdebug.org for a later version of Xdebug."

I could not get xcache to work with PHP5.2.0, but on another machine with PHP-5.1.6

Frameworks und Vertrauen

,

Ich bin ein PHP-Hobbyist.

Meine erste Tat auf einem WAMP (Windows 98!) war es, ein PHPNuke aufzusetzen. Seitdem habe ich einiges dazugelernt, schliesslich sitzen mir keine Fertigstellungstermine im Nacken! *aetsch* (hehe, scnr)

Im Jahr 2005 stand an, ein Framework mit Objektorientierung, Datenbankansprache mit objektrelationaler Verknuepfung und sowieso im MVC-Entwurfsmuster zu erlernen: Ich moechte stets mit eigenem Code am Informationsaustausch im Internet teilnehmen koennen, und mindestens mit Benutzerauthentifizierung. Das ist fuer mich ein kultur- und technikgeschichtliches Beduerfnis, aber das will ich hier und jetzt nicht weiter ausfuehren.

Mit dem Anwender in einer Agentur habe ich aber eines gemeinsam: Meine Zeit ist zu limitiert, um eine Vielzahl an Frameworks zu erlernen. Ich brauch eine Codesammlung, die mich sofort produktiv sein laesst, und die mir auch in zwei Jahren noch zur Verfuegung steht.

Bei der Evaluierung blieb ich bei symfony haengen.

Obwohl zu diesem Zeitpunkt nur in Version 0.4 verfuegbar, ueberzeugte es mich
  • mit umfangreicher Dokumentation in bestem Englisch, obwohl die Verfasser Franzosen sind,
  • als nicht-englische-Muttersprachler bauten die Entwickler I18n von Grund auf ein (Hallo RoR!),
  • einer hohen Schlagzahl an Commits,
  • der pragmatischen Grundeinstellung
  • und einem niedrigen Ego-Niveau.


Zwar gibt es fuer jeden Suchenden auf dem Feld der PHP5-Frameworks noch eine Menge anderer Gruende, symfony einmal zu begutachten, aber die obigen sind fuer mich aus einem Grund bedeutsam:
Sie schaffen Vertrauen.

Meine persoenliche Zeit-Wette sieht also vollen Einsatz auf symfony gesetzt. Weil es von Anfang an produktiv einsetzbar war. Und weil ich glaube, dass es auch uebernaechstes Jahr noch existiert.

ExTracTing

, , ,

<?php

$lines = file('http://www.symfony-project.com/trac/timeline?'.
  'from=04%2F09%2F06&daysback=365&changeset=on&update=Update');

foreach ($lines as $k => $line){
  if(strpos($line, 'h2') === false) unset($lines[$k]);
}//end forezch lines

$data = array();
foreach ($lines as $line){
  $tmp=''; $date = ''; $time = ''; $changeset = ''; $_changeset = false; $author = ''; $_author = false;
  $dom = new domDocument;
  $dom->loadHTML($line);
  $h2 = $dom->getElementsByTagName('h2');
  $date = substr($h2->item(0)->nodeValue,0,8);
  $dts = $dom->getElementsByTagName('dt');
  if($dts){
    preg_match_all('#\[(.*)\]#', $dts->item(0)->nodeValue,$_changeset);
    if($_changeset) $changeset = $_changeset[1];
    preg_match_all('#by (.+)$#', $dts->item(0)->nodeValue, $_author);
    if($_author) $author = $_author[1];
    foreach ($dts as $dt){
      $spans = $dt->getElementsByTagName('span');
      $time = $spans->item(0)->nodeValue;
      //collect the data in an array
      $data[] = array('changeset' => $changeset[0], 'author' => $author[0], 'unixtime' => strtotime("$date $time"));
    }//end foreach
  }//end if
}//end foreach

die(var_dump($data));

?>

Vim, PHP and symfony

, , ,

An IRC log bot with MySQL and flat-file fallback

, , , ...

A bit hackish, but working.

Usage: ~$ php path/to/followingFile.php

<?php
/**
 * An IRC logbot based on PEAR::NET_SmartIRC
 *
 * Logs an IRC channel to a MySQL database, triggered by "ActionHandler"s
 * as implemented in SmartIRC.
 *
 * ActionHandler values are defined in Net_SmartIRC/SmartIRC/defines.php
 * Normal conversation can be caught by SMARTIRC_TYPE_CHANNEL,
 * a /me is a SMARTIRC_TYPE_ACTION
 *
 * There is currently no logging for joins/quits/etc.
 *
 * This script has been written on a server with PHP Version 4.4.0-4
 * and a MySQL server version 4.1.15
 *
 * @author Chris Prior <public@prior-i.de>
 *
 */

//include the pear class (doesn't need an include_path for that dir)
include_once('php/Net/SmartIRC.php');

class irclogbot extends Net_SmartIRC
{
  var $hasDbConn=false;
  var $mysql_host='localhost';
  var $mysql_user='cpr';
  var $mysql_password='pass';
  var $mysql_db='irc';
  var $mysql_table='irc_log_test';
  var $log_obj;
  var $stats_obj;
  var $loggables=array('nick','ident','host','type','from','channel','message');
  var $logfileIfMysqlError='errorMysqlINSERT.log';

  //function irclogbot(&$log_obj,&$stats_obj2){
  //}

  /*
   * overwriting existing function
   */
  function _nicknameinuse()
  {   
      $newnickname = $this->_nick.'_';
      $this->changeNick($newnickname, SMARTIRC_CRITICAL);
      $this->_register();
  }

  //unused
  function _register()
  {   
      $this->_send('/msg NickServ IDENTIFY sdcy0', SMARTIRC_CRITICAL);
  }

  /*
   * Basic MySQL auth
   */
  function connect_database()
  {
      $link = @mysql_connect($this->mysql_host, $this->mysql_user, $this->mysql_password)
         or die("Keine Verbindung möglich: " . mysql_error());
      $this->hasDbConn = @mysql_select_db("cpr") or die("db select failed.");
  }

  /*
   * the workhorse logging method
   *
   * Checks for content of $data-> object as returned from PEAR class,
   * constructs a SQL statement and inserts with connection check
   *
   * Outputs some stuff to stdout
   * Don't confuse the 2 stdout sources: parent::setDebug also does it!
   *
   * never change the methodname to 'log', incompatible to the PEAR class!
   *
   */
  function my_log(&$irc='',&$data='')
  {
    $doit=true;
    //quick hack to filter out server msg marked S*_TYPE_CHANNEL
    foreach($this->loggables as $v){
      if (!isset($data->$v)) $doit=false;
      //else echo "$v has " . $data->$v."\n"; //debug
    }
    if($doit){
      //there is an 'ACTION' prefix for the message, I strip it.
      //To recognize a type `action` I still have the value 256 in the col `type`
      if(256==$data->type) {
        $data->message = substr($data->message,8);
        $data->message = substr($data->message,0,strlen($data->message)-1);
        }//end if type 256 == action
      /**
       * The following does not work if there is no db link,
       * so I use mysql_real_escape_string selectively.
       * This leaves the error log unescaped!!!
       *
      */
      //split for original debugging as above, could be merged into one foreach
      foreach($this->loggables as $v) {
        //http://php.net/manual/en/function.stripslashes.php#51390
        if (get_magic_quotes_gpc())
          $data->$v = stripslashes($data->$v);
        //can't use it on the ready query as it would return 
        // *VALUES '\'myNickName\',*
        if(!is_numeric($data->$v) AND $this->hasDbConn ) 
          $data->$v = @mysql_real_escape_string($data->$v);
      }
    }//end if $doit
    //no linebreaks or mysql_real_escape_string breaks the statement!
    $sql = sprintf("INSERT INTO %s "
      . "(`nick`, `ident`, `host`, `type`, `from`, `channel`, `message` ) "
      . " VALUES ('%s', '%s', '%s', '%s', '%s', '%s', '%s');",
      $this->mysql_table,
      $data->nick,
      $data->ident,
      $data->host,
      $data->type,
      $data->from,
      $data->channel,
      $data->message
    );
    //echos to stdout
    echo $sql;

    /**
     * Now we are fighting hard to preserve the log
     */
    //the mysql INSERT query
    if(!$this->hasDbConn){
      $irc->connect_database();
      if(!$this->hasDbConn){
        $this->logInsertIfMysqlError($sql);
      }
    }
    //new if, not elseif, so a success above triggers
    if($this->hasDbConn == true AND $doit)
    {
      //echo "hasDbConn\n";
      $result = @mysql_query($sql);
      if (!$result) {
        echo('invalid query: ' . mysql_error());
        $this->logInsertIfMysqlError($sql);
      }
    }//end if hasDbConn*
    else {
      $this->logInsertIfMysqlError($sql);
      echo "\n WARNING! Has no DB connection! WARNING!\n";
    }
    echo "\n\n";
  }

  /**
   * Fallback if no MySQL conn
   *
   * I got an 'invalid query: MySQL server has gone away' after long a silence.
   * This is to preserve the INSERT statements for later addition to the db.
   */
  function logInsertIfMysqlError($content){

    echo "Trying to log into error logfile ".$this->logfileIfMysqlError."\n";
    if(!file_exists($this->logfileIfMysqlError)){
      if (touch($this->logfileIfMysqlError) === false){
        echo "cannot touch the non-existing file!"."\n";
        continue;
      }
    }
    if (!is_writable($this->logfileIfMysqlError)) {
       if (!chmod($this->logfileIfMysqlError, 0666)) {
         echo "Cannot change the mode of file ($this->logfileIfMysqlError)"."\n";
         continue;
       };
     }
     if (!$fp = @fopen($this->logfileIfMysqlError, "a")) {
       echo "Cannot open file ($this->logfileIfMysqlError)"."\n";
       continue;
     }
     if (fwrite($fp, $content."\n") === FALSE) {
       echo "Cannot write to file ($this->logfileIfMysqlError)"."\n";
       continue;
     } 
     else echo "ERROR LOGGED! Wrote into ".$this->logfileIfMysqlError."\n";
     if (!fclose($fp)) {
       echo "Cannot close file ($this->logfileIfMysqlError)"."\n";
       continue;
     }
      
  }//end function

  /**
   * Calling this at startup might catch the worst scenario and
   * renders the above logInsertIfMysqlError($str) useless in many respects
   */
  function testForErrorLogfile(){
     if (!$fp = @fopen($this->logfileIfMysqlError, "a")) {
       echo "Cannot open file ($this->logfileIfMysqlError)"."\n";
       exit;
     }
  }//end function

  //doesn't work as expected, but I don't care
  function my_quit(&$this, &$ircdata)
  {
    echo 'FooBar';
    $this->quit("The Bot sfLog has quit.");
  }

}//end class ######################################

$irc = &new irclogbot();
$irc->testForErrorLogfile();
//$irc->connect_database();

//pear/Net_SmartIRC/SmartIRC/defines.php
$irc->setDebug(SMARTIRC_DEBUG_NOTICE|SMARTIRC_DEBUG_CONNECTION|SMARTIRC_TYPE_ACTION|SMARTIRC_TYPE_CHANNEL);
$irc->setUseSockets(TRUE);
$irc->registerActionhandler(SMARTIRC_TYPE_CHANNEL, '^sfLog: !quit', $irc, 'my_quit');

//pear/Net_SmartIRC/SmartIRC/defines.php
//SMARTIRC_TYPE_CHANNEL is defined as `2` and this gets inserted into the db
//never change the methodname to 'log', as it is incompatible to the PEAR class
$irc->registerActionhandler(SMARTIRC_TYPE_CHANNEL, '^.?', $irc, 'my_log');

//type channel does not catch /me et al.
$irc->registerActionhandler(SMARTIRC_TYPE_ACTION, '^.?', $irc, 'my_log');

$irc->connect('irc.freenode.de', 6667);

//Usage: login(nick, realname, usermode, username, password);
$irc->login('nick', 'Chris Prior', 8, 'nick','pass');

$irc->join(array('#test'));
$irc->listen();
$irc->disconnect();
?>


So you need the sql schema? Here it is:

DROP TABLE IF EXISTS `irc_log`;
CREATE TABLE IF NOT EXISTS `irc_log` (
  `id` bigint(20) unsigned NOT NULL auto_increment,
  `datetime` timestamp NOT NULL default CURRENT_TIMESTAMP,
  `nick` varchar(32) NOT NULL default '',
  `ident` varchar(64) NOT NULL default '',
  `host` varchar(254) NOT NULL default '',
  `type` varchar(4) NOT NULL default '',
  `from` varchar(254) NOT NULL default '',
  `channel` varchar(32) NOT NULL default '',
  `message` text NOT NULL,
  PRIMARY KEY  (`id`),
  FULLTEXT KEY `nick_msg` (`nick`,`message`)
)DEFAULT CHARSET=utf8;

shell script via Apache/PHP

, , , ...

NOPASSWD: /bin/sh, /path/to/script.sh
script.sh chmod 6755
November 2009
S M T W T F S
October 2009December 2009
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30