November 22, 2008

Get File's Total Page Number From PHP

Now it's time to combine the previous two topic(topic1, topic2) together and write a PHP code that gets a file's total page number.

First we must find the file's mime type. And as i explained in this topic, we use fileinfo or file command from Linux console to get the mime type of the file like;
if(function_exists('finfo_file')){
$finfo = finfo_open(FILEINFO_MIME);
$file_type = finfo_file($finfo, $file);
finfo_close($finfo);
}else{
echo "Pecl Fileinfo package not found!!! Trying to get file mime type from Linux Console\r\n";
$file_type = trim(exec("file -bi " . escapeshellarg($file)));
}


if(stripos($file_type, "\\012- ") !== false)
$file_type = substr($file_type, stripos($file_type, "\\012- ")+6, strlen($file_type));


Then we coupled the file's mime type from our predefined mime types;
//Our predefined mime types
var $image_formats = array("image/jpeg", "image/gif", "image/bmp");
var $file_formats = array("application/octet-stream", "application/vnd.ms-excel", "application/msword", "application/vnd.ms-powerpoint", "text/plain", "application/rtf", "text/html");
//check to know which function we use to convert the file to pdf
if(in_array($file_type, $this->image_formats)){
$file = $this->imageProcessing($file);
}else if(in_array($file_type, $this->file_formats)){
$file = $this->fileProcessing($file);
}


In imageProcessing function we convert the image files like jpegs, gifs, bmps to pdfs as i explained in this topic like;
private function imageProcessing($file){
$file_allinfo = pathinfo($file);
$file_pdf = $file_allinfo['dirname'] . "/" . $file_allinfo['filename'] . "_converted.pdf";
exec('convert ' . $file . " " . $file_pdf);
return $file_pdf;
}

and in fileProcessing function we convert the Microsoft Office files or html files etc to pdfs as i explained in this topic like;
private function fileProcessing($file){
$file_allinfo = pathinfo($file);
$file_pdf = $file_allinfo['dirname'] . "/" . $file_allinfo['filename'] . "_converted.pdf";
exec('python ./DocumentConverter.py ' . $file . " " . $file_pdf);
return $file_pdf;
}

But in order to run the function above, we mustn't forget to run OpenOffice at port 80 as i explained before;
openoffice "-accept=socket,host=localhost,port=8100;urp;StarOffice.ServiceManager" -norestore -nofirststartwizard -nologo -headless &

And the last part that gets the total page number info and deletes the pdf file;
//this $file variable contains the path of pdf file that i return from one of my function
$file_allinfo = pathinfo($file);
$file_path_and_name = $file_allinfo['dirname'] . "/" . $file_allinfo['filename'];
exec("pdfinfo ". $file . " | grep Pages: | awk '{print $2}' | tail -n1", $output ,$retval);
$total_page_count = str_replace(" ", "", $output[0]);
unlink($file) or die("Unable To Delete Created File!\r\n");


I write this example as a PHP class, if you want to use it just create an object and pass it's function the file's path like;
require ('PageCount.php');
$c_pagecount = new page_count_class();
$v_totalpage = $c_pagecount->pageCounting("./sample.doc");
var_dump($v_totalpage);


Here
you can get some sample files, with sample test code and my class file.

Linux Get All Types Of Files Total Page Numbers (Almost All Types)

In order to get the total page of a document which is to be faxed or mailed, you can use OpenOffice export tools, imagemagick and some Linux console commands together.
It is easy to get total page numbers of files by converting all files to pdf and use Linux's 'pdfinfo' console command. But it isn't easy to convert all files to pdf, especially the Microsoft Office ones. In order to convert Microsoft Office documents, you must have OpenOffice in your system. And you must run OpenOffice at background by this command;
openoffice "-accept=socket,host=localhost,port=8100;urp;StarOffice.ServiceManager" -norestore -nofirststartwizard -nologo -headless &

Then with this code that i found from here, you can convert excel, word, powerpoint, rtf, txt, html files to pdf files over OpenOffice with Python from Linux Console like;
python ./DocumentConverter.py sample.doc sample.pdf

In order to run the code above you must first run OpenOffice as i mentioned before.
Also if you need to convert image files to pdf files and want to get their total page numbers, you can use imagemagick's convert command from Linux console;
convert sample.jpg sample.pdf

After converting the files to pdfs, you can get the total page of file by;
pdfinfo sample.pdf | grep "Pages:" | awk '{print $2}' | tail -n1

November 21, 2008

PHP-Pecl FileInfo Package Installation Ubuntu

To get a file's mime type within a php code, you can use mime_content_type(), but it is deprecated. So instead of it you can use Pecl/FileInfo package. In order to install FileInfo package to your Ubuntu system, you need to install these packages first (i assume you already have apache2, php5, libapache2-mod-php5 etc);

build-essential (this gets rid of => C compiler cannot create executables)
php5-dev (this gets rid of => sh: phpize: command not found)
php5-pear
libmagic-dev (this gets rid of =>
checking for magic files in default path... not found
configure: error: Please reinstall the libmagic distribution
ERROR: `/tmp/pear/cache/Fileinfo-1.0.4/configure' failed)

libmagic1

Then you do as root;
pear channel-update pear.php.net
pecl install Fileinfo


Then within your php.ini files (/etc/php5/apache2/php.ini and /etc/php5/cli/php.ini), you add this line;
extension=fileinfo.so

And lastly as root we will copy these files;
cp /usr/share/file/magic.mime /etc/magic
cp /usr/share/file/magic.mime /etc/magic.mime


Start the apache server and you are ready to go;
/etc/init.d/apache2 restart

And here is the php code to get file's mime type;
$finfo = finfo_open(FILEINFO_MIME);
$mime_type = finfo_file($finfo, $file_path);
finfo_close($finfo);

C compiler cannot create executables

C compiler cannot create executables

If you are facing with this error while compiling some packages in ubuntu, just do;

aptitude install build-essential

/usr/bin/ld: crt1.o: No such file: No such file or directory collect2: ld returned 1 exit status

/usr/bin/ld: crt1.o: No such file: No such file or directory
collect2: ld returned 1 exit status


If you are using ubuntu and faced with an error message like this while compiling your c code, just install libc6-dev package.

sudo aptitude install libc6-dev

November 18, 2008

Unknown Role class: PEAR_Installer_Role_Pear_Installer_role_test

If you ever faced with this problem(Unknown Role class: PEAR_Installer_Role_Pear_Installer_role_test) while installing some pear package like OLE, just do;
export LC_ALL="C"
export LANG="C"
pear install OLE


also this command may not work then use;
pear install channel://pear.php.net/OLE-1.0.0RC1

and also if you ever faced with this while compiling PHP;
Fatal error: Call to undefined method PEAR_Registry::packageinfo() in phar://install-pear-nozlib.phar/PEAR/Dependency2.php on line 659
make[1]: *** [install-pear-installer] Error 255
make : *** [install-pear] Error 2

the same solution above is worked too;
export LC_ALL="C"
export LANG="C"
make install

Just A Little Warning About PhpExcelWriter

I wrote how to get rid of UTF-8 character encoding problem while reading Excel files with PhpExcelReader. Now i want to warn you about numerics in PhpExcelWriter. For example when i write an 11 character word or a bigger one to the Excel file;
902321111111
it is always showed in excel file;
9,02321E+11
If you faced a problem like it, just write this value to the excel file not by write function;
$workSheet->write(0, 0, $value);
write it by writeString function;
$workSheet->writeString(0, 0, $value);
So the whole code seems like;
require_once("Spreadsheet/Excel/Writer.php");
$workbook = & new Spreadsheet_Excel_Writer();
$workbook->send('excel.xls');
$workbook->setVersion(8);

$worksheet = & $workbook->addWorksheet('Sheet1');
$worksheet->setInputEncoding('UTF-8');

$workSheet->writeString(0, 0, "902321111111");
$workbook->close();

PhpExcelReader UTF-8 Problem HOW TO

At one of my works i had to read Excel files and write their contents to database for a Turkish company. The site's encoding is UTF-8 and the table's encoding is described as 'utf8_turkish_ci'.
I used the PhpExcelReader to read Excel files and i wrote down this code from their examples;
require_once('Excel/reader.php');
$data = new Spreadsheet_Excel_reader();
$data->setOutputEncoding('UTF-8');
$data->read($file_path);


but always when PhpExcelReader saw a Turkish character it stopped reading. So i decided that there may be an encoding mistake, so first i changed the 'outputEncoding's value. But it didn't change anything, also vitiated the words spellings. So i put another encoding conversion while it was reading the Excel files content.

for ($i = 2, $j = 0; $i <= $data->sheets[0]['numRows']; $i++, $j++) {
$value = mb_convert_encoding($data->sheets[0]['cells'][$i][$value_row], "UTF-8", "ISO-8859-9");
}

So that's it. After putting these conversions the contents are saved straightly. Also here is a good trick for ya;

After the excel file is uploaded to the system check all the first rows and ask user to couple them with your database rows from dropdown lists. After user couples the excel rows with database rows, go start from the 2nd row of excel file to read, and save the selected rows to database rows and then get 3rd and 4th etc. So you not need to enforce the user to obey your standarts.

Prado PHP Framework HOW TO 5 - TDataGrid with TDropDownList, TCheckBox

One of the good component's of Prado is it's DataGrid. But i must admit, it refreshes the page so much. In this point you'll understand how javascript is good. But for the one's who dealed with the same problem that how to use TCheckBox or TDropDownList in TDataGrid, i want to explain how i overcome it in here, not how javascript is better.

In here i use basics of TDataGrid if you want to see more about TDataGrid, you can look here.

Also to use this example i define a database schema named as 'test' and username and password also named as 'test'. Then i define 2 tables in my schema, one for items and one for types. Items have type_id's as one of their row. So we can get the values from two tables at the same time while using drop down column in our data grid. I also include the sql file to the source code.

First we define our data grid component;
<com:TDataGrid
ID="DataGrid"
DataKeyField="ID"
AutoGenerateColumns="false"
OnItemCreated="itemCreated"
OnEditCommand="editItem"
OnUpdateCommand="saveItem"
OnDeleteCommand="deleteItem"
OnCancelCommand="cancelItem"
>


Then we define our components that'll be in our data grid;
----------------------------The checkbox--------------------------------
<com:TTemplateColumn ID="checkbox_column">
<prop:ItemTemplate>
<com:TCheckBox ID="select" />
<com:THiddenField ID="item_id" />
</prop:ItemTemplate>
</com:TTemplateColumn>


-------------------------------Edit Column-------------------------------
<com:TEditCommandColumn
UpdateText="Save"
EditText="Edit"
CancelText="Cancel"
/>


------------------------------Drop Down List Column--------------------
<com:TDropDownListColumn
ID="dropdown_column"
DataTextField="type_name"
ListDataSource=<%= $this->LoadDropDown() %>
ListValueField="type_id"
/>


------------------------------Text Box Column----------------------------
<com:TBoundColumn
ID="textbox_column"
DataField="item_name"
/>


------------------------------Delete Column-------------------------------
<com:TButtonColumn
ID="delete_column"
Text="Delete"
CommandName="delete"
/>


At the end we close the data grid component's tag.
</com:TDataGrid>

And we define a button to delete the selected one's.
<com:TButton ID="delete_selecteds"
Text="Delete Selecteds"
onClick="DeleteSelecteds"
/>


And we mustn't forget to enclose our TDataGrid and TButton in TForm component. Now our html page is ready, so get going to write the php page.

We define a local variable to populate our data grid everytime and onLoad function first;
private $_data=null;
public function onLoad($param){
parent::onLoad($param);
if(!$this->IsPostBack){
$this->DataGrid->DataSource=$this->Data;
$this->DataGrid->dataBind();
}
}


We bind the data we have, to our data grid, above. Then comes our second function that creates a TList component and populates our drop down list column in our data grid with it;
public function LoadDropDown(){
$db_connection = $this->Application->Modules['dbconnection']->Database;
$db_connection->Active = true;

$sql_query = "SELECT * FROM types";
$command = $db_connection->createCommand($sql_query);
$db_records = $command->query();

$data=new TList; $i=0;
foreach($db_records as $key)
$data->add(array('type_id'=>$key["type_name"]));

$db_connection->active = false;
return $data;
}


After that we started to define our public functions that are called by our data grid component when a delete, update, save or cancel command comes;
public function itemCreated($sender,$param){
$item=$param->Item;
if($item->ItemType==='EditItem'){
$item->textbox_column->TextBox->Columns=10;
}
if($item->ItemType==='Item' || $item->ItemType==='AlternatingItem' || $item->ItemType==='EditItem'){
$item->delete_column->Button->Attributes->onclick='if(!confirm(\'Are you sure?\')) return false;';
}
}

This function above, provides a confirm box to our delete buttons to check if person is sure to delete the item.

public function editItem($sender,$param){
$this->DataGrid->EditItemIndex=$param->Item->ItemIndex;
$this->DataGrid->DataSource=$this->Data;
$this->DataGrid->dataBind();
}

With this function above, we open the text boxes, drop down lists instead of the items. So user can edit them.

public function saveItem($sender,$param){
$item=$param->Item;
if($this->_data===null)
$this->loadData();

$updateRow=null;
foreach($this->_data as $index=>$row)
if($row['ID']===$this->DataGrid->DataKeys[$item->ItemIndex])
$updateRow=&$this->_data[$index];

if($updateRow!==null){
$old_typename = $updateRow['type_name'];
$old_itemname = $updateRow['item_name'];
}

$new_typename = $item->dropdown_column->DropDownList->SelectedValue;
$new_itemname = $item->textbox_column->TextBox->Text;

$db_connection = $this->Application->Modules['dbconnection']->Database;
$db_connection->Active = true;
$transaction = $db_connection->beginTransaction();
try{
$sql_query = "Select type_id from types where type_name='". $new_typename ."'";
$command = $db_connection->createCommand($sql_query);
$new_typeid = $command->queryScalar();

$sql_query = "Select type_id from types where type_name='". $old_typename ."'";
$command = $db_connection->createCommand($sql_query);
$old_typeid = $command->queryScalar();

$sql_query = "Select item_id from items where item_type='" . $old_typeid . "' and item_name='". $old_itemname
."'";
$command = $db_connection->createCommand($sql_query);
$item_id = $command->queryScalar();

$sql_query = "update items set item_name='". $new_itemname ."', item_type='". $new_typeid ."' where item_id='
". $item_id ."'";
$command = $db_connection->createCommand($sql_query);
$command->execute();
$transaction->commit();
}catch(Exception $ex){
$transaction->rollback();
var_dump("UPPSSS Update Failed");
return;
}

$this->updateGrid(
$this->DataGrid->DataKeys[$item->ItemIndex],
$new_typename,
$new_itemname
);

$this->DataGrid->EditItemIndex=-1;
$this->DataGrid->DataSource=$this->Data;
$this->DataGrid->dataBind();
$db_connection->Active = false;
}

With this function above, if user clicks the save button in edit mode, we first find the old values of the item and then find the item's id. Then we get the new values of the item from text box and drop down list and update the item with them.

public function cancelItem($sender,$param){
$this->DataGrid->EditItemIndex=-1;
$this->DataGrid->DataSource=$this->Data;
$this->DataGrid->dataBind();
}

With this function above, if user clicks the cancel button in edit mode, we do nothing and refresh the list.

public function deleteItem($sender,$param){
$this->deleteFromGrid($this->DataGrid->DataKeys[$param->Item->ItemIndex]);
$this->DataGrid->EditItemIndex=-1;
$this->DataGrid->DataSource=$this->Data;
$this->DataGrid->dataBind();
$this->response->reload();
}

With this function above, if user clicks the delete button we delete the item at this index.

public function deleteSelecteds(){
foreach($this->DataGrid->Items as $i){
if($i->checkbox_column->select->Checked)
$this->deleteFromGrid($this->DataGrid->DataKeys[$i->ItemIndex]);
}
$this->response->reload();
}

With this function above, if user clicks our 'Delete Selecteds' button we walk through the indexes whom their checkbox's clicked and delete them one by one.

Other functions are implementation details, that's why they defined as 'protected';
protected function getData(){
if($this->_data===null)
$this->loadData();
return $this->_data;
}


protected function loadData(){
$db_connection = $this->Application->Modules['dbconnection']->Database;
$db_connection->Active = true;

$sql_query= "SELECT item_id, item_name, item_type FROM items";
$command = $db_connection->createCommand($sql_query);
$db_records = $command->query(); $i = 0;
foreach($db_records as $key){
$sql_query = "SELECT type_name FROM types where type_id='" . $key["item_type"] . "'";
$command = $db_connection->createCommand($sql_query);
$type_name = $command->queryScalar();
$array[$i] = array(
'ID'=>$i+1,
'type_name'=>$type_name,
'item_name'=>$key["item_name"],
);
$i++;
}

$this->_data = $array;
$this->saveData();
$db_connection->active = false;
}

With this function above we populate our datagrid from our mysql server.

protected function saveData(){
$this->setViewState('Data',$this->_data);
}


protected function updateGrid($id, $type_name, $item_name){
if($this->_data===null)
$this->loadData();
$updateRow=null;
foreach($this->_data as $index=>$row)
if($row['ID']===$id)
$updateRow=&$this->_data[$index];
if($updateRow!==null){
$updateRow['type_name']=$type_name;
$updateRow['item_name']=$item_name;
$this->saveData();
}
}

With this function above we update the values of the item that is at that index.

protected function deleteFromGrid($id){
if($this->_data===null)
$this->loadData();
$deleteIndex=-1;
foreach($this->_data as $index=>$row)
if($row['ID']===$id){
$deleteIndex=$index;
$deleteRow = &$this->_data[$index];
}
if($deleteIndex>=0){
unset($this->_data[$deleteIndex]);
if($deleteRow!==null){
$old_typename = $deleteRow['type_name'];
$old_itemname = $deleteRow['item_name'];
}

$db_connection = $this->Application->Modules['dbconnection']->Database;
$db_connection->Active = true;

$sql_query = "Select type_id from types where type_name='" . $old_typename . "'";
$command = $db_connection->createCommand($sql_query);
$type_id = $command->queryScalar();
$transaction = $db_connection->BeginTransaction();

try{
$sql_query = "delete from items where item_name='". $old_itemname ."' and item_type='". $type_id ."'"
;
$command = $db_connection->createCommand($sql_query);
$command->execute();
$transaction->commit();
}catch(Exception $ex){
$transaction->rollBack();
var_dump("UPPSSS Delete Failed");
return;
}
$this->saveData();
$db_connection->Active = false;
}

With this function above we delete the item that is at that index.

Here is the source code with the mysql dump of the database we used in the example. Also to run the application you need to copy Prado's directory to the same place with the datagrid directory.

Prado PHP Framework HOW TO 4 - MYSQL Everything (Almost)

In order to connect to a mysql server within your Prado application, first you need to define your Connection String in your application.xml file;
<module id="dbconnection" class="System.Data.TDataSourceConfig">
<database ConnectionString="mysql:host=YOURHOST;dbname=DBTOCONNECT" Username="YOURUSERNAME" Password="YOURPASSWORD" />
</module>


Then when you want to connect to your mysql server within one of your php file's, you just use this connection string;
$db_connection = $this->Application->Modules['dbconnection']->Database;
$db_connection->Active = true;


Then you are ready to go, first we preapare our query;
$sql_query = "";
$command = $connection->createCommand($sql);


Then run it as what it is;
------For select queries
$db_records = $command->query();

------For insert, update, delete queries
$command->execute();

After select queries, you can get the results by;
foreach($db_records as $key){
$key["row_name"];
}


And also if you are using InnoDB as your storage engine, you can use transactions and rollback from the states that throws exceptions. It's possible for MyISAM too but you must write down your own implementation that follows the running queries and when the time comes rollback them. Because when i searched for if MyISAM'll support transactions, i found that the programmers won't think anything about it because they developed them as they are, for higher speed and light applications MyISAM and for secured business applications InnoDB. If you want to look more for differences, you can look here. And here is how you can use transactions within your PHP code in Prado;

First we enclose our sql queries within try-catch block;
try{
}catch(Exception $ex){
}


Then after creating our connection object, we start transaction on it;
$transaction = $db_connection->beginTransaction();

At the end if some of our code fails and throws an exception, we rollback the operations in our catch block;
$transaction->rollBack();

And of course to close the connection;
$db_connection->Active = false;

Then our code now looks like;
$db_connection = $this->Application->Modules['dbconnection']->Database;
$db_connection->Active = true;
try{
$transaction = $db_connection->beginTransaction();
$sql_query = "";
$command = $connection->createCommand($sql);
$command->execute();
}catch(Exception $ex){
$transaction->rollBack();
}
$db_connection->Active = false;

Also you can enclose these code to another try catch block. It is good to see an Error Message instead of a whole Php-Prado Exception for our user's sake i think :)

Prado PHP Framework HOW TO 3 - Store a Value To A Global Variable

To store a value to a Global Variable in Prado you can do;
$this->application->setGlobalState("variable", "value");

and to get it from another page in your application;

$this->application->getGlobalState("variable");

that's it.

Prado PHP Framework HOW TO 2 - File Hierarchy

Before writing some piece of code here, i try to explain file hierarchy of our application so it will be easy to understand i think.

Our application's web pages are under application_directory/protected/pages. Our application's configuration file is application_directory/protected/application.xml.

Our web pages are consisted from 2 files, one page file and one php file. It's good for the ones whom really get used to write ASP.Net codes. Because all the html and php codes will be separated so. We write our php code's to php file and write html codes to html file. In order to attain to html page from our php code we use Prado's components. For example if we want to put a textbox on our html page and want to change it's value by clicking a button;

We first define a text box and a button component at our page;
<com:TForm>
<com:TTextBox id="textbox" />
&nbsp;
<com:TButton Text="Try" OnClick="changeTextBoxValue" />
</com:TForm>


The text box must be defined within form tag, if it's not, prado will throw an exception about it.
Now we define our function that our button component calls when it'll be clicked in our php page.

public function changeTextBoxValue(){
$this->textbox->Text = "Hello";
}

also this function must be within our page class that is inherited from Prado's TPage.

class Home extends TPage{

}


This is going to be a Prado tutorial so i want to end it here and want to write some useful bunch of codes about Prado. If you want to go with tutorials, this will be the point to it. Also here is the code we write down up there. To run the code Prado must be at same place where the project code is.

Prado PHP Framework HOW TO 1 - Create Skeleton Code

I once used Prado, a PHP Framework, at one of my works. I really liked it, because of its documentation and demos. If you really want to check it out, here is the address.
The first thing to begin with Prado, you must build your application's skeleton by the way Prado expects;

-Your Application Directory
---assets directory
---protected directory
-------pages directory
-------runtime directory
---index php-file

But don't really worry about it, you can use prado's command line tool 'prado-cli.php'. For example let's say that we'll start a new project named 'firstproject' and we want to create the application's skeleton;

First we must be sure, for linux if php5-cli was installed to our system and for windows if php.exe's path is added to environment variables. After that we copy the prado's directory to our local directory. For my Apache web server in Linux it is '/var/www/'. So let's see;

For Linux;
cd /var/www/
cp -R path-to-prado ./
php prado/framework/prado-cli.php -c firstproject

After this command prado automatically creates the skeleton of your application and create the necessary files. The rest is for you to arrange them for your needs, that's it.

November 15, 2008

Python Web Services - HOW TO 4 - XML-RPC Client

I tried to explain how to write web service server code with Python using ZSI and XML-RPC before and also i explained how to write a web service client code with Python using ZSI too. Now i want to explain how to write a web service client code with Python using XML-RPC lib.

It is simple than using ZSI again. We just first import our xmlrpclib module;

#!/usr/bin/python

import xmlrpclib

Then we give the url and create a server object;

server = xmlrpclib.Server("http://localhost/cgi-bin/index.py")

and lastly we request to the methods we want from web service with this object;

print server.asillyfunction("hello world")

Also there are methods in xmlrpclib like, to see which methods are the web service provides;

for method in server.system.listMethods():

print method

Here is the sample code. And here is a better client code. Also i want to mention again, i wrote down this code just to test my web service code that i wrote in here.

Python Web Services - HOW TO 3 - ZSI Client

I tried to explain how to write web service server code with Python using ZSI and XML-RPC before. Now i want to explain how to write a web service client code with Python using ZSI.

We may remember that when we use wsdl2py command, there comes 3 files those names are;

SillyWebService_server.py

SillyWebService_client.py

SillyWebService_types.py

and also if we remember, we import SillyWebService_server while writing our web service server code. So this time, we import SillyWebService_client and other necessary modules to our client code;

#!/usr/bin/python

import sys

from ZSI.client import Binding

from optparse import OptionParser

from SillyWebService_client import *

After that, we define a function that takes arguments as web service's function;

def tryWebService(param):

request = sillyfunctionRequest(param = param)

response = service.sillyfunction(request)

print response._return

And then we write down the code that takes url from console and make a request to it and write the whole response to the console;

op = OptionParser(usage="%prog [options]")

op.add_option("-u", "--url", help="service URL", metavar="URL")

options, args = op.parse_args()

service = SillyWebServiceLocator().getSillyWebServicePort(url=options.url, tracefile=sys.stdout)

At the end we call the function and return to the console.

tryWebService("hello world!")

I know that, this code is so simple and has no object oriented approach. I write it only to test the web service server i wrote down. So if you want a better client code, you can look up here.

To run the client code, i assume we saved it as 'client.py', you just open the console;

python client.py -u http://localhost:8181/SillyWebService

I write down the url as i define it at this article i write. Also here is the sample code.

Python Web Services - HOW TO 2 - XML-RPC Server

It’s possible to write web services with Python in too many ways i said in Python Web Services HOW TO-1 (ZSI) and i explain how to write a web service by using ZSI framework. Now i want to explain how to write the same web service by using XML-RPC Server.

It's a lot easier to write web service by using XML-RPC Server than by using ZSI framework. You just need this Python XmlRpcServer Module and an Apache Web Server. Why don't we start then;

First we write down our web service implementation in Python;

We import the sys and XmlRpcServer modules first.

#!/usr/bin/env python

import sys

from xmlrpcserver import XmlRpcServer

Then we write down what the response contains it's data as.

sys.stdout.write("Content-type: text/xml\n\n")

And we write down our web service implementation.

def sillyfunction(self, param):

return param

At the end we create a server from our XmlRpcServer module, register it to our function and run the server as an Apache cgi code.

server = XmlRpcServer()

server.register("asillyfunction", sillyfunction)

server.execute()

To run the code as cgi, we just copy our code to the place where Apache server runs cgi codes. It is /usr/lib/cgi-bin in my linux distribution. Also you can define this place in your Apache server configuration as you want and also you can give ssl support within this configuration files too. Just for now i assume our cgi directory is /usr/lib/cgi-bin/ and we saved our code as silly.py;

cp silly.py /usr/lib/cgi-bin/

Also we may copy the XmlRpcServer code to same place or we just use system module and append the path that contains this file in our python code. In this case i just copy this file to there too.

cp xmlrpcserver.py /usr/lib/cgi-bin/

Then we just change the ownership of files to 755 for Apache to run the codes.

cd /usr/lib/cgi-bin/

chmod 755 silly.py xmlrpcserver.py

And that's it, we have a Python Xml-Rpc Server that runs under our Apache Web Server now.

Here is the sample code. And here is how to write a client that connects to this web service with XML-RPC and say hello to it.


Python Web Services - HOW TO 1 - ZSI Server

It’s possible to write web services with Python in too many ways. For example you can use Python-ZSI framework or SOAPpy or Python XML-RPC. But if you don't want to face with the problem which some of your customers whom use C# wants a wsdl file to create a connection object, i suggest you to use Python-ZSI framework and here you can find how to write down it in Linux.

First we need to install zsi package to our Linux distribution;

You can get the package from here. Also the package can be in your distribution’s repository’s. So you can check it first. But i strongly recommend you to install the package manually. To install the package manually you'll just do after downloading the package;

tar -xvzf zsi.tar.gz

cd zsi

python setup.py build

python setup.py install

Now we are starting to go for web service, (is it always been a hello world example, what a draaaag. so i write down a sillier one, that takes “hello world” as a parameter and sends it back);

First we start to write down our .wsdl file. If you are not familiar with .wsdl standarts, you can check here.

Now here it comes, our wsdl definitions;

<?xml version="1.0"?>

<definitions name="SillyWebService"

targetNamespace="http://services.zsiserver.net:8181/SillyWebService"

xmlns:tns="http://services.zsiserver.net:8181/SillyWebService"

xmlns:xsd="http://www.w3.org/2001/XMLSchema"

xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/"

xmlns="http://schemas.xmlsoap.org/wsdl/">

That “http://services.zsiserver.net:8181” is equivalent to your “http://localhost:8181” and your “http://yourip:8181”. With ZSI the web services are connecting through the internet via a port. And if you have any web server running on 8080 like Apache, you must change the web services port. So i give 8181 to the port number.

And now the major elements of our wsdl;

<message name="sillyfunctionRequest">

<part name="param" type="xsd:string"/>

</message>

<message name="sillyfunctionResponse">

<part name="return" type="xsd:string"/>

</message>

Like message; which represents an abstract definition of the data being transmitted, like type; which provides data type definitions used to describe the messages exchanged.

<portType name="SillyWebServicePortType">

<operation name="sillyfunction">

<documentation> A Silly Web Service Function </documentation>

<input message="tns:sillyfunctionRequest"/>

<output message="tns:sillyfunctionResponse"/>

</operation>

</portType>

Like portType; which is a set of abstract operations.

<binding name="SillyWebServiceBinding" type="tns:SillyWebServicePortType">

<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http"/>

<operation name="sillyfunction">

<soap:operation soapAction="http://services.zsiserver.net:8181/SillyWebService/sillyfunction"/>

<input>

<soap:body use="literal" namespace="http://services.zsiserver.net:8181/SillyWebService"/>

</input>

<output>

<soap:body use="literal" namespace="http://services.zsiserver.net:8181/SillyWebService"/>

</output>

</operation>

</binding>

Like binding; which specifies concrete protocol and data format specifications for the operations and messages defined by a particular portType.

<service name="SillyWebService">

<documentation> A Silly Web Service Implementation </documentation>

<port name="SillyWebServicePort" binding="tns:SillyWebServiceBinding">

<soap:address location="http://services.zsiserver.net:8181/SillyWebService"/>

</port>

</service>

Like service; which is used to aggregate a set of related ports, like port; which specifies an address for a binding, thus defining a single communication endpoint.

I don’t mention much about types, messages etc in here, because we aren’t learning wsdl, aren’t we.

And at the end we don't forget to close definitions tag.

</definitions>

After we finished about writing down our wsdl file, we use wsdl2py from console to create the web service objects with ZSI. I assume we save our wsdl file as “silly.wsdl”;

wsdl2py silly.wsdl

After this command we must now see that we have 3 files that are automatically created by ZSI.

SillyWebService_server.py

SillyWebService_client.py

SillyWebService_types.py

After that, it's time to write down our python web service code or to arrange our code that we wrote down before.

First we import the modules that we need to run our web service;

from optparse import OptionParser

from ZSI.wstools import logging

from ZSI.ServiceContainer import AsServer

from SillyWebService_server import SillyWebService

Then we start to write our web service implementation, that handles the requests and return responses;

class WebServiceImplementation(SillyWebService):

_wsdl = "".join(open("silly.wsdl").readlines())

def soap_sillyfunction(self, ps, **kw):

request, response = SillyWebService.soap_sillyfunction(self, ps, **kw)

response._return = self.sillyfunction(request._param)

return request, response

def sillyfunction(self, param):

return param

The first function that starts with "soap_" is to to interact with the ZSI framework. And the second function is our implementation function. We handle the request and give response on this function.

At the end we write down the parts that run the web service as a server via a port;

op = OptionParser(usage="%prog [options]")

op.add_option("-l", "--loglevel", help="loglevel (DEBUG, WARN)", metavar="LOGLEVEL")

op.add_option("-p", "--port", help="HTTP port", metavar="PORT", default=8181, type="int")

options, args = op.parse_args()

if options.loglevel:

loglevel = eval(options.loglevel, logging.__dict__)

logger = logging.getLogger("")

logger.setLevel(loglevel)

AsServer(port=options.port, services=[WebServiceImplementation()])

And that's the time for us to run our web service, i assume we save our web service code as silly.py;

python silly.py

if you want to run the web service behind, you must add '&' after the command;

python silly.py&

And here it is the sample code. Also if you want to look how to write down a client for this web service in python, you can look here.

November 14, 2008

Let's Get Going

Today i started to write down here what i faced with, what i experienced, what i wrote down while programming. It's free to use whatever these pages contains, wherever you want, whenever it's useful. But also some materials that i used here may have some obligations to be used everywhere so please make sure to read terms.
You may find in these pages codes of Java, C, Python, PHP, Javascript and so on. Just be sure to correct me if i'm wrong, if content isn't it good and so on. And be sure to use it if it's useful.
I also want to thank to everyone whom i don't know or remember, whom just show me the exit point or the solution itself while googling about the problem that i encounter.

Starting Point

I think some of you should say that the header is contrary with the content but it isn't. Header is just emphasize how i want to see the world, but the content is how i must see the world. Maybe someday the header and the content will get swapped and i'll cheer you up with the content.