768x90 Getting Online Shouldn't be Tough- $7.49 .com Domains at Go Daddy

Create and Update Google Contact from Ruby without Batch

There's less information about ruby on rails method in google contact. I would like to share you about how to export new google contact / create new google contact from our table contacts through Ruby.

in my contacts_controller.rb, i wrote this script


class ContactsController < ApplicationController
require 'yaml'
require 'cgi'
before_filter :prepare_google_contact, :expect => [:create, :update]
CONTACTS_SCOPE = 'http://www.google.com/m8/feeds/'

def create
@contact = Contact.new(params[:contact])

respond_to do |format|
if @contact.save
feed = @google_contact.post( CONTACTS_SCOPE + 'contacts/default/base', google_contact(@contact)).to_xml
@contact.update_attribute(:google_contact_id, feed.elements['id'].text)
flash[:notice] = 'Contact was successfully created.'
format.html { redirect_to(@contact) }
format.xml { render :xml => @contact, :status => :created, :location => @contact }
format.fxml { render :fxml => @contact }
else
format.html { render :action => "new" }
format.xml { render :xml => @contact.errors, :status => :unprocessable_entity }
format.fxml { render :fxml => @contact.errors }
end
end
end

# PUT /contacts/1
# PUT /contacts/1.xml
# PUT /contacts/1.fxml
def update
@contact = Contact.find(params[:id])
@saved = @contact.update_attributes(params[:contact])

respond_to do |format|
if @saved
@google_contact.headers = {'If-Match'=>'*'}
feed = @google_contact.put(@contact.google_contact_id,
create_google_contact(@contact.reload())).to_xml
flash[:notice] = 'Contact was successfully updated.'
format.html { redirect_to(@contact) }
format.xml { head :ok }
format.fxml { render :fxml => @contact }
else
format.html { render :action => "edit" }
format.xml { render :xml => @contact.errors, :status => :unprocessable_entity }
format.fxml { render :fxml => @contact.errors }
end
end
end

private

def prepare_google_contact
contact_setup = YAML.load_file("#{RAILS_ROOT}/config/contact.yml")
contact_setup["google"].each { |key, value| instance_variable_set("@#{key}", value) }
@google_contact = GData::Client::Contacts.new({
:authsub_scope => 'http://www.google.com/m8/feeds/',
:source => 'google-DocListManager-v1.1',
:version => '3.0'})
session[:token_contact] = @google_contact.clientlogin(@email_contact, @password_contact)
@contact_entry = <<-EOF
<entry xmlns="http://www.w3.org/2005/Atom"
xmlns:contact="http://schemas.google.com/contact/2008"
xmlns:gd="http://schemas.google.com/g/2005">

<category term='http://schemas.google.com/contact/2008#contact'
scheme='http://schemas.google.com/g/2005#kind'/>
EOF

session[:token_contact] = @google_contact.clientlogin(@email_contact, @password_contact)
end

def google_contact(contact)
data = <<-EOF
#{@contact_entry}
<title>#{contact.first_name}</title>
<content>#{contact.note}</content>
<gd:name>
<gd:fullName>#{contact.first_name}</gd:fullName>
</gd:name>
<gContact:birthday when='#{contact.birth_day}'/>
<gd:email primary='true' rel='http://schemas.google.com/g/2005#home' address='#{contact.email}'/>
<gd:phoneNumber rel='http://schemas.google.com/g/2005#mobile'>#{contact.mobile}</gd:phoneNumber>
<gd:phoneNumber rel='http://schemas.google.com/g/2005#work'>#{contact.phone}</gd:phoneNumber>
<gd:structuredPostalAddress rel='http://schemas.google.com/g/2005#home'>
<gd:formattedAddress>#{contact.street}
#{contact.city}
#{contact.province}, #{contact.zipcode}
#{contact.country}
</gd:formattedAddress>
</gd:structuredPostalAddress>
</entry>
EOF
return data
end

end


in this study case I put my login google information in config/contact.yml file like this :


google:
email_contact: yacobus.r@kiranatama.com
password_contact: dec.07.1982


and here is my contact migration script lines :

class CreateContacts < ActiveRecord::Migration
def self.up
create_table :contacts do |t|
t.string :first_name
t.string :middle_name
t.string :last_name
t.string :phone
t.string :mobile
t.string :email
t.string :street
t.string :province
t.string :zipcode
t.string :city
t.string :country
t.string :note
t.string :type
t.string :google_contact_id
t.timestamps
end
end

def self.down
drop_table :contacts
end
end


and of course you have to install gem install gdata

Do not confuse about "format.fxml" this is respond data type for Restfulx (Flex/Air Framework).

Simple right !! but when this written's published, google still not release how to create and update trough ruby on rails. And many developer stucked because google provided create and update contact trough Batch method.

Basic Authentication in Flex or Air

After discussing about AuthSub and ClientLogin in Google in Flex or Air, now I would like to step forward about Basic authentication in Flex or Air. To know more about Basic Authentication please browse to this link https://mail.google.com/mail/feed/atom/all , you will be asked by pop up window to enter your login information right? now let we see how to handle it :



<mx:VBox
xmlns:mx = "http://www.adobe.com/2006/mxml"
width = "100%"
height = "100%"
verticalAlign = "middle"
horizontalAlign = "center"
backgroundColor = "#364a59"
creationComplete= "{creationHandler()}"
>

<mx:Script>
<![CDATA[

import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.mxml.HTTPService;
import mx.utils.*;

private function creationHandler():void{
gmailService.headers = {Authorization:"Basic " + basicAuth()};
gmailService.url = "https://mail.google.com/mail/feed/atom/all"
gmailService.contentType = "application/x-www-form-urlencoded"
gmailService.resultFormat = "e4x"
gmailService.addEventListener(ResultEvent.RESULT, feedSuccess);
gmailService.addEventListener(FaultEvent.FAULT, faultHandler);
gmailService.send(); //Update Here
}

private function basicAuth():String{
var encoder:Base64Encoder = new Base64Encoder();
encoder.insertNewLines = false;
encoder.encode("yacobus.r@kiranatama.com:Dec.07.1082"));
return String(encoder);
}

private function feedSuccess(event:ResultEvent):void{
//Do any logic for feed result here
trace(XML(event.result))
}


private function faultHandler(event:FaultEvent):void{

}

]]>
</mx:Script>

<mx:HTTPService id="gmailService" showBusyCursor="true"/>

</mx:VBox>


Perfect right!!

AuthSub Authentication on Flex or Air

There are 3 types of authentication on when you are accessing website nowdays, they are :

  1. AuthSub / ClientLogin authentication, this authentication uses credential login information and give back to you authentication token that will be used on header as security login token to make you available login in 24 hours.
  2. OAuth authentication, this authentication is using secret key and customer key, more secure than AuthSub, this kind authentication will use your token and secret token in header Authentication information to identify you are the valid user when accessing secure data or page.
  3. Basic Authentication, if you see pop up alert that ask you to enter username or password, that is Basic Authentication.
Now i would like to share you about how to make those authentication become autologin without you face on their login page. First let discuss AuthSub or ClientLogin :

Now, try access this page : http://docs.google.com/feeds/documents/private/full

You will see error like this Authorization required, Error 401. These scripts all you need to pass the authentication easily :

you can use or just a class of HTTPService.


<mx:VBox
xmlns:mx = "http://www.adobe.com/2006/mxml"
width = "100%"
height = "100%"
verticalAlign = "middle"
horizontalAlign = "center"
backgroundColor = "#364a59"
creationComplete= "{creationHandler()}"
>

<mx:Script>
<![CDATA[

import mx.rpc.events.FaultEvent;
import mx.rpc.events.ResultEvent;
import mx.rpc.http.mxml.HTTPService;
import mx.utils.*;

private function creationHandler():void{
var data:Object = new Object;
data.Email = "yacobus.r@kiranatama.com";
data.Passwd = "Dec.07.1082"
data.accountType = "GOOGLE";
data.service = "writely";
//ClientLogin Url : https://www.google.com/accounts/ClientLogin
//AuthSub Url : https://www.google.com/accounts/AuthSubRequest
gmailService.url = "https://www.google.com/accounts/ClientLogin";
gmailService.contentType = "application/x-www-form-urlencoded";
gmailService.method = "POST";
gmailService.request = data;
gmailService.addEventListener(ResultEvent.RESULT, successHandler);
gmailService.addEventListener(FaultEvent.FAULT, faultHandler);
gmailService.send();
}

private function successHandler(event:ResultEvent):void{
gmailService.removeEventListener(ResultEvent.RESULT, new Function);
var txtAuth:String = String(event.result);
var authPosition:int = txtAuth.search("Auth");
txtAuth = txtAuth.substring(authPosition);
txtAuth = txtAuth.replace("Auth=","");
authPosition = txtAuth.length;
authPosition = authPosition - 1;
txtAuth = txtAuth.substring(0,authPosition);

accessProtectedUrl(txtAuth);
}

private function accessProtectedUrl(txtAuth:String):void{

gmailService.headers = {Authorization:"GoogleLogin auth="+txtAuth};
gmailService.url = "http://docs.google.com/feeds/documents/private/full";
gmailService.method = "GET";
gmailService.addEventListener(ResultEvent.RESULT, feedSuccess);
gmailService.addEventListener(FaultEvent.FAULT, faultHandler);
}

private function feedSuccess(event:ResultEvent):void{
//Do any logic for feed result here
trace(XML(event.result))
}


private function faultHandler(event:FaulttEvent):void{

}


]]>
</mx:Script>

<mx:HTTPService id="gmailService" showBusyCursor="true"/>

</mx:VBox>


List of Google Apps Service : http://code.google.com/apis/base/faq_gdata.html#clientlogin

How to make Air Application become iPhone SDK

Adobe air is great and smooth desktop application, many developers of Air dream their application can be installed into iPhone SDK. Now that dream come true. Thanks to my friend auraAnar for this great information :

First thing you do is downloading editor Eclips (like Flex Builder) from openplug.com, once you have successfully download it, create new project, in this show case i would to create sample parking searcher based on google Map for iPhone SDK.


Preview builder application

  1. Create WindowedApplication example project name is parkingApp.mxml
  2. Design indexView for iPhone application, let's called it as indexView.mxml (click the link)
  3. For component you can use mx:xxx like Flex or Air, but for control you should use mob:xxx from openPlug. Take a look my textinput Here
  4. Here is the screenshot of iPhone Emulator :


Preview Emulator


Once you success compiling your script without error, you need XCode of Apple to compile your script to iPhone SDK, i am using this way to compile my script in XCode. Happy iPhoning.

PS: I've tried commiting my script to google codes but it seems the google SVN is under maintenance, once it works i will upload the sample codes. Here is the address:

svn checkout http://airiphone.googlecode.com/svn/trunk/

AutoLogin to google account in Air without Oauth

i believe a part number of you there want their application allow the user to enter google account credential information to access the page, right? It's like i were faced off in my project. So how we will do it ?

If you use webservice, here's the information you should send to air application :
Google Account Credential Information and CallBack Url (the next url you want go after login)
I believe to access protected google page it will asked thridparty login, right? Note: OAuth, AuthSub and ClientLogin will not allow you to remote interface specially page after login google. In this case i create a component which is called GoogleBrowser.mxml and here the codes:

 <?xml version="1.0" encoding="utf-8"?>
  

     <mx:Window xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" 
                   width="600" height="600" backgroundColor="#242424"
                   creationComplete="init()"  >

     <mx:Script>
      <![CDATA[
         private var googleUserName:String = "yacobus.r@kiranatama.com";
         private var googlePassword:String = "i_love_u";
         private var nextUrl:String = "http://docs.google.com/a/kiranatama.com/Doc?docid=0AWbobJ8BSfPlZGcyaGtiYmJfMjlkajlwc3hncw&hl=en";  

         private function init():void{
           browserStack.selectedIndex = 1;
           gdocHtml.addEventListener(Event.COMPLETE, onCompleteHandler);
           gdocHtml.location = nextUrl;
         }

   
         private function onCompleteHandler(event:Event):void{
           gdocHtml.removeEventListener(Event.COMPLETE, removeListenerHandler);
           var additionalScript:String = '<script type="text/javascript">\n'+
                                   "gaia_setFocus();\n" + 
                                   "document.gaia_loginform.submit();\n"+
                                   "</script>";
           var username:String = googleUserName.split("@")[0];
           var body:String = String(event.target.htmlLoader.window.document.body.innerHTML);
           body = body.replace('id="Passwd"','id="Passwd" value="'+googlePassword+'" ');
           body = body.replace('value="" class','value="'+username+'" class"');
           body = body + addScript;
           gdocHtml.htmlLoader.window.document.body.innerHTML = body;
           browserStack.selectedIndex = 0;
          }

           private function removeListenerHandler(event:Event):void{
              event.stopPropagation();
           }

        ]]>
      </mx:Script>

      <mx:ViewStack id="browserStack" width="100%" height="100%">
        <mx:Canvas width="100%" height="100%">
          <mx:HTML width="100%" height="100%" id="gdocHtml" />    
        </mx:Canvas>
        <mx:Text id="loadingText" text="Loading ..." />
      </mx:ViewStack>  
</mx:Window>

Autocomplete from arrayCollection data in Flex and Air

Autocomplete is still high traffic in search engine for flex or action script, although it has plugin or component now (FLEX 4 is available). But now i would like to share you my script about how find documents, which is stored in arrayCollection and reflect with autocomplete textInput. here the sample code :

CASE:
In a form there's Multiple selection List the List can be clicked multiply or can be selected using auto complete in text input. the List dataProvider is from arrayCollection. The arrayCollection is filled by data from database.

  <mx:VBox
     xmlns:mx = "http://www.adobe.com/2006/mxml"
     width = "100%"
     height = "100%"
     creationComplete = "{onComplete()}" >

  <mx:Script>
      <![CDATA[

   private var docDummyData:ArrayCollection = new ArrayCollection(
                              [{id:234, title:"qwerty data"}], 
                              [{id:1020, title:"employee data"}],
                              [{id:1033, title:"salary data"}],
                              [{id:643, title:"tomorrow presentation"}],
                              [{id:721, title:"kiranatama human resource"}],
                              [{id:162, title:"flex and air outsource"}],
                              [{id:905, title:"ruby on rails docs"}],
                              [{id:453, title:"and many more"}]);

    private var copyData:ArrayCollection = new ArrayCollection;

    private function onComplete():void{
      copyData = docDummyData;
      docDummyData.sort = sortDoc();
      docDummyData.refresh();
      listDocuments.dataProvider = docDummyData;
    }

    private function sortDoc():Sort{
       var mySort:Sort = new Sort();
       var sortLevel:SortField = new SortField("title");
       sortLevel.numeric = false;
       sortLevel.descending = false;
       mySort.fields = [sortLevel];
       return mySort;
    }

    private function filterTitle(item:Object):Boolean
    {
      var arrTxtDocs:Array = txtGDocs.text.split(", ");
      var keyWord:String = String(arrTxtDocs[arrTxtDocs.length-1]);
      listDocuments.scrollToIndex(0); // scrolled the top item
      i++;
      return item['title'].match(new RegExp(keyWord,"i")); 
    }

    private function onTyping():void{
      if(listDocuments.dataProvider != null){
        docDummyData.filterFunction = filterTitle;
        docDummyData.refresh();
       }
    }

    private function detectEnter(event:KeyboardEvent):void{

       if(event.charCode == 13){
         listDocuments.selectedIndex = i;
        if(docDummyData.length < 1){
         Alert.show("This Document is not exist or invalid");   
        }else{
         var arrInputDoc:Array = txtGDoc.text.split(",");
         arrInputDoc[arrInputDoc.length-1] = String(listDocuments.selectedItem.title)+ ", ";
         txtGDoc.text = arrInputDoc.join(", ");
         docDummyData = copyData;
         docDummyData.refresh();
         listDocuments.invalidateDisplayList();
        }
      }
    }

    private function onSelectDocs(event:ListEvent):void{
       var arrDocTitles:Array = listDocuments.selectedItems;
       var strText:String = txtGDocs.text;

       for(var i:int = 0; i < arrDocTitles.length;i++){
         var nameTitle:String = arrDocTitles[i].title.toString();
         txtGDocs.text += nameTitle+ ', ';
       }
     }
   ]]>
  </mx:Script>

  <mx:Text  text="Please enter your document title" width="100%"/>
  <mx:TextInput width="100%"
           id="txtGDocs"
           change="{onTyping()}"
           keyDown="detectEnter(event)"/>

   <mx:List id="listDocuments"
      labelField="title"
      rowCount="5"
      itemClick="{onSelectDocs(event)}"
      width="100%" 
     allowMultipleSelection="true"/>         
  </mx:VBox>        



That's all :), any body know how to make code sniped like wordpress in blogspot ?

Servicing Restful CakePHP in Flex/Air

I have found a great framework of Dima Berastau which is called Restfulx, this framework is helping you to abstract your application from repetitive CRUD code and switch/synchronize between various data providers with minimal effort, very suitable for Ruby on rails and Phyton(Django) Developers. What about PHP?

Honestly Restfulx is suitable for php developer like CakePHP, CodeIgniter or any MVC and Restful framework as their webservice in flex or Air. But now I would like to share about simple Restful webservice utility for php framework, my handmade, if i get wrong please send me feedback correction.

The main idea of using is :
//http://localhost/baking_cake/users/?first_name=yacobus

RestfulPhp.index(User,{first_name: "yacobus"}, onIndexSuccess, onIndexFailure);


//http://localhost/baking_cake/users
  var params:Object = new Object;
  params.first_name = "yacobus";
  params.last_name = "reinhart";
  params.current_company = "kiranatama.com";
  RestfulPhp.add(User,params, onCreateSuccess, onCreateFailure);



  //http://localhost/baking_cake/users/7.xml
  var params:Object = new Object;
  params.id = "7";
  params.first_name = "yacobus";
  params.last_name = "reinhart";
  params.current_company = "www.wgs.co.id";
  RestfulPhp.edit(User,params, onEditSuccess, onEditFailure);


  //http://localhost/baking_cake/users/7.xml
  RestfulPhp.show(User,{id: "7"}, onShowSuccess, onShowFailure);

  //http://localhost/baking_cake/users/7.xml
  RestfulPhp.delete(User,{id: "7"}, onDeleteSuccess, onDeleteFailure);

First step and the last are :

you should create utility class or any class name that will have function as webservice, for example : I create RestfulPhp in com.reinhartlab.share


package com.teapoci.share
{
  import flash.utils.getQualifiedClassName;
  import mx.messaging.messages.HTTPRequestMessage;
  import mx.rpc.events.FaultEvent;
  import mx.rpc.events.ResultEvent;
  import mx.rpc.http.HTTPService;

  public class RestfulPhp {

    private static var restful:RestfulPhp;
    private static var baseURL:String = "http://localhost/baking_cake/";
    public static function getInstance():RestfulPhp {
      (restful == null) ? restful = new RestfulPhp();
      return restful;
    }

    public function index(model:Class, params:Object = null, successFunction:Function = null, faultFunction: Function = null, resultFormat:String = "e4x"):void
    {
      var sendData:XML = ;
      var httpService : HTTPService = new HTTPService();
      httpService.contentType = "text/xml";
      httpService.method = HTTPRequestMessage.GET_METHOD;
      doHttpService(model, httpService, "GET", resultFormat, params, successFunction,  faultFunction);
     }

     public function add(model:Class, resultFormat:String = "e4x"):void{
       var sendData:XML = ;
       var httpService : HTTPService = new HTTPService();
       httpService.contentType = "text/xml";
       httpService.method = HTTPRequestMessage.POST_METHOD;
       doHttpService(model, httpService, "POST", resultFormat, params, successFunction, faultFunction);
     }

     public function edit(model:Class, params:Object = null, successFunction:Function = null, faultFunction: Function = null, resultFormat:String = "e4x"):void
     {
        var sendData:XML = ;
        var httpService : HTTPService = new HTTPService();
        httpService.contentType = "text/xml";
        httpService.method = HTTPRequestMessage.PUT_METHOD;
        doHttpService(model, httpService, "PUT", resultFormat, params, successFunction, faultFunction);
     }

     public function delete(model:Class, params:Object = null, successFunction:Function = null, faultFunction: Function = null, resultFormat:String = "e4x"):void
     {
         var httpService : HTTPService = new HTTPService();
         httpService.contentType = "text/xml";
         httpService.method = HTTPRequestMessage.DELETE_METHOD;
         doHttpService(model, httpService, "DELETE", resultFormat, params, successFunction, faultFunction);
     }

     public function show(model:Class, params:Object = null, successFunction:Function = null, faultFunction: Function = null, resultFormat:String = "e4x"):void
     {
         var httpService : HTTPService = new HTTPService();
         httpService.contentType = "text/xml";
         httpService.method = HTTPRequestMessage.GET_METHOD;
         doHttpService(model, httpService, "GET", resultFormat, params, successFunction, faultFunction);
     }

     private function doHttpService(_model:Class, _service:HTTPService, _method:String, _format:String, _params:Object,_onSuccess:Function, _onFailure:Function):void
     {         
         var sendData:XML = ;
         (_params!= null) ? sendData.appendChild(_params);
         var controllerUrl:String = flash.utils.getQualifiedClassName(_model)+"s";
         _service.url =  baseURL + controllerUrl;
        if(_method != "POST" && _params.id != null){
        _service.url = _service.url + "/" + String(_params.id)+".xml";
      }
             

     _service.headers = {"REQUEST_METHOD": _method,
                         "X_HTTP_METHOD_OVERRIDE": _method};
     _service.resultFormat = _format;
     _service.addEventListener( ResultEvent.RESULT, _onSuccess);

     if(_onFailure != null )
       _service.addEventListener( FaultEvent.FAULT, _onFailure );

     _service.send( sendData ); 

   }
  }
}             

Resize image to squared in CakePHP

The code is almost closer with my previous article, just change function resize_image to square_image


function crop_img($imgname, $scale, $filename) {

$filetype = $this->getFileExtension($imgname);

$filetype = strtolower($filetype);


switch($filetype){


case "jpeg":


case "jpg":


$img_src = ImageCreateFromjpeg ($imgname);


break;


case "gif":


$img_src = imagecreatefromgif ($imgname);


break;


case "png":


$img_src = imagecreatefrompng ($imgname);


break;


}


$width = imagesx($img_src);


$height = imagesy($img_src);


$ratiox = $width / $height * $scale;


$ratioy = $height / $width * $scale;


//-- Calculate resampling


$newheight = ($width <= $height) ? $ratioy : $scale;


$newwidth = ($width <= $height) ? $scale : $ratiox;


//-- Calculate cropping (division by zero)


$cropx = ($newwidth - $scale != 0) ? ($newwidth - $scale) / 2 : 0;


$cropy = ($newheight - $scale != 0) ? ($newheight - $scale) / 2 : 0;


//-- Setup Resample & Crop buffers


$resampled = imagecreatetruecolor($newwidth, $newheight);


$cropped = imagecreatetruecolor($scale, $scale);


//-- Resample


imagecopyresampled($resampled, $img_src, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);


//-- Crop


imagecopy($cropped, $resampled, 0, 0, $cropx, $cropy, $newwidth, $newheight);


// Save the cropped image


switch($filetype)


{


case "jpeg":


case "jpg":


imagejpeg($cropped,$filename,80);


break;


case "gif":


imagegif($cropped,$filename,80);


break;


case "png":


imagepng($cropped,$filename,80);


break;


}


}

function crop_img($tempFile, $scale, $newFile) {

$filetype = $this->getFileExtension($tempFile);

$filetype = strtolower($tempFile);

switch($filetype) {

case "jpeg":

case "jpg":

 $img_src = imagecreatefromjpeg($tempFile);

 break;

case "gif":

$img_src = imagecreatefromgif ($tempFile);

break;

case "png":

$img_src = imagecreatefrompng ($tempFile);

case "bmp":

$img_src = imagecreatefromwbmp ($tempFile);

break;

}

$width = imagesx($img_src);

$height = imagesy($img_src);

$scale = explode('x',strtolower($size));

$ratiox = $width / $height * $scale[0];

$ratioy = $height / $width * $scale[0];

//-- Calculate resampling

$newheight = ($width <= $height) ? $ratioy : $scale[0];

$newwidth = ($width <= $height) ? $scale[0] : $ratiox;

//-- Calculate cropping (division by zero)

$cropx = ($newwidth - $scale != 0) ? ($newwidth - $scale) / 2 : 0;

$cropy = ($newheight - $scale != 0) ? ($newheight - $scale) / 2 : 0;

//-- Setup Resample & Crop buffers

$resampled = imagecreatetruecolor($newwidth, $newheight);

$cropped = imagecreatetruecolor($scale[0], $scale[0]);

//-- Resample

imagecopyresampled($resampled, $img_src, 0, 0, 0, 0, $newwidth, $newheight, $width, $height);

//-- Crop

imagecopy($cropped, $resampled, 0, 0, $cropx, $cropy, $newwidth, $newheight);

// Save the cropped image

switch($filetype)

{

case "jpeg":

case "jpg":

imagejpeg($cropped,$newFile,80);

break;

case "gif":

imagegif($cropped,$newFile,80);

break;

case "png":

imagepng($cropped,$newFile,80);

break;

}

}

Upload and Resize Image in CakePHP

I have spent many hours to see articles about resizing and uploading image in cakePHP, almost of them are sounding sucks for me like resizing on View by accessing or injecting the url or copy paste by another written without testing code. Event I was trying to convert AkImage from Akelos (Closer to ImageMagick in Rails) but got bunch of errors.

Any way i got article from sobbour website, but i am not satisfied with the code because the component automatically resize for big and thumb by 2 method directly, it will make bounced my hosting with trash image. And some lines were not realible any more with CakePHP, here is my modified Code (save it to /appName/controller/components/image.php)

class ImageComponent extends Object
{
var  $contentType =  array('image/jpg','image/bmp','image/jpeg','image/gif','image/png','image/pjpg','image/pbmp','image/pjpeg','image/ppng','image/pgif');
function  upload_image_and_thumbnail($fileData,$size,$subFolder,$prefix) {
if  (strlen($fileData['name'])>4)
 {
$error =  0;
$destFolder =  WWW_ROOT.$subFolder;
$realFileName  = $fileData['name'];
if(!is_dir($destFolder))  mkdir($destFolder,true);
  $filetype = $this->getFileExtension($fileData['name']);
$filetype  = strtolower($filetype);
if(!in_array($fileData['type'],$this->contentType)){
return false;exit();
}
else if($fileData['size'] > 700000 ){
return false;exit();
}
else
{
$imgsize =  GetImageSize($fileData['tmp_name']);
}
 if  (is_uploaded_file($fileData['tmp_name']))
 {
if  (!copy($fileData['tmp_name'],$destFolder.'/'.$realFileName ))
{
 return false;
exit();
}
else  {
  $this->resize_img($destFolder.'/'.$realFileName, $size,  $destFolder.'/'.$prefix.$realFileName);
 unlink($destFolder.'/'.$realFileName);
 }
 }
return  $fileData;
}
}
function delete_image($filename)
{
unlink($filename);
}
function  resize_img($tempFile, $size, $newFile)
{
$filetype =  $this->getFileExtension($tempFile);
$filetype =  strtolower($filetype);
switch($filetype) {
case "jpeg":
case "jpg":
 $img_src  = imagecreatefromjpeg($tempFile);
 break;
case "gif":
$img_src = imagecreatefromgif  ($tempFile);
break;
case "png":
$img_src = imagecreatefrompng  ($tempFile);
 case "bmp":
$img_src = imagecreatefromwbmp  ($tempFile);
break;
}
$true_width  = imagesx($img_src);
$true_height = imagesy($img_src);

$size = explode('x',strtolower($size));
if  ($true_width>=$true_height)
{
 $width=$size[0];
 $height =  ($width/$true_width)*$true_height;
}
else
{
 $height=$size[1];
 $width =  ($height/$true_height)*$true_width;
}
$img_des =  imagecreatetruecolor($width,$height);
imagecopyresampled  ($img_des, $img_src, 0, 0, 0, 0, $width, $height, $true_width,  $true_height);
// Save the resized image
switch($filetype)
{
 case "jpeg":
 case "jpg":
 imagejpeg($img_des,$newFile,80);
 break;
 case "gif":
 imagegif($img_des,$newFile,80);
break;
case  "png":
imagepng($img_des,$newFile,80);
case "bmp":
imagewbmp($img_des,$newFile,80);
break;
}
}
function  getFileExtension($str)
{
$i  = strrpos($str,".");
if (!$i) { return ""; }
$l =  strlen($str) - $i;
$ext = substr($str,$i+1,$l);
return $ext;
}
}


class  ImageComponent extends Object

{

var  $contentType =  array('image/jpg','image/bmp','image/jpeg','image/gif','image/png','image/pjpg','image/pbmp','image/pjpeg','image/ppng','image/pgif');

function  upload_image_and_thumbnail($fileData,$size,$subFolder,$prefix) {

if  (strlen($fileData['name'])>4)

 {

$error = 0;

$destFolder = WWW_ROOT.$subFolder;

$realFileName = $fileData['name'];

if(!is_dir($destFolder))  mkdir($destFolder,true);

 $filetype =  $this->getFileExtension($fileData['name']);

$filetype  = strtolower($filetype);

if(!in_array($fileData['type'],$this->contentType)){

return false;exit();

}

else if($fileData['size'] >  700000 ){

return  false;exit();

}

else

{

$imgsize =  GetImageSize($fileData['tmp_name']);

}

 if  (is_uploaded_file($fileData['tmp_name']))

 {

if  (!copy($fileData['tmp_name'],$destFolder.'/'.$realFileName ))

{

 return false;

exit();

}

else  {

  $this->resize_img($destFolder.'/'.$realFileName, $size,  $destFolder.'/'.$prefix.$realFileName);

  unlink($destFolder.'/'.$realFileName);

 }

 }

return $fileData;

}

}

function  delete_image($filename)

{

unlink($filename);

}

function  resize_img($tempFile, $size, $newFile)

{

$filetype =  $this->getFileExtension($tempFile);

$filetype =  strtolower($filetype);

switch($filetype) {

case "jpeg":

case "jpg":

 $img_src  = imagecreatefromjpeg($tempFile);

 break;

case "gif":

$img_src = imagecreatefromgif  ($tempFile);

break;

case "png":

$img_src = imagecreatefrompng  ($tempFile);

  case "bmp":

$img_src  = imagecreatefromwbmp ($tempFile);

break;

}

$true_width  = imagesx($img_src);

$true_height = imagesy($img_src);



$size =  explode('x',strtolower($size));

if  ($true_width>=$true_height)

{

 $width=$size[0];

 $height =  ($width/$true_width)*$true_height;

}

else

{

 $height=$size[1];

 $width =  ($height/$true_height)*$true_width;

}

$img_des =  imagecreatetruecolor($width,$height);

imagecopyresampled  ($img_des, $img_src, 0, 0, 0, 0, $width, $height, $true_width,  $true_height);

// Save the resized image

switch($filetype)

{

 case "jpeg":

 case "jpg":

 imagejpeg($img_des,$newFile,80);

 break;

 case "gif":

 imagegif($img_des,$newFile,80);

break;

case  "png":

imagepng($img_des,$newFile,80);

case  "bmp":

imagewbmp($img_des,$newFile,80);

break;

}

}

function  getFileExtension($str)

{

$i = strrpos($str,".");

if  (!$i) { return ""; }

$l = strlen($str) - $i;

$ext  = substr($str,$i+1,$l);

return $ext;

}

}

And in your class instance method , run this line

<?php
class DeJavu extends Appcontroller {
var $components = array("Image");
function add(){
....any code....
$this->Image->upload_image_and_thumbnail($this->data['Webinfo']['file'],'150x150','img','logo_');
....any code....
}
}
?>

now I am happy to see my app can resize image without annoying script any more. Good Luck for you too.

SharedObject in Sever Using NetConnection or by Remote

A few days ago i have problem how to implement my live streaming using SharedObject in Red5 because usually SharedObject, as i know, only good implementable for local only (like getting or store cookies), before implemented to my live streaming application, i created simple chat application to remote SharedObject :

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" creationComplete="creationComplete()">
<mx:Script source="streaming.as"/>
<mx:TextInput x="10" y="10" id="rtmpUrl" text="your rtmp address"/>
<mx:Button x="216" y="10" id="connectBtn"/>
<mx:TextInput x="10" y="269" id="enterMsg" />
<mx:TextArea x="10" y="40" height="221" id="msgBoard" width="222" />
<mx:Button x="178" y="269" id="sendBtn"/>
</mx:Application>

And now let create streaming.as script :
import flash.events.MouseEvent;
import flash.events.NetStatusEvent;
import flash.events.SyncEvent;
import flash.net.NetConnection;
import flash.net.NetStream;
import flash.net.SharedObject;

import mx.controls.Alert;

public var NetCont:NetConnection;
public var NetStrem:NetStream
public var SharObj:SharedObject;

public function creationComplete():void{
connectBtn.label = "Connect";
connectBtn.addEventListener(MouseEvent.CLICK, ConnectServer);

sendBtn.label = "Send";
sendBtn.addEventListener(MouseEvent.CLICK, SendChat);
}

public function ConnectServer(event:MouseEvent):void{
NetCont = new NetConnection();
NetCont.client = new NetConnectionClient;
NetCont.connect(rtmpUrl.text);
NetCont.addEventListener(NetStatusEvent.NET_STATUS, createSharedObject);
}

public function createSharedObject(event:NetStatusEvent):void{

if(NetCont.connected){
SharObj = SharedObject.getRemote("SampleMessage",NetCont.uri,false,false);
SharObj.connect(NetCont);
SharObj.addEventListener(SyncEvent.SYNC, SharObjView);


}else{

Alert.show('Unable to Connect Internet or Rtmp Address');


}
}


public function SharObjView(event:SyncEvent):void{
msgBoard.htmlText += SharObj.data['SampleMessage']+"<br>";

}

public function SendChat(event:MouseEvent):void{
SharObj.setProperty("SampleMessage",enterMsg.text);
}

There are 2 optional for using SharedObject in ActionScript specially for flex SharedObject.getLocal() method or the SharedObject.getRemote()

What we use for internet connection is using getRemote. And here is code for next connection client :
package
{
public class NetConnectionClient
{
public function NetConnectionClient()
{
}
public function onBWDone(... rest):void
{

}
public function onBWCheck(... rest):uint
{
//have to return something, so returning anything :)
return 0;
}

public function onMetaData(info:Object):void {
trace("metadata: duration=" + info.duration + " width=" + info.width + " height=" + info.height + " framerate=" + info.framerate);
}
}
}

Anti Spam Email For Your Rails Page with Javascript

In your view : <%= js_antispam_email_link('username@domain.com') %>


Code for your helper


# Takes in an email address and (optionally) anchor text,

# its purpose is to obfuscate email addresses so spiders and

# spammers can't harvest them.

def js_antispam_email_link(email, linktext=email)

user, domain = email.split('@')

user = html_obfuscate(user)

domain = html_obfuscate(domain)

# if linktext wasn't specified, throw encoded email address builder into js document.write statement

linktext = "'+'#{user}'+'@'+'#{domain}'+'" if linktext == email

rot13_encoded_email = rot13(email) # obfuscate email address as rot13

out = "#{linktext}&lt;br/&gt;&lt;small&gt;#{user}(at)#{domain}&lt;/small&gt;\n" # js disabled browsers see this

out += "// <![CDATA[

\n"

out += " \n"

out += " string = '#{rot13_encoded_email}'.replace(/[a-zA-Z]/g, function(c){ return String.fromCharCode((c = (c = c.charCodeAt(0) + 13) ? c : c - 26);});\n"

out += " document.write('#{linktext}'); \n"

out += " //\n"

out += "

// -->

// ]]>\n"

return out

end


private

# Rot13 encodes a string

def rot13(string)

string.tr "A-Za-z", "N-ZA-Mn-za-m"

end


# HTML encodes ASCII chars a-z, useful for obfuscating

# an email address from spiders and spammers

def html_obfuscate(string)

output_array = []

lower = %w(a b c d e f g h i j k l m n o p q r s t u v w x y z)

upper = %w(A B C D E F G H I J K L M N O P Q R S T U V W X Y Z)

char_array = string.split('')

char_array.each do |char|

output = lower.index(char) + 97 if lower.include?(char)

output = upper.index(char) + 65 if upper.include?(char)

if output

output_array << "&##{output};"

else

output_array << char

end

end

return output_array.join

end

Move To Word Press

I Recently Move my Blog To Wordpress --> inobject.wordpress.com

 
powered by Blogger