how to

You are currently browsing articles tagged how to.

Me and Sandaruwan wanted to create a Facebook app, so just to learn the process I spent an hour or two to create a simple “Hello World” like app. I wanted to share the experience (a walk through / tutorial). It was pretty easy with the example code Facebook provides, and their developer forum.

Here is the link to my Hello World app http://apps.facebook.com/xvpj_hello/. You can download the source code here.

First install get the developer app: http://www.facebook.com/developers/. Then you can create a new application by clicking Set Up New Application.

Then under My Applications you can see a link to view example code.

Clicking it will show you an example index.php (which we are going to use) and a link to download the Facebook Platform PHP library. Download it and extract the folder php in the archive in your server (you need to host this app somewhere – you cannot test it on localhost).

I extracted it on www-root/fb/; i.e. an ls should look like

Note that index.php and invite.php are added later (it’s our code :) )

Then you need to goto Edit Settings in My Applications window

There under Canvas set the Canvas Callback URL to where you hosted the app. In my case it is http://xvpj.net/fb/. (note the ‘/‘ at the end, this is required otherwise there’ll be an error when navigating to the invite page). Also I set the render method to FBML.

Now to the good part, time to code :) . Here’s what my index.php looks like. Note that the link to invite.php includes a parameter invite. This is a small trick so that when user skips sending invitations, there is no parameter invite and the page is redirected back to index.php.

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
<?php
 
require_once 'facebook.php';
 
$appapikey = 'API_KEY';
$appsecret = 'SECRET';
 
$facebook = new Facebook($appapikey, $appsecret);
$facebook->require_frame();
$user_id = $facebook->require_login();
 
/* Greeting */
echo "<p>Hello, <fb:name uid=\"$user_id\" useyou=\"false\" />!</p>";
 
/* Get the list of friends */
$friends = $facebook->api_client->friends_get();
 
/* A link ot invite friends to the application */
echo "<p><a href=\"invite.php?invite\">Invite Friends</a></p>";
 
/* Printing out the friend list */
echo "<h2>Your friends</h2>";
 
foreach ($friends as $friend) {
  echo "<p><fb:name uid=\"$friend\" /></p>";
}

This is the invitation page I used (invite.php)

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
<?php
require_once 'facebook.php';
 
$appapikey = 'API_KEY';
$appsecret = 'SECRET';
 
$facebook = new Facebook($appapikey, $appsecret);
$facebook->require_frame();
$user_id = $facebook->require_login();
 
/* If invitations were sent */
if(isset($_POST["ids"])) {
?>
<center>
  Thank you for inviting <? echo sizeof($_POST["ids"]); ?> of your friends to <b><a href="http://apps.facebook.com/xvpj_hello/">Hello World</a></b>.
</center>
<br /><br />
<?php
}
/* If invite page is to be displayed */
else if(isset($_GET["invite"])) {
  /* A facebook query to select the friends of the current user who use the application */
  $fql = 'SELECT uid FROM user WHERE uid IN (SELECT uid2 FROM friend WHERE uid1='.$user_id.') AND is_app_user = 1';
 
  /* Execute the query */
  $_friends = $facebook->api_client->fql_query($fql);
 
  /* Get the user ids */
  $friends = array();
  if (is_array($_friends) && count($_friends)) {
    foreach ($_friends as $friend) {
      $friends[] = $friend['uid'];
    }
  }
 
  /* Convert the array of friends into a comma-delimeted string. */
  $friends = implode(',', $friends);
 
  /* Prepare the invitation text that all invited users will receive. */
  $content = "<fb:name uid=\"".$user_id."\" /> has invited you to use <a href=\"http://apps.facebook.com/xvpj_hello/\">Hello World</a>!\n";
  $content .= "<fb:req-choice url=\"".$facebook->get_add_url()."\" label=\"Add Hello World to your profile\"/>";
 
  /* This creates the form to select and invite friends.
   * The multi-friend-selector lets you search and select friends */
?>
  <fb:request-form action="invite.php" method="post" type="Hello World" content="<? echo htmlentities($content); ?>">
    <fb:multi-friend-selector actiontext="These poor lads still don't use this great app. Invite em all ;)" exclude_ids="<? echo $friends; ?>" />
  </fb:request-form>
<?
}
/* If sending invitations was skipped */
else {
?>
<fb:redirect url="http://apps.facebook.com/xvpj_hello/" />
<?
}
?>

Note: substitute API_KEY and SECRET

Tags: , , ,

You can check the quality and speed of your internet connection with speed.io. Here’s what I got; overall quality: less good :( .

Tags:

Are you fed up with skipping the disk check at boot because it takes too long?

To cancel the disk check on Drive C:, just go to the command prompt and type

Chkntfs /x d:

To reset it

Chkntfs /c d:

Tags: , ,

Since it took me so long to find the wall of a huge messy profile of a friend when I wanted to say Happy Birthday, I was thinking of doing it by a simple HTTP POST.

First you need to gather following information

  1. Your post_form_id
  2. Your profile id
  3. Your friend’s profile id

That’s all you need, and you must be logged in to your facebook account (doesn’t matter if you have checked remember me).

Then type in the following html code and save it as a .htm file and double click on it. That’s it your message will be on your friends wall :) .

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<html>
 <body>
  <form id="fb_wall" name="fb_wall" method="post"
   action="http://www.facebook.com/wallpost.php?id=[YOUR FRIEND'S ID]">
 
   <input type="text" id="to" name="to" value="[YOUR FRIEND'S ID]" />
   <input type="text" id="wall_text" name="wall_text"
          value="Happy Birthday" />
   <input type="text" id="from" name="from" value="[YOUR ID]" />
 
   <input type="text" id="post_form_id" name="post_form_id"
          value="[YOUR post_form_id]" />
 
   <input type="submit" />
  </form>
  <script language="JavaScript">document.fb_wall.submit();</script>
 </body>
</html>

Ok, so how do we find the post_form_id and the two profile id’s. To find the post_form_id you need to go to your profile and click view source in the view menu of the browser then search for post_form_id.

Now the two ids; Go to your profile and your friend’s profile and you’ll find the id in the URL.

That’s it! Try it for yourself.

Tags: , , ,

This will not serve as a comprehensive tutorial in developing services and clients for Axis2/C, but rather intended to provide some help for starters.

Apache Axis2/C is an engine for web services developed in C – there’s another implementation in Java. You can find an illustration of SOA here.

You first need to download and install Apache Axis2/C 1.3.0. You can download the binaries or sources from the Apache Axis2/C website. It would be easier to install the binaries if you are a beginner.

So let’s get started with developing a service. We’ll create a service to sort a set of integers in ascending or descending order.

Service

The service should have two functions:

  • axis2_get_instant – creates the service skeleton
  • axis2_remove_instant – removes the instant

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
AXIS2_EXPORT int
  axis2_get_instance(axis2_svc_skeleton_t **inst,
                     const axutil_env_t *env)
{
 *inst = axis2_sort_create(env);
 if (!(*inst))
  return AXIS2_FAILURE;
 
 return AXIS2_SUCCESS;
}
 
AXIS2_EXPORT int
  axis2_remove_instance(axis2_svc_skeleton_t *inst,
                        const axutil_env_t *env)
{
 if (inst)
  return AXIS2_SVC_SKELETON_FREE(inst, env);
 
 return AXIS2_FAILURE;
}
 
/* Create the service skeleton */
axis2_svc_skeleton_t *
  axis2_sort_create(const axutil_env_t *env)
{
 axis2_svc_skeleton_t *svc_skeleton = NULL;
 svc_skeleton = AXIS2_MALLOC(env->allocator,
                             sizeof(axis2_svc_skeleton_t));
 
 svc_skeleton->ops = &sort_svc_skeleton_ops_var;
 
 svc_skeleton->func_array = NULL;
 
 return svc_skeleton;
}

axis2_get_instant should create axis2_svc_skeleton struct with corresponding functions assigned. These functions are

  1. init – initializes the skeleton
  2. invoke – invokes the service
  3. on_fault – this is called when an fault is detected
  4. free – frees the skeleton instant

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
/* Functions for axis2_svc_skeleton */
int AXIS2_CALL
  sort_free(axis2_svc_skeleton_t *svc_skeleton,
            const axutil_env_t *env);
 
axiom_node_t* AXIS2_CALL
  sort_invoke(axis2_svc_skeleton_t *svc_skeleton,
              const axutil_env_t *env,
              axiom_node_t *node,
              axis2_msg_ctx_t *msg_ctx);
 
int AXIS2_CALL
  sort_init(axis2_svc_skeleton_t *svc_skeleton,
            const axutil_env_t *env);
 
axiom_node_t* AXIS2_CALL
  sort_on_fault(axis2_svc_skeleton_t *svc_skeli,
                const axutil_env_t *env, axiom_node_t *node);
 
/* Skeleton */
static const axis2_svc_skeleton_ops_t sort_svc_skeleton_ops_var = {
 sort_init,
 sort_invoke,
 sort_on_fault,
 sort_free
};

Now comes the main part of the service – implementation of the invoke function.

This function will be called with a reference to request. The XML request will be passed as a axiom_node_t, and you can navigate through it easily using functions axiom_node_get_first_child and axiom_node_get_next_sibling.

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
/* Process the request */
axiom_node_t* AXIS2_CALL
  sort_invoke(axis2_svc_skeleton_t *svc_skeleton,
               const axutil_env_t *env,
               axiom_node_t *node,
               axis2_msg_ctx_t *msg_ctx)
{
 return axis2_sort(env, node);
}
 
 /* Process the request */
axiom_node_t *
  axis2_sort(const axutil_env_t *env, axiom_node_t *node)
{
 AXIS2_ENV_CHECK(env, NULL);
 
 if(!node) return sort_error(env);
 
 axiom_node_t *order_node = axiom_node_get_first_child(node, env);
 axis2_char_t *order_str = get_string(order_node, env);
 
 if(!order_str) return sort_error(env);
 
 axiom_node_t *list = axiom_node_get_next_sibling(order_node, env);
 
 if(!list) return sort_error(env);
 
 axiom_node_t* current = axiom_node_get_first_child(list, env);
 
 if(!current) return sort_error(env);
 
 int i;
 
 a = AXIS2_MALLOC(env->allocator,
                  sizeof(long int) * MAX);
 
 for(i = 0; i < MAX && current; i++)
 {
  axis2_char_t *str = get_string(current, env);
  a[i] = strtol(str, NULL, 10);
 
  current = axiom_node_get_next_sibling(current, env);
 }
 
 int N = i;
 
 if(axutil_strcmp(order_str, "asc"))
  return build_sort_response(env, N, 1);
 else if(axutil_strcmp(order_str, "des"))
  return build_sort_response(env, N, -1);
 else
  return sort_error(env);
}

After parsing the input you should calculate and prepare the response of the service.

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
/* Generate the response */
axiom_node_t *
  build_sort_response(const axutil_env_t *env, int N, int order)
{
 axis2_char_t value_str[255];
 axiom_node_t *main_node;
 int i, j;
 
 for(i = 0; i < N; i++)
  for(j = 1; j < N; j++)
   if((a[j] - a[j-1]) * order > 0)
 {
  long int temp = a[j];
  a[j] = a[j-1];
  a[j-1] = temp;
 }
 
 axiom_namespace_t *ns1 = axiom_namespace_create(env, "http://axis2/test/sort", "ns1");
 
 axiom_element_create(env, NULL, "result", ns1, &main_node);
 
 for(i = 0 ; i < N; i++)
 {
  axiom_node_t *value_node;
 
  sprintf(value_str, "%ld", a[i]);
 
  axiom_element_t *value_ele = axiom_element_create(env, main_node, "value", NULL, &value_node);
  axiom_element_set_text(value_ele, env, value_str, value_node);
 }
 
 AXIS2_FREE(env->allocator, a);
 
 return main_node;
}

That’s it now we have created the service, but we need to create the service descriptor services.xml

1
2
3
4
5
<service name="sort">
 <parameter name="ServiceClass" locked="xsd:false">sort</parameter>
 <description>Sort service example.</description>
 <operation name="sort"/>
</service>

Here’s the code of the service: sort_service.c and the descriptor: services.xml.

Then compile the service using gcc

gcc -shared -olibsort.so -I$AXIS2C_HOME/include/axis2-1.3.0/ -L$AXIS2C_HOME/lib -laxutil -laxis2_axiom -laxis2_parser -laxis2_engine -lpthread -laxis2_http_sender -laxis2_http_receiver sort_service.c

The environment variable AXIS2C_HOME should be set to the axis2 installation folder.

Copy libsort.so and services.xml to folder AXIS2C_HOME/services/sort/.

Now start the axis server or restart if it’s already running, buy executing axis2_http_server. And check if the service is correctly deployed by checking http://localhost:9090/axis2/services.

Now that the service is running fine we can start creating the client.

Client

First we should set the properties and create the svc client

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
 const axis2_char_t *client_home = NULL;
 axis2_svc_client_t* svc_client = NULL;
 axiom_node_t *payload = NULL;
 axiom_node_t *ret_node = NULL;
 
 /* Create environment */
 axutil_env_t *env = axutil_env_create_all("sort_client.log", AXIS2_LOG_LEVEL_TRACE);
 
 /* Location of the service */
 axis2_char_t *address = "http://localhost:9090/axis2/services/sort";
 printf("Using address : %s\n", address);
 
 /* Creating options */ 
 axis2_options_t *options = axis2_options_create(env);
 axis2_endpoint_ref_t* endpoint_ref = axis2_endpoint_ref_create(env, address);
 axis2_options_set_to(options, env, endpoint_ref);
 
 /* Creating svc client */
 client_home = AXIS2_GETENV("AXIS2C_HOME");
 if (!client_home && !strcmp(client_home, ""))
 {
  printf("AXIS2C_HOME not set\n");
  return -1;
 }
 svc_client = axis2_svc_client_create(env, client_home);
 
 if (!svc_client)
 {
  printf("Error creating service client\n");
  AXIS2_LOG_ERROR(env->log, AXIS2_LOG_SI, "Stub invoke FAILED: Error code:"
    " %d :: %s", env->error->error_number,
    AXIS2_ERROR_GET_MESSAGE(env->error));
  return -1;
 }
 axis2_svc_client_set_options(svc_client, env, options);

Then build the request.

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
axiom_node_t *
   build_om_request(const axutil_env_t *env)
{
 axiom_node_t *main_node;
 axiom_node_t *order_node;
 axiom_node_t *values_node;
 axis2_char_t value_str[255];
 int i;
 
 
 axiom_namespace_t *ns1 = axiom_namespace_create(env, "http://axis2/test/sort", "ns1");
 
 axiom_element_create(env, NULL, "sort", ns1, &main_node);
 
 axiom_element_t *order_ele = axiom_element_create(env, main_node, "order", NULL, &order_node);
 axiom_element_set_text(order_ele, env, "des", order_node);
 
 axiom_element_t *values_ele = axiom_element_create(env, main_node, "values", NULL, &values_node);
 
 int N = 20;
 
 for(i = 0 ; i < N; i++)
 {
  axiom_node_t *value_node;
 
  sprintf(value_str, "%ld", i + 100);
 
  axiom_element_t *value_ele = axiom_element_create(env, values_node, "value", NULL, &value_node);
  axiom_element_set_text(value_ele, env, value_str, value_node);
 }
 
 return main_node;
}

Send the request.

1
ret_node = axis2_svc_client_send_receive(svc_client, env, payload);

Here’s the code of the service: sort_client.c. Now compile the client.

gcc -o sort_client -I$AXIS2C_HOME/include/axis2-1.3.0/ -L$AXIS2C_HOME/lib -laxutil -laxis2_axiom -laxis2_parser -laxis2_engine -lpthread -laxis2_http_sender -laxis2_http_receiver sort_client.c -ldl -Wl,--rpath -Wl,$AXIS2C_HOME/lib

Run it

Run the client to see what happens.

What happens if the client sends an empty request?

Tags: , , , ,

This is a getting started tutorial to Windows Communication Foundation (WCF) Services. I have discussed a simple service to calculate the area of a rectangle; yup, very simple ;)

1. First you need to download and install Visual Studio 2005 extensions for .NET Framework 3.0 (Windows Workflow Foundation).

Oops, looks like it needs a windows validation (bit of a problem if you have a pirate copy :P )

2. Once the installation is complete, start Visual Studio to create the project.

Goto File->New->Web Site, and you’ll see a new template called WFC Service.

Click OK to create an empty WCF Service.

3. Time to get started with the coding

Service.svc

<% @ServiceHost Language=C# Debug="true" Service="GeometryService" CodeBehind="~/App_Code/Service.cs" %>

Only a small change here – the name of the service

Web.config

<?xml version="1.0"?>
 
<configuration xmlns="http://schemas.microsoft.com/.NetConfiguration/v2.0">
  <system.serviceModel>
    <services>
      <!-- Before deployment, you should remove the returnFaults behavior configuration to avoid disclosing information in exception messages -->
      <service name="GeometryService" behaviorConfiguration="GeometryServiceBehavior">
        <endpoint contract="IGeometryService" binding="wsHttpBinding"/>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="GeometryServiceBehavior" >
          <serviceDebug includeExceptionDetailInFaults="true" />
          <serviceMetadata httpGetEnabled="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>
 
  <system.web>
    <compilation debug="true"/>
  </system.web>
 
 </configuration>

Enable metadata publishing and change the name of the service.

Service.cs

using System;
using System.ServiceModel;
using System.Runtime.Serialization;
 
// A WCF service consists of a contract (defined below as IMyService, DataContract1), 
// a class which implements that interface (see MyService), 
// and configuration entries that specify behaviors associated with 
// that implementation (see <system.serviceModel> in web.config)
 
[ServiceContract()]
public interface IGeometryService
{
 [OperationContract]
 int GetArea(Rectangle rect);
 [OperationContract]
 int GetPerimeter(int width, int height);
}
 
public class GeometryService : IGeometryService
{
 public int GetArea(Rectangle rect)
 {
  return rect.Area();
 }
 
 public int GetPerimeter(int width, int height)
 {
  Rectangle rect = new Rectangle(width, height);
  return rect.Perimeter();
 }
}
 
[DataContract]
public class Rectangle
{
 int width;
 int height;
 
 public Rectangle(int width, int height)
 {
  Width = width;
  Height = height;
 }
 
 [DataMember]
 public int Width
 {
  get { return width; }
  set { width = value < 0 ? 0 : value; }
 }
 
 [DataMember]
 public int Height
 {
  get { return height; }
  set { height = value < 0 ? 0 : value; }
 }
 
 public int Area()
 {
  return Height * Width;
 }
 
 public int Perimeter()
 {
  return 2 * (Height + Width);
 }
}

This is the code for the service.

4. Run the service – click F5 :)

This is what you get on the browser. So, lets do what they want.

5. Run the following on you command on Visual Studio Command Prompt

svcutil.exe http://localhost:1479/GeoWFCService/Service.svc?wsdl

Watch out, the path might be different ;) . And if you don’t know what Visual Studio command prompt is

6. Let’s create the client

Create (or rather add) a new project; this could even be a website

7. Then run the service – Ctrl + F5

8. Add a web reference to the service

8. Copy the GeometryService.cs created by svcutil in step 5 to the clients working (main) folder and add them to the project

You should also copy the configurations of output.config created by svcutil to app.config

9. Again time for coding

Form1.cs

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
 
namespace GeoWFCClient
{
 public partial class Form1 : Form
 {
  public Form1()
  {
   InitializeComponent();
  }
 
  private void calculateButton_Click(object sender, EventArgs e)
  {
   GeometryServiceClient gsclient = new GeometryServiceClient();
 
   /* The overloaded constructor of Rectangle is not present here */
   Rectangle rect = new Rectangle();
 
   rect.Width = Int32.Parse(widthTextBox.Text);
   rect.Height = Int32.Parse(heightTextBox.Text);
 
   areaTextBox.Text = gsclient.GetArea(rect).ToString();
   perimeterTextBox.Text = gsclient.GetPerimeter(rect.Width, rect.Height).ToString();
  }
 }
}

Set the textboxes and labels with appropriate names.

10. When you compile you’ll get a set of error because some assemblies are not referenced. Add references to them

11. Now see how it works

Start the service if haven’t done so already, and run the client

Wow! It works :D

Ok, hope you learned something with this and I got to go study for exam :P

Tags: , , , , ,

How to determine whether your Windows XP is 32-bit or 64-bit? You need to know when you want to install certain software.

Problem is that in 32-bit systems they don’t show it explicitly; that is if you have a 32 bit system you won’t see 64 anywhere :D . However, with Vista they display whether you’re on 32-bit or 64-bit.

You can find whether you’re using 32-bit or 64-bit system in a few easy steps.

Go to the control panel and pick the category Performance and Maintenance.

Then select system

In the General Tab of the dialog that appears

  • If you see Microsoft Windows XP Professional Version Year under System, you have a 32-bit system
  • If you see Microsoft Windows XP Professional x64 Edition Version Year under System, you have a 64-bit system

And that’s it.

Tags: ,

Windows andLinux

AndLinux is a free Linux system based on Ubuntu running under Windows. This works under Windows 2000, XP, 2003 Server and also Vista. It is something like a virtual system.

In andLinux Linux is not running under a separate window as in a traditional emulators; instead, programs run under andLinux will have its own windows, so that they would be much different from Windows programs.

AndLinux acts as a Windows service so you can set it to start automatically or start it manually when you want. Another great advantage of this is that you can install any Linux software on this without going through any conversion process; that is, you can use all the Linux programs you love on windows.

And the best thing is that for those of you who have devices which don’t have Linux drivers (mainly modems – ya, I also had that problem), it’s no more a problem. You don’t need drivers!

andLinux is also great if you are new to Linux. Because installing Linux on a computer with Windows isn’t very simple.

Tags: , ,

Yesterday (I’m writing this on 4th March), I switched on my computer, which has Kubuntu 7.10, and went to get the refrigerator to get something to eat. When I came back I saw the message Error 15: File not found. I thought maybe it’s a random error and I restarted the computer – It was still there.

Then I went to the boot menu and tried to boot with the recovery option, but it also gave the same error. Main problem was the simplicity of the error and it gave no clue of what was wrong for me. After that I booted up the computer with the live CD and still I couldn’t find anything. So I thought of getting some advice from an expert: Sandaruwan.

He said it’s probably a problem with locating the kernel and that I must check whether everything specified in the /boot/grub/menu.lst are present in relavent locations. But when I went back to the computer after the call it seemed that it was stuck (it was running on Kubuntu 7.10 live CD).

Therefore I removed the CD and rebooted planning to check which command went wrong using edit commands before booting ‘e’ and command-line ‘c’.

I entered each of the commands in the command prompt and found that initrd caused the trouble.

Initrd /boot/initrd.img-2.6.22-14-generic

It appeared that the file /boot/initrd.img-2.6.22-14-generic was not there; instead a backup file /boot/initrd.img-2.6.22-14-generic.bak was present. So I edited the command to point to /boot/initrd.img-2.6.22-14-generic.bak and booted. After the computer successfully booted up I made a copy of the backup file in the name /boot/initrd.img-2.6.22-14-generic.

Probably the problem would have been an failed upgrade which has backed up the file but not replaced it; however it could have been very convenient if the error message showed which file was missing :P .

Tags: ,

Video Downloader

This is a Firefox plug in which lets you download Youtube videos as FLV (Flash Video) files. You can use a converter to convert these to MPEG or DivX formats. You can also use VLC Player to view FLV videos.

Online FLV Converter

This site lets you download Youtube videos in many formats. You need to enter the URL of the Youtube video and it will prepare a downloadable video in a preferred format. The nice thing about this is that it also lets you download the soundtrack alone as a MP3. This feature is handy if you want to download songs to your MP3 player.

Enjoy!

Edit
These software are also for downloading youtube videos and converting them to preferred formats
YouTube Downloader 2.1.6
Free YouTube to MP3 Converter

Tags: ,

« Older entries