February 25, 2009

Packaging…Mac…???

Posted in Mac, Open Source, Programming, XRap tagged , , , , , , , at 1:51 am by Joshua

Yes.  I need to figure out how to package up a XULRunner app, so that it can be distributed and installed on to a Mac.
From what I have been reading,  there are two methods for installing on a Mac:

  1.  
    1. The software publisher has provided an installer, which will automatically install the application
    2. The software is packaged in the form of an application (.app), framework (.framework), plug-in (.plugin), Safari downloads (.download), and installer packages (.pkg)

I have found a manual install method, which simply taking the .app file and putting it into /Applications, any documentation in the /Library/Documentation, and framework into the /Library/Frameworks.  The only problem is that XULRunner apps have a strict directory structure to maintain, which is actually one of the problems I am having for my Linux distribution.  I found the Apple Software Delivery Guide, which is awesome! but I’ll still have to hop on IRC and findout more about XULRunner apps.  I may find myself having to overhaul my Linux distribution of XRap, depending on what I learn about Mac packages.

December 13, 2008

XRap Version 0.3 Windows Released!

Posted in Open Source, Programming, XRap tagged , , , , , , at 4:25 pm by Joshua

Well its been a long time, a lot of reading, and a lot of learning (JavaScript and XUL), but I’ve managed to finally change over XRap from C# over to a XULRunner Application!  I haven’t quite got the UI just how I like it, but funtionality-wise it works perfectly.

How it works:

  1. Once XRap is started, all you must do is enter the directory path of your XULRunner application, more specifically where the application.ini is located.XRap
  2. When the path is entered, click on ‘Load Application Directory’ .
  3. XRap will read the application.ini file for validity.
  4. Once a valid application.ini file is loaded, click on ‘Check Integrity’
  5. XRap will check for old XRap created files, and the XULRunner runtime (which must be in your applications directory).
  6. Prompts will inform you of any files which will be removed.
  7. Once the integrity check is complete, simply click on the ‘Create Installer’.
  8. XRap will read through your application’s directory, as well as create the executable from the xulrunner-stub.exe file in the XULRunner runtime.XRap

During the creation of the .msi file, XRap may appear to freeze up, but its actually working, it just takes some time to create the file.  Also I need to figure out how to make the textbox scroll automatically, but its a minor cosmetic issue, and should be fixed by the next release.  If anyone knows please let me know.  Other than that, enjoy! and let me know of any suggestions or fixes needed.

Download:

XRap v 0.3 Windows Installer

XRap v 0.3 Source

December 4, 2008

Run External Apps using XPCOM Interfaces

Posted in Open Source, Programming, XRap tagged , , , , , , , at 3:43 am by Joshua

I thought it was impossible to run a program outside my XUL app, mainly because of some kind of JavaScript restriction. There are client-side restrictions to protect the file system from being infected from malicious code, however there are some server side solutions, but most of them use ActiveX. Is it possible to run a program in JavaScript? Even a batch file?

Here’s my problem, basically Im using a program called WiX, to create an Application Packager, I create an XML based file (.wxs), and compile it through a program called candle.exe taking it in as an argument.

C:\>candle.exe filename.wxs
C:\>light.exe filename.wixobj

Candle will return a new file with the extension .wixobj, which must then go through a linking program called light.exe in the same fashion. I’m using XUL (Mozilla) to create a program which will pretty much automate most of the tasks, XUL uses JavaScript, can JavaScript run external commands?

After some chatting on IRC, I was directed to the nsIProcess interface, and nsILocalFile.launch(). I actually ended up trying both, however nsIProcess is actually the recommend way to go about this problem, mainly because nsILocalFile.launch() may not work on all platforms.

This is how I used nsIProcess:

function callLight()
{
var getWorkingDir= Components.classes["@mozilla.org/file/directory_service;1"]

.getService(Components.interfaces.nsIProperties)
.get(“CurProcD”, Components.interfaces.nsIFile);

var lFile = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);

var lPath = getWorkingDir.path + “\\wix-2.0\\light.exe”

lFile.initWithPath(lPath);
var process = Components.classes["@mozilla.org/process/util;1"]
.createInstance(Components.interfaces.nsIProcess);
process.init(lFile);
var wxsPath = inputPath + “\\” + getAppName() + “.wixobj”;
var args = [wxsPath];

process.run(true, args, args.length);
}

getWorkingDir – is of type nsIProperties, and the “CurProcD” basically gets my current working directory, which for my reason is where my wix source files reside

lFile – is of type nsILocalFile, and will hold the file, in my case it will be either candle.exe or light.exe

  • lPath – holds the path to the file which lFile will contain
  • lFile.initWithPath(path) – initalized the nsILocalFile with the parameterized path

process – is of type nsIProcess, is the interface which will represent an executable process

  • process.init(nsILocalFile) – initializes the selected nsILocalFile to a process
  • process.run(blocking, args, arg_count) – Runs the process
    • blocking - is a boolean qualifier, if true will wait for the process to complete before continuing with the program, and if false will continue and let the process run by itself
    • args - is a string array of arguments which may be passed to the executing process
    • arg_count - is the number of arguments being passed

It worked perfectly, the only reason I used the nsILocalFile.launch() was that I didn’t realize that the output file (.wixobj) would end up in the directory which I was executing my XRap program, and not where the source (.wxs) was located. So I had to create a batch file, and use launch() to execute it. It was more code than needed, and created extra files, nsIProcess is much better to work with.

MDC – Running Applications

…Happy Processing!

December 2, 2008

GUID generator in JavaScript

Posted in Open Source, Programming tagged , , , at 9:12 pm by Joshua

Found two little functions in JavaScript to create a GUID

function S4(){
return (((1+Math.random())*0×10000)|0).toString(16).substring(1);
}

function guid() {
return (S4()+S4()+”-”+S4()+”-”+S4()+”-”+S4()+”-”+S4()+S4()+S4());
}

Thanks to sj at note19.com, I don’t know exactly how reliable the generator is, I ran a couple tests against 50 guids, and it passed, but I need to run the guids through the Windows Installer using WiX, and I don’t know if there will be conflicts

I am still open to any other JavaScript generators if anyone knows of any

November 26, 2008

XUL File I/O: Write Files

Posted in How-to, Open Source, Programming tagged , , , , , , , , at 2:06 pm by Joshua

Writing files in XUL isn’t that much harder than reading a file, in fact its very similar.  What a relief.  In my example I am appending the data “Appending Data” to my file.

function writeFile()
{
var data = “Appending Data”;

var filePath = “C:\\text.txt”;

var file = Components.classes["@mozilla.org/file/local;1"]
.createInstance(Components.interfaces.nsILocalFile);
var foStream = Components.classes["@mozilla.org/network/file-output-stream;1"]
                         .createInstance(Components.interfaces.nsIFileOutputStream);
file.initWithPath(filePath);
if ( file.exists() == false ) {
      alert(“File does not exist”);
}

foStream.init(file, 0×02 | 0×10, 00666, 0);
foStream.write(data, data.length);
foStream.close();
}

file – gets the nsILocalFile interface component, making file of type nsILocalFile
foStream – gets the nsIFileOutputStream interface component, inherited from nsIOutputStream, making foStream of type nsIFileOutputStream

  • init(file, file_io_flags,file_mode_flags, behavior_flags) –
Option Type
file nsIFile
File_io_flags 0×01 Read only
0×02 Write only

0×04

Read and Write
0×08 Create File
0×10 Append
0×20 Truncate
0×40 Sync
0×80 Exclude
File_mode_flags 00400 Read by owner
00200 Write by owner
00100 Execute by owner
00040 Read by Group
00020 Write by Group
00010 Execute by Group
00004 Read by Others
00002 Write by Others
00001 Execute by Others
* Mode flags can by added to combine flag
* File_mode_flags is only applicable to UNIX based systems
Behavour_flags 0 Default

write(data, count) – sends the data string parameter to the output stream buffer, and writes the number of bytes according to count
close() – closes the stream

Not too difficult, but it is sure difficult to find the instructions and documentation

November 25, 2008

How-to: Read Files in XUL

Posted in How-to, Open Source, Programming tagged , , , , , , , , at 4:16 pm by Joshua

After some weeks of procrastination and going nuts over other projects, I’m getting back to XUL and my XRap program.  I’ve been asked to change my current XRap code (currently the 0.1 is in C#) to XUL, which would increase its portability, and it just makes sense to make a XULRunner Packager in XUL.  Unfortunately, I must undertake the task of learning how to program in XUL and JavaScript.  So I’ve managed to complete most of my other programming courses, so now I can focus on this.  One of my main problems was that I had no idea of how the JavaScript file was linked to the XUL file, and how it would know where to pass output, or where to get output.  My second major problem was that I couldn’t find any help on how to access the file system using JavaScript.

After a quick chat on IRC, a colleague directed me to the File I/O site on the Mozilla Developer Network.  I found it to be only somewhat useful, but even more so when you take a look at the ‘Read local files and write local files’ page at Captain’s Universe.  Combining the two I’ve managed to come up with this function in my .js file:

function getFile()
{
var dup = document.getElementById(‘tb_input’);

var file = Components.classes["@mozilla.org/file/local;1"]
               .createInstance(Components.interfaces.nsILocalFile);

var fstream = Components.classes["@mozilla.org/network/file-input-stream;1"]
.createInstance(Components.interfaces.nsIFileInputStream);
var sstream = Components.classes["@mozilla.org/scriptableinputstream;1"]
.createInstance(Components.interfaces.nsIScriptableInputStream);

file.initWithPath(filePath);
if ( file.exists() == false ) {
dup.value = “File does not exist”;
}

fstream.init(file, 0×01, 00004, null);
sstream.init(fstream);

var output = sstream.read(sstream.available());
dup.value = output;
sstream.close();
fstream.close();
}

file – gets the nsILocalFile interface component, making file of type nsILocalFile
filepath – use the absolute path, and the double backslash to avoid the escape character.
file – gets the nsILocalFile interface component, making file of type nsILocalFile inherited from nsIFile

  • initWithPath(filepath) – takes in the file path, and initializes it
  • exists() – checks if there is a valid file associated with file

fstream – gets the nsIFileInputStream Interface component, making fStream of type nsIFileInputStream

  • init(file, file_io_flags,file_mode_flags, behavior_flags) –
Option Type
file nsIFile
File_io_flags 0×01 Read only
  0×02 Write only
 

0×04

Read and Write
  0×08 Create File
  0×10 Append
  0×20 Truncate
  0×40 Sync
  0×80 Exclude
     
File_mode_flags 00400 Read by owner
  00200 Write by owner
  00100 Execute by owner
  00040 Read by Group
  00020 Write by Group
  00010 Execute by Group
  00004 Read by Others
  00002 Write by Others
  00001 Execute by Others
* Mode flags can by added to combine flag
* File_mode_flags is only applicable to UNIX based systems
 
Behavour_flags 0 Default

sstream – gets the nsIScriptableInputStream interface component, making sStream of type nsIScriptableInput Stream

  • init(nsIFileInputStream) – initializes the file input stream
  • read(int32 count) – reads the count bytes in the stream
  • available() – returns the number of bytes in the stream

Well, it actually didn’t give me as much of a headache that I thought it might have.  It is just a matter of thinking like a Mozilla/JavaScript person, and knowing what the interfaces can do.  Next up Writing Files…

November 5, 2008

Installing PHPUnit on Ubuntu 8.04

Posted in How-to, Programming, Software tagged , , , at 2:13 pm by Joshua

  1. You need to get the latest release of PHP

    $sudo apt-get install php5

  2. To get PHPUnit you need to get the PEAR installer, which is part of PHP

    $sudo apt-get install php-pear

  3. Once you have PEAR installed you must register the PEAR channel with the PEAR environment

    $sudo pear channel-discover pear.phpunit.de

  4. The and the last step is to get and install PHPUnit

    $sudo pear install phpunit/PHPUnit

Good luck!

Installing WAMP and PHPUnit on Windows

Posted in How-to, Programming tagged , , , , at 11:30 am by Joshua

  1. Download and Install WAMP
  2. Once you have installed and setup WAMP, open up the command prompt and go to your php directory in WAMP

    C:\>cd wamp\bin\php\php5.2.5

  3. From here you must run the go-pear.bat file to install PEAR and all the files needed for it

    C:\wamp\bin\php\php5.2.5>go-pear.bat

  4. When executed PEAR will ask you a series of question to set itself up correctly, if you don’t know what your doing then just accept the defaults
  5. Once installed you must run the PEAR_ENV.reg which will create the environment variables for the user, so that PEAR can be called in any directory on the command line>

    C:\wamp\bin\php\php5.2.5>PEAR_ENV.reg

    For me, it seemed to work no problem, but if you cannot call PEAR from the command prompt, then you must manually add the directory to the path in the Environment Variables list, found in System Properties -> Advanced-> Environment Variables, then add the directory C:\wamp\bin\php\php5.2.5 to the PATH variable

  6. Once you have PEAR setup, then you must register the PHPUnit channel with PEAR

    C:\wamp\bin\php\php5.2.5>pear channel-discover pear.phpunit.de

  7. Now you can use the PEAR to install packages from the PHPUnit channel

    C:\wamp\bin\php\php5.2.5>pear install phpunit/PHPUnit

  8. You should now find the PHPUnit source files under the PHP directory

…Happy Days

October 23, 2008

XML Listing of File System

Posted in How-to, Open Source, Programming tagged , , , , , at 11:08 pm by Joshua

One of the challenges of automatically preparing a wxs (which is in xml) file for WiX to process into an msi file for installation, was creating a recursive algorithm to read a target directory an get all sub-directories and corresponding files. The problem I was having, was that I could get all directories and files, but I couldn’t add them to the wxs file with the depth which they came out.
Finally, after much experimenting and searching around, I found a project by Damian Castroviejo, which was written in VB, but exactly what I was looking for.  Here is my interpretation on it:

public class loopDirectoryNodes
{
public void getDirNodes(XmlDocument xmlDoc, XmlElement xe, String path)
{
foreach (String dir in Directory.GetDirectories(path))
{
XmlElement dirChild = xmlDoc.CreateElement(“Directory”);
dirChild.SetAttribute(“Name”, dir);
Console.WriteLine(“Adding Directory: ” + dir);
xe.AppendChild(dirChild);
foreach (String fileName in Directory.GetFiles(dir, “*.*”))
{
XmlElement xeCom = xmlDoc.CreateElement(“Component”);
xeCom.SetAttribute(“Guid”, Guid.NewGuid().ToString().ToUpper());
XmlElement xeFile = xmlDoc.CreateElement(“File”);
xeFile.SetAttribute(“Id”, fileName);
xeFile.SetAttribute(“Name”, fileName);
xeFile.SetAttribute(“DiskId”, “1″);
xeFile.SetAttribute(“Source”, fileName);
xeFile.SetAttribute(“Vital”, “yes”);
dirChild.AppendChild(xeCom);
xeCom.AppendChild(xeFile);
Console.WriteLine(“Adding File: ” + fileName);
}
getDirNodes(xmlDoc, dirChild, dir);
}
}
}

The parameters passed to the method getDirNodes, are the xmlDoc which is the XML document which the nodes will be added to, xe is the XML Element which is the node you want the directories to be added to, and path is the Directory which you wish you map the sub-directories and files.
The first foreach statement will loop through the Directory passed to find all sub-directories and add each of them to the xe XML Element passed in the parameter, while the second foreach will loop through each of those sub-directories found, and add the files within them to the sub-directory node being searched.  Once all the file for the sub-directory are found (if any), the method calls itself, passing the same XML Document xmlDoc, but with the XML Element of the sub-directory just searched and it path, to search that sub-directory for any other directories within.
Once all sub-directories of a folder are found, the method returns to where it was called in itself, and continues on to the next directory, until all directories are found.  Genius, thanks Damian, you helped me a lot!

October 17, 2008

WiX – Listing File System in XML

Posted in Open Source, Programming tagged , , , , at 6:39 pm by Joshua

Problem:

WiX uses an XML file for instructions on what directories to add to the msi package.  I had no problem in recursively going through the source directory and pulling all sub-directories and files, the trouble I have is inserting those entries into an XML file with the same depth as in the file system.

Working Solution:

After over a week of doing build, run and repeat, I figured I should use the stack in C#, eureka!  Before I was bouncing around some methods until I got all files and directories out, the good things was that they came out in order, the bad thing was that it got complicated because I was passing too many parameters, an XMLELEMENT, XMLDOCUMENT, the directory to read, and then I couldn’t attach a sub-directory to a directory, because it thinks the directory hasn’t been created yet.  Ahh, what a mess.

I implemented the stack in a while loop, pushed directories on it, and at the same time read the directory on the top of the stack for files.  It’s a little complicated when looking at how the directories are read, but I realized it was backwards, because it has the last directory added on the top of the stack.

XmlElement xeDir;
dirStack.Push(args[0]);
int dirCount = -1;
int uniqueFile = 0;
while (dirStack.Count > 0)
{
String curDir = dirStack.Pop(); 

if (dirCount == dirStack.Count)
{
XmlElement childDir = xmlDoc.CreateElement(“Directory”);
childDir.SetAttribute(“Id”, curDir);
Console.WriteLine(“NODE:” +installDirNode.ChildNodes.Count);
installDirNode.LastChild.AppendChild(childDir);

foreach (String fileName in Directory.GetFiles(curDir, “*.*”))
{
String[] comFileID = fileName.Split(new char[] { ‘\\’ });
String[] comID = comFileID[comFileID.Length-1].Split(new char[] { ‘.’ });

XmlElement xeCom = xmlDoc.CreateElement(“Component”);
xeCom.SetAttribute(“Id”, comID[comID.Length-2] + uniqueFile);
xeCom.SetAttribute(“Guid”, Guid.NewGuid().ToString().ToUpper());

XmlElement xeFile = xmlDoc.CreateElement(“File”);
xeFile.SetAttribute(“Id”, fileName);
childDir.AppendChild(xeCom);
xeCom.AppendChild(xeFile);
fileReturn.Add(fileName);
uniqueFile++;
}
}
else
{
xeDir = xmlDoc.CreateElement(“Directory”);
xeDir.SetAttribute(“Id”, curDir);
installDirNode.AppendChild(xeDir);

foreach (String fileName in Directory.GetFiles(curDir, “*.*”))
{
XmlElement xeFile = xmlDoc.CreateElement(“File”);
xeFile.SetAttribute(“Id”, fileName);
xeDir.AppendChild(xeFile);
fileReturn.Add(fileName);
}
}
dirCount = dirStack.Count;
foreach(String dirName in Directory.GetDirectories(curDir))
{
dirStack.Push(dirName);
}
}

Current Problem:

I am able to attach sub-directories to the parent directory in the XML file, but if there is another sub-directory below the first sub-directory, I can’t attach it that deep.

SOLVED! My Solution

Follow

Get every new post delivered to your Inbox.