Wednesday, December 1, 2010

Get Locale in Client Side

Here is a function to detect user's locale in client side:


function getLocale() {
if ( navigator ) {
if ( navigator.language ) {
return navigator.language;
}
else if ( navigator.browserLanguage ) {
return navigator.browserLanguage;
}
else if ( navigator.systemLanguage ) {
return navigator.systemLanguage;
}
else if ( navigator.userLanguage ) {
return navigator.userLanguage;
}
}
}


Courtesy: http://www.ebessette.com/d/ClientSideLocale

Wednesday, May 5, 2010

Apache Ant Presentation

This afternoon, May 5, 2010, I gave a presentation on Apache Ant in our regular informal Tech Talks held in our office. I tried to make it concise yet complete enough for beginners.
Apache Ant

Install new fonts in Ubuntu 9.04

If you have downloaded fonts from the web, purchased them, or acquired them from other sources and want to install these fonts in your Ubuntu 9.04 Jaunty Jackalope box, then there is an easy manual process to do this.

There are various locations in GNU/Linux in which fonts can be kept. These locations are defined in /etc/fonts/fonts.conf . Check your fonts.conf file and most probably you will find these type of entries there:

<dir>/usr/share/fonts</dir>
<dir>/usr/share/X11/fonts</dir>
<dir>/usr/local/share/fonts</dir>
<dir>~/.fonts</dir>

The last entry means .fonts direcotry in the user's home directory.

If you want to make the new fonts available for only one user, then copy those new fonts to the .fonts directory of that user. If .fonts directory is not there, create one first.

If you want to make the new fonts available for all users, then the best place to copy those fonts is to ...say..../usr/share/fonts

Now open a console and run this:
sudo fc-cache -f -v
That's it. There are other ways to install new fonts. But this one is quite good to live with :)

Thursday, April 22, 2010

Recover MySQL root Password

You can recover MySQL database server's root password with the following five steps.
  1. Stop the MySQL server process: $ /etc/init.d/mysql stop
  2. Start the MySQL (mysqld) server/daemon process with the --skip-grant-tables option so that it will not prompt for password: $ mysqld_safe --skip-grant-tables &
  3. Connect to mysql server as the root user: $ mysql -u root
  4. Setup new mysql root account password and quit: mysql> use mysql;
    mysql> update user set password=PASSWORD("NEW-ROOT-PASSWORD") where User='root';
    mysql> flush privileges;
    mysql> quit
  5. Restart the MySQL server: $ /etc/init.d/mysql stop

Monday, April 5, 2010

Make data or tmp web-writable

In a web application, we need to make data or tmp directory writable by the web server. I saw many people achieve this by changing the permission level of that directory recursively to 777 in Unix/Linux:


$ chmod -R 777 tmp

Or

$ chmod -R 777 data

This is really unnecessary. You can find out on behalf of which user, your web server is running by running this single line of php code:


echo `whoami`;

In my case, i got 'daemon' as the user on behalf of which the webserver is running.
Now we need to change the ownership of the data or tmp directory and make 'daemon' as the owner.


$chown -R daemon tmp

Wednesday, January 20, 2010

Tricky error during std::find function applied on std::string

An tricky problem is described here that is worth mentioning. Look at this code chunk:


int count(std::string& s, char c) {
std::string::const_iterator i = std::find(s.begin(), s.end(), c);
int n = 0;
while (i != s.end()) {
n++;
i = std::find(i+1, s.end(), c);
}
return n;
}


If you try to compile this function (offcourse adding main function with required headers), you will find that the first call to find doesn't produce any error. But the second call within the loop generates compilation error of this form:


In function ‘int count(std::string&, char)’:
error: no matching function for call to ‘find(__gnu_cxx::__normal_iterator, std::allocator > >, __gnu_cxx::__normal_iterator, std::allocator > >, char&)’


At first look, it seems to be weird. But it's not :)

The general find function is declared as:


template
InputIterator find(
InputIterator _First,
InputIterator _Last,
const Type& _Val
);


You can see that the type of the first and second parameters of the function template correspond to the same type. The compiler cannot deduce that it is this function that you want to call if your call has a combination of string::const_iterator and string::iterator as arguments.

During first call, i.e. std::find(s.begin(), s.end(), c), the first and second arguments are of string::iterator types and the return value is also of type string::iterator. But this return value is being casted to string::const_iterator.

During second call, i.e. std::find(i+1, s.end(), c), the first argument is of type string::const_iterator (due to that earlier casting) and the second argument is of type string::iterator. So, the types of first and second arguments don't match. That's why , the compiler is generating the error.

Here goes two different types of fixes.

Fix 1:


int count(std::string& s, char c) {
std::string::iterator i = std::find(s.begin(), s.end(), c);
int n = 0;
while (i != s.end()) {
n++;
i = std::find(i+1, s.end(), c);
}
return n;
}


Fix 2:


int count(const std::string& s, char c) {
std::string::const_iterator i = std::find(s.begin(), s.end(), c);
int n = 0;
while (i != s.end()) {
n++;
i = std::find(i+1, s.end(), c);
}
return n;
}


Tricky error..isn't it? ;)

Tuesday, January 19, 2010

Two-stage name lookup issues with template code

The C++ standard prescribes that all names that are not dependent on template parameters are bound to their present definitions when parsing a template function or class. Only names that are dependent are looked up at the point of instantiation. This distinction between lookup of dependent and non-dependent names is called two-stage (or dependent) name lookup. G++ implements it since version 3.4.

Two-stage name lookup sometimes leads to situations with behavior different from non-template codes. The most common is probably this:


//vec.h

#include

template class Vec : public std::vector {
public:
Vec() : std::vector () {}
Vec(int s) : std::vector (s) {}
T& operator[] (int i) { return at(i);}
const T&operator[] (int i) const { return at(i); }
};


the call to at() is not dependent on template arguments (there are no arguments that depend on the type T, and it is also not otherwise specified that the call should be in a dependent context). Thus a global declaration of such a function must be available, since the one in the base class is not visible until instantiation time. The compiler will consequently produce the following error message:


vec.h: In member function ‘T& Vec::operator[](int)’:
vec.h:7: error: there are no arguments to ‘at’ that depend on a template parameter, so a declaration of ‘at’ must be available
vec.h:7: error: (if you use ‘-fpermissive’, G++ will accept your code, but allowing the use of an undeclared name is deprecated)
vec.h: In member function ‘const T& Vec::operator[](int) const’:
vec.h:8: error: there are no arguments to ‘at’ that depend on a template parameter, so a declaration of ‘at’ must be available


To make the code valid either use this->at(i), or vector::at(i). Using the -fpermissive flag will also let the compiler accept the code, by marking all function calls for which no declaration is visible at the time of definition of the template for later lookup at instantiation time, as if it were a dependent call. Using -fpermissive to work around invalid code is not recommended however, and it will also only catch cases where functions in base classes are called, not where variables in base classes are used (as in the example above).

Some compilers (including G++ versions prior to 3.4) get these examples wrong and accept above code without an error. Those compilers do not implement two-stage name lookup correctly.

Clear input stream in C++ - fflush(stdin) equivalent in C

You can't use flush to clear the input stream in C++, it's equivilent to using fflush(stdin) for C. Sometimes it works, sometimes it doesn't, but all of the time it's a bad idea.


cin >> flush;


To clear the input stream in C++ use cin.ignore() everytime you think the input stream may still have data in it.


cout<<"Enter your name"<cin.getline(name, 50, '\n'); //ignore not needed, getline does it
cout<<"Enter your age"<cin>>age; cin.ignore(); //clear the newline from the stream
cout>>"Enter your height"<cin>>height; //this will work now

Thursday, January 7, 2010

Compilation and linking issues for C++ template classes

The common practice in C++ is to write the class definition in a header file(.h file) and to write the class implementation in a source file(.cpp file). This reason behind this is to keep the interface separate from the implementation. This source file is compiled separately. When we want to use the class in another source file say test_stack.cpp, we need to include the header file in test_stack.cpp. We then need to compile this test_stack.cpp and link the object files to make the executable.

But if we want to follow the same practice for a template class, some linking issues arise.

Linking Issue:

Here goes the source files and header file.



//stack.h

#ifndef STACK_H
#define STACK_H

template class Stack {
T *v;
int max_size;
int top;
public:
class Underflow {};
class Overflow {};

Stack(int s);
~Stack();

void push(T);
T pop();
};

class Bad_size {};
class Bad_pop {};

#endif

//stack.cpp

#include "stack.h"

template Stack::Stack(int s) {
top = 0;
if (10000 < s) throw Bad_size();
max_size = s;
v = new T[s];
}

template Stack::~Stack() {
delete [] v;
}

template void Stack::push(T c) {
if (top == max_size) throw Overflow();
v[top++] = c;
}

template T Stack::pop() {
if (top == 0) throw Underflow();
return v[--top];
}

// test_stack.cpp
#include "stack.h"
#include
#include
#include

Stack sc(10);
Stack< std::complex > scplx(10);
Stack< std::list > sli(10);

void f() {
sc.push('a');
sc.push('b');
sc.push('c');
if (sc.pop() != 'c') throw Bad_pop();

scplx.push(std::complex(1, 2));
scplx.push(std::complex(2, 3));
scplx.push(std::complex(3, 4));

if (scplx.pop() != std::complex(3, 4)) throw Bad_pop();

std::cout << "stack of characters, sc: " << sc.pop() << ' ' << sc.pop() << '\n';
std::cout << "stack of complex numbers, scplx: " << scplx.pop() << ' ' << scplx.pop() << '\n';
}

int main() {
f();
return 0;
}



When you try to link the object files created from compiling source files, some linking problems arise:



$ g++ -c stack.cpp
$ g++ -c test_stack.cpp
$ g++ -o test_stack stack.o test_stack.o
test_stack.o: In function `__static_initialization_and_destruction_0(int, int)':
test_stack.cpp:(.text+0x56): undefined reference to `Stack::Stack(int)'
test_stack.cpp:(.text+0x5b): undefined reference to `Stack::~Stack()'
test_stack.cpp:(.text+0x87): undefined reference to `Stack >::Stack(int)'
test_stack.cpp:(.text+0x8c): undefined reference to `Stack >::~Stack()'
test_stack.cpp:(.text+0xb8): undefined reference to `Stack >
-----
------
------
collect2: ld returned 1 exit status



Reason

When the compiler encounters a declaration of a Stack object of some specific type, e.g., int , it must have access to the template implementation source. Otherwise, it will have no idea how to construct the Stack member functions. And, if you have put the implementation in a source (stack.cpp) file the compiler will not be able to find it when it is trying to compile the client source file test_stack.cpp. And, includeing the header file (stack.h) will not be sufficient at that time. That only tells the compiler how to allocate for the object data and how to build the calls to the member functions, not how to build the member functions. And again, the compiler won't complain. It will assume that these functions are provided elsewhere, and leave it to the linker to find them. So, when it's time to link, you will get "unresolved references" to any of the class member functions that are not defined "inline" in the class definition.

Solution

There are different methods to solve this problem. You can select from any of the methods below depending on which is suitable for your application design:

Way 1

You can create an object of a template class in the same source file where it is implemented
(stack.cpp). So, there is no need to link the object creation code with its actual implementation in some other file. This will cause the compiler to compile these particular types so the associated class member functions will be available at link time. Here goes the changes in stack.cpp:




#include "stack.h"

template Stack::Stack(int s) {
top = 0;
if (10000 < s) throw Bad_size();
max_size = s;
v = new T[s];
}

template Stack::~Stack() {
delete [] v;
}

template void Stack::push(T c) {
if (top == max_size) throw Overflow();
v[top++] = c;
}

template T Stack::pop() {
if (top == 0) throw Underflow();
return v[--top];
}

// No need to call this temporaryFunction() function,
// it's just to avoid link error.
void temporaryFunction ()
{
// you need to use those functions here which will be called from test_stack.cpp
Stack sc(10);
sc.push('a');
sc.pop();
}



The temporary function in "stack.cpp" will solve the link error. No need to call this function because it's global.

Way 2

You can #include the source file that implements your template class stack.cpp in your test_stack.cpp source file



#include "stack.h"
#include "stack.cpp"
#include
#include
#include

Stack sc(10);
Stack< std::complex > scplx(10);
Stack< std::list > sli(10);

void f() {
sc.push('a');
sc.push('b');
sc.push('c');
if (sc.pop() != 'c') throw Bad_pop();

scplx.push(std::complex(1, 2));
scplx.push(std::complex(2, 3));
scplx.push(std::complex(3, 4));

if (scplx.pop() != std::complex(3, 4)) throw Bad_pop();

std::cout << "stack of characters, sc: " << sc.pop() << ' ' << sc.pop() << '\n';
std::cout << "stack of complex numbers, scplx: " << scplx.pop() << ' ' << scplx.pop() << '\n';
}

int main() {
f();
return 0;
}



In this case you dont need to compile stack.cpp. You need to compile and link only test_stack.cpp

Way 3

You can #include the source file that implements your template class (stack.cpp) in your header file that defines the template class (stack.h).



#ifndef STACK_H
#define STACK_H

template class Stack {
T *v;
int max_size;
int top;
public:
class Underflow {};
class Overflow {};

Stack(int s);
~Stack();

void push(T);
T pop();
};

class Bad_size {};
class Bad_pop {};

#include "stack.cpp"

#endif



In this case you dont need to compile stack.cpp. You need to compile and link only test_stack.cpp

Way 4

You need to make the class functions inline i.e. implement those inside stack.h and remove stack.cpp. In this case you need to compile and link only test_stack.cpp

Tuesday, September 1, 2009

PEAR Installation Problem: unsupported protocal

I was trying to install PHPUnit, a member of XUnit family of testing frameworks. While running this command:


pear install phpunit/PHPUnit


I got this error:


pear.phpunit.de is using a unsupported protocal – This should never happen. install failed


What I found through investigation is that PEAR installations on PHP 5.2.9 and 5.2.10 seem to be corrupted and I am using PHP 5.2.9. This problem comes from corrupted channel files. The solution is: Go into your PEAR php directory and backup .channels directory.


cd `pear config-get php_dir`
mv .channels .channels-broken
pear update-channels


This means you lost all your channels except for the default ones (pear, pecl, doc and __uri) – but at least you do not have to re-install PEAR :)

Sunday, August 23, 2009

Installing Apache httpd-2.2.11 from source in Ubuntu 9.04

I was trying to install httpd-2.2.11 from source in Ubuntu 9.04.When I tried to execute the first command which is 'configure' with some options like this:


$ ./configure --with-included-apr --enable-cache --enable-mem-cache --enable-ssl --enable-rewrite
--enable-so --enable-deflate


I got this error:


checking whether to enable mod_deflate... configure: error: mod_deflate has been requested but can not be built due to
prerequisite failures


After doing some investigation, I found that zlib1g-dev was not installed. So I installed this using this command:


$ sudo apt-get install zlib1g-dev


Then I tried to install apache again. When I ran configure again, I got this error:


no OpenSSL headers found
checking for SSL-C version... checking sslc.h usability... no
checking sslc.h presence... no
checking for sslc.h... no
no SSL-C headers found
configure: error: ...No recognized SSL/TLS toolkit detected


That means either openssl or libssl-dev was not installed. I was sure that openssl was installed. So I installed libssl-dev using this command:


$ sudo apt-get install libssl-dev


Then I tried to install httpd again and it was successfully installed. :)

Friday, July 24, 2009

Installing the Connector/J in Windows XP with JDK 1.6.0_14

I am writing this post only to note down some quick things that may not be remembered at all times, specially when it is needed :)

You can follow these steps:
  1. Extract the zip file mysql-connector-java-5.1.8.zip in any place as you wish.
  2. Copy file 'mysql-connector-java-3.1.12-bin.jar' from the extracted folder into \jre\lib\ext folder. jdk1.5\jre\lib\ext folder which on my system happens to be 'C:\Program Files\Java\jdk1.6.0_14\jre\lib\ext folder. jdk1.5\jre\lib\ext'.
  3. Go to control Panel->Advance->Environment Variable->System Variable.
  4. The next step depends on your system variable:
  5. IF YOU HAVE CLASSPATH:
  6. Click once at Classpath and then click edit.
  7. At the end of the Variable Value, simply put ';\jre\lib\ext\mysql-connector-java-5.1.8-bin.jar' (Without the single quotes ;) which on my system happens to be ';C:\Program Files\Java\jdk1.6.0_14\jre\lib\ext\mysql-connector-java-5.1.8-bin.jar'.
  8. Click OK.
  9. IF YOU DO NOT HAVE CLASSPATH:
  10. Click on New.
  11. Put 'CLASSPATH' at Variable name, and '.;\jre\lib\ext\mysql-connector-java-5.1.8-bin.jar' at Variable Value.
  12. Click OK

Monday, July 20, 2009

Writing code in blogspot

I am a new and infrequent blogger. So, while writing some php code in one of my post, I was looking for a way to put those code so that code indentation and other aspects don't get lost. After some googling, I found this post as a useful one for that purpose: http://blog.mijalko.com/2008/10/writing-code-in-blogspot.html

A simple solution and off-course a KISS one :)

Friday, July 17, 2009

mysql-5.1.36 in Ubuntu 9.04: FATAL ERROR: Could not find mysqld

I was building mysql-5.1.36 in Ubuntu 9.04 - the Jaunty Jackalope. I was following the instructions given in INSTALL-SOURCE provided with the package. I was trying to create the MySQL data directory and initialize the grant tables by running this command:

$ sudo bin/mysql_install_db --user=mysql

I got this error:

FATAL ERROR: Could not find mysqld

The following directories were searched:

/usr/libexec
/usr/sbin
/usr/bin

If you compiled from source, you need to run 'make install' to copy the software into the correct location ready for operation.

If you are using a binary release, you must either be at the top of the level of the extracted archivem or pass the --basedir option pointing to that location.

After a bit googling and investigation, I found that this package mysql-common was already installed with
Ubuntu 9.04 and there is a file my.cnf in /etc/mysql and db initialization was using this file instead of the one I copied to /etc with this command while following the INSTALL-SOURCE file:

$ sudo cp support-files/my-medium.cnf /etc/my.cnf

So the quick fix was to replace /etc/mysql/my.cnf with /etc/my.cnf that I copied earlier. I did these:

$ sudo mv /etc/mysql/my.cnf /etc/mysql/my_backup.cnf
$ sudo cp /etc/my.cnf /etc/mysql/

CodeIgniter: AJAX Pagination

To use CodeIgniter's Pagination class to create pagination in one of our controller functions:


$this->load->library('pagination');

$config['base_url'] = 'http://example.com/index.php/test/page/';
$config['total_rows'] = '200';
$config['per_page'] = '20';

$this->pagination->initialize($config);

echo $this->pagination->create_links();

The $config array contains your configuration variables. It is passed to the $this->pagination->initialize function. At a minimum we need the three configuration variables shown above.
  • base_url: Full URL to the controller class/function containing our pagination.
  • total_rows: Total rows in the result set we are creating pagination for.
  • per_page: Number of rows we intend to show per page
The pagination links provided by create_links function may not be appropriate for all cases. After-all clicking on these links will do page load which may not be desired on many situation. We may be interested to invoke a javascript function while clicking these links for doing AJAX style pagination. Still we want to use all other features provided by CodeIgniter's Pagination class. This can be accomplished simply. Just follow me ;)

1. All you need to do is adding some more functionality to the existing library i.e. CodeIgniter's Pagination class. To extend the native Pagination class you'll create a file named application/libraries/MY_Pagination.php
, and declare your class with:


class MY_Pagination extends CI_Pagination
{
}

Here MY_ is the sub-class prefix, defined in application/config/config.php as follows:


$config['subclass_prefix'] = 'MY_';


If you need to use a constructor in yo ur class make sure you extend the parent constructor:


class MY_Pagination extends CI_Pagination
{
function MY_Pagination()
{
parent::CI_Pagination();
}
}


2. Next add some member variables to this class:


class MY_Pagination extends CI_Pagination
{
var $js_function_name = '';
var $js_function_params = array();

function MY_Pagination()
{
parent::CI_Pagination();
}
}

js_function_name is the name of the javascript function to invoke when pagination links are clicked.

js_function_params is an array of parameters required for that javascript function. Our customized pagination will; add one more parameter for that javascript function; offset. While viewing the first page, offset=0. In the second page, offset = rows_per_page as defined by $config['per_page'] provided to the $this->pagination->initialize function.

js_href is the name of the div used in the pagination links as the value of the href attribute prefixed with #

3. Add a member function
initialize_js_function to the class:


function initialize_js_function($jsFunction = array())
{
if (count($jsFunction) > 0) {
if (isset($jsFunction['name'])) {
$this->js_function_name = $jsFunction['name'];
}
if (isset($jsFunction['params'])) {
for ($i = 0; $i <>js_function_params[$i] = $jsFunction['params'][$i];
}
}
}
}

This function will be called from the controller function where we are using pagination stuffs.

4. Now modify the function create_links and add this modified function to the MY_Pagination class as create_js_links function. The modification basically ensures that each of the anchor tags generated, will have value of onclick attribute equals the javascript function as defined by the member variable js_function_name having the parameters as defined by the member variable js_function_params plus one extra parameter offset. A comma sperated list of the items in js_function_params will be created. Then the offset parameter will be appended in that comma separated list.



function create_js_links()
{
// If our item count or per-page total is zero there is no need to continue.
if ($this->total_rows == 0 OR $this->per_page == 0)
{
return '';
}

// Calculate the total number of pages
$num_pages = ceil($this->total_rows / $this->per_page);

// Is there only one page? Hm... nothing more to do here then.
if ($num_pages == 1)
{
return '';
}

// Determine the current page number.
$CI =& get_instance();

if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
{
if ($CI->input->get($this->query_string_segment) != 0)
{
$this->cur_page = $CI->input->get($this->query_string_segment);

// Prep the current page - no funny business!
$this->cur_page = (int) $this->cur_page;
}
}
else
{
if ($CI->uri->segment($this->uri_segment) != 0)
{
$this->cur_page = $CI->uri->segment($this->uri_segment);

// Prep the current page - no funny business!
$this->cur_page = (int) $this->cur_page;
}
}

$this->num_links = (int)$this->num_links;

if ($this->num_links <>cur_page))
{
$this->cur_page = 0;
}

// Is the page number beyond the result range?
// If so we show the last page
if ($this->cur_page > $this->total_rows)
{
$this->cur_page = ($num_pages - 1) * $this->per_page;
}

$uri_page_number = $this->cur_page;
$this->cur_page = floor(($this->cur_page/$this->per_page) + 1);

// Calculate the start and end numbers. These determine
// which number to start and end the digit links with
$start = (($this->cur_page - $this->num_links) > 0) ? $this->cur_page - ($this->num_links - 1) : 1;
$end = (($this->cur_page + $this->num_links) < $num_pages) ? $this->cur_page + $this->num_links : $num_pages;

// Is pagination being used over GET or POST? If get, add a per_page query
// string. If post, add a trailing slash to the base URL if needed
if ($CI->config->item('enable_query_strings') === TRUE OR $this->page_query_string === TRUE)
{
$this->base_url = rtrim($this->base_url).'&'.$this->query_string_segment.'=';
}
else
{
$this->base_url = rtrim($this->base_url, '/') .'/';
}

//$js_output = $this->js_function_name . '(';
$js_output = '';
for ($paramIndex = 0; $paramIndex <>js_function_params); $paramIndex++) {
$js_output = $js_output . $this->js_function_params[$paramIndex] . ',';
}
//$js_output = rtrim($js_output, ',');
//$js_output .= ')';

// And here we go...
$output = '';

// Render the "First" link
if ($this->cur_page > ($this->num_links + 1))
{
$js_output = rtrim($js_output, ',');
$output .= $this->first_tag_open.'js_function_name.'('.$js_output.'0)'.'">'.$this->first_link.''.$this->first_tag_close;
}

// Render the "previous" link
if ($this->cur_page != 1)
{
$i = $uri_page_number - $this->per_page;
//if ($i == 0) $i = '';
$output .= $this->prev_tag_open.'js_function_name.'('.$js_output.$i.')'.'">'.$this->prev_link.''.$this->prev_tag_close;
}

// Write the digit links
for ($loop = $start -1; $loop <= $end; $loop++) { $i = ($loop * $this->per_page) - $this->per_page;

if ($i >= 0)
{
if ($this->cur_page == $loop)
{
$output .= $this->cur_tag_open.$loop.$this->cur_tag_close; // Current page
}
else
{
$n = ($i == 0) ? '' : $i;
$output .= $this->num_tag_open.'js_function_name.'('.$js_output.$n.')'.'">'.$loop.''.$this->num_tag_close;
}
}
}

// Render the "next" link
if ($this->cur_page < $num_pages) { $output .= $this->next_tag_open.'js_function_name.'('.$js_output.($this->cur_page * $this->per_page).')'.'">'.$this->next_link.''.$this->next_tag_close;
}

// Render the "Last" link
if (($this->cur_page + $this->num_links) < $num_pages) { $i = (($num_pages * $this->per_page) - $this->per_page);
$output .= $this->last_tag_open.'js_function_name.'('.$js_output.$i.')'.'">'.$this->last_link.''.$this->last_tag_close;
}

// Kill double slashes. Note: Sometimes we can end up with a double slash
// in the penultimate link so we'll kill all double slashes.
//$output = preg_replace("#([^:])//+#", "\\1/", $output);

// Add the wrapper HTML if exists
$output = $this->full_tag_open.$output.$this->full_tag_close;

return $output;
}



5. Now in the controller, where you are using pagination stuffs, initialize the pagition in this way:



//In actual scenario, populate it with number rows to paginate
$config['total_rows'] = 100;
$config['per_page'] = 10;
$config['first_link'] = 'First';
$config['last_link'] = 'Last';
//change it as per your controller's function's number of parameters
$config['uri_segment'] = 3;
$this->pagination->initialize($config);

$jsFunction['name'] = 'your_javascript_function_name';
//provide your params for the javascript function if there is any
//In my case, it is empty
$jsFunction['params'] = array();
$this->pagination->initialize_js_function($jsFunction);
//pass/use this $page_link in your view as per your need
$page_link = $this->pagination->create_js_links($pageNo);


This is the basic outline or structure. You have to write down your own javascript function to make ajax call and fill in the missing or leftover details ;)

Now taste the AJAXified pagiantion in action :D We have done a great job already ;)

You can download a complete sample or demo from here: http://www.mediafire.com/file/4ygym0trmjh/ajax_pagination_demo.zip

mysql-5.1.36 in Ubuntu 9.04: No curses/termcap library found

I was building mysql-5.1.36 in Ubuntu 9.04 - the Jaunty Jackalope and while trying to run:
$ ./configure --prefix=/usr/local/mysql

I got this error:

checking for termcap functions library... configure: error: No curses/termcap library found. After a bit thinking, I found that the ncurses stuff isn't installed for. To find which name Ubuntu uses for that library I did:

$ apt-cache search ncurses

and I found:

libncurses5-dev - Developer's libraries and docs for ncurses

and I installed it with:

$ sudo apt-get install libncurses5-dev

After this, I tried configuring mysql-5.1.36 again and it was a success:) Altough it was a simple workaround for the problem that I faced,
I can't resist myself of sharing this ;)

Thursday, June 18, 2009

Ways of utilizing PHP by a web server

There are three ways a web server can utilize PHP to generate web pages:
  • CGI wrapper
  • Module in a multiprocess web server
  • Plug-in for a multi-threaded web server
CGI wrapper:

The first method is to use PHP as a CGI wrapper. In this case. an instance of the PHP interpreter is created for every page request. The page is offcourse a PHP page. The instance is destroyed after the request is served.

Module in a multiprocess web server:

A multiprocess server typically has one parent process which coordinates a set of child processes. The child processes actually do the serving up web pages. when a request comes from a client, one of the children, who is not serving any client at that moment, is allocated to serve the request. This means that when the same client makes a second request to the server, it may be served by a different child process than the first time. This method currently includes Apache web server. This is the most popular method.

Plug-in for a multi-threaded web server:

This method uses PHP as a plug-in for a multithreaded web server. Currently PHP 4 has support for ISAPI, WSAPI, and NSAPI (on Windows), which all allow PHP to be used as a plug-in on multithreaded servers like Netscape FastTrack (iPlanet), Microsoft's Internet Information Server (IIS), and O'Reilly's WebSite Pro. The behavior is essentially the same as for the multiprocess model.

Thursday, January 1, 2009

Opening file having extension .z

This type of file is Unix Compressed File. This is an standard file format supported by many programs. This compression format is used to compress or "pack" files on Unix servers to save disk space; incorporates a simple compression algorithm that has been mostly replaced by GNUzip compression (which creates (.GZ files)).

File can be decompressed on a Unix machine by typing uncompress filename, where "filename" is the name of the file you want to decompress.

There is a lot of programs listed below for uncompressing/openning this type of file:

Sunday, July 27, 2008

apache didn't start after installing subversion

I installed apache long before. Recently I installed subversion and thought everything is OK. But actually it wasn't. When I tried to start apache, i got this error:

$ /usr/local/apache2/bin/apachectl start
[Mon Jul 28 11:13:10 2008] [warn] module ferite_module is already loaded, skipping
[Mon Jul 28 11:13:11 2008] [warn] module php5_module is already loaded, skipping
Syntax error on line 1048 of /usr/local/apache2/conf/httpd.conf:
Cannot load /usr/local/apache2/modules/mod_dav_svn.so into server: /usr/local/apache2/modules/mod_dav_svn.so: undefined symbol: dav_xml_get_cdata

This time, it took little time to solve this problem. I reinstalled apache using these steps:

$ ./configure --prefix=/usr/local/apache2 --enable-dav --enable-so
$ make
$ sudo make install

And everything is ok now :)

Monday, July 21, 2008

Using svn and got "Unrecognized URL scheme."

This morning, I built subversion-1.5.0 from source using the ./configure, make and make install. Then I tried to check out a repository and got this error:
$ svn checkout http://svn.assembla.com/svn/blog1/ --username azim.babu
svn: Unrecognized URL scheme for 'http://svn.assembla.com/svn/blog1'

It seemed to be a curious problem to analyze. So I did some googling and found these from http://subversion.tigris.org/faq.html :

Subversion uses a plugin system to allow access to repositories. Currently there are three of these plugins: ra_local allows access to a local repository, ra_dav which allows access to a repository via WebDAV, and ra_svn allows local or remote access via the svnserve server. When you attempt to perform an operation in Subversion, the program tries to dynamically load a plugin based on the URL scheme. A `file://' URL will try to load ra_local, and an `http://' URL will try to load ra_dav.

The error you are seeing means that the dynamic linker/loader can't find the plugins to load. This normally happens when you build Subversion with shared libraries, then attempt to run it without first running 'make install'. Another possible cause is that you ran make install, but the libraries were installed in a location that the dynamic linker/loader doesn't recognize. Under Linux, you can allow the linker/loader to find the libraries by adding the library directory to /etc/ld.so.conf and running ldconfig. If you don't wish to do this, or you don't have root access, you can also specify the library directory in the LD_LIBRARY_PATH environment variable.

So what I got is that I was not able to setup the SVN on my ubuntu box properly. Here even after compiling the source I was not able to enable the support of ra_dav module for http and https protocol. So I did a little googling again and found that I was missing neon. So I download neon from http://www.webdav.org/neon/neon-0.28.1.tar.gz , extract the tarball and install neon using ./configure, make and make install.
Then I recompile subversion as follows:
$ ./configure --with-ssl --with-apr=/usr/local/apache2/bin/apr-config --with-apr-util=/usr/local/apache2/bin/apu-config --with-neon=/usr/local
$ make
$ sudo make install

A little explanation of the above options are:

--with-apr : prefix for installed APR, path to APR build tree, or the full path to apr-config

--with-apr-util : prefix for installed APU, path to APU build tree, or the full path to apu-config

--with-neon : Determine neon library configuration based on 'PREFIX/bin/neon-config'. Default is to search for in a subdirectory of the top source directory.

As I installaed neon without any option during configure, it should be /usr/local for my case :P

Although all these steps may seem to be very much intuitive for many, I think for newbies, this type of blog post may provide some sort of quick help. :)