Merging PDF files with Linux

Almost everything I write here is related to problems I face daily and this time I came with something new and not very common :D.

A client of mine asked me to find a solution which allow him to combine several PDFs files into a single one without the “complicated” steps of Windows software. I think there is no free solution to do that and the one I know, Adobe Reader, comes with this feature only with paid licence.

The physical scenario involve a Linux file server reachable by a network of Windows machines acting as SMB/CIFS clients and the procedure to merge the files looks like the following:

– The file server shares, with read/write permissions, a directory (folder) called zip2pdf.
– If a user wants to combine a series of files he just need to zip the files and copy the compressed file into the shared directory.
– After a certain time, proportional to the size of the documents to be merged, a PDF file will “appear” in the shared directory containing the PDFs combined.

How I did this?

– I used a filesystem watcher which notifies me every change on a target directory, in my case, file creation.
– I unzipped the file, sorted the output and merged the PDFs with ghostscript.
– I put it all in a bash script and ran it in background.

[bash]
#!/bin/bash
inotifywait –monitor –event CREATE –format “%w%f” $1 | while read file
do
MATCH=echo $file | grep -P ".zip$"
if [ “$MATCH”!=”” ] && [ -e $file ];
then
sleep 3 # wait an arbitrary value to “ensure” the file was closed.
# There are another ways to check it using lsof for instance,
# but it would complicate the script a lot

STAMP=date +"%Y-%m-%d_%N"
DIR=”uncompressed_$STAMP/”

mkdir -p $DIR

unzip $file -d $DIR

FILES=find $DIR -type f -iname *.PDF | sort
#echo “LIST: $FILES”
gs -dNOPAUSE -sDEVICE=pdfwrite -sOUTPUTFILE=$STAMP.pdf -dBATCH $FILES

mv $STAMP.pdf $1
rm -rf $DIR
else
echo NOOOOOOOOOOO
fi
done
[/bash]

[bash]
$ ./z2p.sh /home/carlos/Desktop/zip2pdf/
[/bash]

It works and it was pretty simple 😀

Kindle Touch at home

Last week I went to the courier to pick up my recently arrived package from Amazon. I bought the 99 Dollars Kindle Touch which I hope will help me to actually do the research I need to start my thesis and finally get my Computer Science major.

I was expecting something a little more handy but it is fine in almost all aspects. The thing that bothered me the most was the PDF to AZW conversion because like the majority of the people, I have my e-books in PDF format and Kindle’s native support for PDF files is really poor reaching the unusable/unreadable boundary.

With this situation in front of me I started googling with the wrong query, “pdf to kindle format”. The results pointed to a PDF reformatting software which I incorrectly thought would work.

Finally, there was a really simple solution provided by Amazon itself!. I just needed to send by email my PDF copy of the book to <my-amazon-username>@free.kindle.com with the subject “convert”. After a short period of time they email you back with the AZW file automatically available in your book catalog accessible with your Kindle.

Despite this service is really useful, Amazon seems to keep it in the fog. It wasn’t easy to find but the results were satisfactory.

Backup system using Samba

It is well known that Windows owns the desktop/laptop market in personal computing. Despite I don’t have anything against Windows, this situation is not precisely to my liking because it would be easier to manage a network of workstations if they would be running Linux instead of Windows.

I don’t want to get any deeper with my operating systems preferences because it would probably lead into some sort of awkward post explaining my point of view or the philosophical reason of my preference to Linux so, we should probably just stick with the code :D.

The problem I’m facing looks like this:

1. There is a network of Windows computers.
2. There is a Linux machine serving as Internet gateway and some other services.
3. They needed a backup system which stores data outside they workstations.
4. They needed to have privacy (password protected).
5. They demanded it to be quick (“I want it know”).

If the computers were running Linux it would have taken me about 5 minutes to configure sshfs (user space filesystem) but since Windows is in scene I needed an easy way to integrate a backup system that seamlessly attach itself to the Windows user interface and, what’s better than SMB/CIFS file sharing for this case?.

To achieve this I used SAMBA following the steps below (supposing that you already installed Samba).

1. Determine how many users will be using the backup system and create a Linux user for every single one of them if they don’t exists.

[bash]
# useradd lorena -m -c “Lorena Algo”
[/bash]

2. Create Samba users/passwords for the users you just created. In this case, the password changing program will also create the user if the option “-a” is specified.

[bash]
# smbpasswd -a lorena
[/bash]

3. Configure smb.conf file to share the user’s home directory or another directory you want. In my case, there is three users configured: Lorena, Eve and Ada.

[bash]
[global]
workgroup = WORKGROUP
passdb backend = tdbsam
security = user

[lorena]
path = /home/lorena
guest ok = No
valid users = lorena
read only = No

[eve]
path = /home/eve/
guest ok = No
valid users = eve
read only = No

[ada]
path = /home/ada/
guest ok = No
valid users = ada
read only = No
[/bash]

4. Start or restart smbd deamon.

[bash]
# /etc/init.d/smb restart
[/bash]

Give it a try. If everything were configured correctly, every user will only have access to their home directory and nowhere else. It is simple to do but there is a serious problem: what if the user wants to change the password of its account?, there is no way to do it with this method.

A PHP web script is a good approach to change passwords from a web page but since web pages are served by Apache normally with a non-root account there would be a problem calling smbpasswd program from the script. Sudo is the answer for this and with exactly one line we found the solution.

[bash]
# visudo
[/bash]

and append this line (wwwrun is the Apache user, you should change it with the one you are using):

[bash]
wwwrun ALL=NOPASSWD:/usr/bin/smbpasswd
[/bash]

The front-end is a (horrible) HTML page with just a web form.

[html]

Username:
Current :

New Password:

Re-type Password:

[/html]

I know, it looks absolutely ugly but it makes my point :D.

And finally, the password logic changing is implemented here:
[php]
/usr/bin/smbclient -L localhost -U “$username%$password” 2>&1;

return !(preg_match(‘/NT_STATUS_LOGON_FAILURE/’, $output));
}

function change_password($username, $newpassword)
{
$output = (echo $newpassword; echo $newpassword) | /usr/bin/sudo /usr/bin/smbpasswd -U $username -s 2>&1;

return !trim($output);
}

?>
[/php]

Aaaand that’s it. I hope it could be useful for you as it was for me.

Thank you for reading 🙂