/******************************************************************************* Jimm - Mobile Messaging - J2ME ICQ clone Copyright (C) 2003-05 Jimm Project This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ******************************************************************************** File: src/jimm/comm/Util.java Version: ###VERSION### Date: ###DATE### Author(s): Manuel Linsmayer, Andreas Rossbacher, Sergey Chernov, Andrey B. Ivlev Artyomov Denis, Igor Palkin, Vladimir Kryukov *******************************************************************************/ package jimm.comm; import java.util.*; import javax.microedition.lcdui.*; import jimm.*; import jimm.util.JLocale; public class Util { // Password encryption key private static final byte[] PASSENC_KEY = {(byte)0xF3, (byte)0x26, (byte)0x81, (byte)0xC4, (byte)0x39, (byte)0x86, (byte)0xDB, (byte)0x92, (byte)0x71, (byte)0xA3, (byte)0xB9, (byte)0xE6, (byte)0x53, (byte)0x7A, (byte)0x95, (byte)0x7C}; // Extracts the byte from the buffer (buf) at position off public static int getByte(byte[] buf, int off) { return ((int) buf[off]) & 0x000000FF; } // Puts the specified byte (val) into the buffer (buf) at position off public static void putByte(byte[] buf, int off, int val) { buf[off] = (byte) (val & 0x000000FF); } // Extracts the word from the buffer (buf) at position off using the specified byte ordering (bigEndian) /** @deprecated */ public static int getWordLE(byte[] buf, int off) { int val = (((int) buf[off])) & 0x000000FF; return val | (((int) buf[++off]) << 8) & 0x0000FF00; } public static int getWordBE(byte[] buf, int off) { int val = (((int) buf[off]) << 8) & 0x0000FF00; return val | (((int) buf[++off])) & 0x000000FF; } /** @deprecated */ public static void putWordLE(byte[] buf, int off, int val) { buf[off] = (byte) ((val) & 0x000000FF); buf[++off] = (byte) ((val >> 8) & 0x000000FF); } // Puts the specified word (val) into the buffer (buf) at position off using big endian byte ordering public static void putWordBE(byte[] buf, int off, int val) { buf[off] = (byte) ((val >> 8) & 0x000000FF); buf[++off] = (byte) ((val) & 0x000000FF); } public static long getDWordLE(byte[] buf, int off) { long val; // Little endian val = (((long) buf[off])) & 0x000000FF; val |= (((long) buf[++off]) << 8) & 0x0000FF00; val |= (((long) buf[++off]) << 16) & 0x00FF0000; val |= (((long) buf[++off]) << 24) & 0xFF000000; return val; } // Extracts the double from the buffer (buf) at position off using big endian byte ordering public static long getDWordBE(byte[] buf, int off) { long val; val = (((long) buf[off]) << 24) & 0xFF000000; val |= (((long) buf[++off]) << 16) & 0x00FF0000; val |= (((long) buf[++off]) << 8) & 0x0000FF00; val |= (((long) buf[++off])) & 0x000000FF; return val; } // Puts the specified double (val) into the buffer (buf) at position off using the specified byte ordering (bigEndian) public static void putDWordLE(byte[] buf, int off, long val) { // Little endian buf[off] = (byte) ((val) & 0x00000000000000FF); buf[++off] = (byte) ((val >> 8) & 0x00000000000000FF); buf[++off] = (byte) ((val >> 16) & 0x00000000000000FF); buf[++off] = (byte) ((val >> 24) & 0x00000000000000FF); } // Puts the specified double (val) into the buffer (buf) at position off using big endian byte ordering public static void putDWordBE(byte[] buf, int off, long val) { buf[off] = (byte) ((val >> 24) & 0x00000000000000FF); buf[++off] = (byte) ((val >> 16) & 0x00000000000000FF); buf[++off] = (byte) ((val >> 8) & 0x00000000000000FF); buf[++off] = (byte) ((val) & 0x00000000000000FF); } // DeScramble password public static byte[] decipherPassword(byte[] buf) { byte[] ret = new byte[buf.length]; for (int i = 0; i < buf.length; ++i) { ret[i] = (byte) (buf[i] ^ PASSENC_KEY[i % PASSENC_KEY.length]); } return ret; } // If the numer has only one digit add a 0 public static String makeTwo(int number) { if (number < 10) { return "0" + String.valueOf(number); } return String.valueOf(number); } private static Random rand = new Random(System.currentTimeMillis()); public static int nextRandInt() { return Math.abs(Math.max(Integer.MIN_VALUE + 1, rand.nextInt())); } // #sijapp cond.if modules_TRAFFIC is "true" # // Returns String value of cost value public static String intToDecimal(int value) { try { if (value != 0) { String costString = Integer.toString(value / 1000) + "."; String afterDot = Integer.toString(value % 1000); while (afterDot.length() != 3) { afterDot = "0" + afterDot; } while ((afterDot.endsWith("0")) && (afterDot.length() > 2)) { afterDot = afterDot.substring(0, afterDot.length() - 1); } return costString + afterDot; } } catch (Exception ignored) { } return "0.0"; } // Extracts the number value form String public static int decimalToInt(String string) { try { int i = string.indexOf('.'); if (i < 0) { return Integer.parseInt(string) * 1000; } else { int value = Integer.parseInt(string.substring(0, i)) * 1000; string = string.substring(i + 1, Math.min(string.length(), i + 1 + 3)); while (string.length() < 3) { string = string + "0"; } return value + Integer.parseInt(string); } } catch (Exception ignored) { return 0; } } // #sijapp cond.end# /*///////////////////////////////////////////////////////////////////////// // // // METHODS FOR DATE AND TIME PROCESSING // // // /////////////////////////////////////////////////////////////////////////*/ private final static int TIME_SECOND = 0; private final static int TIME_MINUTE = 1; private final static int TIME_HOUR = 2; private final static int TIME_DAY = 3; private final static int TIME_MON = 4; private final static int TIME_YEAR = 5; final private static byte[] dayCounts = { 31,28,31,30,31,30,31,31,30,31,30,31 }; private final static int[] calFields = { Calendar.YEAR, Calendar.MONTH, Calendar.DAY_OF_MONTH, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND}; private final static int[] ofsFieldsA = { 0, 4, 6, 9, 12, 15 } ; //XEP-0091 - DEPRECATED private final static int[] ofsFieldsB = { 0, 5, 8, 11, 14, 17 } ;//XEP-0203 private final static String[] months = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"}; public static long createGmtDate(String sdate) { Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); try { sdate = sdate.trim(); int[] ofs = sdate.endsWith("Z") ? ofsFieldsB : ofsFieldsA; long result; if (Character.isDigit(sdate.charAt(0))) { int fieldLength = 4; // yearlen for (int i = 0; i < calFields.length; ++i) { int begIndex = ofs[i]; int field = strToIntDef(sdate.substring(begIndex, begIndex + fieldLength), 0); if (1 == i) { field += Calendar.JANUARY - 1; } fieldLength = 2; c.set(calFields[i], field); } result = Math.max(0, c.getTime().getTime() / 1000); } else { String[] rfcDate = Util.explode(sdate, ' '); c.set(Calendar.YEAR, strToIntDef(rfcDate[3], 0)); for (int i = 0; i < months.length; ++i) { if (months[i].equals(rfcDate[2])) { c.set(Calendar.MONTH, i); break; } } c.set(Calendar.DAY_OF_MONTH, strToIntDef(rfcDate[1], 0)); c.set(Calendar.HOUR_OF_DAY, strToIntDef(rfcDate[4].substring(0, 2), 0)); c.set(Calendar.MINUTE, strToIntDef(rfcDate[4].substring(3, 5), 0)); c.set(Calendar.SECOND, strToIntDef(rfcDate[4].substring(6), 0)); long delta = strToIntDef(rfcDate[5].substring(1, 3), 0) * 60 * 60 + strToIntDef(rfcDate[5].substring(3, 5), 0) * 60; if ('+' == rfcDate[5].charAt(0)) { delta = -delta; } result = Math.max(0, c.getTime().getTime() / 1000 + delta); } return result; } catch (Exception ignored) { } return 0; } public static long createLocalDate(String date) { try { date = date.replace('.', ' ').replace(':', ' '); String[] values = Util.explode(date, ' '); Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); c.set(Calendar.YEAR, Util.strToIntDef(values[2], 0)); c.set(Calendar.MONTH, Util.strToIntDef(values[1], 0) - 1); c.set(Calendar.DAY_OF_MONTH, Util.strToIntDef(values[0], 0)); c.set(Calendar.HOUR_OF_DAY, Util.strToIntDef(values[3], 0)); c.set(Calendar.MINUTE, Util.strToIntDef(values[4], 0)); c.set(Calendar.SECOND, 0); return localTimeToGmtTime(c.getTime().getTime() / 1000); } catch (Exception ignored) { return 0; } } /* Creates current date (local) */ public static long createCurrentLocalTime() { return gmtTimeToLocalTime(Jimm.getCurrentGmtTime()); } public static String getLocalDayOfWeek(long gmtTime) { // local Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT")); cal.setTime(new Date(Util.gmtTimeToLocalTime(gmtTime) * 1000)); String[] days = {"", "sunday", "monday", "tuesday", "wednesday", "thursday", "friday", "saturday"}; return JLocale.getString(days[cal.get(Calendar.DAY_OF_WEEK)]); } public static String getLocalDateString(long gmtDate, boolean onlyTime) { if (0 == gmtDate) return "***error***"; int[] localDate = createDate(gmtTimeToLocalTime(gmtDate)); StringBuilder sb = new StringBuilder(16); if (!onlyTime) { sb.append(Util.makeTwo(localDate[TIME_DAY])) .append('.') .append(Util.makeTwo(localDate[TIME_MON])) .append('.') .append(localDate[TIME_YEAR]) .append(' '); } sb.append(Util.makeTwo(localDate[TIME_HOUR])) .append(':') .append(Util.makeTwo(localDate[TIME_MINUTE])); return sb.toString(); } public static String getDate(String format, long anyDate) { if (0 == anyDate) return "error"; int[] localDate = createDate(anyDate); format = Util.replace(format, "%H", Util.makeTwo(localDate[TIME_HOUR])); format = Util.replace(format, "%M", Util.makeTwo(localDate[TIME_MINUTE])); format = Util.replace(format, "%S", Util.makeTwo(localDate[TIME_SECOND])); format = Util.replace(format, "%Y", "" + localDate[TIME_YEAR]); format = Util.replace(format, "%y", Util.makeTwo(localDate[TIME_YEAR] % 100)); format = Util.replace(format, "%m", Util.makeTwo(localDate[TIME_MON])); format = Util.replace(format, "%d", Util.makeTwo(localDate[TIME_DAY])); return format; } /* Show date string */ public static String getUtcDateString(long gmtTime) { return getDate("%Y-%m-%dT%H:%M:%SZ", gmtTime); } /* Generates seconds count from 1st Jan 1970 till mentioned date */ public static long createGmtTime(int year, int mon, int day, int hour, int min, int sec) { try { Calendar c = Calendar.getInstance(TimeZone.getTimeZone("GMT")); c.set(Calendar.YEAR, year); c.set(Calendar.MONTH, mon - 1); c.set(Calendar.DAY_OF_MONTH, day); c.set(Calendar.HOUR_OF_DAY, hour); c.set(Calendar.MINUTE, min); c.set(Calendar.SECOND, sec); return c.getTime().getTime() / 1000; } catch (Exception ignored) { return 0; } } // Creates array of calendar values form value of seconds since 1st jan 1970 (GMT) private static int[] createDate(long value) { int total_days, last_days, i; int sec, min, hour, day, mon, year; sec = (int) (value % 60); min = (int) ((value / 60) % 60); // min value -= 60 * min; hour = (int) ((value / 3600) % 24); // hour value -= 3600 * hour; total_days = (int) (value / (3600 * 24)); year = 1970; for (;;) { last_days = total_days - ((year % 4 == 0) && (year != 2000) ? 366 : 365); if (last_days <= 0) break; total_days = last_days; year++; } // year int febrDays = ((year % 4 == 0) && (year != 2000)) ? 29 : 28; mon = 1; for (i = 0; i < 12; ++i) { last_days = total_days - ((i == 1) ? febrDays : dayCounts[i]); if (last_days <= 0) break; mon++; total_days = last_days; } // mon day = total_days; // day return new int[] { sec, min, hour, day, mon, year }; } public static long gmtTimeToLocalTime(long gmtTime) { return gmtTime + Options.getInt(Options.OPTION_GMT_OFFSET) * 3600L; } public static long localTimeToGmtTime(long localTime) { return localTime - Options.getInt(Options.OPTION_GMT_OFFSET) * 3600L; } public static String longitudeToString(long seconds) { int days = (int)(seconds / 86400); seconds %= 86400; int hours = (int)(seconds / 3600); seconds %= 3600; int minutes = (int)(seconds / 60); StringBuilder buf = new StringBuilder(); if (days != 0) { buf.append(days).append(' ').append( JLocale.getString("days") ).append(' '); } if (hours != 0) { buf.append(hours).append(' ').append( JLocale.getString("hours") ).append(' '); } if (minutes != 0) { buf.append(minutes).append(' ').append( JLocale.getString("minutes") ); } return buf.toString(); } ////////////////////////////////////////////////////////////////////////////////// public static int uniqueValue() { int time = (int)(Jimm.getCurrentGmtTime() & 0x7FFF); return (time << 16) | (rand.nextInt() & 0xFFFF); } ////////////////////////////////////////////////////////////////////////////////// private static final int URL_CHAR_PROTOCOL = 0; private static final int URL_CHAR_PREV = 1; private static final int URL_CHAR_OTHER = 2; private static final int URL_CHAR_DIGIT = 3; private static final int URL_CHAR_NONE = 4; private static boolean isURLChar(char chr, int mode) { if (mode == URL_CHAR_PROTOCOL) { return ((chr >= 'A') && (chr <= 'Z')) || ((chr >= 'a') && (chr <= 'z')); } if (mode == URL_CHAR_PREV) { return ((chr >= 'A') && (chr <= 'Z')) || ((chr >= 'a') && (chr <= 'z')) || ((chr >= '0') && (chr <= '9')) || ('@' == chr) || ('-' == chr) || ('_' == chr)|| ('%' == chr); } if (URL_CHAR_DIGIT == mode) return Character.isDigit(chr); if (URL_CHAR_NONE == mode) return (' ' == chr) || ('\n' == chr); return !((chr <= ' ') || (chr == '\n')); } private static void putUrl(Vector<String> urls, String url) { final String skip = "?!;:,."; final String openDelemiters = "{[(«"; final String delemiters = "}])»"; int cutIndex = url.length() - 1; for (; cutIndex >= 0; --cutIndex) { char lastChar = url.charAt(cutIndex); if (-1 != skip.indexOf(lastChar)) { continue; } int delemiterIndex = delemiters.indexOf(lastChar); if (-1 != delemiterIndex) { if (-1 == url.indexOf(openDelemiters.charAt(delemiterIndex))) { continue; } } break; } if (cutIndex <= 0) { return; } else if (cutIndex != url.length() - 1) { url = url.substring(0, cutIndex + 1); } if (-1 == url.indexOf(':')) { boolean isPhone = ('+' == url.charAt(0)); boolean hasDot = false; boolean nonDigit = false; for (int i = isPhone ? 1 : 0; i < url.length(); ++i) { char ch = url.charAt(i); if ('.' == ch) { hasDot = true; } else if (!Character.isDigit(ch)) { nonDigit = true; break; } } if (isPhone) { if (!nonDigit && !hasDot && (7 <= url.length())) { url = "tel:" + url; } else { return; } } else { if (nonDigit) { if (-1 == url.indexOf('/')) { if (-1 == url.indexOf('@')) return; // jid or email } else { url = "http:\57\57" + url; } } else { return; } } } int protoEnd = url.indexOf(':'); if (-1 != protoEnd) { if (url.length() <= protoEnd + 5) { return; } for (int i = 0; i < protoEnd; ++i) { if (!isURLChar(url.charAt(i), URL_CHAR_PROTOCOL)) { return; } } } if (!urls.contains(url)) { urls.addElement(url); } } private static void parseForUrl(Vector<String> result, String msg, char ch, int before, int after, int limit) { if (limit <= result.size()) { return; } int size = msg.length(); int findIndex = 0; int beginIdx; int endIdx; for (;;) { if (findIndex >= size) break; int ptIndex = msg.indexOf(ch, findIndex); if (ptIndex == -1) break; for (endIdx = ptIndex + 1; endIdx < size; ++endIdx) { if (!isURLChar(msg.charAt(endIdx), after)) { break; } } findIndex = endIdx; if (endIdx - ptIndex < 2) continue; if (URL_CHAR_NONE != before) { for (beginIdx = ptIndex - 1; beginIdx >= 0; --beginIdx) { if (!isURLChar(msg.charAt(beginIdx), before)) { break; } } if ((beginIdx == -1) || !isURLChar(msg.charAt(beginIdx), before)) { beginIdx++; } if (ptIndex == beginIdx) continue; } else { beginIdx = ptIndex; if ((0 < beginIdx) && !isURLChar(msg.charAt(beginIdx - 1), before)) { continue; } } if (endIdx - beginIdx < 5) continue; putUrl(result, msg.substring(beginIdx, endIdx)); if (limit < result.size()) { return; } } } public static String getUrlWithoutProtocol(String url) { int index = url.indexOf(':'); if (-1 != index) { url = url.substring(index + 1); if (url.startsWith("\57\57")) { url = url.substring(2); } if (url.endsWith("/")) { url = url.substring(0, url.length() - 1); } } return url; } public static String notUrls(String str) { str = StringUtils.notNull(str); return (-1 != str.indexOf("http://")) ? "" : str; } public static boolean hasURL(String msg) { if (null == msg) return false; Vector<String> result = new Vector<String>(); parseForUrl(result, msg, '.', URL_CHAR_PREV, URL_CHAR_OTHER, 1); parseForUrl(result, msg, ':', URL_CHAR_PROTOCOL, URL_CHAR_OTHER, 1); parseForUrl(result, msg, '+', URL_CHAR_NONE, URL_CHAR_DIGIT, 1); parseForUrl(result, msg, '@', URL_CHAR_PREV, URL_CHAR_OTHER, 1); return !result.isEmpty(); } public static Vector parseMessageForURL(String msg) { if (null == msg) return null; // we are parsing 100 links only final int MAX_LINK_COUNT = 100; Vector<String> result = new Vector<String>(); parseForUrl(result, msg, '.', URL_CHAR_PREV, URL_CHAR_OTHER, MAX_LINK_COUNT); parseForUrl(result, msg, ':', URL_CHAR_PROTOCOL, URL_CHAR_OTHER, MAX_LINK_COUNT); parseForUrl(result, msg, '+', URL_CHAR_NONE, URL_CHAR_DIGIT, MAX_LINK_COUNT); parseForUrl(result, msg, '@', URL_CHAR_PREV, URL_CHAR_OTHER, MAX_LINK_COUNT); return result.isEmpty() ? null : result; } public static int strToIntDef(String str, int defValue) { if (null == str) { return defValue; } try { while ((1 < str.length()) && ('0' == str.charAt(0))) { str = str.substring(1); } return Integer.parseInt(str); } catch (Exception ignored) { } return defValue; } public static String replace(String text, String from, String to) { int fromSize = from.length(); int start = 0; int pos = 0; StringBuilder sb = new StringBuilder(); for (;;) { pos = text.indexOf(from, pos); if (-1 == pos) break; sb.append(text.substring(start, pos)).append(to); pos += fromSize; start = pos; } if (start < text.length()) { sb.append(text.substring(start)); } return sb.toString(); } public static String replace(String text, String[] from, String[] to, String keys) { // keys - is first chars of from StringBuilder result = new StringBuilder(); int pos = 0; while (pos < text.length()) { char ch = text.charAt(pos); int index = keys.indexOf(ch); while (-1 != index) { if (text.startsWith(from[index], pos)) { pos += from[index].length(); result.append(to[index]); break; } index = keys.indexOf(text.charAt(pos), index + 1); } if (-1 == index) { result.append(ch); pos++; } } return result.toString(); } /* Divide text to array of parts using serparator charaster */ static public String[] explode(String text, char separator) { if (StringUtils.isEmpty(text)) { return new String[0]; } Vector<String> tmp = new Vector<String>(); int start = 0; int end = text.indexOf(separator, start); while (end >= start) { tmp.addElement(text.substring(start, end)); start = end + 1; end = text.indexOf(separator, start); } tmp.addElement(text.substring(start)); String[] result = new String[tmp.size()]; tmp.copyInto(result); return result; } static public String implode(String[] text, String separator) { StringBuilder result = new StringBuilder(); for (String item : text) { if (null != item) { if (0 != result.length()) { result.append(separator); } result.append(item); } } return result.toString(); } private static final String base64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="; private static int base64GetNextChar(String str, int index) { if (-1 == index) return -2; char ch = str.charAt(index); if ('=' == ch) { return -1; } return base64.indexOf(ch); } private static int base64GetNextIndex(String str, int index) { for (; index < str.length(); ++index) { char ch = str.charAt(index); if ('=' == ch) { return index; } int code = base64.indexOf(ch); if (-1 != code) { return index; } } return -1; } public static byte[] base64decode(String str) { if (null == str) str = ""; OutStream out = new OutStream(); for (int strIndex = 0; strIndex < str.length(); ++strIndex) { strIndex = base64GetNextIndex(str, strIndex); if (-1 == strIndex) break; int ch1 = base64GetNextChar(str, strIndex); if (-1 == ch1) break; strIndex = base64GetNextIndex(str, strIndex + 1); if (-1 == strIndex) break; int ch2 = base64GetNextChar(str, strIndex); if (-1 == ch2) break; out.writeByte((byte)(0xFF & ((ch1 << 2) | (ch2 >>> 4)))); strIndex = base64GetNextIndex(str, strIndex + 1); if (-1 == strIndex) break; int ch3 = base64GetNextChar(str, strIndex); if (-1 == ch3) break; out.writeByte((byte)(0xFF & ((ch2 << 4) | (ch3 >>> 2)))); strIndex = base64GetNextIndex(str, strIndex + 1); if (-1 == strIndex) break; int ch4 = base64GetNextChar(str, strIndex); if (-1 == ch4) break; out.writeByte((byte)(0xFF & ((ch3 << 6) | (ch4)))); } return out.toByteArray(); } public static String base64encode( final byte[] data ) { char[] out = new char[((data.length + 2) / 3) * 4]; for (int i = 0, index = 0; i < data.length; i += 3, index += 4) { boolean quad = false; boolean trip = false; int val = (0xFF & data[i]); val <<= 8; if ((i + 1) < data.length) { val |= (0xFF & data[i + 1]); trip = true; } val <<= 8; if ((i + 2) < data.length) { val |= (0xFF & data[i + 2]); quad = true; } out[index+3] = base64.charAt(quad ? (val & 0x3F) : 64); val >>= 6; out[index+2] = base64.charAt(trip ? (val & 0x3F) : 64); val >>= 6; out[index+1] = base64.charAt(val & 0x3F); val >>= 6; out[index+0] = base64.charAt(val & 0x3F); } return new String(out); } private static final String[] escapedChars = {""", "'", ">", "<", "&"}; private static final String[] unescapedChars = {"\"", "'", ">", "<", "&"}; public static String xmlEscape(String text) { text = StringUtils.notNull(text); return Util.replace(text, unescapedChars, escapedChars, "\"'><&"); } public static String xmlUnescape(String text) { if (-1 == text.indexOf('&')) { return text; } return Util.replace(text, escapedChars, unescapedChars, "&&&&&"); } public static Image createThumbnail(Image image, int width, int height) { int sourceWidth = image.getWidth(); int sourceHeight = image.getHeight(); if ((width > sourceWidth) && (height > sourceHeight)) { return image; } int thumbWidth = width; int thumbHeight = thumbWidth * sourceHeight / sourceWidth; if (thumbHeight > height) { thumbHeight = height; thumbWidth = thumbHeight * sourceWidth / sourceHeight; } // #sijapp cond.if modules_ANDROID is "true"# Image scaled = image.scale(thumbWidth, thumbHeight); if (null != scaled) return scaled; // #sijapp cond.end# Image thumb = Image.createImage(thumbWidth, thumbHeight); Graphics g = thumb.getGraphics(); for (int y = 0; y < thumbHeight; ++y) { for (int x = 0; x < thumbWidth; ++x) { g.setClip(x, y, 1, 1); int dx = x * sourceWidth / thumbWidth; int dy = y * sourceHeight / thumbHeight; g.drawImage(image, x - dx, y - dy, Graphics.LEFT | Graphics.TOP); } } return thumb; } ////////////////////////////////////////////////////////////////////////////////// private static int compareNodes(Sortable node1, Sortable node2) { int result = node1.getNodeWeight() - node2.getNodeWeight(); if (0 == result) { result = StringUtils.stringCompare(node1.getText(), node2.getText()); } return result; } public static void sort(Vector subnodes) { for (int i = 1; i < subnodes.size(); ++i) { Sortable currNode = (Sortable)subnodes.elementAt(i); int j = i - 1; for (; j >= 0; --j) { Sortable itemJ = (Sortable)subnodes.elementAt(j); if (compareNodes(itemJ, currNode) <= 0) { break; } subnodes.setElementAt(itemJ, j + 1); } if (j + 1 != i) { subnodes.setElementAt(currNode, j + 1); } } } ////////////////////////////////////////////////////////////////////////////////// private static void putCh(StringBuilder sb, int ch) { String s = Integer.toHexString(ch); sb.append("%"); if (1 == s.length()) sb.append('0'); sb.append(s); } public static String urlEscape(String param) { String urlOK = ""; StringBuilder sb = new StringBuilder(); for (int i = 0; i < param.length(); ++i) { char ch = param.charAt(i); char lowerCh = Character.toLowerCase(ch); if (Character.isDigit(ch) || (-1 != "qwertyuiopasdfghjklzxcvbnm@.-".indexOf(lowerCh))) { sb.append(ch); } else if (' ' == ch) { sb.append('+'); } else if ((0x7F & ch) == ch) { putCh(sb, ch); } else if ((0xFFF & ch) == ch) { putCh(sb, 0xD0 | (ch >> 6)); putCh(sb, 0x80 | (0x3F & ch)); } else { putCh(sb, 0xE8 | (ch >> 12)); putCh(sb, 0x80 | (0x3F & (ch >> 6))); putCh(sb, 0x80 | (0x3F & ch)); } } return sb.toString(); } ////////////////////////////////////////////////////////////////////////////////// public static int getIndex(Vector v, Object o) { synchronized (v) { int size = v.size(); for (int i = 0; i < size; ++i) { if (v.elementAt(i) == o) { return i; } } } return -1; } public static void removeAll(Vector to, Vector all) { synchronized (to) { int current = 0; for (int index = 0; index < to.size(); ++index) { if (0 <= Util.getIndex(all, to.elementAt(index))) continue; if (current < index) { to.setElementAt(to.elementAt(index), current); current++; } } if (current < to.size()) to.setSize(current); } } public static void addAll(Vector to, Vector all) { synchronized (to) { for (int i = 0; i < all.size(); ++i) { to.addElement(all.elementAt(i)); } } } public static void addNew(Vector to, Vector all) { synchronized (to) { for (int i = 0; i < all.size(); ++i) { if (0 <= Util.getIndex(to, all.elementAt(i))) continue; to.addElement(all.elementAt(i)); } } } }