republish avatar if server offers non-persistent pep :-(
This commit is contained in:
		
							parent
							
								
									23a0beab43
								
							
						
					
					
						commit
						7ff890e513
					
				| @ -26,6 +26,7 @@ import java.io.ByteArrayOutputStream; | ||||
| import java.io.Closeable; | ||||
| import java.io.File; | ||||
| import java.io.FileDescriptor; | ||||
| import java.io.FileInputStream; | ||||
| import java.io.FileNotFoundException; | ||||
| import java.io.FileOutputStream; | ||||
| import java.io.IOException; | ||||
| @ -402,6 +403,43 @@ public class FileBackend { | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public Avatar getStoredPepAvatar(String hash) { | ||||
| 		if (hash == null) { | ||||
| 			return null; | ||||
| 		} | ||||
| 		Avatar avatar = new Avatar(); | ||||
| 		File file = new File(getAvatarPath(hash)); | ||||
| 		FileInputStream is = null; | ||||
| 		try { | ||||
| 			BitmapFactory.Options options = new BitmapFactory.Options(); | ||||
| 			options.inJustDecodeBounds = true; | ||||
| 			BitmapFactory.decodeFile(file.getAbsolutePath(), options); | ||||
| 			is = new FileInputStream(file); | ||||
| 			ByteArrayOutputStream mByteArrayOutputStream = new ByteArrayOutputStream(); | ||||
| 			Base64OutputStream mBase64OutputStream = new Base64OutputStream(mByteArrayOutputStream, Base64.DEFAULT); | ||||
| 			MessageDigest digest = MessageDigest.getInstance("SHA-1"); | ||||
| 			DigestOutputStream os = new DigestOutputStream(mBase64OutputStream, digest); | ||||
| 			byte[] buffer = new byte[4096]; | ||||
| 			int length; | ||||
| 			while ((length = is.read(buffer)) > 0) { | ||||
| 				os.write(buffer, 0, length); | ||||
| 			} | ||||
| 			os.flush(); | ||||
| 			os.close(); | ||||
| 			avatar.sha1sum = CryptoHelper.bytesToHex(digest.digest()); | ||||
| 			avatar.image = new String(mByteArrayOutputStream.toByteArray()); | ||||
| 			avatar.height = options.outHeight; | ||||
| 			avatar.width = options.outWidth; | ||||
| 			return avatar; | ||||
| 		} catch (IOException e) { | ||||
| 			return null; | ||||
| 		} catch (NoSuchAlgorithmException e) { | ||||
| 			return null; | ||||
| 		} finally { | ||||
| 			close(is); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public boolean isAvatarCached(Avatar avatar) { | ||||
| 		File file = new File(getAvatarPath(avatar.getFilename())); | ||||
| 		return file.exists(); | ||||
|  | ||||
| @ -6,11 +6,13 @@ import android.graphics.Paint; | ||||
| import android.graphics.Rect; | ||||
| import android.graphics.Typeface; | ||||
| import android.net.Uri; | ||||
| import android.util.Log; | ||||
| 
 | ||||
| import java.util.ArrayList; | ||||
| import java.util.List; | ||||
| import java.util.Locale; | ||||
| 
 | ||||
| import eu.siacs.conversations.Config; | ||||
| import eu.siacs.conversations.entities.Account; | ||||
| import eu.siacs.conversations.entities.Bookmark; | ||||
| import eu.siacs.conversations.entities.Contact; | ||||
| @ -19,8 +21,10 @@ import eu.siacs.conversations.entities.ListItem; | ||||
| import eu.siacs.conversations.entities.Message; | ||||
| import eu.siacs.conversations.entities.MucOptions; | ||||
| import eu.siacs.conversations.utils.UIHelper; | ||||
| import eu.siacs.conversations.xmpp.OnAdvancedStreamFeaturesLoaded; | ||||
| import eu.siacs.conversations.xmpp.XmppConnection; | ||||
| 
 | ||||
| public class AvatarService { | ||||
| public class AvatarService implements OnAdvancedStreamFeaturesLoaded { | ||||
| 
 | ||||
| 	private static final int FG_COLOR = 0xFFFAFAFA; | ||||
| 	private static final int TRANSPARENT = 0x00000000; | ||||
| @ -227,8 +231,7 @@ public class AvatarService { | ||||
| 		if (avatar != null || cachedOnly) { | ||||
| 			return avatar; | ||||
| 		} | ||||
| 		avatar = mXmppConnectionService.getFileBackend().getAvatar( | ||||
| 				account.getAvatar(), size); | ||||
| 		avatar = mXmppConnectionService.getFileBackend().getAvatar(account.getAvatar(), size); | ||||
| 		if (avatar == null) { | ||||
| 			avatar = get(account.getJid().toBareJid().toString(), size,false); | ||||
| 		} | ||||
| @ -387,10 +390,20 @@ public class AvatarService { | ||||
| 		return false; | ||||
| 	} | ||||
| 
 | ||||
| 	private boolean drawTile(Canvas canvas, Bitmap bm, int dstleft, int dsttop, | ||||
| 						  int dstright, int dstbottom) { | ||||
| 	private boolean drawTile(Canvas canvas, Bitmap bm, int dstleft, int dsttop, int dstright, int dstbottom) { | ||||
| 		Rect dst = new Rect(dstleft, dsttop, dstright, dstbottom); | ||||
| 		canvas.drawBitmap(bm, null, dst, null); | ||||
| 		return true; | ||||
| 	} | ||||
| 
 | ||||
| 	@Override | ||||
| 	public void onAdvancedStreamFeaturesAvailable(Account account) { | ||||
| 		XmppConnection.Features features = account.getXmppConnection().getFeatures(); | ||||
| 		if (features.pep() && !features.pepPersistent()) { | ||||
| 			Log.d(Config.LOGTAG,account.getJid().toBareJid()+": has pep but is not persistent"); | ||||
| 			if (account.getAvatar() != null) { | ||||
| 				mXmppConnectionService.republishAvatarIfNeeded(account); | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @ -840,6 +840,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa | ||||
| 		connection.setOnBindListener(this.mOnBindListener); | ||||
| 		connection.setOnMessageAcknowledgeListener(this.mOnMessageAcknowledgedListener); | ||||
| 		connection.addOnAdvancedStreamFeaturesAvailableListener(this.mMessageArchiveService); | ||||
| 		connection.addOnAdvancedStreamFeaturesAvailableListener(this.mAvatarService); | ||||
| 		AxolotlService axolotlService = account.getAxolotlService(); | ||||
| 		if (axolotlService != null) { | ||||
| 			connection.addOnAdvancedStreamFeaturesAvailableListener(axolotlService); | ||||
| @ -2338,9 +2339,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	public void publishAvatar(final Account account, | ||||
| 							  final Uri image, | ||||
| 							  final UiCallback<Avatar> callback) { | ||||
| 	public void publishAvatar(Account account, Uri image, UiCallback<Avatar> callback) { | ||||
| 		final Bitmap.CompressFormat format = Config.AVATAR_FORMAT; | ||||
| 		final int size = Config.AVATAR_SIZE; | ||||
| 		final Avatar avatar = getFileBackend().getPepAvatar(image, size, format); | ||||
| @ -2358,40 +2357,96 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa | ||||
| 				callback.error(R.string.error_saving_avatar, avatar); | ||||
| 				return; | ||||
| 			} | ||||
| 			final IqPacket packet = this.mIqGenerator.publishAvatar(avatar); | ||||
| 			this.sendIqPacket(account, packet, new OnIqPacketReceived() { | ||||
| 			publishAvatar(account, avatar, callback); | ||||
| 		} else { | ||||
| 			callback.error(R.string.error_publish_avatar_converting, null); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 				@Override | ||||
| 				public void onIqPacketReceived(Account account, IqPacket result) { | ||||
| 					if (result.getType() == IqPacket.TYPE.RESULT) { | ||||
| 						final IqPacket packet = XmppConnectionService.this.mIqGenerator | ||||
| 								.publishAvatarMetadata(avatar); | ||||
| 						sendIqPacket(account, packet, new OnIqPacketReceived() { | ||||
| 							@Override | ||||
| 							public void onIqPacketReceived(Account account, IqPacket result) { | ||||
| 								if (result.getType() == IqPacket.TYPE.RESULT) { | ||||
| 									if (account.setAvatar(avatar.getFilename())) { | ||||
| 										getAvatarService().clear(account); | ||||
| 										databaseBackend.updateAccount(account); | ||||
| 									} | ||||
| 	public void publishAvatar(Account account, final Avatar avatar, final UiCallback<Avatar> callback) { | ||||
| 		final IqPacket packet = this.mIqGenerator.publishAvatar(avatar); | ||||
| 		this.sendIqPacket(account, packet, new OnIqPacketReceived() { | ||||
| 
 | ||||
| 			@Override | ||||
| 			public void onIqPacketReceived(Account account, IqPacket result) { | ||||
| 				if (result.getType() == IqPacket.TYPE.RESULT) { | ||||
| 					final IqPacket packet = XmppConnectionService.this.mIqGenerator | ||||
| 							.publishAvatarMetadata(avatar); | ||||
| 					sendIqPacket(account, packet, new OnIqPacketReceived() { | ||||
| 						@Override | ||||
| 						public void onIqPacketReceived(Account account, IqPacket result) { | ||||
| 							if (result.getType() == IqPacket.TYPE.RESULT) { | ||||
| 								if (account.setAvatar(avatar.getFilename())) { | ||||
| 									getAvatarService().clear(account); | ||||
| 									databaseBackend.updateAccount(account); | ||||
| 								} | ||||
| 								if (callback != null) { | ||||
| 									callback.success(avatar); | ||||
| 								} else { | ||||
| 									Log.d(Config.LOGTAG,account.getJid().toBareJid()+": published avatar"); | ||||
| 								} | ||||
| 							} else { | ||||
| 								if (callback != null) { | ||||
| 									callback.error( | ||||
| 											R.string.error_publish_avatar_server_reject, | ||||
| 											avatar); | ||||
| 								} | ||||
| 							} | ||||
| 						}); | ||||
| 					} else { | ||||
| 						} | ||||
| 					}); | ||||
| 				} else { | ||||
| 					if (callback != null) { | ||||
| 						callback.error( | ||||
| 								R.string.error_publish_avatar_server_reject, | ||||
| 								avatar); | ||||
| 					} | ||||
| 				} | ||||
| 			}); | ||||
| 		} else { | ||||
| 			callback.error(R.string.error_publish_avatar_converting, null); | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	public void republishAvatarIfNeeded(Account account) { | ||||
| 		if (account.getAxolotlService().isPepBroken()) { | ||||
| 			Log.d(Config.LOGTAG,account.getJid().toBareJid()+": skipping republication of avatar because pep is broken"); | ||||
| 			return; | ||||
| 		} | ||||
| 		IqPacket packet = this.mIqGenerator.retrieveAvatarMetaData(null); | ||||
| 		this.sendIqPacket(account, packet, new OnIqPacketReceived() { | ||||
| 
 | ||||
| 			private Avatar parseAvatar(IqPacket packet) { | ||||
| 				Element pubsub = packet.findChild("pubsub", "http://jabber.org/protocol/pubsub"); | ||||
| 				if (pubsub != null) { | ||||
| 					Element items = pubsub.findChild("items"); | ||||
| 					if (items != null) { | ||||
| 						return Avatar.parseMetadata(items); | ||||
| 					} | ||||
| 				} | ||||
| 				return null; | ||||
| 			} | ||||
| 
 | ||||
| 			private boolean errorIsItemNotFound(IqPacket packet) { | ||||
| 				Element error = packet.findChild("error"); | ||||
| 				return packet.getType() == IqPacket.TYPE.ERROR | ||||
| 						&& error != null | ||||
| 						&& error.hasChild("item-not-found"); | ||||
| 			} | ||||
| 
 | ||||
| 			@Override | ||||
| 			public void onIqPacketReceived(Account account, IqPacket packet) { | ||||
| 				if (packet.getType() == IqPacket.TYPE.RESULT || errorIsItemNotFound(packet)) { | ||||
| 					Avatar serverAvatar = parseAvatar(packet); | ||||
| 					if (serverAvatar == null && account.getAvatar() != null) { | ||||
| 						Avatar avatar = fileBackend.getStoredPepAvatar(account.getAvatar()); | ||||
| 						if (avatar != null) { | ||||
| 							Log.d(Config.LOGTAG,account.getJid().toBareJid()+": avatar on server was null. republishing"); | ||||
| 							publishAvatar(account, fileBackend.getStoredPepAvatar(account.getAvatar()), null); | ||||
| 						} else { | ||||
| 							Log.e(Config.LOGTAG, account.getJid().toBareJid()+": error rereading avatar"); | ||||
| 						} | ||||
| 					} | ||||
| 				} | ||||
| 			} | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	public void fetchAvatar(Account account, Avatar avatar) { | ||||
| @ -2526,8 +2581,7 @@ public class XmppConnectionService extends Service implements OnPhoneContactsLoa | ||||
| 			@Override | ||||
| 			public void onIqPacketReceived(Account account, IqPacket packet) { | ||||
| 				if (packet.getType() == IqPacket.TYPE.RESULT) { | ||||
| 					Element pubsub = packet.findChild("pubsub", | ||||
| 							"http://jabber.org/protocol/pubsub"); | ||||
| 					Element pubsub = packet.findChild("pubsub","http://jabber.org/protocol/pubsub"); | ||||
| 					if (pubsub != null) { | ||||
| 						Element items = pubsub.findChild("items"); | ||||
| 						if (items != null) { | ||||
|  | ||||
| @ -1530,13 +1530,15 @@ public class XmppConnection implements Runnable { | ||||
| 
 | ||||
| 		public boolean pep() { | ||||
| 			synchronized (XmppConnection.this.disco) { | ||||
| 				ServiceDiscoveryResult info = disco.get(account.getServer()); | ||||
| 				if (info != null && info.hasIdentity("pubsub", "pep")) { | ||||
| 					return true; | ||||
| 				} else { | ||||
| 					info = disco.get(account.getJid().toBareJid()); | ||||
| 					return info != null && info.hasIdentity("pubsub", "pep"); | ||||
| 				} | ||||
| 				ServiceDiscoveryResult info = disco.get(account.getJid().toBareJid()); | ||||
| 				return info != null && info.hasIdentity("pubsub", "pep"); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		public boolean pepPersistent() { | ||||
| 			synchronized (XmppConnection.this.disco) { | ||||
| 				ServiceDiscoveryResult info = disco.get(account.getJid().toBareJid()); | ||||
| 				return info != null && info.getFeatures().contains("http://jabber.org/protocol/pubsub#persistent-items"); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Daniel Gultsch
						Daniel Gultsch