Short Tag – Web Development Blog

Can connect but cannot retrieve directory listings – xinetd

After installing the ftp server you can connect to it but cannot retrieve directory listings?
This happens because iptables won’t let you work in passive mode. So you need to load the “ip_conntrack_ftp” module.
You know you have this issue if you disable iptables and the FTP is working correctly.

Edit the following file:
/etc/sysconfig/iptables-config

And put this line anywhere in that file:

IPTABLES_MODULES="ip_conntrack_ftp"

Also make sure that port 21 is open. Edit the iptables file: /etc/sysconfig/iptables
Make sure you have this line in there:

-A INPUT -m state --state NEW -m tcp -p tcp --dport 21 -j ACCEPT

Now restart the firewall:

service iptables restart

How to disable XDebug

If you want to disable XDebug on your server for some reason, you can do one of the following:

1.) Locate your php.ini file (the server’s php.ini or if your server allows it create one in the root of your website). Find the following directives and change them as below:

xdebug.remote_autostart=0
xdebug.remote_enable=0
xdebug.profiler_enable=0

2.) Disable it just for one website with HTACCESS. Enter the following lines in your .htaccess file:

php_value xdebug.remote_autostart 0
php_value xdebug.remote_enable 0
php_value xdebug.profiler_enable 0

3.) Disable it directly from PHP, copy these lines at the begginning of your script

if (function_exists('xdebug_disable'))
{
     xdebug_disable();
}

FTP not working on Kloxo LxAdmin

I just installed LxAdmin on Centos 5.9 Final and the ftp was not working by default.
I got it working eventually and I share my experience for those who have the same problem.

1.) Firewall
Make sure the firewall has port 21 open.
Open the iptables file: /etc/sysconfig/iptables

You need to have this line in this file, if not include it

-A RH-Firewall-1-INPUT -m tcp -p tcp --dport 21 -j ACCEPT

2.) Enabling the ftp server
Strangely the ftp server has been disabled, so I had to enable it.
Go to /etc/xinetd.d/pureftp and open it.
Replace

disable = yes

with

disable = no

in this file then save it.

3.) Restart the services:

service iptables restart
service xinetd restart

jQuery treeview Expand all / Collapse all not working

In jQuery 1.3.2 there was a change in how :visible and :hidden selectors work.
Here is more info: http://docs.jquery.com/Release:jQuery_1.3.2#:visible.2F:hidden_Overhauled

This change affects directly the functionality of the treeview plugin of jQuery.
I am referring to this one: http://jquery.bassistance.de/treeview/demo/

The expand all functionality will be effected the most since it will be visible for the users that the tree is not expanded entirely, only just the first level. You can see how it happens on the link above, in Sample 4.

There is an easy fix you can do, just open “jquery.treeview.js” file, go to line 42 and change:
replace this line

jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();

with this line

jQuery(this)[ jQuery(this).css("display") == "none" ? "show" : "hide" ]();

You can also download the fixed javascript file from here!

PHP Reflection Class – The basics

Part1 – Using the ReflectionClass in PHP to get basic information about a class.

Build the Refelection Class

$class = new ReflectionClass($className);

$className – can be the name of any class

Get the name of the class:

echo $class->getName()

Get the name of the file that contains the class:

echo $class->getFileName()

Get the class inherited by this class:

echo $class->getParentClass();

Get all the list of all parent classes (inheritance):

$parents = array();
while ($parent =  $parent->getParentClass())
{
	$parents[] = $parent;
}

They will be of ReflectionClass type too, so you can use the same functions on them.

Get the classes constants:

var_dump($class->getConstants());

Get the classes properties:

var_dump($class->getProperties());

All methods of ReflectionClass can be found here:
http://php.net/manual/en/class.reflectionclass.php

CSS3 input highlight on focus with transition

CSS3 makes your job a lot easier with it’s new features.
For example creating an input that will highlight on focus with animation is an easy task now with CSS3 in comparison with all the work it would’ve needed with javascript and CSS2.

Style all the inputs, textareas and combo boxes:

input, select, textarea
{
    background: none repeat scroll 0 0 #FFFFFF;
    border-color: #999;
    border-image: none;
    border-radius: 2px;
    border-style: solid;
    border-width: 1px;
    color: #555555;
    transition: border 0.2s linear 0s, box-shadow 0.2s linear 0s;
}

transition: border 0.2s linear 0s, box-shadow 0.2s linear 0s;
This is the line that insures the transition.
You can also use: transition: all 0.2s linear 0s

On focus just change the border color and shadow:

input:focus, select:focus, textarea:focus
{
    border-color:#12799A;
    box-shadow:0 0 3px rgba(18, 121, 154, 0.6);
}

Fancybox – width and height not working

Let’s say you have this code:

$.fancybox({
	'autoScale'		: false,
	'transitionIn'	: 'none',
	'transitionOut'	: 'none',
	'width'		: '680',
	'height'		: '495'
		});

If you use Fancybox like this the width and height of the window will not be 680×495. Instead the window will have almost the size of the browser window. This is an often encountered problem.

The solution is to remove the quotes from the width and height. So this will look like:

$.fancybox({
	'autoScale'		: false,
	'transitionIn'	: 'none',
	'transitionOut'	: 'none',
	'width'		: 680,
	'height'		: 495
		});

It seems fancybox will accept only numbers when specifying dimensions in pixels. If you want to set the width and height using percents than you have to use strings, like this:

$.fancybox({
	'autoScale'		: false,
	'transitionIn'	: 'none',
	'transitionOut'	: 'none',
	'width'		: '50%',
	'height'		: '30%'
		});

Restart XULRunner application with XPCOM

The following code will restart the XULRunner application it is used in:

var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"]
.getService(Components.interfaces.nsIAppStartup);

appStartup.quit(Components.interfaces.nsIAppStartup.eRestart |
Components.interfaces.nsIAppStartup.eAttemptQuit);

Initialize nsIAppStartup interface with the first line of code. With the second line of code I call the function called “quit”.

var appStartup = Components.classes["@mozilla.org/toolkit/app-startup;1"]
.getService(Components.interfaces.nsIAppStartup);

appStartup.quit(Components.interfaces.nsIAppStartup.eRestart |
Components.interfaces.nsIAppStartup.eAttemptQuit);

Make cPanel Api2 Requests with Jquery and Javascript

First, include jQuery in your page:

<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.4.2/jquery.min.js"></script>

Here is the API 2 of cPanel:
http://docs.cpanel.net/twiki/bin/view/ApiDocs/Api2/WebHome

Find the modules and function names you need, and use them when calling the function below.

Copy the following function to your webpage:

function cpanel_call(module, fct, domain, user, password, secure, port, json, callback, return_as, async)
{
var protocol = secure ? "https" : "http";
var data_type = json ? 'json-api' : 'xml-api';

var authStr = "Basic " + Base64.encode(user + ":" + password);
var url = protocol + "://" + domain + ":" + port + "/" + data_type + "/cpanel?user=" + user + "&cpanel_xmlapi_module=" + module + "&cpanel_xmlapi_func=" + fct + "&cpanel_xmlapi_version=2&domain=" + domain;

jQuery.ajax({
"type" : "GET",
"username" : user,
"password" : password,
"url" : url,
"async" : false,
"dataType" : return_as ? return_as : "text",
headers : {"Authorization" : authStr},
beforeSend : function(xhr)
{
xhr.setRequestHeader("Authorization", authStr);
},
success : function(msg, textStatus, xhr){

if (callback)
callback.apply(this, [msg]);

},
error : function(){
alert("Connection Error!");
}
});
}

Use the function like this:


cpanel_call(cpanel_module_name, cpanel_fct_name, domain, cp_user, cp_password, port, json, function(msg){
//do whatever you want, when it finished
}, return_as, async);

The answer from the server will be found in the msg variable received by the callback function. You will receive it in the format specified by return_as parameter. See the parameter explanation below.

Parameter explanation:
cpanel_module_name – the cPanel module you would like to call from API2
cpanel_fct_name – a cPanel function from the module above
domain – the domain of your host
cp_user – cPanel username
cp_password – cPanel password
port – cPanel port, usually 2082 for unsecure and 2083 for secure
json – specifies the format of the received data, set “json” for json, set “xml” or leave it empty for xml
function(){ – a callback function, this is executed after the cpanel request has been executed
return_as – the format format for returning data, set “text” or leave it empty to return as text, “json” for a JSON object, “xml” for an xml object
async – the call should be synchronous or asynchronous? Set false for synchronous and true for asynchronous

Example, list all Addon Domains from cPanel:

cpanel_call("AddonDomain", "listaddondomains", "my_domain.com", "my_user", "my_pass", 2082, "xml", function(msg){
alert("msg"); //this is what the server returned
}, "text", false);

One last thing! My function uses a BASE64 encode class, from: webtoolkit.info! Copy the function from below or from their website: http://www.webtoolkit.info/javascript-base64.html. Make sure your page contains this function, otherwise my function won’t work.


/**
*
*  Base64 encode / decode
*  http://www.webtoolkit.info/
*  Class Needed for authentication
*
**/

var Base64 = {

// private property
_keyStr : "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",

// public method for encoding
encode : function (input) {
var output = "";
var chr1, chr2, chr3, enc1, enc2, enc3, enc4;
var i = 0;

input = Base64._utf8_encode(input);

while (i < input.length) {

chr1 = input.charCodeAt(i++);
chr2 = input.charCodeAt(i++);
chr3 = input.charCodeAt(i++);

enc1 = chr1 >> 2;
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
enc4 = chr3 & 63;

if (isNaN(chr2)) {
enc3 = enc4 = 64;
} else if (isNaN(chr3)) {
enc4 = 64;
}

output = output +
this._keyStr.charAt(enc1) + this._keyStr.charAt(enc2) +
this._keyStr.charAt(enc3) + this._keyStr.charAt(enc4);

}

return output;
},

// public method for decoding
decode : function (input) {
var output = "";
var chr1, chr2, chr3;
var enc1, enc2, enc3, enc4;
var i = 0;

input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");

while (i < input.length) {

enc1 = this._keyStr.indexOf(input.charAt(i++));
enc2 = this._keyStr.indexOf(input.charAt(i++));
enc3 = this._keyStr.indexOf(input.charAt(i++));
enc4 = this._keyStr.indexOf(input.charAt(i++));

chr1 = (enc1 << 2) | (enc2 >> 4);
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
chr3 = ((enc3 & 3) << 6) | enc4;

output = output + String.fromCharCode(chr1);

if (enc3 != 64) {
output = output + String.fromCharCode(chr2);
}
if (enc4 != 64) {
output = output + String.fromCharCode(chr3);
}

}

output = Base64._utf8_decode(output);

return output;

},

// private method for UTF-8 encoding
_utf8_encode : function (string) {
string = string.replace(/\r\n/g,"\n");
var utftext = "";

for (var n = 0; n < string.length; n++) {

var c = string.charCodeAt(n);

if (c < 128) {
utftext += String.fromCharCode(c);
}
else if((c > 127) & (c < 2048)) {
utftext += String.fromCharCode((c >> 6) | 192);
utftext += String.fromCharCode((c & 63) | 128);
}
else {
utftext += String.fromCharCode((c >> 12) | 224);
utftext += String.fromCharCode(((c >> 6) & 63) | 128);
utftext += String.fromCharCode((c & 63) | 128);
}

}

return utftext;
},

// private method for UTF-8 decoding
_utf8_decode : function (utftext) {
var string = "";
var i = 0;
var c = c1 = c2 = 0;

while ( i < utftext.length ) {

c = utftext.charCodeAt(i);

if (c < 128) {
string += String.fromCharCode(c);
i++;
}
else if((c > 191) & (c < 224)) {
c2 = utftext.charCodeAt(i+1);
string += String.fromCharCode(((c & 31) << 6) | (c2 & 63));
i += 2;
}
else {
c2 = utftext.charCodeAt(i+1);
c3 = utftext.charCodeAt(i+2);
string += String.fromCharCode(((c & 15) << 12) | ((c2 & 63) << 6) | (c3 & 63));
i += 3;
}

}

return string;
}

}

If you set up everything correctly the alert above should show the xml that cPanel API returned. If you find something that is hard to understand please post it below in the comment box and I will try to answer as soon as possible!

Xul and XPCOM: Delete files

Here is a little handy function for removing files with Javascript on Mozzila platform:

function delete_file_by_path(path)
{
var file = Components.classes['@mozilla.org/file/local;1']
.createInstance(Components.interfaces.nsILocalFile);
file.initWithPath(path);
if (file.exists())
file.remove(false);
}

Create a new instance of nsILocalFile, and the use the initWithPath function to initialize the file, and the delete the file is exists.