some code cleanup

This commit is contained in:
iNPUTmice 2014-08-31 16:28:21 +02:00
parent 8d456085e5
commit 1ac5be4855
75 changed files with 1483 additions and 1264 deletions

View file

@ -0,0 +1,21 @@
package eu.siacs.conversations;
import android.graphics.Bitmap;
public final class Config {
public static final String LOGTAG = "conversations";
public static final int PING_MAX_INTERVAL = 300;
public static final int PING_MIN_INTERVAL = 30;
public static final int PING_TIMEOUT = 10;
public static final int CONNECT_TIMEOUT = 90;
public static final int CARBON_GRACE_PERIOD = 60;
public static final int AVATAR_SIZE = 192;
public static final Bitmap.CompressFormat AVATAR_FORMAT = Bitmap.CompressFormat.WEBP;
private Config() {
}
}

View file

@ -17,6 +17,7 @@ import org.json.JSONObject;
import android.content.Context;
import android.util.Log;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.persistance.DatabaseBackend;
import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
@ -30,8 +31,6 @@ import net.java.otr4j.session.SessionID;
public class OtrEngine implements OtrEngineHost {
private static final String LOGTAG = "xmppService";
private Account account;
private OtrPolicy otrPolicy;
private KeyPair keyPair;
@ -77,8 +76,10 @@ public class OtrEngine implements OtrEngineHost {
KeyFactory keyFactory;
try {
keyFactory = KeyFactory.getInstance("DSA");
DSAPrivateKeySpec privateKeySpec = keyFactory.getKeySpec(privateKey, DSAPrivateKeySpec.class);
DSAPublicKeySpec publicKeySpec = keyFactory.getKeySpec(publicKey, DSAPublicKeySpec.class);
DSAPrivateKeySpec privateKeySpec = keyFactory.getKeySpec(
privateKey, DSAPrivateKeySpec.class);
DSAPublicKeySpec publicKeySpec = keyFactory.getKeySpec(publicKey,
DSAPublicKeySpec.class);
this.account.setKey("otr_x", privateKeySpec.getX().toString(16));
this.account.setKey("otr_g", privateKeySpec.getG().toString(16));
this.account.setKey("otr_p", privateKeySpec.getP().toString(16));
@ -134,7 +135,8 @@ public class OtrEngine implements OtrEngineHost {
this.saveKey();
DatabaseBackend.getInstance(context).updateAccount(account);
} catch (NoSuchAlgorithmException e) {
Log.d(LOGTAG,"error generating key pair "+e.getMessage());
Log.d(Config.LOGTAG,
"error generating key pair " + e.getMessage());
}
}
return this.keyPair;
@ -152,7 +154,8 @@ public class OtrEngine implements OtrEngineHost {
}
@Override
public void injectMessage(SessionID session, String body) throws OtrException {
public void injectMessage(SessionID session, String body)
throws OtrException {
MessagePacket packet = new MessagePacket();
packet.setFrom(account.getFullJid());
if (session.getUserID().isEmpty()) {

View file

@ -14,6 +14,7 @@ import org.openintents.openpgp.OpenPgpSignatureResult;
import org.openintents.openpgp.util.OpenPgpApi;
import org.openintents.openpgp.util.OpenPgpApi.IOpenPgpCallback;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
@ -38,7 +39,7 @@ public class PgpEngine {
public void decrypt(final Message message,
final UiCallback<Message> callback) {
Log.d("xmppService", "decrypting message " + message.getUuid());
Log.d(Config.LOGTAG, "decrypting message " + message.getUuid());
Intent params = new Intent();
params.setAction(OpenPgpApi.ACTION_DECRYPT_VERIFY);
params.putExtra(OpenPgpApi.EXTRA_ACCOUNT_NAME, message
@ -73,8 +74,9 @@ public class PgpEngine {
message);
return;
case OpenPgpApi.RESULT_CODE_ERROR:
OpenPgpError error = result.getParcelableExtra(OpenPgpApi.RESULT_ERROR);
Log.d("xmppService",error.getMessage());
OpenPgpError error = result
.getParcelableExtra(OpenPgpApi.RESULT_ERROR);
Log.d(Config.LOGTAG, error.getMessage());
callback.error(R.string.openpgp_error, message);
return;
default:
@ -109,7 +111,8 @@ public class PgpEngine {
message.setEncryption(Message.ENCRYPTION_DECRYPTED);
PgpEngine.this.mXmppConnectionService
.updateMessage(message);
PgpEngine.this.mXmppConnectionService.updateConversationUi();
PgpEngine.this.mXmppConnectionService
.updateConversationUi();
callback.success(message);
return;
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
@ -221,9 +224,9 @@ public class PgpEngine {
}
});
} catch (FileNotFoundException e) {
Log.d("xmppService", "file not found: " + e.getMessage());
Log.d(Config.LOGTAG, "file not found: " + e.getMessage());
} catch (IOException e) {
Log.d("xmppService", "io exception during file encrypt");
Log.d(Config.LOGTAG, "io exception during file encrypt");
}
}
}
@ -267,7 +270,7 @@ public class PgpEngine {
case OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED:
return 0;
case OpenPgpApi.RESULT_CODE_ERROR:
Log.d("xmppService",
Log.d(Config.LOGTAG,
"openpgp error: "
+ ((OpenPgpError) result
.getParcelableExtra(OpenPgpApi.RESULT_ERROR))

View file

@ -4,7 +4,6 @@ import android.content.ContentValues;
public abstract class AbstractEntity {
public static final String UUID = "uuid";
protected String uuid;

View file

@ -86,7 +86,8 @@ public class Account extends AbstractEntity {
}
public Account(String uuid, String username, String server,
String password, int options, String rosterVersion, String keys, String avatar) {
String password, int options, String rosterVersion, String keys,
String avatar) {
this.uuid = uuid;
this.username = username;
this.server = server;
@ -151,7 +152,10 @@ public class Account extends AbstractEntity {
public boolean errorStatus() {
int s = getStatus();
return (s == STATUS_REGISTRATION_FAILED || s == STATUS_REGISTRATION_CONFLICT || s == STATUS_REGISTRATION_NOT_SUPPORTED || s == STATUS_SERVER_NOT_FOUND || s == STATUS_UNAUTHORIZED);
return (s == STATUS_REGISTRATION_FAILED
|| s == STATUS_REGISTRATION_CONFLICT
|| s == STATUS_REGISTRATION_NOT_SUPPORTED
|| s == STATUS_SERVER_NOT_FOUND || s == STATUS_UNAUTHORIZED);
}
public boolean hasErrorStatus() {

View file

@ -25,7 +25,8 @@ public class Bookmark implements ListItem {
Bookmark bookmark = new Bookmark(account, element.getAttribute("jid"));
bookmark.setName(element.getAttribute("name"));
String autojoin = element.getAttribute("autojoin");
if (autojoin!=null && (autojoin.equals("true")||autojoin.equals("1"))) {
if (autojoin != null
&& (autojoin.equals("true") || autojoin.equals("1"))) {
bookmark.setAutojoin(true);
} else {
bookmark.setAutojoin(false);
@ -51,12 +52,14 @@ public class Bookmark implements ListItem {
@Override
public int compareTo(ListItem another) {
return this.getDisplayName().compareToIgnoreCase(another.getDisplayName());
return this.getDisplayName().compareToIgnoreCase(
another.getDisplayName());
}
@Override
public String getDisplayName() {
if (this.mJoinedConversation!=null && (this.mJoinedConversation.getMucOptions().getSubject() != null)) {
if (this.mJoinedConversation != null
&& (this.mJoinedConversation.getMucOptions().getSubject() != null)) {
return this.mJoinedConversation.getMucOptions().getSubject();
} else if (name != null) {
return name;
@ -81,8 +84,8 @@ public class Bookmark implements ListItem {
public boolean match(String needle) {
return needle == null
|| getJid().contains(needle.toLowerCase(Locale.US))
|| getDisplayName().toLowerCase(Locale.US)
.contains(needle.toLowerCase(Locale.US));
|| getDisplayName().toLowerCase(Locale.US).contains(
needle.toLowerCase(Locale.US));
}
public Account getAccount() {
@ -92,9 +95,11 @@ public class Bookmark implements ListItem {
@Override
public Bitmap getImage(int dpSize, Context context) {
if (this.mJoinedConversation == null) {
return UIHelper.getContactPicture(getDisplayName(), dpSize, context, false);
return UIHelper.getContactPicture(getDisplayName(), dpSize,
context, false);
} else {
return UIHelper.getContactPicture(this.mJoinedConversation, dpSize, context, false);
return UIHelper.getContactPicture(this.mJoinedConversation, dpSize,
context, false);
}
}

View file

@ -309,7 +309,8 @@ public class Contact implements ListItem {
@Override
public int compareTo(ListItem another) {
return this.getDisplayName().compareToIgnoreCase(another.getDisplayName());
return this.getDisplayName().compareToIgnoreCase(
another.getDisplayName());
}
public String getServer() {

View file

@ -88,7 +88,8 @@ public class Conversation extends AbstractEntity {
public List<Message> getMessages() {
if (messages == null) {
this.messages = new CopyOnWriteArrayList<Message>(); // prevent null pointer
this.messages = new CopyOnWriteArrayList<Message>(); // prevent null
// pointer
}
// populate with Conversation (this)

View file

@ -5,6 +5,8 @@ import android.graphics.Bitmap;
public interface ListItem extends Comparable<ListItem> {
public String getDisplayName();
public String getJid();
public Bitmap getImage(int dpSize, Context context);
}

View file

@ -38,7 +38,8 @@ public class Presences {
Iterator<Entry<String, Integer>> it = presences.entrySet().iterator();
while (it.hasNext()) {
Entry<String, Integer> entry = it.next();
if (entry.getValue()<status) status = entry.getValue();
if (entry.getValue() < status)
status = entry.getValue();
}
return status;
}

View file

@ -10,13 +10,12 @@ import eu.siacs.conversations.xmpp.stanzas.IqPacket;
public class IqGenerator extends AbstractGenerator {
public IqPacket discoResponse(IqPacket request) {
IqPacket packet = new IqPacket(IqPacket.TYPE_RESULT);
packet.setId(request.getId());
packet.setTo(request.getFrom());
Element query = packet.addChild("query","http://jabber.org/protocol/disco#info");
Element query = packet.addChild("query",
"http://jabber.org/protocol/disco#info");
query.setAttribute("node", request.query().getAttribute("node"));
Element identity = query.addChild("identity");
identity.setAttribute("category", "client");
@ -32,7 +31,8 @@ public class IqGenerator extends AbstractGenerator {
protected IqPacket publish(String node, Element item) {
IqPacket packet = new IqPacket(IqPacket.TYPE_SET);
Element pubsub = packet.addChild("pubsub", "http://jabber.org/protocol/pubsub");
Element pubsub = packet.addChild("pubsub",
"http://jabber.org/protocol/pubsub");
Element publish = pubsub.addChild("publish");
publish.setAttribute("node", node);
publish.addChild(item);
@ -41,7 +41,8 @@ public class IqGenerator extends AbstractGenerator {
protected IqPacket retrieve(String node, Element item) {
IqPacket packet = new IqPacket(IqPacket.TYPE_GET);
Element pubsub = packet.addChild("pubsub", "http://jabber.org/protocol/pubsub");
Element pubsub = packet.addChild("pubsub",
"http://jabber.org/protocol/pubsub");
Element items = pubsub.addChild("items");
items.setAttribute("node", node);
if (item != null) {
@ -61,7 +62,8 @@ public class IqGenerator extends AbstractGenerator {
public IqPacket publishAvatarMetadata(Avatar avatar) {
Element item = new Element("item");
item.setAttribute("id", avatar.sha1sum);
Element metadata = item.addChild("metadata","urn:xmpp:avatar:metadata");
Element metadata = item
.addChild("metadata", "urn:xmpp:avatar:metadata");
Element info = metadata.addChild("info");
info.setAttribute("bytes", avatar.size);
info.setAttribute("id", avatar.sha1sum);

View file

@ -38,7 +38,8 @@ public class MessageGenerator {
}
private void addDelay(MessagePacket packet, long timestamp) {
final SimpleDateFormat mDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'",Locale.US);
final SimpleDateFormat mDateFormat = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
mDateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
Element delay = packet.addChild("delay", "urn:xmpp:delay");
Date date = new Date(timestamp);
@ -58,8 +59,7 @@ public class MessageGenerator {
packet.addChild("private", "urn:xmpp:carbons:2");
packet.addChild("no-copy", "urn:xmpp:hints");
try {
packet.setBody(otrSession.transformSending(message
.getBody()));
packet.setBody(otrSession.transformSending(message.getBody()));
return packet;
} catch (OtrException e) {
return null;
@ -121,7 +121,8 @@ public class MessageGenerator {
return packet;
}
public MessagePacket conferenceSubject(Conversation conversation,String subject) {
public MessagePacket conferenceSubject(Conversation conversation,
String subject) {
MessagePacket packet = new MessagePacket();
packet.setType(MessagePacket.TYPE_GROUPCHAT);
packet.setTo(conversation.getContactJid().split("/")[0]);
@ -155,7 +156,8 @@ public class MessageGenerator {
return packet;
}
public MessagePacket received(Account account, MessagePacket originalMessage, String namespace) {
public MessagePacket received(Account account,
MessagePacket originalMessage, String namespace) {
MessagePacket receivedPacket = new MessagePacket();
receivedPacket.setType(MessagePacket.TYPE_NORMAL);
receivedPacket.setTo(originalMessage.getFrom());

View file

@ -41,7 +41,8 @@ public class PresenceGenerator extends AbstractGenerator {
}
String capHash = getCapHash();
if (capHash != null) {
Element cap = packet.addChild("c","http://jabber.org/protocol/caps");
Element cap = packet.addChild("c",
"http://jabber.org/protocol/caps");
cap.setAttribute("hash", "sha-1");
cap.setAttribute("node", "http://conversions.siacs.eu");
cap.setAttribute("ver", capHash);

View file

@ -33,7 +33,8 @@ public abstract class AbstractParser {
try {
String stamp = stamps.get(stamps.size() - 1);
if (stamp.contains(".")) {
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ",Locale.US)
Date date = new SimpleDateFormat(
"yyyy-MM-dd'T'HH:mm:ss.SSSZ", Locale.US)
.parse(stamp);
if (now < date.getTime()) {
return now;
@ -41,8 +42,8 @@ public abstract class AbstractParser {
return date.getTime();
}
} else {
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ",Locale.US)
.parse(stamp);
Date date = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ",
Locale.US).parse(stamp);
if (now < date.getTime()) {
return now;
} else {
@ -57,7 +58,8 @@ public abstract class AbstractParser {
}
}
protected void updateLastseen(Element packet, Account account, boolean presenceOverwrite) {
protected void updateLastseen(Element packet, Account account,
boolean presenceOverwrite) {
String[] fromParts = packet.getAttribute("from").split("/");
String from = fromParts[0];
String presence = null;

View file

@ -44,7 +44,8 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
}
public String avatarData(IqPacket packet) {
Element pubsub = packet.findChild("pubsub", "http://jabber.org/protocol/pubsub");
Element pubsub = packet.findChild("pubsub",
"http://jabber.org/protocol/pubsub");
if (pubsub == null) {
return null;
}
@ -63,20 +64,19 @@ public class IqParser extends AbstractParser implements OnIqPacketReceived {
Element query = packet.findChild("query");
this.rosterItems(account, query);
}
} else if (packet
.hasChild("open", "http://jabber.org/protocol/ibb")
|| packet
.hasChild("data", "http://jabber.org/protocol/ibb")) {
mXmppConnectionService.getJingleConnectionManager().deliverIbbPacket(account, packet);
} else if (packet.hasChild("open", "http://jabber.org/protocol/ibb")
|| packet.hasChild("data", "http://jabber.org/protocol/ibb")) {
mXmppConnectionService.getJingleConnectionManager()
.deliverIbbPacket(account, packet);
} else if (packet.hasChild("query",
"http://jabber.org/protocol/disco#info")) {
IqPacket response = mXmppConnectionService.getIqGenerator().discoResponse(packet);
IqPacket response = mXmppConnectionService.getIqGenerator()
.discoResponse(packet);
account.getXmppConnection().sendIqPacket(response, null);
} else {
if ((packet.getType() == IqPacket.TYPE_GET)
|| (packet.getType() == IqPacket.TYPE_SET)) {
IqPacket response = packet
.generateRespone(IqPacket.TYPE_ERROR);
IqPacket response = packet.generateRespone(IqPacket.TYPE_ERROR);
Element error = response.addChild("error");
error.setAttribute("type", "cancel");
error.addChild("feature-not-implemented",

View file

@ -4,6 +4,7 @@ import android.os.SystemClock;
import android.util.Log;
import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionStatus;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
@ -18,7 +19,7 @@ import eu.siacs.conversations.xmpp.stanzas.MessagePacket;
public class MessageParser extends AbstractParser implements
OnMessagePacketReceived {
private long lastCarbonMessageReceived = -XmppConnectionService.CARBON_GRACE_PERIOD;
private long lastCarbonMessageReceived = -(Config.CARBON_GRACE_PERIOD * 1000);
public MessageParser(XmppConnectionService service) {
super(service);
@ -173,7 +174,8 @@ public class MessageParser extends AbstractParser implements
finishedMessage.setTrueCounterpart(conversation.getMucOptions()
.getTrueCounterpart(counterPart));
}
if (packet.hasChild("delay") && conversation.hasDuplicateMessage(finishedMessage)) {
if (packet.hasChild("delay")
&& conversation.hasDuplicateMessage(finishedMessage)) {
return null;
}
finishedMessage.setTime(getTimestamp(packet));
@ -198,7 +200,8 @@ public class MessageParser extends AbstractParser implements
}
Element message = forwarded.findChild("message");
if ((message == null) || (!message.hasChild("body"))) {
if (status == Message.STATUS_RECEIVED && message.getAttribute("from")!=null) {
if (status == Message.STATUS_RECEIVED
&& message.getAttribute("from") != null) {
parseNormal(message, account);
}
return null;
@ -313,10 +316,12 @@ public class MessageParser extends AbstractParser implements
avatar)) {
if (account.getJid().equals(from)) {
if (account.setAvatar(avatar.getFilename())) {
mXmppConnectionService.databaseBackend.updateAccount(account);
mXmppConnectionService.databaseBackend
.updateAccount(account);
}
} else {
Contact contact = account.getRoster().getContact(from);
Contact contact = account.getRoster().getContact(
from);
contact.setAvatar(avatar.getFilename());
}
} else {
@ -324,11 +329,11 @@ public class MessageParser extends AbstractParser implements
}
}
} else {
Log.d("xmppService", account.getJid() + ": " + node + " from "
Log.d(Config.LOGTAG, account.getJid() + ": " + node + " from "
+ from);
}
} else {
Log.d("xmppService", event.toString());
Log.d(Config.LOGTAG, event.toString());
}
}
@ -355,7 +360,7 @@ public class MessageParser extends AbstractParser implements
boolean notify = true;
if (mXmppConnectionService.getPreferences().getBoolean(
"notification_grace_period_after_carbon_received", true)) {
notify = (SystemClock.elapsedRealtime() - lastCarbonMessageReceived) > XmppConnectionService.CARBON_GRACE_PERIOD;
notify = (SystemClock.elapsedRealtime() - lastCarbonMessageReceived) > (Config.CARBON_GRACE_PERIOD * 1000);
}
if ((packet.getType() == MessagePacket.TYPE_CHAT)) {

View file

@ -29,6 +29,7 @@ import android.util.Base64;
import android.util.Base64OutputStream;
import android.util.Log;
import android.util.LruCache;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
@ -45,7 +46,8 @@ public class FileBackend {
private Context context;
private LruCache<String, Bitmap> thumbnailCache;
private SimpleDateFormat imageDateFormat = new SimpleDateFormat("yyyyMMdd_HHmmssSSS",Locale.US);
private SimpleDateFormat imageDateFormat = new SimpleDateFormat(
"yyyyMMdd_HHmmssSSS", Locale.US);
public FileBackend(Context context) {
this.context = context;
@ -92,7 +94,8 @@ public class FileBackend {
public JingleFile getJingleFile(Message message, boolean decrypted) {
StringBuilder filename = new StringBuilder();
filename.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES).getAbsolutePath());
filename.append(Environment.getExternalStoragePublicDirectory(
Environment.DIRECTORY_PICTURES).getAbsolutePath());
filename.append("/Conversations/");
filename.append(message.getUuid());
if ((decrypted) || (message.getEncryption() == Message.ENCRYPTION_NONE)) {
@ -144,14 +147,15 @@ public class FileBackend {
private JingleFile copyImageToPrivateStorage(Message message, Uri image,
int sampleSize) throws ImageCopyException {
try {
InputStream is = context.getContentResolver().openInputStream(image);
InputStream is = context.getContentResolver()
.openInputStream(image);
JingleFile file = getJingleFile(message);
file.getParentFile().mkdirs();
file.createNewFile();
Bitmap originalBitmap;
BitmapFactory.Options options = new BitmapFactory.Options();
int inSampleSize = (int) Math.pow(2, sampleSize);
Log.d("xmppService", "reading bitmap with sample size "
Log.d(Config.LOGTAG, "reading bitmap with sample size "
+ inSampleSize);
options.inSampleSize = inSampleSize;
originalBitmap = BitmapFactory.decodeStream(is, null, options);
@ -197,8 +201,11 @@ public class FileBackend {
private int getRotation(Uri image) {
if ("content".equals(image.getScheme())) {
Cursor cursor = context.getContentResolver().query(image,
new String[] { MediaStore.Images.ImageColumns.ORIENTATION }, null, null, null);
Cursor cursor = context
.getContentResolver()
.query(image,
new String[] { MediaStore.Images.ImageColumns.ORIENTATION },
null, null, null);
if (cursor.getCount() != 1) {
return -1;
@ -258,7 +265,7 @@ public class FileBackend {
try {
this.deleteFile(file);
} catch (IOException e) {
Log.d("xmppService",
Log.d(Config.LOGTAG,
"error deleting file: " + file.getAbsolutePath());
}
}
@ -273,11 +280,13 @@ public class FileBackend {
public Uri getTakePhotoUri() {
StringBuilder pathBuilder = new StringBuilder();
pathBuilder.append(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
pathBuilder.append(Environment
.getExternalStoragePublicDirectory(Environment.DIRECTORY_DCIM));
pathBuilder.append('/');
pathBuilder.append("Camera");
pathBuilder.append('/');
pathBuilder.append("IMG_"+this.imageDateFormat.format(new Date())+".jpg");
pathBuilder.append("IMG_" + this.imageDateFormat.format(new Date())
+ ".jpg");
Uri uri = Uri.parse("file://" + pathBuilder.toString());
File file = new File(uri.toString());
file.getParentFile().mkdirs();
@ -292,9 +301,11 @@ public class FileBackend {
return null;
}
ByteArrayOutputStream mByteArrayOutputStream = new ByteArrayOutputStream();
Base64OutputStream mBase64OutputSttream = new Base64OutputStream(mByteArrayOutputStream, Base64.DEFAULT);
Base64OutputStream mBase64OutputSttream = new Base64OutputStream(
mByteArrayOutputStream, Base64.DEFAULT);
MessageDigest digest = MessageDigest.getInstance("SHA-1");
DigestOutputStream mDigestOutputStream = new DigestOutputStream(mBase64OutputSttream, digest);
DigestOutputStream mDigestOutputStream = new DigestOutputStream(
mBase64OutputSttream, digest);
if (!bm.compress(format, 75, mDigestOutputStream)) {
return null;
}
@ -327,7 +338,8 @@ public class FileBackend {
FileOutputStream mFileOutputStream = new FileOutputStream(file);
MessageDigest digest = MessageDigest.getInstance("SHA-1");
digest.reset();
DigestOutputStream mDigestOutputStream = new DigestOutputStream(mFileOutputStream, digest);
DigestOutputStream mDigestOutputStream = new DigestOutputStream(
mFileOutputStream, digest);
mDigestOutputStream.write(avatar.getImageAsBytes());
mDigestOutputStream.flush();
mDigestOutputStream.close();
@ -337,7 +349,7 @@ public class FileBackend {
file.renameTo(new File(filename));
return true;
} else {
Log.d("xmppService","sha1sum mismatch for "+avatar.owner);
Log.d(Config.LOGTAG, "sha1sum mismatch for " + avatar.owner);
file.delete();
return false;
}
@ -381,8 +393,7 @@ public class FileBackend {
float outHeight = scale * h;
float left = (size - outWidth) / 2;
float top = (size - outHeight) / 2;
RectF target = new RectF(left, top, left + outWidth, top
+ outHeight);
RectF target = new RectF(left, top, left + outWidth, top + outHeight);
Bitmap output = Bitmap.createBitmap(size, size, input.getConfig());
Canvas canvas = new Canvas(output);
@ -436,7 +447,8 @@ public class FileBackend {
}
public static Bitmap getAvatar(String avatar, int size, Context context) {
Bitmap bm = BitmapFactory.decodeFile(FileBackend.getAvatarPath(context, avatar));
Bitmap bm = BitmapFactory.decodeFile(FileBackend.getAvatarPath(context,
avatar));
if (bm == null) {
return null;
}

View file

@ -1,11 +0,0 @@
package eu.siacs.conversations.services;
import android.graphics.Bitmap;
public final class Defaults {
public static final int AVATAR_SIZE = 192;
public static final Bitmap.CompressFormat AVATAR_FORMAT = Bitmap.CompressFormat.WEBP;
private Defaults() {
}
}

View file

@ -3,6 +3,7 @@ package eu.siacs.conversations.services;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class EventReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {

View file

@ -2,8 +2,8 @@ package eu.siacs.conversations.services;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
@ -27,7 +27,7 @@ public class ImageProvider extends ContentProvider {
DatabaseBackend databaseBackend = DatabaseBackend
.getInstance(getContext());
String uuids = uri.getPath();
Log.d("xmppService", "uuids = " + uuids+" mode="+mode);
Log.d(Config.LOGTAG, "uuids = " + uuids + " mode=" + mode);
if (uuids == null) {
throw new FileNotFoundException();
}
@ -38,13 +38,13 @@ public class ImageProvider extends ContentProvider {
String conversationUuid = uuidsSplited[1];
String messageUuid = uuidsSplited[2].split("\\.")[0];
Log.d("xmppService","messageUuid="+messageUuid);
Log.d(Config.LOGTAG, "messageUuid=" + messageUuid);
Conversation conversation = databaseBackend
.findConversationByUuid(conversationUuid);
if (conversation == null) {
throw new FileNotFoundException("conversation " + conversationUuid
+ " could not be found");
throw new FileNotFoundException("conversation "
+ conversationUuid + " could not be found");
}
Message message = databaseBackend.findMessageByUuid(messageUuid);
if (message == null) {
@ -102,11 +102,8 @@ public class ImageProvider extends ContentProvider {
}
public static Uri getProviderUri(Message message) {
return Uri
.parse("content://eu.siacs.conversations.images/"
+ message.getConversationUuid()
+ "/"
+ message.getUuid()
return Uri.parse("content://eu.siacs.conversations.images/"
+ message.getConversationUuid() + "/" + message.getUuid()
+ ".webp");
}
}

View file

@ -20,6 +20,7 @@ import de.duenndns.ssl.MemorizingTrustManager;
import net.java.otr4j.OtrException;
import net.java.otr4j.session.Session;
import net.java.otr4j.session.SessionStatus;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.crypto.PgpEngine;
import eu.siacs.conversations.entities.Account;
@ -83,18 +84,11 @@ import android.util.Log;
public class XmppConnectionService extends Service {
protected static final String LOGTAG = "xmppService";
public DatabaseBackend databaseBackend;
private FileBackend fileBackend;
public long startDate;
private static final int PING_MAX_INTERVAL = 300;
private static final int PING_MIN_INTERVAL = 30;
private static final int PING_TIMEOUT = 10;
private static final int CONNECT_TIMEOUT = 90;
public static final long CARBON_GRACE_PERIOD = 60000L;
private static String ACTION_MERGE_PHONE_CONTACTS = "merge_phone_contacts";
private MemorizingTrustManager mMemorizingTrustManager;
@ -169,16 +163,17 @@ public class XmppConnectionService extends Service {
}
if (connection != null && connection.getFeatures().csi()) {
if (checkListeners()) {
Log.d(LOGTAG, account.getJid()
Log.d(Config.LOGTAG, account.getJid()
+ " sending csi//inactive");
connection.sendInactive();
} else {
Log.d(LOGTAG, account.getJid() + " sending csi//active");
Log.d(Config.LOGTAG, account.getJid()
+ " sending csi//active");
connection.sendActive();
}
}
syncDirtyContacts(account);
scheduleWakeupCall(PING_MAX_INTERVAL, true);
scheduleWakeupCall(Config.PING_MAX_INTERVAL, true);
} else if (account.getStatus() == Account.STATUS_OFFLINE) {
resetSendingToWaiting(account);
if (!account.isOptionSet(Account.OPTION_DISABLED)) {
@ -192,7 +187,7 @@ public class XmppConnectionService extends Service {
&& (account.getStatus() != Account.STATUS_NO_INTERNET)) {
if (connection != null) {
int next = connection.getTimeToNextAttempt();
Log.d(LOGTAG, account.getJid()
Log.d(Config.LOGTAG, account.getJid()
+ ": error connecting account. try again in "
+ next + "s for the "
+ (connection.getAttempt() + 1) + " time");
@ -355,10 +350,11 @@ public class XmppConnectionService extends Service {
.getLastPacketReceived();
long lastSent = account.getXmppConnection()
.getLastPingSent();
if (lastSent - lastReceived >= PING_TIMEOUT * 1000) {
Log.d(LOGTAG, account.getJid() + ": ping timeout");
if (lastSent - lastReceived >= Config.PING_TIMEOUT * 1000) {
Log.d(Config.LOGTAG, account.getJid()
+ ": ping timeout");
this.reconnectAccount(account, true);
} else if (SystemClock.elapsedRealtime() - lastReceived >= PING_MIN_INTERVAL * 1000) {
} else if (SystemClock.elapsedRealtime() - lastReceived >= Config.PING_MIN_INTERVAL * 1000) {
account.getXmppConnection().sendPing();
this.scheduleWakeupCall(2, false);
}
@ -370,8 +366,8 @@ public class XmppConnectionService extends Service {
new Thread(account.getXmppConnection()).start();
} else if ((account.getStatus() == Account.STATUS_CONNECTING)
&& ((SystemClock.elapsedRealtime() - account
.getXmppConnection().getLastConnect()) / 1000 >= CONNECT_TIMEOUT)) {
Log.d(LOGTAG, account.getJid()
.getXmppConnection().getLastConnect()) / 1000 >= Config.CONNECT_TIMEOUT)) {
Log.d(Config.LOGTAG, account.getJid()
+ ": time out during connect reconnecting");
reconnectAccount(account, true);
} else {
@ -380,7 +376,7 @@ public class XmppConnectionService extends Service {
}
}
// in any case. reschedule wakup call
this.scheduleWakeupCall(PING_MAX_INTERVAL, true);
this.scheduleWakeupCall(Config.PING_MAX_INTERVAL, true);
}
if (mOnAccountUpdate != null) {
mOnAccountUpdate.onAccountUpdate();
@ -450,7 +446,7 @@ public class XmppConnectionService extends Service {
.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, EventReceiver.class);
alarmManager.cancel(PendingIntent.getBroadcast(context, 0, intent, 0));
Log.d(LOGTAG, "good bye");
Log.d(Config.LOGTAG, "good bye");
stopSelf();
}
@ -673,10 +669,10 @@ public class XmppConnectionService extends Service {
public void fetchRosterFromServer(Account account) {
IqPacket iqPacket = new IqPacket(IqPacket.TYPE_GET);
if (!"".equals(account.getRosterVersion())) {
Log.d(LOGTAG, account.getJid() + ": fetching roster version "
+ account.getRosterVersion());
Log.d(Config.LOGTAG, account.getJid()
+ ": fetching roster version " + account.getRosterVersion());
} else {
Log.d(LOGTAG, account.getJid() + ": fetching roster");
Log.d(Config.LOGTAG, account.getJid() + ": fetching roster");
}
iqPacket.query("jabber:iq:roster").setAttribute("ver",
account.getRosterVersion());
@ -1006,7 +1002,8 @@ public class XmppConnectionService extends Service {
XmppConnection connection = account.getXmppConnection();
if (connection != null && connection.getFeatures().csi()) {
connection.sendActive();
Log.d(LOGTAG, account.getJid() + " sending csi//active");
Log.d(Config.LOGTAG, account.getJid()
+ " sending csi//active");
}
}
}
@ -1018,7 +1015,8 @@ public class XmppConnectionService extends Service {
XmppConnection connection = account.getXmppConnection();
if (connection != null && connection.getFeatures().csi()) {
connection.sendInactive();
Log.d(LOGTAG, account.getJid() + " sending csi//inactive");
Log.d(Config.LOGTAG, account.getJid()
+ " sending csi//inactive");
}
}
}
@ -1040,7 +1038,7 @@ public class XmppConnectionService extends Service {
account.pendingConferenceJoins.remove(conversation);
account.pendingConferenceLeaves.remove(conversation);
if (account.getStatus() == Account.STATUS_ONLINE) {
Log.d(LOGTAG,
Log.d(Config.LOGTAG,
"joining conversation " + conversation.getContactJid());
String nick = conversation.getMucOptions().getProposedNick();
conversation.getMucOptions().setJoinNick(nick);
@ -1142,8 +1140,8 @@ public class XmppConnectionService extends Service {
sendPresencePacket(conversation.getAccount(), packet);
conversation.getMucOptions().setOffline();
conversation.deregisterWithBookmark();
Log.d(LOGTAG, conversation.getAccount().getJid() + " leaving muc "
+ conversation.getContactJid());
Log.d(Config.LOGTAG, conversation.getAccount().getJid()
+ " leaving muc " + conversation.getContactJid());
} else {
account.pendingConferenceLeaves.add(conversation);
}
@ -1184,7 +1182,6 @@ public class XmppConnectionService extends Service {
pushContactToServer(contact);
}
if (contact.getOption(Contact.Options.DIRTY_DELETE)) {
Log.d(LOGTAG, "dirty delete");
deleteContactOnServer(contact);
}
}
@ -1204,7 +1201,8 @@ public class XmppConnectionService extends Service {
Account account = conversation.getAccount();
List<Message> messages = conversation.getMessages();
Session otrSession = conversation.getOtrSession();
Log.d(LOGTAG, account.getJid() + " otr session established with "
Log.d(Config.LOGTAG,
account.getJid() + " otr session established with "
+ conversation.getContactJid() + "/"
+ otrSession.getSessionID().getUserID());
for (int i = 0; i < messages.size(); ++i) {
@ -1280,8 +1278,8 @@ public class XmppConnectionService extends Service {
public void publishAvatar(Account account, Uri image,
final UiCallback<Avatar> callback) {
final Bitmap.CompressFormat format = Defaults.AVATAR_FORMAT;
final int size = Defaults.AVATAR_SIZE;
final Bitmap.CompressFormat format = Config.AVATAR_FORMAT;
final int size = Config.AVATAR_SIZE;
final Avatar avatar = getFileBackend()
.getPepAvatar(image, size, format);
if (avatar != null) {
@ -1341,7 +1339,7 @@ public class XmppConnectionService extends Service {
public void fetchAvatar(Account account, final Avatar avatar,
final UiCallback<Avatar> callback) {
Log.d(LOGTAG, account.getJid() + ": retrieving avatar for "
Log.d(Config.LOGTAG, account.getJid() + ": retrieving avatar for "
+ avatar.owner);
IqPacket packet = this.mIqGenerator.retrieveAvatar(avatar);
sendIqPacket(account, packet, new OnIqPacketReceived() {
@ -1439,7 +1437,8 @@ public class XmppConnectionService extends Service {
}
Thread thread = new Thread(account.getXmppConnection());
thread.start();
scheduleWakeupCall((int) (CONNECT_TIMEOUT * 1.2), false);
scheduleWakeupCall((int) (Config.CONNECT_TIMEOUT * 1.2),
false);
}
}
}).start();

View file

@ -77,20 +77,19 @@ public class ChooseContactActivity extends XmppActivity {
}
};
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_choose_contact);
mListView = (ListView) findViewById(R.id.choose_contact_list);
mContactsAdapter = new ListItemAdapter(getApplicationContext(), contacts);
mContactsAdapter = new ListItemAdapter(getApplicationContext(),
contacts);
mListView.setAdapter(mContactsAdapter);
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> arg0, View arg1, int position,
long arg3) {
public void onItemClick(AdapterView<?> arg0, View arg1,
int position, long arg3) {
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(mSearchEditText.getWindowToken(),
InputMethodManager.HIDE_IMPLICIT_ONLY);
@ -98,7 +97,8 @@ public class ChooseContactActivity extends XmppActivity {
Intent data = new Intent();
data.putExtra("contact", contacts.get(position).getJid());
data.putExtra("account", request.getStringExtra("account"));
data.putExtra("conversation",request.getStringExtra("conversation"));
data.putExtra("conversation",
request.getStringExtra("conversation"));
setResult(RESULT_OK, data);
finish();
}

View file

@ -250,7 +250,8 @@ public class ConferenceDetailsActivity extends XmppActivity {
if (contact.showInRoster()) {
bm = contact.getImage(48, this);
name.setText(contact.getDisplayName());
role.setText(user.getName() + " \u2022 " + getReadableRole(user.getRole()));
role.setText(user.getName() + " \u2022 "
+ getReadableRole(user.getRole()));
} else {
bm = UIHelper.getContactPicture(user.getName(), 48, this,
false);

View file

@ -111,7 +111,8 @@ public class ContactDetailsActivity extends XmppActivity {
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked) {
if (contact.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
if (contact
.getOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST)) {
xmppConnectionService.sendPresencePacket(contact
.getAccount(),
xmppConnectionService.getPresenceGenerator()
@ -363,7 +364,8 @@ public class ContactDetailsActivity extends XmppActivity {
@Override
public void onBackendConnected() {
xmppConnectionService.setOnRosterUpdateListener(this.rosterUpdate);
xmppConnectionService.setOnAccountListChangedListener(this.accountUpdate );
xmppConnectionService
.setOnAccountListChangedListener(this.accountUpdate);
if ((accountJid != null) && (contactJid != null)) {
Account account = xmppConnectionService
.findAccountByJid(accountJid);

View file

@ -35,7 +35,6 @@ import android.graphics.drawable.Drawable;
import android.support.v4.widget.SlidingPaneLayout;
import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
@ -197,8 +196,8 @@ public class ConversationActivity extends XmppActivity {
if (ab != null) {
ab.setDisplayHomeAsUpEnabled(true);
ab.setHomeButtonEnabled(true);
ab.setTitle(
getSelectedConversation().getName(useSubject));
ab.setTitle(getSelectedConversation().getName(
useSubject));
}
invalidateOptionsMenu();
if (!getSelectedConversation().isRead()) {
@ -232,7 +231,8 @@ public class ConversationActivity extends XmppActivity {
MenuItem menuClearHistory = (MenuItem) menu
.findItem(R.id.action_clear_history);
MenuItem menuAdd = (MenuItem) menu.findItem(R.id.action_add);
MenuItem menuInviteContact = (MenuItem) menu.findItem(R.id.action_invite);
MenuItem menuInviteContact = (MenuItem) menu
.findItem(R.id.action_invite);
if ((spl.isOpen() && (spl.isSlideable()))) {
menuArchive.setVisible(false);
@ -267,11 +267,12 @@ public class ConversationActivity extends XmppActivity {
@Override
public void onPresenceSelected() {
if (attachmentChoice == ATTACHMENT_CHOICE_TAKE_PHOTO) {
pendingImageUri = xmppConnectionService.getFileBackend().getTakePhotoUri();
Log.d("xmppService",pendingImageUri.toString());
pendingImageUri = xmppConnectionService.getFileBackend()
.getTakePhotoUri();
Intent takePictureIntent = new Intent(
MediaStore.ACTION_IMAGE_CAPTURE);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,pendingImageUri);
takePictureIntent.putExtra(MediaStore.EXTRA_OUTPUT,
pendingImageUri);
if (takePictureIntent.resolveActivity(getPackageManager()) != null) {
startActivityForResult(takePictureIntent,
REQUEST_IMAGE_CAPTURE);
@ -553,7 +554,8 @@ public class ConversationActivity extends XmppActivity {
if (xmppConnectionServiceBound) {
if ((Intent.ACTION_VIEW.equals(intent.getAction()) && (VIEW_CONVERSATION
.equals(intent.getType())))) {
String convToView = (String) intent.getExtras().get(CONVERSATION);
String convToView = (String) intent.getExtras().get(
CONVERSATION);
updateConversationList();
for (int i = 0; i < conversationList.size(); ++i) {
if (conversationList.get(i).getUuid().equals(convToView)) {
@ -602,7 +604,8 @@ public class ConversationActivity extends XmppActivity {
}
if (getSelectedConversation() != null && pendingImageUri != null) {
attachImageToConversation(getSelectedConversation(), pendingImageUri);
attachImageToConversation(getSelectedConversation(),
pendingImageUri);
pendingImageUri = null;
} else {
pendingImageUri = null;
@ -670,7 +673,8 @@ public class ConversationActivity extends XmppActivity {
} else if (requestCode == REQUEST_ATTACH_FILE_DIALOG) {
pendingImageUri = data.getData();
if (xmppConnectionServiceBound) {
attachImageToConversation(getSelectedConversation(),pendingImageUri);
attachImageToConversation(getSelectedConversation(),
pendingImageUri);
pendingImageUri = null;
}
} else if (requestCode == REQUEST_SEND_PGP_IMAGE) {
@ -686,10 +690,12 @@ public class ConversationActivity extends XmppActivity {
// encryptTextMessage();
} else if (requestCode == REQUEST_IMAGE_CAPTURE) {
if (xmppConnectionServiceBound) {
attachImageToConversation(getSelectedConversation(), pendingImageUri);
attachImageToConversation(getSelectedConversation(),
pendingImageUri);
pendingImageUri = null;
}
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Intent intent = new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(pendingImageUri);
sendBroadcast(intent);
} else if (requestCode == REQUEST_RECORD_AUDIO) {
@ -744,7 +750,8 @@ public class ConversationActivity extends XmppActivity {
}
public void updateConversationList() {
xmppConnectionService.populateWithOrderedConversations(conversationList);
xmppConnectionService
.populateWithOrderedConversations(conversationList);
listView.invalidateViews();
}
@ -761,7 +768,8 @@ public class ConversationActivity extends XmppActivity {
try {
this.startIntentSenderForResult(pi.getIntentSender(), requestCode,
null, 0, 0, 0);
} catch (SendIntentException e1) {}
} catch (SendIntentException e1) {
}
}
class BitmapWorkerTask extends AsyncTask<Message, Void, Bitmap> {

View file

@ -201,7 +201,8 @@ public class EditAccountActivity extends XmppActivity {
this.mSaveButton.setEnabled(true);
this.mSaveButton.setTextColor(getPrimaryTextColor());
if (jidToEdit != null) {
if (mAccount!= null && mAccount.getStatus() == Account.STATUS_ONLINE) {
if (mAccount != null
&& mAccount.getStatus() == Account.STATUS_ONLINE) {
this.mSaveButton.setText(R.string.save);
} else {
this.mSaveButton.setText(R.string.connect);

View file

@ -4,6 +4,8 @@ import android.app.PendingIntent;
public interface UiCallback<T> {
public void success(T object);
public void error(int errorCode, T object);
public void userInputRequried(PendingIntent pi, T object);
}

View file

@ -1,5 +1,6 @@
package eu.siacs.conversations.ui;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Contact;
@ -34,8 +35,6 @@ public abstract class XmppActivity extends Activity {
protected static final int REQUEST_ANNOUNCE_PGP = 0x0101;
protected static final int REQUEST_INVITE_TO_CONVERSATION = 0x0102;
protected final static String LOGTAG = "xmppService";
public XmppConnectionService xmppConnectionService;
public boolean xmppConnectionServiceBound = false;
protected boolean handledViewIntent = false;
@ -370,7 +369,7 @@ public abstract class XmppActivity extends Activity {
if (conversation.getMode() == Conversation.MODE_MULTI) {
xmppConnectionService.invite(conversation, contactJid);
}
Log.d("xmppService", "inviting " + contactJid + " to "
Log.d(Config.LOGTAG, "inviting " + contactJid + " to "
+ conversation.getName(true));
}
}

View file

@ -19,7 +19,8 @@ public class KnownHostsAdapter extends ArrayAdapter<String> {
final String[] split = constraint.toString().split("@");
if (split.length == 1) {
for (String domain : domains) {
suggestions.add(split[0].toLowerCase(Locale.getDefault()) + "@" + domain);
suggestions.add(split[0].toLowerCase(Locale
.getDefault()) + "@" + domain);
}
} else if (split.length == 2) {
for (String domain : domains) {
@ -27,7 +28,8 @@ public class KnownHostsAdapter extends ArrayAdapter<String> {
suggestions.clear();
break;
} else if (domain.contains(split[1])) {
suggestions.add(split[0].toLowerCase(Locale.getDefault()) + "@" + domain);
suggestions.add(split[0].toLowerCase(Locale
.getDefault()) + "@" + domain);
}
}
} else {

View file

@ -14,7 +14,6 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.Typeface;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
@ -69,7 +68,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
this.mOnContactPictureClickedListener = listener;
}
public void setOnContactPictureLongClicked(OnContactPictureLongClicked listener) {
public void setOnContactPictureLongClicked(
OnContactPictureLongClicked listener) {
this.mOnContactPictureLongClickedListener = listener;
}
@ -219,7 +219,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
} else {
String privateMarker;
if (message.getStatus() <= Message.STATUS_RECEIVED) {
privateMarker = activity.getString(R.string.private_message);
privateMarker = activity
.getString(R.string.private_message);
} else {
String to;
if (message.getPresence() != null) {
@ -227,11 +228,18 @@ public class MessageAdapter extends ArrayAdapter<Message> {
} else {
to = message.getCounterpart();
}
privateMarker = activity.getString(R.string.private_message_to, to);
privateMarker = activity.getString(
R.string.private_message_to, to);
}
SpannableString span = new SpannableString(privateMarker+" "+message.getBody());
span.setSpan(new ForegroundColorSpan(activity.getSecondaryTextColor()), 0, privateMarker.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
span.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0, privateMarker.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
SpannableString span = new SpannableString(privateMarker + " "
+ message.getBody());
span.setSpan(
new ForegroundColorSpan(activity
.getSecondaryTextColor()), 0, privateMarker
.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
span.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 0,
privateMarker.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
viewHolder.messageBody.setText(span);
}
} else {
@ -404,7 +412,8 @@ public class MessageAdapter extends ArrayAdapter<Message> {
if (name == null) {
name = item.getCounterpart();
}
viewHolder.contact_picture.setImageBitmap(mBitmapCache.get(name, getContext()));
viewHolder.contact_picture.setImageBitmap(mBitmapCache.get(
name, getContext()));
}
viewHolder.contact_picture
.setOnClickListener(new OnClickListener() {
@ -419,12 +428,14 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
});
viewHolder.contact_picture.setOnLongClickListener(new OnLongClickListener() {
viewHolder.contact_picture
.setOnLongClickListener(new OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
if (MessageAdapter.this.mOnContactPictureLongClickedListener != null) {
MessageAdapter.this.mOnContactPictureLongClickedListener.onContactPictureLongClicked(item);
MessageAdapter.this.mOnContactPictureLongClickedListener
.onContactPictureLongClicked(item);
return true;
} else {
return false;

View file

@ -48,7 +48,8 @@ public class CryptoHelper {
return result;
}
public static String saslDigestMd5(Account account, String challenge, SecureRandom random) {
public static String saslDigestMd5(Account account, String challenge,
SecureRandom random) {
try {
String[] challengeParts = new String(Base64.decode(challenge,
Base64.DEFAULT)).split(",");
@ -66,23 +67,24 @@ public class CryptoHelper {
String x = account.getUsername() + ":" + account.getServer() + ":"
+ account.getPassword();
MessageDigest md = MessageDigest.getInstance("MD5");
byte[] y = md
.digest(x.getBytes(Charset.defaultCharset()));
byte[] y = md.digest(x.getBytes(Charset.defaultCharset()));
String cNonce = new BigInteger(100, random).toString(32);
byte[] a1 = concatenateByteArrays(y,(":"+nonce+":"+cNonce).getBytes(Charset.defaultCharset()));
byte[] a1 = concatenateByteArrays(y,
(":" + nonce + ":" + cNonce).getBytes(Charset
.defaultCharset()));
String a2 = "AUTHENTICATE:" + digestUri;
String ha1 = bytesToHex(md.digest(a1));
String ha2 = bytesToHex(md.digest(a2.getBytes(Charset
.defaultCharset())));
String kd = ha1 + ":" + nonce + ":"+nonceCount+":" + cNonce + ":auth:"
+ ha2;
String kd = ha1 + ":" + nonce + ":" + nonceCount + ":" + cNonce
+ ":auth:" + ha2;
String response = bytesToHex(md.digest(kd.getBytes(Charset
.defaultCharset())));
String saslString = "username=\"" + account.getUsername()
+ "\",realm=\"" + account.getServer() + "\",nonce=\""
+ nonce + "\",cnonce=\"" + cNonce
+ "\",nc="+nonceCount+",qop=auth,digest-uri=\""+digestUri+"\",response=" + response
+ ",charset=utf-8";
+ nonce + "\",cnonce=\"" + cNonce + "\",nc=" + nonceCount
+ ",qop=auth,digest-uri=\"" + digestUri + "\",response="
+ response + ",charset=utf-8";
return Base64.encodeToString(
saslString.getBytes(Charset.defaultCharset()),
Base64.NO_WRAP);

View file

@ -10,6 +10,7 @@ import de.measite.minidns.record.A;
import de.measite.minidns.record.AAAA;
import de.measite.minidns.record.Data;
import de.measite.minidns.util.NameUtil;
import eu.siacs.conversations.Config;
import java.io.IOException;
import java.net.InetAddress;
@ -47,13 +48,10 @@ public class DNSHelper {
Bundle namePort = new Bundle();
try {
String qname = "_xmpp-client._tcp." + host;
Log.d("xmppService", "using dns server: " + dnsServer.getHostAddress()
Log.d(Config.LOGTAG,
"using dns server: " + dnsServer.getHostAddress()
+ " to look up " + host);
DNSMessage message =
client.query(
qname,
TYPE.SRV,
CLASS.IN,
DNSMessage message = client.query(qname, TYPE.SRV, CLASS.IN,
dnsServer.getHostAddress());
// How should we handle priorities and weight?
@ -64,21 +62,20 @@ public class DNSHelper {
// a random order respecting the weight, and dump that priority by
// priority
TreeMap<Integer, ArrayList<SRV>> priorities =
new TreeMap<Integer, ArrayList<SRV>>();
TreeMap<String, ArrayList<String>> ips4 =
new TreeMap<String, ArrayList<String>>();
TreeMap<String, ArrayList<String>> ips6 =
new TreeMap<String, ArrayList<String>>();
TreeMap<Integer, ArrayList<SRV>> priorities = new TreeMap<Integer, ArrayList<SRV>>();
TreeMap<String, ArrayList<String>> ips4 = new TreeMap<String, ArrayList<String>>();
TreeMap<String, ArrayList<String>> ips6 = new TreeMap<String, ArrayList<String>>();
for (Record[] rrset : new Record[][] { message.getAnswers(),
message.getAdditionalResourceRecords() }) {
for (Record rr : rrset) {
Data d = rr.getPayload();
if (d instanceof SRV && NameUtil.idnEquals(qname,rr.getName())) {
if (d instanceof SRV
&& NameUtil.idnEquals(qname, rr.getName())) {
SRV srv = (SRV) d;
if (!priorities.containsKey(srv.getPriority())) {
priorities.put(srv.getPriority(), new ArrayList<SRV>(2));
priorities.put(srv.getPriority(),
new ArrayList<SRV>(2));
}
priorities.get(srv.getPriority()).add(srv);
}
@ -100,7 +97,8 @@ public class DNSHelper {
}
Random rnd = new Random();
ArrayList<SRV> result = new ArrayList<SRV>(priorities.size() * 2 + 1);
ArrayList<SRV> result = new ArrayList<SRV>(
priorities.size() * 2 + 1);
for (ArrayList<SRV> s : priorities.values()) {
// trivial case
@ -115,13 +113,15 @@ public class DNSHelper {
}
while (totalweight > 0l && s.size() > 0) {
long p = (rnd.nextLong() & 0x7fffffffffffffffl) % totalweight;
long p = (rnd.nextLong() & 0x7fffffffffffffffl)
% totalweight;
int i = 0;
while (p > 0) {
p -= s.get(i++).getPriority();
}
i--;
// remove is expensive, but we have only a few entries anyway
// remove is expensive, but we have only a few entries
// anyway
SRV srv = s.remove(i);
totalweight -= srv.getWeight();
result.add(srv);
@ -164,10 +164,10 @@ public class DNSHelper {
}
} catch (SocketTimeoutException e) {
Log.d("xmppService", "timeout during dns");
Log.d(Config.LOGTAG, "timeout during dns");
namePort.putString("error", "timeout");
} catch (Exception e) {
Log.d("xmppService","unhandled exception in sub project");
Log.d(Config.LOGTAG, "unhandled exception in sub project");
namePort.putString("error", "unhandled");
}
return namePort;

View file

@ -14,10 +14,12 @@ public class ExceptionHandler implements UncaughtExceptionHandler {
private UncaughtExceptionHandler defaultHandler;
private Context context;
public ExceptionHandler(Context context) {
this.context = context;
this.defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
}
@Override
public void uncaughtException(Thread thread, Throwable ex) {
Writer result = new StringWriter();
@ -26,7 +28,8 @@ public class ExceptionHandler implements UncaughtExceptionHandler {
String stacktrace = result.toString();
printWriter.close();
try {
OutputStream os = context.openFileOutput("stacktrace.txt",Context.MODE_PRIVATE);
OutputStream os = context.openFileOutput("stacktrace.txt",
Context.MODE_PRIVATE);
os.write(stacktrace.getBytes());
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block

View file

@ -7,6 +7,7 @@ import java.io.IOException;
import java.io.InputStreamReader;
import java.util.List;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
@ -27,13 +28,16 @@ import android.util.Log;
public class ExceptionHelper {
public static void init(Context context) {
if (!(Thread.getDefaultUncaughtExceptionHandler() instanceof ExceptionHandler)) {
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(context));
Thread.setDefaultUncaughtExceptionHandler(new ExceptionHandler(
context));
}
}
public static void checkForCrash(Context context, final XmppConnectionService service) {
public static void checkForCrash(Context context,
final XmppConnectionService service) {
try {
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(context);
final SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(context);
boolean neverSend = preferences.getBoolean("never_send", false);
if (neverSend) {
return;
@ -51,18 +55,21 @@ public class ExceptionHelper {
}
final Account finalAccount = account;
FileInputStream file = context.openFileInput("stacktrace.txt");
InputStreamReader inputStreamReader = new InputStreamReader(
file);
BufferedReader stacktrace = new BufferedReader(
inputStreamReader);
InputStreamReader inputStreamReader = new InputStreamReader(file);
BufferedReader stacktrace = new BufferedReader(inputStreamReader);
final StringBuilder report = new StringBuilder();
PackageManager pm = context.getPackageManager();
PackageInfo packageInfo = null;
try {
packageInfo = pm.getPackageInfo(context.getPackageName(), 0);
report.append("Version: " + packageInfo.versionName + '\n');
report.append("Last Update: "+DateUtils.formatDateTime(context, packageInfo.lastUpdateTime, DateUtils.FORMAT_SHOW_TIME|DateUtils.FORMAT_SHOW_DATE)+'\n');
} catch (NameNotFoundException e) {}
report.append("Last Update: "
+ DateUtils.formatDateTime(context,
packageInfo.lastUpdateTime,
DateUtils.FORMAT_SHOW_TIME
| DateUtils.FORMAT_SHOW_DATE) + '\n');
} catch (NameNotFoundException e) {
}
String line;
while ((line = stacktrace.readLine()) != null) {
report.append(line);
@ -73,22 +80,30 @@ public class ExceptionHelper {
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(context.getString(R.string.crash_report_title));
builder.setMessage(context.getText(R.string.crash_report_message));
builder.setPositiveButton(context.getText(R.string.send_now), new OnClickListener() {
builder.setPositiveButton(context.getText(R.string.send_now),
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Log.d("xmppService","using account="+finalAccount.getJid()+" to send in stack trace");
Conversation conversation = service.findOrCreateConversation(finalAccount, "bugs@siacs.eu", false);
Message message = new Message(conversation, report.toString(), Message.ENCRYPTION_NONE);
Log.d(Config.LOGTAG, "using account="
+ finalAccount.getJid()
+ " to send in stack trace");
Conversation conversation = service
.findOrCreateConversation(finalAccount,
"bugs@siacs.eu", false);
Message message = new Message(conversation, report
.toString(), Message.ENCRYPTION_NONE);
service.sendMessage(message);
}
});
builder.setNegativeButton(context.getText(R.string.send_never),new OnClickListener() {
builder.setNegativeButton(context.getText(R.string.send_never),
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
preferences.edit().putBoolean("never_send", true).commit();
preferences.edit().putBoolean("never_send", true)
.commit();
}
});
builder.create().show();

View file

@ -30,16 +30,17 @@ public final class PRNGFixes {
private static final int VERSION_CODE_JELLY_BEAN = 16;
private static final int VERSION_CODE_JELLY_BEAN_MR2 = 18;
private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL =
getBuildFingerprintAndDeviceSerial();
private static final byte[] BUILD_FINGERPRINT_AND_DEVICE_SERIAL = getBuildFingerprintAndDeviceSerial();
/** Hidden constructor to prevent instantiation. */
private PRNGFixes() {}
private PRNGFixes() {
}
/**
* Applies all fixes.
*
* @throws SecurityException if a fix is needed but could not be applied.
* @throws SecurityException
* if a fix is needed but could not be applied.
*/
public static void apply() {
applyOpenSSLFix();
@ -50,7 +51,8 @@ public final class PRNGFixes {
* Applies the fix for OpenSSL PRNG having low entropy. Does nothing if the
* fix is not needed.
*
* @throws SecurityException if the fix is needed but could not be applied.
* @throws SecurityException
* if the fix is needed but could not be applied.
*/
private static void applyOpenSSLFix() throws SecurityException {
if ((Build.VERSION.SDK_INT < VERSION_CODE_JELLY_BEAN)
@ -66,7 +68,8 @@ public final class PRNGFixes {
.invoke(null, generateSeed());
// Mix output of Linux PRNG into OpenSSL's PRNG
int bytesRead = (Integer) Class.forName(
int bytesRead = (Integer) Class
.forName(
"org.apache.harmony.xnet.provider.jsse.NativeCrypto")
.getMethod("RAND_load_file", String.class, long.class)
.invoke(null, "/dev/urandom", 1024);
@ -85,10 +88,10 @@ public final class PRNGFixes {
* default. Does nothing if the implementation is already the default or if
* there is not need to install the implementation.
*
* @throws SecurityException if the fix is needed but could not be applied.
* @throws SecurityException
* if the fix is needed but could not be applied.
*/
private static void installLinuxPRNGSecureRandom()
throws SecurityException {
private static void installLinuxPRNGSecureRandom() throws SecurityException {
if (Build.VERSION.SDK_INT > VERSION_CODE_JELLY_BEAN_MR2) {
// No need to apply the fix
return;
@ -96,12 +99,12 @@ public final class PRNGFixes {
// Install a Linux PRNG-based SecureRandom implementation as the
// default, if not yet installed.
Provider[] secureRandomProviders =
Security.getProviders("SecureRandom.SHA1PRNG");
Provider[] secureRandomProviders = Security
.getProviders("SecureRandom.SHA1PRNG");
if ((secureRandomProviders == null)
|| (secureRandomProviders.length < 1)
|| (!LinuxPRNGSecureRandomProvider.class.equals(
secureRandomProviders[0].getClass()))) {
|| (!LinuxPRNGSecureRandomProvider.class
.equals(secureRandomProviders[0].getClass()))) {
Security.insertProviderAt(new LinuxPRNGSecureRandomProvider(), 1);
}
@ -109,8 +112,8 @@ public final class PRNGFixes {
// SecureRandom.getInstance("SHA1PRNG") return a SecureRandom backed
// by the Linux PRNG-based SecureRandom implementation.
SecureRandom rng1 = new SecureRandom();
if (!LinuxPRNGSecureRandomProvider.class.equals(
rng1.getProvider().getClass())) {
if (!LinuxPRNGSecureRandomProvider.class.equals(rng1.getProvider()
.getClass())) {
throw new SecurityException(
"new SecureRandom() backed by wrong Provider: "
+ rng1.getProvider().getClass());
@ -122,8 +125,8 @@ public final class PRNGFixes {
} catch (NoSuchAlgorithmException e) {
throw new SecurityException("SHA1PRNG not available", e);
}
if (!LinuxPRNGSecureRandomProvider.class.equals(
rng2.getProvider().getClass())) {
if (!LinuxPRNGSecureRandomProvider.class.equals(rng2.getProvider()
.getClass())) {
throw new SecurityException(
"SecureRandom.getInstance(\"SHA1PRNG\") backed by wrong"
+ " Provider: " + rng2.getProvider().getClass());
@ -131,14 +134,13 @@ public final class PRNGFixes {
}
/**
* {@code Provider} of {@code SecureRandom} engines which pass through
* all requests to the Linux PRNG.
* {@code Provider} of {@code SecureRandom} engines which pass through all
* requests to the Linux PRNG.
*/
private static class LinuxPRNGSecureRandomProvider extends Provider {
public LinuxPRNGSecureRandomProvider() {
super("LinuxPRNG",
1.0,
super("LinuxPRNG", 1.0,
"A Linux-specific random number provider that uses"
+ " /dev/urandom");
// Although /dev/urandom is not a SHA-1 PRNG, some apps
@ -151,8 +153,8 @@ public final class PRNGFixes {
}
/**
* {@link SecureRandomSpi} which passes all requests to the Linux PRNG
* ({@code /dev/urandom}).
* {@link SecureRandomSpi} which passes all requests to the Linux PRNG (
* {@code /dev/urandom}).
*/
public static class LinuxPRNGSecureRandom extends SecureRandomSpi {
@ -230,8 +232,8 @@ public final class PRNGFixes {
in.readFully(bytes);
}
} catch (IOException e) {
throw new SecurityException(
"Failed to read from " + URANDOM_FILE, e);
throw new SecurityException("Failed to read from "
+ URANDOM_FILE, e);
}
}
@ -250,8 +252,8 @@ public final class PRNGFixes {
// PRNG output performance and can live with future PRNG
// output being pulled into this process prematurely.
try {
sUrandomIn = new DataInputStream(
new FileInputStream(URANDOM_FILE));
sUrandomIn = new DataInputStream(new FileInputStream(
URANDOM_FILE));
} catch (IOException e) {
throw new SecurityException("Failed to open "
+ URANDOM_FILE + " for reading", e);
@ -278,8 +280,7 @@ public final class PRNGFixes {
private static byte[] generateSeed() {
try {
ByteArrayOutputStream seedBuffer = new ByteArrayOutputStream();
DataOutputStream seedBufferOut =
new DataOutputStream(seedBuffer);
DataOutputStream seedBufferOut = new DataOutputStream(seedBuffer);
seedBufferOut.writeLong(System.currentTimeMillis());
seedBufferOut.writeLong(System.nanoTime());
seedBufferOut.writeInt(Process.myPid());

View file

@ -56,7 +56,9 @@ public class PhoneHelper {
contact.putString("lookup", cursor.getString(cursor
.getColumnIndex(ContactsContract.Data.LOOKUP_KEY)));
contact.putString("jid",cursor.getString(cursor
contact.putString(
"jid",
cursor.getString(cursor
.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)));
phoneContacts.add(contact);
}
@ -69,8 +71,7 @@ public class PhoneHelper {
}
public static Uri getSefliUri(Context context) {
String[] mProjection = new String[] { Profile._ID,
Profile.PHOTO_URI };
String[] mProjection = new String[] { Profile._ID, Profile.PHOTO_URI };
Cursor mProfileCursor = context.getContentResolver().query(
Profile.CONTENT_URI, mProjection, null, null, null);

View file

@ -118,9 +118,13 @@ public class UIHelper {
}
private static int getNameColor(String name) {
/*int holoColors[] = { 0xFF1da9da, 0xFFb368d9, 0xFF83b600, 0xFFffa713,
0xFFe92727 };*/
int holoColors[] = {0xFFe91e63, 0xFF9c27b0, 0xFF673ab7, 0xFF3f51b5, 0xFF5677fc, 0xFF03a9f4, 0xFF00bcd4, 0xFF009688, 0xFFff5722, 0xFF795548, 0xFF607d8b};
/*
* int holoColors[] = { 0xFF1da9da, 0xFFb368d9, 0xFF83b600, 0xFFffa713,
* 0xFFe92727 };
*/
int holoColors[] = { 0xFFe91e63, 0xFF9c27b0, 0xFF673ab7, 0xFF3f51b5,
0xFF5677fc, 0xFF03a9f4, 0xFF00bcd4, 0xFF009688, 0xFFff5722,
0xFF795548, 0xFF607d8b };
return holoColors[(int) ((name.hashCode() & 0xffffffffl) % holoColors.length)];
}

View file

@ -4,8 +4,8 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Validator {
public static final Pattern VALID_JID =
Pattern.compile("^[^@/<>'\"\\s]+@[^@/<>'\"\\s]+$", Pattern.CASE_INSENSITIVE);
public static final Pattern VALID_JID = Pattern.compile(
"^[^@/<>'\"\\s]+@[^@/<>'\"\\s]+$", Pattern.CASE_INSENSITIVE);
public static boolean isValidJid(String jid) {
Matcher matcher = VALID_JID.matcher(jid);

View file

@ -15,33 +15,35 @@ public class ZLibInputStream extends InflaterInputStream {
/**
* Construct a ZLibInputStream, reading data from the underlying stream.
*
* @param is The {@code InputStream} to read data from.
* @throws IOException If an {@code IOException} occurs.
* @param is
* The {@code InputStream} to read data from.
* @throws IOException
* If an {@code IOException} occurs.
*/
public ZLibInputStream(InputStream is) throws IOException {
super(is, new Inflater(), 512);
}
/**
* Provide a more InputStream compatible version of available.
* A return value of 1 means that it is likly to read one byte without
* blocking, 0 means that the system is known to block for more input.
* Provide a more InputStream compatible version of available. A return
* value of 1 means that it is likly to read one byte without blocking, 0
* means that the system is known to block for more input.
*
* @return 0 if no data is available, 1 otherwise
* @throws IOException
*/
@Override
public int available() throws IOException {
/* This is one of the funny code blocks.
* InflaterInputStream.available violates the contract of
* InputStream.available, which breaks kXML2.
/*
* This is one of the funny code blocks. InflaterInputStream.available
* violates the contract of InputStream.available, which breaks kXML2.
*
* I'm not sure who's to blame, oracle/sun for a broken api or the
* google guys for mixing a sun bug with a xml reader that can't handle
* it....
*
* Anyway, this simple if breaks suns distorted reality, but helps
* to use the api as intended.
* Anyway, this simple if breaks suns distorted reality, but helps to
* use the api as intended.
*/
if (inf.needsInput()) {
return 0;

View file

@ -9,11 +9,15 @@ import java.util.zip.Deflater;
import java.util.zip.DeflaterOutputStream;
/**
* <p>Android 2.2 includes Java7 FLUSH_SYNC option, which will be used by this
* <p>
* Android 2.2 includes Java7 FLUSH_SYNC option, which will be used by this
* Implementation, preferable via reflection. The @hide was remove in API level
* 19. This class might thus go away in the future.</p>
* <p>Please use {@link ZLibOutputStream#SUPPORTED} to check for flush
* compatibility.</p>
* 19. This class might thus go away in the future.
* </p>
* <p>
* Please use {@link ZLibOutputStream#SUPPORTED} to check for flush
* compatibility.
* </p>
*/
public class ZLibOutputStream extends DeflaterOutputStream {
@ -33,7 +37,8 @@ public class ZLibOutputStream extends DeflaterOutputStream {
static {
Method m = null;
try {
m = Deflater.class.getMethod("deflate", byte[].class, int.class, int.class, int.class);
m = Deflater.class.getMethod("deflate", byte[].class, int.class,
int.class, int.class);
} catch (SecurityException e) {
} catch (NoSuchMethodException e) {
}
@ -44,9 +49,13 @@ public class ZLibOutputStream extends DeflaterOutputStream {
/**
* Create a new ZLib compatible output stream wrapping the given low level
* stream. ZLib compatiblity means we will send a zlib header.
* @param os OutputStream The underlying stream.
* @throws IOException In case of a lowlevel transfer problem.
* @throws NoSuchAlgorithmException In case of a {@link Deflater} error.
*
* @param os
* OutputStream The underlying stream.
* @throws IOException
* In case of a lowlevel transfer problem.
* @throws NoSuchAlgorithmException
* In case of a {@link Deflater} error.
*/
public ZLibOutputStream(OutputStream os) throws IOException,
NoSuchAlgorithmException {
@ -55,7 +64,9 @@ public class ZLibOutputStream extends DeflaterOutputStream {
/**
* Flush the given stream, preferring Java7 FLUSH_SYNC if available.
* @throws IOException In case of a lowlevel exception.
*
* @throws IOException
* In case of a lowlevel exception.
*/
@Override
public void flush() throws IOException {

View file

@ -20,7 +20,6 @@ public class Tag {
this.name = name;
}
public static Tag no(String text) {
return new Tag(NO, text);
}
@ -56,12 +55,14 @@ public class Tag {
}
public boolean isStart(String needle) {
if (needle==null) return false;
if (needle == null)
return false;
return (this.type == START) && (needle.equals(this.name));
}
public boolean isEnd(String needle) {
if (needle==null) return false;
if (needle == null)
return false;
return (this.type == END) && (needle.equals(this.name));
}

View file

@ -15,6 +15,7 @@ public class TagWriter {
private LinkedBlockingQueue<AbstractStanza> writeQueue = new LinkedBlockingQueue<AbstractStanza>();
private Thread asyncStanzaWriter = new Thread() {
private boolean shouldStop = false;
@Override
public void run() {
while (!shouldStop) {

View file

@ -7,13 +7,14 @@ import java.io.InputStreamReader;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import eu.siacs.conversations.Config;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.util.Log;
import android.util.Xml;
public class XmlReader {
private static final String LOGTAG = "xmppService";
private XmlPullParser parser;
private PowerManager.WakeLock wakeLock;
private InputStream is;
@ -21,9 +22,10 @@ public class XmlReader {
public XmlReader(WakeLock wakeLock) {
this.parser = Xml.newPullParser();
try {
this.parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES,true);
this.parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES,
true);
} catch (XmlPullParserException e) {
Log.d(LOGTAG,"error setting namespace feature on parser");
Log.d(Config.LOGTAG, "error setting namespace feature on parser");
}
this.wakeLock = wakeLock;
}
@ -60,15 +62,20 @@ public class XmlReader {
public Tag readTag() throws XmlPullParserException, IOException {
if (wakeLock.isHeld()) {
try { wakeLock.release();} catch (RuntimeException re) {}
try {
wakeLock.release();
} catch (RuntimeException re) {
}
}
try {
while(this.is != null && parser.next() != XmlPullParser.END_DOCUMENT) {
while (this.is != null
&& parser.next() != XmlPullParser.END_DOCUMENT) {
wakeLock.acquire();
if (parser.getEventType() == XmlPullParser.START_TAG) {
Tag tag = Tag.start(parser.getName());
for (int i = 0; i < parser.getAttributeCount(); ++i) {
tag.setAttribute(parser.getAttributeName(i), parser.getAttributeValue(i));
tag.setAttribute(parser.getAttributeName(i),
parser.getAttributeValue(i));
}
String xmlns = parser.getNamespace();
if (xmlns != null) {
@ -84,21 +91,28 @@ public class XmlReader {
}
}
if (wakeLock.isHeld()) {
try { wakeLock.release();} catch (RuntimeException re) {}
try {
wakeLock.release();
} catch (RuntimeException re) {
}
}
} catch (ArrayIndexOutOfBoundsException e) {
throw new IOException("xml parser mishandled ArrayIndexOufOfBounds", e);
throw new IOException(
"xml parser mishandled ArrayIndexOufOfBounds", e);
} catch (StringIndexOutOfBoundsException e) {
throw new IOException("xml parser mishandled StringIndexOufOfBounds", e);
throw new IOException(
"xml parser mishandled StringIndexOufOfBounds", e);
} catch (NullPointerException e) {
throw new IOException("xml parser mishandled NullPointerException", e);
throw new IOException("xml parser mishandled NullPointerException",
e);
} catch (IndexOutOfBoundsException e) {
throw new IOException("xml parser mishandled IndexOutOfBound", e);
}
return null;
}
public Element readElement(Tag currentTag) throws XmlPullParserException, IOException {
public Element readElement(Tag currentTag) throws XmlPullParserException,
IOException {
Element element = new Element(currentTag.getName());
element.setAttributes(currentTag.getAttributes());
Tag nextTag = this.readTag();

View file

@ -32,6 +32,7 @@ import android.os.PowerManager.WakeLock;
import android.os.SystemClock;
import android.util.Log;
import android.util.SparseArray;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.CryptoHelper;
@ -58,7 +59,6 @@ import eu.siacs.conversations.xmpp.stanzas.streammgmt.ResumePacket;
public class XmppConnection implements Runnable {
protected Account account;
private static final String LOGTAG = "xmppService";
private WakeLock wakeLock;
@ -109,8 +109,8 @@ public class XmppConnection implements Runnable {
this.mRandom = service.getRNG();
this.mMemorizingTrustManager = service.getMemorizingTrustManager();
this.account = account;
this.wakeLock = service.getPowerManager().newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
account.getJid());
this.wakeLock = service.getPowerManager().newWakeLock(
PowerManager.PARTIAL_WAKE_LOCK, account.getJid());
tagWriter = new TagWriter();
}
@ -133,7 +133,7 @@ public class XmppConnection implements Runnable {
}
protected void connect() {
Log.d(LOGTAG, account.getJid() + ": connecting");
Log.d(Config.LOGTAG, account.getJid() + ": connecting");
usingCompression = false;
lastConnect = SystemClock.elapsedRealtime();
lastPingSent = SystemClock.elapsedRealtime();
@ -147,7 +147,7 @@ public class XmppConnection implements Runnable {
this.changeStatus(Account.STATUS_CONNECTING);
Bundle namePort = DNSHelper.getSRVRecord(account.getServer());
if ("timeout".equals(namePort.getString("error"))) {
Log.d(LOGTAG, account.getJid() + ": dns timeout");
Log.d(Config.LOGTAG, account.getJid() + ": dns timeout");
this.changeStatus(Account.STATUS_OFFLINE);
return;
}
@ -156,13 +156,14 @@ public class XmppConnection implements Runnable {
int srvRecordPort = namePort.getInt("port");
if (srvRecordServer != null) {
if (srvIpServer != null) {
Log.d(LOGTAG, account.getJid() + ": using values from dns "
+ srvRecordServer + "[" + srvIpServer + "]:"
+ srvRecordPort);
Log.d(Config.LOGTAG, account.getJid()
+ ": using values from dns " + srvRecordServer
+ "[" + srvIpServer + "]:" + srvRecordPort);
socket = new Socket(srvIpServer, srvRecordPort);
} else {
Log.d(LOGTAG, account.getJid() + ": using values from dns "
+ srvRecordServer + ":" + srvRecordPort);
Log.d(Config.LOGTAG, account.getJid()
+ ": using values from dns " + srvRecordServer
+ ":" + srvRecordPort);
socket = new Socket(srvRecordServer, srvRecordPort);
}
} else {
@ -180,7 +181,8 @@ public class XmppConnection implements Runnable {
processStream(nextTag);
break;
} else {
Log.d(LOGTAG, "found unexpected tag: " + nextTag.getName());
Log.d(Config.LOGTAG,
"found unexpected tag: " + nextTag.getName());
return;
}
}
@ -190,27 +192,39 @@ public class XmppConnection implements Runnable {
} catch (UnknownHostException e) {
this.changeStatus(Account.STATUS_SERVER_NOT_FOUND);
if (wakeLock.isHeld()) {
try { wakeLock.release();} catch (RuntimeException re) {}
try {
wakeLock.release();
} catch (RuntimeException re) {
}
}
return;
} catch (IOException e) {
this.changeStatus(Account.STATUS_OFFLINE);
if (wakeLock.isHeld()) {
try { wakeLock.release();} catch (RuntimeException re) {}
try {
wakeLock.release();
} catch (RuntimeException re) {
}
}
return;
} catch (NoSuchAlgorithmException e) {
this.changeStatus(Account.STATUS_OFFLINE);
Log.d(LOGTAG, "compression exception " + e.getMessage());
Log.d(Config.LOGTAG, "compression exception " + e.getMessage());
if (wakeLock.isHeld()) {
try { wakeLock.release();} catch (RuntimeException re) {}
try {
wakeLock.release();
} catch (RuntimeException re) {
}
}
return;
} catch (XmlPullParserException e) {
this.changeStatus(Account.STATUS_OFFLINE);
Log.d(LOGTAG, "xml exception " + e.getMessage());
Log.d(Config.LOGTAG, "xml exception " + e.getMessage());
if (wakeLock.isHeld()) {
try { wakeLock.release();} catch (RuntimeException re) {}
try {
wakeLock.release();
} catch (RuntimeException re) {
}
}
return;
}
@ -235,7 +249,7 @@ public class XmppConnection implements Runnable {
} else if (nextTag.isStart("compressed")) {
switchOverToZLib(nextTag);
} else if (nextTag.isStart("success")) {
Log.d(LOGTAG, account.getJid() + ": logged in");
Log.d(Config.LOGTAG, account.getJid() + ": logged in");
tagReader.readTag();
tagReader.reset();
sendStartStream();
@ -256,11 +270,12 @@ public class XmppConnection implements Runnable {
Element enabled = tagReader.readElement(nextTag);
if ("true".equals(enabled.getAttribute("resume"))) {
this.streamId = enabled.getAttribute("id");
Log.d(LOGTAG, account.getJid() + ": stream managment("
+ smVersion + ") enabled (resumable)");
Log.d(Config.LOGTAG, account.getJid()
+ ": stream managment(" + smVersion
+ ") enabled (resumable)");
} else {
Log.d(LOGTAG, account.getJid() + ": stream managment("
+ smVersion + ") enabled");
Log.d(Config.LOGTAG, account.getJid()
+ ": stream managment(" + smVersion + ") enabled");
}
this.lastSessionStarted = SystemClock.elapsedRealtime();
this.stanzasReceived = 0;
@ -273,15 +288,18 @@ public class XmppConnection implements Runnable {
try {
int serverCount = Integer.parseInt(h);
if (serverCount != stanzasSent) {
Log.d(LOGTAG,account.getJid() + ": session resumed with lost packages");
Log.d(Config.LOGTAG, account.getJid()
+ ": session resumed with lost packages");
stanzasSent = serverCount;
} else {
Log.d(LOGTAG, account.getJid() + ": session resumed");
Log.d(Config.LOGTAG, account.getJid()
+ ": session resumed");
}
if (acknowledgedListener != null) {
for (int i = 0; i < messageReceipts.size(); ++i) {
if (serverCount >= messageReceipts.keyAt(i)) {
acknowledgedListener.onMessageAcknowledged(account, messageReceipts.valueAt(i));
acknowledgedListener.onMessageAcknowledged(
account, messageReceipts.valueAt(i));
}
}
}
@ -301,13 +319,14 @@ public class XmppConnection implements Runnable {
String msgId = this.messageReceipts.get(serverSequence);
if (msgId != null) {
if (this.acknowledgedListener != null) {
this.acknowledgedListener.onMessageAcknowledged(account, msgId);
this.acknowledgedListener.onMessageAcknowledged(
account, msgId);
}
this.messageReceipts.remove(serverSequence);
}
} else if (nextTag.isStart("failed")) {
tagReader.readElement(nextTag);
Log.d(LOGTAG, account.getJid() + ": resumption failed");
Log.d(Config.LOGTAG, account.getJid() + ": resumption failed");
streamId = null;
if (account.getStatus() != Account.STATUS_ONLINE) {
sendBindRequest();
@ -446,7 +465,7 @@ public class XmppConnection implements Runnable {
.setInputStream(new ZLibInputStream(tagReader.getInputStream()));
sendStartStream();
Log.d(LOGTAG, account.getJid() + ": compression enabled");
Log.d(Config.LOGTAG, account.getJid() + ": compression enabled");
usingCompression = true;
processStream(tagReader.readTag());
}
@ -462,23 +481,30 @@ public class XmppConnection implements Runnable {
tagReader.readTag();
try {
SSLContext sc = SSLContext.getInstance("TLS");
sc.init(null, new X509TrustManager[] { this.mMemorizingTrustManager }, mRandom);
sc.init(null,
new X509TrustManager[] { this.mMemorizingTrustManager },
mRandom);
SSLSocketFactory factory = sc.getSocketFactory();
HostnameVerifier verifier = this.mMemorizingTrustManager.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier());
HostnameVerifier verifier = this.mMemorizingTrustManager
.wrapHostnameVerifier(new org.apache.http.conn.ssl.StrictHostnameVerifier());
SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket,
socket.getInetAddress().getHostAddress(), socket.getPort(),
true);
if (verifier != null && !verifier.verify(account.getServer(), sslSocket.getSession())) {
Log.d(LOGTAG, account.getJid() + ": host mismatch in TLS connection");
if (verifier != null
&& !verifier.verify(account.getServer(),
sslSocket.getSession())) {
Log.d(Config.LOGTAG, account.getJid()
+ ": host mismatch in TLS connection");
sslSocket.close();
throw new IOException();
}
tagReader.setInputStream(sslSocket.getInputStream());
tagWriter.setOutputStream(sslSocket.getOutputStream());
sendStartStream();
Log.d(LOGTAG, account.getJid() + ": TLS connection established");
Log.d(Config.LOGTAG, account.getJid()
+ ": TLS connection established");
processStream(tagReader.readTag());
sslSocket.close();
} catch (NoSuchAlgorithmException e1) {
@ -604,7 +630,7 @@ public class XmppConnection implements Runnable {
changeStatus(Account.STATUS_REGISTRATION_CONFLICT);
} else {
changeStatus(Account.STATUS_REGISTRATION_FAILED);
Log.d(LOGTAG, packet.toString());
Log.d(Config.LOGTAG, packet.toString());
}
disconnect(true);
}
@ -612,7 +638,7 @@ public class XmppConnection implements Runnable {
} else {
changeStatus(Account.STATUS_REGISTRATION_FAILED);
disconnect(true);
Log.d(LOGTAG, account.getJid()
Log.d(Config.LOGTAG, account.getJid()
+ ": could not register. instructions are"
+ instructions.getContent());
}
@ -638,7 +664,8 @@ public class XmppConnection implements Runnable {
tagWriter.writeStanzaAsync(enable);
stanzasSent = 0;
messageReceipts.clear();
} else if (streamFeatures.hasChild("sm", "urn:xmpp:sm:2")) {
} else if (streamFeatures.hasChild("sm",
"urn:xmpp:sm:2")) {
smVersion = 2;
EnablePacket enable = new EnablePacket(smVersion);
tagWriter.writeStanzaAsync(enable);
@ -660,7 +687,8 @@ public class XmppConnection implements Runnable {
}
});
if (this.streamFeatures.hasChild("session")) {
Log.d(LOGTAG, account.getJid() + ": sending deprecated session");
Log.d(Config.LOGTAG, account.getJid()
+ ": sending deprecated session");
IqPacket startSession = new IqPacket(IqPacket.TYPE_SET);
startSession.addChild("session",
"urn:ietf:params:xml:ns:xmpp-session");
@ -725,10 +753,10 @@ public class XmppConnection implements Runnable {
@Override
public void onIqPacketReceived(Account account, IqPacket packet) {
if (!packet.hasChild("error")) {
Log.d(LOGTAG, account.getJid()
Log.d(Config.LOGTAG, account.getJid()
+ ": successfully enabled carbons");
} else {
Log.d(LOGTAG, account.getJid()
Log.d(Config.LOGTAG, account.getJid()
+ ": error enableing carbons " + packet.toString());
}
}
@ -736,7 +764,7 @@ public class XmppConnection implements Runnable {
}
private void processStreamError(Tag currentTag) {
Log.d(LOGTAG, "processStreamError");
Log.d(Config.LOGTAG, "processStreamError");
}
private void sendStartStream() throws IOException {
@ -781,12 +809,15 @@ public class XmppConnection implements Runnable {
private synchronized void sendPacket(final AbstractStanza packet,
PacketReceived callback) {
if (packet.getName().equals("iq") || packet.getName().equals("message") || packet.getName().equals("presence")) {
if (packet.getName().equals("iq") || packet.getName().equals("message")
|| packet.getName().equals("presence")) {
++stanzasSent;
}
tagWriter.writeStanzaAsync(packet);
if (packet instanceof MessagePacket && packet.getId() != null && this.streamId != null) {
Log.d(LOGTAG,"request delivery report for stanza "+stanzasSent);
if (packet instanceof MessagePacket && packet.getId() != null
&& this.streamId != null) {
Log.d(Config.LOGTAG, "request delivery report for stanza "
+ stanzasSent);
this.messageReceipts.put(stanzasSent, packet.getId());
tagWriter.writeStanzaAsync(new RequestPacket(this.smVersion));
}
@ -844,7 +875,7 @@ public class XmppConnection implements Runnable {
public void disconnect(boolean force) {
changeStatus(Account.STATUS_OFFLINE);
Log.d(LOGTAG, "disconnecting");
Log.d(Config.LOGTAG, "disconnecting");
try {
if (force) {
socket.close();
@ -858,20 +889,21 @@ public class XmppConnection implements Runnable {
tagWriter.finish();
try {
while (!tagWriter.finished()) {
Log.d(LOGTAG, "not yet finished");
Log.d(Config.LOGTAG, "not yet finished");
Thread.sleep(100);
}
tagWriter.writeTag(Tag.end("stream:stream"));
} catch (IOException e) {
Log.d(LOGTAG, "io exception during disconnect");
Log.d(Config.LOGTAG,
"io exception during disconnect");
} catch (InterruptedException e) {
Log.d(LOGTAG, "interrupted");
Log.d(Config.LOGTAG, "interrupted");
}
}
}
}).start();
} catch (IOException e) {
Log.d(LOGTAG, "io exception during disconnect");
Log.d(Config.LOGTAG, "io exception during disconnect");
}
}
@ -917,6 +949,7 @@ public class XmppConnection implements Runnable {
public class Features {
XmppConnection connection;
public Features(XmppConnection connection) {
this.connection = connection;
}
@ -944,12 +977,14 @@ public class XmppConnection implements Runnable {
if (connection.streamFeatures == null) {
return false;
} else {
return connection.streamFeatures.hasChild("csi","urn:xmpp:csi:0");
return connection.streamFeatures.hasChild("csi",
"urn:xmpp:csi:0");
}
}
public boolean pubsub() {
return hasDiscoFeature(account.getServer(), "http://jabber.org/protocol/pubsub#publish");
return hasDiscoFeature(account.getServer(),
"http://jabber.org/protocol/pubsub#publish");
}
public boolean rosterVersioning() {
@ -961,7 +996,8 @@ public class XmppConnection implements Runnable {
}
public boolean streamhost() {
return connection.findDiscoItemByFeature("http://jabber.org/protocol/bytestreams") != null;
return connection
.findDiscoItemByFeature("http://jabber.org/protocol/bytestreams") != null;
}
public boolean compression() {

View file

@ -80,7 +80,8 @@ public class JingleCandidate {
}
public boolean equalValues(JingleCandidate other) {
return other.getHost().equals(this.getHost())&&(other.getPort()==this.getPort());
return other.getHost().equals(this.getHost())
&& (other.getPort() == this.getPort());
}
public boolean isOurs() {
@ -100,12 +101,15 @@ public class JingleCandidate {
}
public static JingleCandidate parse(Element candidate) {
JingleCandidate parsedCandidate = new JingleCandidate(candidate.getAttribute("cid"), false);
JingleCandidate parsedCandidate = new JingleCandidate(
candidate.getAttribute("cid"), false);
parsedCandidate.setHost(candidate.getAttribute("host"));
parsedCandidate.setJid(candidate.getAttribute("jid"));
parsedCandidate.setType(candidate.getAttribute("type"));
parsedCandidate.setPriority(Integer.parseInt(candidate.getAttribute("priority")));
parsedCandidate.setPort(Integer.parseInt(candidate.getAttribute("port")));
parsedCandidate.setPriority(Integer.parseInt(candidate
.getAttribute("priority")));
parsedCandidate
.setPort(Integer.parseInt(candidate.getAttribute("port")));
return parsedCandidate;
}
@ -133,6 +137,7 @@ public class JingleCandidate {
}
public String toString() {
return this.getHost()+":"+this.getPort()+" (prio="+this.getPriority()+")";
return this.getHost() + ":" + this.getPort() + " (prio="
+ this.getPriority() + ")";
}
}

View file

@ -12,6 +12,7 @@ import android.content.Intent;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.util.Log;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
@ -100,10 +101,11 @@ public class JingleConnection {
mXmppConnectionService.markMessage(message,
Message.STATUS_RECEIVED);
}
Log.d("xmppService",
Log.d(Config.LOGTAG,
"sucessfully transmitted file:" + file.getAbsolutePath());
if (message.getEncryption() != Message.ENCRYPTION_PGP) {
Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
Intent intent = new Intent(
Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
intent.setData(Uri.fromFile(file));
mXmppConnectionService.sendBroadcast(intent);
}
@ -121,17 +123,17 @@ public class JingleConnection {
@Override
public void success() {
if (initiator.equals(account.getFullJid())) {
Log.d("xmppService", "we were initiating. sending file");
Log.d(Config.LOGTAG, "we were initiating. sending file");
transport.send(file, onFileTransmissionSatusChanged);
} else {
transport.receive(file, onFileTransmissionSatusChanged);
Log.d("xmppService", "we were responding. receiving file");
Log.d(Config.LOGTAG, "we were responding. receiving file");
}
}
@Override
public void failed() {
Log.d("xmppService", "proxy activation failed");
Log.d(Config.LOGTAG, "proxy activation failed");
}
};
@ -177,13 +179,13 @@ public class JingleConnection {
returnResult = this.receiveFallbackToIbb(packet);
} else {
returnResult = false;
Log.d("xmppService", "trying to fallback to something unknown"
Log.d(Config.LOGTAG, "trying to fallback to something unknown"
+ packet.toString());
}
} else if (packet.isAction("transport-accept")) {
returnResult = this.receiveTransportAccept(packet);
} else {
Log.d("xmppService", "packet arrived in connection. action was "
Log.d(Config.LOGTAG, "packet arrived in connection. action was "
+ packet.getAction());
returnResult = false;
}
@ -224,14 +226,14 @@ public class JingleConnection {
@Override
public void failed() {
Log.d("xmppService",
Log.d(Config.LOGTAG,
"connection to our own primary candidete failed");
sendInitRequest();
}
@Override
public void established() {
Log.d("xmppService",
Log.d(Config.LOGTAG,
"succesfully connected to our own primary candidate");
mergeCandidate(candidate);
sendInitRequest();
@ -239,7 +241,7 @@ public class JingleConnection {
});
mergeCandidate(candidate);
} else {
Log.d("xmppService",
Log.d(Config.LOGTAG,
"no primary candidate of our own was found");
sendInitRequest();
}
@ -288,7 +290,7 @@ public class JingleConnection {
filename[filename.length - 2])) {
supportedFile = true;
if (filename[filename.length - 1].equals("otr")) {
Log.d("xmppService", "receiving otr file");
Log.d(Config.LOGTAG, "receiving otr file");
this.message
.setEncryption(Message.ENCRYPTION_OTR);
} else {
@ -304,13 +306,13 @@ public class JingleConnection {
conversation.getMessages().add(message);
if (size <= this.mJingleConnectionManager
.getAutoAcceptFileSize()) {
Log.d("xmppService", "auto accepting file from "
Log.d(Config.LOGTAG, "auto accepting file from "
+ packet.getFrom());
this.acceptedAutomatically = true;
this.sendAccept();
} else {
message.markUnread();
Log.d("xmppService",
Log.d(Config.LOGTAG,
"not auto accepting new file offer with size: "
+ size
+ " allowed size:"
@ -400,7 +402,7 @@ public class JingleConnection {
@Override
public void failed() {
Log.d("xmppService",
Log.d(Config.LOGTAG,
"connection to our own primary candidate failed");
content.socks5transport().setChildren(
getCandidatesAsElements());
@ -411,7 +413,7 @@ public class JingleConnection {
@Override
public void established() {
Log.d("xmppService",
Log.d(Config.LOGTAG,
"connected to primary candidate");
mergeCandidate(candidate);
content.socks5transport().setChildren(
@ -422,7 +424,7 @@ public class JingleConnection {
}
});
} else {
Log.d("xmppService",
Log.d(Config.LOGTAG,
"did not find a primary candidate for ourself");
content.socks5transport().setChildren(
getCandidatesAsElements());
@ -446,7 +448,7 @@ public class JingleConnection {
}
private void sendJinglePacket(JinglePacket packet) {
// Log.d("xmppService",packet.toString());
// Log.d(Config.LOGTAG,packet.toString());
account.getXmppConnection().sendIqPacket(packet, responseListener);
}
@ -470,14 +472,14 @@ public class JingleConnection {
} else {
String cid = content.socks5transport()
.findChild("activated").getAttribute("cid");
Log.d("xmppService", "received proxy activated (" + cid
Log.d(Config.LOGTAG, "received proxy activated (" + cid
+ ")prior to choosing our own transport");
JingleSocks5Transport connection = this.connections
.get(cid);
if (connection != null) {
connection.setActivated(true);
} else {
Log.d("xmppService", "activated connection not found");
Log.d(Config.LOGTAG, "activated connection not found");
this.sendCancel();
this.cancel();
}
@ -487,7 +489,7 @@ public class JingleConnection {
onProxyActivated.failed();
return true;
} else if (content.socks5transport().hasChild("candidate-error")) {
Log.d("xmppService", "received candidate error");
Log.d(Config.LOGTAG, "received candidate error");
this.receivedCandidate = true;
if ((status == STATUS_ACCEPTED) && (this.sentCandidate)) {
this.connect();
@ -497,14 +499,14 @@ public class JingleConnection {
String cid = content.socks5transport()
.findChild("candidate-used").getAttribute("cid");
if (cid != null) {
Log.d("xmppService", "candidate used by counterpart:" + cid);
Log.d(Config.LOGTAG, "candidate used by counterpart:" + cid);
JingleCandidate candidate = getCandidate(cid);
candidate.flagAsUsedByCounterpart();
this.receivedCandidate = true;
if ((status == STATUS_ACCEPTED) && (this.sentCandidate)) {
this.connect();
} else {
Log.d("xmppService",
Log.d(Config.LOGTAG,
"ignoring because file is already in transmission or we havent sent our candidate yet");
}
return true;
@ -523,7 +525,7 @@ public class JingleConnection {
final JingleSocks5Transport connection = chooseConnection();
this.transport = connection;
if (connection == null) {
Log.d("xmppService", "could not find suitable candidate");
Log.d(Config.LOGTAG, "could not find suitable candidate");
this.disconnect();
if (this.initiator.equals(account.getFullJid())) {
this.sendFallbackToIbb();
@ -532,7 +534,7 @@ public class JingleConnection {
this.status = STATUS_TRANSMITTING;
if (connection.needsActivation()) {
if (connection.getCandidate().isOurs()) {
Log.d("xmppService", "candidate "
Log.d(Config.LOGTAG, "candidate "
+ connection.getCandidate().getCid()
+ " was our proxy. going to activate");
IqPacket activation = new IqPacket(IqPacket.TYPE_SET);
@ -557,17 +559,17 @@ public class JingleConnection {
}
});
} else {
Log.d("xmppService",
Log.d(Config.LOGTAG,
"candidate "
+ connection.getCandidate().getCid()
+ " was a proxy. waiting for other party to activate");
}
} else {
if (initiator.equals(account.getFullJid())) {
Log.d("xmppService", "we were initiating. sending file");
Log.d(Config.LOGTAG, "we were initiating. sending file");
connection.send(file, onFileTransmissionSatusChanged);
} else {
Log.d("xmppService", "we were responding. receiving file");
Log.d(Config.LOGTAG, "we were responding. receiving file");
connection.receive(file, onFileTransmissionSatusChanged);
}
}
@ -579,11 +581,11 @@ public class JingleConnection {
for (Entry<String, JingleSocks5Transport> cursor : connections
.entrySet()) {
JingleSocks5Transport currentConnection = cursor.getValue();
// Log.d("xmppService","comparing candidate: "+currentConnection.getCandidate().toString());
// Log.d(Config.LOGTAG,"comparing candidate: "+currentConnection.getCandidate().toString());
if (currentConnection.isEstablished()
&& (currentConnection.getCandidate().isUsedByCounterpart() || (!currentConnection
.getCandidate().isOurs()))) {
// Log.d("xmppService","is usable");
// Log.d(Config.LOGTAG,"is usable");
if (connection == null) {
connection = currentConnection;
} else {
@ -592,7 +594,7 @@ public class JingleConnection {
connection = currentConnection;
} else if (connection.getCandidate().getPriority() == currentConnection
.getCandidate().getPriority()) {
// Log.d("xmppService","found two candidates with same priority");
// Log.d(Config.LOGTAG,"found two candidates with same priority");
if (initiator.equals(account.getFullJid())) {
if (currentConnection.getCandidate().isOurs()) {
connection = currentConnection;
@ -672,7 +674,7 @@ public class JingleConnection {
@Override
public void failed() {
Log.d("xmppService", "ibb open failed");
Log.d(Config.LOGTAG, "ibb open failed");
}
@Override
@ -742,7 +744,7 @@ public class JingleConnection {
@Override
public void failed() {
Log.d("xmppService",
Log.d(Config.LOGTAG,
"connection failed with " + candidate.getHost() + ":"
+ candidate.getPort());
connectNextCandidate();
@ -750,7 +752,7 @@ public class JingleConnection {
@Override
public void established() {
Log.d("xmppService",
Log.d(Config.LOGTAG,
"established connection with " + candidate.getHost()
+ ":" + candidate.getPort());
sendCandidateUsed(candidate.getCid());
@ -874,7 +876,7 @@ public class JingleConnection {
}
}).start();
} else {
Log.d("xmppService", "status (" + status + ") was not ok");
Log.d(Config.LOGTAG, "status (" + status + ") was not ok");
}
}
}

View file

@ -7,6 +7,7 @@ import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import android.annotation.SuppressLint;
import android.util.Log;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.services.XmppConnectionService;
@ -37,14 +38,16 @@ public class JingleConnectionManager {
connections.add(connection);
} else {
for (JingleConnection connection : connections) {
if (connection.getAccountJid().equals(account.getFullJid()) && connection
.getSessionId().equals(packet.getSessionId()) && connection
.getCounterPart().equals(packet.getFrom())) {
if (connection.getAccountJid().equals(account.getFullJid())
&& connection.getSessionId().equals(
packet.getSessionId())
&& connection.getCounterPart().equals(packet.getFrom())) {
connection.deliverPacket(packet);
return;
}
}
account.getXmppConnection().sendIqPacket(packet.generateRespone(IqPacket.TYPE_ERROR), null);
account.getXmppConnection().sendIqPacket(
packet.generateRespone(IqPacket.TYPE_ERROR), null);
}
}
@ -90,10 +93,15 @@ public class JingleConnectionManager {
.findChild("streamhost",
"http://jabber.org/protocol/bytestreams");
if (streamhost != null) {
JingleCandidate candidate = new JingleCandidate(nextRandomId(),true);
candidate.setHost(streamhost.getAttribute("host"));
candidate.setPort(Integer.parseInt(streamhost.getAttribute("port")));
candidate.setType(JingleCandidate.TYPE_PROXY);
JingleCandidate candidate = new JingleCandidate(
nextRandomId(), true);
candidate.setHost(streamhost
.getAttribute("host"));
candidate.setPort(Integer
.parseInt(streamhost
.getAttribute("port")));
candidate
.setType(JingleCandidate.TYPE_PROXY);
candidate.setJid(proxy);
candidate.setPriority(655360 + 65535);
primaryCandidates.put(account.getJid(),
@ -121,7 +129,8 @@ public class JingleConnectionManager {
}
public long getAutoAcceptFileSize() {
String config = this.xmppConnectionService.getPreferences().getString("auto_accept_file_size", "524288");
String config = this.xmppConnectionService.getPreferences().getString(
"auto_accept_file_size", "524288");
try {
return Long.parseLong(config);
} catch (NumberFormatException e) {
@ -133,10 +142,12 @@ public class JingleConnectionManager {
String sid = null;
Element payload = null;
if (packet.hasChild("open", "http://jabber.org/protocol/ibb")) {
payload = packet.findChild("open","http://jabber.org/protocol/ibb");
payload = packet
.findChild("open", "http://jabber.org/protocol/ibb");
sid = payload.getAttribute("sid");
} else if (packet.hasChild("data", "http://jabber.org/protocol/ibb")) {
payload = packet.findChild("data","http://jabber.org/protocol/ibb");
payload = packet
.findChild("data", "http://jabber.org/protocol/ibb");
sid = payload.getAttribute("sid");
}
if (sid != null) {
@ -150,9 +161,10 @@ public class JingleConnectionManager {
}
}
}
Log.d("xmppService","couldnt deliver payload: "+payload.toString());
Log.d(Config.LOGTAG,
"couldnt deliver payload: " + payload.toString());
} else {
Log.d("xmppService","no sid found in incomming ibb packet");
Log.d(Config.LOGTAG, "no sid found in incomming ibb packet");
}
}

View file

@ -5,6 +5,7 @@ import java.security.Key;
import javax.crypto.spec.SecretKeySpec;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.utils.CryptoHelper;
import android.util.Log;
@ -54,9 +55,11 @@ public class JingleFile extends File {
System.arraycopy(key, 0, secretKey, 0, 16);
this.aeskey = new SecretKeySpec(secretKey, "AES");
} else {
Log.d("xmppService","weird key");
Log.d(Config.LOGTAG, "weird key");
}
Log.d("xmppService","using aes key "+CryptoHelper.bytesToHex(this.aeskey.getEncoded()));
Log.d(Config.LOGTAG,
"using aes key "
+ CryptoHelper.bytesToHex(this.aeskey.getEncoded()));
}
public Key getKey() {

View file

@ -77,7 +77,8 @@ public class JingleInbandTransport extends JingleTransport {
}
@Override
public void receive(JingleFile file, OnFileTransmissionStatusChanged callback) {
public void receive(JingleFile file,
OnFileTransmissionStatusChanged callback) {
this.onFileTransmissionStatusChanged = callback;
this.file = file;
try {
@ -150,7 +151,8 @@ public class JingleInbandTransport extends JingleTransport {
try {
byte[] buffer = Base64.decode(data, Base64.NO_WRAP);
if (this.remainingSize < buffer.length) {
buffer = Arrays.copyOfRange(buffer, 0, (int) this.remainingSize);
buffer = Arrays
.copyOfRange(buffer, 0, (int) this.remainingSize);
}
this.remainingSize -= buffer.length;

View file

@ -21,7 +21,8 @@ public class JingleSocks5Transport extends JingleTransport {
private boolean activated = false;
protected Socket socket;
public JingleSocks5Transport(JingleConnection jingleConnection, JingleCandidate candidate) {
public JingleSocks5Transport(JingleConnection jingleConnection,
JingleCandidate candidate) {
this.candidate = candidate;
try {
MessageDigest mDigest = MessageDigest.getInstance("SHA-1");
@ -48,7 +49,8 @@ public class JingleSocks5Transport extends JingleTransport {
@Override
public void run() {
try {
socket = new Socket(candidate.getHost(), candidate.getPort());
socket = new Socket(candidate.getHost(),
candidate.getPort());
inputStream = socket.getInputStream();
outputStream = socket.getOutputStream();
byte[] login = { 0x05, 0x01, 0x00 };
@ -57,8 +59,9 @@ public class JingleSocks5Transport extends JingleTransport {
outputStream.write(login);
inputStream.read(reply);
if (Arrays.equals(reply, expectedReply)) {
String connect = "" + '\u0005' + '\u0001' + '\u0000' + '\u0003'
+ '\u0028' + destination + '\u0000' + '\u0000';
String connect = "" + '\u0005' + '\u0001' + '\u0000'
+ '\u0003' + '\u0028' + destination + '\u0000'
+ '\u0000';
outputStream.write(connect.getBytes());
byte[] result = new byte[2];
inputStream.read(result);
@ -83,7 +86,8 @@ public class JingleSocks5Transport extends JingleTransport {
}
public void send(final JingleFile file, final OnFileTransmissionStatusChanged callback) {
public void send(final JingleFile file,
final OnFileTransmissionStatusChanged callback) {
new Thread(new Runnable() {
@Override
@ -128,7 +132,8 @@ public class JingleSocks5Transport extends JingleTransport {
}
public void receive(final JingleFile file, final OnFileTransmissionStatusChanged callback) {
public void receive(final JingleFile file,
final OnFileTransmissionStatusChanged callback) {
new Thread(new Runnable() {
@Override

View file

@ -15,15 +15,24 @@ import javax.crypto.CipherInputStream;
import javax.crypto.NoSuchPaddingException;
import javax.crypto.spec.IvParameterSpec;
import eu.siacs.conversations.Config;
import android.util.Log;
public abstract class JingleTransport {
public abstract void connect(final OnTransportConnected callback);
public abstract void receive(final JingleFile file, final OnFileTransmissionStatusChanged callback);
public abstract void send(final JingleFile file, final OnFileTransmissionStatusChanged callback);
private byte[] iv = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0xf};
protected InputStream getInputStream(JingleFile file) throws FileNotFoundException {
public abstract void receive(final JingleFile file,
final OnFileTransmissionStatusChanged callback);
public abstract void send(final JingleFile file,
final OnFileTransmissionStatusChanged callback);
private byte[] iv = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xf };
protected InputStream getInputStream(JingleFile file)
throws FileNotFoundException {
if (file.getKey() == null) {
return new FileInputStream(file);
} else {
@ -31,25 +40,26 @@ public abstract class JingleTransport {
IvParameterSpec ips = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.ENCRYPT_MODE, file.getKey(), ips);
Log.d("xmppService","opening encrypted input stream");
Log.d(Config.LOGTAG, "opening encrypted input stream");
return new CipherInputStream(new FileInputStream(file), cipher);
} catch (NoSuchAlgorithmException e) {
Log.d("xmppService","no such algo: "+e.getMessage());
Log.d(Config.LOGTAG, "no such algo: " + e.getMessage());
return null;
} catch (NoSuchPaddingException e) {
Log.d("xmppService","no such padding: "+e.getMessage());
Log.d(Config.LOGTAG, "no such padding: " + e.getMessage());
return null;
} catch (InvalidKeyException e) {
Log.d("xmppService","invalid key: "+e.getMessage());
Log.d(Config.LOGTAG, "invalid key: " + e.getMessage());
return null;
} catch (InvalidAlgorithmParameterException e) {
Log.d("xmppService","invavid iv:"+e.getMessage());
Log.d(Config.LOGTAG, "invavid iv:" + e.getMessage());
return null;
}
}
}
protected OutputStream getOutputStream(JingleFile file) throws FileNotFoundException {
protected OutputStream getOutputStream(JingleFile file)
throws FileNotFoundException {
if (file.getKey() == null) {
return new FileOutputStream(file);
} else {
@ -57,19 +67,20 @@ public abstract class JingleTransport {
IvParameterSpec ips = new IvParameterSpec(iv);
Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
cipher.init(Cipher.DECRYPT_MODE, file.getKey(), ips);
Log.d("xmppService","opening encrypted output stream");
return new CipherOutputStream(new FileOutputStream(file), cipher);
Log.d(Config.LOGTAG, "opening encrypted output stream");
return new CipherOutputStream(new FileOutputStream(file),
cipher);
} catch (NoSuchAlgorithmException e) {
Log.d("xmppService","no such algo: "+e.getMessage());
Log.d(Config.LOGTAG, "no such algo: " + e.getMessage());
return null;
} catch (NoSuchPaddingException e) {
Log.d("xmppService","no such padding: "+e.getMessage());
Log.d(Config.LOGTAG, "no such padding: " + e.getMessage());
return null;
} catch (InvalidKeyException e) {
Log.d("xmppService","invalid key: "+e.getMessage());
Log.d(Config.LOGTAG, "invalid key: " + e.getMessage());
return null;
} catch (InvalidAlgorithmParameterException e) {
Log.d("xmppService","invavid iv:"+e.getMessage());
Log.d(Config.LOGTAG, "invavid iv:" + e.getMessage());
return null;
}
}

View file

@ -2,5 +2,6 @@ package eu.siacs.conversations.xmpp.jingle;
public interface OnFileTransmissionStatusChanged {
public void onFileTransmitted(JingleFile file);
public void onFileTransferAborted();
}

View file

@ -1,5 +1,6 @@
package eu.siacs.conversations.xmpp.jingle;
public interface OnPrimaryCandidateFound {
public void onPrimaryCandidateFound(boolean success, JingleCandidate canditate);
public void onPrimaryCandidateFound(boolean success,
JingleCandidate canditate);
}

View file

@ -2,5 +2,6 @@ package eu.siacs.conversations.xmpp.jingle;
public interface OnTransportConnected {
public void failed();
public void established();
}

View file

@ -26,7 +26,8 @@ public class Content extends Element {
}
public void setFileOffer(JingleFile actualFile, boolean otr) {
Element description = this.addChild("description", "urn:xmpp:jingle:apps:file-transfer:3");
Element description = this.addChild("description",
"urn:xmpp:jingle:apps:file-transfer:3");
Element offer = description.addChild("offer");
Element file = offer.addChild("file");
file.addChild("size").setContent("" + actualFile.getSize());
@ -38,7 +39,8 @@ public class Content extends Element {
}
public Element getFileOffer() {
Element description = this.findChild("description", "urn:xmpp:jingle:apps:file-transfer:3");
Element description = this.findChild("description",
"urn:xmpp:jingle:apps:file-transfer:3");
if (description == null) {
return null;
}
@ -50,9 +52,11 @@ public class Content extends Element {
}
public void setFileOffer(Element fileOffer) {
Element description = this.findChild("description", "urn:xmpp:jingle:apps:file-transfer:3");
Element description = this.findChild("description",
"urn:xmpp:jingle:apps:file-transfer:3");
if (description == null) {
description = this.addChild("description", "urn:xmpp:jingle:apps:file-transfer:3");
description = this.addChild("description",
"urn:xmpp:jingle:apps:file-transfer:3");
}
description.addChild(fileOffer);
}
@ -67,18 +71,22 @@ public class Content extends Element {
}
public Element socks5transport() {
Element transport = this.findChild("transport", "urn:xmpp:jingle:transports:s5b:1");
Element transport = this.findChild("transport",
"urn:xmpp:jingle:transports:s5b:1");
if (transport == null) {
transport = this.addChild("transport", "urn:xmpp:jingle:transports:s5b:1");
transport = this.addChild("transport",
"urn:xmpp:jingle:transports:s5b:1");
transport.setAttribute("sid", this.transportId);
}
return transport;
}
public Element ibbTransport() {
Element transport = this.findChild("transport", "urn:xmpp:jingle:transports:ibb:1");
Element transport = this.findChild("transport",
"urn:xmpp:jingle:transports:ibb:1");
if (transport == null) {
transport = this.addChild("transport", "urn:xmpp:jingle:transports:ibb:1");
transport = this.addChild("transport",
"urn:xmpp:jingle:transports:ibb:1");
transport.setAttribute("sid", this.transportId);
}
return transport;

View file

@ -11,9 +11,11 @@ public class Avatar {
public int width;
public long size;
public String owner;
public byte[] getImageAsBytes() {
return Base64.decode(image, Base64.DEFAULT);
}
public String getFilename() {
if (type == null) {
return sha1sum;
@ -40,7 +42,8 @@ public class Avatar {
return null;
}
for (Element child : metadata.getChildren()) {
if (child.getName().equals("info") && primaryId.equals(child.getAttribute("id"))) {
if (child.getName().equals("info")
&& primaryId.equals(child.getAttribute("id"))) {
Avatar avatar = new Avatar();
String height = child.getAttribute("height");
String width = child.getAttribute("width");

View file

@ -2,7 +2,6 @@ package eu.siacs.conversations.xmpp.stanzas;
import eu.siacs.conversations.xml.Element;
public class IqPacket extends AbstractStanza {
public static final int TYPE_ERROR = -1;

View file

@ -1,6 +1,5 @@
package eu.siacs.conversations.xmpp.stanzas;
public class PresencePacket extends AbstractStanza {
public PresencePacket() {