--- /HTPasswdSync.module	Ïò ìàð 27 01:15:29 2009
+++ /HTPasswdSync.module	Âñ àïð 19 19:40:50 2009
@@ -1,447 +1,437 @@
-<?php
-// $Id: HTPasswdSync.module,v 1.1.2.2 2009/03/26 22:15:29 mfu Exp $
-/*
- * $Log: HTPasswdSync.module,v $
- * Revision 1.1.2.2  2009/03/26 22:15:29  mfu
- * Added #408798 by fasdalf@fasdalf.ru : request for windows support
- *   windows does not support crypt password hash
- *   added support for SHA-1 password hash which is supported by windows.
- * Fixed : group file not allways updated.
- *
- * Revision 1.1.2.1  2009/03/25 19:24:10  mfu
- * Fixed #409406 by fasdalf@fasdalf.ru : remove comma in htgroup file
- *
- * 
- */  
-
-/* @file
- * Synchronize users password and htpasswd file
- * 
- * HTPasswd Sync module duplicates all users changes in the configured htpasswd
- * file. Password a hashed with the crypt function. The htgroup file contains 
- * roles as groups. 
- */     
- 
- /**
-  * return htpasswd file name
-  *     
-  * @return
-  *   full filname of the htpasswd
-  */
- function _htpasswdsync_passfilename() {
-    return variable_get('htpasswdsync_htpasswd', "/etc/httpd/htpasswd");
- }
- 
- /**
-  * return htgroup file name
-  *     
-  * @return
-  *   full filname of the htgroup file
-  */
- function _htpasswdsync_grpfilename() {
-    return variable_get('htpasswdsync_htgroup', "/etc/httpd/htgroup");
- }
- 
- /**
-  * return role to put in htgroup
-  * 
-  * return the roles selectionned in the admin page to put into
-  * the htgroup file.
-  *       
-  * @return
-  *   array of role id
-  */
- function _htpasswdsync_roles() {
-    return variable_get('htpasswdsync_roles', array());
- }
-
-
- /**
-  * return array of available hashes
-  * 
-  * return an array of possible hashes
-  *       
-  * @return
-  *   array
-  */
- function _htpasswdsync_hashes() {
-    return array ('crypt', 'SHA-1');
- }
-  
- /**
-  * return hash algorithm name
-  * 
-  * return the name of the hash algorithm to use for password
-  * hashing  
-  *       
-  * @return
-  *   string ('crypt', 'SHA-1')
-  */
- function _htpasswdsync_hash() {
-    return variable_get('htpasswdsync_hash', 0);
- }
-  
- /**
-  * crypt password
-  * 
-  * return the password hashed according to users preferences
-  *       
-  * @param $password
-  *   the password, as a string,  to encrypt     
-  * @return
-  *   encrpyted password (actually hashed)
-  */
- function _htpasswdsync_crypt($password) {
-  $hashes = _htpasswdsync_hashes();
-  switch ($hashes[_htpasswdsync_hash()]) {
-    case 'crypt':
-      return crypt($password, chr(rand(65, 122)) . chr(rand(65, 122)));
-    break;
-    case 'SHA-1':
-      return '{SHA}' . base64_encode(sha1($password, TRUE));
-    break;
-  }
-  return _htpasswdsync_hash();
-}
- 
-/**
- * read an htfile
- *     
- * read an htfile, format is key: value, one key per row
- * 
- * @param &$arr
- *   array to read to
- * @param $file
- *   file to read
- * @return
- *   none 
- */
-
- function _htpasswdsync_read_htfile(&$arr, $file) {
-   $f = fopen($file, "r");
-   while ($l = fgets($f)) {
-     list($u, $p) = split(":", rtrim($l), 2);
-     if ($u != "") {
-       $arr[$u] = $p;
-     }
-   }
-   fclose($f);
- }
- 
- /**
- * write an htfile
- *     
- * write an array to an htfile, format is key: value, one key per row
- * 
- * @param &$arr
- *   array to write
- * @param $file
- *   file to write to
- * @return
- *   none 
- */
- function _htpasswdsync_write_htfile(&$arr, $file) {
-  $f = fopen($file, "w");
-  foreach ($arr as $u => $p) {
-    if ($u != "" && $p != "") {
-      fputs($f, $u .":". $p ."\n");
-    }
-  }
-  fclose($f);
- }
- 
-/* generate the htgroup content
- *
- * for each role configured (htpasswdsync_roles array), list users
- * and update the htgroup accordingly
- * 
- * @param
- * @return   
- */    
- function _htpasswdsync_updategroup() {
-  
-  $file = _htpasswdsync_grpfilename();
-  $groups = array();
-  _htpasswdsync_read_htfile($groups, $file);
-  
-  foreach (_htpasswdsync_roles() as $rid) {
-    // get role name
-    $res = db_fetch_object(db_query('SELECT name FROM {role} WHERE rid = %d', $rid));
-    $name = $res->name;
-    
-    //empty group
-    $groups[$name] = "";
-    
-    // add members to the group
-    $res = db_query('SELECT name FROM {users} u, {users_roles} ur WHERE ur.rid = %d AND ur.uid = u.uid', $rid);
-    while ($r = db_fetch_object($res)) {
-      $groups[$name] .= " ". $r->name;
-    }
-
-  } _htpasswdsync_write_htfile($groups, $file);
- }
-
-/* generate the htpasswd content from the database
- *
- * update the htpasswd file from the table htpasswdsync_passwd
- * 
- * @param
- * @return   
- */    
- function _htpasswdsync_updatepasswd() {
-  
-  $file = _htpasswdsync_passfilename();
-  $passwords = array();
-  _htpasswdsync_read_htfile($passwords, $file);
-
-  //get all users  
-  $res = db_query('SELECT username, passwd FROM {htpasswdsync_passwd}');
-  while ($r = db_fetch_object($res)) {
-    if ($r->passwd == "****DELETED") {
-      unset($passwords[$r->username]);
-    }
-    else {
-      $passwords[$r->username] = $r->passwd; 
-    }
-  }
-  _htpasswdsync_write_htfile($passwords, $file);
- }
-
- 
-/* update htpassword with the new password of the user
- *
- * @param $account
- *   account of the user to update 
- * @return   
- */    
- function _htpasswdsync_update($account) {
-  
-  // read current file
-  $f = _htpasswdsync_passfilename();
-  $passwds = array();
-  _htpasswdsync_read_htfile($passwds, $f);
-  
-  // update with the $account information received
-  // password crypted with the standard crypt (not MD5) function
-  $user = $account['name'];
-  $pass = _htpasswdsync_crypt($account['pass']);
-  $passwds[$user] = $pass;
-  
-  //save file
-  _htpasswdsync_write_htfile($passwds, $f);
-  
-  //update table
-  db_query("DELETE FROM {htpasswdsync_passwd} WHERE username = '%s'", $user);
-  db_query("INSERT INTO {htpasswdsync_passwd} (username, passwd) VALUES('%s', '%s')", $user, $pass);
-  _htpasswdsync_updategroup();
-}
- 
-/* remove the user for the htpassword file
- *
- * @param $account
- *   array of account to delete 
- * @return   
- */    
-function _htpasswdsync_delete($account) {
-  $f = _htpasswdsync_passfilename();
-  $passwds = array();
-  _htpasswdsync_read_htfile($passwds, $f);
-
-  foreach ($account['accounts'] as $a) {
-    $r = db_query("SELECT name FROM {users} WHERE uid = %d", $a);
-    $user = db_fetch_object($r);
-    unset($passwds[$user->name]);
-    db_query("DELETE FROM {htpasswdsync_passwd} WHERE username = '%s'", $user->name);
-    db_query("INSERT INTO {htpasswdsync_passwd} (username, passwd) VALUES('%s', '%s')", $user->name, "****DELETED");
-  }
-  _htpasswdsync_write_htfile($passwds, $f);
-  
-  _htpasswdsync_updategroup();
- }
-
- /**
-* Display help and module information
-* @param path which path of the site we're displaying help
-* @param arg array that holds the current path as would be returned from arg() function
-* @return help text for the path
-*/
-function htpasswdsync_help($path, $arg) {
-  $output = '';  //declare your output variable
-  switch ($path) {
-    case "admin/help#htpasswdsync":
-      $output = '<p>'.  t("synchronize password with a htpasswd file") .'</p>';
-      break;
-  }
-  return $output;
-} // function htpasswdsync_help
-
-/**
-* Valid permissions for this module
-* @return array An array of valid permissions for the htpasswdsync module
-*/
-function htpasswdsync_perm() {
-  return array('administer htpasswdsync');
-} // function htpasswdsync_perm()
-
-/*
- * Implementation of hook_user()
- */  
-function htpasswdsync_user($op, &$edit, &$account, $category = NULL) {
-  switch ($op) {
-    case "delete": 
-      _htpasswdsync_delete($edit);
-    break;
-    case "insert": 
-      _htpasswdsync_update($edit);
-    break;
-    case "update": 
-      _htpasswdsync_update($edit);
-    break;
-  }
-} // function htpasswdsync_user()
-
-
-function htpasswdsync_admin() {
-
-  $form['htpasswdsync_htpasswd'] = array(
-    '#type' => 'textfield',
-    '#title' => t('htpasswd file'),
-    '#default_value' => _htpasswdsync_passfilename(),
-    '#size' => 100,
-    '#maxlength' => 200,
-    '#description' => t("Where is stored the !file file we want to synchronize with.",
-          array('!file' => 'htpasswd')),
-    '#required' => TRUE,
-  );
-  $form['htpasswdsync_htgroup'] = array(
-    '#type' => 'textfield',
-    '#title' => t('htgroup file'),
-    '#default_value' => _htpasswdsync_grpfilename(),
-    '#size' => 100,
-    '#maxlength' => 200,
-    '#description' => t("Where is stored the !file file we want to synchronize with.",
-          array('!file' => 'htgroup')),
-    '#required' => TRUE,
-  );
-  $form['htpasswdsync_hash'] = array(
-    '#type' => 'radios',
-    '#title' => t('password hashing algorythm'),
-    '#description' => t("How shall the password be hashed (crypt for unix, SHA1 for all)"),
-    '#options' => _htpasswdsync_hashes(),    
-    '#default_value' => _htpasswdsync_hash(),
-  );
-   $form['htpasswdsync_roles'] = array(
-    '#type' => 'checkboxes',
-    '#title' => t('Roles to be exported in htgroup'),
-    '#default_value' => _htpasswdsync_roles(),
-    '#options' => user_roles(TRUE),
-  );
- 
-  return system_settings_form($form);
-}
-
-
-/* Test if a file exist and is writable
- *
- * @param $filename
- *   name of the file
- * @return
- *   return false on success, otherwise an error message
- */
-function _htpasswdsync_check_file($file) {
-  $f = @fopen($file, "r");
-  if (!$f) {
-    return t("File '!file' does not exists, you should create it.",
-      array('!file' => $file));
-  }
-  else {
-    fclose($f);
-    $f = @fopen($file, "a");
-    if (!$f) {
-      return t("cannot write to file '!file'.", array('!file' => $file));
-    }
-    else {
-      fclose($f);
-    }
-  } 
-  return FALSE;
-}
-
-function htpasswdsync_admin_validate($form, &$form_state) {
-
-  $file = $form_state['values']['htpasswdsync_htpasswd'];
-  if ($msg = _htpasswdsync_check_file($file)) {
-    form_set_error('htpasswdsync_htpasswd', $msg);
-  }
-
-  $file = $form_state['values']['htpasswdsync_htgroup'];
-  if ($msg = _htpasswdsync_check_file($file)) {
-    form_set_error('htpasswdsync_htpasswd', $msg);
-  }
-}
-
-function htpasswdsync_menu() {
-
-  $items = array();
-
-  $items['admin/user/htpasswdsync'] = array(
-    'title' => 'HTPassword Sync',
-    'description' => 'Preferences for the HTPasswd Sync module',
-    'page callback' => 'drupal_get_form',
-    'page arguments' => array('htpasswdsync_admin'),
-    'access arguments' => array('access administration pages'),
-    'type' => MENU_NORMAL_ITEM,
-   );
-
-  return $items;
-}
-
-function htpasswdsync_requirements($phase) {
-
-  $requirements = array();
-
-  // if not runtime query, exit
-  if ($phase != 'runtime') {
-    return $requirements;
-  }
-  
-  $htpasswd_status_msg = _htpasswdsync_check_file(_htpasswdsync_passfilename());
-  $htpasswd_status_val = REQUIREMENT_ERROR;
-  if (!$htpasswd_status_msg) {
-    $htpasswd_status_msg = t('!file file is available', array('!file' => 'htpasswd'));
-    $htpasswd_status_val = REQUIREMENT_OK;
-  }
-
-  $htgroup_status_msg = _htpasswdsync_check_file(_htpasswdsync_grpfilename());
-  $htgroup_status_val = REQUIREMENT_ERROR;
-  if (!$htgroup_status_msg) {
-    $htgroup_status_msg = t('!file file is available', array('!file' => 'htgroup'));
-    $htgroup_status_val = REQUIREMENT_OK;
-  }
-  
-  $status = $htpasswd_status_val > $htgroup_status_val ?
-    $htpasswd_status_val : $htgroup_status_val;
-
-  $requirements['htpasswdsync_status'] = array(
-    'title'       => t('HTPasswd Sync Status'),
-    'value'       => $htpasswd_status_msg ."<br>". 
-                     $htgroup_status_msg ."<br>".
-                     t('last update !time ago.', array(
-                        '!time' => format_interval(time()-variable_get('htpasswdsync_cron_time', 0)))),
-    'severity'    => $status,
-    );
-  if ($status != REQUIREMENT_OK) {
-    $requirements['htpasswdsync_status']['description'] =
-      t('Cannot access files, please <a href="!url">check configuration</a>.',
-         array('!url' => url('admin/user/htpasswdsync')));
-  }
-
-  return $requirements;
-}
-
-function htpasswdsync_cron() {
-  $time = variable_get('htpasswdsync_cron_time', 0);
-  _htpasswdsync_updatepasswd();
-  _htpasswdsync_updategroup();
-  variable_set('htpasswdsync_cron_time', time());
-}
+<?php
+// $Id: HTPasswdSync.module,v 1.1.2.2 2009/03/26 22:15:29 mfu Exp $
+/*
+ * $Log: HTPasswdSync.module,v $
+ * Revision 1.1.2.2  2009/03/26 22:15:29  mfu
+ * Added #408798 by fasdalf@fasdalf.ru : request for windows support
+ *   windows does not support crypt password hash
+ *   added support for SHA-1 password hash which is supported by windows.
+ * Fixed : group file not allways updated.
+ *
+ * Revision 1.1.2.1  2009/03/25 19:24:10  mfu
+ * Fixed #409406 by fasdalf@fasdalf.ru : remove comma in htgroup file
+ *
+ * 
+ */  
+
+/* @file
+ * Synchronize users password and htpasswd file
+ * 
+ * HTPasswd Sync module duplicates all users changes in the configured htpasswd
+ * file. Password a hashed with the crypt function. The htgroup file contains 
+ * roles as groups. 
+ */     
+ 
+ /**
+  * return htpasswd file name
+  *     
+  * @return
+  *   full filname of the htpasswd
+  */
+ function _htpasswdsync_passfilename() {
+    return variable_get('htpasswdsync_htpasswd', "/etc/httpd/htpasswd");
+ }
+ 
+ /**
+  * return htgroup file name
+  *     
+  * @return
+  *   full filname of the htgroup file
+  */
+ function _htpasswdsync_grpfilename() {
+    return variable_get('htpasswdsync_htgroup', "/etc/httpd/htgroup");
+ }
+ 
+ /**
+  * return role to put in htgroup
+  * 
+  * return the roles selectionned in the admin page to put into
+  * the htgroup file.
+  *       
+  * @return
+  *   array of role id
+  */
+ function _htpasswdsync_roles() {
+    return variable_get('htpasswdsync_roles', array());
+ }
+
+
+ /**
+  * return array of available hashes
+  * 
+  * return an array of possible hashes
+  *       
+  * @return
+  *   array
+  */
+ function _htpasswdsync_hashes() {
+    return array ('crypt', 'SHA-1');
+ }
+  
+ /**
+  * return hash algorithm name
+  * 
+  * return the name of the hash algorithm to use for password
+  * hashing  
+  *       
+  * @return
+  *   string ('crypt', 'SHA-1')
+  */
+ function _htpasswdsync_hash() {
+    return variable_get('htpasswdsync_hash', 0);
+ }
+  
+ /**
+  * crypt password
+  * 
+  * return the password hashed according to users preferences
+  *       
+  * @param $password
+  *   the password, as a string,  to encrypt     
+  * @return
+  *   encrpyted password (actually hashed)
+  */
+ function _htpasswdsync_crypt($password) {
+  $hashes = _htpasswdsync_hashes();
+  switch ($hashes[_htpasswdsync_hash()]) {
+    case 'crypt':
+      return crypt($password, chr(rand(65, 122)) . chr(rand(65, 122)));
+    break;
+    case 'SHA-1':
+	  return '{SHA}' . base64_encode(sha1($password, TRUE));
+    break;
+  }
+  return _htpasswdsync_hash();
+}
+ 
+/**
+ * read an htfile
+ *     
+ * read an htfile, format is key: value, one key per row
+ * 
+ * @param &$arr
+ *   array to read to
+ * @param $file
+ *   file to read
+ * @return
+ *   none 
+ */
+
+ function _htpasswdsync_read_htfile(&$arr, $file) {
+   $f = fopen($file, "r");
+   while ($l = fgets($f)) {
+     list($u, $p) = split(":", rtrim($l), 2);
+     if ($u != "") {
+       $arr[$u] = $p;
+     }
+   }
+   fclose($f);
+ }
+ 
+ /**
+ * write an htfile
+ *     
+ * write an array to an htfile, format is key: value, one key per row
+ * 
+ * @param &$arr
+ *   array to write
+ * @param $file
+ *   file to write to
+ * @return
+ *   none 
+ */
+ function _htpasswdsync_write_htfile(&$arr, $file) {
+  $f = fopen($file, "w");
+  foreach ($arr as $u => $p) {
+    if ($u != "" && $p != "") {
+      fputs($f, $u .":". $p ."\n");
+    }
+  }
+  fclose($f);
+ }
+ 
+/* generate the htgroup content
+ *
+ * for each role configured (htpasswdsync_roles array), list users
+ * and update the htgroup accordingly
+ * 
+ * @param
+ * @return   
+ */    
+ function _htpasswdsync_updategroup() {
+  
+  $file = _htpasswdsync_grpfilename();
+  $groups = array();
+  _htpasswdsync_read_htfile($groups, $file);
+  
+  foreach (_htpasswdsync_roles() as $rid) {
+    // get role name
+    $res = db_fetch_object(db_query('SELECT name FROM {role} WHERE rid = %d', $rid));
+    $name = $res->name;
+    
+    //empty group
+    $groups[$name] = "";
+    
+    // add members to the group
+    $res = db_query('SELECT name FROM {users} u, {users_roles} ur WHERE ur.rid = %d AND ur.uid = u.uid', $rid);
+    while ($r = db_fetch_object($res)) {
+      $groups[$name] .= " ". $r->name;
+    }
+
+  } _htpasswdsync_write_htfile($groups, $file);
+ }
+
+/* generate the htpasswd content from the database
+ *
+ * update the htpasswd file from the table htpasswdsync_passwd
+ * 
+ * @param
+ * @return   
+ */    
+ function _htpasswdsync_updatepasswd() {
+  $file = _htpasswdsync_passfilename();
+  $passwords = array();
+  
+  //get all users  
+  $res = db_query('SELECT username, passwd FROM {htpasswdsync_passwd}');
+  while ($r = db_fetch_object($res)) {
+
+	  $passwords[$r->username] = $r->passwd; 
+  }
+  _htpasswdsync_write_htfile($passwords, $file);
+ }// function _htpasswdsync_updatepasswd
+
+ 
+/* update htpassword with the new password of the user
+ *
+ * @param $account
+ *   account of the user to update 
+ * @return   
+ */    
+ function _htpasswdsync_update($account) {
+  
+  // read current file
+  $f = _htpasswdsync_passfilename();
+  $passwds = array();
+  _htpasswdsync_read_htfile($passwds, $f);
+  
+  // update with the $account information received
+  // password crypted with the standard crypt (not MD5) function
+  $user = $account['name'];
+  $pass = _htpasswdsync_crypt($account['pass']);
+  $passwds[$user] = $pass;
+  
+  //save file
+  _htpasswdsync_write_htfile($passwds, $f);
+  
+  //update table
+  db_query("DELETE FROM {htpasswdsync_passwd} WHERE username = '%s'", $user);
+  db_query("INSERT INTO {htpasswdsync_passwd} (username, passwd) VALUES('%s', '%s')", $user, $pass);
+  _htpasswdsync_updategroup($account);
+}
+ 
+/* remove the user for the htpassword file
+ *
+ * @param $account
+ *   array of account to delete 
+ * @return   
+ */    
+function _htpasswdsync_delete($account) {
+  $f = _htpasswdsync_passfilename();
+  $passwds = array();
+  _htpasswdsync_read_htfile($passwds, $f);
+	// FASDALF 's change for single user deletion
+    unset($passwds[$account->name]);
+    db_query("DELETE FROM {htpasswdsync_passwd} WHERE username = '%s'", $account->name);
+
+  _htpasswdsync_write_htfile($passwds, $f);
+
+  _htpasswdsync_updategroup();
+ }// function _htpasswdsync_delete
+
+ /**
+* Display help and module information
+* @param path which path of the site we're displaying help
+* @param arg array that holds the current path as would be returned from arg() function
+* @return help text for the path
+*/
+function htpasswdsync_help($path, $arg) {
+  $output = '';  //declare your output variable
+  switch ($path) {
+    case "admin/help#htpasswdsync":
+      $output = '<p>'.  t("synchronize password with a htpasswd file") .'</p>';
+      break;
+  }
+  return $output;
+} // function htpasswdsync_help
+
+/**
+* Valid permissions for this module
+* @return array An array of valid permissions for the htpasswdsync module
+*/
+function htpasswdsync_perm() {
+  return array('administer htpasswdsync');
+} // function htpasswdsync_perm()
+
+/*
+ * Implementation of hook_user()
+ */  
+function htpasswdsync_user($op, &$edit, &$account, $category = NULL) {
+  switch ($op) {
+    case "delete": 
+      _htpasswdsync_delete($account);
+      break;
+    case "insert": 
+      _htpasswdsync_update($edit);
+      break;
+    case "update": 
+      _htpasswdsync_update($edit);
+      break;
+  }
+} // function htpasswdsync_user()
+
+
+function htpasswdsync_admin() {
+
+  $form['htpasswdsync_htpasswd'] = array(
+    '#type' => 'textfield',
+    '#title' => t('htpasswd file'),
+    '#default_value' => _htpasswdsync_passfilename(),
+    '#size' => 100,
+    '#maxlength' => 200,
+    '#description' => t("Where is stored the !file file we want to synchronize with.",
+          array('!file' => 'htpasswd')),
+    '#required' => TRUE,
+  );
+  $form['htpasswdsync_htgroup'] = array(
+    '#type' => 'textfield',
+    '#title' => t('htgroup file'),
+    '#default_value' => _htpasswdsync_grpfilename(),
+    '#size' => 100,
+    '#maxlength' => 200,
+    '#description' => t("Where is stored the !file file we want to synchronize with.",
+          array('!file' => 'htgroup')),
+    '#required' => TRUE,
+  );
+  $form['htpasswdsync_hash'] = array(
+    '#type' => 'radios',
+    '#title' => t('password hashing algorythm'),
+    '#description' => t("How shall the password be hashed (crypt for unix, SHA1 for all)"),
+    '#options' => _htpasswdsync_hashes(),    
+    '#default_value' => _htpasswdsync_hash(),
+  );
+   $form['htpasswdsync_roles'] = array(
+    '#type' => 'checkboxes',
+    '#title' => t('Roles to be exported in htgroup'),
+    '#default_value' => _htpasswdsync_roles(),
+    '#options' => user_roles(TRUE),
+  );
+ 
+  return system_settings_form($form);
+}
+
+
+/* Test if a file exist and is writable
+ *
+ * @param $filename
+ *   name of the file
+ * @return
+ *   return false on success, otherwise an error message
+ */
+function _htpasswdsync_check_file($file) {
+  $f = @fopen($file, "r");
+  if (!$f) {
+    return t("File '!file' does not exists, you should create it.",
+      array('!file' => $file));
+  }
+  else {
+    fclose($f);
+    $f = @fopen($file, "a");
+    if (!$f) {
+      return t("cannot write to file '!file'.", array('!file' => $file));
+    }
+    else {
+      fclose($f);
+    }
+  } 
+  return FALSE;
+}
+
+function htpasswdsync_admin_validate($form, &$form_state) {
+
+  $file = $form_state['values']['htpasswdsync_htpasswd'];
+  if ($msg = _htpasswdsync_check_file($file)) {
+    form_set_error('htpasswdsync_htpasswd', $msg);
+  }
+
+  $file = $form_state['values']['htpasswdsync_htgroup'];
+  if ($msg = _htpasswdsync_check_file($file)) {
+    form_set_error('htpasswdsync_htpasswd', $msg);
+  }
+}
+
+function htpasswdsync_menu() {
+
+  $items = array();
+
+  $items['admin/user/htpasswdsync'] = array(
+    'title' => 'HTPassword Sync',
+    'description' => 'Preferences for the HTPasswd Sync module',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('htpasswdsync_admin'),
+    'access arguments' => array('access administration pages'),
+    'type' => MENU_NORMAL_ITEM,
+   );
+
+  return $items;
+}
+
+function htpasswdsync_requirements($phase) {
+
+  $requirements = array();
+
+  // if not runtime query, exit
+  if ($phase != 'runtime') {
+    return $requirements;
+  }
+  
+  $htpasswd_status_msg = _htpasswdsync_check_file(_htpasswdsync_passfilename());
+  $htpasswd_status_val = REQUIREMENT_ERROR;
+  if (!$htpasswd_status_msg) {
+    $htpasswd_status_msg = t('!file file is available', array('!file' => 'htpasswd'));
+    $htpasswd_status_val = REQUIREMENT_OK;
+  }
+
+  $htgroup_status_msg = _htpasswdsync_check_file(_htpasswdsync_grpfilename());
+  $htgroup_status_val = REQUIREMENT_ERROR;
+  if (!$htgroup_status_msg) {
+    $htgroup_status_msg = t('!file file is available', array('!file' => 'htgroup'));
+    $htgroup_status_val = REQUIREMENT_OK;
+  }
+  
+  $status = $htpasswd_status_val > $htgroup_status_val ?
+    $htpasswd_status_val : $htgroup_status_val;
+
+  $requirements['htpasswdsync_status'] = array(
+    'title'       => t('HTPasswd Sync Status'),
+    'value'       => $htpasswd_status_msg ."<br>". 
+                     $htgroup_status_msg ."<br>".
+                     t('last update !time ago.', array(
+                        '!time' => format_interval(time()-variable_get('htpasswdsync_cron_time', 0)))),
+    'severity'    => $status,
+    );
+  if ($status != REQUIREMENT_OK) {
+    $requirements['htpasswdsync_status']['description'] =
+      t('Cannot access files, please <a href="!url">check configuration</a>.',
+         array('!url' => url('admin/user/htpasswdsync')));
+  }
+
+  return $requirements;
+}
+
+function htpasswdsync_cron() {
+  $time = variable_get('htpasswdsync_cron_time', 0);
+  _htpasswdsync_updatepasswd();
+  _htpasswdsync_updategroup();
+  variable_set('htpasswdsync_cron_time', time());
+}
