November 22, 2008
Get File's Total Page Number From PHP
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)
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
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
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
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
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
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
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
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)
<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
$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
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" />
<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
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 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
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.
.bmp)