CVS to Subversion Transfer

Most of my projects all use Subversion now, as everyone knows it’s the recommended little brother of CVS. However, for everything that doesn’t have a home in SVN with a client, I was storing in CVS I had running on my local dev machine.

Not wanting to loose any of my files or their histories, I wanted to find a way to transfer everything into subversion. At the recent ZendCon I heard about cvs2svn and I tried it out. It was very easy to install (required Python, which was easy for me to installed through Yum), and it was easy to run – at least for me as I was just pulling everything over.

Now I’ve got everything in subversion and I was able to maintain the file histories for everything.

Tagging & Protecting PDF Files using PHP

I recently had to run some tests on tagging/watermarking an existing PDF file, and then protecting it using php. First, you’ll need to download the proper libraries.

Extract all of those packages, get rid of non-essential files and place most everything in the same folder… “font” and “decoders” will likely be the only folders remaining.

Then, place your existing pdf in the same folder.

Then, create a new php file with the following code. You can modify the message or its position, or you can ready the manuals for the above packages for more options. To set a user/owner password, just add them as the second and third arguments for the SetProtection method (outside the array, which is the first argument).

[PHP]
define(‘FPDF_FONTPATH’,'font/’);
require(‘FPDI_Protection.php’);

class PDF extends FPDI_Protection
{
function Footer()
{
//Position at 1.5 cm from bottom
$this->SetY(-15);
//Arial italic 8
$this->SetFont(‘Arial’,'I’,8);
//Page number
$msg = “If you’re not ” . $_SERVER['REMOTE_ADDR'] . “, then you’ve stolen our stuff.”;
$this->Cell(0,10,$msg,0,0,’C');
}
}

$pdf= new PDF();

$pagecount = $pdf->setSourceFile(“document.pdf”);

for ($i=1; $i < = $pagecount; $i++) {
$tplidx = $pdf->ImportPage(1);
$pdf->addPage();
$pdf->useTemplate($tplidx,0,0,0);
}

$pdf->SetProtection(array(‘print’));
$pdf->Output(“newpdf.pdf”,”I”);
[/PHP]

Installing Subversion on Fedora Core

I’ve been using subversion a lot recently – from using repositories with client development companies to installing it for clients – it seems to be the SVN month.

Here’s how I installed subversion on a machine with Fedora Core 4. For anyone learning or using Subversion, I highly recommend that you read the book.

You may already have subversion installed, if not, just run this:

# yum install subversion
# yum install mod_dav_svn

Then you’ll need to setup at least one repository. I’m going to need multiple repositories that I can use for different clients so I have a bit of extra admin work ahead of me. You can setup as many repositories as you need, but no matter what you’ll need at least one. Here create the folders…

# mkdir /svn
# mkdir /svn/repos
# mkdir /svn/users
# mkdir /svn/permissions

We need to give these folders the proper permissions

# chown -R apache.apache /svn

Then we need to tell subversion to make our first repository.

# svnadmin create /svn/repos/myproject

First, I need to setup a config file for svnserve.

# vi /svn/repos/conf/svnserve.conf

Then, look for variations of the following code and edit it as necessary. By default any anonymous user can access the code so to disable that you must include anon-access = none, just commenting the value out will not prevent anonymous access.

anon-access = none
password-db = passwdfile
realm = My SVN Repository
auth-access = write

The password-db is just a path to a file containing usernames and passwords. You’ll create this file especially for SVN. I create each file inside of the repository conf directory. So, save your changes and then we’ll create said user file.

# vi passwdfile

Enter in something like:

[users]
username = password

Anyway, you’ll need to start the svn server.

# svnserve -d --listen-port=3690

One side note – svnserve just runs and doesn’t have a way to stop besides killing the process. If you make changes to the svnserve.conf or user file you’ll need to restart svnserve.

# killall svnserve

Then, go ahead and test (best to do so on a different machine).

# svn co --username=myusername svn://mydomain/svn/repos/myproject

The system should then ask you for your password. Go ahead and run some tests.

Now, let’s setup apache.

Create a new apache include file that will hold our configurations (You may already have this is subversion was already installed).

# vi /etc/httpd/conf.d/subversion.conf

Now, this file will need to contain something like this to serve the repository through apache:


LoadModule dav_svn_module modules/mod_dav_svn.so
LoadModule authz_svn_module modules/mod_authz_svn.so


DAV svn
SVNPath /svn/repos
AuthType Basic
AuthName "Subversion Repository"
AuthUserFile /svn/users/svnpass
Require valid-user
AuthzSVNAccessFile /svn/permissions/svnauthz.conf

Now, this essentially tells apache to load the mods needed for svn. We need to create some files so that this config will work properly. The first is our htpasswd file which I named “/svn/users/svnpass”.

# htpasswd -cb /svn/users/svnpass username password

Next we need to create the svnauth file.

# vi /svn/permissions/svnauthz.conf

Inside we’ll place a list of users who have access to files:


[/]

username = rw

The “rw” states that this user has read/write access to the root repository /.

Restart your web server and you should be done.

service httpd reload
or you can use:
/usr/sbin/apachectl restart – this option outputs better error messages in case you’ve made some syntax mistakes.

Go to your repository and you should see subversion displaying the repo info.

http://yoursite.com/svn/repos/

Tech-Tidbit: Checking a sendmail queue

I recently had to research the source of some email issues which required me to check what may still be in a queue for sendmail. Since the source of the email was PHP, which was using the default mail method, the emails would be going through sendmail.

To check the queue, I used:


# mailq

(this checks /var/spool/mqueue, the primary queue)


# mailq -Ac

(this checks /var/spool/clientmqueue, which may or not be used on your server)

Unfortunately my queues were empty, but these commands will be very helpful to me in the future.

Tech-Tidbit: Altering Primary Keys in MySQL

I’ve come to design every database table with an auto-increment id field that is a primary key. However, sometimes I work on projects where tables have no such column and may have duplicate rows. In order to drop the existing primary key definitions I run:

[mysql]
ALTER TABLE mytable DROP PRIMARY KEY;
[/mysql]

Then, I add a new one:

[mysql]
ALTER TABLE `mytable` ADD `id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY FIRST ;
[/mysql]

Tech-Tidbit: HTML Entity to Decimal Translation

It became necessary this week for me to find a way to convert html entities into their decimal equivalents. I’m not very fond of dealing with character encoding and entity issues but I was finally able to get things working. In the end we modified data within the database which meant I wouldn’t get to use this script, but it was a very nice find.

The nice thing about this is that it leaves any existing decimal-format characters alone, and properly translates html entities to the decimal format.

After searching the net for a while I found a piece of code that seemed like a good solution. The original needed a bit of cleanup and tweaking, but here it is:

function htmlentities2unicodeentities ($input) {
  $htmlEntities = array_values (get_html_translation_table (HTML_ENTITIES, ENT_QUOTES));
  $entitiesDecoded = array_keys  (get_html_translation_table (HTML_ENTITIES, ENT_QUOTES));
  $num = count ($entitiesDecoded);
  for ($u = 0; $u < $num; $u++) {
   $utf8Entities[$u] = '&#'.ord($entitiesDecoded[$u]).';';
  }
  return str_replace ($htmlEntities, $utf8Entities, $input);
}

You can test the translation with this:

$test_strs = array('K&#363;lob', 'K&oacute;pavogur');

foreach($test_strs as $test_str){

  print 'ORIGINAL: ' . $test_str . '<br />'."\n";
  print 'TRANSLATED: ' . entities_to_unicode($test_str) . '<p>'."\n";

}

If you’re interested in converting things the other way around, good luck. I’ve been searching around for a while and I just can’t seem to find anything that works well enough without using some long array to translate things. Let me know if you find one!

Tech-Tidbit: MultipleIE

I’ve been using VMWare so that I can test IE6 as well as IE7 (which is the default on my actual machine). VMWare takes a lot of system resources, and with the laptop I use at the moment, it requires a few items to be closed so that it will work properly. I’ve read about several manual hack-ish methods of getting both versions of IE to work on a single machine but I just didn’t want to bother with all of that.

Enter MultipleIE.

An excellent system that allows me to install multiple versions of IE at the click of a button. I no longer support IE5.5 or it’s predecessors, so I just installed IE6. It works very well! I’ve noticed that it shares it’s location bar history with IE7, but they render things as you would expect each to.

Thanks to one of my development partners for pointing me to that.

Tech-Tidbit: MySQL Weighting

I’m still rather disappointed with my options for weighting random results in MySQL, but I’ve done the best I can do with it. It’s more about figuring out what numbers you use for the weighting rather than the calculation itself. The query itself ends with:

[mysql]
ORDER BY RAND() * weight_fieldname
[/mysql]

Now, my possible weights from weight_fieldname are 5, 20, 100. 5 is the default weight for every record – 20 increases the chances of the record a bit and 100 pretty much sets the record as an exclusive result. Now, if you only have a single weight applied then setting it to 0 will reduce the weight of an item, however this is very difficult when you start having multiple weights.

One additional problem is that if you have a serious amount of records, using ORDER BY RAND() is going to be a performance hit.

Tech-Tidbit: Smarty Variables

One of my recent projects was using Smarty – I found myself in a position where I needed to access a variable assigned to a Smarty template directly – I could not access it before/while it was being assigned and Smarty doesn’t provide enough resources to interact with it directly before it’s actually transferred to the template. Smarty does allow you to edit other variables by using the global command in php, but not those that have already been assigned.

What did I end up doing? I just accessed the Smarty template object itself.

$this->_tpl_vars['name_of_template_var_here'];

I had to perform some fairly fancy tests on that data. Then, if you want modify that data you can just save it back to the above variable or re-assign it:

$this->Assign("name_of_template_var_here", $new_value_here);

Tech-Tidbit: Subversion Post-Commit Email

I was setting up an installation of subversion for a client (and I will be for myself soon here – it’s about time to move from CVS) and I needed to enable it to send an email to folks each time a commit was made. This tidbit assumes that you’ve already installed SVN on a linux machine.

First, you need to visit your hooks dir (created when you create a new repository (which is done using svnadmin)).

# cd /path/to/repo/hooks

You need to download a copy of the commit email perl script, which you can get from here.

# wget http://svn.collab.net/repos/svn/trunk/tools/hook-scripts/commit-email.pl.in

Then, rename it to .pl. You’ll need to rename the special file that SVN uses to activate the email. This file is post-commit.tmpl and you’ll need to rename it to post-commit.

# mv commit-email.pl.in commit-email.pl
# cp post-commit.tmpl post-commit

Next you need to edit the post-commit file so that it sends your email out. At the bottom of the file, add the following:

/path/to/repo/hooks/commit-email.pl "$REPOS" "$REV" --from svn@example.com "me@example.com" "you@example.com"

Then just save the file. Now you’re ready to test. You can either make a commit or run the below command. First call the post-commit, then provide the path to a repository to watch, then provide the revision number you want to run a test on. If you’ve just imported code and don’t have any other revisions, just provide the number 1 – but beware the possibility of a really long email.

# ./post-commit /path/to/repo 40

Things should be working fine by this point, but I ran into a problem. I saw the error message Global symbol "@SVN_BINDIR" requires explicit package. In that case, just go into the commit-email and change the @SVN_BINDIR variable on line 46 to the full path of svnlook.