วันพฤหัสบดีที่ 23 ธันวาคม พ.ศ. 2553

วิธีการ restore database ที่มี character encoding utf-8

เนื่องจากเวลา restore database ด้วย MySQL command โดยที่ไฟล์ sql ของเรานั้นมีภาษาไทยอยู่ และไฟล์ดังกล่าวมี encoding เป็น utf-8 การใช้ command ปกติจะทำให้เวลา restore เข้าไปภาษาไทยจะเละ

ดังนั้นเวลาเรา restore เราควรจะต้องกำหนด default character set ให้กับ command ด้วย
mysql -u [username] -p --default_character_set utf8 [database_name] < [file.sql]
mysql -u root -p --default_character_set utf8 leknarm < leknarm.sql
Continue Reading...

วันศุกร์ที่ 17 ธันวาคม พ.ศ. 2553

สร้าง module ใน drupal

ถึง drupal จะยืดหยุ่นมากจนเราทำอะไรก็ได้ใน content จะเขียน php ลงใน content โดยใช้ php filter หรือจะทำ cck field สำหรับ download ไฟล์ แต่มันก็ยังไม่เพียงพอสำหรับการทำงานบางอย่างของ site ของเรา

เช่นผมอยากจะ validate ข้อมูลบน form ซึ่ง webfrom validation ไม่สามารถทำได้ เราจำเป็นต้องสร้าง custom module ขึ้นมาเพื่อจะทำงานนั้นๆ

การสร้าง custom module นั้นมี tutorial อยู่ที่ http://drupal.org/developing/modules หรือที่ ThaiTux ซึ่งได้แปลไว้เรียบร้อยแล้ว(อ่านแล้วงงนิดหน่อย) ซึ่งผมจะขออธิบายการสร้าง module ง่ายๆ คือ

การสร้าง module จำเป็นต้องมีไฟล์สำคัญอยู่ 2 ไฟล์คือ
  1. module_name.info
  2. module_name.module
ซึ่ง file info จะประกอบด้วยส่วนสำคัญคือ

; $Id$
name = leknarm
description = leknarm hook module
package = "Other"
core = 6.x

โดยความหมายก็ตรงตัวเลยครับ
  • name คือชื่อ
  • description คือรายละเอียด
  • package คือให้มันอยู่ package ไหน ในที่นี้คือ Other
  • และ core คือใช้ได้กับ version อะไร
เมื่อสร้างไฟล์ info เสร็จแล้วเราก็มาสร้างไฟล์ module กัน

<?php
// $Id$

/**
 * Implementation of hook_form().
 */
function leknarm_form_alter(&$form, $form_state, $form_id) {
  if($form_id == 'webform_client_form_1') {
    $form['#submit'][] = 'leknarm_form1_submit';
  }
  if($form_id == 'webform_client_form_2') {
    $form['#submit'][] = 'leknarm_form2_submit';
  }
}
function leknarm_form1_submit($form, &$form_state) {
  // do anything 
}
function leknarm_form2_submit($form, &$form_state) {
  // do anything 
}
?> 
จากด้านบน มีฟังก์ชัน leknarm_form_alter ซึ่งฟังก์ชันดังกล่าวเป็น hook ของ form โดยที่เมื่อมีการ request page ที่มี form ใดๆ มันจะไปเรียกฟังก์ชันดังกล่าวทันที ซึ่งในฟังก์ชันดังกล่าวเราเขียนไว้ว่า ถ้าเป็น form ที่มี id เป็น webform_client_form_1 มีการ submit ข้อมูลแล้วให้ไปเรียกฟังก์ชัน leknarm_form1_submit

นอกจากนี้เรายังสามารถทำ validation ได้โดยใช้คำสั่ง $form['#validate'][] แทนที่คำสั่ง $form['#submit'][]
Continue Reading...

วันศุกร์ที่ 19 พฤศจิกายน พ.ศ. 2553

ตั้งค่าให้ Thunderbird delete mail ทันทีหลังจากกดปุ่ม delete เมื่อ connect กับ Microsoft Exchange

อ่านหัวข้อแล้วอาจจะยังงงกันอยู่ว่ามันหมายความว่ายังไง ???

จริงๆ แล้วเมื่อ Thunderbird มีการเชื่อมต่อกับ microsoft exchange แล้วหากลองใช้ web mail ของ exchange ลบ mail ใน inbox ของเรา บน thunderbird เมลก็จะถูกลบทันที

ในทางกลับกัน ถ้าเราลบเมลบน thunderbird ที่เชื่อมต่อกับ exchange ลองไปดูบน web mail ของ exchange .... อ้าว !! ทำไมมันไม่ยอมลบล่ะเนี่ย

ปัญหาดังกล่าวเกิดขึ้นจากใน Thunderbird เวลาลบเมลนั้น thunderbird จะทำแค่ mark as delete แต่ไม่ได้ลบจริงๆ ดังนั้นบน exchange server ก็จะยังมีเมลอยู่ ถึงแม้จะมีการเชื่อมต่อแบบ IMAP เมลก็ยังอยู่เหมือนเดิม

คำถามเกิดขึ้น ? แล้วถ้าจะให้เมลมันลบจริงๆ จะทำยังไงล่ะ
คำตอบคือ ใน Thunderbirdให้ไปที่เมนู Tools > Account Settings > Server Settings > ให้คลิกเครื่องหมายถูกหน้า Clean up ("Expunge") Inbox on Exit ซึ่งหมายถึงบอกให้ Thunderbird ทำการ expunge เมื่อมีการปิด Thunderbird

แค่นี้เมื่อปิด Thunderbird เมลที่เราเคย delete ไว้ก็จะไป sync กับ exchange แล้วครับ แต่ถ้าจะให้ expunge หรือ sync ทันทีจำเป็นต้องไป config ค่าเพิ่มนิดหน่อยครับ โดยไปที่

Tools > Options > Advanced > General > คลิกที่ปุ่ม Config Editor > คลิกปุ่ม I'll be careful, I promise! จากนั้นในช่อง filter ให้พิมพ์คำว่า expunge ให้ double คลิกที่ mail.imap.expunge_after_delete ให้ค่า Value เป็น true



เท่านั้นเวลาเราลบเมล บน Exchange ก็จะ update ทันทีเลยครับ

ที่มา http://forums.mozillazine.org/
Continue Reading...

วันพุธที่ 3 พฤศจิกายน พ.ศ. 2553

get locale ของ openoffice.org ด้วย macro

ในบ้างครั้งการเขียนมาโครก็มีความจำเป็นต้องรู้ว่าเครื่องนั้นๆ มีการ settings อะไรไว้บ้างเช่น set ค่า locale ไว้เป็นอะไรเพื่อที่จะได้รู้ว่ามีการเขียนวันเดือนปีเป็นแบบไหน (ปี/เดือน/วัน, วัน/เดือน/ปี)
การเขียนมาโครบน OpenOffice.org เพื่อแสดงค่า locale ที่ตั้งค่าไว้สามารถเขียนได้ดังนี้

dim lang as string 
dim args(0) As new com.sun.star.beans.PropertyValue 

configprovider = createUnoService( "com.sun.star.configuration.ConfigurationProvider" ) 
args(0).name = "nodepath" 
args(0).value = "/org.openoffice.Setup/L10N" 
settings = configprovider.createInstanceWithArguments("com.sun.star.configuration.ConfigurationAccess", args() )
print settings.ooSetupSystemLocale

ค่า locale ของเราจะอยู่ที่ property ooSetupSystemLocale ซึ่งใน code ตัวอย่างเราจะได้ผลลัพธ์เป็น th-TH
Continue Reading...

วันศุกร์ที่ 29 ตุลาคม พ.ศ. 2553

ช่วยกันทดสอบ patch แก้ bug วันที่พุทธศักราช export ไปยัง excel แล้วเสียหาย

และแล้ว bug http://www.openoffice.org/issues/show_bug.cgi?id=93503 ก็แก้ไขเสร็จสิ้นเรียบร้อย แต่ไม่รู้เมื่อไร Oracle จะ approved ก็ไม่รู้ แต่ก่อนที่ทาง Oracle จะ approved ผมจึงอยากให้ลองช่วยกันทดสอบ patch ที่แก้ไข bug ดังกล่าวแล้ว

สามารถดาวน์โหลดได้ ที่นี่


โดยวิธีการ patch คือ
  1. ปิดโปรแกรม OpenOffice.org ทั้งหมด รวมทั้ง quickstart ด้วย
  2. rename ไฟล์ svtmi.dll บนเครื่อง computer ของเราที่ c:\program files\openoffice.org3\program\svtmi.dll ให้เป็น svtmi.dll.bak (เพื่อ backup ข้อมูล)
  3. download และแตกไฟล์ (จะได้ไฟล์ svtmi.dll)
  4. copy ไฟล์ที่แตกออกมาไปที่ c:\program files\openoffice.org3\program\
ซึ่งส่ิงที่แก้ไขไปคือ
  1. เมื่อ export วันที่ที่มี format เป็น [~buddhist], Microsoft Excel จะเปิดขึ้นมาได้ถูกต้อง
  2. เมื่อเปิดวันที่ที่มี LCID จาก Microsoft Office ที่บ่งบอกว่าเป็นปีพุทธศักราช OpenOffice.org Calc จะเปิดได้ถูกต้อง
  3. เมื่อ export วันที่ที่มีเลขไทย Microsoft Excel จะเปิดขึ้นมาได้ถูกต้อง
  4. เมื่อเปิดวันที่หรือตัวเลขที่มีเลขไทย OpenOffice.org จะเปิดได้อย่างถูกต้อง
ดูข่าวได้จาก http://openoffice.in.th/
Continue Reading...

วันศุกร์ที่ 22 ตุลาคม พ.ศ. 2553

เปลี่ยนตัวเลขอาราบิก ให้เป็นเลขไทยบน OpenOffice.org Writer ด้วยมาโคร

เนื่องจาก @gumara ได้ฝากถามมาว่าบน OpenOffice.org สามารถกด keypad แล้วพิมพ์เป็นเลขไทยได้ไหม เพราะพวกหนังสือราชการนั้นจำเป็นต้องเป็นเลขไทย ให้คอยมากด shift + เลข ก็เสียเวลา

ปัญหาดังกล่าวไม่สามารถทำได้บน OpenOffice.org เนื่องมาจาก key ที่ให้เราสามารถตั้งค่าการทำงานต่างๆ บน OpenOffice.org มีอยู่จำกัดและไม่สามารถเพิ่มเองได้เหมือนกับ Microsoft Office ดังนั้นผมจึงคิดว่าควรทำเป็น extension หรือ ง่ายกว่านั้นก็คือ macro 

ดังนั้นผมจึงเขียนมาโครที่ทำการ convert ตัวเลขอาราบิกทั้งหมดภายในเอกสารให้กลายเป็นตัวเลขไทยซะดังนี้

sub main
  dim descriptor
  dim foundall
  dim found
 
  descriptor = ThisComponent.createSearchDescriptor()
  thainum = array("๐", "๑", "๒", "๓", "๔", "๕", "๖", "๗", "๘", "๙")
  for num = 0 to 9
    with descriptor
      .SearchString = num
      .SearchCaseSensitive = False
    end with
  
    foundall = ThisComponent.findall(descriptor)
    for i = 0 to foundall.getcount() -1
      found = foundall.getbyindex(i)
      found.setstring(thainum(num))
    next
  next
end sub

แค่นี้ เมื่อกดรันมาโครดังกล่าว ตัวเลขภายในเอกสารของเราก็จะกลายเป็นเลขไทยแล้ว

-----------------------------------------------------------

เพิ่มเติมอีกนิด สำหรับการแก้ไขเลขไทยเฉพาะส่วนที่คลุมครับ

sub mainselected
  dim leftpos
  dim rightpos
  dim found
  dim descriptor

  descriptor = ThisComponent.createSearchDescriptor()
  thainum = array("๐", "๑", "๒", "๓", "๔", "๕", "๖", "๗", "๘", "๙")
  for num = 0 to 9
    with descriptor
      .SearchString = num
      .SearchCaseSensitive = False
    end with
    leftpos = thiscomponent.getcurrentcontroller().getviewcursor().getstart()
    rightpos = thiscomponent.getcurrentcontroller().getviewcursor().getend()

    found = thiscomponent.findnext(leftpos.getstart(), descriptor)
    do while not isnull(found)
      if -1 = thiscomponent.gettext().compareRegionEnds(found, rightpos) then exit do
      found.setstring(thainum(num))
      found = thiscomponent.findnext(found.end, descriptor)
    loop
  next
end sub

-----------------------------------------------------------
update

ทำเป็น extension เพื่อให้ติดตั้งแล้วใช้งานได้ทันทีครับ


download

เมื่อติดตั้งแล้วจะอยู่ที่เมนู format > convert to native number ครับโดยต้องคลุมก่อนแล้วเลือกใช้งานครับ
Continue Reading...

วันพฤหัสบดีที่ 7 ตุลาคม พ.ศ. 2553

ทำ image ให้เป็น button ใน drupal from

ห่างหายกับการเขียน blog ไปนาน วันนี้จะมาเขียนเรื่องการทำรูปให้เป็นปุ่ม button แต่ทำใน drupal กัน

ก่อนอื่นต้องบอกก่อนว่าใน html นั้นเวลาทำ input ที่มี type เป็น image, image นั้นๆ จะทำหน้าที่เป็น submit button โดยอัตโนมัติ คราวนี้เราอยากจะใส่ <input type="image" src="/path/to/image" /> ใน drupal แต่ปัญหาดันเกิดขึ้นที่ต้องใช้ drupal api น่ะสิจะทำยังไง

จากการ google ดูเราได้หน้า API Quickstart ของ drupal มาเป็นหน้านี้

http://drupal.org/node/751826

แต่ว่าดันไม่มี example ของ image เลย ก็เลยลองหาก็ไปเจอหน้า API Reference

http://api.drupal.org/api/drupal/developer--topics--forms_api_reference.html/6

ซึ่งบอกไว้ว่า type image นั้นใน drupal ต้องเขียนว่า image_button ซึ่งถ้าจะเขียนในรูปแบบ drupal form api จะเขียนได้ดังนี้

<?php
$form['example'] = array(
  '#type' => 'image_button',
  '#value' => 'path/to/your/image',
);
?>

แค่นี้เราก็จะได้ form image button โดยใช้ drupal api แล้วครับ
Continue Reading...

วันศุกร์ที่ 3 กันยายน พ.ศ. 2553

สร้าง custom workflow บน alfresco

ขั้นตอนการสร้าง custom workflow บน alfresco นั้นมีขั้นตอนหลักๆ อยู่ 4-5 ขั้นตอนครับ ที่บอกว่า 4-5 เพราะว่ามีอยู่ขั้นตอนนึงที่ทำแค่ครั้้งแรกครั้งเดียวเท่านั้นครับ
  •  ขั้นตอนที่ 1 : สร้าง Task Model 
ปกติแล้วเราสามารถสร้าง Task Model ได้หลายวิธีเช้นแก้ไข file workflowModel.xml ใน server แต่การทำเช่นนี้เราจำเป็นต้อง restart server ก่อน Task Model ที่เราแก้ไขจึงจะใช้งานได้ แต่ถ้าเราต้องการสร้าง Task Model โดยที่ไม่จำเป็นต้อง restart server ให้เราไปแก้ที่ Alfresco Explorer แทนครับโดยให้ไปที่ Company Home > Data Dictionary > Models แล้วเลือก Create > Create Content แล้วใส่ค่าตามนี้
  1. Name: ใส่ชื่อของ Model เช่น leknarmModel
  2. Type: เลือกเป็น Content
  3. Content Type เลือกเป็น XML
เสร็จแล้วกด OK
ในหน้า Enter Content ให้ใส่ค่า

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

<model name="osdev:reviewapprovemodel" xmlns="http://www.alfresco.org/model/dictionary/1.0">
  <description>Approve 2 Step Model</description>
  <author>Tantai Thanakanok</author>
  <version>1.0</version>

  <imports>
    <import uri="http://www.alfresco.org/model/dictionary/1.0" prefix="d"/>
    <import uri="http://www.alfresco.org/model/content/1.0" prefix="cm"/>
    <import uri="http://www.alfresco.org/model/bpm/1.0" prefix="bpm"/>
    <import uri="http://www.alfresco.org/model/system/1.0" prefix="sys" />
  </imports>

  <namespaces>
    <namespace uri="th.co.osdev.model" prefix="osdev"/>
  </namespaces>    
  <types>
    <type name="osdev:submitReviewTask">
      <parent>bpm:startTask</parent>
      <properties>
        <property name="osdev:expiredate">
          <title>Expired date.</title>
          <type>d:date</type>
        </property>            
      </properties>
      <mandatory-aspects>
        <aspect>bpm:assignee</aspect>
      </mandatory-aspects>
    </type>  

    <type name="osdev:reviewTask">
      <parent>osdev:submitReviewTask</parent>
      <overrides>
        <property name="osdev:expiredate">
        </property>
      </overrides>
      <mandatory-aspects>
        <aspect>bpm:assignee</aspect>
      </mandatory-aspects>
    </type>

    <type name="osdev:approveTask">
      <parent>osdev:reviewTask</parent>
      <overrides>
        <property name="osdev:expiredate">
        </property>
      </overrides>
    </type>

  </types>  
</model> 

code ด้านบนนี้เป็นแค่ตัวอย่างเท่านั้น โดย code ดังกล่าวจะไป map กับ jPDL ที่เราวาดหลังจากนี้


เมื่อใส่ code ด้านบนนี้เสร็จแล้วให้กด Finish เพื่อไปยังหน้าถัดไป 
ในหน้า Modify Content Properties ให้เลือก Model Activate ด้วยจากนั้นกด OK
  • ขั้นตอนที่ 2 : สร้าง Workflow Resource Bundle
ให้ไปสร้างไฟล์ที่ Company Home > Data Dictionary > Messages โดยใส่ค่าดังนี้
  1. Name: ชื่อของไฟล์.properties เช่น leknarm-messages.properties
  2. Type: เลือกเป็น Content
  3. Content Type: เลือกเป็น Plain Text
ในหน้า Enter Content ให้ใส่ค่า
osdev_reviewApprove.workflow.title= Osdev Review , Approval of content
osdev_reviewApprove.workflow.description= Osdev Review , Approval of content
osdev_reviewapprovemodel.type.osdev_submitReviewTask.title=Start  Review
osdev_reviewapprovemodel.type.osdev_submitReviewTask.description=Submit documents for review & approval
osdev_reviewapprovemodel.type.osdev_reviewTask.title=Review
osdev_reviewapprovemodel.type.osdev_reviewTask.description=Review Documents to Approve or Reject them
osdev_reviewapprovemodel.type.osdev_approveTask.title=Approve
osdev_reviewapprovemodel.type.osdev_apporveTask.description=Approve to Finishing Documents 
เมื่อใส่ค่าเสร็จแล้วให้กดปุ่ม Finish
ใน่ส่วนของ ไฟล์ Resource Bundle นั้นเราจำเป็นต้อง deploy ด้วยมือ ไม่มี option ที่จะ deploy อัตโนมัติ ดังนั้นให้เราไปที่ url
http://<host>:<port>/alfresco/faces/jsp/admin/repoadmin-console.jsp 
แล้วพิมพ์
reload messages leknarm-messages
  • ขั้นตอนที่ 3 : สร้าง Process Definition
โดยปกติแล้ว การสร้าง Process Definition เท่าที่ทราบ จะสามารถสร้างได้ 2 วิธีคือ 1 สร้างโดยการ import ไฟล์ process definition แล้ว deploy แบบ manual แต่วิธีที่ผมจะใช้นั้นคือการ deploy โดยใช้งาน eclipse ครับ

ใน part นี้ผมขอยกตัวอย่าง การสร้าง jPDL ครับเนื่องจากถ้าลากยาวไปถึงการติดตั้งจะทำให้ยาวเกินไป ขอแยกการติดตั้งไปเป็นอีก part ละกันครับ

ให้สร้างไฟล์ process definition ที่มีรูปแบบดังตัวอย่างด้านล่างนี้


จากนั้นในส่วน code ให้ใส่ค่าตามนี้ครับ

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

<process-definition  xmlns="urn:jbpm.org:jpdl-3.2"  name="osdev:reviewApprove">

    <swimlane name="initiator"></swimlane>
    
    <swimlane name="reviewer">
        <assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
            <actor>#{bpm_assignee}</actor>
        </assignment>
    </swimlane>
    
    <swimlane name="approver">
        <assignment class="org.alfresco.repo.workflow.jbpm.AlfrescoAssignment">
            <actor>#{bpm_assignee}</actor>
        </assignment>
    </swimlane>

    <start-state name="start">
        <task name="osdev:submitReviewTask" swimlane="initiator"></task>
        <transition to="review"></transition>
    </start-state>


    <task-node name="review">
        <task name="osdev:reviewTask" swimlane="reviewer"></task>
        <transition to="approve"></transition>
    </task-node>

    <task-node name="approve">
        <task name="osdev:approveTask" swimlane="approver"></task>
        <transition to="end"></transition>
    </task-node>


    <end-state name="end"></end-state>

</process-definition>

เมื่อวาด diagram และใส่ code เรียบร้อย ให้ไปที่ Tab Deployment ในส่วนของ Deployment Server Setting ให้ใส่ค่าตามนี้
  1. Server Name: server ของท่านเช่น localhost
  2. Server Port: ให้ใส่ 8080 หรือว่า port ที่ตั้งค่าไว้
  3. Server Deployer: ให้ใส่เป็น /alfresco/jbpm/deployprocess
จากนั้นให้ลองกด Test Connection... ดูว่า connection เราเปิดไว้หรือยัง หาก error ให้ตรวจสอบดูว่าเรา start alfresco หรือยังหรือว่ามีการใส่ค่าอะไรผิดพลาดหรือไม่ จากนั้นกด Deploy Process Archive
  • ขั้นตอนที่ 4 : แก้ไข config ให้ display workflow image 
ขั้นตอนนี้ ทำแค่ครั้งแรกครั้งเดียวเท่านั้นครับ โดยให้ไปที
$ALF_ROOT/tomcat/webapps/alfresco/jsp/workflow/start-workflow-wizard/workflow-options.jsp
และ
$ALF_ROOT/tomcat/webapps/alfresco/jsp/workflow/manage-task-dialog.jsp
ให้แก้ไข code จาก
<a:panel rendered="false" id="workflow-outline" label="#{msg.workflow_outline}" progressive="true" expanded="false"
border="white" bgcolor="white" titleBorder="lbgrey" expandedTitleBorder="dotted" titleBgcolor="white" styleClass="mainSubTitle">
เป็น
<a:panel rendered="true" id="workflow-outline" label="#{msg.workflow_outline}" progressive="true" expanded="true"
border="white" bgcolor="white" titleBorder="lbgrey" expandedTitleBorder="dotted" titleBgcolor="white" styleClass="mainSubTitle">
  • ขั้นตอนที่ 5 : สร้าง Alfresco Exploror Task Dialog
ให้สร้างไฟล์ web-client-config-custom.xml ไว้บนเครื่องของเราโดยมี code ดังนี้

<alfresco-config>

<config evaluator="node-type" condition="osdev:submitReviewTask" replace="true">
    <property-sheet>
        <show-property name="osdev:expiredate" display-label="Expired Date"/>
        <show-association name="bpm:assignee" display-label-id="wf_reviewers" />
    </property-sheet>
</config>

<config evaluator="node-type" condition="osdev:reviewTask" replace="true">
    <property-sheet>
        <show-property name="osdev:expiredate" display-label="Expired Date"/>
        <show-association name="bpm:assignee" display-label-id="wf_approver" />
    </property-sheet>
</config> 

<config evaluator="node-type" condition="osdev:approveTask" replace="true">
    <property-sheet>
        <show-property name="osdev:expiredate" display-label="Expired Date"/>
    </property-sheet>
</config> 

</alfresco-config>
เมื่อใส่ code เสร็จเรียบร้อยให้ไปที่ Company Home > Data Dictionary > Web Client Extension จากนั้นให้  Add Content โดยเลือกไฟล์ที่เราเพิ่งสร้าง แล้วกด Next จน Finish

จากนั้นเราต้อง deploy Web Client Extension เองโดยไปที่ url
http://<host>:<port>/alfresco/faces/jsp/admin/webclientconfig-console.jsp
แล้วพิมพ์คำว่า reload

เมื่อเสร็จขั้นตอนที่หมดแล้ว ให้ลอง logout ออกมาครั้งนึงก่อน จากนั้น login เข้าไปใหม่และให้ลอง test โดยการรัน workflow จากไฟล์ หรือจากที่ใดก็ได้ จะสังเกตุว่ามี custom workflow ที่เราเพิ่งสร้างเกิดขึ้นมาครับ

ที่มา - หนังสือ Alfresco 3 Enterprise Implementation
Continue Reading...

วันศุกร์ที่ 27 สิงหาคม พ.ศ. 2553

แก้ไข default language ของ alfresco

หากใครทำ full text search ภาษาไทยบน alfresco เรียบร้อยแล้ว คงสังเกตุกันว่าการ login ต้องเลือกภาษาเป็นภาษาไทย แต่ว่า login language ดันมีให้เลือก 2 ภาษาหรือหลายภาษา แต่ยังไง default ก็เป็นภาษาอังกฤษอยู่ดี


คราวนี้หากเราต้องการ set ค่า default language ของหน้า login นี้จะต้องไป set ค่าที่
tomcat/shared/classes/alfresco/extension/web-client-config-custom.xml
โดยในส่วน config ของ language ให้แก้ค่าจาก
<config evaluator="string-compare" condition="Languages">
เป็น
<config evaluator="string-compare" condition="Languages" replace="true">
ซึ่งการใส่ replace="true" นั้นหมายความว่า ให้นำ config ดังกล่าว replace config default แทนครับ

ที่มา alfresco forum
Continue Reading...

วันพุธที่ 25 สิงหาคม พ.ศ. 2553

เขียนไฟล์ OpenOffice.org ด้วย Java

ก่อนที่จะเขียนไฟล์ OpenOffice.org ด้วย Java ได้ก่อนอื่นก็ต้องเข้าใจ API ของ OpenOffice.org ซะก่อนซึ่งถ้าใครเคยเขียน Macro บน OpenOffice.org มาบ้างก็คงจะพอเข้าใจ

วิธีที่นำมาบอกนี้จะเป็นวิธีที่ใช้ eclipse ในการเขียนครับ

ขั้นแรกก็ให้ download eclipse มาก่อนจากนั้นสร้าง Java Project ธรรมดาๆ มาซัก Project ตั้งชื่อตามสะดวกจากนั้นก็ add external jar เข้ามาตามนี้
  1. juh.jar
  2. jurt.jar
  3. ridl.jar
  4. unoil.jar
  5. bootstrapconnector.jar สามารถ download ได้จาก ที่นี่
ซึ่งไฟล์ดังกล่าวหาได้จากภายใน folder ที่ติดตั้ง OpenOffice.org

เมื่อ add jar เสร็จแล้วให้สร้าง Class มาซัก Class แล้วใส่ code ตามนี้เลยครับ

// connect to openoffice.org
String exePath = "C:/Program Files/OpenOffice.org 3/program/";
   
XComponentContext xContext = BootstrapSocketConnector.bootstrap(exePath);
com.sun.star.lang.XMultiComponentFactory xMFC = xContext.getServiceManager();
Object oDesktop = xMFC.createInstanceWithContext("com.sun.star.frame.Desktop", xContext);
XComponentLoader xCLoader = (com.sun.star.frame.XComponentLoader) UnoRuntime.queryInterface(com.sun.star.frame.XComponentLoader.class, oDesktop);
           
// create openoffice.org writer document
XComponent document = xCLoader.loadComponentFromURL("private:factory/swriter", "_blank", 0, new PropertyValue[0]);
XTextDocument xTextDocument = (XTextDocument) UnoRuntime.queryInterface(XTextDocument.class, document);
XText xText = xTextDocument.getText();
           
// create paragraph cursor
XParagraphCursor xParagraphCursor = (XParagraphCursor) UnoRuntime.queryInterface(XParagraphCursor.class, xText.createTextCursor());
           
// add some text
xText.insertString(xText.getEnd(), "My First OpenOffice Document", false);
           
// add style
XPropertySet xPropertySet = (XPropertySet) UnoRuntime.queryInterface(XPropertySet.class, xParagraphCursor);
xPropertySet.setPropertyValue("ParaStyleName", "Heading 1");
           
// add some text
xText.insertString(xText.getEnd(), "rThis is the first line in my paragraph. Some more text, just to add some text to this document. ", false);
xPropertySet.setPropertyValue("ParaStyleName", "Text body");
           
// Add another heading paragraph
xText.insertString(xText.getEnd(), "rSecond heading", false);
xPropertySet.setPropertyValue("ParaStyleName", "Heading 2");
           
// And another text body paragraph
xText.insertString(xText.getEnd(), "rThis is the second normal paragraph.", false);
xPropertySet.setPropertyValue("ParaStyleName", "Text body");
           
// save document
XStorable xStorable = (XStorable) UnoRuntime.queryInterface(XStorable.class, document);
PropertyValue[] storeProps = new PropertyValue[0];
xStorable.storeAsURL("file:///d:/first_document.odt", storeProps);

// export document to pdf
storeProps = new PropertyValue[1];
storeProps[0] = new PropertyValue();
storeProps[0].Name = "FilterName";
storeProps[0].Value = "writer_pdf_Export";
xStorable.storeToURL("file:///d:/first_document.pdf", storeProps);

// close document
XCloseable xcloseable = (XCloseable) UnoRuntime.queryInterface(XCloseable.class, document);
xcloseable.close(false);

} catch (Exception e) {
    e.printStackTrace();
} catch (BootstrapException e) {
    e.printStackTrace();
}

จริงๆ แล้ว bootstrap นั้นไม่จำเป็นต้องระบุ path ไปที่ soffice.exe ครับ แต่เนื่องจาก ผมลองใช้ bootstrap แบบธรรมดาแล้วไม่ work เลย search ดูจึงเจอ solution นี้ขึ้นมาแทนครับ

ตัวอย่างนี้สามารถเอาไป apply เป็นแบบอื่นๆ ได้อีกมากมายครับ

ที่มา www.it-eye.nl - openoffice.org forum
Continue Reading...

วันศุกร์ที่ 20 สิงหาคม พ.ศ. 2553

Install openerp on ubuntu 10.04 server

หลังจากลองหา solution ในการติดตั้ง openerp มาพักใหญ่ซึ่ง document บน ubuntu นั้นไม่ค่อยจะสมบูรณ์เท่าไร ทำให้อยาก blog solution สำหรับ ubuntu

ขั้นตอนแรกเลย เมื่อติดตั้ง ubuntu 10.04 เรียบร้อยแล้ว ให้ upgrade update ซะก่อน
sudo apt-get upgrade
sudo apt-get update

  1. ติดตั้ง postgresql ก่อนโดยใช้คำสั่ง
  2. sudo apt-get install postgresql
  3. แก้ไฟล์ pg_hba.conf ที่ /etc/postgresql/8.4/main/pg_hba.conf
  4. # "local" is for Unix domain socket connections only
    local   all         all                               ident
    ให้เป็น
    # "local" is for Unix domain socket connections only
    local   all         all                               md5
  5. สร้าง database-user "openuser"
  6. tantai$ sudo su - postgres
    password: password_of_johndoe
    postgres$ createuser --createdb --username postgres --no-createrole --pwprompt openuser
    Enter password for new role: your_password_of_openuser
    Enter it again: your_password_of_openuser
    Shall the new role be a superuser? (y/n) n
    postgres$
    จากนั้นให้ exit ออกจาก postgres
    postgres$ exit
    logout
    johndoe$
    
  7. restart postgres ซะ
  8. sudo /etc/init.d/postgresql-8.4 restart
  9. ติดตั้ง package ที่จำเป็นก่อนลอง openerp
  10. sudo apt-get install python python-psycopg2 python-reportlab python-egenix-mxdatetime python-tz python-pychart python-pydot python-lxml python-vobject
    
  11. download openerp-server มาจาก http://openerp.com/downloads.html แล้วแตกไฟล์
  12. tar -zxvf openerp-server-5.0.12.tar.gz
    cd openerp-server-5.0.12
    
    โดยสามารถ test ก่อน install ได้จาก
    cd bin
    python openerp-server.py
    
    ถ้าถูกต้องจะขึ้นคำว่า [date/time] INFO:web-services:the server is running, waiting for connections...
  13. จากนั้นให้ให้ออกมากที่ root ของ openerp-server ที่ download มาแล้วติดตั้ง
  14. sudo python setup.py install
    
  15. จากนั้นให้ลอง start server ดูด้วยคำสั่ง
  16. openerp-server --db_user=openuser --db_password=your_password_of_openuser
    
    โดย password คือ password ที่เราตั้งตอนที่เรา create user ใน postgres ครับ
  17. จากนั้นถ้าหากไม่ต้องการพิมพ์ username และ password ตอนสั่ง run ใน terminal ก็ให้เก็บ username และ password ลงไปใน file config ที่ /etc/openerp-server.conf
  18. sudo vim /etc/openerp-server.conf
    
    โดยใส่ค่า
    [options] 
    db_name =
    db_user = openuser
    db_password = your_password_of_openuser
    
  19. จากนั้นถ้าต้องการ run server ให้ใช้คำสั่งนี้แทน
  20. openerp-server --config=/etc/openerp-server.conf
    
โดยเมื่อติดตั้ง openerp-server เสร็จเรียบร้อย จะสามารถ access เข้าไปใน server ได้ผ่าน openerp-client ครับโดยสามารถหา download ได้จาก http://openerp.com/downloads.html แต่เนื่องจากสิ่งที่ผมต้องการนั้นเป็นการ access ผ่าน web browser จึงจำเป็นต้องลง openerp-web อีก

ปกติแล้วใน openerp-web จะมีขั้นตอนการติดตั้งบอกอยู่ใน doc/README.txt ครับแต่ว่าผมขอนำมาทำเป็นขั้นๆ ดังนี้

  1. download openerp-web มาจาก http://openerp.com/downloads.html แล้วแตกไฟล์
  2. tar -zxvf openerp-web-5.0.12.tar.gz
    
  3. ติดตั้ง package ที่จำเป็น เนื่องจากผมลองทำในขั้นตอนตาม README.txt แล้วไม่ work จึงต้องติดตั้งด้วยมือ
  4. apt-get install python-cherrypy3 python-pybabel python-mako python-simplejson python-formencode python-pyparsing python-tz python-xlwt
    
  5. ติดตั้ง setuptools สำหรับติดตั้งตัว web
  6. sudo apt-get install python python-dev build-essential
    sudo apt-get install python-setuptools
    
  7. จากนั้นออกมาที่ root ของ openerp-web ที่ download มาแล้วรันคำสั่ง
  8. sudo easy_install -U openerp-web
    
  9. จากนั้นรัน openerp-web ด้วยคำสั่ง
  10. openerp-web
    
เมื่อรัน server ทั้ง 2 ตัวเสร็จก็จะสามารถเข้าใช้งาน openerp ได้ทาง port 8080 ครับ http://ipaddress:8080/
Continue Reading...

วันเสาร์ที่ 7 สิงหาคม พ.ศ. 2553

แปลงไฟล์ผ่าน command line ด้วย JODConverter (Command line version)

เนื่องจากลูกค้าต้องการจะแปลงไฟล์ที่ export ออกมาจาก SAP (csv) ให้เป็น ods โดยอัตโนมัติเขาจึงอยากให้หา solution ให้หน่อยว่าต้องทำอย่างไร ตอนแรกคิดว่าจะเขียน OpenOffice.org macro convert ไฟล์เอาแต่ดูท่าทางจะวุ่นวายไป ก็เลยลองหา search ดูว่าน่าจะมีคนเคยทำมาแล้ว และก็ไปเจอ JODConverter ซึ่งทำหน้าที่นี้โดยตรง

JODConverter โดยปกติแล้วสามารถ run ได้โดยเป็น java lib, command line tools, หรือเป็น web app ก็ได้ แต่ที่ผมใช้จะเป็น command line tools

ก่อนอื่นเราจำเป็นต้องรัน OpenOffice.org ให้เป็น service พร้อมทั้งเปิด port 8100 ให้ด้วย สามารถทำได้โดยพิมพ์คำสั่ง

soffice.exe -headless -nologo -norestore -accept=socket,host=localhost,port=8100;urp;StarOffice.ServiceManager

จากนั้นให้ไปที่ใช้คำสั่ง

java -jar path/to/jodconverter/lib/jodconverter-cli-2.2.2.jar filename.csv output.ods

เมื่อรันคำสั่งเสร็จจะได้ผลลัพธ์เป็นไฟล์ ods เป็นที่เรียบร้อย

thanks for oooninja
Continue Reading...

วันพุธที่ 28 กรกฎาคม พ.ศ. 2553

Switch ubuntu 10.04 ไปใช้ sun java

ปัญหาเกิดขึ้นเมื่อจะ build openoffice.org บน ubuntu แต่ว่า dependency ของ openoffice.org ดันเรียกใช้งาน jawt ซึ่ง java ของ gnome ไม่มี ดังนั้นเราต้อง switch java ให้ใช้ของ sun ซะหน่อย

ขั้นแรกให้เปิด terminal แล้วพิมพ์ว่า

sudo update-java-alternatives -s java-6-sun

เมื่อพิมพ์เสร็จแรียบร้อยแล้วให้ทดสอบโดยพิมพ์ java -version เพื่อดูว่า java เราใช้งานที่ใดอยู่
ถ้าตรงก็เสร็จเรียบร้อย

หรือหากต้องการเปลี่ยนกลับให้พิมพ์

sudo update-alternatives --config java

แล้วเลือก java ที่ต้องการได้เลยครับ

อันนี้สำหรับ สำหรับ java 6 นะครับ
Continue Reading...

วันอังคารที่ 29 มิถุนายน พ.ศ. 2553

hover ไม่เวิร์คบน IE

ได้ลองไปแก้ไฟล์ hta แล้วจะทำ css hover ซักหน่อยแต่ดันทำไม่ได้ซะงั้น ก็เลยนำไป rename แล้วเปิดด้วย firefox ดันใช้ได้
ปัญหานี้อยู่ที่ IE ไม่สามารถใช้งาน hover ได้ซึ่งได้ลอง search ดูปรากฏว่าจำเป็นต้องใส่

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"  "http://www.w3.org/TR/html4/strict.dtd">

ที่ด้านบนสุดของไฟล์ เท่านี้ก็สามารถใช้งาน hover บน IE ได้แล้วครับ
ที่มา http://www.bernzilla.com/
Continue Reading...

วันอังคารที่ 15 มิถุนายน พ.ศ. 2553

แก้ไขไฟล์ read-only บน OpenOffice.org ให้กลับมาใช้ได้

สำหรับคนที่ใช้งาน OpenOffice.org บางท่านอาจเคยไป set ค่าไฟล์ให้เป็น read-only ที่เมนู Tools > Option > OpenOffice.org > Security แล้วคลิกเครื่องหมายถูกหน้า "Open this document in read-only mode" ซึ่งเมื่อหลังจาก save แล้วเราจะไม่สามารถเปิดไฟล์มาแก้ไขได้อีกเลย

วิธีการแก้ไขนั้น จำเป็นต้องแก้ไข settings ของไฟล์(hack) โดยขั้นแรกให้แตกไฟล์ OpenOffice.org ที่ติด read-only ออกมาก่อน(ไฟล์ OpenOffice.org นั้นเป็น zip ไฟล์ที่มีนามสกุลเป็น od*) จากนั้นเปิดไฟล์ settings.xml ด้วย editor ตัวใดก็ได้แล้ว search หาส่วน
<config:config-item config:name="LoadReadonly" config:type="boolean">true</config:config-item> 
จากนั้นให้แก้ value จาก true ให้เป็น false

ให้ save ไฟล์ settings.xml และ zip ข้อมูลทั้งหมดกลับเป็น zip ไฟล์แล้วค่อยแก้นามสกุลให้เป็น ods, odt หรืออื่นๆ แค่นี้ไฟล์เราก็จะสามารถแก้ไขได้ตามปรกติแล้วครับ
Continue Reading...

วันพุธที่ 2 มิถุนายน พ.ศ. 2553

show จำนวน reads (view) ของ node ใน drupal

เผอิญต้องการแสดงว่า content ต่างๆ มีจำนวนการอ่านไปทั้งหมดกี่ครั้งแล้ว ก็เลยลองไปดูที่ setting ต่างๆ ของส่วน content แต่ดันไม่เจอเมื่อเป็นเช่นนั้นตาม step ของ drupal ก็ต้อง search หา module ซึ่งพอหาดูแล้วก็ยังไม่เจออีก ก็เลยลอง search ใน forum ของ drupal ได้วิธีมาดังนี้
  1. เปิด module Statistics ซึ่งเป็น core module ของ drupal
  2. ไปที่ Status report แล้วเปิดการทำงาน
โดย Status report นั้นจะอยู่ในส่วนของ report ครับสรุปว่าตั้งค่าง่ายๆ แต่หาไม่เจอเอง
    Continue Reading...

    วันจันทร์ที่ 24 พฤษภาคม พ.ศ. 2553

    วิธีการ set redirect แบบ permanent บน virtualhost

    โจทย์มีอยู่ว่าผมจะ redirect example.com ไปที่ www.example.com โดยต้อง redirect แบบ permanent ในขั้นแรกผมจะต้องมี virtualhost ที่เป็น www ก่อนคือ

    1. www.example.com โดยในไฟล์ใส่ค่าเป็น
      <virtualhost *>
      ServerAdmin     webmaster@example.com 
      DocumentRoot    /var/www/example.com/ 
      ServerName      www.example.com 
      </virtualhost>
      
    2. จากนั้นสร้าง virtualhost อีกไฟล์เป็น example.com
      <virtualhost *>
      ServerName      example.com
      redirect        permanent / http://www.example.com/
      </virtualhost>

    เมื่อสร้างไฟล์เสร็จแล้วให้ใช้คำสั่ง a2ensite เพื่อ enable site แต่ละ site และให้ reload apache ด้วย

    ผมใช้ path บน web ตามชื่อ domain และไฟล์ virtualhost เป็นชื่อ domain เหมือนกันเพื่อกันความสับสนครับ หากใครอยากใช้ชื่ออื่นก็สามารถทำได้ครับ
    Continue Reading...

    วันศุกร์ที่ 14 พฤษภาคม พ.ศ. 2553

    ติดตั้ง bazaar v2.x ใน ubuntu

    เนื่องจาก bzr ใน ubuntu ถ้าติดตั้งด้วยวิธี apt-get install แล้ว default นั้นเป็น v1.3 ซึ่งโดยส่วนมากแล้วจะต้องใช้ v1.6+ ขึ้นไป ดังนั้นจึงต้องทำให้มันเป็น v1.6+ ซะก่อน

    ดังนั้นก็เลย search หากับพี่กูซะหน่อยไปเจอ http://wiki.bazaar.canonical.com/DistroDownloads#Ubuntu ซึ่งได้บอกวิธีไว้ว่าใช้ add source list เพิ่มโดยใช้ repository ดังนี้

    ขั้นตอนคือไปแก้ที่ file /etc/apt/source.list และเพิ่ม list ด้านล่างลงไป

    deb http://ppa.launchpad.net/bzr/ppa/ubuntu YOUR_UBUNTU_VERSION_HERE main 
    deb-src http://ppa.launchpad.net/bzr/ppa/ubuntu YOUR_UBUNTU_VERSION_HERE main
    

    โดยสำหรับผม ใช้ 8.04 server ดังนั้นจึงใช้

    deb http://ppa.launchpad.net/bzr/ppa/ubuntu hardy main 
    deb-src http://ppa.launchpad.net/bzr/ppa/ubuntu hardy main 
    

    จากนั้นให้พิมพ apt-get update แล้วค่อยติดตั้ง bzr ตามปกติ
    Continue Reading...

    วันพุธที่ 5 พฤษภาคม พ.ศ. 2553

    Bonita and Ldap Configuration (Authenticate User)

    หลังจากที่เราได้ทำ ldap module login สำหรับ bonita กันไปแล้ว ปัญหาก็ได้เกิดขึ้นอีก เนื่องจากเราต้องการ map ให้แต่ละ activity ถูกเรียกใช้งานด้วย group ที่ต่างกันเช่น

    group sales เป็นผู้สร้าง Quotation ขั้นต่อไปคือการ sign Quotation ซึ่งต้องเป็น group manager

    โดย bonita นั้นมี connector ที่ช่วยเราทำงานในลักษณะนี้อยู่แล้ว ซึ่งเราสามารถใส่ host, port, protocol, username, password รวมถึงกำหนด base group, base people แม้กระทั่ง time limit ก็สามารถตั้งค่าได้ แต่ดันไม่มีช่องที่ map attribute กับ username ที่ login มาให้ใส่ค่าซะงั้น

    ก็ต้องมาแกะ code กันเหมือนเดิม ซึ่ง code ในส่วนนี้จะอยู่ที่ bonita-connector ปรากฏว่ามีจุดที่แปลกๆ อยู่ 2 จุดคือ
    1. ที่ method getGroupLdapConenctor ในclass LdapRoleResolver ดันมีการ set ค่า attribute ดื้อๆ เป็น hardcode ซะงั้น
    2. ที่ method getMembersSet ใน class LdapRoleResolver มีการเรียกใช้ method execute() ของ class LdapConnector ถึง 2 ครั้ง (อาจมีความตั้งใจอะไรบางอย่างแต่ผมไม่เข้าใจ)

    ** LdapRoleResolver และ LdapConnector อยู่ที่ bonita-connectors-5.1/ldap/src/main/java/org/bonitasoft/connectors/ldap/

     ดังนั้นจึงต้องแก้ code ใน class นี้ซะได้เป็น

    method getGroupLdapConenctor (สงสัยรีบจัดเลยเขียนชื่อ method ผิด)

    private LdapConnector getGroupLdapConenctor() {
     LdapConnector ldap = new LdapConnector();
     ldap.setHost(host);
     ldap.setPort(port);
     ldap.setProtocol(protocol);
     ldap.setUserName(userName);
     ldap.setPassword(password);
     //ldap.setAttributes("uniqueMember");  แก้จาก uniqueMember เป็น uid
     ldap.setAttributes("uid");
     ldap.setBaseObject(baseObjectGroup);
     ldap.setDerefAliases(derefAliases);
     ldap.setFilter(filter);
     ldap.setReferralHandling(referralHandling);
     ldap.setScope(scope);
     ldap.setSizeLimit(sizeLimit);
     ldap.setTimeLimit(timeLimit);
     return ldap;
    }
    

    และ method getMembersSet

    @Override
    protected Set<String> getMembersSet(String roleId) throws Exception {
     LdapConnector ldap = getGroupLdapConenctor();
         ldap.execute();
    
         Set<String> returns = new HashSet<String>();
         List<List<LdapAttribute>> list = ldap.getLdapAttributeList();
         if (!list.isEmpty()) {
                    // comment ส่วนที่ เรียกซ้ำซ้อน (จริงๆ ไม่รู้ว่าเขาใช้ทำอะไร)
            /*List<LdapAttribute> members = list.get(0);
            StringBuilder builder = new StringBuilder();
            if (members.size() > 1) {
              builder.append("(|");
            }
            for (LdapAttribute member : members) {
              builder.append("(");
              String value = member.getValue();
              int index = value.indexOf(",");
       builder.append(value.substring(0, index));
       builder.append(")");
            }
            if (members.size() > 1) {
              builder.append(")");
            }
            ldap.setBaseObject(baseObjectPeople);
            ldap.setFilter(builder.toString());
            ldap.setAttributes("uid");
            ldap.execute();
            list = ldap.getLdapAttributeList();*/
            for (List<LdapAttribute> uids : list) {
              returns.add(uids.get(0).getValue());
            }
         }
     return returns;
    }


    จากนั้นต้องไปแก้ไข method executeConnector ที่ไฟล์ LdapConnector ด้วยตามนี้

    if (getProtocol() == LdapProtocol.TLS) {
    
    comment ส่วนตรวจสอบ response
    
          //StartTlsRequest request = new StartTlsRequest();
    
          //response = (StartTlsResponse) ctx.extendedOperation(request);
    
          //response.negotiate();
    
          if (getUserName() != null && getPassword() != null) {
    
            ctx.addToEnvironment(Context.SECURITY_AUTHENTICATION, "simple");
    
            ctx.addToEnvironment(Context.SECURITY_PRINCIPAL, getUserName());
    
            ctx.addToEnvironment(Context.SECURITY_CREDENTIALS, getPassword());
    
          }
    
        }
    
    และ
    
        if (getProtocol() == LdapProtocol.TLS) {
    
          //response.close();
    
        }
    
    

    เนื่องจากหากไม่ comment ส่วนดังกล่าวจะทำให้เกิด error ขึ้น ไม่แน่ใจว่าเกิดจาก zimbra ไม่ยอมตอบเมื่อมีการ request ไปหรือเปล่า

    จากนั้นให้ build code ในส่วนนี้ ซึ่ง build แล้วจะได้ไฟล์ ldap-5.x.jar จากนั้นให้นำไฟล์ดังกล่าวไปยัดไว้ที่ studio ที่ path

    BOS-5.x/studio/workspace/My Extensions/provided-libs/ldap/

    แล้วค่อย export bar ไฟล์ใหม่อีกครั้ง ซึ่ง bar นี้จะสามารถ group user ได้ตามที่ตั้งค่าไว้ใน process

    -----------------------------------------

    thanks for @iporsut
    Continue Reading...

    Bonita and Ldap Configuration (Module Login)

    เนื่องจาก bonita นั้นไม่มี module login ที่ใช้ ldap ในการ authentication ดังนั้นเราต้อง implement ส่วนนี้ขึ้นมาเอง โดยขั้นตอนที่เราต้องทำคือสร้าง class ที่ implement interface AuthenticationService

    public interface AuthenticationService {
        /**
         * Check whether a user has admin privileges or not
         * @param username the user's username
         * @return true if the user has admin privileges, false
      otherwise
         * @throws UserNotFoundException
         */
        boolean isUserAdmin(String username) throws UserNotFoundException;
        /**
         * Check some user's credentials
         * @param username the user's username
         * @param password the user's password
         * @return true if the credentials are valid, false otherwise
         */
        boolean checkUserCredentials(String username, String password);
    }  

    ตัวอย่าง class ที่ implement เรียบร้อยแล้ว

    public class LdapZimbraLoginModule implements AuthenticationService {
    
        private String connection;
        private String ldapDN;
    
        public LdapZimbraLoginModule(String connection, String ldapDN) {
            super();
            this.connection = connection;
            this.ldapDN = ldapDN;
        }
    
        public boolean isUserAdmin(String username) throws UserNotFoundException {
            Hashtable env = new Hashtable();
            env.put(Context.INITIAL_CONTEXT_FACTORY, "com.sun.jndi.ldap.LdapCtxFactory");
            env.put(Context.PROVIDER_URL, "ldap://domain:port");
            env.put(Context.SECURITY_PRINCIPAL, username);
            env.put(Context.SECURITY_CREDENTIALS, password);
            try {
                DirContext ctx = new InitialDirContext(env);
                SearchControls sc = new SearchControls();
                sc.setSearchScope(SearchControls.ONELEVEL_SCOPE);
                NamingEnumeration results = ctx.search("ou=people,dc=example,dc=com", "(zimbraIsAdminAccount=TRUE)", sc);
                while (results.hasMore()) {
                    SearchResult searchResult = (SearchResult) results.next();
                    Attributes attributes = searchResult.getAttributes();
                    Attribute attr = attributes.get("uid");
                    if (username.trim().equals(attr.get().toString().trim())){
                        return true;
                    }
                }
                ctx.close();
            } catch (javax.naming.NamingException r) {
            }
            return false;
        }
    
        public boolean checkUserCredentials(String username, String password) {
                Hashtable env = new Hashtable();
                env.put(Context.INITIAL_CONTEXT_FACTORY, 
          "com.sun.jndi.ldap.LdapCtxFactory");
                env.put(Context.PROVIDER_URL, this.connection);
                env.put(Context.SECURITY_PRINCIPAL, 
          "uid=" + 
          username.split("@")[0] + 
          ",ou=people," + 
          this.ldapDN);
                env.put(Context.SECURITY_CREDENTIALS, password);
                DirContext ctx;
                try {
                    ctx = new InitialDirContext(env);
                    ctx.close();
                    return true;
                } catch (javax.naming.NamingException r) {
                }
                return false;
        }
    }

    และควรจะนำไปไว้ที่ bonita-runtime-5.1/bonita-server/src/main/java/org/ow2/bonita/services/impl/ เพื่อ ความเป็นระเบียบ จากนั้นให้ build code ในส่วนของ bonita-server จะได้ไฟล์ bonita-server-5.x.jar

    ให้นำ jar ไฟล์ที่ได้ไป deploy ที่ server ของเรา (ทับของเก่าเลยนะครับ)

    TOMCAT_ROOT/lib/
    ** TOMCAT_ROOT คือ tomcat ที่ได้มาจากการ build ตัว console ของ bonita

    จากนั้นไปแก้ไข authentication service ให้ไปเรียก class ที่เราสร้างขึ้นที่ไฟล์

    TOMCAT_ROOT/conf/bonita-environment.xml

    โดยแก้ไขจาก

    <authentication-service class="org.ow2.bonita.services.impl.DbAuthentication" name="authentication-service">
      <arg>

        <string value="bonita-session:core"></string>
      </arg>
    </authentication-service>


    ให้เป็น

    <authentication-service name='authentication-service' class='org.ow2.bonita.services.impl.LdapZimbraLoginModule'>
               <arg><string value='ldap://domain:port' /></arg>
               <arg><string value='dc=example,dc=com' /></arg>
    </authentication-service>


    โดยค่า <arg> คือ parameter ที่ส่งไปยัง class LdapZimbraLoginModule

    สรุปหลักการโดยคร่าวๆ คือให้สร้าง class ที่ implement AuthenticationService interface เพื่อเป็นตัว check ว่าจะ login ผ่านเมื่อใด จากนั้นแก้ไขให้ server ไปเรียกใช้ class นั้นครับ

    วิธีข้างต้นเป็นวิธีที่ ดิบ+เถื่อนนะครับ เกิดจากการแกะ code แล้วแก้เอาดื้อๆ ซึ่งจริงๆแล้ว มีวิธีที่ดีกว่านี้อยู่ครับ ตามนี้เลย http://www.bonitasoft.org/forum/viewtopic.php?id=2397
    ซึ่งผมอ่านแล้วไม่ค่อยเข้าใจเท่าไร

    -------------------------------------------------------

    thanks for @iporsut
    Continue Reading...

    วันศุกร์ที่ 30 เมษายน พ.ศ. 2553

    แก้ไขปัญหา wireless driver ของ Compaq CQ40-621TU (Broadcom Driver)

    เนื่องจากเพิ่งลง ubuntu 10.04 (lucid) มาใหม่ๆ แล้ว driver ดันใช้ไม่ได้ซะงั้น (scan ไม่เจออะไรเลย) ทำให้ต้องมาแก้ไขกันหน่อย โดยขั้นตอนที่ผมแก้ไขคือ ไป connect internet ด้วย lan ก่อนครับจากนั้นก็ใช้คำสั่ง

    sudo apt-get update

    เมื่อ update เสร็จแล้วให้รันคำสั่ง

    sudo apt-get install --reinstall bcmwl-kernel-source

    จากนั้นก็ restart ซักทีครับ เมื่อ restart กลับมาจะเห็นว่า wireless สามารถใช้งานได้แล้ว (น่าจะสามารถใช้งานได้กับ wireless ของ Broadcom ทุกตัวครับ ลองกับ compaq และ dell)
    Continue Reading...

    วิธีการตั้งค่า locale ใน ubuntu

    เนื่องจากจำเป็นต้องแตกไฟล์ 7zip บน ubuntu แต่เมื่อแตกแล้วภาษาไทยดันเป็น ??? ประเด็นแรกที่ต้องสนใจคือ locale นั่นเอง

    วิธีการตั้งค่าให้ไปแก้ไขไฟล์

    /etc/default/locale 

    โดยใส่ค่าเป็น

    LANG=en_US.UTF-8

    จากนั้น reboot

    หากเป็น case ปกติก็จะสามารถใช้งานได้ทันที แตกไฟล์ 7zip ก็จะได้ภาษาไทย แต่ปัญหาของผมคือมันยังเป็น ??? อยู่แล้วเมื่อพิมพ์ locale ดันขึ้น error ดังนี้

    locale: Cannot Set LC_ALL to default locale: No such file or directory. 

    โดยเมื่อลอง search ดูแล้วเขาบอกว่าอาการนี้เกิดจากการที่ไม่มี locale ดังกล่าวอยู่ในเครื่อง วิธีการตรวจสอบคือให้พิมพ์

    locale -a 

    คำสั่งนี้จะแสดง locale ทั้งหมดของเครื่องออกมา โดยหากไม่มี en_US.UTF-8 แสดงว่าไม่มี locale ดังกล่าวอยู่ในเครื่องแต่มีการเรียกใช้งาน ทำให้เกิด error ดังกล่าว ดังนั้นจำเป็นต้อง add locale ก่อนด้วยคำสั่ง

    localedef -v -c -i en_US -f UTF-8 en_US.UTF-8 

    เมื่อ add locale แล้วให้ตรวจสอบว่ายังมี error อีกหรือไม่ด้วยคำสั่ง locale อีกครั้ง หากไม่มี error ก็แสดงว่าสามารถใช้งานได้แล้ว

    ผมลองแตกไฟล์ 7zip อีกครั้งปรากฏว่าสามารถแสดงผลภาษาไทยได้อย่างไม่มีปัญหา
    Continue Reading...

    วันพฤหัสบดีที่ 25 มีนาคม พ.ศ. 2553

    การ repeat เส้นใน Detail Band บน iReport

    ก่อนอื่นต้องบอกก่อนว่า วิธีการปกติไม่สามารถทำได้ครับ ต้องแปลงๆ เอานิดหน่อยเหมือนกับจะใช้ OpenOffice.org ทำ feature ยากๆ บน Microsoft Office

    โดยปกติแล้ว detail band มักจะต้อง print repeat value เสมอและทำ height ให้เท่ากับ 1 row เพื่อที่จะได้ repeat ค่าที่ query มาจาก database แต่คราวนี้เราจะใช้วิธีการให้ detail band นั้นเป็นเหมือนแค่ template และให้การ fill value นั้นกระทำโดย sub report แทน

    ก่อนอื่นเราก็ตีเส้นตามที่ต้องการใน detail band และยัด sub report ลงไปใน detail band ด้วย


    โดยที่ sub report ก็ลบ band ทั้งหมดให้เหลือเพียง detail band เท่านั้น จากนั้นก็ใส่ field ที่ต้องการลงไป



    เพียงแค่นี้เราก็จะได้การ repeat เส้นภายใน detail band แล้วครับ

    Continue Reading...

    วันจันทร์ที่ 1 มีนาคม พ.ศ. 2553

    ปัญหา fgetcsv กับ php

    เนื่องจากได้เขียน php โดยอ่านไฟล์จากไฟล์ csv ซึ่งมีข้อความภาษาไทยอยู่ โดยเมื่อทดสอบบนเครื่องตัวเองนั้นไม่มีปัญหาใดๆ ทั้งสิ้นแต่เมื่อ deploy ขึ้นไปบน server ดันเกิดปัญหาขึ้นโดย ภาษาไทยนั้นไม่แสดงผล

    จากที่ลอง research ดูก็ไล่ไปเรื่อยๆ ตั้งแต่ check ว่าเปิดไฟล์ได้ไหม echo ภาษาไทยได้ไหม และก็มาเจอประเด็นที่ fgetcsv

    จากที่อ่านใน http://php.net/manual/en/function.fgetcsv.php ซึ่งมีเขียนไว้ว่า

    Note: Locale setting is taken into account by this function. If LANG is e.g. en_US.UTF-8, files in one-byte encoding are read wrong by this function.

    แสดงว่าเราต้องทำการ set locale ให้กับ apache การแสดงผลจึงจะถูกต้องโดยใช้คำสั่ง

    setlocale ( LC_ALL, 'en_US.UTF-8' );

    แค่นี้ก้จะทำให้การ get csv ที่มีภาษาไทยภายในไฟล์แสดงผลได้ถูกต้องแล้วครับ
    Continue Reading...

    วันพุธที่ 3 กุมภาพันธ์ พ.ศ. 2553

    การใช้งาน svn command (ubuntu)

    เนื่องจากมีความจำเป็นต้องใช้งาน svn เลยต้องศึกษาวิธีใช้งาน ซึ่งตอนแรก งง มากไม่ค่อยเข้าใจ concept มันเท่าไร อ่านของคนอื่นที่เขียนไว้ก็ไม่เข้าใจ ทั้งๆ ที่เป็นภาษาไทย เพราะยังไม่เข้าใจ concept ของมันนั่นเอง

    คราวนี้เมื่อทำเป็นแล้วจึงอยากเขียนอธิบายไว้ครับ

    ขั้นแรกก็ต้องติดตั้ง svn ก่อนโดยใช้คำสั่ง

    sudo apt-get install svn

    จากนั้นเมื่อติดตั้งเรียบร้อยแล้วให้หา folder เหมาะๆ ที่จะใช้ในการ checkout และ commit ไฟล์ ของ svn เช่น /home/user/subversion/

    เมื่อเลือก folder ได้แล้วให้ใช้คำสั่ง

    svnadmin create /home/user/subversion/

    จากคำสั่งด้านบน folder subversion ของเราก็จะกลายเป็น repository เพื่อใช้ในการ checkout ไฟล์จาก svn และเป็น working copy ที่จะ commit ไฟล์กลับเข้าไปครับ

    จากนั้นขั้นตอนต่อไปคือต้อง checkout ไฟล์ออกมาจาก svn server ก่อน (อันนี้งงตั้งนาน ใจจริงผมอยาก import เข้าไปใน svn แต่ไม่อยาก checkout แต่ขั้นตอนคือ ยังไงต้อง checkout ออกมาก่อน) ด้วยคำสั่ง

    svn co url

    โดยที่ url คือ svn server path เช่น svn://domain/project/trunk

    จากนั้นเมื่อ checkout ออกมาแล้วอยากจะ commit ไฟล์กลับขึ้นไป ให้ใช้คำสั่ง svn add /path/to/file ซึ่งทางที่ดี นำไฟล์นั้นมาวางใน folder ของเราเลยก็ได้ครับ จากนั้นใช้คำสั่ง

    svn commit -m "comment"

    ซึ่ง comment นั้นสำคัญมากครับ ถ้าไม่ระบุ บุคคลอื่นจะไม่รู้ว่าที่เรา commit ขึ้นไปนั้น แก้ไขอะไรบ้าง

    ก่อนที่เราจะ commit ไฟล์ขึ้นไป อาจใช้คำสั่ง

    svn status

    ดูก่อนก็ได้ว่า เราจะ Deleting, Adding ไฟล์อะไรขึ้น server บ้าง
    Continue Reading...

    วันเสาร์ที่ 16 มกราคม พ.ศ. 2553

    set ค่า mysql ให้ใช้งาน utf8

    โดยปกติแล้ว default character ของ mysql นั้นจะไม่ใช่ utf8 ทำให้ค่าที่ input ที่เป็นภาษาไทยมีค่าเป็น ??? ดังนั้นเราต้องมาตั้งค่า config ของ mysql ให้เป็น utf8 โดยการ

    ใช้ text editor ที่ถนัดเปิด /etc/mysql/my.cnf จากนั้นไปที่ส่วนของ [client] แล้วหาบรรทัดว่างๆ เพิ่มคำว่า

    default-character-set=utf8



    จากนั้นทำเหมือนกันที่ส่วนของ [mysqld]
    เมื่อแก้ไขไฟล์เสร็จเรียบร้อยแล้ว ทำการ restart mysql แล้วทดลอง input ค่าเป็นภาษาไทยดู จะเห็นว่าไม่เป็น ??? แล้ว
    Continue Reading...

    วันจันทร์ที่ 11 มกราคม พ.ศ. 2553

    reset, change password สำหรับ mysql

    กรณีที่ลืม password mysql วิธีที่ง่ายที่สุดคือการ reset password โดยสำหรับ ubuntu นั้นสามารถทำได้โดยใช้คำสั่ง

    sudo /etc/init.d/mysql stop
    sudo mysqld --skip-grant-tables &
    mysql -u root mysql
    UPDATE user SET Password=PASSWORD('YOURNEWPASSWORD') WHERE User='root'; FLUSH PRIVILEGES; exit;

    โดยใส่ password ที่ต้องการใที่ 'YOURNEWPASSWORD' จากนั้นสั่ง start mysql ใหม่แล้ว login ด้วย password ใหม่ได้ทันที

    ที่มา - ubuntu.flowconsult.at
    Continue Reading...

    วันเสาร์ที่ 9 มกราคม พ.ศ. 2553

    แก้ปัญหา driver บน Ubuntu สำหรับ Intel 945GM

    เพิ่งจะได้ลง 9.10 กับเขาเสียที แต่ก็เจอปัญหาคือ display แสดงผลกระพริบตลอดเวลาเลย เลยลอง search ดูว่ามีทางแก้ปัญหาไหม ซึ่งก็ได้เจอ link นี้ซึ่งได้ลองทำตามดู (อ่านไม่ออกเลยมั่วๆ เอาดูแล้วน่าจะเป็นภาษาเสปน) ได้ขั้นตอนดังนี้
    1. add repository ไปที่ /etc/apt/source.list
      deb http://ppa.launchpad.net/siretart/ppa/ubuntu jaunty main
      deb-src http://ppa.launchpad.net/siretart/ppa/ubuntu jaunty main
      
    2. จากนั้น ยืนยัน key กับ server ด้วยคำสั่ง
      sudo apt-key adv --recv-keys --keyserver keyserver.ubuntu.com 0xce90d8983e731f79
    3. จากนั้นใช้คำสั่ง
      sudo apt-get update
    4. จากนั้นติดตั้ง driver
      sudo apt-get install xserver-xorg-video-intel-2.4
    5. ขั้นตอนสุดท้ายคือ restart gdm
      sudo /etc/init.d/gdm restart
    เมื่อ restart gdm แล้วจอเราก็จะไม่กระพริบอีกต่อไปครับ
      Continue Reading...

      วันพฤหัสบดีที่ 7 มกราคม พ.ศ. 2553

      basic html and js

      ได้กลับมาเขียน html 1 หน้าทำให้รู้สึกว่า เมื่อไม่ได้เขียนมันนานๆ ต้องเปิด reference ตลอดเลยเรา ก็พอเขียนไปได้เรื่อยๆ จนถึงขั้นตอนการทำ js ดึงค่าจากไฟล์ มาใส่ใน dropdown ใน html ขั้นตอนนี้เสียเวลานานมาก เพราะ search มาเจอ solution ต่างกันทำให้สับสนมากจนอยากเขียนเก็บไว้เอง

      output ที่ต้องการนั้นคือ เมื่อ load html แล้วต้องการให้รายชื่อทั้งหมด add ลงไปใน dropdown ใน html ที่ load ขึ้นมา ขั้นแรกก็ต้องใส่ function onload ที่ body ซะก่อนคือ

      <body onload="additem();">
      

      ต่อมาก็ต้องสร้าง dropdown โดยเราต้องกำหนด id ให้มันด้วยเนื่องจากจะได้ระบุได้ว่าจะเอา output จากไฟล์ไปใส่ที่ใด

      <select id="myitem"></select>
      

      ขั้นต่อไปก็ต้องไปสร้าง javascript function ที่ชื่อว่า additem() ดังนี้ครับ
      function additem(){
      var ajax;
      try{
        // Opera 8.0+, Firefox, Safari
        ajax = new XMLHttpRequest();
      } catch (e){
        // Internet Explorer Browsers
        try{
          ajax = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
          try{
            ajax = new ActiveXObject("Microsoft.XMLHTTP");
          } catch (e){
            // Something went wrong
            alert("Your browser broke!");
            return false;
          }
        }
      }
      
      ajax.onreadystatechange = function(){
        if (ajax.readyState == 4) {
          document.getElementById('myitem').innerHTML = ajax.responseText;
        }
      }
      ajax.open("GET", "item.html", true);
      ajax.send(null); 
      }
      

      ซึ่งไฟล์ของเราที่ชื่อ item.html นั้นมีข้อมูลดังนี้

      <option>item1</option>
      <option>item2</option>
      <option>item3</option>
      

      สรุปคือเมื่อ load page นี้ขึ้นมาแล้วจะทำการ add option ต่างๆ จากไฟล์ item.html ไปใส่ที่ select id="myitem" ครับซึ่งก็จะได้ dropdown ที่มีค่า item1, item2, item3 ตามลำดับคร้าบ
      Continue Reading...

      Blogroll

      About