BackUpWordPress plugin produces tarballs containing duplicates

July 18th, 2010 RaftaMan No comments

I’m using BackUpWordPress to do regular database and file tree backups of this blog. Unfortunately, there is a nasty bug in this plugin which may cause the tarball to contain every backuped file multiple times (to be precise, every file except the first one will go into the tarball exactly three times).

The problem is that the . and .. directories may appear in a somewhat random order and not necessarily as the first entries in a directory. This is probably host specific (I encountered this error for the first time after I relocated this blog to another server).

To fix BackUpWordPress v0.4.5, locate line 103 in Directory.php (resides in wp-content/plugins/backupwordpress/Archive/Reader/) and change the while-loop inside the next() function

...
        while ($this->source === null ||
              ($error = $this->source->next()) !== true) {
...

like this

...
        $file = null;
        while ($this->source === null ||
              $file == '.' || $file == '..' ||
              ($error = $this->source->next()) !== true) {
...

Alternatively, you can use the following patch:

--- Directory.php.orig	2010-07-17 15:02:56.093238736 +0200
+++ Directory.php	2010-07-17 15:04:10.367237641 +0200
@@ -103,0 +104 @@
+        $file = null; 

@@ -104,0 +106 @@
+              $file == '.' || $file == '..' || 

Resources:
http://pear.php.net/bugs/bug.php?id=6546

Categories: Uncategorized Tags: ,

Visualizing rpm dependencies with Graphviz

July 16th, 2010 RaftaMan No comments

Sometimes, rpm dependencies get rather complex. It’s not always easy for an rpm maintainer to keep track of the runtime requirements of his package and therefore, huge rpm dependency trees develop. And it’s even more difficult so see which packages get pulled by yum, because only a tiny part of those are actually listed as requirements in the spec file. The tree gets huge with recursion!

With rpmdep, there’s a small tool that will help you visualize those dependency trees. It’s part of Fedora’s rpmorphan-package, so you can easily pull it with yum:

# yum install rpmorphan

rpmdep itself is just a perl script, that walks down the rpm tree recursively. It can produce a Graphviz dot-file, which in turn can be used to make rather since pictures. For example,

$ rpmdep -dot firefox.dot firefox
$ dot -Tpng firefox.dot -o firefox.png

produces a complete rpm dependency tree for firefox. An exemplary picture (firefox’s dependencies in Fedora 13):

Click image for full size (1.6MB)

Graphvic can produce quite a few output formats. For an overview about all available commands, have a look at http://www.graphviz.org/doc/info/command.html.

Categories: Uncategorized Tags:

Granting access to X server with xhost

July 14th, 2010 RaftaMan No comments

Every X server internally manages an ACL (Access Control List) of those hosts, that are allowed to connect. The server only authorizes connections from X clients, whose host is on that list and rejects access to all others. The xhost program is used to add or revert access to the X server for specified hosts. It’s also possible to specify a user and a hostname pair.

Host-based Control (xhost)

To see if access control is enabled, type xhost. It displays the current ACL:

$ xhost
access control enabled, only authorized clients can connect
SI:localuser:user
SI:localuser:gdm
SI:localuser:root

If the access control is disabled, it prints:

$ xhost
access control disabled, clients can connect from any host

To disable the access control type xhost + which allows any host to access your X server. You probaly don’t want to do this because it allows the world to open windows on your screen and grab the keystrokes you type.

To enable the access control again type xhost - and only authorized clients/hosts are allowed to do the things mentioned above.

A simple example

Now let’s do something useful, e.g. grant another user on the local machine access to our X server. It’s pretty easy:

$ xhost +SI:localuser:anotheruser
localuser:anotheruser being added to access control list

And after that, anotheruser should show up in the ACL:

$ xhost
access control disabled, clients can connect from any host
SI:localuser:anotheruser
SI:localuser:user
SI:localuser:gdm
SI:localuser:root

To revoke the access right for anotheruser, use

$ xhost -SI:localuser:anotheruser
localuser:anotheruser being removed from access control list

For granting access to users on different hosts, have a look at the xhost manpage or the examples provided on http://linux.about.com/library/cmd/blcmdl_xhost.htm.

Categories: Uncategorized Tags: , ,

Dealing with .rpmnew and .rpmsave files

July 8th, 2010 RaftaMan No comments

When an upgrade includes changes to a default configuration file, the package will write either a .rpmnew or a .rpmsave file instead of overwriting the configuration file on your system. Which file a package creates is up to the discretion of the package maintainer.

From “Dealing with .rpmnew and .rpmsave files” By Bruce Byfield:

An .rpmnew file contains the new default configuration file and leaves your original configuration file untouched. By contrast, and .rpmsave file is a copy of your original configuration file, which has been replaced by the new default file.

The following script can be helpful to find (and possibly merge) those files with your original configuration

for a in $(find /etc /var -name '*.rpm?*'); do diff -u $a ${a%.rpm?*}; done

You may also want to check on yum-merge-conf, a yum plugin to merge configuration files.

Categories: Uncategorized Tags: , , ,

Cleaning up locally-installed RPMs with package-cleanup

July 6th, 2010 RaftaMan No comments

Sometimes, packages you never actually use get installed as dependency by yum (or even during initial installation by anaconda). package-cleanup is a great tool that helps you find packages not required by other packages. It it part of the yum-utils package which can easily be pulled with yum:

# yum install yum-utils

1. Find and review “unused” packages

You can find packages not required by other packages with

# package-cleanup --leaves

These packages could be candidates for removal, but check to see whether you use them directly or if they are used by applications not backed by rpm packages.

2. Find and review “lost” packages

You can find orphaned packages (i.e. packages not in the repositories anymore) with

# package-cleanup --orphans

This will also show packages which have been partially uninstalled but where the “%postun” script failed.

q.v. package-cleanup manpage

Categories: Uncategorized Tags: ,

Duplicate log4j output lines

June 28th, 2010 RaftaMan No comments

Ever seen duplicate lines in your log4j output? Maybe something like this:

2010-06-28 21:56:11,743 [main] INFO  org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 1.8.1
2010-06-28 21:56:11,743 [main] INFO  org.quartz.impl.StdSchedulerFactory - Quartz scheduler version: 1.8.1
2010-06-28 21:56:11,750 [main] INFO  org.quartz.core.QuartzScheduler - Scheduler MyScheduler_$_1 started.
2010-06-28 21:56:11,750 [main] INFO  org.quartz.core.QuartzScheduler - Scheduler MyScheduler_$_1 started.

Well, the obvious cause is probably duplicate loggers your log4j configuration:

log4j.rootLogger=INFO, DefaultConsoleAppender
log4j.logger.org.quartz=DEBUG, DefaultConsoleAppender

As the properties are inherited from the root logger, this is telling log4j that all quartz-classes should send their log to the DefaultConsoleAppender (which the root logger is doing anyway). So we simply have to remove the appender from the second logger definition:

log4j.rootLogger=INFO, DefaultConsoleAppender
log4j.logger.org.quartz=DEBUG

So watch your inherited log levels and appenders in your log4j configuration!

If anyone knows, why these duplicate lines appear from time to time in heavily multi-threaded environments (although log4j claims to be thread-safe) despite correct property files, please drop me a mail or leave a comment.

Categories: Uncategorized Tags: ,

Efficiently searching the Java API

June 17th, 2010 RaftaMan No comments

Since Sun’s API search is a real pain in the arse and even DocWeb doesn’t allow you to quickly search the Java API, this firefox plugin is a substantial improvement: https://addons.mozilla.org/en-US/firefox/addon/60675/

It basically redirects the search query to Google’s “I’m Feeling Lucky” feature to search Java’s API for the class information.

Together with Second Search querying the Java API is now lightning fast: https://addons.mozilla.org/en-US/firefox/addon/4096/

Categories: Uncategorized Tags: ,

Implementing equals() the right way

June 15th, 2010 RaftaMan No comments

At first sight, implementing equals() doesn’t seem fairly hard. Unfortunately, it turns out that writing a correct equality method is surprisingly difficult:

http://java.sun.com/javase/6/docs/api/java/lang/Object.html

The equals method implements an equivalence relation on non-null object references:

  • It is reflexive: for any non-null reference value x, x.equals(x) should return true.
  • It is symmetric: for any non-null reference values x and y, x.equals(y) should return true if and only if y.equals(x) returns true.
  • It is transitive: for any non-null reference values x, y, and z, if x.equals(y) returns true and y.equals(z) returns true, then x.equals(z) should return true.
  • It is consistent: for any non-null reference values x and y, multiple invocations of x.equals(y) consistently return true or consistently return false, provided no information used in equals comparisons on the objects is modified.
  • For any non-null reference value x, x.equals(null) should return false.

In fact, after studying a large body of Java code, the authors of a 2007 paper concluded that almost all implementations of equals methods are faulty.1

There are quite a lot of HowTos available on the web. One of the best might be the article “How to Write an Equality Method in Java” by Martin Odersky, Lex Spoon, and Bill Venners.

So instead of repeating all the pitfalls you have to avoid, I’ll give you a sample implementation2 of the equals()-method that follows the general contract using the example of an imaginary class Point:

public boolean equals (final Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (this.getClass() != obj.getClass()) {
      return false;
    }
    final Point other = (Point) obj;
    if (this.x != other.x) {
      return false;
    }
    if (this.y != other.y) {
      return false;
    }
    return true;
  }

Be careful: Whenever you overwrite equals() it is generally necessary to override the hashCode()-method, too!

If you want to learn more about this topic, I suggest, you have a look at Joshua Bloch’s Effective Java Second Edition. Addison-Wesley, 2008.


[1] Vaziri, Mandana, Frank Tip, Stephen Fink, and Julian Dolby. “Declarative Object Identity Using Relation Types.” In Proc. ECOOP 2007, pages 54–78. 2007.
[2] http://www.artima.com/forums/flat.jsp?forum=226&thread=259279&start=30&msRange=15

Categories: Uncategorized Tags:

Using a HashSet in a thread-safe manner

June 13th, 2010 RaftaMan No comments

Thread safety is a very hot topic for Java programmers right now. But I’ve seen quite a few folks using the rather complex collections from java.util.concurrent when they actually needed just a thread-safe implementation of a Set.

Of course, the HashSet implementation is non-thread-safe:

http://java.sun.com/javase/6/docs/api/java/util/HashSet.html

Note that this implementation is not synchronized. If multiple threads access a hash set concurrently, and at least one of the threads modifies the set, it must be synchronized externally. This is typically accomplished by synchronizing on some object that naturally encapsulates the set. If no such object exists, the set should be “wrapped” using the Collections.synchronizedSet method. This is best done at creation time, to prevent accidental unsynchronized access to the set:

So getting a thread-safe representation of the HashSet class is pretty easy:

   Set s = Collections.synchronizedSet(new HashSet(...));

This returns a synchronized set backed by the specified set. But be careful: In order to guarantee serial access, it is critical that all access to the backing set is accomplished through the returned set.

A further pitfall is the use of the class’s iterator

Note that the fail-fast behavior of an iterator cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification. Fail-fast iterators throw ConcurrentModificationException on a best-effort basis. Therefore, it would be wrong to write a program that depended on this exception for its correctness: the fail-fast behavior of iterators should be used only to detect bugs.

So it is imperative that you manually synchronize on the returned set when iterating over it:

  Set s = Collections.synchronizedSet(new HashSet());
      ...
  synchronized(s) {
      Iterator i = s.iterator(); // Must be in the synchronized block
      while (i.hasNext())
          foo(i.next());
  }
 

Failure to follow this advice may result in non-deterministic behavior.

Categories: Uncategorized Tags:

Inside adsense’s show_ads.js

June 5th, 2010 RaftaMan No comments

For those of you, who want to understand what goes on inside google adsense’s show_ads.js, here is the complete source code:

google_ad_url = '';
google_random = (new Date()).getTime();
google_org_error_handler = window.onerror;

function quoted(str) {
  return (str != null) ? '"' + str + '"' : '""';
}

function google_encodeURIComponent(str) {
  if (typeof(encodeURIComponent) == 'function') {
    return encodeURIComponent(str);
  } else {
    return escape(str);
  }
}

function google_write_tracker(tracker_event) {
  var img_url = window.google_ad_url.replace(/pagead\/ads/, 'pagead/imp.gif');
  var img_src = img_url + '&event=' + tracker_event;
  var img_tag = '<i' + 'mg height="1" width="1" border="0" ' +
                'src=' + quoted(img_src) +
                ' />';
  document.write(img_tag);
}

function google_append_url(param, value) {
  if (value) {
    window.google_ad_url += '&' + param + '=' + value;
  }
}

function google_append_url_esc(param, value) {
  if (value) {
    google_append_url(param, google_encodeURIComponent(value));
  }
}

function google_append_color(param, value) {
  if (value && typeof(value) == 'object') {
    value = value[window.google_random % value.length];
  }
  google_append_url('color_' + param, value);
}

function google_show_ad() {
  var w = window;
  w.onerror = w.google_org_error_handler;

  if (w.google_num_ad_slots) {
    w.google_num_ad_slots = w.google_num_ad_slots + 1;
  } else {
    w.google_num_ad_slots = 1;
  }

  if (w.google_num_ad_slots > 3) {
    return;
  }

  w.google_ad_url = 'http://pagead2.googlesyndication.com/pagead/ads?';
  w.google_ad_client = w.google_ad_client.toLowerCase();
  if (w.google_ad_client.substring(0,3) != 'ca-') {
     w.google_ad_client = 'ca-' + w.google_ad_client;
  }
  w.google_ad_url += 'client=' + escape(w.google_ad_client) +
                     '&random=' + w.google_random;

  google_append_url('hl', w.google_language);
  if (w.google_country) {
    google_append_url('gl', w.google_country);
  } else {
    google_append_url('gl', w.google_gl);
  }
  google_append_url('gr', w.google_region);
  google_append_url_esc('gcs', w.google_city);
  google_append_url_esc('hints', w.google_hints);
  google_append_url('adsafe', w.google_safe);
  google_append_url('oe', w.google_encoding);
  google_append_url('lmt', w.google_last_modified_time);
  google_append_url_esc('alternate_ad_url', w.google_alternate_ad_url);
  google_append_url('alt_color', w.google_alternate_color);

  if (w.google_skip) {
    google_append_url("skip", w.google_skip);
  } else if (w.google_prev_ad_formats) {
    google_append_url_esc('prev_fmts', w.google_prev_ad_formats.toLowerCase());
  }

  if (w.google_ad_format) {
    google_append_url_esc('format', w.google_ad_format.toLowerCase());
    if (w.google_prev_ad_formats) {
      w.google_prev_ad_formats = w.google_prev_ad_formats + ',' + w.google_ad_format;
    } else {
      w.google_prev_ad_formats = w.google_ad_format;
    }
  }

  google_append_url('num_ads', w.google_max_num_ads);
  google_append_url('output', w.google_ad_output);
  google_append_url('adtest', w.google_adtest);
  if (w.google_ad_channel) {
    google_append_url_esc('channel', w.google_ad_channel.toLowerCase());
  }
  google_append_url_esc('url', w.google_page_url);
  google_append_color('bg', w.google_color_bg);
  google_append_color('text', w.google_color_text);
  google_append_color('link', w.google_color_link);
  google_append_color('url', w.google_color_url);
  google_append_color('border', w.google_color_border);
  google_append_color('line', w.google_color_line);
  google_append_url('kw_type', w.google_kw_type);
  google_append_url_esc('kw', w.google_kw);
  google_append_url_esc('contents', w.google_contents);
  google_append_url('num_radlinks', w.google_num_radlinks);
  google_append_url('max_radlink_len', w.google_max_radlink_len);
  google_append_url('rl_filtering', w.google_rl_filtering);
  google_append_url('ad_type', w.google_ad_type);
  google_append_url('image_size', w.google_image_size);
  google_append_url('feedback_link', w.google_feedback);

  w.google_ad_url = w.google_ad_url.substring(0, 1000);
  w.google_ad_url = w.google_ad_url.replace(/%\w?$/, '');

  if (google_ad_output == 'js' && w.google_ad_request_done) {
    document.write('<scr' + 'ipt language="JavaScript1.1"' +
                   ' src=' + quoted(google_ad_url) +
                   '></scr' + 'ipt>');
  } else if (google_ad_output == 'html') {
    if (w.name == 'google_ads_frame') {
      google_write_tracker('reboundredirect');
    } else {
      document.write('<ifr' + 'ame' +
                     ' name="google_ads_frame"' +
                     ' width=' + quoted(w.google_ad_width) +
                     ' height=' + quoted(w.google_ad_height) +
                     ' frameborder=' + quoted(w.google_ad_frameborder) +
                     ' src=' + quoted(w.google_ad_url) +
                     ' marginwidth="0"' +
                     ' marginheight="0"' +
                     ' vspace="0"' +
                     ' hspace="0"' +
                     ' allowtransparency="true"' +
                     ' scrolling="no">');
      google_write_tracker('noiframe');
      document.write('</ifr' + 'ame>');
    }
  }

  w.google_ad_frameborder = null;
  w.google_ad_format = null;
  w.google_page_url = null;
  w.google_language = null;
  w.google_gl = null;
  w.google_country = null;
  w.google_region = null;
  w.google_city = null;
  w.google_hints = null;
  w.google_safe = null;
  w.google_encoding = null;
  w.google_ad_output = null;
  w.google_max_num_ads = null;
  w.google_ad_channel = null;
  w.google_contents = null;
  w.google_alternate_ad_url = null;
  w.google_alternate_color = null;
  w.google_color_bg = null;
  w.google_color_text = null;
  w.google_color_link = null;
  w.google_color_url = null;
  w.google_color_border = null;
  w.google_color_line = null;
  w.google_adtest = null;
  w.google_kw_type = null;
  w.google_kw = null;
  w.google_num_radlinks = null;
  w.google_max_radlink_len = null;
  w.google_rl_filtering = null;
  w.google_ad_type = null;
  w.google_image_size = null;
  w.google_feedback = null;
  w.google_skip = null;
}

function google_error_handler(message, url, line) {
  google_show_ad();
  return true;
}

window.onerror = google_error_handler;

if (window.google_ad_frameborder == null) {
  google_ad_frameborder = 0;
}

if (window.google_ad_output == null) {
  google_ad_output = 'html';
}

if (window.google_ad_format == null && window.google_ad_output == 'html') {
  google_ad_format = google_ad_width + 'x' + google_ad_height;
}

if (window.google_page_url == null) {
  google_page_url = document.referrer;
  if (window.top.location == document.location) {
    google_page_url = document.location;
    google_last_modified_time = Date.parse(document.lastModified) / 1000;
  }
}
google_show_ad();

Found on http://www.koders.com.

Categories: Uncategorized Tags:
This website uses a Hackadelic PlugIn, Hackadelic SEO Table Of Contents 1.7.3.