Simpan Gambar Cover Buku dari LibraryThing ke server sendiri

Salam Sejahtera dan Selamat Maju Jaya

Hari ini saya hendak bercerita tentang sedikit programming language iaitu PHP. Semasa saya bekerja di Open University Malaysia dahulu kala, saya ada menulis script untuk Drupal untuk dapatkan image dari server LibraryThing dan muat-turun gambar tersebut ke server kita. Adapun tujuan ini adalah untuk mengurangkan tekanan bandwidth kepada pengguna ketika itu. Umumnya pada waktu ini, mungkin tidak relevan lagi kerana rata² masyarakat mempunyai akses kepada internet super.

Namun pada hari ini, API LibraryThing telah dihentikan sehingga diberitahu kelak (tak tahu la sampai bila). Takper, script ini adalah bebas untuk kita tukar source server kepada servis yang lain.

API LibraryThing dihentikan buat sementara waktu

Sebagai penambahbaik servis Perpustakaan Digital OUM ketika itu, saya telah menulis script untuk mendapatkan data² dari Syndetics untuk memperkayakan atau enrich Katalog OUM mereka dengan Muka Buku, Ringkasan Buku dan sebagainya.

Pengkayaan Katalog dengan Servis Syndetics

Script yang saya tulis untuk Perpustakaan Digital Tan Sri Abdullah Sanusi akan menyimpan Book Summary, Publisher, Author dan juga Imej Muka Buku ke dalam sistem secara dinamik.

Buku di Perpustakaan Digital Tan Sri Abdullah Sanusi

Melalui script ini, pengguna hanya perlu memasukkan No ISBN buku tersebut dan yang lain² akan dilakukan secara dinamik oleh server. Mudah bukan? Masukkan ISBN, semua data² akan diambil dan disimpan di dalam database.

Muat-turun Book Cover ke Server

Hari ini, saya ingin berkongsi maklumat atau script tentang cara² mendapatkan gambar dari server lain dan seterusnya menyimpan gambar tersebut ke dalam server kita. Script ini juga akan menyusun dan menyimpan gambar² buku mengikut jumlah askara ISBN samada 10-askara atau 13-askara.

Dalam erti kata lain, script ini akan create folder kepada beberapa bahagian kecil di dalam format 3/3/3/3/1. Sebagai contoh, jika ISBN yang diberikan adalah 978-0735210967, maka script ini akan create folder dan subfolder seperti berikut:

978/073/521/096/7

Ini adalah untuk mengelakkan daripada server mempunyai ribuan folder dengan no ISBN yang banyak yang pasti akan membebankan server apabila pengguna browse folder ini menggunakan SFTP atau FTP.

Langkah yang bijak adalah dengan memecahkannya kepada beberapa cluster. Ini akan membantu untuk mengurangkan pengunaan folder yang banyak apabila koleksi buku anda lebih dari 100,000.00.

Memecahkan ISBN kepada beberapa kluster

Kita ambil contoh ISBN untuk buku² di bawah:

  1. 978-1621001539
  2. 978-9971693367
  3. 978-0415834841 
  4. 978-1840760378

Di dalam keadaan biasa, selalunya adalah mudah untuk kita terus create folder (4 Folder) untuk setiap ISBN di atas. Jika kita berbuat demikian, sekiranya buku yang kita serve adalah kurang dari 1,000, ini mungkin tidak menjejaskan prestasi server. Namun Perpustakaan jarang sekali ada buku dengan jumlah seperti itu. Selalunya pasti lebih daripada 10,000 judul dan jika kita teruskan juga, tidak ada salahnya, tapi nanti di dalam 1 folder akan ada beribu folder yang pastinya tidak baik untuk kesihatan Server Admin (sian pada dia).

Perasan tak kebanyakan ISBN ada mempunyai prefix yang sama seperti berikut:

  1. 9780415778299 
  2. 9780415820349 
  3. 9780415809771 
  4. 9780415442060 
  5. 9780415579841 

Dengan menggunakan kaedah clustering ini, mereka boleh kongsi folder yang sama dibawah “/978/041/”. Ini akan membantu untuk mengurangkan kepada pembentukkan folder di dalam jumlah yang banyak.

Fungsi di bawah ini yang memecahkan folder kepada beberapa cluster, Lihat $parts = Array.

function BikinFolder($KEPALA, $isbn, $TestingCode) {
		$parts = Array ($KEPALA, 
			substr($isbn, 0, 3), 
			substr($isbn, 3, 3), 
			substr($isbn, 6, 3), 
			substr($isbn, 9, 3));		
		
		if (13 == strlen($isbn))
			array_push($parts, substr($isbn, 12, 3));
		$dirName = join('/', $parts);
		if (file_exists($dirName))
			return $dirName;
		$path = $KEPALA;
		for ($i = 1; $i < count($parts); $i++)
		{
			$path .= '/' . $parts[$i];
			if ($TestingCode)
				print "<p>Buat Folder di directory: $path</p>\n";
			@mkdir($path);
		}
		return $dirName;
	}

Test Run (Gambar dan Folder Tak Pernah Ada)

Di bawah adalah Print Out dari script tersebut sekiranya TestingCode = True serta gambar dan folder tersebut tidak wujud di dalam server.

Buat Folder di directory: muka-buku/978
Buat Folder di directory: muka-buku/978/041
Buat Folder di directory: muka-buku/978/041/557
Buat Folder di directory: muka-buku/978/041/557/984
Buat Folder di directory: muka-buku/978/041/557/984/1

creating/serving local file muka-buku/978/041/557/984/1/9780415579841-mc.jpg

Gambar Tiada di server. Jom kita ambil dari Syndetics. Source Gambar: https://secure.syndetics.com/index.aspx?isbn=9780415579841/mc.jpg&client=RAHSIA

Berjaya. Gambar dari Syndetics sudah disimpan di dalam server

Gambar kita ada simpan disini: www.munmon.com/main2/muka-buku/978/041/557/984/1/9780415579841-mc.jpg

Test Run (Gambar dan Folder Ada)

Script yang sama tapi gambar serta folder itu wujud. Berikut adalah Print Out dari script jika kita on kan setting TestingCode.

Create atau Load Gambar dari Local Server: muka-buku/978/041/557/984/1/9780415579841-mc.jpg

Gambar ini ada di dalam Server. Yeay!

Gambar kita ada simpan disini: www.munmon.com/main2/muka-buku/978/041/557/984/1/9780415579841-mc.jpg

Di bawah adalah keseluruhan script sekiranya berminat untuk guna. Saya lesenkan code ini dibawah dilesenkan di bawah CC BY-NC 4.0. Download Script di bawah jika mahu details dan description functionnya.

//Masukkan Nama Folder di sini
define('KEPALA', 'muka-buku');
// Masukkan Nama Lesen Library	
define('LESEN', 'RAHSIA-XXXXX-RAHSIA');
// Ini gambar default jika tak ada Gambar (
define('GAMBAR-TIADA', 'muka-buku/transparent.gif');
	
$TestingCode = False;
	
if ($TestingCode)
header("Content-type: text/html");	
$size = strtolower($_REQUEST['size']);	
if ('sc' != $size && 'mc' != $size && 'lc' != $size)
{
print "<p>ERROR - Illegal size. Must be either LC (Small), MC (Medium) or LC (Large). Please refer Syndetics Documentation </p>";
exit;
}
		
$isbn = strtoupper(preg_replace('/[^0-9Xx]/', '', $_REQUEST['isbn']));
if (10 != strlen($isbn) && 13 != strlen($isbn))
{
print "<p>Error - ISBN must be either 10 or 13 Characters</p>";
exit;
}
	
$directory = BikinFolder(KEPALA, $isbn, $TestingCode);	
	
$GambarMukaBuku = "${directory}/${isbn}-${size}.jpg";
if ($TestingCode)
print "<p>Create atau Load Gambar dari Local Server: $GambarMukaBuku</p>\n";
	
if ( ! file_exists($GambarMukaBuku) )
{
$sourceURL = 'https://secure.syndetics.com/index.aspx?isbn=' . "$isbn" . "/mc.jpg&client=" . LESEN;
		
if ($TestingCode)
print "<p>Gambar Tiada di server. Jom kita ambil dari Syndetics. Source Gambar: $sourceURL</p>\n";
		
if ($remote = fopen($sourceURL, 'r') )
{
$image = '';
while ( ! feof($remote) )
$image .= fread($remote, 8192);
fclose($remote);
if (strlen($image) >= 100  &&  $local = fopen($GambarMukaBuku, 'w'))
{
fwrite($local, $image);
fclose($local);
if ($TestingCode)
print "<p>Berjaya. Gambar dari Syndetics sudah disimpan di dalam server</p>\n";
}
}
}
else
{
if ($TestingCode)
print "<p>Gambar ini ada di dalam Server. Yeay!</p>\n";
}
$GambarKitaSimpan = file_exists($GambarMukaBuku) ? $GambarMukaBuku : GAMBAR-TIADA;
if ($TestingCode)
{	
print "<p>Gambar kita ada simpan disini: ";
print $_SERVER['SERVER_NAME'] . "/" . basename(getcwd()) ."/" . $GambarKitaSimpan;
print "</p>\n";
;
		
}
else
{
header("Content-Type: image/jpeg");
header("Content-Length: " . filesize($GambarKitaSimpan));
header("X-Pad: avoid browser bug");
}
		
print "<img class=thumber3 src='{$GambarKitaSimpan}'>";

function BikinFolder($KEPALA, $isbn, $TestingCode)
{
$parts = Array ($KEPALA, 
substr($isbn, 0, 3), 
substr($isbn, 3, 3), 
substr($isbn, 6, 3), 
substr($isbn, 9, 3));		
		
if (13 == strlen($isbn))
array_push($parts, substr($isbn, 12, 3));
$dirName = join('/', $parts);
if (file_exists($dirName))
return $dirName;
$path = $KEPALA;
for ($i = 1; $i < count($parts); $i++)
{
$path .= '/' . $parts[$i];
if ($TestingCode)
print "<p>Buat Folder di directory: $path</p>\n";
@mkdir($path);
}
return $dirName;
}

This work is licensed under CC BY-NC 4.0

Position has been confirmed

Syukur Alhamdulillah. Setelah berbulan-bulan bertungkus lumus menyiapkan apa yang patut, akhirnya telah membuahkan hasil apabila posisi sebagai Librarian di PETRONAS Petroleum Resource Centre telah disahkan oleh pihak berwajib. Maka dengan ini saya adalah Rakyat Kerajaan PETRONAS yang sah. Oleh itu, saya harus berusaha untuk mempertahankan kedudukan saya sebagai warga PETRONAS dengan bekerja dengan lebih iltizam lagi.

Mari kita lihat apa yang saya buat sepanjang waktu Probasi di PRC selama 6 bulan

The New PULSE
Seperti biasa, ini adalah benda pertama yang saya akan sentuh ditempat saya mula bekerja. Web Development dan Web Design adalah benda yang seronok dan cepat untuk dihasilkan. Ianya adalah benda yang dapat dilihat dan dibuktikan hanya dengan melayari laman tersebut. Kena pula dengan masanya, terdapat VIS (Visual Identification System) yang wajib diikuti, maka PULSE atau PETRONAS Ubiquitous Library Search Engine merupakan calon yang terbaik untuk dikerjakan. Rujuk sini : http://www.munmon.com/v3/2014/01/14/new-pulse/

Library Record Re-Index
Ini adalah proses automasi yang paling mencabar. Sebelum tahu selok belok Millennium ILS, memang sangat leceh. Ada Load tables, ada konsep overlay dan overlay protect. Tapi, syukur, kemampuan untuk memahami sesuatu dengan cepat adalah kurnianNya yang paling utama bisa membantu proses ini. Akhirnya kesemua BIB Record mempunyai location yang tepat dan para kataloger tidak lagi perlu memasukkan lokasi secara manual.

Upload Ebrary Records
Setelah berjaya memahami Load Tables dan Concept of Overlaying MARC records pada Millennium ILS, proses untuk update dan replace MARC record dapat dilakukan dengan jayanya. Terima Kasih diucapkan pada para pustakawan yang menyediakan maklumat ini di blog-blog mereka. Juga III kerana menyediakan manual yang mudah difahami. Dari sini, saya tahu cara-cara untuk replace, delete dan update MARC record menggunakan Data Exchange di Klien Millennium ILS.

Administer MyPRECISE Portal
Ini lagi satu benda pelik yang kena belajar. Dahulu kala saya menggunakan Drupal sebagai CMS, tetapi di PRC, kena guna Microsoft Sharepoint. Nasib baik mudah faham dan cepat belajar. Dibekalkan dengan pengalaman mengendali pelbagai jenis portal, belajar menggunakan Shareponint tidaklah begitu sukar. Natijahnya sama cuma caranya sahaja yang berbeza.

Begitulah beberapa perkara yang dilakukan sepanjang saya berada di peringkat dalam perhatian sebelum disahkan jawatan. Pokok pangkalnya, apa-apa sahaja yang diberi, hendaklah kita lakukan dengan terbaik. Di mana-mana pon kita berada, tugas yang diberi hendaklah dilakukan dengan penuh amanah dan penuh semangat. Itulah dia pesan ibu saya.

CSS problem with Internet Explorer

After spending many hours trying to looking for solution why some of the pages do not render correctly in Internet Explorer, finally I have found the answer. In Microsoft Help and Support : A webpage that uses CSS styles does not render correctly in Internet Explorer :

This problem occurs because the following conditions are true in Internet Explorer:

  • All style tags after the first 31 style tags are not applied.
  • All style rules after the first 4,095 rules are not applied.
  • On pages that uses the @import rule to continously import external style sheets that import other style sheets, style sheets that are more than three levels deep are ignored.

My 48 hours gone just like that. At 1st I thought there must be something wrong with one of the scripts. Alas I get the answer which is very annoying.

[img_assist|nid=1259|title=|desc=|link=node|align=none|width=400|height=187]

Futile Resistance : Defeating Anti-Right Click

Evening

Sometimes, I wonder why would a web-master disable the right-click function? Do these nerds really think that they can protect their contents by disabling our browsers’ context menu? Sometimes I laugh hysterically thinking of their futile efforts to disable the “Right Click”. Huhuhu.

Come on, It’s only JavaScript and can be defeated simply by disabling javascript. This is an archaic way of protecting your content. If you do not want people to steal your images or anything and such. Don’t even post it in the 1st place.

Sometimes, right-click is very useful and disabling it is very-very offensive. People do right-click for one of these reasons:

  • Learning Purposes
  • Designing Idea

Why you should not disable right-click

Reason #1 : Annoying
Users who are using gesture to open new tab or links will be the most annoyed with this so called protecting feature. Most function to open link in new tab or window lies within the context menu. This is too retards. Oh yeah. You can tell people to use Ctrl or Apple Command key to open link in new tab/window. What about people with only one hand?

[img_assist|nid=512|title=|desc=|link=node|align=none|width=500|height=161]

Reason #2 : Unprofessional and Insulting and very Offensive
Do you like to be treated like a thief? You don’t. No one does. Do unto others as you would have them do unto you. You don’t like to be treated like one. So don’t treat others like one. Capisc!!!

Reason #3 : It is Futile
This is 21st century. Generation X, Y and Z. The Google Generation. Protecting Site with disabling Right-Click is archaic. 5 years old kid knows how to disable javascript.

Thanks Doug

Drupal 6.XX Single Sign On

Salam Sejahtera

Setelah berhari-hari membaca dan memahami Documentation API untuk Drupal. Akhirnya, pening kepala saya itu memberikan hasil yang bagus. Dokumentasi itu amatlah penting, Tanpanya penulis skrip akan tersesat jauh kerana tidak faham akan process yang ada di Drupal. Bila dah paham barulah kita boleh menulis skrip mengikut suka kita.

Senario saya adalah seperti berikut, setiap pelajar perlu mempunyai akaun perpustakaannya yang tersendiri. Namun, tidak ada sebarang integrasi diantara Sistem Pelajar dengan Sistem Perpustakaan. Mungkin atas sebab keselamatan, atau isu kompatibiliti, Data Sharing antara database tidak boleh dilakukan.

Keduanya, oleh kerana tidak ada integrasi antara Sistem, pelajar menggunakan sebuah akaun Generic untuk semua aktiviti Perpustakaan (Online Database sahaja). Makna kata Pelajar A, Pelajar B, Staff A dan B menggunakan Akaun yang sama untuk akses ke Online Database. Sebenarnya lebih mudah begini, tetapi di penghujung cerita, kami tidak boleh membuat database tracking kepada pengguna. Kita tidak dapat membezakan Pengguna A dengan Pelajar B dan sebagainya.

Oleh itu, timbullah idea ini untuk mendaftarkan mereka secara automatik dikala mereka membuka portal perpustakaan. Macam2 functions yang saya guna antaranya ialah

  1. hook_form_alter
  2. user external login register
  3. dan macam2 lagi.

Namun, kesemua ini adalah komplikated dan panjang ceritanya. Akhirnya, terdapat satu function yang paling mudah dan murah. Cukup senang dan kecil. Iaitu user_save & user_authenticate. Simple sungguh penulisan skripnya.

Sebelum itu, kita kaji dahulu workflownya

  1. Login ke iPortal
  2. Kemudian Drupal akan check data pelajar samada wujud atau tidak
  3. Jika Wujud, Drupal akan Load datanya
  4. Jika tidak Drupal akan Create data Pelajar dan Load
  5. Login ke Sistem secara halus (Pengguna tidak perlu tahu akan hal ini)

Snippet nya adalah seperti berikut (Nanti saya install Code Filter)

<?php

$iportal_userdata = array (
'name' => "$name",
'pass' => "$password",
'mail' => "$email",
'status' => 1,
'init' => 'External Authentication'
);

if (!db_result(db_query("SELECT COUNT(*) FROM {users} WHERE name = '%s';", $name))) {
// Kalau Data Pelajar itu Tidak Wujud. Kita bikin baru untuk dia.
user_save (NULL, $iportal_userdata);
// Kemudian kita Load Data
user_authenticate ($iportal_userdata);
}

else {
// Kalau data Pelajar Wujud, Kita Load datanya
user_authenticate ($iportal_userdata);
}

?>

That dreaded IE6… [#2]

Throm-ka

Yesterday I made a post regarding that fakap IE6. Which is Web-Developers worst nightmares on earth. My nightmare. IE6 is the dying old man which refuses to retire. So I wrote a little script to force users to upgrade whenever they view the library portal.

However, after looking at the log files and google anal. report, I soon realize that forcing users to upgrade their browser is mean. So mean, to the extend that some users still stump upon the upgrade warning. (lol. they still asked me what to do). I do so believe the warning is so direct. Why some users still don’t get it.

Some users may not upgrade to the latest IE due to unlicensed copy of Windows (stop using pirated windows ler). Some users may not install alternative browsers due to Company Restrictions (what company is that… so evil). Due to this I will have to lift the force upgrade script.

So… once again hacks and workaround will do the trick. All this started with CSS compatibility issues. Some elements may not appear in IE6 and some element will break the page in IE6. Sometimes I will have to forget the beautiful effect and design since in IE6 the page will break. What a nuisance.

After searching for solutions how to these pages at least viewable in IE6 I come across the conditional codes. Hmm. Created by Microsoft for Internet Explorers.

One of the most common operations performed in a Web page is to detect the browser type and version. Browser detection is performed to ensure that the content presented to the browser is compatible and renders correctly. The browser type can be detected using many different techniques. Most methods of browser detection make use of script on the server or client.

This article introduces conditional comments, which offer certain advantages over scripted browser detection techniques. Conditional comments make it easy for developers to take advantage of the enhanced features offered by Microsoft Internet Explorer 5 and later versions, while writing pages that downgrade gracefully in less-capable browsers or display correctly in browsers other than Windows Internet Explorer. Conditional comments are the preferred means of differentiating Cascading Style Sheets (CSS) rules intended for specific versions of Internet Explorer.

Source : msdn.microsoft.com

After some reading I use these stupid IE codes

 <!--[if lte IE 6 ]><div id="bodoh"><![endif]-->
 <!--[if gte IE 7 ]><div id="panes"><![endif]-->
 <!--[if !IE]>--><div id="panes"><!--<![endif]-->

These codes will load specific line based on users’ browsers as explained in the links. I hate IE.

That dreaded IE6…

Throm-ka

Perhaps, web developers worst nightmare is Internet Explorer 6. I usually don’t give a damn to this issue. All troubles while developing site and designing web page, CSS issues, div placement with IE6, I will choose to create a friendlier version for IE6. Forget the those standards and try to make that page appear correctly in IE6. Why? One reason : some users still refuse to change. They would rather spend their time with that ageing IE6.

Bah! But today, after so sick with, real sick with IE6, I have decided to force users to upgrade their IE6 or you are not welcome. It is so hard to create one page that is friendly with IE6 but looks horrible with other browsers. NO! NO! NO! NO!. That’s not gonna happen today.

I have put a code to ask users to upgrade their Internet Explorer 6. I wonder, why users are still tagged with that stupid browser. What a nonsense! I mean, how on earth IE6, the world’s most Worst Tech Products still being used by the general public? Don’t the users know how bad is IE6.

  • As of January 10, 2009, Secunia reports 142 vulnerabilities in Internet Explorer 6
  • Security advisory site Secunia counted 20 unpatched security flaws for Internet Explorer 6, many more and older than for any other browser
  • IE6 does not fully support CSS version 2, unlike most browsers which in turn means web developers must use “hacks” or workarounds so IE6 will display web pages correctly.
  • Internet Explorer 6 is evil – pure and simple.

Finding myself through WP themes

Good Evening,

This is my 3rd times in this week alone I replace my WordPress Theme. Why? I just got fed up with the old themes. I just don’t like it anymore. Usually, I would restrain myself from keep on replacing themes. It requires tremendous works. A theme is just a theme, but, to enter www.munmon.com, a theme must have many things that amuse me. I am very picky. Yes, I am. Colours, CSS, customisation and appearance all must pass my Rigid “Seal of Quality“.

I had my own theme for the past few years. It was called Orange: munmonlisme. It was Hemingway inspired theme. That was my best self-created theme. CSS certified, XHTML certified and W3C compliant. All gone due to too inevitable computer disaster. And, I failed to pay my bill (my previous web hosting).

I just don’t have the time to start from scratch. Forget about creating a new WP theme. WP has changed a lot since the last time I created my own theme. I have much better things to do. Shall we take a look at the themes I have used? Hmmm. Let me see…..

When I 1st set-up the new munmonlisme (this is version 2), I searched for a theme that really appealed me. So enter the faleonis by flisterz. Used it for about 4 months. When I found out this theme did not render me shadow properly (your theme is great flisterz, but please blame Microsoft for their stupid IE) in IE, I started to search for new theme.

deLight seemed to appeal to me. Oh. Sorry, this theme is created by Simon, a web designer from German. This theme is pretty nice, but, I don’t like the wasted space in the sidebar. Scrap this one too. Then, I found Ship Ahoy by Theme Terminal. I seem to like this one. Must be for the pirate’s naming convention. Ahoy. I just love to be a pirate. Even dream to become one. The good old-time pirate with that amazing Jolly Roger. Sweet huh?

Yarrrrr! Tis me blog. Arrgh!, See Ya Chum!