Tremend Tech Blog

"Software is a great combination between artistry and engineering. When you finally get done and get to appreciate what you have done it is like a part of yourself that you've put together." (Bill Gates)

Looking for software experts?

Need an expert advice on software development? Need consulting work done in time and at high standards? Tremend has the right solution for you.

We can provide expertise in:
  • high traffic and complex content website infrastructures
  • website development-advanced web programming with PHP, .NET, Java, Flash/Flex, Ajax

Our friends

File not found: transaction …, path …. SVN mysteries behind an Apache Reverse Proxy

December 6th, 2009 by Bogdan Nitulescu

We have an SVN server somewhere on our intranet, but since outside people want to access it, I put it behind an Apache reverse proxy. It was fairly straightforward. Here’s an excellent tutorial if you want to know how to do it: http://silmor.de/49 .

Basically, you have the intranet apache that’s configured to serve SVN, and you have an outside apache in your firewall’s DMZ that proxies the request:

ProxyPass /svn/ http://intranet.example.com/svn/
ProxyPassReverse
/svn/ http://intranet.example.com/svn/

It was all fine when people checked out their sources, but there were strange errors during commits. 7 files commits worked ok. When you tried 8 files or more, you got something like…

File not found: transaction ‘431-12′, path ‘/parser/XMLparser/XMLparser.sln’

It took a lot of sweat to find out why 8 was the magic number - and after a lot of packet dumps and tracing, I found out that one of the servers used HTTP keepalives, and the other one rejected them.

So here’s a couple of rules not to be broken when proxying SVN requests:

Keep the same paths. Do not try something like ProxyPass /svn/ http://intranet.example.com/my_svn/ . It will fail with a cryptic error message at the worst of time.

Keep the same configuration.  Check your /etc/httpd/conf/httpd.conf on both servers for differences in your configuration. In my case, I had “KeepAlives On” in one server and “KeepAlives Off” in the other. When I put them both to On, it worked just fine.

Share/Save

Posted in General, Tools | No Comments »

How to move Drupal to a subdirectory and keep the links

October 20th, 2009 by Bogdan Nitulescu

The usual way for Drupal is to have it live in the root of your web site. It’s all nice if the only thing on your site is Drupal, but it gets very cluttered when you have other top-level directories.

One customer had his corporate site at, say, “www.example.com“, and his customer support pages at “www.example.com/support“.  We wanted to keep the application in the “support” directory, move all the drupal directories under “corporate“. And keep the old links working.

First we had to let Drupal know that, even if it’s been relocated to “corporate”, the URL still remains the same. Do it in “corporate/sites/default/settings.php“:

$base_url = 'http://www.example.com';

Then tell Apache that Drupal has moved. Put these rewrite rules in .htaccess in the root of your web site.

  RewriteEngine on
 
  # Rewrite www.example.com to the Drupal home page: www.example.com/corporate/index.php
  RewriteRule ^$ corporate/index.php [L]
  # Let Drupal process paths like www.example.com/corporate/about
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteRule ^corporate/(.*)$ corporate/index.php?q=$1 [L,QSA]
 
  # Search for real Drupal files that moved, 
  #  (e.g. www.example.com/flash/intro.swf to www.example.com/corporate/flash/intro.swf)
  RewriteCond %{DOCUMENT_ROOT}/corporate/$1 -f
  RewriteRule ^(.*)$ corporate/$1 [L]
 
  # Let Drupal process all paths that are not real files and directories, like www.example.com/about
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteCond %{REQUEST_URI} !=/favicon.ico
  RewriteRule ^(.*)$ corporate/index.php?q=$1 [L,QSA]
 
  # What's left are real non-Drupal pages and directories, like www.example.com/support

Share/Save

Posted in Drupal | No Comments »

Xaraya to Drupal Migration Script

September 11th, 2009 by Julia Biro

Using some features from the following script(http://drupal.org/node/105308) I managed to port
a Xaraya 1.4 to Drupal 6.13.

It does the following:

  • import of users
  • import of articles and comments
  • import of forums and comments
  • import of content types
  • import of vocabularies and terms
  • import of files

The first thing I’ve done was to eliminate the sequences table, which is deprecated starting from Drupal version 4.

Managing categories:
I’ve used the xaraya categories with parent id equal to 0 as Content Types and Vocabularies
and inserted all the other as terms associated with the vocabulary.

The term hierachy is created by running a script on the term_hierarchy table
setting parent_id 0 for the first child and the original parent_id for the next ones.

Managing files and images:
Inserting them into the ‘files’ table is not enought, the FileField
and ImageField modules installation is mandatory in order to associate an field with an node.(this part is not implemented)

In order to mentain the relationships safe I had to use the original id’s in all tables .

Click here to download the script

Share/Save

Posted in Drupal | No Comments »

Windows cannot find “url”

September 9th, 2009 by Marius Hanganu

If you’ve encountered this message: “Windows cannot find url” when clicking links in external applications (like for example Yahoo Messenger, Adobe Acrobat, etc), here’s the solution as stated here:

1. Open Explorer
2. Select Tools and then Folder Options
3. Select the File Types tab
4. Select Extension: (NONE), File Type: HyperText Transfer Protocol
5. Click Advanced toward the bottom of the window
6. In the Edit File Type window, select open and click Edit
7. Clear the DDE message box (which should contain “%1″)
8. Click OK, Click OK
9. Repeat for File Type: HyperText Transfer Protocol with Privacy

Share/Save

Posted in General | No Comments »

Software consulting services from Tremend

April 6th, 2009 by Ioan Cocan

Need an expert advice regarding software development? Need consulting work done in time and at high standards? Tremend has the right solution for you.

We can provide expertise in:
- high traffic and complex content website infrastructures
- website development-advanced web programming with PHP, .NET, Java, Flash/Flex, Ajax

Custom programming in the following areas:
- expert level Content Management Systems using PHP and Drupal
- Flash and Flex custom development
- low level C/C++ programming for devices
- scalable Java infrastructures using Spring Framework, Hibernate, Tomcat
- expert Javascript development using frameworks like Dojo, ExtJS, jQuery, Prototype
- Bluetooth programming (Unix/Windows)

You can reach us at contact at tremend.ro.

Share/Save

Posted in business | No Comments »

Springy: org aspectj weaver reflect ReflectionWorld ReflectionWorldException: warning can’t determine implemented interfaces of missing type

March 30th, 2009 by Marius Hanganu

Here’s a quick one: if you’ve encountered the following error

1
2
3
4
5
org.springframework.beans.factory.BeanCreationException: Error creating bean with name '...': Initialization of bean failed; nested exception is org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException: warning can't determine implemented interfaces of missing type ...
 [Xlint:cantFindType]
Caused by: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException: warning can't determine implemented interfaces of missing type ro.tremend.bigg.web.tile.currencyCustomTileRenderer2
 [Xlint:cantFindType]
	at org.aspectj.weaver.reflect.ReflectionWorld$ExceptionBasedMessageHandler.handleMessage(ReflectionWorld.java:163)

And didn’t figure out yet what was the problem, you may want to check your spring version. This error happens in 2.0.2  but it seems it was fixed since 2.0.5.

More here

Share/Save

Posted in Java, General, Spring | No Comments »

FLEX - live scroll datagrid

March 2nd, 2009 by alinca

A nice feature on search engines would be a live scroll, so right before you get to the end of the current page the next page with results is loaded automatically and you won’t have to click next, this can be done using ajax, flex, flash…

I will tell you how it can be done with adobe flex sdk.

First you need a mx.rpc.http.HTTPService to map the search service to. For the service I created a simple php page that returns some random list of data and mapped my HTTPService to it.

I create list of type ArrayCollection to hold the search results, and a DataGrid component with the list binded as dataProvider.

When the application starts the HTTPService send a first request for data and when getting the result will parse it and add the data to the ArrayCollection which is binded to the DataGrid, so the results will show up in the DataGrid

For now our application only loads the first page of results so we need to load the next page each time the user gets to the end of the results, so we add an event listener for the DataGrid scroll event. On this listener we check if the user scrolled down using the ScrollEvent direction and delta properties, if so we check if the user is close to the end (there are 3 more results to show) then we send a new request to the search service for next page o data.

Here you can checkout the example. (right-click on the flash to view the source code).

One problem that I was not able to solve was that when loading the first page with data the maxVerticalScrollPosition of the DataGrid was not updated, I was using this in the status label from the bottom to show the index of data show in the DataGrid; maxVerticalScrollPosition was only updated when making the first scroll. For the status label I used a hack that you can check in the code.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute"
	creationComplete="creationCompleteImpl()"
	width="400"
	height="500"
 viewSourceURL="srcview/index.html">
	<mx:Script>
		<![CDATA[
			import mx.events.ScrollEventDirection;
			import mx.events.ScrollEvent;
			import mx.controls.Alert;
			import mx.rpc.http.HTTPService;
			import mx.rpc.events.FaultEvent;
			import mx.rpc.events.ResultEvent;
			import mx.collections.ArrayCollection;
 
			[Embed(source="assets/loading.swf")]
			private var loadingAnimation:Class;
 
			//keep a request count not to make new request until last request data is received
			private var loadRequests:int = 0;
 
			[Bindable]
			private var list:ArrayCollection = new ArrayCollection();
			//http service from where you get random data
			private var httpService:HTTPService = new HTTPService();
			/**
			 * after load complete add event listeners for httpService and make a first call 
			 */
			private function creationCompleteImpl():void
			{
				//add an event listener for the httpService events
				httpService.url = parameters.serviceUrl;
				httpService.addEventListener(ResultEvent.RESULT, httpServiceEvent);
				httpService.addEventListener(FaultEvent.FAULT, httpServiceEvent);
				getNewData();
			}
			/**
			 * httpService event handler 
			 */
			private function httpServiceEvent(event:Event):void
			{
				if(event is ResultEvent)//if we get a result from the httpService
				{
					//parse the result and add the values to the datagrid
					//on a request the test php returns 50 random values
					var result:String = (event as ResultEvent).result as String;
					var values:Array = result.split("\n");
					for each(var value:String in values)
					{
						if(value.length > 0)
						{
							var props:Array = value.split(/(\d+)/);
							list.addItem({text:props[0], number:props[1]});
						}
					}
				}
				else
				{
					//show an alert if error
					Alert.show((event as FaultEvent).message.toString());
				}
				loadRequests--;
				if(loadRequests == 0)
				{
					loadingImage.visible = false;
				}
			}
			/**
			 * call the php service 
			 */
			private function getNewData():void
			{
				if(loadRequests == 0)
				{
					httpService.send();
					loadingImage.visible = true;
					loadRequests++;
				}
			}
			/**
			 * event handler for datagrid scrolling 
			 */
			private function listScrolled(event:ScrollEvent):void
			{
				if(event.direction == ScrollEventDirection.VERTICAL && event.delta > 0)
				{
					//if close to last item make a new call to get new results
					if(liveDataGrid.maxVerticalScrollPosition - event.position < 3)
					{
						getNewData();
					}
				}
			}
		]]>
	</mx:Script>
	<mx:VBox paddingTop="10" paddingBottom="10" paddingLeft="10" paddingRight="10"
		horizontalAlign="center" 
		width="100%" height="100%">
		<mx:Canvas width="100%">
			<mx:Label text="Live scroll" left="0" verticalCenter="0"/>
			<mx:Image id="loadingImage" source="{loadingAnimation}" right="0" verticalCenter="0" visible="false"/>
		</mx:Canvas>
		<mx:DataGrid id="liveDataGrid" height="100%" width="100%"
			scroll="listScrolled(event)"
			dataProvider="{list}"
			>
			<mx:columns>
		        <mx:DataGridColumn dataField="text" headerText="Text"/>
		        <mx:DataGridColumn dataField="number" headerText="Random value"/>
		    </mx:columns>
		</mx:DataGrid>
		<mx:Label
			visible="{list.length > 0}" 
			text="{'Showing ' + (liveDataGrid.verticalScrollPosition + 1) + ' to ' + (liveDataGrid.verticalScrollPosition + Math.round((liveDataGrid.height - liveDataGrid.headerHeight) / liveDataGrid.rowHeight) - 1)}" width="100%"/>
	</mx:VBox>
</mx:Application>

Share/Save

Posted in Flex | No Comments »

Dynamically create Spring beans from groovy scripts at runtime

February 24th, 2009 by Marius Hanganu

Groovy

In the current project - a java based CMS - we were faced with an interesting problem: how can we dynamically create renderers to power our blocks in the html page (currently all renderers are Java classes and Spring beans also described in the application context files).

Imagine the power of this approach. Especially when Java deployments can be quite a hassle in a multi server environment (deploying sources on the linux machines, wait for a good moment for starting/stopping the servers - which may or may not perform a sensitive operation at that time, synchronize the restart of the web servers, check log files for any errors, etc).

What could be better than having your Spring beans dinamically created from the administration panel? No server restarts, no deployments. Just keep your Groovy scripts in the database and make any modification realtime.

Achieving the programatic creation of Spring beans from groovy scripts can be done in four steps:

1. load the groovy script and parse it into a java Class
2. create a bean definition using the previously loaded class
3. inject any other beans into your bean definition
4. register the bean definition and get a handle on the bean created

Of course, you cannot declare variables as instances of the Java class defined in the groovy script. Or you may do it programatically through reflection. But it is much simpler (if the project suits these needs) to have a base interface for all your dynamic beans and after those 4 steps, simply cast the bean created to the Java interface. So you might add two more steps to the previous four:

0. declare a base interface for your all your classes declared in groovy scripts
5. cast the created bean to the base interface so that you can use it in your code

The code is actually pretty simple. But you can hardly find any article/post on the subject. Most of them discuss an older version of Spring (1.x), while my code had to work with Spring 2.0.x - which is completely different in terms of the API calls needed to create a bean.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
public class GroovyTemplateEngineImpl extends DefaultListableBeanFactory implements ApplicationContextAware {
    public BaseInterface createOrUpdateBean(String rendererName, String code) throws Exception, ClassNotFoundException {
 
        // 1. load the groovy script and parse it into a class
        GroovyClassLoader gcl = new GroovyClassLoader(getClassLoader());
        Class clazz = gcl.parseClass(groovyScriptAsAString);
 
        // 2. create the bean definition
        AbstractBeanDefinition beanDef = BeanDefinitionReaderUtils.createBeanDefinition( "parentBean", packageName + "." + className, gcl);
 
        // 3. inject here any attributes that would normally be passed using spring XML configuration files
        beanDef.setAttribute("attr1", bean1);
        DefaultListableBeanFactory factory = (DefaultListableBeanFactory) appCtx.getAutowireCapableBeanFactory();
 
        // 4. Create the bean - I'm using the class name as the bean name
        factory.registerBeanDefinition(className, beanDef);
        Object bean = factory.createBean(clazz, AUTOWIRE_BY_NAME, false);
 
        // 5. further on you can cast it to any interface
        return (BaseInterface) bean;
    }
}

You will also need to add to the previous class a setter for application context to be injected (the class needs to implement ApplicationContextAware).

Please note that this code only works from spring version 2.0.3 and up. If you’re using a lower version, you’ll likely encounter this exception:

1
2
3
Caused by: org.aspectj.weaver.reflect.ReflectionWorld$ReflectionWorldException: 
warning can't determine implemented interfaces of missing type .... 
[Xlint:cantFindType]

Good luck groovying!

Share/Save

Posted in Java, General | No Comments »

Getting updated Bluetooth discovery names from nearby devices

November 24th, 2008 by lstroie

I’ve needed to see updated information related to nearby Bluetooth devices.

When using < hcitool scan > command, the output is not updated on every run, and even when used with the –flush option, the obtained results did not reflect the reality because the data is cached.

The solution seems to be < hcitool scan –flush –info > . This forces a detailed inquiry that is not cached.

One minor disadvantage would be the bigger amount unuseful data obtained, if we are looking only for the Bluetooth discovery name.

Share/Save

Posted in linux | No Comments »

Codepress extension - syntax highlighting for Velocity

November 19th, 2008 by Marius Hanganu

For the impacients, here’s a link on how Velocity syntax highlighting can be done in a browser.

Codepress is an excellent script for syntax highlighting when editing code using the browser. We needed some syntax highlighting for one of the projects at Tremend which included some Velocity code. So after some hacking I came out with a set of regular expressions which should match almost all instructions for a Velocity template.

Of course, the well known problem of matching paranthesis is not solved, so the expressions work only up to three levels of embedded paranthesis, which should be enough for most projects. If more levels of embedded paranthesis are needed, more expressions can be defined.

Here’s how the editor looks like

Velocity in Codepress

Also, velocity is always used in conjunction with other language. Whether it’s about generating HTML, XML or any other piece of text, Velocity is a template engine.

The rules defined in velocity.js are comprising also HTML and JavaScript rules, since the code we’re generating is HTML + JavaScript.

Share/Save

Posted in HTML, Javascript | No Comments »

Where in the /dev is the card reader?

November 3rd, 2008 by Bogdan Nitulescu

I’ve plugged a card reader in a USB socket on my Linux box and it’s not that trivial to know if it’s on /dev/sda or /dev/sdb or elsewhere. That can be even dangerous - I know someone who just erased his hard drive, trying to reformat a card. (Yes, he used a script that assumed the card reader is /dev/sda… and it worked so well on his old machine).

Here’s a method to find it out.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
$ cat /proc/scsi/scsi
Attached devices:
Host: scsi0 Channel: 00 Id: 00 Lun: 00
Vendor: ASUS     Model: DVD-E616A        Rev: 1.08
Type:   CD-ROM                           ANSI  SCSI revision: 05
Host: scsi2 Channel: 00 Id: 00 Lun: 00
Vendor: ATA      Model: WDC WD2500KS-00M Rev: 02.0
Type:   Direct-Access                    ANSI  SCSI revision: 05
Host: scsi4 Channel: 00 Id: 00 Lun: 00
Vendor: GENERIC  Model: USB Storage-CFC  Rev: I19B
Type:   Direct-Access                    ANSI  SCSI revision: 00
Host: scsi4 Channel: 00 Id: 00 Lun: 01
Vendor: GENERIC  Model: USB Storage-MSC  Rev: I19B
Type:   Direct-Access                    ANSI  SCSI revision: 00
Host: scsi4 Channel: 00 Id: 00 Lun: 02
Vendor: GENERIC  Model: USB Storage-SMC  Rev: I19B
Type:   Direct-Access                    ANSI  SCSI revision: 00
Host: scsi4 Channel: 00 Id: 00 Lun: 03
Vendor: GENERIC  Model: USB Storage-SDC  Rev: I19B
Type:   Direct-Access                    ANSI  SCSI revision: 00

So here they are - the DVD-ROM, the hard drive, and readers for various types of cards. I’m interested in the SD card reader, so that would be the device identified by “scsi4 Channel: 00 Id: 00 Lun: 03″ - that’s 4:0:0:3 .
The second piece of magic

1
2
$ ls -l /sys/bus/scsi/drivers/sd/4:0:0:3/block*
lrwxrwxrwx 1 root root 0 2008-11-03 15:03 /sys/bus/scsi/drivers/sd/4:0:0:3/block:sde -&gt; ../../../../../../../../../block/sde

So the SD card I’ve just plugged is in /dev/sde .

Share/Save

Posted in linux | No Comments »

Escaping in Bash: how to handle multiple file names containing spaces

October 6th, 2008 by Bogdan Nitulescu

Did you ever saved file names in a bash parameter, and everything crashed down when they contain spaces?

The script started simple:

1
2
3
FILENAMES="log-file-1.txt log-file-2.txt"
cp $FILENAMES logs
rm $FILENAMES

When you have spaces, it becomes a nightmare. You’ll probably add a lot of quotes and try first something like this:

1
2
3
FILENAMES='"log file 1.txt" "log file 2.txt"'
cp $FILENAME logs
rm $FILENAME

Don’t try it at home, it does not work. Bash applies its dreadfully complex parameter expansion rules and you will end up useless errors about things called “log”, “file” and “1.txt” which cannot be found.

Solution: use arrays:

1
2
3
4
5
6
FILENAMES=(
"log file 1.txt"
"log file 2.txt"
)
cp "${FILENAMES[@]}" logs
rm "${FILENAMES[@]}"

They work only on bash. Here’s a page about how they work.

Share/Save

Posted in linux | No Comments »

Create directories in C using mkdir with proper permissions

October 6th, 2008 by Bogdan Nitulescu

I just wrote a C application where I had to create a directory and let everyone read and write it.  That should be plain easy:

1
int result_code = mkdir("/usr/local/logs", S_IRWXU | S_IRWXG | S_IRWXO)

Apparently it’s a bit more complex, and I made a beginner’s error. I did forgot about the UMASK (http://www.tech-faq.com/umask.shtml).

Briefly: When you create a new file or directory, some of its permissions are restricted and cannot be set. Each process has a set of restrictions called the umask, and you must use the umask system call to disable or enable those restrictions. In my case, I set the umask to 0, that is no restrictions, created the directory, then restored the umask to its previous value:

1
2
3
mode_t process_mask = umask(0);
int result_code = mkdir("/usr/local/logs", S_IRWXU | S_IRWXG | S_IRWXO)
umask(process_mask);

The code above is not reentrant and it gets a bit more complex if your program is multithreaded, but you get the idea.

Share/Save

Posted in linux | 1 Comment »

Link flash to html page

October 3rd, 2008 by Marius Hanganu

This is a small one, but I banged my head several times now before fixing it. Although many have written about it, I decided to write also. More resources are always better than fewer resources :-)

So you’ve created the flash object, correctly set the URL, but when embedding it on the web page on your web server, the link doesn’t work. The solution is quite simple: you need to set allowScriptAccess to sameDomain or even always if sameDomain doesn’t do the job.

And of course, you need to do that for both the object and the embedtag. For example:

1
2
3
4
5
6
7
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0" width="295" height="240">
    <param name="allowScriptAccess" value="always" />
    <param name="allowFullScreen" value="false" />
    <param name="movie" value="http://server/flash.swf">
    <param name="quality" value="high">
    <embed src="http://server/flash.swf" quality="high" allowScriptAccess="always" allowFullScreen="false"  pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash" width="295" height="240"></embed>
</object>

Using this parameter, the flash object will now allow linking to the HTML page set in the flash object.

Blogged with Flock

Tags: , , ,

Share/Save

Posted in General, HTML, Javascript | No Comments »

Google Talk in Yahoo Messenger

September 23rd, 2008 by Marius Hanganu

Some time ago, when I first saw the Google Talk gadget is being released, I got this crazy idea of embedding the gadget in Yahoo Messenger as a plugin.

Once logged in, the gadget was displayed just fine as a plugin, but if the user was not logged in, he’d be taken to the google login page. So I started hacking and chopping and after half hour I finally got this version working. Click here to download the plugin.

After downloading it, unzip it into the C:\Program Files\Yahoo!\Messenger\Plugin\Test\ContentTab\ folder. UPDATE: after unzipping, rename the folder to test.plugin (thanks Tudor) The final path should look like: C:\Program Files\Yahoo!\Messenger\Plugin\Test\ContentTab\test.yplugin\.

Restart Yahoo Messenger, log-in and select Actions -> Load Test Plug-in, and the Google login page will show up in the plug-ins area. You can select the “remember me” box, so that after restart you will be automatically logged in.

The plugin is quite simple: it contains one simple HTML file with some Google styles, and the HTML code for the login page. On page load - a request is made to http://www.google.com/ig to check if the user is already logged in. This is achieved by parsing the response and checking for “Sign out” string - which means the user is logged in.

Surprisingly, from all the Google pages, the http://www.google.com/ig page was the only one (after 4 or 5 unsuccessful attempts) that could give me an indicator on whether the user is logged in or not.

In case user is logged in, the page is redirected to the URL containing the embeddable flash gadget for Google Talk: http://talkgadget.google.com/talkgadget/popout.

Unfortunately, the administrators of Yahoo Messenger plug-ins at http://gallery.yahoo.com/messenger have rejected the application so far, so in order to use it, every time you start Yahoo Messenger, you need to select “Load Test Plug-in” to load this plugin.

Here are some images with the plugin:
Google Talk in Yahoo Messenger

Google Talk in Yahoo Messenger
And here’s the code for the plugin:

    <!--
<!–
        body,td,div,p,a,font,span {font-family: arial,sans-serif;}
        body {margin-top:2}.c {width:4; height: 4}
        body { background-color:#E8EEFA; }
        A:link {color:#0000cc; }
        A:visited { color:#551a8b; }
        A:active { color:#ff0000; }
        .form-noindent {background-color: #ffffff; border: #C3D9FF 1px solid}
        .gaia.le.lbl { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
        .gaia.le.fpwd { font-family: Arial, Helvetica, sans-serif; font-size: 70%; }
        .gaia.le.chusr { font-family: Arial, Helvetica, sans-serif; font-size: 70%; }
        .gaia.le.val { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
        .gaia.le.button { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
        .gaia.le.rem { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
        .gaia.captchahtml.desc { font-family: arial, sans-serif; font-size: smaller; }
        .gaia.captchahtml.cmt { font-family: arial, sans-serif; font-size: smaller; font-style: italic; }
        .body { margin-left: 3em;margin-right: 5em;font-family: arial,sans-serif; }
        div.errorbox-good {}
        div.errorbox-bad {}
        div.errormsg { color: red; font-size: smaller; font-family: arial,sans-serif;}
        font.errormsg { color: red; font-size: smaller; font-family: arial,sans-serif;}
        hr {border: 0;background-color:#DDDDDD;height: 1px;width: 100%;text-align: left;margin: 5px;}
         div.errormsg { color: red; font-size: smaller; font-family:arial,sans-serif; }
         font.errormsg { color: red; font-size: smaller; font-family:arial,sans-serif; }
        .gaia.le.lbl { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
        .gaia.le.fpwd { font-family: Arial, Helvetica, sans-serif; font-size: 70%; }
        .gaia.le.chusr { font-family: Arial, Helvetica, sans-serif; font-size: 70%; }
        .gaia.le.val { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
        .gaia.le.button { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
        .gaia.le.rem { font-family: Arial, Helvetica, sans-serif; font-size: smaller; }
        .gaia.captchahtml.desc { font-family: arial, sans-serif; font-size: smaller; }
        .gaia.captchahtml.cmt { font-family: arial, sans-serif; font-size: smaller; font-style: italic; }
    –>
-->
    <script type="text/javascript"><!--mce:0--></script>
<form id="gaia_loginform" action="https://www.google.com/accounts/ServiceLoginAuth" method="post">
<div class="loginBox">
<table id="gaia_table" style="display:none" border="0" cellspacing="0" align="center">
<tbody>
<tr>
<td colspan="2">
                        <span>
                                    <img src="https://www.google.com/accounts/google_transparent.gif" alt="Google" />
                                </span></td>
<td valign="middle">
                                    <span>
                    </span></td>
</tr>
<tr>
<td>
<div>
                            <span class="gaia le lbl">Email:</span></div></td>
<td>
<input id="continue" name="continue" type="hidden" value="http://talkgadget.google.com/talkgadget/popout" />
<input id="service" name="service" type="hidden" value="talk" />
<input id="skipvpage" name="skipvpage" type="hidden" value="true" />
<input name="GALX" type="hidden" value="aa3Jml3aMHk" />
<input id="Email" class="’gaia" name="Email" size="18" type="text" /></td>
</tr>
<tr>
<td></td>
<td align="left"></td>
</tr>
<tr>
<td align="right">
                        <span class="gaia le lbl"> Password: </span></td>
<td>
<input id="Passwd" name="Passwd" size="18" type="password" /></td>
</tr>
<tr>
<td></td>
<td align="left"></td>
</tr>
<tr>
<td align="right" valign="top">
<input id="PersistentCookie" checked="’checked’/" name="PersistentCookie" type="checkbox" value="yes" />
<input name="’rmShown’" type="hidden" value="1?/&gt;
                    &lt;/td&gt;
&lt;td&gt;
                        &lt;span class=" />Remember me on this computer.</td>
</tr>
<tr>
<td></td>
<td align="left">
<input class="gaia le button" name="signIn" type="submit" value="Sign in" /></td>
</tr>
</tbody></table>
</div>
</form>

Share/Save

Posted in General, HTML, Javascript, Tools | No Comments »

« Previous Entries