fixed problems with sha sum calculation on avatar write. delete avatars with non matching sha sum

iNPUTmice created

Change summary

res/values/strings.xml                                         |  1 
src/eu/siacs/conversations/persistance/FileBackend.java        | 35 ++-
src/eu/siacs/conversations/services/XmppConnectionService.java | 17 +
src/eu/siacs/conversations/ui/adapter/MessageAdapter.java      | 10 
4 files changed, 43 insertions(+), 20 deletions(-)

Detailed changes

res/values/strings.xml 🔗

@@ -274,4 +274,5 @@
     <string name="publishing">Publishing&#8230;</string>
     <string name="error_publish_avatar_server_reject">The server rejected your publication</string>
     <string name="error_publish_avatar_converting">Something went wrong while converting your picture</string>
+    <string name="error_saving_avatar">Could not save avatar to disk</string>
 </resources>

src/eu/siacs/conversations/persistance/FileBackend.java 🔗

@@ -1,6 +1,5 @@
 package eu.siacs.conversations.persistance;
 
-import java.io.ByteArrayInputStream;
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
@@ -239,12 +238,18 @@ public class FileBackend {
 			Base64OutputStream mBase64OutputSttream = new Base64OutputStream(mByteArrayOutputStream, Base64.DEFAULT);
 			MessageDigest digest = MessageDigest.getInstance("SHA-1");
 			DigestOutputStream mDigestOutputStream = new DigestOutputStream(mBase64OutputSttream, digest);
-			bm.compress(format, 75, mDigestOutputStream);
+			if (!bm.compress(format, 75, mDigestOutputStream)) {
+				return null;
+			}
+			mDigestOutputStream.flush();
+			mDigestOutputStream.close();
 			avatar.sha1sum = CryptoHelper.bytesToHex(digest.digest());
 			avatar.image = new String(mByteArrayOutputStream.toByteArray());
 			return avatar;
 		} catch (NoSuchAlgorithmException e) {
 			return null;
+		} catch (IOException e) {
+			return null;
 		}
 	}
 	
@@ -253,26 +258,38 @@ public class FileBackend {
 		return file.exists();
 	}
 	
-	public void save(Avatar avatar) {
-		File file = new File(getAvatarPath(context, avatar.getFilename()));
+	public boolean save(Avatar avatar) {
+		if (isAvatarCached(avatar)) {
+			return true;
+		}
+		String filename = getAvatarPath(context, avatar.getFilename());
+		File file = new File(filename+".tmp");
 		file.getParentFile().mkdirs();
-		Log.d("xmppService",file.getAbsolutePath());
 		try {
 			file.createNewFile();
 			FileOutputStream mFileOutputStream = new FileOutputStream(file);
 			MessageDigest digest = MessageDigest.getInstance("SHA-1");
+			digest.reset();
 			DigestOutputStream mDigestOutputStream = new DigestOutputStream(mFileOutputStream, digest);
 			mDigestOutputStream.write(avatar.getImageAsBytes());
 			mDigestOutputStream.flush();
 			mDigestOutputStream.close();
 			avatar.size = file.length();
+			String sha1sum = CryptoHelper.bytesToHex(digest.digest());
+			if (sha1sum.equals(avatar.sha1sum)) {
+				file.renameTo(new File(filename));
+				return true;
+			} else {
+				Log.d("xmppService","sha1sum mismatch for "+avatar.owner);
+				file.delete();
+				return false;
+			}
 		} catch (FileNotFoundException e) {
-			
+			return false;
 		} catch (IOException e) {
-			Log.d("xmppService",e.getMessage());
+			return false;
 		} catch (NoSuchAlgorithmException e) {
-			// TODO Auto-generated catch block
-			e.printStackTrace();
+			return false;
 		}
 	}
 	

src/eu/siacs/conversations/services/XmppConnectionService.java 🔗

@@ -1201,7 +1201,10 @@ public class XmppConnectionService extends Service {
 			} else if (format.equals(Bitmap.CompressFormat.PNG)) {
 				avatar.type = "image/png";
 			}
-			getFileBackend().save(avatar);
+			if (!getFileBackend().save(avatar)) {
+				callback.error(R.string.error_saving_avatar, avatar);
+				return;
+			}
 			IqPacket packet = this.mIqGenerator.publishAvatar(avatar);
 			this.sendIqPacket(account, packet, new OnIqPacketReceived() {
 				
@@ -1232,6 +1235,7 @@ public class XmppConnectionService extends Service {
 	}
 	
 	public void fetchAvatar(Account account, final Avatar avatar) {
+		Log.d(LOGTAG,account.getJid()+": retrieving avatar for "+avatar.owner);
 		IqPacket packet = this.mIqGenerator.retrieveAvatar(avatar);
 		sendIqPacket(account, packet, new OnIqPacketReceived() {
 			
@@ -1239,9 +1243,14 @@ public class XmppConnectionService extends Service {
 			public void onIqPacketReceived(Account account, IqPacket result) {
 				avatar.image = mIqParser.avatarData(result);
 				if (avatar.image!=null) {
-					getFileBackend().save(avatar);
-					Contact contact = account.getRoster().getContact(avatar.owner);
-					contact.setAvatar(avatar.getFilename());
+					if (getFileBackend().save(avatar)) {
+						if (account.getJid().equals(avatar.owner)) {
+							account.setAvatar(avatar.getFilename());
+						} else {
+							Contact contact = account.getRoster().getContact(avatar.owner);
+							contact.setAvatar(avatar.getFilename());
+						}
+					}
 				}
 			}
 		});

src/eu/siacs/conversations/ui/adapter/MessageAdapter.java 🔗

@@ -451,14 +451,10 @@ public class MessageAdapter extends ArrayAdapter<Message> {
 		private HashMap<String, Bitmap> unknownBitmaps = new HashMap<String, Bitmap>();
 
 		public Bitmap get(Contact contact, Context context) {
-			if (contactBitmaps.containsKey(contact.getJid())) {
-				return contactBitmaps.get(contact.getJid());
-			} else {
-				Bitmap bm = UIHelper.getContactPicture(contact, 48, context,
-						false);
-				contactBitmaps.put(contact.getJid(), bm);
-				return bm;
+			if (!contactBitmaps.containsKey(contact.getJid())) {
+				contactBitmaps.put(contact.getJid(), contact.getImage(48, context));
 			}
+			return contactBitmaps.get(contact.getJid());
 		}
 
 		public Bitmap get(String name, Context context) {