Tuesday, February 22, 2011

PHP DB2 extension should support features like timeout checking.

I ran into very troublesome problem when I use DB2 connection from PHP to call RPG stored procedure. What happened is described in the following diagram.
  
As you can see, if calling a bad configured RPG stored procedure from PHP through DB2 extension on the same machine where Zend server and DB2 are installed, Zend Server may hang and it can not even be restarted from Zend Menu in green screen of i5/OS.

The appeared phenomenon is that QSQSRVR jobs is under MSGW status and seems the waiting status will never be broken. I am not sure which part exactly causes this. But, I think adding a time-out check mechanism in PHP DB2 extension on IBM i could be considered. The detailed discussion can be found from Zend Forums.

Thursday, February 17, 2011

naming scheme of i5/OS commands

This post is a citation from http://www.mcpressonline.com. I like it because this tip helps me to remember command set from i5/OS. I cite it to my blog here as I think this place is better than my Web browser bookmark.
  1. First, a three-letter abbreviation for a verb, such as create, remove, print, or send. See the table below.
  2. Last, a series of abbreviations for modifiers, such as file, program, job queue, or user profile. These abbreviations are usually three letters long, but there are many exceptions.



Example Abbreviations
Verbs
Modifiers
CRT
Create
F
File
CHG
Change
PF
Physical File
DLT
Delete
LF
Logical File
ADD
Add
SRCF
Source File
RMV
Remove
CLPGM
CL Program
DSP
Display
RPGPGM
RPG Program
WRK
Work with
MSGQ
Message Queue
STR
Start
OUTQ
Output Queue
END
End
JOBQ
Job Queue


DTAQ
Data Queue


DTAARA
Data Area


SBS
Subsystem


For example,
DSPSBSD SBSD(QUSRWRK) => DSP+SBS+D(display)
STRSQL  =>  STR + SQL 
WRKJVMJOB  =>  WRK + JVM  + JOB
CRTDTAQ  => CRT  +  DTAQ
DSPMSGD CPEnnnn (where NNNN is 4-digit error number)
CHGATR OBJ(Sth) ATR(*READONLY) VALUE(*NO)
WRKLNK 'your/file'

The full article is here

Wednesday, February 16, 2011

seven ways for cross domain script programming

I was interested in making a conclusion about how to make XSS (cross site script)application. But, this is not an article about how to write javascript code to do XSS code hack. I just want to make an conclusion on this to show possible techniques used by ASP, who wants to integrate all of its existing web application into one portal. Maybe, I should call it as Cross Domain Script instead of Cross Site Script as XSS make me think it is a technique to insert malicious script into Web page.

As far as I know, there are at least seven techniques to make cross domain script app and plus one special way for flash player only.

1) Using crossdomain.xml . This is a special technique invented for Flash player. For example, if a Flex programmer wants his flash application loaded from Web site to access resource on Web site B, which is different from its original site, he can ask the administrator of Web site B to put a crossdomain.xml file on the Web site B. In the xml file, it will be declared that this site is allowed to access resource on Web site B. BTW, this crossdomain.xml could be security hole for any site that allow user to upload file. crossdomain.xml should be forbidden to be uploaded. Here are two samples Google Docs puts Google Users at Risk and Using Google App Engine as a Proxy Server

2) Using reverse proxy. One traditional way to make cross domain script app is using reverse proxy. Actually, I really think this is a "walk around" technique for cross domain script as its idea is to "cheat" Web browser that content from different domains are from same domain, which is actually reverse proxy's domain.

3) Using digital Sign Javascript. This technique is similar as signing a Java applet. However, this will suffered from different actions taken by Web browser users. The code can not do cross domain request if end user say NO.

4) Access-Control-Allow-Origin HTTP header field. It is defined by W3C as Cross-Origin Resource Sharing. It is supported by Fireforx 3.5 or newer and IE 8 or newer. In IE, for the Internet access, you need to enable it. For Intranet access, by default, it is enabled.

"Access-Control-Allow-Origin" header is not just one HTTP header. It is a set of HTTP headers. Below lists out some.

Access-Control-Allow-Origin: http://yiyujia.blogspot.com
Access-Control-Allow-Credentials: true
Access-Control-Allow-Methods: PROPFIND, PROPPATCH, COPY, MOVE, DELETE, MKCOL, LOCK, UNLOCK, PUT, GETLIB, VERSION-CONTROL, CHECKIN, CHECKOUT, UNCHECKOUT, REPORT, UPDATE, CANCELUPLOAD, HEAD, OPTIONS, GET, POST
Access-Control-Allow-Headers: Overwrite, Destination, Content-Type, Depth, User-Agent, X-File-Size, X-Requested-With, If-Modified-Since, X-File-Name, Cache-Control
Access-Control-Max-Age: 3600


5) using iframe. iframe is a popular way for Web app developer to achieve cross site script programming. There are many online articles describe XSS with iframe.

6) Using JSON Padding (JSONP). This method include a server side proxy programm, which generate data in javaScript type (JSONP) and use a callback parameter to allow javascript from other domain residing in browser to consume the data. You can make your own server side proxy program. However, here are two example from yahoo (demo link) and google (demo link)respectively.

7) using bookmarklet. If it is possible for software vendor to ask user to bookmark the web page, we can create a bookmarklet to achieve cross site scripting. A bookmarklet is a piece of JavaScript code attached to hyperlink URL. Once the hyperlink is clicked, your JavaScrript code is run. There is limitation for the length of JavaSccript code. However, with dynamic JavaScript loading, we can easily workaround this limitation.

As conclusion, methods 1 and 4 are similar: server tells browser that it is OK for script loaded from other domain to access its resource. Method 2 is a popular way to walk around the cross domain forbidden. But, it block some information from client from our server side application too. Method 3 is complex and highly depends on end user's behavior. Methods 4, which depends on support from different Web browsers. However, those popular web browser supports this header and they are upgraded quickly. Method 5, using iframe, is a well known XSS techniques. Method 6 is also a technique belongs to server side solution. Method 7 is an interesting way.

BTW, for mod_jk does not work with mod_headers. But, it is easy to write a servlet filter to add any HTTP headers you want.

Monday, February 14, 2011

IBM Web Shpere MQ client for PHP on IBM i platform.

I am designing a log framework for my PHP code on IBM i. As the application will not only log some system level info but also many application level logs, I can expect that the log traffic will be crowed. In this case, I would like to let the app to throw log info into a message queue rather than to directly write into database.

However, I noticed that Zend Framework (v1.10) on IBM i only partially supports ActiveMQ as MQ client. I also find that there are at least two PHP extension in PECL to support IBM Web Sphere MQ: mqseries and SAM . However, as extensions, both of them are wrappers of under native code. So, they might have compiled libraries for Linux or MS Windows. But, there is no compiled package for IBM i platform.

So, we can see that we can not use IBM Web Sphere MQ with PHP on IBM i platform. In my case, I can not use Zend Server for IBM i and IBM Web Sphere together with Zend PHP. Therefore, using ActiveMQ on IBM i with Zend PHP on IBM will be only option (not consider other asynchronous message methods). But, I feel this is funny as I think IBM will not see ActiveMQ, which implements STOMP protocol, is used to replace Web Sphere MQ on IBM i and Zend will not see developer finally adband Zend server for IBM i and go back to linux, where more PHP vendors can compete at. As a developer, it is uncomfortable not to be able to use most nature way to finish project on IBM i.

If possible, we can put PHP engine on a Linux server and install MySQL server and DB2i storage engine on IBM i. then, PHP developer can walk around the DB2 Connect license issue and Web Sphere MQ client issue. However, if this happen, technically speaking, it will be easier for applicaton developer to shift whole application out of IBM i platform. Is this what IBM and Zend want? I guess they will not. So, I think Zend or IBM should release a PHP version Web Sphere MQ client for IBM i platform. I put my thoughts on Zend forum (link). I hope they will see it.

Friday, February 11, 2011

How to run multiple Xlet applicaitons in one DVB service stream.

When I cleaned my backup hard driver, I found some code which makes me to recall pieces of interesting work I did in Malaysia years ago. I did iTV application consultant for a Malaysia Broadcaster, which is doing trial broadcasting of DVB HDTV at that time.

Teltext is a popular TV service in Asia, where PAL is in the dominant position. Therefore, they want to have a new version of "teltext", which is written in MHP. However, since their STB standard has not been finalized and all MHP applications are broadcasting application instead of resident application. Then, they have a problem now. How can they put two or more broadcasting application in one digital channel (service) and user can select among application only by simply clicking a button on remote control. It must be as easy as viewer clicks button to see teletext. I made a simple Xlet to help them. It might not be perfect solution. But it works. The key is that I ejected two MHP application into one service and configure one of them to be in auto start state and the other is not. I used TSBroadcaster as head end system. The headend configuration steps are too complex to be a post. But, I will put the simple version of my work here to help me to recall later.

/*
 * XletSwitcher.java
 *
 */
package blog.jia.xlet.util;

import java.util.Vector;
import java.util.Enumeration;
import javax.tv.xlet.Xlet;
import javax.tv.xlet.XletContext;

import org.dvb.application.AppAttributes;
import org.dvb.application.AppProxy;
import org.dvb.application.AppsDatabase;
import org.dvb.application.CurrentServiceFilter;
import org.dvb.application.DVBJProxy;
import org.dvb.event.EventManager;
import org.dvb.event.UserEvent;
import org.dvb.event.UserEventListener;
import org.dvb.event.UserEventRepository;
import org.havi.ui.event.HRcEvent;

/**
 *
 * @author Jia Yiyu
 */

public class XletSwitcher implements Xlet, UserEventListener {

    private  XletContext context;
    private String supertekName;
    private String appName;
    private AppProxy supertekProxy;
    private AppProxy tempProxy;
    private AppProxy activeProxy;
    private Vector appProxies;

    private AppProxy[] proxyArray;
    private boolean supertekOn;

   
    /** Creates a new instance of XletSwitcher */
    public XletSwitcher() {

    }

    /**
     * destroyXlet
     *
     * @param boolean0 boolean
     */

    public void destroyXlet(boolean boolean0) {
        //doDestroy();
    }

    /**
     * initXlet
     *
     * @param xletContext XletContext
     */

    public void initXlet(XletContext xletContext) {

        String[] args = (String[])xletContext.getXletProperty(XletContext.ARGS);

        if(args != null && args.length == 1)
            supertekName = args[0];
        else 
   supertekName = "supertek";

        appProxies = new Vector();

        //initializing key event listener.

        UserEventRepository rep = new UserEventRepository("jia");

        rep.addKey(HRcEvent.VK_TELETEXT);

        EventManager.getInstance().addUserEventListener(this, rep);

        //supertek's initalizing status is invisible.'
        supertekOn = false;

    }    

    /**
     * pauseXlet
     */
    public void pauseXlet() {
        //doPause();
    }

    /**
     * startXlet
     */
    public void startXlet() {

        // startXlet() should not block for too long, and doing UI stuff is
        // way too long.  To solve this, we start another thread to do the work
        
        //initialize the appsdatabase

        AppsDatabase appsdatabase = AppsDatabase.getAppsDatabase();

        if (appsdatabase != null) {            

            Enumeration enumeration =
                    appsdatabase.getAppAttributes(new CurrentServiceFilter());

            if (enumeration != null) {

                while (enumeration.hasMoreElements()) {

                    AppAttributes appattributes = (AppAttributes) enumeration.nextElement();                    
                    tempProxy = appsdatabase.getAppProxy(appattributes.getIdentifier());

                    if (appattributes.getName().trim().equals(supertekName)) {
                        supertekProxy = tempProxy;
                    }
                    else {
                        if(tempProxy.getState() == DVBJProxy.STARTED)
                            activeProxy = tempProxy; 
                        appProxies.add(appsdatabase.getAppProxy(appattributes.getIdentifier()));
                    }
                }
                proxyArray = (AppProxy[])appProxies.toArray();
                appProxies = null;
            }
        }
    }

    public void userEventReceived(UserEvent e) {
        if(e.getType() == HRcEvent.KEY_PRESSED) {
            if(e.getCode() == HRcEvent.VK_TELETEXT){                
                if(supertekProxy != null){
                    if(supertekOn){
                        supertekProxy.stop(true);//maybe i will use pause.
                        if(activeProxy != null) activeProxy.start();
                        supertekOn = false;
                    } else {
                        activeProxy = getActiveProxy();
                        activeProxy.stop(true);
                        supertekProxy.start();
                        supertekOn = true;
                    }
                }
            }
        }
    }


    private AppProxy getActiveProxy(){

        for (int i=0; i < proxyArray.length; i++){

            if(proxyArray[i].getState() == DVBJProxy.STARTED) return proxyArray[i];            

        }
        return null;
    }
}


Wednesday, February 9, 2011

jquery 1.5 plugin for Aptana 2.0 for code assist

I recently reviewed jQuery again. I feel it has been more attractive. For examples, I like its plugins jqGrid, sparkline, and Raphael. It seems its quality and community size have been grown a lot. So, I am interested in trying it again.

I download and installed Aptana Studio 2.0 on my machine. But, it currently support jquery 1.4.2 version. Therefore, I created a jquery 1.5 version plugin for aptana 2.0. I created a simple project and see it works fine so far. Here is the simple installation steps.

1)Download plugin by clicking this: com.jquery.1.5_1.5.jar

2) Copy file com.jquery.1.5_1.5.jar to directory %apatana install directory%/dropins/

3) Start Aptana 2.0 and enable the code assist as shown in the following picture.

4) Open JQuery View by select Menu Windows -> Show view -> Others... -> Visual JQuery . Below is a screen shot for this.

Enjoy it.

Tuesday, February 8, 2011

A simple tutorial about creating SOAP Web Service in netbean 6.9.1 with Metro and use user defined class as parameters for Web service call.

In Java world, as far as I know, there are at least five Web service stacks: Metro, Axis2, Glue, JBossWS and CXF. According to this WS stack comparison, it seems that Axis2 supports most features than others do. However, according to this performance comparison article, it seems that Metro has better performance than Axis2 when WS-Security is used in application. I used Axis before. And I think every thing keeps changing including the performance benchmark. I will just give Metro a try this time. There are many tutorials online. But, most of them just show a simple function (operator) to operate on primary or String type. Obviously, it is not enough for a real project as real project always requires to deliver user defined classes as parameters for SOAP Web Service call.

Below is the steps to create a simple Metro (JAX-WS) based Web service and the service consumer. It is a simple stub Web service. But, it could be a good start for a real project, where user defined classes as parameters are required.

1) Well, let's start it by creating a Web project in Netbeans. By clicking  File -> New Project... -> Java Web -> Web Application, we see screen like below. I name the project as JiaMetroWS and give it package name as jia.blog.ws. Click Finish to close this dialogue window.


2) Select the new created project jiaBlogWS in project list and right click the node. Click New -> Web Service... as shown below.


3) Right click the new created Web service jiaBlogWs and select add operator, we see below screen. We click the "add operation" button to add a operator (function) into the new created Web service jiaBlogWS.
4) After add the operator, we can see the main area of Netbean is like this. Please notice that there are two buttons there, source and Design. I suggest to click source to have a look at the source code with Web service annotation. These annotations are keys.
I added some dummy data in the class. And, I created two helper classes Invoice.java and Item.java as return parameters. Now, we have jiaMetroWS source code like below,

JiaBlogWS.java
package jia.blog.ws;

import java.util.ArrayList;
import javax.jws.WebMethod;
import javax.jws.WebParam;
import javax.jws.WebService;

/**
 *
 * @author Yiyu Jia
 */
@WebService()
public class jiaBlogWS {

    /**
     * Web service operation
     */
    @WebMethod(operationName = "callSP")
    public Invoice[] callSP(@WebParam(name = "customID")
    final String customID) {
        //creat a dummy invoice data.
        Invoice inv = new Invoice();
        inv.setInvoiceNum(2);
        inv.setName("yiyu jia");
        ArrayList list1 = new ArrayList();
        Item i1 = new Item();
        i1.setItemNum("00011");
        list1.add(i1);
        inv.setItems(list1);
        //crteate another dummy invoice data.
        Invoice inv2 = new Invoice();
        inv2.setInvoiceNum(3);
        inv2.setName("yan zhang");
        ArrayList list2 = new ArrayList();
        Item i2 = new Item();
        i2.setItemNum("00011");
        list2.add(i2);
        inv2.setItems(list2);

        //create a dummy invoice array as return data.
        Invoice[] invs = new Invoice[2];
        invs[0] = inv;
        invs[1] = inv2;
        return invs;
    }
}

Invoice.java
package jia.blog.ws;

import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;

/**
 *
 * @author Yiyu Jia
 */
@XmlAccessorType (XmlAccessType.FIELD)
public class Invoice {

    public int invoiceNum;

    public String name;

    @XmlElement(name = "items")
    List items;

    public int getInvoiceNum() {
        return invoiceNum;
    }

    public void setInvoiceNum(int invoiceNum) {
        this.invoiceNum = invoiceNum;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List getItems() {
        return items;
    }

    public void setItems(List items) {
        this.items = items;
    }

}

Item.java
import javax.xml.bind.annotation.XmlAccessorType;
/**
 *
 * @author Yiyu Jia
 */
@XmlAccessorType (XmlAccessType.FIELD)
public class Item {
    String itemNum;

    public String getItemNum() {
        return itemNum;
    }

    public void setItemNum(String itemNum) {
        this.itemNum = itemNum;
    }
}

Also, in order to illustrate a situation closing to real world app, I created two helper classes, which are used as parameters returned by jiaMetroWS.

Invoice.java
package jia.blog.ws;

import java.util.List;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
import javax.xml.bind.annotation.XmlElement;

/**
 *
 * @author Yiyu Jia
 */
@XmlAccessorType (XmlAccessType.FIELD)
public class Invoice {

    public int invoiceNum;

    public String name;

    //declaring list of items as List type.
    @XmlElement(name = "items")
    List items;

    public int getInvoiceNum() {
        return invoiceNum;
    }

    public void setInvoiceNum(int invoiceNum) {
        this.invoiceNum = invoiceNum;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public List getItems() {
        return items;
    }

    public void setItems(List items) {
        this.items = items;
    }

}

Item.java
package jia.blog.ws;

import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
/**
 *
 * @author Yiyu Jia
 */
@XmlAccessorType (XmlAccessType.FIELD)
public class Item {
    String itemNum;

    public String getItemNum() {
        return itemNum;
    }

    public void setItemNum(String itemNum) {
        this.itemNum = itemNum;
    }
}

Now, we can test our Web service. Since I use Glassfish 3.0 as my Web container, I can see the test page by right click Web Service node in project explorer and select "Test Web Service". After the testing page has been shown in your Web browser, you can play around by input parameter and get return. Also, we can see the request SOAP message in XML format and the return SOAP message. And, the most useful info is that you can find WSDL in the test page. Then, you can find XSD file in WSDL document.


Once we successfully see the test page, we can move to next step to create an Web service client to test our Web service. If you can not successfully see the test page. I do not know why. But, I can suggest you to uninstall the netbeans and reinstall the latest netbeans. I am using Netbeans 6.9.1. You can try to reinstall netbeans even you think your netbeans has same version as mime.

Creating a simple Web Service client with Metro toolkit is simple too.

1) In netbeans, we create a new standalone java project.

2) right click the new created project and select New --> Web Service Client... . Then, we will see a screen as below,

3) After we input the correct WSDL URL and click Finish, the netbeans will generate lots of stuff for us, including the stub classes for calling jiaMetroWS, which is still running on our local machine now.

4) writing our own simple code to call jiaMetroWS through generated Web service stub classes. The code is as below,

MetroClientTest.java
package jia.blog.ws.client;

import java.util.Iterator;
import java.util.List;

/**
 *
 * @author Yiyu Jia
 */
public class MetroClientTest {

    public static void main(String[] args){
    jia.blog.ws.client.JiaBlogWSService service = new jia.blog.ws.client.JiaBlogWSService();
    jia.blog.ws.client.JiaBlogWS port = service.getJiaBlogWSPort();

    String customId = "100";
    //below invoice should be Invoice 
    List invs = port.callSP(customId);
    //below invoice should be Invoice 
    Iterator it = invs.iterator();

    while( it.hasNext()){
        Invoice inv = it.next();
        System.out.print("Invoice number: "+inv.invoiceNum + " Name: "+inv.getName());
        for(int i=0; i < inv.getItems().size(); i++){
               System.out.println(" item" + i +": "+inv.getItems().get(i).itemNum);
         }
    }
  }
}

The netbeans projects can be downloaded here: jiaMetroWS.zip and jiaMetroWSClient.zip .

Sunday, February 6, 2011

How to host multiple instances of Sync4J server on one machine

There was one guy told me that he wanted to install multiple instances of sync4j in one Tomcat instance. He hoped that he can increase the performance of synchronization in this way. To increase performance of software, there are many aspects to work on. From the system architecture aspect, we can improve hardware system in vertical way and horizon way. I do not know if he go multi-CPU server and he can achieve better performance by increase number of instances on sync4j. It will be a big topic to discuss. Here, what I want to discuss is that it is impossible to install two sync4j server inside one Tomcat instance. The reasons are,

  1. Sync4j server uses the server.uri in Sync4j.properties as part of its authentication logic when it processing the syncMessage.
  2. Sync4j finds the path of configuration files based on a system properties called "SYNC4J_HOME". This is not a good design because this configuration property will be used JVM wide. Sync4j server, running in Tomcat, is a servlet. So, two sync4j instances will have to share same sync4j.properties. Therefore, I think Funambol should put all configuration related information under a Web App context only. But, they put the "SYNC4J_HOME" as a system property, which is JVM wide.


Based on the above two factors, I suggested him to install multiple tomcat and link each tomcat to a virtual host under Apache. But, please notice the second factor mentioned above, we will not run multiple tomcat instances on ONE virtual machine. So, we need run multiple binary copies of Tomcat. Then, we can set different Sync4j_Home for different Sync4j servers inside different Tomcat instance (different binary instance of Tomcat).

This installation configuration may cause challenge for sync module developers as they have to consider about plan of database instances. Will different sync4j module instances, having identical code base , share one database or different databases? Obviously, earlier designer think about this questions, better result they will have.

Note: the above analysis is based on sync4j server version 2.3 only. 

Friday, February 4, 2011

limitation of Sync4J to support sync from multiple subnet through proxy

I happened to had a look at AGPL again recently. AGPL is created to prevent people to host a modified open source project. Therefore, developer can not modify the software under AGPL project and deploy it on his own server as ASP. According to Funambol's site, it is said that user is not allowed to modify its source code even if the modification will be open source. I do not know if I understand it in correct way or not. As a programmer, I understood that open source projects need fund support to keep it to be alive.

But, this AGPL topic made me to recall one issue, i ran into when I worked on sync4j (old name of funambol). To describe the issue clearly, I made the following diagram,


As you can see, terminal one and terminal two sync with sync4j server from different sub net and through proxies respectively. Also, because DNS server in different sub net give the sync4j server different host name, terminal one and terminal two will sync to different host names, which are belong to one same physical server. In this case, the sync4j server can receive the sync request. However, it will refuse to process it. Why? Because sync4j use serverUri as part of its authentication protocol. Sync4j will load serverURI from its sync4j.properties configuration file and compare it with localURI from sync client in syncML. Therefore, sync4j server failure on processing the sync message as the serverUri from client side does not match the serverURI from sync4j.properties file.

We can see relevant code from sync4j client native code. In file SyncMLProcessor.cpp, around line 241, we can see some code like this,

uri = getElementContentSaveMem(target, TEXT("LocURI"), NULL, &startPos, &endPos);
        if ((uri == NULL) || (wcsncmp(uri, source.getName(NULL, 0), endPos - startPos) != 0)) {
            //
            // This Sync is for another source
            //
            target  = NULL;
            uri     = NULL;
            continue;
        }


However, it is not difficult to walk around this by modifying its SyncSessionHandler.java. But, this will broke Funambol's AGPL license. Fortunately, in sync4j, many things are configurable. Developer can actually develop their own syncSessionHandler class and registered it into sync4j server.

The above analysis only apply to sync4jServer version 2.3. This post is only based on what I can recall. Probably, it has been changed in new version of Funambol server. I do not have time to check it yet. But, you can pay attention on this unique sync server name requirement from sync4j server if you plan to sync through multiple subnet connected with multiple routers attached to different DNS servers' configurations. Also, BTW, the native sync client API library from Funambol does not support sync through proxy and proxy authentication. When I worked on it, I have to add my own code to support sync through proxy with proxy authentication. But, I am not sure if they have added features to support this in their new release. It will be interesting to have a look at it later.