Ady Wicaksono Daily Activities

Archive for October 2007

verify blank string on form with javascript

without comments

Here’s the function

function isSpaceOnly(s){
var l = s.length;
var c; for(i = 0; i < l; i++){
   if(s.charAt(i) != ' ' && s.charAt(i) != '\t' && s.charAt(i) != '\n'){
      return false;
   }
 }
 return true;
}

Then you only need to use if that function return true -> meaning blank string including space only string given

Written by adywicaksono

October 31, 2007 at 2:18 pm

Posted in javascript

create “select all” & “deselect all” for checkbox option with javascript

without comments

Sometimes we create HTML document that contains some checkbox option.Sometime we need to click every checkbox option, so is there quick way for doing this? Off course we can do it easily if there’s “select all” button to click every checkbox option…, so how to do it?

Here’s the example code for doing this

function checkAll(){
	var i = document.f['keycode_id[]'].length;
	if(i == undefined){
		document.f['keycode_id[]'].checked = true;
	}else{
		for(j = 0; j < i; j++){
			document.f['keycode_id[]'][j].checked = true;
		}
	}
}	

function unCheckAll(){
	var i = document.f['keycode_id[]'].length;
	if(i == undefined){
		document.f['keycode_id[]'].checked = false;
	}else{
		for(j = 0; j < i; j++){
			document.f['keycode_id[]'][j].checked = false;
		}
	}
}

With assumption that the document form is “f” and the option chekbox variable name is “keycode_id[]“, otherwise you only need to change it. Next step youonly need to create button with event “onClick” will execute one of those 2 function (select all or deselect all)

Written by adywicaksono

October 31, 2007 at 2:13 pm

Posted in javascript

Javacard code to send SMS (Unformated SMS-PP & 7Bit TP-UD)

with one comment

TP-UD of SMS as defined in GSM 03.40 can contain up to 140 octet/bytes. But some common people always ask, are you sure only 140 bytes? Because normally we can send 160 character. Yes, because those 160 character is actually a 7bit data (septet), means with 140 octet we can send 140 * 8/7 ~ 160 septet. I hope you know it now :)

Ok, some javacard programmer ask how to send SMS Unformatted PP (means not include GSM 03.48 header) with 7bit TP-UD? Let me show you.

1. You need to define these variables somewhere inside your javaclass

// Variable to declare inside your class
private byte[] bSendSMSBuffer; // Buffer of TP-UD SMS
private byte[] ramUnPacked;
private byte[] ramPacked;

2. You need to allocate memory for this, normally you should put it on RAM rather on EEPROM, because do writing on EEPROM too oftenly will kill the card. Normally you will put these codes inside your javacard class constructor

try{
      // Allocate buffer on RAM and free it once the applet is deselected
      bSendSMSBuffer  = JCSystem.makeTransientByteArray( ( short )160,
                                              JCSystem.CLEAR_ON_DESELECT );
}catch (SystemException e){
      // Allocate buffer on EEPROM, if your application will write a lot on this variable,
      // this one should be avoided if possible
      bSendSMSBuffer  = new byte[(short)160];
}

try{
   ramUnPacked		= JCSystem.makeTransientByteArray( (short)8,
                                           JCSystem.CLEAR_ON_DESELECT);
}catch(SystemException e){
   ramUnPacked     = new byte[(short)8];
}
try{
     ramPacked		= JCSystem.makeTransientByteArray( (short)8,
                                           JCSystem.CLEAR_ON_DESELECT);
}catch(SystemException e){
    ramPacked     = new byte[(short)8];
}

3. Add this 2 function on your javacard class code:


	// Send sms function
	// input: tpud, len of tpud, destination address , len of destination address
	public byte sendSMS(byte[] dataBuff, short Len,byte[] DesAdd, short DesLen) throws UserException {
		ProactiveHandler proHdlr = ProactiveHandler.getTheHandler();
		short smstpduLength      = (short) 0;
		short numberLength       = (byte)  0;
		final byte CMD_QUALIFIER_PACKING_NOT_REQUIRED = (byte) 0;

		//Initialize the recordbuffer to Construct the Sms-TPDU Buffer
		Util.arrayFillNonAtomic(bSendSMSBuffer, (short)0,
		            (short)bSendSMSBuffer.length, (byte)0x00);

		// Now Construct the Sms TPDU in the recordData
		// see GSM 03.40 for details
		bSendSMSBuffer[smstpduLength++] = (byte) 0x01; //SMS-Submit Type
		bSendSMSBuffer[smstpduLength++] = (byte) 0x01; //Message reference

		// TP-Destination Address
		Util.arrayCopy(DesAdd,(short)0, bSendSMSBuffer, smstpduLength,(short)DesLen);
		smstpduLength = (short) ((short) smstpduLength + (short)DesLen);

		bSendSMSBuffer[smstpduLength++] = (byte) 0x00; // TP-PID 0x00
		bSendSMSBuffer[smstpduLength++] = (byte) 0x00; // TP-DCS 0x00
		bSendSMSBuffer[smstpduLength++] = (byte) Len;  // TP-UDL (User Data Length)

		// Pack data to 7 bit before sending
		convert_8bit_2_7bit( dataBuff, (short)0, Len, bSendSMSBuffer, smstpduLength );

		short f = 0;
		f       = (short)((short)(Len * 7 )/(short)8 );
		if((short)(Len % 8 ) != (short)0){
				f++;
		}	

		smstpduLength+=f;                 

		// Sending the message
		proHdlr.init(PRO_CMD_SEND_SHORT_MESSAGE,CMD_QUALIFIER_PACKING_NOT_REQUIRED, DEV_ID_NETWORK);

		// Uncommented this one to add some text while sending sms
		//proHdlr.appendTLV((byte) (TAG_ALPHA_IDENTIFIER),SENDING, (byte)0, (short) SENDING.length);

		proHdlr.appendTLV((byte) (TAG_SMS_TPDU),bSendSMSBuffer, (byte)0, (short)smstpduLength);
		return proHdlr.send();
	}

	private void convert_8bit_2_7bit( byte[] source,
                                      short sourceStartOfst,
                                      short sourceLen,
                                      byte[] destin,
                                      short destinOfst){

		// Convert 8 bytes of data at each pass
		short copyLength = (short) 8;

		// Pointer pointing to the start offset
		short sourcePtr = sourceStartOfst;

		// Calculate the end offset of the unpacked data
		short sourceEndOfst = (short) ( sourceStartOfst + sourceLen );

		// Loop until gone through all the data
		while ( sourcePtr < sourceEndOfst ){
			// If the remaining data in Unpacked data is less than the 8 byte unit
			if ( (short) ( sourcePtr + copyLength ) > sourceEndOfst ) {
				// Get the remaining number of bytes
				copyLength = (short) ( sourceEndOfst - sourcePtr );
				// Clear the RAM data
				Util.arrayFillNonAtomic( ramUnPacked, (short) 0, (short) 8, (byte) 0x00 );
			}

			// Copy from source data to RAM unpacked data
			Util.arrayCopyNonAtomic( source, sourcePtr, ramUnPacked, (short) 0, copyLength );

			// Update Source Pointer
			sourcePtr += copyLength;
			// Calculate 1st byte
			ramPacked[0] = (byte) ( ( ( ramUnPacked[0] << 1 ) & 0xFE) | ( ( ramUnPacked[1] >> 6 ) & 0x01 ) );
			// Calculate 2nd byte
			ramPacked[1] = (byte) ( ( ( ramUnPacked[1] << 2 ) & 0xFC) | ( ( ramUnPacked[2] >> 5 ) & 0x03 ) );
			// Calculate 3rd byte
			ramPacked[2] = (byte) ( ( ( ramUnPacked[2] << 3 ) & 0xF8) | ( ( ramUnPacked[3] >> 4 ) & 0x07 ) );
			// Calculate 4th byte
			ramPacked[3] = (byte) ( ( ( ramUnPacked[3] << 4 ) & 0xF0) | ( ( ramUnPacked[4] >> 3 ) & 0x0F ) );
			// Calculate 5th byte
			ramPacked[4] = (byte) ( ( ( ramUnPacked[4] << 5 ) & 0xE0) | ( ( ramUnPacked[5] >> 2 ) & 0x1F ) );
			// Calculate 6th byte
			ramPacked[5] = (byte) ( ( ( ramUnPacked[5] << 6 ) & 0xC0) | ( ( ramUnPacked[6] >> 1 ) & 0x3F ) );
			// Calculate 7th byte
			ramPacked[6] = (byte) ( ( ( ramUnPacked[6] << 7 ) & 0x80) | ( ( ramUnPacked[7] >> 0 ) & 0x7F ) );

			// Copy the RAM packed data to destination byte array
			Util.arrayCopyNonAtomic( ramPacked, (short) 0, destin, destinOfst, (short) 7 );

			// Update Destination Pointer
			destinOfst += (short) 7;
		}
	}

And you then can simply sms like this:
1. For example you want to send SMS to 12345, you will need to create TP_DA (Destination Address) byte array containing:
1. first 1 byte that inform the length of address
2. 2nd 1 byte that inform TON/NPI
3. the rest is address in BCD swapped format

e.g like this:

private byte[] TPDA       = {(byte)0x05,(byte)0x81,(byte)0x21,(byte)0x43,(byte)0xF5};
0x05 : Length of '12345' -> 5 bytes
0x81: TON/NPI
0x21 0x43 0xF5: BCD swapped format for address 12345

And then you define the SMS content like this:

private byte[] sms_content = {(byte)'T',(byte)'e',(byte)'s',(byte)'t')};

And then you send it like this

try{
sendSMS(sms_content,(short)sms_content.length, TPDA, (short)TPDA.length);
}catch(Exception e){
}

Good luck :)

Written by adywicaksono

October 24, 2007 at 2:54 pm

Posted in SmartCard

Some Projects while running adiska.com

without comments

1. Aug 2007, Implement Kannel with connectivity to Mblox (www.mblox.com) for InspironLogistic, USA. InspironLogistic products including WENS. Website http://www.inspironlogistics.com/.
Application: Linux 2.6 (Fedora Core 3), Kannel + Patch for Mblox + SQLBox, MySQL

2. April 2007, Implement OMA SyncML Data Synchronization Setting Over The Air for Spiderboss (www.spiderboss.com), Sweden.
Application: Linux 2.6 (Fedora), Java, WBXML, OMA DS Spec., Nokia/Ericsson Setting OTA Spec, OpenSMPP

3. Sept 2007, Implement WAP Push engine with connectivity with Zong (www.zong.com) and Esendex (www.esendex.com) for Flexta (www.flexta.co.uk).
Skillset: PHP, Push Proxy Gateway (PPG), Push Access Protocol

4. Sept 2007, Implement Kannel with connectivity to Opera (http://www.operatelecom.com/) for ListenerActive Pty Ltd (www.listeneractive.com), Australia. Need to patch Kannel

5. 2006, Deliver SMS platform for ListenerActive Pty Ltd (www.listeneractive.com), including kannel implementation + content management system to manage kannel connection, sms keyword, monitoring, …

6. 2006, Implement Postfix + Cyrus Email system based on Fedora Linux for Regional Investment, BKPM (www.bkpm.go.id)

7. 2004, Implement Mobile eMail based on WAPMail + WAP Push for ease mail notification for PT Rekayasa Industri (www.rekayasa.com)

Written by adywicaksono

October 17, 2007 at 1:09 pm

Posted in adiska.com

Patch Kannel to disable enquire_link/enquire_link_resp logging

without comments

Kannel monitoring sometimes needed by administrator. Normally, we will activate debug log to monitor submit_sm, deliver_sm, data_sm, and similar one. But, maybe you got annoyed by enquire_link & enquire_link_resp which normally done almost every 30 seconds or less.

To enable debug mode of kannel but skip enquire_link/resp you need to modify

1. gw/smsc/smpp_pdu.c

Find function name “void smpp_pdu_dump(SMPP_PDU *pdu)” and add this line at the
on the first line of function body code:

// No need enquire_link debug info
if(pdu->type == 0x80000015){
   return;
}

2. gw/smsc/smsc_smpp.c
Find function name “static void send_enquire_link(SMPP *smpp, Connection *conn, long *last_sent)” and add remove or comment this line.

dump_pdu("Sending enquire link:", smpp->conn->id, pdu);

3. gw/smsc/smsc_smpp.c
Find function name “static void io_thread(void *arg)” and find this line

/* Deal with the PDU we just got */
dump_pdu("Got PDU:", smpp->conn->id, pdu);

Change to

/* Deal with the PDU we just got */
if(pdu->type != 0x80000015){
dump_pdu("Got PDU:", smpp->conn->id, pdu);
}
Now your log will contain no enquire_link/resp :)

Written by adywicaksono

October 11, 2007 at 4:23 pm

Posted in C/C++, kannel

Learning C/C++ part 1

with 6 comments


#include <iostream>
#include <cstdlib> // Define system()
#include <string>  // Define string
#include <fstream> // File Operation
#include <vector>  // The same with java Vector implementation
using namespace std;

// Global Variable
int globalIntOK = 1000;

string hello(){
    return "Hello TAHU\n";
}

void swap(int *a, int *b){
    int c;
    c  = *a; // C now contains memory address of a
    *a = *b; // data pointed by address memory a is now contain data pointed by memory b
    *b = c;  // data pointed by address memory b is now = c
}

void func_withnostatic(){
    int y = 10;
    cout << "y: " << y++ << endl;
}

void func_withstatic(){
    static int y = 10;
    cout << "y: " << y++ << endl;
}

void swapCPP(int& a, int& b){
    cout << "C++ SWAP -> a = " << a << endl;
    cout << "C++ SWAP -> b = " << b << endl;
    cout << "C++ SWAP address -> a = " << &a << endl;
    cout << "C++ SWAP address -> b = " << &b << endl;

    int c;
    c = a; // karena &a adalah alamat memory,
    // maka a adalah isi dari alamat memori itu
    a = b;
    b = c;
}

int main_learn1(int argc, char **argv){
    int number;
    cout << "Hello World" << endl
    << "Hello too !" << endl;
    cout << "Number 15 in decimal: " << dec << 15 << endl;
    cout << "Number 15 in octal : " << oct << 15 << endl;
    cout << "Number 15 in hex : " << hex << 15 << endl;
    cout << "Floating Point : " << 15.12 << endl;
    cout << "Char(27) is : " << char(27) << endl;
    cout << "Char concat "
    " continue 1 "
    " continue 2 " << endl;
    cout << "Enter Number: " ;
    cin >> number;
    cout << "Number: " << dec << number << endl;

    // Calling SYSTEM Program
    system("echo 'Hallo ADY'");

    // String on C++
    string s1, s2; // Empty String
    string s3 = "hello World String"; // init string
    string s4("Hello World Another string"); // init string too

    cout << "String 3: " << s3 << endl;
    cout << "String 4: " << s4 << endl;

    cout << "Just like java...concat is simple-> " << s3 + " " + s4 << endl;

    s1 = "testaja.yt";
    ifstream inFile(s1.c_str()); // ifstream -> open for reading
    if(inFile.is_open()){
        cout << "File " << s1 << " is opened" << endl;
        string buff1;
        while(getline(inFile,buff1)){ // ReadFile .. but '\n' discarded
            cout << buff1 << endl;
        }
        inFile.close();
    }else{
        cout << "File " << s1 << " is NOT opened" << endl;
    }

    ofstream outFile(s1.c_str()); // ofstream -> open for writing
    if(outFile.is_open()){
        cout << "File " << s1 << " is opened to be written" << endl;
        outFile.write(s3.c_str(),s3.length());
        outFile.close(); // Close File
    }else{
        cout << "File " << s1 << " is NOT opened to be written" << endl;
    }

    cout << "Vector" << endl;
    string x1,x2,x3;
    vector<string> vStr;

    x1 = "Data 1";
    x2 = "Data 2";
    x3 = "Data 3";
    vStr.push_back(x1); // Masukin Elemen
    vStr.push_back(x2); // Masukin Elemen
    vStr.push_back(x3); // Masukin Elemen

    // Tampilkan Elemen
    int i;
    for(i=0; i < vStr.size(); i++){
        cout << "Elemen ke-" << i+i << ": " << vStr[i] << endl;
    }

    vector<int> vInt;
    vInt.push_back(1);
    vInt.push_back(2);
    vInt.push_back(3);
    for(i=0; i < vInt.size(); i++){
        cout << "Elemen ke-" << i+i << ": " << vInt[i] << endl;
    }

    // Fungsi juga bisa dipakai lho untuk cout
    cout << "Hasil fungsi hello(): " << hello() << endl;

    // Ada boolean di sana
    bool x;
    x = true;

    cout << "Boolean x = " << x << endl;

    // Pointer tetap ada
    int y = 1231;
    cout << "Alamat memory dari y yang bernilai " << y << ", adalah " << (long)&y << endl;
    cout << "Alamat memory dari fungsi hello(), adalah " << (long)&hello << endl;

    int abc = 1000;
    int *p_abc = &abc; // p_abc adalah pointer ke integer -> diacu ke alamat abc
    cout << "ABC = " << abc << endl;
    *p_abc = 2000;
    cout << "Skrg ABC = " << abc << endl;

    // Fungsi Pointer dengan C

    char ans;
    while(true){
        cout << "Ketik y untuk melanjutkan: ";
        cin >> ans;
        if(ans == 'y'){
            break;
        }
    }
    int tahu = 100;
    int tempe = 200;
    cout << "Tahu = " << tahu << endl;
    cout << "Tempe = " << tempe << endl;
    swap(&tahu,&tempe); // Alamat memory tahu & tempe dipass ke fungsi
    cout << "SWAP(), now...\nTahu = " << tahu << endl;
    cout << "Tempe = " << tempe << endl;

    // C++ reference
    // C++ punya model baru untuk pass by reference,
    // Yakni dengan menggunakan tanda & pada parameter fungsi, bukan *
    swapCPP(tahu,tempe);
    cout << "SWAP back with C++ Reference(), now...\nTahu = " << tahu << endl;
    cout << "Tempe = " << tempe << endl;

    cout << "Now about scoping" << endl;
    { int tahutempe; // variabel ini hanya dikenali di sini
    };

    // Disini jika diuncomment akan tampil
    // : error C2065: 'tahutempe' : undeclared identifier (vc++6)
    /* cout << "Tahu Tempe variabel? " << tahutempe; */

    // Global Variable
    cout << "Global Variable globalIntOK = " << globalIntOK << endl;

    // Register Variable, process it as fast as you can :D
    // Only valid in block, you may not have global register :D
    register int test01 = 1001;
    cout << "Test01 Var as Register = " << test01 << endl;

    // Static Variables
    // Variabel yang tidak didefinisikan static dalam sebuah fungsi
    // nilainya akan diinisialisasi ulang, tp jika static maka
    // saat "return" dari fungsi nilainya akan tetap disimpan
    // Static mirip dengan global, tapi variabel static hanya berlaku
    // dalam blok fungsi dimana dia diterapkan :)
    // dikenal juga file scope, dimana static variabel yang ditaruh
    // spt penempatan variabel global -> berarti variabel ini hanya dikenali
    // di file ini saja
    for(i = 0; i < 10; i++){
        func_withnostatic();
    }
    for(i = 0; i < 10; i++){
        func_withstatic();
    }

    // Variabel extern ... waktu dilakukan linking (compile -> link)
    // diasumsikan ada diantara file2 yang linking
    /*
    When the compiler encounters the declaration ‘extern int i’, it
    knows that the definition for i must exist somewhere as a global
    variable.
    */
    // Constanta di C++
    // di C biasanya digunakan macro
    #define MY_CONST 1000
    cout << "My Const = " << MY_CONST << endl;
    // di C++ bisa digunakan const
    const int h = 121;
    cout << "Const h = " << h << endl;

    return 0;
}

int main_learn2(int argc, char **argv){
    return 0;
}

int main(int argc, char **argv){
    main_learn1(argc,argv);
    return 0;
}

Written by adywicaksono

October 5, 2007 at 10:19 pm

Posted in C/C++

Traceroute – how it works?

without comments

I was a network and system administrator, one of tools I used is traceroute or tracert (in Windows). See this example traceroute from my desktop:

Tracing route to www.yahoo-ht3.akadns.net [69.147.114.210]
over a maximum of 30 hops:
1     2 ms     1 ms     2 ms  192.168.1.1
2     9 ms    15 ms    12 ms  10.53.128.1
3    13 ms    11 ms    12 ms  172.20.53.65
4    12 ms    11 ms     8 ms  172.26.53.1
5    16 ms    12 ms    13 ms  172.20.8.245
6    12 ms    14 ms    13 ms  203.116.5.125
7    20 ms    16 ms    24 ms  203.118.3.229
8   232 ms   237 ms   230 ms  so-4-0-0.edge2.LosAngeles1.Level3.net [4.71.134.1]
9   233 ms   232 ms   230 ms  ae-2-54.bbr2.LosAngeles1.Level3.net [4.68.102.97]
10   237 ms   229 ms   232 ms  ae-0-0.bbr1.SanJose1.Level3.net [64.159.1.129]
11   316 ms   230 ms   426 ms  ae-13-69.car3.SanJose1.Level3.net [4.68.18.5]
12   386 ms   402 ms   400 ms  4.71.112.14
13   283 ms   294 ms   287 ms  so-0-0-0.pat2.dcp.yahoo.com [216.115.101.150]
14   292 ms   295 ms   289 ms  ge-3-1-0-p171.msr2.re1.yahoo.com [216.115.108.71]
15   288 ms   291 ms   293 ms  gi1-22.bas-a1.re3.yahoo.com [68.142.238.65]
16   285 ms   286 ms   286 ms  f1.www.vip.re3.yahoo.com [69.147.114.210]

Traceroute use TTL (time-to-live) feature of IP (Internet Protocol). TTL is an upper bound of the time that IP datagram packet can exist in an internet system. TTL field will be decrease by one value by every host on the route to its destination. If the TTL field reaches zero before the datagram arrives at its destination, then the datagram is discarded and an ICMP error datagram (11 – Time Exceeded) is sent back to the sender.

So for previous example, traceroute application will firstly set TTL to 1 to access www.yahoo.com, but because when pass 192.168.1.1 the value will reduced by one, become zero than, host 192.168.1.1 will send ICMP error datagram. The traceroute application will then know that next hop is 192.168.1.1. Again it’s now set TTL to 2, but after 10.53.128.1 TTL value become 0 but the IP is still not reach it’s final destination so 10.53.128.1 will send ICMP error datagram. Again and again traceroute application will increase TTL value and collect ICMP error datagram from each hop until the TTL value is big enough to reach final destination. The result is shown as traceroute log above.

Another issue, this traceroute application on UNIX platform need to access ICMP protocol which is only accessible by root (or any user with uid = 0). So, application traceroute mostly will run with setuid root active and can become a security hole. Don’t worry, normally current traceroute application is secure enough event with setuid flag root active.

For more information about ICMP please refer to RFC 792

Written by adywicaksono

October 5, 2007 at 4:10 pm

Posted in networking