Redmine SVN set up.

For those of you that do not know, “Redmine is a flexible project management web application. Written using the Ruby on Rails framework, it is cross-platform and cross-database.

Redmine is open source and released under the terms of the GNU General Public License v2 (GPL).”

We are using the TurnkeyLinux version of Redmine which allows us to run a pre-built Virtual Machine image.

It works pretty good right out the box. One of the nice features is being able to run Subversion (SVN). Allowing you to version control, archive and back up your code.

To tie a project into SVN you need to manually set a few images in the web interface.

Log into Redmine via web interface

  1. Create/edit a project
  2. Go to “Repository” tab
    • Select SCM as Subversion
    • file:///srv/repos/svn/{PROJECT NAME}
    • Create a Login
    • Create a Password
  3. Click Save

Next you will need to log into Redmine server via SSH and complete the following steps.

  1. Create a folder to store the new repository:

    mkdir /srv/repos/svn/{PROJECT NAME}
  2. Create the repository.

    svnadmin create /srv/repos/svn/{PROJECT NAME}
  3. If need to you can verify the repository with the following line of code.

    svnadmin verify /srv/repos/svn/{PROJECT NAME}
  4. Edit the configuration file for the repository.

    nano /srv/repos/svn/{PROJECT NAME}/conf/svnserve.conf
  5. Unhide the following items:

    anon-access = read
    auth-access = write
    password-db = passwd
  6. Save file
  7. Edit the password file to mamange user names and passwords

    nano /srv/repos/svn/{PROJECT NAME}/conf/passwd
  8. When finished adding the user accounts save the file and exit the editor
  9. You may need to restart service/server

    touch /etc/init.d/svnserve

Finally connect to the Repository via tortoiseSVN

  1. Use tortoiseSVN “repo browser” to connect to svn://{IP ADDRESS}/svn/{PROJECT NAME}
  2. Add the following folders:

    • branches
    • trunk
    • tags

  3. Set folder on development machine.

Installing Samba on Ubuntu

Samba is a Local Area Network (LAN) file sharing service for Linux and Unix.

To download the Samba pages need run the following line.

sudo apt-get install libcups2 samba samba-common

After the packages are loaded we need to edit the Samba configuration file. To do that we will use the text editor nano.

nano /etc/samba/smb.conf

In the global section, remove the “#” at the beginning of the line security = user so that it looks like this:

[...]
# "security = user" is always a good idea. This will require a Unix account
# in this server for every user accessing the server. See
# /usr/share/doc/samba-doc/htmldocs/Samba3-HOWTO/ServerType.html
# in the samba-doc package for details.
   security = user
[...]

This enables Linux system users to log in to the Samba server.

Close the file and restart Samba.

Adding Samba Shares

If you have not already determines a share directory you may wish to create generic share for system user accounts.

mkdir -p /home/shares/allusers

Next adjust the owner of directory and all the files and subfolders for the directory share

chown -R root:users /home/shares/allusers/

Now you can set the user permissions for all the files and subfolders for the directory share

chmod -R ug+rwx,o+rx-w /home/shares/allusers/

Now we can edit the Samba configuration file to set up the share.

vi /etc/samba/smb.conf

Add the following lines of code to the end of the smb.conf file

[allusers]
  comment = All Users
  path = /home/shares/allusers
  valid users = @users
  force group = users
  create mask = 0660
  directory mask = 0771
  writable = yes

You may want to also add a line to the configuration to limit which users have permission to write to file

write list = userX

Next restart the Samba service to load you changes.

Managing Users

Setting the user account up

Before adding users to Samba you must add them to the system. Do this by running the useradd command. Then the user name. Followed by -m -G. Lastly the name of the group. In this case users

useradd userX -m -G users

Set the user account password

Now that we have created a user account we need to set a password for said account.

passwd userX userY

Adding the User Account to the Samba User Database

Now we can add the user to the Samba database. You will be prompted to create a password for the Samba account. In most cases you want the system user account password and Samba password to be the same.

smbpasswd -a userX

Connection to a Samba Share

Windows

To connect to a Samba share you will need to open the Windows Explorer program. In the address bar type \\ and the IP address of the machine you are trying to connect to.

\\10.0.0.11

cfc – full SMTP method

I have been wanting to update my ColdFusion skills writing code in full cfscript. So, one of the first things that I did was write a method to send me email from a contact form for my UX site.

To do this I created the following CFC. Most of which is written on page 22 of the 25Meg PDF file Developing Applications ADOBE� COLDFUSION 10.


component displayname="contactUs" hint="Allows users to send email." output="false" {
  remote any function setEmailMessage(
    required string fromName,
    required string fromEmail,
    required string message,
    string subject = "Contact Form",
    string toEmail = "to@fake.com",
    string failToEmail = "fail.to@fake.com",
    numeric priority = 2,
    array attachements,
    required string smtp,
    required string smtpUsername,
    required string smtpPassword
  )
  returnformat='json' {
    /***** BEGIN DEFAULT RETURN VALUE *****/
      // Pre-populate the JSON structure that is to be returned on failure or success.
      // This can be adjusted to meet your needs.
      local.returnValue = {
        "statusCode" : 1000,
        "requestID" : createUUID(),
        "permissions" : "VALED",
        "data" = {
          "message" : "Success"
        },
        "eventName" : "/com/modules/contactUs.cfc",
        "requestParams" : arguments
     };
    /***** END DEFAULT RETURN VALUE *****/

    /***** BEGIN EMAIL PROCESS *****/
      try {
        // Create an instance of the mail object
        mail=new mail();

        // Set it's properties
        mail.setSubject( arguments.subject );
        mail.setTo( arguments.toEmail );
        mail.setFrom( arguments.fromEmail );
        if ( arguments.ccEmail !== "~") {
          mail.setCC( arguments.ccEmail );
        }
        if ( arguments.bccEmail !== "~") {
          mail.setBCC( arguments.bccEmail );
        }
        if ( arguments.failToEmail !== "~") {
          mail.setFailTo( arguments.failToEmail );
        }

        // Set the priority (1, 2 or 3 - High to Low)
        mail.addParam(
        name="X-Priority",
        value= arguments.priority
      );

      // Add email body content in text format
      mail.addPart(
        type="text",
        charset="utf-8",
        wraptext="72",
        body=REReplace( arguments.message, "<[^>]*>", "", "All" )
      );

      // Add email body content in HTML formats
      mail.addPart(
        type="html",
        charset="utf-8",
        body=arguments.message
      );

      // Set SMTP account access
      mail.setServer( arguments.smtp );
      mail.setUsername( arguments.smtpUsername );
      mail.setPassword( arguments.smtpPassword );

      // Send the email message
      mail.send();

      // Update JSON status message
      local.returnValue.data.message = "Email Sent";
    } 
    catch (any e) {
      local.returnValue.statusCode = 5000;
      local.returnValue.data.message = e.message;
    }
  /***** END EMAIL PROCESS *****/

  /***** BEGIN JSON CLEAN UP OF ARGUMENTS TO RELAY BACK THE USER *****/
    StructDelete(local.returnValue.requestParams, "smtp");
    StructDelete(local.returnValue.requestParams, "smtpUsername");
    StructDelete(local.returnValue.requestParams, "smtpPassword");
    StructDelete(local.returnValue.requestParams, "failToEmail");
    if ( local.returnValue.requestParams.ccEmail == "~" ) {
      StructDelete(local.returnValue.requestParams, "ccEmail");
    }
    if ( local.returnValue.requestParams.bccEmail == "~" ) {
      StructDelete(local.returnValue.requestParams, "bccEmail");
    }
  /***** END JSON CLEAN UP OF ARGUMENTS TO RELAY BACK THE USER *****/

  return local.returnValue;
}

Minimal event listeners with jQuery

I have a few pages on a project that use lots of buttons and event listeners. The developers that worked on this page created a single event listener for every button and every state (click, hover, mouseover, mouseout, etc). This seems to standard development practice.

But, to save 600 lines of code I created only one or two listeners using regular expressions and made up HTML tag attributes. For example, we created a video player interface for JWPlayer which included a play, pause, and stop button.

<span ref="playButton">Play</span>
<span ref="pauseButton">Play</span>
<span ref="stopButton">Play</span>

Normally most people would create an event listener for each button and their click event. But, by using the regular expression I only need to create on event listener for the page. Once clicked I can check to see what button was pressed and run a method call for that button pressed.

jQuery( "[ref$=Button" ).click(
  { 
    if ( jQuery( this ).attr( "ref" ) === "playButton" ) {
      playJWPlayerVideo();
    }
    else if (jQuery( this ).attr( "ref" ) === "pauseButton" ) {
      pauseJWPlayerVideo();
    }
    else {
      stopJWPlayerVideo();
    }
  }
);

For more than 5 click events you might want to use a switch/case statement to make it run faster and to group similar events together to run the same method.

Regular Expression to test for ColdFusion ODBC data time

I started writing a Javascript library to convert dates in Javascript notation to ColdFusion ODBCDateTime format and back.

One of the first things that I needed to do was to check to see if a client-side ColdFusion ODBCDateTime was being returned from the server. To do this I created a Regular Expression in Javascript to make sure that the value was indeed a valid ODBCDateTime object.

Here is the Regular Expression that I used.

/^[{ts]+\s+[']+\d{4}(\-)+[0-1][0-9](\-)+[0-3][0-9]+\s+[0-2][0-9](\:)[0-5][0-9](\:)[0-5][0-9]['][}]/gi

To test that a date being returned by my server is in ODBCDateTime format I created this test:

var isODBCDateTime = /^[{ts]+\s+[']+\d{4}(\-)+[0-1][0-9](\-)+[0-3][0-9]+\s+[0-2][0-9](\:)[0-5][0-9](\:)[0-5][0-9]['][}]/gi.test( <em>date to test</em> );

Do you know your hotkeys?

For the last few days some colleges and I have been discussing the skill levels of computer users ( I will have to write a posting on this at another time). One of the topics that I brought up is that few people know what hotkey are.

For those of you that do not know what hotkeys are, they a series of keyboard shortcuts that perform tasks and run programs. Your Window key and Apple Key on your keyboard are short cut keys.

In the old days of Windows. Almost 20 years ago there was not a “Windows” key on the keyboard (Gasp!!!). So you had drag the mouse the Start button bring up your list of installed programs. But, if you knew the long running hotkey combination Ctrl-Esc you could activated the Start menu and use you arrow keys to navigate the menu and find your application.

“But, why would I care about this. I have a mouse.” True. But, using hot keys speeds up routine tasks.

For example. Think about how much time it takes you to save a document with the mouse.

If I am working on a paper for a class I have to scroll down to the end of the document with the mouse to make changes. I leave my mouse pointer / cursor in the bottom right of the screen. I start typing. I feel good about my changes and now have to my mouse to to the application tool to find and click the save button.

Now open a document. Hold down the Ctrl and press the End key to take you to the of the document. Append your document. When finished hold down the Ctrl and press the S key. You have just saved your document.

Just think about all the time you could save if your hand never had to leave the keyboard to reach for your mouse.

Every program and operating system has different hotkeys. I don’t know them all. But, I have a few URL addresses to help us find them.

Here are some generic keyboard short cuts. That work in 90% of all windows programs.

Generic
Ctrl + C or Ctrl + Insert: Copy.
Ctrl + X or Shift + Delete: Cut.
Ctrl + V or Shift + Insert: Paste/Move.
Ctrl + N: New File, Tab, Entry, etc.
Ctrl + S: Save.
Ctrl + O: Open…
Ctrl + P: Print.
Ctrl + Z: Undo.
Ctrl + A: Select all.
Ctrl + F: Find…
Ctrl + F4: Close tab or child window.
F1: Open help.
F11: Toggle full screen mode.
Alt or F10: Activate menu bar.
Alt + Space: Display system menu. Same as clicking the icon on the titlebar.
Escape: Remove focus from current control/menu, or close dialog box.

Generic Navigation
Tab: Forward one item.
Shift + Tab: Backward one item.
Ctrl + Tab: Cycle through tabs/child windows.
Ctrl + Shift + Tab: Cycle backwards through tabs/child windows.
Enter: If a button’s selected, click it, otherwise, click default button.
Space: Toggle items such as radio buttons or checkboxes.
Alt + (Letter): Activate item corresponding to (Letter). (Letter) is the underlined letter on the item’s name.
Ctrl + Left: Move cursor to the beginning of previous word.
Ctrl + Right: Move cursor to the beginning of next word.
Ctrl + Up: Move cursor to beginning of previous paragraph. This and all subsequent Up/Down hotkeys in this section have only been known to work in RichEdit controls.
Ctrl + Down: Move cursor to beginning of next paragraph.
Shift + Left: Highlight one character to the left.
Shift + Right: Highlight one character to the right.
Shift + Up: Highlight from current cursor position, to one line up.
Shift + Down: Highlight from current cursor position, to one line down.
Ctrl + Shift + Left: Highlight to beginning of previous word.
Ctrl + Shift + Right: Highlight to beginning of next word.
Ctrl + Shift + Up: Highlight to beginning of previous paragraph.
Ctrl + Shift + Down: Highlight to beginning of next paragraph.
Home: Move cursor to top of a scrollable control.
End: Move cursor to bottom of a scrollable control.

Generic Web Browsers
Ctrl + Tab or Ctrl + PageDown: Cycle through tabs.
Ctrl + Shift + Tab or Ctrl + PageUp: Cycle through tabs in reverse.
Ctrl + (1-9): Switch to tab corresponding to number.
Ctrl + N: New browser window.
Ctrl + T: New tab.
Ctrl + L or Alt + D or F6: Switch focus to location bar.
Ctrl + Enter: Open location in new tab.
Shift + Enter: Open location in new window.
Ctrl + O: Open a local file.
Ctrl + W: Close tab, or window if there’s only one tab open.
Ctrl + Shift + W: Close window.
Ctrl + S: Save page as a local file.
Ctrl + P: Print page.
Ctrl + F or F3: Open find toolbar.
Ctrl + G or F3: Find next
Ctrl + Shift + G or Shift + F3: Find previous
Ctrl + B or Ctrl + I: Open Bookmarks sidebar.
Ctrl + H: Open History sidebar.
Escape: Stop loading page.
Ctrl + R or F5: Reload current page.
Ctrl + Shift + R or Ctrl + F5: Reload current page; bypass cache.
Ctrl + U: View page source.
Ctrl + D: Bookmark current page.
Ctrl + NumpadPlus or Ctrl + Equals (+/=): Increase text size.
Ctrl + NumpadMinus or Ctrl + Minus: Decrease text size.
Ctrl + Numpad0 or Ctrl + 0: Set text size to default.
Alt + Left or Backspace: Back.
Alt + Right or Shift + Backspace: Forward.
Alt + Home: Open home page.
Ctrl + M: Open new message in integrated mail client.
Ctrl + J: Open Downloads dialog.

Portable Apps

I had a posting on my old blog about Portable Apps and want to talk about them for those of you that do not know what they are.

Basically Portable Apps allow users to take some of their favorite apps with them where ever they go. For instance I installed the portable apps to my iPod, which I can use as a portable hard drive for backup.

I get calls from people all the time that need help fixing their computers. To avoid downloading software to install on a clients machine. I simple connect my iPod to their computer, run the Portable Apps menu, and now have access to all my applications. I can scan for viruses, trojans, malware and spyware. Check hard drives for bad sectors, recover deleted files, and defrag. Additional apps allow me to packet sniff network traffic, surf the internet, make Skype calls, manage passwords, edit and browse the photos. And if you really need to there a ton of games.

These are some of my day-to-day apps. But there are tons more at PortableApps.com

  • Fire Fox – Web browser
  • Google Chrome – Web browser
  • Opera – Web browser
  • FileZilla – FTP Client
  • Mozilla Thunderbird – Email Client
  • Pidgin – Chat with AOL, MSN, Yahoo, etc.
  • PuTTY – telnet and SSH client
  • OpenOffice – word processor, spreadsheet, presentations with Microsoft compatibility
  • LibreOffice Portable – word processor, spreadsheet, presentations with excellent compatibility
  • ClamWin Portable – Antivirus
  • Eraser Portable – securely delete files and data
  • KeePass Password Safe – Secure, easy-to-use password manager
  • Spybot – Search & Destroy – Spyware detection and removal
  • 7-Zip – File archiver and compressor
  • CrystalDiskInfo – disk health monitoring tool
  • Disk Cleaner – cache, temp file and history cleaner
  • Smart Defrag – disk defragmentation and optimization
  • TeamViewer – remote PC support and screen-sharing
  • Toucan – backup, sync and encrypt for advanced users
  • VirtuaWin – virtual desktop manager
  • Wise Registry Cleaner – registry cleaner and optimizer
  • Wise Data Recovery – data and file recovery
  • Notepad++ – A full-featured text editor with syntax highlighting

Visual Trace Route via VisualRoute.com

I some times get calls from a client telling me that their connection to a site is bad or slow. As always, testing from my office is fine. But, how do you check a server from out side you network?

Well, here is one way. As you know there is tracert for DOS and shell. But, is only for the network that you are connect to. To test out side you network you might want to use VisualRoute.com and follow these steps.

  1. Go to VisualRoute.com
  2. Click Live Demo on the gray menu bar.
  3. Select which region of world you wish to connect from (“North America”)
  4. Select a push pin to select a server to test from (“Oklahoma City, Oklahoma)
  5. Next the site will try and run the Java app that talks to the server you selected. You may be prompted to verify that you want to run this Java app.
  6. Once the app is loaded you should see field labelled Perform connection test to. The filed is per-populated with your IP address.
  7. To test a URL or IP address other than your own. Change the field value for Perform connection test to ( http://www.lighthouseknowledge.com )
  8. Click the start button to the right of the field.
  9. When the test is complete the Summary will give you a visual representation of the network path it took, a performance chart of said machines, text analysis information, and a map of the path it took. All of which are clickable for more information or to load each segment in its corresponding tab.

Visualware, the developer of VisualRoute.com, allows you purchase a desktop application from them perform the same task but from with the network you are in.

If you wish you can also download the server version from Visualware and be added to the world wide network list of trace route servers.

BASE64 and JSON

I have been working on a project that requires me to make an AJAX request to a ColdFusion service that returns a BASE64 version of an image wrapped in JSON. This JSON packet is used by the client-side to populate the SRC argument of an <IMG> tag. The process was working fine most of the time. But, every once and a while the image is broken.

After doing some checking I noticed that on the client-side the BASE64 string was not the same as the server-side.  The issue was that parts of the string were being transposed. It seems that the browser(s) were thinking that parts of the string were Unicode because some images strings contained sub-strings of u+a4f7 or u+c19b.

To correct the transposing issue ended up adjusting the client-side code and the ColdFusion service. First, on the server-side I wrapped the BASE64 process in the URLEndcodedFormat()function. Second, I adjusted the client-side code to decodeURI() the string from the JSON packet.

This process resolved the issue.