Thumbnail CKFinder Tidak Tampil ( Solved )

Kemarin tanggal 26 September 2013 ada sebuah notifikasi pesan masuk di akun facebook saya, ternyata ada seorang teman yang mengalami kesulitan dalam memasang ckfinder pada aplikasi ujian online miliknya. Masalahnya adalah setelah mengupload aplikasi tersebut ke public hosting ckfinder tersebut tidak dapat menampilkan gambar yang diupload dalam bentuk thumbnail padahal ketika aplikasi tersebut diinstall di web server local ( komputer local ) hal tersebut tidak terjadi alias lancar jaya tanpa hambatan apapun.
Screenshot dari teman saya blank_thumb
Setelah saya membaca pesannya maka saya memberanikan diri untuk meminta screenshot dari aplikasi ujian online miliknya beserta dengan username dan password untuk masuk ke public hosting milik teman saya tadi ( padahal saya juga belum pernah mengalami hal tersebut pada ckfinder saya, hehehhehe …….. ) dan setelah beliau memberikannya saya segera beraksi untuk mencari tahu apa yang terjadi dengan ckfinder tersebut. Segera saja saya mencoba untuk login ke aplikasi ujian online teman saya tersebut dan mencoba ckfinder pada aplikasi tersebut, singkat cerita setelah berputar – putar melakukan percobaan akhirnya saya menemukan solusi yaitu ada pada folder ../ckfinder/core/connector/php/ didalamnya terdapat file error_log segera saja saya membukanya dan alhamdulillah ada petunjuk yang sangat jelas yaitu

[27-Sep-2013 13:39:29] PHP Warning: readfile() has been disabled for security reasons in /xxxxxxx/xxxxxx/public_html/cbt/include/ckfinder/core/connector/php/php5/CommandHandler/Thumbnail.php on line 123
[27-Sep-2013 13:39:47] PHP Warning: readfile() has been disabled for security reasons in /xxxxxxx/xxxxxx/public_html/cbt/include/ckfinder/core/connector/php/php5/CommandHandler/Thumbnail.php on line 123

Maka setelah penyebabnya ditemukan saya mencari solusinya dan sampailah saya pada alamat dan segera saja saya mengedit file /xxxxxxx/xxxxxx/public_html/cbt/include/ckfinder/core/connector/php/php5/CommandHandler/Thumbnail.php dengan text editor kesayangan saya geany, berikut ini hasil editan saya

<?php
/*
* CKFinder
* ========
* http://ckfinder.com
* Copyright (C) 2007-2011, CKSource - Frederico Knabben. All rights reserved.
*
* The software, this file and its contents are subject to the CKFinder
* License. Please read the license.txt file before using, installing, copying,
* modifying or distribute this file or part of its contents. The contents of
* this file is part of the Source Code of CKFinder.
*/
if (!defined('IN_CKFINDER')) exit;

/**
 * @package CKFinder
 * @subpackage CommandHandlers
 * @copyright CKSource - Frederico Knabben
 */

/**
 * Handle Thumbnail command (create thumbnail if doesn't exist)
 *
 * @package CKFinder
 * @subpackage CommandHandlers
 * @copyright CKSource - Frederico Knabben
 */
class CKFinder_Connector_CommandHandler_Thumbnail extends CKFinder_Connector_CommandHandler_CommandHandlerBase
{
    /**
     * Command name
     *
     * @access private
     * @var string
     */
    private $command = "Thumbnail";

    /**
     * handle request and send response
     * @access public
     *
     */
    public function sendResponse()
    {
        // Get rid of BOM markers
        if (ob_get_level()) {
            while (@ob_end_clean() && ob_get_level());
        }
        header("Content-Encoding: none");

        $this->checkConnector();
        $this->checkRequest();

        $_config =& CKFinder_Connector_Core_Factory::getInstance("Core_Config");

        $_thumbnails = $_config->getThumbnailsConfig();
        if (!$_thumbnails->getIsEnabled()) {
            $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_THUMBNAILS_DISABLED);
        }

        if (!$this->_currentFolder->checkAcl(CKFINDER_CONNECTOR_ACL_FILE_VIEW)) {
            $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_UNAUTHORIZED);
        }

        if (!isset($_GET["FileName"])) {
            $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST);
        }

        $fileName = CKFinder_Connector_Utils_FileSystem::convertToFilesystemEncoding($_GET["FileName"]);
        $_resourceTypeInfo = $this->_currentFolder->getResourceTypeConfig();

        if (!CKFinder_Connector_Utils_FileSystem::checkFileName($fileName)) {
            $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_INVALID_REQUEST);
        }

        $sourceFilePath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getServerPath(), $fileName);

        if ($_resourceTypeInfo->checkIsHiddenFile($fileName) || !file_exists($sourceFilePath)) {
            $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_FILE_NOT_FOUND);
        }

        $thumbFilePath = CKFinder_Connector_Utils_FileSystem::combinePaths($this->_currentFolder->getThumbsServerPath(), $fileName);

        // If the thumbnail file doesn't exists, create it now.
        if (!file_exists($thumbFilePath)) {
            if(!$this->createThumb($sourceFilePath, $thumbFilePath, $_thumbnails->getMaxWidth(), $_thumbnails->getMaxHeight(), $_thumbnails->getQuality(), true, $_thumbnails->getBmpSupported())) {
                $this->_errorHandler->throwError(CKFINDER_CONNECTOR_ERROR_ACCESS_DENIED);
            }
        }

        $size = filesize($thumbFilePath);
        $sourceImageAttr = getimagesize($thumbFilePath);
        $mime = $sourceImageAttr["mime"];

        $rtime = isset($_SERVER["HTTP_IF_MODIFIED_SINCE"])?@strtotime($_SERVER["HTTP_IF_MODIFIED_SINCE"]):0;
        $mtime =  filemtime($thumbFilePath);
        $etag = dechex($mtime) . "-" . dechex($size);

        $is304 = false;

        if (isset($_SERVER["HTTP_IF_NONE_MATCH"]) && $_SERVER["HTTP_IF_NONE_MATCH"] === $etag) {
            $is304 = true;
        }
        else if($rtime == $mtime) {
            $is304 = true;
        }

        if ($is304) {
            header("HTTP/1.0 304 Not Modified");
            exit();
        }

        //header("Cache-Control: cache, must-revalidate");
        //header("Pragma: public");
        //header("Expires: 0");
        header('Cache-control: public');
        header('Etag: ' . $etag);
        header("Content-type: " . $mime . "; name=\"" . CKFinder_Connector_Utils_Misc::mbBasename($thumbFilePath) . "\"");
        header("Last-Modified: ".gmdate('D, d M Y H:i:s', $mtime) . " GMT");
        //header("Content-type: application/octet-stream; name=\"{$file}\"");
        //header("Content-Disposition: attachment; filename=\"{$file}\"");
        header("Content-Length: ".$size);
        //readfile($thumbFilePath);

        $file = fopen($thumbFilePath, 'rb');
		if ( $file !== false ) {
		while ( !feof($file) ) {
        echo fread($file, 4096);
			}
			fclose($file);
		}

        exit;
    }

    /**
     * Create thumbnail
     *
     * @param string $sourceFile
     * @param string $targetFile
     * @param int $maxWidth
     * @param int $maxHeight
     * @param boolean $preserverAspectRatio
     * @param boolean $bmpSupported
     * @return boolean
     * @static
     * @access public
     */
    public static function createThumb($sourceFile, $targetFile, $maxWidth, $maxHeight, $quality, $preserverAspectRatio, $bmpSupported = false)
    {
        $sourceImageAttr = @getimagesize($sourceFile);
        if ($sourceImageAttr === false) {
            return false;
        }
        $sourceImageWidth = isset($sourceImageAttr[0]) ? $sourceImageAttr[0] : 0;
        $sourceImageHeight = isset($sourceImageAttr[1]) ? $sourceImageAttr[1] : 0;
        $sourceImageMime = isset($sourceImageAttr["mime"]) ? $sourceImageAttr["mime"] : "";
        $sourceImageBits = isset($sourceImageAttr["bits"]) ? $sourceImageAttr["bits"] : 8;
        $sourceImageChannels = isset($sourceImageAttr["channels"]) ? $sourceImageAttr["channels"] : 3;

        if (!$sourceImageWidth || !$sourceImageHeight || !$sourceImageMime) {
            return false;
        }

        $iFinalWidth = $maxWidth == 0 ? $sourceImageWidth : $maxWidth;
        $iFinalHeight = $maxHeight == 0 ? $sourceImageHeight : $maxHeight;

        if ($sourceImageWidth <= $iFinalWidth && $sourceImageHeight <= $iFinalHeight) {
            if ($sourceFile != $targetFile) {
                copy($sourceFile, $targetFile);
            }
            return true;
        }

        if ($preserverAspectRatio)
        {
            // Gets the best size for aspect ratio resampling
            $oSize = CKFinder_Connector_CommandHandler_Thumbnail::GetAspectRatioSize($iFinalWidth, $iFinalHeight, $sourceImageWidth, $sourceImageHeight );
        }
        else {
            $oSize = array('Width' => $iFinalWidth, 'Height' => $iFinalHeight);
        }

        CKFinder_Connector_Utils_Misc::setMemoryForImage($sourceImageWidth, $sourceImageHeight, $sourceImageBits, $sourceImageChannels);

        switch ($sourceImageAttr['mime'])
        {
            case 'image/gif':
                {
                    if (@imagetypes() & IMG_GIF) {
                        $oImage = @imagecreatefromgif($sourceFile);
                    } else {
                        $ermsg = 'GIF images are not supported';
                    }
                }
                break;
            case 'image/jpeg':
                {
                    if (@imagetypes() & IMG_JPG) {
                        $oImage = @imagecreatefromjpeg($sourceFile) ;
                    } else {
                        $ermsg = 'JPEG images are not supported';
                    }
                }
                break;
            case 'image/png':
                {
                    if (@imagetypes() & IMG_PNG) {
                        $oImage = @imagecreatefrompng($sourceFile) ;
                    } else {
                        $ermsg = 'PNG images are not supported';
                    }
                }
                break;
            case 'image/wbmp':
                {
                    if (@imagetypes() & IMG_WBMP) {
                        $oImage = @imagecreatefromwbmp($sourceFile);
                    } else {
                        $ermsg = 'WBMP images are not supported';
                    }
                }
                break;
            case 'image/bmp':
                {
                    /*
                    * This is sad that PHP doesn't support bitmaps.
                    * Anyway, we will use our custom function at least to display thumbnails.
                    * We'll not resize images this way (if $sourceFile === $targetFile),
                    * because user defined imagecreatefrombmp and imagecreatebmp are horribly slow
                    */
                    if ($bmpSupported && (@imagetypes() & IMG_JPG) && $sourceFile != $targetFile) {
                        $oImage = CKFinder_Connector_Utils_Misc::imageCreateFromBmp($sourceFile);
                    } else {
                        $ermsg = 'BMP/JPG images are not supported';
                    }
                }
                break;
            default:
                $ermsg = $sourceImageAttr['mime'].' images are not supported';
                break;
        }

        if (isset($ermsg) || false === $oImage) {
            return false;
        }


        $oThumbImage = imagecreatetruecolor($oSize["Width"], $oSize["Height"]);

        if ($sourceImageAttr['mime'] == 'image/png')
        {
            $bg = imagecolorallocatealpha($oThumbImage, 255, 255, 255, 127); // (PHP 4 >= 4.3.2, PHP 5)
            imagefill($oThumbImage, 0, 0 , $bg);
            imagealphablending($oThumbImage, false);
            imagesavealpha($oThumbImage, true);
        }

        //imagecopyresampled($oThumbImage, $oImage, 0, 0, 0, 0, $oSize["Width"], $oSize["Height"], $sourceImageWidth, $sourceImageHeight);
        CKFinder_Connector_Utils_Misc::fastImageCopyResampled($oThumbImage, $oImage, 0, 0, 0, 0, $oSize["Width"], $oSize["Height"], $sourceImageWidth, $sourceImageHeight, (int)max(floor($quality/20), 6));

        switch ($sourceImageAttr['mime'])
        {
            case 'image/gif':
                imagegif($oThumbImage, $targetFile);
                break;
            case 'image/jpeg':
            case 'image/bmp':
                imagejpeg($oThumbImage, $targetFile, $quality);
                break;
            case 'image/png':
                imagepng($oThumbImage, $targetFile);
                break;
            case 'image/wbmp':
                imagewbmp($oThumbImage, $targetFile);
                break;
        }

        $_config =& CKFinder_Connector_Core_Factory::getInstance("Core_Config");
        if (file_exists($targetFile) && ($perms = $_config->getChmodFiles())) {
            $oldUmask = umask(0);
            chmod($targetFile, $perms);
            umask($oldUmask);
        }

        imageDestroy($oImage);
        imageDestroy($oThumbImage);

        return true;
    }



    /**
     * Return aspect ratio size, returns associative array:
     * <pre>
     * Array
     * (
     *      [Width] => 80
     *      [Heigth] => 120
     * )
     * </pre>
     *
     * @param int $maxWidth
     * @param int $maxHeight
     * @param int $actualWidth
     * @param int $actualHeight
     * @return array
     * @static
     * @access public
     */
    public static function getAspectRatioSize($maxWidth, $maxHeight, $actualWidth, $actualHeight)
    {
        $oSize = array("Width"=>$maxWidth, "Height"=>$maxHeight);

        // Calculates the X and Y resize factors
        $iFactorX = (float)$maxWidth / (float)$actualWidth;
        $iFactorY = (float)$maxHeight / (float)$actualHeight;

        // If some dimension have to be scaled
        if ($iFactorX != 1 || $iFactorY != 1)
        {
            // Uses the lower Factor to scale the oposite size
            if ($iFactorX < $iFactorY) {
                $oSize["Height"] = (int)round($actualHeight * $iFactorX);
            }
            else if ($iFactorX > $iFactorY) {
                $oSize["Width"] = (int)round($actualWidth * $iFactorY);
            }
        }

        if ($oSize["Height"] <= 0) {
            $oSize["Height"] = 1;
        }
        if ($oSize["Width"] <= 0) {
            $oSize["Width"] = 1;
        }

        // Returns the Size
        return $oSize;
    }
}

lihat baris ke 123 fungsi readfile() telah saya ganti dengan fopen() dan fclose()
berikut ini hasilnya setelah saya mengeditnya
sman1-bpp

semoga bermanfaat, hanya berbagi pengalaman aja ………

Sistem Informasi Manajemen Desa ( simdesa )

Setelah sekian lama saya tidak menulis artikel di blog ini, rasanya kangen juga ingin berbagi dengan para pembaca sekalian ( gayane koyok akeh sing moco ae …….). Langsung saja kali ini saya akan membagikan sebuah aplikasi sederhana yang saya buat di waktu luang saya ( sok sibuk ceritane ) yaitu sistem informasi manajemen desa. Beberapa fitur yang tersedia dalam aplikasi tersebut adalah :

  1. Administrasi data kependudukan/li>
  2. Administrasi surat – menyurat
  3. Membuat laporan

Berikut ini video yang saya buat sebagai tutorial singkat untuk menjalankan aplikasi ini

Untuk yang mau mencoba ini saya sediakan source codenya Download disini
Untuk manual aplikasi belum buat, kalo ada kritik dan saran monggo disampaikan

Ujian Online Sederhana

Ujian online sederhana demikianlah judul yang saya ambil dalam tulisan ini, aplikasi ini awalnya saya buat ketika melakukan praktek kerja lapangan di SMA Muhammadiyah 08 Cerme Gresik. Dari judulnya saya yakin anda sekalian pasti telah memiliki gambaran tentang aplikasi saya ini. Fitur utama dari aplikasi ini adalah sebagai berikut :

  1. kemampuan membuat soal dan pilihan jawaban menggunakan gambar dengan memanfaatkan text editor ckeditor
  2. penggunaan timer ketika siswa mengerjakan ujian secara online dan siswa dapat melihat kembali detail jawaban yang diberikan ketika ujian tersebut

Baca pos ini lebih lanjut

Membuat Plugin Jquery Lightbox Sendiri

Demo Aplikasi Plugin
Setelah kemarin kita telah belajar membuat sebuah plugin sederhana untuk jquery maka selanjutnya kita akan membuat sebuah plugin yang sedikit lebih sulit yaitu plugin untuk membuat efek seperti lightbox, fancybox atau colorbox. Meskipun sebenarnya telah banyak plugin – plugin keren yang sudah tersebar di internet, namun disini saya membuatnya sendiri agar saya lebih paham dengan jquery dan teknik – teknik yang sering digunakan. Baca pos ini lebih lanjut

Countdown Timer Dengan Jquery

Dalam kesempatan kali ini saya akan berbagi sedikit tips membuat countdown sederhana yang bisa digunakan dalam aplikasi seperti ujian online. Dimana dalam ujian online tersebut biasanya diberikan batas waktu dalam mengerjakan ujian dan bila user melakukan refresh halaman web maka waktu juga harus tetap berjalan tidak mengulang dari awal. Untuk itu disini saya akan menggunakan bantuan jquery Download disini, jquery.countdown.js Download disini dan menggunakan $_SESSION php untuk terus memastikan waktu terus berjalan meskipun halaman direfresh ulang. Oke karena kodenya cukup sederhana maka langsung saja saya tampilkan kode programnya dibawah ini


<?php
session_start();
if(isset($_SESSION["mulai_waktu"])){
 $telah_berlalu = time() - $_SESSION["mulai_waktu"];
 }
else {
 $_SESSION["mulai_waktu"] = time();
 $telah_berlalu = 0;
 }
?>
<script type="text/javascript" src="js/jquery-1.5.1.min.js"></script>
<script type="text/javascript" src="js/jquery.countdown.js"></script>
<div id="tempat_timer">
<span id="timer">00 : 00 : 00</span>
</div>
<script type="text/javascript">
function waktuHabis(){
 alert("selesai dikerjakan ......");
 }
function hampirHabis(periods){
 if($.countdown.periodsToSeconds(periods) == 60){
 $(this).css({color:"red"});
 }
 }
$(function(){
 var waktu = 180; // 3 menit
 var sisa_waktu = waktu - <?php echo $telah_berlalu ?>;
 var longWayOff = sisa_waktu;
 $("#timer").countdown({
 until: longWayOff,
 compact:true,
 onExpiry:waktuHabis,
 onTick: hampirHabis
 });
 })
</script>
<style>
#tempat_timer{
 margin:0 auto;
 text-align:center;
 }
#timer{
 border-radius:7px;
 border:2px solid gray;
 padding:7px;
 font-size:2em;
 font-weight:bolder;
 }
</style>

Keterangan singkat

session_start();
if(isset($_SESSION["mulai_waktu"])){
$telah_berlalu = time() - $_SESSION["mulai_waktu"];
}
else {
$_SESSION["mulai_waktu"] = time();
$telah_berlalu = 0;
}

kode diatas akan mencatat waktu pertama kali user membuka halaman tersebut dan menyimpannya dalam variabel $_SESSION[“waktu_mulai”] dan menghitung waktu yang telah digunakan sehingga dapat dihitung pula waktu yang tersisa.

$(function(){
 var waktu = 180; // 3 menit
 var sisa_waktu = waktu - <?php echo $telah_berlalu ?>;
 var longWayOff = sisa_waktu;
 $("#timer").countdown({
 until: longWayOff,
 compact:true,
 onExpiry:waktuHabis,
 onTick: hampirHabis
 });
 })

Kode diatas adalah kode utama dari countdown timer ini dan dijalankan ketika halaman telah diload dengan sempurna untuk konfigurasi setting jquery.countdown.js anda dapat membacanya secara langsung disitus resminya di http://keith-wood.name/countdown.html

Source code Download disini
Semoga bermanfaat …………. tinggalkan komentar jika ingin bertanya

Form Ala Aplikasi Desktop

Sengaja saya memberi tulisan ini dengan judul diatas, karena disini kita akan membuat sebuah form yang dibuat semirip mungkin dengan form pada aplikasi desktop. Perbedaan utama yang paling saya rasakan ketika mengisi form pada aplikasi web dan aplikasi desktop adalah perpindahan dari sebuah field inputan ke field inputan berikutnya. Pada aplikasi desktop kita dapat menggunakan tombol enter  sedangkan pada aplikasi web bila kita menggunakan tombol Enter maka yang terjadi adalah data kita dalam form akan segera dikirim ke server ( proses submit ). Baca pos ini lebih lanjut

Convert grafik flash menjadi image

Sebenarnya ide  ini muncul ketika seorang teman bertanya kepada saya bagaimana caranya mengubah grafik yang digenerate oleh fusionchart free menjadi sebuah image (.jpg / .png) tujuannya adalah agar gambar tersebut bisa ditampilkan dalam laporan dengan format pdf  ( konversi menggunakan tcpdf ). Setelah bertanya kepada mbah google dan berkunjung ke situs fusionchart free akhirnya didapat sebuah kesimpulan untuk versi free hal ini sangat sulit dilakukan, akhirnya saya mencoba untuk mencari tools lain yang dapat mengenerate grafik dalam format flash seperti fusionchart free sehingga jatuhlah pilihan saya pada open flash chart 2 ( http://teethgrinder.co.uk/open-flash-chart-2/ ).
Baca pos ini lebih lanjut

Menambah dan Mengurangi Option List di Combo Box (Select)

Dalam kesempatan kali ini kita akan sedikit bermain – main dengan elemen select ( combo box ), dimana kita akan mencoba untuk menambahkan dan menghapus option list ( daftar pilihan ) dalam sebuah halaman web menggunakan jquery. Baiklah langsung saja kita lihat code yang telah saya buat berikut ini : Baca pos ini lebih lanjut

Perulangan (Looping) Sederhana

Looping atau perulangan , seleksi kondisi merupakan dua hal yang sangat penting diketahui bila anda berminat untuk terjun ke dunia pemrograman komputer, tidak perduli bahasa apa yang anda gunakan tetap saja anda akan bersentuhan dengan yang namanya looping dan seleksi kondisi. Untuk saat ini saya akan membahas sedikit mengenai looping dan dalam contoh kasus ini saya menggunakan bahasa pemmrograman php dan javascript. Baca pos ini lebih lanjut