background image
HomeRecent PostsDrupalSearchTagsRSSContactAboutAccount
Eric.London's picture

Rsync is a great command line program for copying and sync'ing data. It can use standard SSH protocol (default port 22) to copy files from computer to computer, or locally from one path to another. It frequently comes on linux/unix systems, but if you're using Windoze, I suggest installing Cygwin.

Part One
The first step in this tutorial is to setup passwordless SSH. Open a terminal on the computer you want to copy files from, referred to in this article as "local".

# use the ssh-keygen command to generate a public and private key
# I left the passphrase empty, and used the default path: ~/.ssh/id_dsa
local$ ssh-keygen -t dsa

# the above command will create two files (public and private keys)
local$ ls -l ~/.ssh/id_dsa*
-rw-------  1 Eric  staff  668 Feb 26 11:32 /Users/Eric/.ssh/id_dsa
-rw-r--r--  1 Eric  staff  611 Feb 26 11:32 /Users/Eric/.ssh/id_dsa.pub

SCP the public key file (id_dsa.pub) to the computer that will receive the files, referred to as "remote".

# NOTE: you'll need to replace "Eric@remote" with your remote username and IP address
local$ scp ~/.ssh/id_dsa.pub Eric@remote:~/.ssh/id_dsa.pub.transferred

SSH to the remote system and execute a few commands to enable passwordless SSH

$ SSH to remote system
local$ ssh Eric@remote

# append public key to "authorized_keys"
remote$ cat ~/.ssh/id_dsa.pub.transferred >> ~/.ssh/authorized_keys

# remove obsolete public key
remote$ rm ~/.ssh/id_dsa.pub.transferred

# exit remote system
remote$ exit

To verify that the public/private keys are working, SSH to the remote system. You should not be prompted for a password this time.

Part Two
The second step of this tutorial is creating an executable shell script that will transfer the files. I chose to put my scripts in the folder "~/scripts/", but you could put them anywhere you want.

Open up your favorite text editor (emacs, vi, nano, etc) and enter your rsync command.

#!/bin/bash
rsync -avz --delete /path/on/local/computer/ Eric@remote:/path/on/remote/computer/

Please note, the "--delete" flag is optional, and will remove files on the remote computer that do not exist on the local computer. Please use caution.

For my real life example, I setup a script to rsync my iTunes library from my iMac to my MacBookPro.

#!/bin/bash
rsync -avz --delete --exclude '*.m4v' --exclude '*.mp4' ~/Music/iTunes/ Eric@remote:~/Music/iTunes/

After saving the script, set it to be executable using chmod.

local$ chmod u+x /path/to/local/rsync.script.sh

Test your script on the command line, and then SSH to the remote computer to verify the copied files.

local$ /path/to/local/rsync.script.sh

If all is working well, you can setup a cron job to run at your desired time interval. Remember, both computers must be running for this to be automated, so choose a time you know they'll both be on. For example, to run this script daily..

local$ crontab -e

# min hour dayMonth month dayWeek command
0 0 * * * /path/to/local/rsync.script.sh

Eric.London's picture

Here is how you can password protect a directory using htpasswd and .htaccess files:

mkdir /path/to/new/directory/YOURNEWDIRECTORY
cd /path/to/new/directory/YOURNEWDIRECTORY
htpasswd -c .htpasswd YOURUSER

Next, edit/create an .htaccess file in the same directory containing:
AuthUserFile /path/to/new/directory/YOURNEWDIRECTORY/.htpasswd
AuthType Basic
AuthName "YOURDESCRIPTION"
Require valid-user

NOTE: A absolute path is required for the AuthUserFile directive.

Here is the code I used to add a password strength meter to the user edit form.

First, I added a menu item that will be used by AJAX to process the user's password. The path will be used like this: http://MYWEBSITE/passwordStrength/USERPASSWORD. As you can see in the callback arguments, the remainder of the query string after the first "/" is passed into the callback function.

<?php
function MYMODULE_menu() {
 
$items = array();
 
// ...code...
 
$items[] = array(
   
'path' => 'passwordStrength',
   
'callback' => 'MYMODULE_passwordStrength',
   
'type' => MENU_CALLBACK,
   
'access' => TRUE,
   
'callback arguments' => array(array_pop(explode("/",$_REQUEST['q'],2))),
  );
 
// ...code...
 
return $items;
}
?>

Here's the callback function. It returns an integer to the screen with no theming.

<?php
function patient_portal_callback_passwordStrength($password) {
   
 
// NOTE: "SSL: Fatal Protocol Error" occurring
  // echo file_get_contents('https://www.google.com/accounts/RatePassword?Passwd=' . $password);
   
  // NOTE: google will return 1-4

  // check for invalid password
 
if (strlen($password)==0 || !$password) {
    echo
1;
    die;   
  }
   
 
// using CURL to fetch website result
 
$ch = curl_init();
 
curl_setopt($ch, CURLOPT_URL, 'https://www.google.com/accounts/RatePassword?Passwd=' . urlencode($password));
 
curl_exec($ch);   
 
curl_closE($ch);
   
  die;

}
?>

The next part is modifying the user edit form using the form_alter hook.

<?php
function MYMODULE_form_alter($form_id, &$form) {
 
// ...code...
 
if ($form_id == 'user_edit') {

   
// add weights to current account form elements
   
if (isset($form['account']['name'])) $form['account']['name']['#weight'] = 1;
    if (isset(
$form['account']['mail'])) $form['account']['mail']['#weight'] = 2;
    if (isset(
$form['account']['pass'])) $form['account']['pass']['#weight'] = 3;
    if (isset(
$form['account']['status'])) $form['account']['status']['#weight'] = 5;
    if (isset(
$form['account']['roles'])) $form['account']['roles']['#weight'] = 6;
       
   
// create html for password meter
   
$passwordMeterHtml = "
      <div id='passwordMeterFormItem' class='form-item'>
        <label>
          <span id='passwordStrengthLabel'>Password Strength:</span>
          <span id='passwordStrengthDescription'></span>
        </label>
        <table id='passwordMeter'>
          <tr>
            <td id='barLeft'></td>
            <td id='barRight'></td>
          </tr>
        </table>
      </div>
    "
;
       
   
// add form "element"
   
$form['account']['passwordMeter'] = array(
     
'#value' => $passwordMeterHtml,
     
'#weight' => 4,
    );
       
   
// add js to password input
   
$js = "
      $(document).ready(function(){
        $('form#user-edit #edit-pass-pass1').keyup(function(e){
                   
          if (this.value.length) {
            $.ajax({
              type: 'GET',
              url: '/passwordStrength/' + this.value,
              success: function(passwordCode){
                switch (passwordCode) {
                  case '1':
                    word = 'Weak';
                    break;
                  case '2':
                    word = 'Fair';
                    break;
                  case '3':
                    word = 'Good';
                    break;
                  case '4':
                    word = 'Strong';
                    break;
                }
   
                // remove td classes
                $('table#passwordMeter td#barLeft').removeClass();
                $('table#passwordMeter td#barRight').removeClass();
                               
                // add td classes
                $('table#passwordMeter td#barLeft').addClass(word);
                $('table#passwordMeter td#barRight').addClass(word);

                // set description
                $('span#passwordStrengthDescription').html(word);
                $('span#passwordStrengthDescription').removeClass();
                $('span#passwordStrengthDescription').addClass(word);
              }
            });                   
          } else {
            // remove td classes
            $('table#passwordMeter td#barLeft').removeClass();
            $('table#passwordMeter td#barRight').removeClass();
                       
            // set description
            $('span#passwordStrengthDescription').html('');
            $('span#passwordStrengthDescription').removeClass();
          }
        });
      });
    "
;
   
drupal_add_js($js, 'inline');

  }
 
// ...code...
}
?>

Lastly, I added some CSS

div#passwordMeterFormItem {
  width: 210px;
}

table#passwordMeter {
  width: 100%;
  height: 10px;
  margin: 0;
  clear: both;
}

span#passwordStrengthLabel {
  float: left;
}

table#passwordMeter tbody, table#passwordMeter tr {
  border: none;
}

table#passwordMeter td {
  padding: 0;
  height: 10px;
}

table#passwordMeter td#barLeft {
  background-color: #e0e0e0;
  width: 0%;
}

table#passwordMeter td#barRight {
  background-color: #e0e0e0;
  width: 100%;
}

table#passwordMeter td#barLeft.Weak {
  width: 25%;
  background-color: #AA0033;
}

table#passwordMeter td#barRight.Weak {
  width: 75%;
}

table#passwordMeter td#barLeft.Fair {
  width: 50%;
  background-color: #FFCC33;
}

table#passwordMeter td#barRight.Fair {
  width: 50%;
}

table#passwordMeter td#barLeft.Good {
  width: 75%;
  background-color: #6699CC;
}

table#passwordMeter td#barRight.Good {
  width: 25%;
}

table#passwordMeter td#barLeft.Strong {
  width: 100%;
  background-color: #008000;
}

table#passwordMeter td#barRight.Strong {
  width: 0%;
}

span#passwordStrengthDescription {
  display: block;
  float: right;
}

span#passwordStrengthDescription.Weak {
  color: #AA0033;
}

span#passwordStrengthDescription.Fair {
  color: #FFCC33;
}

span#passwordStrengthDescription.Good {
  color: #6699CC;
}

span#passwordStrengthDescription.Strong {
  color: #008000;
}

Here's a screen shot...

Eric.London's picture

Here is a script I wrote to generate passwords...

<?php
function passwordCreate($length = 8) {
  if (
$length>62 || $length<1) $length = 8;
 
$chars = array();
  for (
$i=0; $i<$length; $i++) {
    do {
     
$r = rand(48, 122);
    }
    while ((
$r>57 && $r<65) || ($r>90 && $r<97) || in_array(chr($r),$chars));
     
$chars[] = chr($r);
  }   
  return
implode('', $chars);
}
?>

Syndicate content