Archive for January, 2006

Let’s assume that you have a script that creates folders and files with specific php functions.
On Linux-based servers, these files and folders belongs to “apache” user, and not to you. Of course, you can create them with 777 permissions, but default is 755, which means no write permissions to other users and groups than “apache”.
Can you delete these files and folders through FTP ? No way.
The only way to delete them is like you create (through php functions, under the “apache” user):
unlink (file) deletes a file
rmdir (folder) deleted a folder
You can use them independently or, if you want to recursive delete a folder, its subfolders and files you can use this function (i found it php manual unlink page):

function SureRemoveDir($dir) {
   if(!$dh = @opendir($dir)) return;
   while (($obj = readdir($dh))) {
     if($obj==‘.’ || $obj==‘..’) continue;
     if (!@unlink($dir.‘/’.$obj)) {
         SureRemoveDir($dir.‘/’.$obj);
     } else {
         $file_deleted++;
     }
   }
   if (@rmdir($dir)) $dir_deleted++;
}

and you can simply call it as:

<? SureRemoveDir ("Test"); ?>

Another techniques can also solve this situation, such as:
– if you have SSH access, you can user sudo chown command to take control and then delete then normally
– you can ask for help to an administrator (he will also use the sudo chown)
– use suExec, if it is installed on the machine

Andrei
http://www.webxpert.ro

Comments 4 Comments »

Typical formatting of all HTML 4.0 FORM tag has a strange behavior when it contains a table cell inside. A strange vertical space appears after the FORM, even there is no <BR> or something else there.
Here is the a typical behavior:

Email:

and the code is:

<table style="text-align: left; background-color: #336699; width: 300px;" border="1" cellpadding="2" cellspacing="0">
    <tr>
      <td>
      <form name="example1">
        <table style="text-align: left; background-color: #ffffff; width: 100%;" border="1" cellpadding="2" cellspacing="0">
            <tr>
              <td><small><span style="font-family: Tahoma;">Email:</span></small></td>
              <td><input name="text1" value="just a test"/></td>
            </tr>
            <tr>
              <td rowspan="1" colspan="2"><input name="Submit" value="Submit" type="submit"/></td>
            </tr>
        </table>
      </form>
      </td>
    </tr>
</table>

Read the rest of this entry »

Comments No Comments »

This is intended to be a tutorial of how to use ASP.Net DataGrid for view, edit, insert and delete items from an XML file.
Many people probably would need to keep some small amount of data in XML files rather than in the database. Manipulating this data is very simple and it can be made with a DataGrid, and this is the scope of this article, to show you how.

The result must look like this one:

First of all we need the XML file

< ?xml version="1.0" standalone="yes"?>
<catalog>
  <cd>
    <title>Empire Burlesque</title>
    <artist>Bob Dylan</artist>
    <country>USA</country>
    <price>10.90</price>
    <year>1985</year>
    <style>1</style>
  </cd>
  <cd>
    <title>Flick Of The Switch</title>
    <artist>AC DC</artist>
    <country>Australia</country>
    <price>15.90</price>
    <year>1983</year>
    <style>2</style>
  </cd>
  <cd>
    <title>Gold</title>
    <artist>Nirvana</artist>
    <country>USA</country>
    <price>10.90</price>
    <year>1991</year>
    <style>4</style>
  </cd>
  <cd>
    <title>Kings of Metal</title>
    <artist>Manowar</artist>
    <country>USA</country>
    <price>17.90</price>
    <year>1988</year>
    <style>3</style>
  </cd>
  <cd>
    <title>Rocka Rolla</title>
    <artist>Judas Priest</artist>
    <country>England</country>
    <price>16.90</price>
    <year>1974</year>
    <style>3</style>
  </cd>
</catalog>

We saved this file in the application root as source.xml

Then we will create a new webform page named xmlDataGrid.aspx, and add a DataGrid control, a Button and set tht title, exactly like in the above screenshot.
AutoGenerateColumns must set to false and must add the following columns in the DataGrid:
– Title binded to TITLE DataField
– Artist binded to ARTIST DataField
– Country binded to COUNTRY DataField
– Price binded to PRICE DataField
– Year binded to YEAR DataField
– Style binded to STYLE DataField
– Button column for “Edit, Update, Cancel”
– Button column for “Delete”

The code for the aspx page is the following:

<html>
<head>
</head>
<body>
    <form runat="server">
        <p align="center">
            <font face="Tahoma"><strong>DataGrid &amp; XML DataSource Example</strong></font>
           

           

            <asp :Button id="btnAdd" onclick="btnAdd_Click" runat="server" Text="Add new row"></asp>
           

            <asp :DataGrid id="dgCatalog" runat="server" AlternatingItemStyle-BackColor="#EEEEEE" ItemStyle-BackColor="#FFFFCC" HorizontalAlign="Center" Font-Size="10px" Font-Name="Tahoma" CellPadding="3" Font-Names="Tahoma" AutoGenerateColumns="False" OnCancelCommand="dgCatalog_CancelCommand" OnDeleteCommand="dgCatalog_DeleteCommand" OnEditCommand="dgCatalog_EditCommand" OnUpdateCommand="dgCatalog_UpdateCommand" Width="550px">
                <alternatingitemstyle backcolor="#EEEEEE"></alternatingitemstyle>
                <itemstyle backcolor="#FFFFCC"></itemstyle>
                <headerstyle backcolor="Aqua" font-italic="False" font-strikeout="False" font-underline="False" font-overline="False" font-bold="True"></headerstyle>
                <columns>
                    <asp :BoundColumn DataField="TITLE" HeaderText="Title"></asp>
                    <asp :BoundColumn DataField="ARTIST" HeaderText="Artist"></asp>
                    <asp :BoundColumn DataField="COUNTRY" HeaderText="Country"></asp>
                    <asp :BoundColumn DataField="PRICE" HeaderText="Price"></asp>
                    <asp :BoundColumn DataField="YEAR" HeaderText="Year"></asp>
                    <asp :BoundColumn DataField="STYLE" HeaderText="Style"></asp>
                    <asp :EditCommandColumn CancelText="Cancel" UpdateText="Update" EditText="Edit"></asp>
                    <asp :ButtonColumn CommandName="Delete" Text="Delete"></asp>
                </columns>
            </asp>
        </p>
        <p align="center">
            <font face="Tahoma" size="1">©2005 Andrei DANEASA – <a href="http://www.webxpert.ro">http://www.webxpert.ro</a></font>
        </p>
    </form>
</body>
</html>

In order to add some functionality to the DataGrid, first of all we need to load the data to the grid.
In the Page_Load event, we wil fill the dataset with XML data and then bind the DataGrid to this dataset:

//the dataset that will keep the data
System.Data.DataSet myDataSet = new System.Data.DataSet();

void Page_Load(object sender, EventArgs e) {
    FillData();
    if (!Page.IsPostBack) {
        dgCatalog.DataBind();
    }
}

//populate the dataset from XML
void FillData() {
    //read the XML into the DataSet
    myDataSet.ReadXml(Server.MapPath("source.xml"));
    //set the grid’s DataSource to DataSet
    dgCatalog.DataSource = myDataSet;
}

Now the DataGrid will display the data like in the above screenshot. We need to add functionalities for Edit, Delete and Update events.
Before writing these events, we must write the function that will save the dataset back to disk as XML file.

//write XML back to disk
void SaveData() {
    myDataSet.WriteXml(Server.MapPath("source.xml"));
}

The simplest events are Edit and Delete:

//event occurs when Edit link is clicked
void dgCatalog_EditCommand(object sender, DataGridCommandEventArgs e) {
    //turn the selected Item in Edit mode
    dgCatalog.EditItemIndex = e.Item.ItemIndex;
    dgCatalog.DataBind();
}

//event occurs when Delete link is clicked
void dgCatalog_DeleteCommand(object sender, DataGridCommandEventArgs e) {
    //delete from DataSet
    myDataSet.Tables[0].Rows[e.Item.ItemIndex].Delete();
    //Write the changes to disk
    SaveData();
    //rebind the data
    dgCatalog.DataBind();
    dgCatalog.EditItemIndex = -1;
    dgCatalog.DataBind();
}

A little complicated is Cancel event. Because we have a button that adds a new row to the dataset and change the text for Update link to “Insert”, we must assure that on Cancel event the text for the link is set back to “Update”.

//event occurs when Cancel link is clicked
void dgCatalog_CancelCommand(object sender, DataGridCommandEventArgs e) {
    //put the link title back to "Update"
    EditCommandColumn ecc = (EditCommandColumn) dgCatalog.Columns[6];
    ecc.UpdateText = "Update";

    //reset the selection
    dgCatalog.EditItemIndex = -1;
    dgCatalog.DataBind();
}

The “Add new row” button adds non-default functionality to the DataGrid control. A simple DataGrid does not have an event for Add or Insert. We used a trick to do this by adding a blank row to the dataset and then turn that row into edit mode and change the text for Update link to “Insert”.

//event occurs when "Add new row" button is pressed
void btnAdd_Click(object sender, EventArgs e) {
    //add an extra row to the dataSet
    InsertEmpty();
    //the new row is the last one in the dataset
    dgCatalog.EditItemIndex = myDataSet.Tables[0].Rows.Count-1;

    //change the update button title to "Insert"
    EditCommandColumn ecc = (EditCommandColumn) dgCatalog.Columns[6];
    ecc.UpdateText = "Insert";

    //rebind
    dgCatalog.DataBind();
}

//procedure that add an empty row to the DataSet
private void InsertEmpty() {
    //insert a new row at the end of the dataSet
    myDataSet.Tables[0].Rows.InsertAt(myDataSet.Tables[0].NewRow(), myDataSet.Tables[0].Rows.Count);
}

We missed one single event: Update. Here’s the code (it’s a little complicated due to the duble functionality: Update and Insert:

//event occurs when Update or Insert link is clicked
void dgCatalog_UpdateCommand(object sender, DataGridCommandEventArgs e) {
    System.Data.DataRow dr;
    //we must use the catch to identify a wrong index
    try {
        //if this event is called from Update
        dr = myDataSet.Tables[0].Rows[e.Item.ItemIndex];
    }
    catch {
        //if the event is called from Insert
        myDataSet.Tables[0].Rows.InsertAt( myDataSet.Tables[0].NewRow(), myDataSet.Tables[0].Rows.Count);
        dr = myDataSet.Tables[0].Rows[e.Item.ItemIndex];
    }

    //pupulate the dataRow cells with the supplied values
    dr[0] = ((TextBox) (e.Item.Cells[0].Controls[0])).Text;
    dr[1] = ((TextBox) (e.Item.Cells[1].Controls[0])).Text;
    dr[2] = ((TextBox) (e.Item.Cells[2].Controls[0])).Text;
    dr[3] = ((TextBox) (e.Item.Cells[3].Controls[0])).Text;
    dr[4] = ((TextBox) (e.Item.Cells[4].Controls[0])).Text;
    dr[5] = ((TextBox) (e.Item.Cells[5].Controls[0])).Text;
    //save dataset
    SaveData();

    //put the link title back to "Update"
    EditCommandColumn ecc = (EditCommandColumn) dgCatalog.Columns[6];
    ecc.UpdateText = "Update";

    //rebind
    dgCatalog.DataBind();
    dgCatalog.EditItemIndex = -1;
    dgCatalog.DataBind();
}

You can download the sources here
* All this article was written using only Freeware applications: ASP.NET Web Matrix for writing and testing the page, Notepad++ for writing the XML file, Gimp for screenshots.

Comments 5 Comments »

Nowadays everybody talks about Ajax. To be truly honest, I thought that is something extremely difficult, but it is not.
It is no more than a programming technique (Asynchronous JavaScript and XML) in order to load external info in DIVs, without reloading the whole page (Gmail users probably knows best what I’m talking).

The reason why it was not widely used was that the XMLHttpRequest object is not supported by all browsers. Internet Explorer has his own object called XMLHTTP (as an ActiveX object).
Since all new browsers have this facility, this technology (I think that calling this “Language” is not fair) exploded.

First of all we need to define some javascripts to create the object and handle the request. For this particular example, I used another javascript function to make the request.

<script language="javascript"  type="text/javascript">

        //cross-browser object creation function
        function createRequestObject() {
                var ret;
                //read the user’s browser
                var browser = navigator.appName;
               
                //Internet Explorer has his own object
                if(browser == "Microsoft Internet Explorer"){
                        ret = new ActiveXObject("Microsoft.XMLHTTP");
                }
                else{
                        ret = new XMLHttpRequest();
                }
                return ret;
        }
       
        //create a request object
        var http = createRequestObject();
       
        //you will call this function
        function sendRequest(action) {
                //here’s the catch – call an external page
                http.open(‘get’, ‘req.php?action=’+action);
                //wait until the request is completed
                http.onreadystatechange = handleResponse;
                //finalize the request
                http.send(null);
        }
       
        //function that handle response state changes
        function handleResponse() {
                //fires only the object change to state 4
                if(http.readyState == 4){
                        //get the text from the external procedure
                        var response = http.responseText;
                        var update = new Array();
       
                        //parse the text
                        if(response.indexOf(‘|’ != -1)) {
                                //response should be ‘divID|value"
                                update = response.split(‘|’);
                                //update the element with the divID with the value
                                document.getElementById(update[0]).innerHTML = update[1];
                        }
                }
        }

</script>

After this we need to call sendRequest function from HTML, just like this:

<a href="javascript:sendRequest(‘currentDateTime’)">update time</a>

As you see, this example get the date from an external script (req.php), and return a string with the id of the DIV that will be updated and the value of the DIV, separated by a pipe:
Below is the entire code from req.php. It’s easy, don’t it?

<?
  //test the action from request
  switch($_REQUEST[‘action’]) {
        case ‘currentDateTime’:
                //return the divID and the value separated by a pipe
                echo "currentDateTime|".date("d/m/Y h:i:s");
        break;
  }
?>

In the original page we need a DIV to be filled with external info

<div id="currentDateTime">
</div>

The whole code from HTML file is:

< !DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head>
<title>Ajax demystified</title>
<style type="text/css">
A {
  color: #336699;
  text-decoration: none;
  font-weight: bold;
}

A:hover {
  color: #FF0000;
  font-weight: bold;
}

BODY {
  font-family: Tahoma, Verdana, Arial, sans-serif;
  font-size: 12px;
}

.mark {
  color: #FF0000;
  font-weight: bold;
}
</style>
<script language="javascript"  type="text/javascript">

        //cross-browser object creation function
        function createRequestObject() {
                var ret;
                //read the user’s browser
                var browser = navigator.appName;
               
                //Internet Explorer has his own object
                if(browser == "Microsoft Internet Explorer"){
                        ret = new ActiveXObject("Microsoft.XMLHTTP");
                }
                else{
                        ret = new XMLHttpRequest();
                }
                return ret;
        }
       
        //create a request object
        var http = createRequestObject();
       
        //you will call this function
        function sendRequest(action) {
                //here’s the catch – call an external page
                http.open(‘get’, ‘req.php?action=’+action);
                //wait until the request is completed
                http.onreadystatechange = handleResponse;
                //finalize the request
                http.send(null);
        }
       
        //function that handle response state changes
        function handleResponse() {
                //fires only the object change to state 4
                if(http.readyState == 4){
                        //get the text from the external procedure
                        var response = http.responseText;
                        var update = new Array();
       
                        //parse the text
                        if(response.indexOf(‘|’ != -1)) {
                                //response should be ‘divID|value"
                                update = response.split(‘|’);
                                //update the element with the divID with the value
                                document.getElementById(update[0]).innerHTML = update[1];
                        }
                }
        }

</script>
</head>

<body onload="javascript:sendRequest(‘currentDateTime’)">
        This page shows how Ajax is working. Is is nothing fabulous here.
       

 Click here for
         <a href="javascript:sendRequest(‘currentDateTime’)">update time</a>
          <div id="currentDateTime" class="mark">
          </div>
       
Nothing else but the date and time is updated.
       

        &copy;2006 <a href="mailto:andrei@webxpert.ro">Andrei DANEASA</a>
</body>
</html>

If you want to see this example working and test it, click here.

*This is not intended to be a complete tutorial of Ajax, but it covers the main functionalities. The rest is only programmer’s imagination.

Andrei
http://www.webxpert.ro

Comments No Comments »