Posterous
Daniele is using Posterous to post everything online. Shouldn't you?
Unknown35
 

Daniel’strae

Is cuma cá mhinice a théann tú ar strae; is é is tábhachtaí gurb áil leat do bhealach a aimsiú arís.

Compressing mysqldump output

The result of mysqldump is a flat text file containing the sql commands used to restore the mysql databases/tables that were dumped. Normally the result of mysqldump is compressed (in regular backups) because the size of the resulted file is normally big and good compression rates are achieved on such text files.
To do this manually using gzip we just run:

gzip -v outputfile.sql

This quick tip shows how you can run the same thing on the fly with only one command directly compressing the resulted file. This might be useful in situations where space is a problem and the full dump can’t be saved on the available storage directly because of its size. Also this might be useful to not run it in 2 commands and have one compact command (maybe used also in some backup scripts, etc.)

mysqldump < mysqldump options> | gzip > outputfile.sql.gz

When restoring from a compressed file we can manually uncompress it first:

gunzip -v outputfile.sql.gz

or again we can run in the same command line mysqldump and gunzip:

gunzip < outputfile.sql.gz | mysql < mysql options> 

The same can be done using bzip2 compression:

mysqldump < mysqldump options> | bzip2 > outputfile.sql.bz2

and to restore

bunzip2 < outputfile.sql.bz2 | mysql < mysql options> 

From my own experience I would not recommend using bzip2 for this because even if the compression is better the time to run it on large files will be much longer than gzip (6-10 times longer). But if you are in need for every bit of space and don’t care that this will take much longer then bzip2 is the solution for you.

Source: http://www.ducea.com/2006/10/28/compressing-mysqldump-output/

Loading mentions Retweet
Posted January 22, 2010
// 0 Comments

Example of PHP Plugin system

<?php

/** Plugin system **/

$listeners = array();

/* Create an entry point for plugins */
function hook(){
  global $listeners;

  $num_args = func_num_args();
  $args = func_get_args();

  if($num_args < 2)
    trigger_error("Insufficient arguments", E_USER_ERROR);

  // Hook name should always be first argument
  $hook_name = array_shift($args);

  if(!isset($listeners[$hook_name]))
    return; // No plugins have registered this hook

  foreach($listeners[$hook_name] as $func){
    $args = $func($args);
  }

  return $args;
}

/* Attach a function to a hook */
function add_listener($hook, $function_name){
  global $listeners;

  $listeners[$hook][] = $function_name;
}


/////////////////////////

/** Sample Plugin **/
add_listener('a_b', 'my_plugin_func1');
add_listener('str', 'my_plugin_func2');

function my_plugin_func1($args){
  return array(4, 5);
}
function my_plugin_func2($args){
  return str_replace('sample', 'CRAZY', $args[0]);
}

/////////////////////////

/** Sample Application **/

$a = 1;
$b = 2;

list($a, $b) = hook('a_b', $a, $b);

$str  = "This is my sample application\n";
$str .= "$a + $b = ".($a+$b)."\n";
$str .= "$a * $b = ".($a*$b)."\n";

$str = hook('str', $str);

echo $str;

?>

Loading mentions Retweet
Posted December 17, 2009
// 0 Comments

Simple FTP upload with Python

import ftplib
import os
import sys
import traceback

print "Files:", sys.argv[1:]

print "Logging in..."
ftp = ftplib.FTP()
ftp.connect(host, port)
print ftp.getwelcome()
try:
    try:
        ftp.login(login, password)
        ftp.cwd(some_directory)
        # move to the desired upload directory
        print "Currently in:", ftp.pwd()

        print "Uploading...",
        fullname = sys.argv[1]
        name = os.path.split(fullname)[1]
        f = open(fullname, "rb")
        ftp.storbinary('STOR ' + name, f)
        f.close()
        print "OK"
       
        print "Files:"
        print ftp.retrlines('LIST')
    finally:
        print "Quitting..."
        ftp.quit()
except:
    traceback.print_exc()

       
raw_input("Press Enter...")

Loading mentions Retweet
Filed under  //   ftp   Python  
Posted December 15, 2009
// 0 Comments

Lighttpd setup a password protected directory (directories)

If you require authentication on certain directories using the Lighttpd web server, you can use Lighttpd's mod_auth module. It allows you to protect any directory in web server with access restrictions (just like Apache's password protected directory) .

Lighttpd supports both basic and digest authentication methods. Now consider following sample setup:

  1. Domain name: theos.in
  2. Directory (DocRoot) to protect with a password: /home/lighttpd/theos.in/http/docs
  3. Username: vivek
  4. Lighttpd password file: /home/lighttpd/.lighttpdpassword (this file should be outside default http document root)

How do I use Basic authentication method?

Easy to implement and password stored in cleartext format using files. If you are going to use this method make sure you use SSL (Secure Socket Layer) connection/encryption.

Step #1: Open /etc/lighttpd/lighttpd.conf file

Make sure mod_auth is loaded:
server.modules += ( "mod_auth" )

Now add following three directives:
auth.debug = 2
auth.backend = "plain"
auth.backend.plain.userfile = "/home/lighttpd/.lighttpdpassword"

Where,

  • auth.debug = 2 : Specify debug level (0 turns off debug message, 1 for authentication ok message and 2 for detailed/verbose debugging message). This is useful for troubleshooting authentication problem. It logs message in access.log and error.log files
  • auth.backend = "plain" : You are using plain text backend (other options are ldap, htpasswd and others)
  • auth.backend.plain.userfile = "/home/lighttpd/.lighttpdpassword" : Filename of the username:password storage

Next, you need specify which directory you want to password protect. For example, consider directory /home/lighttpd/theos.in/http/docs directory. Find out your domains virtual hosting section (theos.in) and append following text:
auth.require = ( "/docs/" =>
(
"method" => "basic",
"realm" => "Password protected area",
"require" => "user=vivek"
)
)

Where,

  • auth.require = ( "/docs/" => : Directory name
  • "method" => "basic", : Authentication type
  • "realm" => "Password protected area", : Password realm/message
  • "require" => "user=vivek" : Only user vivek can use /docs/

At the end, your configuration should read as follows:
$HTTP["host"] == "theos.in" {
server.document-root = "/home/lighttpd/theos.in/http"
server.errorlog = "/var/log/lighttpd/theos.in/error.log"
accesslog.filename = "/var/log/lighttpd/theos.in/access.log"
auth.require = ( "/docs/" =>
(
"method" => "basic",
"realm" => "Password protected area",
"require" => "user=vivek"
)
)
}

Save and close the file.

Step # 2: Create a password file

Create a plain text username (vivek) and password file:
# vi /home/lighttpd/.lighttpdpassword

Append username:password:
vivek:mysecretepassword

Where,

  • vivek - is the name of a user. Please note that do not use a system user stored in /etc/passwd file. It is recommended that you use a different username that only exists for the purpose of authenticating password protected directories.
  • mysecretepassword - is the password for user vivek (must be in clear text format for plain text method)

Save and close the file. Make sure file /home/lighttpd/.lighttpdpassword is readable by lighttpd:
# chown lighttpd:lighttpd /home/lighttpd/.lighttpdpassword

Finally, restart lighttpd server:
# /etc/init.d/lighttpd restart

Step # 3: Test your configuration

Fire your browser and point a web browser to http://yourdomain.com/docs/ or http://localhost/docs/ or http://ip-address/docs. You should be prompted for a username and password.

Loading mentions Retweet
Filed under  //   Auth   Lighttpd   tutorial  
Posted December 7, 2009
// 0 Comments

Lighttpd - Docs:ModAuth - lighty labs

Docs »

Module mod_auth - Using Authentication

Supported Methods

lighttpd supports both authentication methods described by
RFC 2617:

basic

The Basic method transfers the username and the password in
cleartext over the network (base64 encoded) and might result
in security problems if not used in conjunction with a crypted
channel between client and server.

digest

The Digest method only transfers a hashed value over the
network which performs a lot of work to harden the
authentication process in insecure networks.

Backends

Depending on the method lighttpd provides various way to store
the credentials used for the authentication.

For basic auth:
  • plain_
  • htpasswd_
  • htdigest_
  • ldap_
For digest auth:
  • plain_
  • htdigest_

plain

A file which contains username and the cleartext password
seperated by a colon. Each entry is terminated by a single
newline.

e.g.:

agent007:secret

htpasswd

A file which contains username and the crypt()'ed password
seperated by a colon. Each entry is terminated by a single
newline.

e.g.:

agent007:XWY5JwrAVBXsQ

You can use htpasswd from the apache distribution to manage
those files.

$ htpasswd lighttpd.user.htpasswd agent007

Keep in mind that not all versions of htpasswd default to use
Apache's modified MD5 algorithm for passwords, which is
required by lighttpd. You can force most to use MD5 with:

$ htpasswd -m <pwfile> <username>

htdigest

A file which contains username, realm and the md5()'ed
password seperated by a colon. Each entry is terminated
by a single newline.

e.g.:

agent007:download area:8364d0044ef57b3defcfa141e8f77b65

You can use htdigest from the apache distribution to manage
those files.

$ htdigest lighttpd.user.htdigest 'download area' agent007

Using md5sum can also generate the password-hash:

#!/bin/sh
user=$1
realm=$2
pass=$3

hash=`echo -n "$user:$realm:$pass" | md5sum | cut -b -32`

echo "$user:$realm:$hash" 

To use it (spaces between arguments!):

$ htdigest.sh 'agent007' 'download area' 'secret'
agent007:download area:8364d0044ef57b3defcfa141e8f77b65

follow code is improved when you use for service:

#!/bin/sh

export PATH="/bin:/usr/bin:/usr/sbin:$PATH" 

# when input ctrl-c, remove lockfile and exit
trap '[ $lockstart -eq 1 ] && unlock $pfile && exit 0 || exit 0' INT

pfile="/etc/lighttpd/conf.d/lighttpd.user" 
lockstart=0 
remove=0

errmsg() {
    echo "$1" > /dev/stderr
}

user_check() {
    check_user=$1
    grep "^${check_user}:" ${pfile} >& /dev/null
    return $?
}

lock() {
    lockfile="$1" 
    lockfile="${lockfile}.lock" 

    [ -f "${lockfile}" ] && {
        errmsg "WARNING: lock file ${lockfile} is already exists" 
        errmsg "         Wait minites for end of previous working ..." 
    }

    while [ -f "${lockfile}" ]; do echo >& /dev/null ; done
    touch ${lockfile} 
    lockstart=1
}

unlock() {
    lockfile="$1" 
    lockfile="${lockfile}.lock" 

    [ -f "${lockfile}" ] && rm -f ${lockfile} && lockstart=0
}

usage() {
    errmsg
    errmsg "lightdigest: lighttpd htdigest password generation program" 
    errmsg "Scripted by JoungKyun.Kim <http://oops.org>" 
    errmsg
    errmsg "Usage: $0 -[hd] -u user -p pass -r realm [-f password_file]" 
    errmsg "Options:" 
    errmsg "    -h          print this help messages" 
    errmsg "    -u user     username" 
    errmsg "    -p pass     password" 
    errmsg "    -r realm    realm name" 
    errmsg "    -f filename password file [default: /etc/lighttpd/conf.d/lighttpd.user" 
    errmsg "    -d          remove user" 
    errmsg

    [ $lockstart -eq 1 ] && rm -f ${pfile}.lock

    exit 1
}   

opts=$(getopt df:hp:r:u: $*)
[ $? != 0 ] && usage

set -- ${opts}
for i
do
    case "$i" in
        -d) remove=1; shift;;
        -f) pfile="$2"; shift; shift;;
        -p) pass="$2"; shift; shift;;
        -r) realm="$2"; shift; shift;;
        -u) user="$2"; shift; shift;;
        --) shift; break;
    esac
done

#echo $user
#echo $realm
#echo $pass
#echo $pfile
#echo $remove

[ -z "$user" ] && errmsg "ERROR: User is none!!" && usage
[ ${remove} -eq 0 -a -z "${realm}" ] && errmsg "ERROR: Realm is none!!" && usage

if [ -z "${pass}" -a ${remove} -eq 0 ]; then
    echo -n "Input new password : " 
    read newpass
    echo -n "Reinput password for confirm : " 
    read renewpass

    if [ "${newpass}" != "${renewpass}" ]; then
        errmsg "ERROR: Password is not match" 
        exit 1
    fi

    pass=${newpass}
fi

lock ${pfile}

if [ ${remove} -eq 0 ]; then
    # User Add Mode
    hash=$(echo -n "${user}:${realm}:${pass}" | md5sum | cut -b -32)
    user_check ${user}
    already=$?

    [ -f "${pfile}" ] && cp -af ${pfile} ${pfile}.bak
    if [ ${already} -eq 0 ]; then
        # already exists
        perl -pi -e "s/^${user}:.*$/${user}:${realm}:${hash}/g" ${pfile}
    else
        # add new user
        echo "${user}:${realm}:${hash}" >> ${pfile}
    fi
else
    # User Remove Mode
    tmp_htdigest="/tmp/lighttpd-htdiges.tmp.$$" 
    cp -af ${pfile} ${pfile}.bak
    grep -v "^${user}:" ${pfile} > ${tmp_htdigest}
    mv -f ${tmp_htdigest} ${pfile}
fi

unlock ${pfile}

exit 0

To use it (don't use realm value! getopt of some bash version has bug.) :

  # if you add or change
  $ lightdigest -u USERNAME -r REALM_NAME -f PASSWORD_FILE_PATH
  # if you want to remove use  
  $ lightdigest -d -u USERNAME

ldap

The ldap backend is performing the following steps to authenticate a user

  1. Init the LDAP connection
  2. Set Protocol version to LDAPv3
  3. If StartTLS if configured -> Configure CA certificate if supplied
  4. If StartTLS if configured -> Activate TLS using StartTLS
  5. If Bind DN is included -> Simple bind with Bind-DN and Bind-Password
  6. If there is no Bind-DN -> Simple bind anonymously
  7. Try up to two times a SUBTREE search of the base-DN with the filter applied.
  8. Retrieve the DN of the user matching the filter.
  9. Finally, re-init the connection (following the steps above), this time using the DN found using the filter and the password supplied by the user.

If all 9 steps are performed without any error the user is authenticated.

Configuration template

After setup the backend, edit the authentication configuration file to reflect your backend selected. The following is a configuration template.

## debugging
# 0 for off, 1 for 'auth-ok' messages, 2 for verbose debugging
auth.debug                 = 0

## type of backend 
# plain, htpasswd, ldap or htdigest
auth.backend               = "htpasswd" 

# filename of the password storage for plain
auth.backend.plain.userfile = "lighttpd-plain.user" 

## for htpasswd
auth.backend.htpasswd.userfile = "/full/path/to/lighttpd-htpasswd.user" 

## for htdigest
auth.backend.htdigest.userfile = "lighttpd-htdigest.user" 

## for ldap
# the $ in auth.backend.ldap.filter is replaced by the 
# 'username' from the login dialog
auth.backend.ldap.hostname = "localhost" 
auth.backend.ldap.base-dn  = "dc=my-domain,dc=com" 
auth.backend.ldap.filter   = "(uid=$)" 
# if enabled, startTLS needs a valid (base64-encoded) CA 
# certificate unless the certificate has been stored
# in a c_hashed directory and referenced in ldap.conf
auth.backend.ldap.starttls   = "enable" 
auth.backend.ldap.ca-file   = "/etc/CAcertificate.pem" 
# If you need to use a custom bind to access the server
auth.backend.ldap.bind-dn  = "uid=admin,dc=my-domain,dc=com" 
auth.backend.ldap.bind-pw  = "mysecret" 
# If you want to allow empty passwords
# "disable" for requiring passwords, "enable" for allowing empty passwords
auth.backend.ldap.allow-empty-pw = "disable" 

## restrictions
# set restrictions:
#
# ( <left-part-of-the-url> =>
#   ( "method" => "digest"/"basic",
#     "realm" => <realm>,
#     "require" => "user=<username>" )
# )
#
# <realm> is a string to display in the dialog 
#         presented to the user and is also used for the 
#         digest-algorithm and has to match the realm in the 
#         htdigest file (if used)
#

auth.require = ( "/download/" =>
                 (
                 # method must be either basic or digest
                   "method"  => "digest",
                   "realm"   => "download archiv",
                   "require" => "user=agent007|user=agent008" 
                 ),
                 "/server-info" =>
                 (
                 # limit access to server information
                   "method"  => "digest",
                   "realm"   => "download archiv",
                   "require" => "valid-user" 
                 )
                 "/protected-folder/" =>
                 (
                 # 
                   "method"  => "digest",
                   "realm"   => "download archiv",
                   "require" => "valid-user" 
                 )
               )

# Or, using regular expressions:
$HTTP["url"] =~ "^/download|^/server-info" {
  auth.require = ( "" =>
                   (
                     "method"  => "digest",
                     "realm"   => "download archiv",
                     "require" => "user=agent007|user=agent008" 
                   )
                 )
}

When completed, enable the authentication configuration module. The way to enable the module varies from different distributions.

Limitations

  • The implementation of digest method is currently not completely compliant with the standard as it still allows a replay attack. (i.e. not secure)
  • LDAP authentication only allows alphanumeric uid's that do not contain punctuations. i.e.) john.doe will come up as "ldap: invalid character (a-zA-Z0-9 allowed) in username: john.doe"
  • There seems to be no reasonable logging of failed login attempts yet
  • As of 1.4.19 the group field inside the require directive is not yet implemented. So auth.backend.plain.groupfile is of no use at this moment.

See Also

htdigest.sh.txt - htdigest.sh from this article (it's easier to grab that way) (2,919 KB) ckujau, Sab 28 Mar 2009, 04:51:01 +0000

Esporta su HTML TXT

Sembra un pò più complessa di quella di apache..

Loading mentions Retweet
Filed under  //   Auth   Lighttpd  
Posted December 7, 2009
// 0 Comments

Authentication, Authorization and Access Control - Apache HTTP Server

Getting it working

Here's the basics of password protecting a directory on your server.

You'll need to create a password file. This file should be placed somewhere not accessible from the web. This is so that folks cannot download the password file. For example, if your documents are served out of /usr/local/apache/htdocs you might want to put the password file(s) in /usr/local/apache/passwd.

To create the file, use the htpasswd utility that came with Apache. This will be located in the bin directory of wherever you installed Apache. To create the file, type:

htpasswd -c /usr/local/apache/passwd/passwords rbowen

htpasswd will ask you for the password, and then ask you to type it again to confirm it:

# htpasswd -c /usr/local/apache/passwd/passwords rbowen
New password: mypassword
Re-type new password: mypassword
Adding password for user rbowen

If htpasswd is not in your path, of course you'll have to type the full path to the file to get it to run. On my server, it's located at /usr/local/apache/bin/htpasswd

Next, you'll need to configure the server to request a password and tell the server which users are allowed access. You can do this either by editing the httpd.conf file or using an .htaccess file. For example, if you wish to protect the directory /usr/local/apache/htdocs/secret, you can use the following directives, either placed in the file /usr/local/apache/htdocs/secret/.htaccess, or placed in httpd.conf inside a <Directory /usr/local/apache/apache/htdocs/secret> section.

AuthType Basic
AuthName "Restricted Files"
AuthUserFile /usr/local/apache/passwd/passwords
Require user rbowen

Let's examine each of those directives individually. The AuthType directive selects that method that is used to authenticate the user. The most common method is Basic, and this is the method implemented by mod_auth. It is important to be aware, however, that Basic authentication sends the password from the client to the browser unencrypted. This method should therefore not be used for highly sensitive data. Apache supports one other authentication method: AuthType Digest. This method is implemented by mod_auth_digest and is much more secure. Only the most recent versions of clients are known to support Digest authentication.

The AuthName directive sets the Realm to be used in the authentication. The realm serves two major functions. First, the client often presents this information to the user as part of the password dialog box. Second, it is used by the client to determine what password to send for a given authenticated area.

So, for example, once a client has authenticated in the "Restricted Files" area, it will automatically retry the same password for any area on the same server that is marked with the "Restricted Files" Realm. Therefore, you can prevent a user from being prompted more than once for a password by letting multiple restricted areas share the same realm. Of course, for security reasons, the client will always need to ask again for the password whenever the hostname of the server changes.

The AuthUserFile directive sets the path to the password file that we just created with htpasswd. If you have a large number of users, it can be quite slow to search through a plain text file to authenticate the user on each request. Apache also has the ability to store user information in fast database files. The mod_auth_dbm module provides the AuthDBMUserFile directive. These files can be created and manipulated with the dbmmanage program. Many other types of authentication options are available from third party modules in the Apache Modules Database.

Finally, the Require directive provides the authorization part of the process by setting the user that is allowed to access this region of the server. In the next section, we discuss various ways to use the Require directive.

Loading mentions Retweet
Filed under  //   apache   Auth  
Posted December 7, 2009
// 0 Comments

Enabling / Disabling apace modules in command line on debian/ubuntu distribution

Per abilitare moduli è presente il comando

a2enmod <nomeModuloDaAttivare>

Digitandolo senza argomenti, restituisce l'elenco dei moduli attivabili:

/#  a2enmod
 Your choices are: actions alias asis auth_basic auth_digest authn_alias authn_anon authn_dbd authn_dbm authn_default authn_file authnz_ldap authz_dbm authz_default authz_groupfile authz_host authz_owner authz_user autoindex cache cern_meta cgi cgid charset_lite dav dav_fs dav_lock dbd deflate dir disk_cache dump_io env expires ext_filter fcgid file_cache filter headers ident imagemap include info ldap log_forensic mem_cache mime mime_magic negotiation perl php5 proxy proxy_ajp proxy_balancer proxy_connect proxy_ftp proxy_http rewrite setenvif speling ssl status substitute unique_id userdir usertrack version vhost_alias
Which module(s) do you want to enable (wildcards ok)?

Per disattivare moduli, invece, si usa

a2dismod

che funziona esattamente come a2enmod.

Dopo aver fatto le modifiche, ricordarsi di riavviare apache

/# /etc/init.d/apache2 restart

Loading mentions Retweet
Posted December 2, 2009
// 0 Comments

Running lighttpd under apache2

Basic configuration to run lighttpd under apache2 (lighttpd will be act as a proxy on port 81, in this example):

 

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so

ProxyRequests Off
ProxyPreserveHost On
proxypass /folder-to-proxy http://localhost:81/folder
proxypassReverse /folder-to-proxy http://localhost:81/folder

<Proxy http://localhost:81/>
    Order Allow,Deny
    Allow from all
</Proxy>

Loading mentions Retweet
Posted November 26, 2009
// 0 Comments

Semplici test OOP

##file: lib-doc.php
<?php
class Document{
    private $code;
    private $date;
    private $costumer;
    private $total;
    private $vat;
    private $imp;
    private $i;
    public $items;
    public $template;

       
    public function __construct($code, $date, $costumer){
        $this->i = 0;
        $this->template = 'document.tpl.php';
        $this->code = $code;
        $this->date = $date;
        $this->costumer = $costumer;
        $this->items = array();
    }

        public function addItem($title, $code, $qnt, $price, $nVat){
        $this->i++;
        $item = new Item($code, $title, $qnt, $price, $nVat, $this->i, $this);
        $this->items[$this->i] = $item;

                $this->totaliDocumento();
        return $item;
    }

        public function removeItem($item){
        if(isset($this->items[$item->getKey()])){
            unset($this->items[$item->getKey()]);
            $this->totaliDocumento();
        }
    }

        public function changeQnt($item, $newQnt){
        if(isset($this->items[$item->getKey()])){
            $item->changeQnt($newQnt);
            $this->totaliDocumento();
        }
    }

        public function totaliDocumento(){
        $this->total = 0;
        $this->vat = 0;
        $this->imp = 0;
        foreach($this->items AS $item){
            $this->total += $item->getImporto('totale');
            $this->imp += $item->getImporto('imponibile');
            $this->vat += $item->getImporto('iva');
        }
    }

        public function attr($attr){
        return $this->$attr;
    }

        public function output(){
        $document = $this;
        include($this->template);
    }
    public function outputItem($item){
        include($item->template);
    }
}
class Item Document{
    private $qnt;
    private $prezzo;
    private $cIva;
    public $titolo;
    public $codice;
    public $template;
    /*
     * rayKey e' la chiave dell'array items
     * dell'istanza di ogni Item.
     * Serve per tenerne la tracciabilita'
     * (per rimuovere gli oggetti o modificarli)
    */
    private $rayKey;

        private $documento;
    private $totale;
    private $imponibile;
    private $iva;

        public function __construct($codice, $titolo, $qnt, $prezzo, $cIva, $key, $documento){
        $this->template = 'item.tpl.php';
        $this->documento = $documento;
        $this->rayKey = $key;
        $this->codice = $codice;
        $this->titolo = $titolo;
        $this->qnt = $qnt;
        $this->prezzo = $prezzo;
        $this->cIva = $cIva;
        //calcolo i totali
        $this->calcolaTotali();
    }
    public function getKey(){
        return $this->rayKey;
    }
    /*
     *Diciamo che voglio avere la certezza che
     *aggiornando la quantita' o il prezzo
     *dell'oggetto, i totali sono sempre aggiornati.
     *Quindi qnt e prezzo sono privati, per aggiornarli
     *bisogna utilizzare la relativa funzione che
     *aggiorna anche i totali dell'oggetto.
    */
    public function aggiornaQnt($qnt){
        $this->qnt = $qnt;
        $this->calcolaTotali();
    }

        public function aggiornaPrezzo($prezzo){
        $this->prezzo = $prezzo;
        $this->calcolaTotali();
    }

        private function calcolaTotali(){
        $this->imponibile = $this->qnt * $this->prezzo;
        $this->iva = ($this->imponibile * $this->cIva) / 100;
        $this->totale = $this->imponibile + $this->iva;
        $this->documento->totaliDocumento();
    }
    /*
     * Anche i totali non sono modificabili
     * direttamente ma dipendono da altre
     * proprieta' dell'oggetto.
     * L'unico modo per ottenerli al di fuori
     * della classe, e' quindi questa funzione
    */
    public function getImporto($importo = 'totale'){
        switch($importo){
            case 'totale':
                return $this->totale;
                break;
            case 'imponibile':
                return $this->imponibile;
                break;
            case 'iva':
                return $this->iva;
                break;
        }
    }
    /*
     * questo metodo serve solo per recuperare dall'esterno
     * le variabli protette
    */
    public function attr($attr){
        return $this->$attr;
    }

        public function output(){
        $item = $this;
        include($this->template);
    }
}
?>

##file: index.php
<?php
require_once('lib-doc.php');

$fattura = new Document('00001', '11 November 2009', 'Jhon Doe');

$beer = $fattura->addItem('Beer Bottle', 'F6ASJK8', 6, 3.43, 20);
$chips = $fattura->addItem('Cheesy Chips', 'KBLN32', 2, 1.12, 20);
$popcorn = $fattura->addItem('Pop Corn', 'BCHREUD6', 2, 0.69, 20);
$fattura->removeItem($beer);
$beer_cans = $fattura->addItem('Beer Cans, x6', 'YHEF6DTT', 1, 5.99, 20);
//$fattura->changeQnt($chips, 4);

$fattura->output();
?>

##file: document.tpl.php
<div class="document document-<?php echo $document->attr('code'); ?>">
    <h1>Document <?php echo $document->attr('code'); ?> of <?php echo $document->attr('date'); ?></h1>
    <p>Costumer: <b><?php echo $document->attr('costumer'); ?></b></p>
    <h2>Items Details</h2>
    <p class="item-list">
<?php
foreach($document->items AS $item){
    $document->outputItem($item);
}
?>
    </p>
    <h2>Document Totals:</h2>
    <ul class="totals">
        <li><b>Imponibile:</b> <?php echo $document->attr('imp'); ?>&euro;</li>
        <li><b>VAT:</b> <?php echo $document->attr('vat'); ?>&euro;</li>
        <li><b>Total:</b> <?php echo $document->attr('total'); ?>&euro;</li>
    </ul>
</div>

##file: item.tpl.php
<?php
//questo DEVE dare ERRORE!
$item->aggiornaPrezzo(10.54);
?>
<div class="item item-<?php echo $item->codice; ?>">
    <h3><?php echo $item->titolo; ?></h3>
    <ul>
        <li><b>Quantity:</b> <?php echo $item->attr('qnt'); ?></li>
        <li><b>Cost per Unit:</b> <?php echo $item->attr('prezzo'); ?></li>
        <li><b>VAT Appliable:</b> <?php echo $item->attr('cIva'); ?>%</li>
        <li><b>Imponibile:</b> <?php echo $item->getImporto('imponibile'); ?>&euro;</li>
        <li><b>VAT:</b> <?php echo $item->getImporto('iva'); ?>&euro;</li>
        <li><b>Total:</b> <?php echo $item->getImporto('totale'); ?>&euro;</li>
    </ul>
</div>

Full version: http://pastie.org/705984

Loading mentions Retweet
Posted November 19, 2009
// 0 Comments

Reminder: postgresql 8.4.1 Conditional Expressions

9.16.1. CASE

The SQL CASE expression is a generic conditional expression, similar to if/else statements in other programming languages:

CASE WHEN condition THEN result
[WHEN ...]
[ELSE result]
END

CASE clauses can be used wherever an expression is valid. Each condition is an expression that returns a boolean result. If the condition's result is true, the value of the CASE expression is the result that follows the condition, and the remainder of the CASE expression is not processed. If the condition's result is not true, any subsequent WHEN clauses are examined in the same manner. If no WHEN condition yields true, the value of the CASE expression is the result of the ELSE clause. If the ELSE clause is omitted and no condition is true, the result is null.

An example:

SELECT * FROM test;

a
---
1
2
3


SELECT a,
CASE WHEN a=1 THEN 'one'
WHEN a=2 THEN 'two'
ELSE 'other'
END
FROM test;

a | case
---+-------
1 | one
2 | two
3 | other

The data types of all the result expressions must be convertible to a single output type. See Section 10.5 for more details.

There is a "simple" form of CASE expression that is a variant of the general form above:

CASE expression
WHEN value THEN result
[WHEN ...]
[ELSE result]
END

The first expression is computed, then compared to each of the value expressions in the WHEN clauses until one is found that is equal to it. If no match is found, the result of the ELSE clause (or a null value) is returned. This is similar to the switch statement in C.

The example above can be written using the simple CASE syntax:

SELECT a,
CASE a WHEN 1 THEN 'one'
WHEN 2 THEN 'two'
ELSE 'other'
END
FROM test;

a | case
---+-------
1 | one
2 | two
3 | other

A CASE expression does not evaluate any subexpressions that are not needed to determine the result. For example, this is a possible way of avoiding a division-by-zero failure:

SELECT ... WHERE CASE WHEN x <> 0 THEN y/x > 1.5 ELSE false END;

9.16.2. COALESCE

COALESCE(value [, ...])

The COALESCE function returns the first of its arguments that is not null. Null is returned only if all arguments are null. It is often used to substitute a default value for null values when data is retrieved for display, for example:

SELECT COALESCE(description, short_description, '(none)') ...

Like a CASE expression, COALESCE only evaluates the arguments that are needed to determine the result; that is, arguments to the right of the first non-null argument are not evaluated. This SQL-standard function provides capabilities similar to NVL and IFNULL, which are used in some other database systems.

9.16.3. NULLIF

NULLIF(value1, value2)

The NULLIF function returns a null value if value1 equals value2; otherwise it returns value1. This can be used to perform the inverse operation of the COALESCE example given above:

SELECT NULLIF(value, '(none)') ...

If value1 is (none), return a null, otherwise return value1.

9.16.4. GREATEST and LEAST

GREATEST(value [, ...])
LEAST(value [, ...])

The GREATEST and LEAST functions select the largest or smallest value from a list of any number of expressions. The expressions must all be convertible to a common data type, which will be the type of the result (see Section 10.5 for details). NULL values in the list are ignored. The result will be NULL only if all the expressions evaluate to NULL.

Note that GREATEST and LEAST are not in the SQL standard, but are a common extension. Some other databases make them return NULL if any argument is NULL, rather than only when all are NULL.


Source: http://www.postgresql.org/docs/8.4/interactive/functions-conditional.html

Loading mentions Retweet
Posted November 12, 2009
// 0 Comments