Monday, March 09, 2009

Quick Tip: Firefox exception 0xc000000d at location 0x7817EF67

If your firefox shows this error: THE EXCEPTION UNKNOWN SOFTWARE EXCEPTION (0xc000000d) OCCURED IN THE APPLICATION AT LOCATION 0x7817EF67 and you've tried to restart the application, but the problem still exists, try this solution.

It will happen when you've AVG in your system and the Link Scanner is enabled. The only solution until it's fixed by Mozilla or AVG, is disabling the AVG's Link Scanner. Here's how:
  • Close your firefox

  • Right click on AVG tray icon, then select Open AVG User Interface

  • Double click on LinkScanner Component or from the menu Components>>LinkScanner

  • Deselect on Enable AVG Search Shield (need web browser restart) checkbox

  • Run your firefox and try to browse the sites which the browser usually crash.

Labels: ,

Tuesday, September 02, 2008

New Backup/Restore Statement in MySQL 6.0

Finally, what I've been waiting for long time is currently in progress !
New backup and restore syntax is available in MySQL begin from version 6.0.5. (it's still in alpha state at the time I write this post)

This syntax is use just like ordinary DDL/DML SQL syntax, so you wouldn't need to run external application eg. mysqldump anymore. The best of it, is the backup process won't block any client accesses, or vice versa. They can now work concurrently, except for the DDL syntax.

The syntax is so simple:
BACKUP DATABASE [DATABASE] TO [PATH];
RESTORE FROM [PATH];

For example, to backup,
BACKUP DATABASE mycompanydatase TO '/home/staff/backup/backupfile.dat';
to restore,
RESTORE FROM '/home/staff/backup/backupfile.dat';

For more information about new BACKUP/RESTORE syntax in MySQL 6.0, see the documentation.
BACKUP/RESTORE using MySQL < 6.0 still need external tools. See my tutorial about Backup MySQL Data Using Java.

Thursday, July 31, 2008

Dealing With MySQL Cast() Limitation

If your application depends on data type of your database, you will notice that mysql cast() function has limitation that can't cast to specific datatype, like tinyint, smallint, mediumint, bigint, etc.

There is simple (dumb and idiot) workaround you can do to overcome this situation. Let's try it out.

Create a table with 5 column.
CREATE TABLE datatype_test (
tiny_int tinyint(4),
small_int smallint(6),
medium_int mediumint(9),
_int int(11),
big_int bigint(20)
);


Populate each column with value of 10.
INSERT datatype_test (
tiny_int,
small_int,
medium_int,
_int,
big_int
)
values (10,10,10,10,10);


Now, let's try with a simple query.
select     (d.tiny_int*1) as tiny,
(d.small_int*1) as small,
(d.medium_int*1) as `medium`,
(d._int*1) as regular,
(d.big_int*1) as big
from datatype_test d;


When you multiply the columns with any number, the result data type is not same as the original data type. You can check it using this Java snippet:
import java.sql.*;

public class datatype_test {
public Connection cn;
public PreparedStatement st;
public ResultSet rs;

public static void main(String[] a) throws Exception {
new datatype_test();
}

public datatype_test() throws Exception {
connect();

showcase1();
}

private void connect() throws Exception {
Class.forName("com.mysql.jdbc.Driver");

String url = "jdbc:mysql://localhost/test";
cn=DriverManager.getConnection(url,"user","password");
}

private void showcase1() throws Exception {
st = cn.prepareStatement(
"select (d.tiny_int*1) as tiny, " +
" (d.small_int*1) as small, " +
" (d.medium_int*1) as `medium`, " +
" (d._int*1) as regular, " +
" (d.big_int*1) as big " +
"from datatype_test d;");

if (st.execute()) {
rs = st.getResultSet();
rs.next();

ResultSetMetaData rsmt = rs.getMetaData();
int cols = rsmt.getColumnCount();

for (int i=1;i<=cols;i++) {
System.out.println(rsmt.getColumnLabel(i) + " = " +
rsmt.getColumnTypeName(i));
}
}

rs.close();
st.close();
}
}



When you run it, the result will looks like this:
tiny = BIGINT
small = BIGINT
medium = BIGINT
regular = BIGINT
big = BIGINT


That's the problem. Let's do something with this. While MySQL cast() has limitation, why not make our own cast function.
CREATE FUNCTION x_cast_to_tinyint(number bigint) RETURNS tinyint
BEGIN
return number;
END

CREATE FUNCTION x_cast_to_smallint(number bigint) RETURNS smallint
BEGIN
return number;
END

CREATE FUNCTION x_cast_to_mediumint(number bigint) RETURNS mediumint
BEGIN
return number;
END

CREATE FUNCTION x_cast_to_int(number bigint) RETURNS int
BEGIN
return number;
END

CREATE FUNCTION x_cast_to_bigint(number bigint) RETURNS bigint
BEGIN
return number;
END


Now we already have our cast function, we should alter our query.
select   x_cast_to_tinyint(d.tiny_int*1) as tiny,
x_cast_to_smallint(d.small_int*1) as small,
x_cast_to_mediumint(d.medium_int*1) as `medium`,
x_cast_to_int(d._int*1) as regular,
x_cast_to_bigint(d.big_int*1) as big
from datatype_test d;


Let's compare the two queries with our Java snippet:
import java.sql.*;

public class datatype_test {
public Connection cn;
public PreparedStatement st;
public ResultSet rs;

public static void main(String[] a) throws Exception {
new datatype_test();
}

public datatype_test() throws Exception {
connect();

showcase1();
System.out.println();
showcase2();
}

private void connect() throws Exception {
Class.forName("com.mysql.jdbc.Driver");

String url = "jdbc:mysql://localhost/test";
cn=DriverManager.getConnection(url,"user","password");
}

private void showcase1() throws Exception {
st = cn.prepareStatement(
"select (d.tiny_int*1) as tiny, " +
" (d.small_int*1) as small, " +
" (d.medium_int*1) as `medium`, " +
" (d._int*1) as regular, " +
" (d.big_int*1) as big " +
"from datatype_test d;");

if (st.execute()) {
rs = st.getResultSet();
rs.next();

ResultSetMetaData rsmt = rs.getMetaData();
int cols = rsmt.getColumnCount();

System.out.println("Without Cast");

for (int i=1;i<=cols;i++) {
System.out.println(rsmt.getColumnLabel(i) + " = " +
rsmt.getColumnTypeName(i));
}
}

rs.close();
st.close();
}

private void showcase2() throws Exception {
st = cn.prepareStatement(
"select x_cast_to_tinyint(d.tiny_int*1) as tiny, " +
" x_cast_to_smallint(d.small_int*1) as small, " +
" x_cast_to_mediumint(d.medium_int*1) as `medium`, " +
" x_cast_to_int(d._int*1) as regular, " +
" x_cast_to_bigint(d.big_int*1) as big " +
"from datatype_test d;");

if (st.execute()) {
rs = st.getResultSet();
rs.next();

ResultSetMetaData rsmt = rs.getMetaData();
int cols = rsmt.getColumnCount();

System.out.println("With Cast");

for (int i=1;i<=cols;i++) {
System.out.println(rsmt.getColumnLabel(i) + " = " +
rsmt.getColumnTypeName(i));
}
}

rs.close();
st.close();
}
}


The result is:
Without Cast
tiny = BIGINT
small = BIGINT
medium = BIGINT
regular = BIGINT
big = BIGINT

With Cast
tiny = TINYINT
small = SMALLINT
medium = MEDIUMINT
regular = INTEGER
big = BIGINT

Labels:

Wednesday, July 16, 2008

Java ByteCode Manipulation

WARNING - Contents of this file are for educational purposes only. It is strongly suggested that you do not use this knowledge for illegal purposes!


There are two ways to modify the compiled java code (assume you don't have the source or have loss it):

  • Decompile all dependent file, make any modification to .java files created, then recompile.
    Pros:
    • Easy to manage your modification.

    • You don't have to decompile them next time you want to modify again.

    Cons:
    • Hard/Impossible to do that on obfuscated file.


  • Make any modification directly to .class file.
    Pros:
    • It's so easy to do on obfuscated file.


    Cons:
    • You have to learn about bytecode.

    • It will be hard at beginning.



The method I will be discuss right now is option (b), handling .class file directly.
Now let's we begin with simple example.
public class bytecode1 {
public static void main(String[] a) {
System.out.println("Hello Worlf");
System.out.println("Hello Worlf");
System.out.println("Hello Worlf");
}
}

Save it with the name bytecode1.java, then compile it, you will got bytecode1.class. Now you may run it, by executing: java bytecode1

See the result? I've made typo mistake, it should display "Hello World", not "Hello Worlf".
It's too easy, isn't it? You can just use any hex editor to replace the "f" to "d". But how if I want only one "Hello World" line displayed? Can hex editor handling it? maybe yes, maybe no. I don't want to think about it while there are more elegant way to do it.

The tools I use are BCEL and CCK. Both of them are quite old version, but still usable. So download it, and run CCK. Select Menu File>Open, then click Choose File .... Open bytecode1.class file.
java bytecode

From menu above, select Code from main methods. The right side panel will display content of main method.
java bytecode

You see the pattern? System.out.println is consist of getstatic, ldc, and invokevirtual.
java bytecode

So what I'm going to do now is remove two System.out.println routines. This should be tricky, when you are trying to remove getstatic routine, it will say "cannot remove...still has targeter".

If you select "Line Numbers" from left panel, it will show you dependencies from source code to bytecode. Remove the coresponding line where you want to remove the code.

Assume I want to remove the last two System.out.println routines (The first won't removed), that is with offset 8 to 21, so in the "Line Numbers" section, I will remove source index 4 and 5 that link to the offset 8-21.
java bytecode

if you done that, go back to Code, and then delete offset 8-21.
java bytecode

Done. save it with File>Save Menu.

That's enough for today, I will cover another technique next time.

Labels:

Wednesday, June 25, 2008

Backup MySQL Database From Java Part 3

This is the last part of MySQL Database Backup from Java tutorial series.

In previous post, already discussed about how to get the backup streams from Process Object to String variable. What are we going to do now is, saving the variable to a file. You should consider about compressing the output file if your data is somewhat like enterprise one.

To compress the file, there is ZipOutputStream class to utilize it.

You need to call setMethod() function to define what will you do with the stream. One of the option available is ZipOutputStream.DEFLATED, meaning you will compress the stream, another is ZipOutputStream.STORED, meaning you just store the stream without compress.

Another function to call if you choose DEFLATED method is setLevel(), which is setting the compression level. The value range from 0 (Deflater.NO_COMPRESSION) to 9 (Deflater.BEST_COMPRESSION).

It will looks like:
byte[] data = getData().getBytes();
byte[] routine = getRoutine().getBytes();
File filedst = new File("example file.zip");

FileOutputStream dest = new FileOutputStream(filedst);
ZipOutputStream zip = new ZipOutputStream(
new BufferedOutputStream(dest));
zip.setMethod(ZipOutputStream.DEFLATED);
zip.setLevel(Deflater.BEST_COMPRESSION);

zip.putNextEntry(new ZipEntry("data.sql"));
zip.write(data);

zip.putNextEntry(new ZipEntry("routine.sql"));
zip.write(routine);

zip.close();
dest.close();
Explanation:
First, we collect all the data needed, see previous post
byte[] data = getData().getBytes();
byte[] routine = getRoutine().getBytes();
File filedst = new File("example file.zip");
Initiating the file stream and the zip stream
FileOutputStream dest = new FileOutputStream(filedst);
ZipOutputStream zip = new ZipOutputStream(
new BufferedOutputStream(dest));
zip.setMethod(ZipOutputStream.DEFLATED);
zip.setLevel(Deflater.BEST_COMPRESSION);
Write the file
zip.putNextEntry(new ZipEntry("data.sql"));
zip.write(data);

zip.putNextEntry(new ZipEntry("routine.sql"));
zip.write(routine);
Close the stream.
zip.close();
dest.close();

Labels: ,

Thursday, May 29, 2008

Backup MySQL Database From Java Part 2

After we know how to separate the backup process between data, stored routine, and trigger, next thing to do is implementing them in Java.

Consider the following code:
private int BUFFER = 10485760;

private String getData(String host, String port, String user,
String password, String db) throws Exception {
Process run = Runtime.getRuntime().exec(
"mysqldump --host=" + host + " --port=" + port +
" --user=" + user + " --password=" + password +
" --compact --complete-insert --extended-insert " +
"--skip-comments --skip-triggers " + db);
InputStream in = run.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));

StringBuffer temp = new StringBuffer();

int count;
char[] cbuf = new char[BUFFER];

while ((count = br.read(cbuf, 0, BUFFER)) != -1)
temp.append(cbuf, 0, count);

br.close();
in.close();

return temp.toString();
}

private String getRoutine(String host, String port, String user,
String password, String db) throws Exception {
Process run = Runtime.getRuntime().exec(
"mysqldump --host=" + host + " --port=" + port +
" --user=" + user + " --password=" + password +
" --compact --skip-comments --no-create-info " +
"--no-data --routines " + db);
InputStream in = run.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));

StringBuffer temp = new StringBuffer();

int count;
char[] cbuf = new char[BUFFER];

while ((count = br.read(cbuf, 0, BUFFER)) != -1)
temp.append(cbuf, 0, count);

br.close();
in.close();

return temp.toString();
}
Now we have two functions, one for dumping only data, the other dumping stored routines and trigger. Both of them will return String variable, that is your backup.

Please note the BUFFER variable, you may customized for your need. Just remember, the bigger value, consumes more heaps but decrease loops. The smaller value, consumes less heaps but increase loops.

The next step is how to store them.

Labels: ,

Backup MySQL Database From Java Part 1

Nothing new with this topic because it has been asked and answered so many times in forums and mailing-lists, but still it's a quite hot topic.

The backup method I'm using in this blog entry is using mysqldump utility that bundled with MySQL download.
Mysqldump has several useful argument that we can make to customize our backup files, such as dumping data, triggers, stored routines in separate files.

For example, backing-up data only should be,
mysqldump --host=myserver --port=3306 --user=william --password=secret --compact --skip-comments --complete-insert --extended-insert --skip-triggers mydata

and backing-up stored routine and triggers should be,
mysqldump --host=myserver --port=3306 --user=william --password=secret --compact --skip-comments --no-create-info --no-data --routines mydata

For complete argument list of mysql dump, click here.

The next step is how to implementing mysqldump in Java

Labels: ,

Monday, April 07, 2008

Create Your Own Simple, Fully Customized Captcha in Desktop Java


Captcha in webpages is designed to avoid bots, I used captcha in my desktop application to avoid accidental processing on high critical transaction as you can see at my screenshot above.

First I initialized array of alphanumeric, I don't use some of them like '1', 'i', '5', 's' to avoid misreading.


private String[] token = new String[]{"3", "r", "c", "t", "9",
"n", "x", "a", "j", "8",
"d", "p", "f", "y", "7",
"h", "k"};

This array will be shuffled everytime the class created using Collections.shuffle() method.

java.util.List l = Arrays.asList(token);
Collections.shuffle(l);

Then simply read the shuffled array into a String variable.

captcha = token[0] + token[1] + token[2] + token[3];

The next thing to do is paint the component. Step one is drawing the horizontal and vertical gridlines with random color.
Graphics2D g2d = (Graphics2D) g.create();
Random r = new Random();

for (int x = 10; x < getWidth(); x+=10) {
g2d.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g2d.drawLine(x, 0, x, getHeight());
}

for (int y = 10; y < getHeight(); y+=10) {
g2d.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g2d.drawLine(0, y, getWidth(), y);
}

Step two is drawing text shadow. This step is optional.
g2d.setColor(Color.BLACK);
fm = getFontMetrics(bigFont);
g2d.drawString(token[0], 7, fm.getHeight() + 2);
g2d.drawString(token[1], 7 + fm.getWidths()[0], fm.getHeight() + 2);
g2d.drawString(token[2], 7 + (fm.getWidths()[0]*2), fm.getHeight() + 2);
g2d.drawString(token[3], 7 + (fm.getWidths()[0]*3), fm.getHeight() + 2);

Step three is drawing the text itself, each letter is drawn using random color too.
g2d.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g2d.drawString(token[0], 5, fm.getHeight());
g2d.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g2d.drawString(token[1], 5 + fm.getWidths()[0], fm.getHeight());
g2d.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g2d.drawString(token[2], 5 + (fm.getWidths()[0]*2), fm.getHeight());
g2d.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g2d.drawString(token[3], 5 + (fm.getWidths()[0]*3), fm.getHeight());

After painting is done, the last thing should be done is create comparing method.
public boolean match(String input) {
return (input.equalsIgnoreCase(captcha));
}

From your application, just create a new instance of the class, waiting for user input then compare them.
wCaptcha c = new wCaptcha();
. . .
. . .
. . .
c.match(txtInput.getText());

The complete source is below.

import java.util.*;
import java.awt.*;

import javax.swing.*;

public class wCaptcha extends JPanel {
private String[] token = new String[]{"3", "r", "c", "t", "9",
"n", "x", "a", "j", "8",
"d", "p", "f", "y", "7",
"h", "k"};
private String captcha = new String();

private Font bigFont;
private FontMetrics fm;

public wCaptcha() {
super();

initData();
initUI();
}

private void initData() {
java.util.List l = Arrays.asList(token);
Collections.shuffle(l);

captcha = token[0] + token[1] + token[2] + token[3];
}

private void initUI() {
setDoubleBuffered(true);

bigFont = new Font("Monospaced",Font.BOLD,getSize2D() + 20);
fm = getFontMetrics(bigFont);

setBorder(null);
setPreferredSize(new Dimension((fm.getWidths()[0]*4) + 27,
fm.getHeight() + fm.getMaxDescent() + 2));
setMaximumSize(new Dimension((fm.getWidths()[0]*4) + 27,
fm.getHeight() + fm.getMaxDescent() + 2));
setMinimumSize(new Dimension((fm.getWidths()[0]*4) + 27,
fm.getHeight() + fm.getMaxDescent() + 2));
setBackground(Color.WHITE);
}

public void paintComponent(Graphics g) {
super.paintComponent(g);

Random r = new Random();

Graphics2D g2d = (Graphics2D) g.create();
g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
RenderingHints.VALUE_ANTIALIAS_ON);
g2d.setFont(bigFont);
g2d.translate(0, 0);

for (int x = 10; x < getWidth(); x+=10) {
g2d.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g2d.drawLine(x, 0, x, getHeight());
}

for (int y = 10; y < getHeight(); y+=10) {
g2d.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g2d.drawLine(0, y, getWidth(), y);
}

g2d.setColor(Color.BLACK);
g2d.drawString(token[0], 7, fm.getHeight() + 2);
g2d.drawString(token[1], 7 + fm.getWidths()[0], fm.getHeight() + 2);
g2d.drawString(token[2], 7 + (fm.getWidths()[0]*2), fm.getHeight() + 2);
g2d.drawString(token[3], 7 + (fm.getWidths()[0]*3), fm.getHeight() + 2);

g2d.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g2d.drawString(token[0], 5, fm.getHeight());
g2d.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g2d.drawString(token[1], 5 + fm.getWidths()[0], fm.getHeight());
g2d.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g2d.drawString(token[2], 5 + (fm.getWidths()[0]*2), fm.getHeight());
g2d.setColor(new Color(r.nextInt(255), r.nextInt(255), r.nextInt(255)));
g2d.drawString(token[3], 5 + (fm.getWidths()[0]*3), fm.getHeight());
}

public boolean match(String input) {
return (input.equalsIgnoreCase(captcha));
}
}

Labels:

Monday, January 21, 2008

(Easily) Running Java Application

Here is the situation:
My Java desktop application run accross my company LAN, thus I put it in the server, every workstation can access to it, and I can easily update my application just by uploading to one machine. The workstations are consist of mixture of Windows 98, 2000, XP and Linux.

The problem is:
  • When making shortcut pointing to Java application reside in the server. I need only one shortcut reside on server (It has to worked on Windows and Linux).
  • Using java utility will displaying console window. Some people suggested using .BAT or .CMD, but it's useless.
  • Using javaw utility will solved above problem, but it's only available on Windows.
  • When I created shortcut, Windows always add C:\WINDOWS\SYSTEM32 (for 98, XP) and C:\WINNT\SYSTEM32 (for 2000), in front of the command line. The path is unavailable and the shortcut may not worked on Linux machine. And I don't think shortcut from Linux will be worked on Windows (I haven't tested yet).
  • Making .JAR from my application? Great, but I have some argument and classpath to pass with the application.

Then I came out to Runtime.exec() solution. So I create this Launcher class

import java.io.*;
import javax.swing.*;

public class Launcher {
private BufferedReader in;
private String cmdLine = null;
private Runtime rt;
private Process p;

public Launcher() {
try {
rt = Runtime.getRuntime();
in = new BufferedReader(new FileReader("launch.app"));

do {
cmdLine = in.readLine();
if (cmdLine!=null & !("".equals(cmdLine))) {
p = rt.exec(cmdLine);

InputStream is = p.getInputStream();
InputStreamReader inr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(inr);

StringBuffer temp = new StringBuffer();
String b;

do {
b = br.readLine();

if (b!=null)
temp.append(b);
} while (b!=null);

if(temp.toString().trim().length()>0)
JOptionPane.showMessageDialog(null, temp.toString(),
"Error Occured",
JOptionPane.ERROR_MESSAGE);
}
} while (cmdLine!=null);

in.close();
} catch (Exception e) {
JOptionPane.showMessageDialog(null, e.getMessage(),
"Error Occured",
JOptionPane.ERROR_MESSAGE);
}
}

public static void main(String[] arg) {
new Launcher();
}
}
This class will need a text file called launch.app, contain command line to run, for example:

java -Xms384m -Xmx512m -Djava.library.path=jug-native -cp jar/mysql-connector-java-5.0.3-bin.jar; bin.Main

Next step to do is making .JAR file for our Launcher class. First Prepare a text file called mymanifest.txt in same folder with Launcher.class contain:

Main-Class: Launcher

and then run this command to create .JAR file:

jar -cvfm Launcher.jar mymanifest.txt Launcher.class
Copy generated Launcher.jar and launch.app to the directory where Java application is resided.
You may try double click Launcher.jar file or create shortcut from it.

Labels:

Friday, January 18, 2008

NOD32 LAN Update Server

Yes, I know there are several ways to create your own NOD32 Update Server posted by people in their blogs. There are official Business Edition of NOD32 and unofficial NOD32 Update Generator. I just want to share another way that I think more flexible and automated. I don't know if it's posted or not, cause I just made my own experiment about it and didn't google for it. Here it is.

I'm using Ubuntu 7.10, but you may use another OS, just remember to equip it with:
  • Webserver (I'm using Apache)
  • wget
  • Scheduling app/daemon (I'm using cron)
Prepare a location in your Webserver for storing downloaded update files. In my Ubuntu, I just create a new folder named nod32_update in /var/www.

Using cron, I scheduled wget every Monday and Thursday like this:
* * * * 1,4 wget -m -nH -nd -A nup,ver --directory-prefix=/var/www/nod32_update [your nod32 update server]

Replace [your nod32 update server] with your current remote update server. Don't forget to add parameter --http-user and --http-password if your update server need authentication. You may run it for the first time.

Please Spare Your Time To Visit Our Sponsored Ads
Your Ads Here. Post a comment to make a deal.


Last, add your newly created server to NOD32 server list, it should looks like this
http://[your server host]/nod32_update/

Voila, every computer in your LAN can now update their virus definition.

Labels: ,