Tag Archives: php

mysql connect error

Τι σπαστικό πράγμα αυτό, να στήνεις ολόκληρο virtual machine με linux (centos 6.3), apache και php, αλλά τελικά να μην μπορεί να συνδεθεί στη mysql (που τρέχει σε διαφορετικό server σε διαφορετικό δίκτυο) από τον apache και τις ιστοσελίδες τελικά, ενώ ο ίδιος κώδικας όταν τον τρέχεις από το command line με php-cgi να τρέχει κανονικά…

Η μεγαλύτερη αρρώστια είναι ότι σε άλλα linux μηχανήματα και σε άλλα windows μηχανήματα η σύνδεση γίνεται κανονικά, αλλά στο μηχάνημα που θέλεις, επιμένει σαν πεισματάρικο μουλάρι να μην τρέχει. Σου πετάει φαρδύ πλατύ στη μούρη ένα

SQLSTATE[HY000] [2003] Can’t connect to MySQL server on ‘xxx.xxx.xxx.xxx’

Δεν λέω καλό το linux και το open source, αλλά έχει από διανομή σε διανομή και μερικά κολλήματα πολύ άγρια που σου κάνουν τα νεύρα κουρέλια. Μετά από αρκετά μπινελίκια δοκιμές και ψάξιμο του selinux, firewall, permissions, iptables, και ότι μπορούσε να μου περάσει από το μυαλό… …τελικά η μαγική εντολή ήταν η ακόλουθη (από root user πάντα):

[root@server ~]# setsebool -P httpd_can_network_connect=1

Τέλος καλό και… μακρυά και αγαπημένοι.

Ημέρες – Μήνες – Έτη (php)

Λίγος κώδικας σε PHP που επιστρέφει τη διαφορά δύο ημερομηνιών σε Ημέρες – Μήνες – Έτη, αφού οι DateTime::Diff() και date_diff() που παρέχει η PHP τα κάνουν μαντάρα.
Για συντομία και καθαρότητα του κώδικα δεν μπήκαν έλεγχοι με ποια σειρά έχουν δοθεί οι ημερομηνίες, οπότε περιμένει να είναι πρώτα η παλαιότερη και μετά η μεταγενέστερη.

function dmydiff($dateS, $dateE)
{
    $dS = getdate($dateS);
    $dE = getdate($dateE);

    $DMY = array('Y'=>0, 'M'=>0, 'D'=>0);

    $DMY['Y'] = $dE['year'] - $dS['year'];
    $DMY['M'] = $dE['mon'] - $dS['mon'];
    $DMY['D'] = $dE['mday'] - $dS['mday'];

    if ($DMY['D'] < 0)
    {
        $dT = mktime(0,0,0,$dS['mon']+1,1,$dS['year']);
        $dT = intval(($dT - $dateS) / (24*60*60));
        $DMY['D'] =  $dT + $dE['mday'] - 1;
        $DMY['M']--;
    }
    if ($DMY['M'] < 0)
    {
        $DMY['Y']--;
        $DMY['M'] += 12;
    }

    return $DMY;
}

Ο δοκιμαστικός κώδικας που φαίνεται παρακάτω βγάζει τα εξής αποτελέσματα.

Start Date: 31/01/2012
End Date  : 20/03/2013

Using DateTime::Diff() or date_diff() functions
Years  : 1
Months : 1
Days   : 17

Using custom PHP Source code
Years  : 1
Months : 1
Days   : 20

Και τέλος ο κώδικας…

<?php
header('Content-type: text/plain');
date_default_timezone_set('Europe/Athens');

//----------------------------------------------------------------------------
$dtStart = mktime(0,0,0,1,31,2012); //31/01/2012
$dtStop = mktime(0,0,0,3,20,2013);  //20/03/2013
$daySecs = 24 * 60 * 60;

echo PHP_EOL;
echo 'Start Date: ',strftime('%d/%m/%Y',$dtStart),PHP_EOL;
echo 'End Date : ',strftime('%d/%m/%Y',$dtStop),PHP_EOL,PHP_EOL;

//----------------------------------------------------------------------------
echo 'Using DateTime::Diff() or date_diff() functions',PHP_EOL;
$dtStart = date_date_set(date_create(),2012,1,31); //31/01/2012
$dtStop = date_date_set(date_create(),2013,3,20); //20/03/2013
$diff = date_diff($dtStart,$dtStop);
echo 'Years : ',$diff->y,PHP_EOL,
'Months : ',$diff->m,PHP_EOL,
'Days : ',$diff->d,PHP_EOL,PHP_EOL;
unset($diff);

//----------------------------------------------------------------------------
echo 'Using custom PHP Source code',PHP_EOL;
function dmydiff($dateS, $dateE)
{
    $dS = getdate($dateS);
    $dE = getdate($dateE);

    $DMY = array('Y'=>0, 'M'=>0, 'D'=>0);

    $DMY['Y'] = $dE['year'] - $dS['year'];
    $DMY['M'] = $dE['mon'] - $dS['mon'];
    $DMY['D'] = $dE['mday'] - $dS['mday'];

    if ($DMY['D'] < 0)
    {
        $dT = mktime(0,0,0,$dS['mon']+1,1,$dS['year']);
        $dT = intval(($dT - $dateS) / (24*60*60));
        $DMY['D'] =  $dT + $dE['mday'] - 1;
        $DMY['M']--;
    }
    if ($DMY['M'] < 0)
    {
        $DMY['Y']--;
        $DMY['M'] += 12;
    }

    return $DMY;
}

$dtStart = mktime(0,0,0,1,31,2012); //31/01/2012
$dtStop = mktime(0,0,0,3,20,2013);  //20/03/2013
$diff = dmyDiff($dtStart, $dtStop);
echo 'Years : ',$diff['Y'],PHP_EOL,
'Months : ',$diff['M'],PHP_EOL,
'Days : ',$diff['D'],PHP_EOL,PHP_EOL;
unset($diff);
//----------------------------------------------------------------------------

?>

pdo σύνδεση σε sql server 2005

Έκανα μια δοκιμή σε Ubuntu server να συνδεθώ σε sql server 2005 μέσω pdo και όχι με τις mssql_* functions. Αν και η σύνδεση έπαιξε αμέσως μια χαρά και έβλεπα ελληνικά (utf8) από την php χρησιμοποιώντας τις mssql functions, από το pdo είχα ένα περίεργο πρόβλημα:

Τρέχοντας τον κώδικα από το shell έβλεπα στο output κανονικά τα ελληνικά, αλλά τρέχοντας τον κώδικα από τον apache η ιστοσελίδα μου έφερνε μόνο ερωτηματικά ????????????

Μετά από ψάξιμο μιας μέρας και αρκετές δοκιμές η λύση τελικά ήταν στο connection string. Για να βλέπεις τα ελληνικά αρκεί να προσθέσεις το ;charset=utf8"

<?php
    try {
        $hostname = 'Ο sql server';
        $dbname = 'Η βάση δεδομένων';
        $username = '...';
        $pw = '...';

        $dbh = new PDO (
                "dblib:host=$hostname;dbname=$dbname;charset=utf8",
                "$username",
                "$pw");
    } catch (PDOException $e) {
        echo "Failed to get DB handle: " . $e->getMessage() . "n";
        exit;
    }
    $stmt = $dbh->prepare('SELECT * FROM users');
    $stmt->execute();
    while ($row = $stmt->fetchobject())
    {
        print_r($row);
    }
    unset($dbh);
    unset($stmt);
?>

Δι@ύγεια OpenData API – PHP Version

Δοκίμασα να κάνω μια διαφορετική δοκιμή να χρησιμοποιήσω το OpenData API της δι@ύγειας σε php αυτή τη φορά μήπως και έχω περισσότερη τύχη. Μετά από δοκιμές και άπειρα “500 internal errors” κατέληξα σε αυτά τα δύο κομμάτια κώδικα (μη ρωτήσετε που τα βρήκα, ούτε που θυμάμαι, κάπου στο internet) με όνομα works που δείχνει να δουλεύει και με όνομα fails που αρνείται πεισματικά και επιστρέφει πάντα 500 internal error.

<?php 
$ada = 'Β4ΩΛΧ-ΨΚΒ'; 
$url = 'http://opendata.diavgeia.gov.gr/api/decisions?ada='.urlencode($ada); 

function works($url) 
{ 
   $ch = curl_init(); 
   curl_setopt($ch, CURLOPT_URL,$url); 
   curl_setopt($ch, CURLOPT_HEADER, false); 
   curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); 
   $xmlstr = curl_exec($ch); 
   curl_close($ch); 

   return $xmlstr; 
} 

function fails($url) 
{ 
   $xmlstr = file_get_contents($url); //<-- line 19
   return $xmlstr; 
} 

$xml1 = simplexml_load_string(works($url)); 
$xml2 = simplexml_load_string(fails($url)); 

print_r($xml1); 
print_r($xml2); 
?>

Στο ini to allow_url_fopen το έχω on. Εκανα και το allow_url_include on (που δεν χρειάζεται αλλά να υπάρχει), έβαλα και το user_agent=”PHP” μιας και το ανέφερε και αυτό κάποιος στο documentation της file_get_contents.

Αυτό που παίρνω όταν τρέχω το αρχείο από κονσόλα είναι:

[dva@test ~]# php diavgeia.php 
PHP Warning:  file_get_contents(http://opendata.diavgeia.gov.gr/api/decisions?ada=%CE%924%CE%A9%CE%9B%CE%A7-%CE%A8%CE%9A%CE%92): failed to open stream: HTTP request failed! HTTP/1.1 500 Internal Server Error 
 in /var/www/html/test/xml/diavgeia.php on line 19 
SimpleXMLElement Object 
( 
    [queryInfo] => SimpleXMLElement Object 
        ( 
            [count] => 1 
            [from] => 1 
            [order] => desc 
            [total] => 1 
        ) 
)

Το οποίο δείχνει ότι η function works πέρασε, η fails κράσαρε κάτι στον server της διαύγειας, και μετά τυπώνει το xml που διάβασε η works, (για τη fails δε δείχνει τίποτα).

PHP Password generator extension

Και το αντίστοιχο password generator σε php extension για να υπάρχει παντού διαθέσιμο χωρίς να χρειάζεται includes και copy/paste, αλλά και να είναι λίγο ή πολύ πιο γρήγορο από την αντίστοιχη function.

Δημιουργούμε ένα νέο φάκελο passwd και εκεί μέσα δημιουργούμε τα εξής αρχεία:

config.m4

PHP_ARG_ENABLE(passwd, whether to enable passwd support, [ --enable-passwd Enable passwd support])

if test "$PHP_PASSWD" = "yes"; then
  AC_DEFINE(HAVE_PASSWD, 1, [Whether you have passwd])
  PHP_NEW_EXTENSION(passwd, passwd.c, $ext_shared)
fi

INC_CHECK_DIRS="/usr /usr/local"

for i in $INC_CHECK_DIRS ; do
  if test -f $i/include/php/ext/standard/php_rand.h; then
    PHP_ADD_INCLUDE($i/include/php/ext/standard)
    break
  fi
done

passwd.h

#ifndef __PASSWD_H__
#define __PASSWD_H__ 1
#ifndef _WIN32
#include
#endif
#include
#ifdef ZTS
#include "TSRM.h"
#endif

#ifndef BOOL
#define BOOL	short
#endif //BOOL
#ifndef FALSE
#define FALSE	(0)
#endif
#ifndef TRUE
#define TRUE	(1)
#endif

#define PHP_PASSWD_WORLD_VERSION "1.0.0"
#define PHP_PASSWD_WORLD_EXTNAME "passwd"

PHP_FUNCTION(passwd_version);
PHP_FUNCTION(passwd_create);

PHP_MINIT_FUNCTION(passwd);
PHP_MINFO_FUNCTION(passwd);

extern zend_module_entry passwd_module_entry;
#define phpext_passwd_ptr &passwd_module_entry

#endif //__PASSWD_H__

passwd.c

#include "php.h"
#include "php_rand.h"

#ifdef _WIN32
#include "ext/standard/info.h"
#endif

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include "passwd.h"

#ifndef LONG
typedef long LONG;
#endif

static function_entry passwd_functions[] = {
    PHP_FE(passwd_version, NULL)
    PHP_FE(passwd_create, NULL)
    {NULL, NULL, NULL}
};

zend_module_entry passwd_module_entry = {
#if ZEND_MODULE_API_NO >= 20010901
    STANDARD_MODULE_HEADER,
#endif
    PHP_PASSWD_WORLD_EXTNAME,
    passwd_functions,
    PHP_MINIT(passwd),
    NULL,
    NULL,
    NULL,
    PHP_MINFO(passwd),
#if ZEND_MODULE_API_NO >= 20010901
    PHP_PASSWD_WORLD_VERSION,
#endif
    STANDARD_MODULE_PROPERTIES
};

#ifdef COMPILE_DL_PASSWD  
ZEND_GET_MODULE(passwd)
#endif

char* passwordChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-_=+[]{}\|,<.>/?~;:";
int passwordCharsLen = 0; 

static void ZEND_MODULE_GLOBALS_CTOR_N(passwd)(void *passwd_globals TSRMLS_DC)
{
    //php_srand( time(NULL) );  
}

PHP_MINIT_FUNCTION(passwd)
{
    passwordCharsLen = strlen(passwordChars);
    return SUCCESS;  
}

PHP_MINFO_FUNCTION(passwd)
{
    php_info_print_table_start();
    php_info_print_table_row(2, "passwd", "passwd Functions");
    php_info_print_table_row(2, "passwd_create", "return a random password string");
    php_info_print_table_end();
}

PHP_FUNCTION(passwd_version)
{
    RETURN_STRING(PHP_PASSWD_WORLD_VERSION, 1);
} 

PHP_FUNCTION(passwd_create)
{
    long i, llen, rnd_idx;
    char* tmp;
    if (ZEND_NUM_ARGS() != 1) {
        WRONG_PARAM_COUNT;
    } 
    llen = 8;
    if ((zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &llen) == FAILURE) ||
        (llen < 4) || (llen > 128))
    {
        RETURN_STRING("len should be an integer between 4 and 128", 1);
    } 

    tmp = emalloc(llen+1);

    for (i=0; i<llen; i++)
    {
        rnd_idx = php_rand(TSRMLS_C);
        RAND_RANGE(rnd_idx, 0, passwordCharsLen-1, PHP_RAND_MAX);
        tmp[i] = passwordChars[rnd_idx];
    }
    tmp[i]=(char)0; 
    RETURN_STRING(tmp, 0);
}

Τώρα o αντίστοιχος κώδικας του σχετικού post θα μπορούσε να γίνει ως εξής:

<?php
header('Content-type: text/plain');
    if (isset($_GET['len'])) $len = (int)$_GET['len'];
    if (($len < 4) || ($len > 128)) $len = 8;
    echo passwd_create($len);
?>

PHP password generator

Χρειάστηκα σήμερα έναν password generator, γιατί ήθελα να δώσω passwords σε μια λίστα από emails που έφτιαχνα, και δεν μου πέρασε καν απο το μυαλό ότι το συγκεκριμένο το έχουν χρειαστεί χιλιάδες πριν από μένα. Οπότε ξεκίνησα να γράφω κώδικα και ιδού:

<?php
header('Content-type: text/plain');

function generatePassword($len)
{
    $passwordChars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890!@#$%^&*()-_=+[]{}\|,<.>/?`~;:';
    $passwordCharsLen = strlen($passwordChars);
    $tmp = '';
    for ($i=0; $i < $len; $i++)
    {
        $x = rand(1, $passwordCharsLen);
        $tmp .= $passwordChars[$x-1];
    }
    return $tmp;
}

    if (isset($_GET['len'])) $len = (int)$_GET['len'];
    if (($len < 4) || ($len > 128)) $len = 8;
    echo generatePassword($len);
?>

Ισως βέβαια το να έψαχνα και να δοκίμαζα τι δουλεύει και τι όχι να μου έπαιρνε περισσότερο χρόνο απ΄ όσο μου πήρε να κάτσω να το γράψω μόνος μου, αλλά δεν πρόκειται να το μάθω ποτέ…

Ελεγχος Εγκυρότητας Α.Φ.Μ. (PHP Version)

Απλώς για να υπάρχει διαθέσιμο σε όποιον το χρειαστεί, η php version του κώδικα που υπάρχει στο άρθρο Ελεγχος Εγκυρότητας Α.Φ.Μ.

<?php
    function CheckAFM($afm)
    {
        if (!preg_match('/^(EL){0,1}[0-9]{9}$/i', $afm))
            return false;
        if (strlen($afm) > 9)
            $afm = substr($afm, 2);

        $remainder = 0;
        $sum = 0;

        for ($nn = 2, $k = 7, $sum = 0; $k >= 0; $k--, $nn += $nn)
            $sum += $nn * ($afm[$k]);
        $remainder = $sum % 11;

        return ($remainder == 10) ? $afm[8] == '0'
                                  : $afm[8] == $remainder;
    }
?>

Εχει μερικές μικροδιαφορές από τις C, C# Versions, αλλά ήταν απαραίτητο αφού προοριζόταν για χρήση σε ιστοσελίδα…

WordPress plugin Quick ‘n’ Dirty

Ηθελε ένας συμφορουμίτης στο freestuff.gr που είμαι μέλος να προσθέσει ένα custom widget για να παίρνει κάποια στατιστικά από ένα άλλο plugin (GD Star Rating) που είχε εγκαταστήσει, και έψαχνε για κάποιον να του φτιάξει ένα νέο plugin που να μπορεί να διαβάσει τα στοιχεία από το υπάρχον και να τα εμφανίζει με κάποιον custom τρόπο που ήθελε.
Το να κάτσεις να κάνεις ένα νέο plugin που να βγαίνει στη sidebar του wordpress blog σαν widget είναι αρκετή δουλειά και έχει και αρκετή χαμαλοδουλειά πέρα από τις λίγες απαιτήσεις γνώσεων που έχει για php και mysql. Continue reading

PHP Extension – Ευρώ Ολογράφως

Χρησιμοποιώντας περιστασιακά (ubuntu) linux και php, σε μια στιγμή χαλαρότητας, είπα να δοκιμάσω να δουλέψω λίγο με την php. Να προσπαθήσω να προσθέσω κάποιες συναρτήσεις επιπλέον, όχι όμως σαν php source κώδικα, αλλά σαν extension module. Οι βασικοί λόγοι ήταν 3.
1ον) Δεν έχω κάποιον (αφεντικό ή πελάτη) πάνω από το κεφάλι μου να με πιέζει να παραδώσω χθές.
2ον) php sources γράφει και η κουτσή μαρία. php extensions όμως είναι λίγοι αυτοί που γράφουν, και ήθελα να δω πόσο εύκολο είναι να μην είσαι ένας από τους πολλούς, να ξεχωρίσεις από το μπουλούκι.
3ον) μια function μέσα σε ένα compiled php module τρέχει πιο γρήγορα από μια που γίνεται parse κάθε φορά. Το πόσο πιο γρήγορα θα κάτσω άλλη φορά να ασχοληθώ (αν βρώ χρόνο και κυρίως όρεξη). Continue reading