Automatically download log files through FTP

Schedule a cron command that looks like this:

wget ftp://username:password@ftp_host/file_to_download

Can also specify file name masks: (in my case I want all .gz log files)

wget ftp://username:password@ftp_host/logs/*.gz

Ultimate website launch checklist

http://www.boxuk.com/blog/the-ultimate-website-launch-checklist

Uncaught SoapFault exception / Invalid parameters Error

I am using nusoap library to connect to Kintera API.  It worked fine on my other sites, but this one was giving me the following error message:

Fatal error: Uncaught SoapFault exception: [Client] SoapClient::SoapClient() [<a href=’soapclient.soapclient’>soapclient.soapclient</a>]: Invalid parameters in /test.php:147 Stack trace: #0 /test.php(147): SoapClient->SoapClient(’KinteraConnect….’, true) #1 {main} thrown in /test.php on line 147

Line 147 has the following code:

$client = new soapclient($wsdl,true);

After reading up online a bit, it seems this error appears on PHP 5 servers because of class name conflicts. So I opened up nusoap.php file and figured that you could just use nusoap_client as a class name. Code piece from nusoap.php

if (!extension_loaded('soap')) {

/***    For backwards compatiblity, define soapclient unless the PHP SOAP extension is loaded.*/

class soapclient extends nusoap_client {

}

}

So I just went ahead and changed

$client = new soapclient($wsdl,true);

to

$client = new nusoap_client($wsdl,true);

and it fixed it.

Code colorizers, code highlighters

http://www.smashingmagazine.com/2007/07/12/time-savers-code-beautifier-and-formatter/

Modifying Drupal download_count module to show files per user

Task:

  1. allow file downloads for only registered users in Drupal
  2. for admins, show download count for each file
  3. show which user downloaded which files

The download_count module is great for #1 and #2. However, it doesn’t save any information about users.

Here’s some modifications I’ve added to it to accomplish #3.

In the download_count.module file, find download_count_file_download() function. It saves the information about downloaded files into “file_downloads” table.

  • I created another similar table, called it “file_download_users” (columns: filename, user_id, timestamp) where I am going to save information about each download and keep user IDs.
  • Made sure I use global $user in this function
  • Insert the information about users into my new table:

db_query(”INSERT INTO {file_downloads_users} (filename, user_id, timestamp) VALUES (’%s’, %d,%d)”, $filename, $user->uid, time());

Now I write my own hook_user function:

<?php/**

 * Implementation of hook_user()

 */



function download_count_user($op, &$edit, &$account, $caterory = NULL) {

  if ($op == ‘view’) 

  {

   

   $result = db_query(“SELECT filename FROM file_downloads_users WHERE user_id = %d”, $account->uid);



   while ($file_array = db_fetch_object($result)) {

      $file_str .= $file_array->filename . ‘<br/>’;

   }

     $account->content[’summary’][‘file_downloads’] =  array(

      ‘#type’ => ‘user_profile_item’,

      ‘#title’ => t(‘File Downloads’),

      ‘#value’ => $file_str,

      ‘#weight’ => 1

    );

        

  }

  

}

?>

The above is Drupal 6 version. First I wrote one for Drupal 5 and it just didn’t work for me, until some nice fellow from StackOverflow pointed out the difference between 5 and 6 when it comes to handling user hooks.

Here’s the Drupal 5 version:

<?php

function download_count_user($op, &$edit, &$account, $caterory = NULL) {



  if ($op == ‘view’)

  {

    $result = db_query(“SELECT filename FROM file_downloads_users WHERE user_id = %d”, $account->uid);



    while ($file = db_fetch_object($result)) {

      $file_str .= $file->filename . ‘<br/>’;

    }

   $items[‘downloads’] = array(

    ‘title’ => t(‘Files’),

    ‘value’ => $file_str,

    ‘class’ => ‘member’

    );

    return array(t(‘Downloads’)=>$items);

 }

}

?>

Now when you login into your user account after downloading some files, you’ll see that info displayed as a part of your user profile:

Drupal screenshot

Text resizing with JavaScript

<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”>
<HTML>
 <HEAD>
<script>

function init() {

  if($(‘container’))
    textSize.init();
}

var textSize = {
  small:  ‘80%’,
  medium: ‘100%’,
  large:  ‘120%’,

  init: function() {
    var small_text  = $(’small_text’);
    var medium_text = $(‘medium_text’);
    var large_text  = $(‘large_text’);
    var container   = $(‘container’);

    var textSizeCookie     = readCookie(‘textSize’);
    var textSizeCookieName = readCookie(‘textSizeName’);
    if(textSizeCookie && textSizeCookieName) {
      container.style.fontSize = textSizeCookie;
      textSize.resetClassNames();
      eval(textSizeCookieName + ‘_text’).className = ‘current’;
    }

    small_text.onclick = function() {
      textSize.resetClassNames();
      this.className = ‘current’;
      createCookie(‘textSize’, textSize.small, 14);
      createCookie(‘textSizeName’, ’small’, 14);
      container.style.fontSize = textSize.small;
      $(‘header’).style.fontSize = ‘11px’;
    }
    medium_text.onclick = function() {
      textSize.resetClassNames();
      this.className = ‘current’;
      createCookie(‘textSize’, textSize.medium, 14);
      createCookie(‘textSizeName’, ‘medium’, 14);
      container.style.fontSize = textSize.medium;
      $(‘header’).style.fontSize = ‘11px’;
    }
    large_text.onclick = function() {
      textSize.resetClassNames();
      this.className = ‘current’;
      createCookie(‘textSize’, textSize.large, 14);
      createCookie(‘textSizeName’, ‘large’, 14);
      container.style.fontSize = textSize.large;
      $(‘header’).style.fontSize = ‘11px’;
    }
  },

  resetClassNames: function() {
    $(’small_text’).className  = ;
    $(‘medium_text’).className = ;
    $(‘large_text’).className  = ;
  }
};

function $(element_id) {
  var element = document.getElementById(element_id);
  return (element == null) ? (false) : (element);
}

function createCookie(name, value, days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime() + (days*24*60*60*1000));
    var expires = ‘; expires=’ + date.toGMTString();
  }
  else var expires = ;
  document.cookie = name + ‘=’ + value + expires + ‘; path=/’;
}

function readCookie(name) {
  var nameEQ = name + “=”;
  var ca = document.cookie.split(‘;’);
  for(var i=0;i < ca.length;i++) {
    var c = ca[i];
    while (c.charAt(0)==‘ ‘) c = c.substring(1,c.length);
    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
  }
  return null;
}

function eraseCookie(name) {
  createCookie(name, , -1);
}

if (document.addEventListener) {
  document.addEventListener(“DOMContentLoaded”, init, false);
}
/* for Internet Explorer */
/*@cc_on @*/
/*@if (@_win32)
  document.write(”<script id=__ie_onload defer src=javascript:void(0)><\/script>”);
  var script = document.getElementById(”__ie_onload”);
  script.onreadystatechange = function() {
    if (this.readyState == “complete”) {
      init(); // call the onload handler
    }
  };
/*@end @*/
/* for Safari */
if (/WebKit/i.test(navigator.userAgent)) { // sniff
  var _timer = setInterval(function() {
    if (/loaded|complete/.test(document.readyState)) {
      init(); // call the onload handler
    }
  }, 10);
}
/* for other browsers */
window.onload = init;

</script>
 </HEAD>

 <BODY>
      <p id=“accessibility”>

         Text Size:
         <a href=“#” id=“small_text” class=“current”>S</a>
         <a href=“#” id=“medium_text”>M</a>
         <a href=“#” id=“large_text”>L</a>

    </p>
    <div id=“container”>
<p>Text example</p>
</div>
 </BODY>
</HTML>

IE tester

As much as we all hate IE… have to deal with it. This is a great testing tool, includes IE6

http://www.my-debugbar.com/wiki/IETester/HomePage

Unix: move folder into current directory

I know it’s stupid and straightforward but I’m going to write it down for my own reference:

mv foldername/* ./

Will move the files from a folder into the same (current) directory.

Javascript goodies

Text auto-complete: http://devthought.com/textboxlist-meets-autocompletion/

Links from Smashing Mag:

http://www.smashingmagazine.com/2008/09/11/75-really-useful-javascript-techniques/

http://www.smashingmagazine.com/2009/02/08/50-extremely-useful-javascript-tools/

http://www.smashingmagazine.com/2008/04/15/60-more-ajax-and-javascript-solutions-for-professional-coding/

http://www.smashingmagazine.com/2008/09/16/jquery-examples-and-best-practices/

IE7: page contains both secure and nonsecure items

 This message shows up on secure pages and sometimes it’s really hard to find what’s causing it.

Since your page is secure, all the external files, including CSS files, Javascript include files and images need to be linked from secure https pages in order for IE7 to load your page without errors. The Fiddler tool helps identify which images/files are not being linked from https.

Once you install it, just run it and open the page you want to test in a browser. Here’s my screenshot that found that offending image in no time:

Fiddler screenshot

« Previous PageNext Page »