diff --git a/.gitmodules b/.gitmodules index cdfee6b31..85ba19063 100644 --- a/.gitmodules +++ b/.gitmodules @@ -120,3 +120,9 @@ [submodule "submodules/externals/zxing-cpp"] path = submodules/externals/zxing-cpp url = git://git.linphone.org/zxing-cpp.git +[submodule "submodules/externals/decaf"] + path = submodules/externals/decaf + url = git://git.linphone.org/decaf.git +[submodule "submodules/lime"] + path = submodules/lime + url = gitosis@git.linphone.org:lime.git diff --git a/res/layout/chat.xml b/res/layout/chat.xml index 9c2103ee9..dace7c3bb 100644 --- a/res/layout/chat.xml +++ b/res/layout/chat.xml @@ -162,9 +162,9 @@ android:id="@+id/send_message" android:layout_width="wrap_content" android:layout_height="wrap_content" + android:layout_gravity="center" android:contentDescription="@string/content_description_send_message" - android:padding="10dp" - android:src="@drawable/chat_send_message"/> + android:src="@drawable/chat_send"/> diff --git a/src/android/org/linphone/LinphoneManager.java b/src/android/org/linphone/LinphoneManager.java index f57c11ef7..bb042dbfc 100644 --- a/src/android/org/linphone/LinphoneManager.java +++ b/src/android/org/linphone/LinphoneManager.java @@ -1621,7 +1621,7 @@ public class LinphoneManager implements CoreListener, SensorEventListener, Accou if (prefs.isProvisioningLoginViewEnabled()) { ProxyConfig proxyConfig = lc.createProxyConfig(); Address addr = proxyConfig.getIdentityAddress(); - wizardLoginViewDomain = addr.getDomain(); + wizardLoginViewDomain = (addr != null) ? addr.getDomain() : ""; } prefs.setPushNotificationEnabled(prefs.isPushNotificationEnabled()); } diff --git a/src/android/org/linphone/assistant/RemoteProvisioningLoginActivity.java b/src/android/org/linphone/assistant/RemoteProvisioningLoginActivity.java index 43d5287fe..c92490542 100644 --- a/src/android/org/linphone/assistant/RemoteProvisioningLoginActivity.java +++ b/src/android/org/linphone/assistant/RemoteProvisioningLoginActivity.java @@ -54,6 +54,19 @@ import android.widget.RelativeLayout; import android.widget.TextView; import android.widget.Toast; +import java.io.ByteArrayInputStream; +import java.math.BigInteger; +import java.nio.charset.StandardCharsets; +import java.security.spec.KeySpec; +import java.util.Base64; + +import javax.crypto.Cipher; +import javax.crypto.SecretKey; +import javax.crypto.SecretKeyFactory; +import javax.crypto.spec.IvParameterSpec; +import javax.crypto.spec.PBEKeySpec; +import javax.crypto.spec.SecretKeySpec; + import static android.os.SystemClock.sleep; public class RemoteProvisioningLoginActivity extends Activity implements OnClickListener { @@ -63,12 +76,14 @@ public class RemoteProvisioningLoginActivity extends Activity implements OnClick private Button ok, back; private ProgressDialog progress; private String qrcodeString; + private String remoteUrl; private RelativeLayout bottom; private CoreListenerStub mListener; private SurfaceView mQrcodeView; private AndroidVideoWindowImpl androidVideoWindowImpl; private boolean cameraAuthorize = false; private boolean readQRCode = true; + private boolean backCamera = true; private int PERMISSION_CAMERA = 108; @Override @@ -102,6 +117,8 @@ public class RemoteProvisioningLoginActivity extends Activity implements OnClick if (readQRCode && getPackageManager().checkPermission(Manifest.permission.CAMERA, getPackageName()) != PackageManager.PERMISSION_GRANTED) { checkAndRequestVideoPermission(); + } else { + instance.setBackCamera(!backCamera); } } }); @@ -132,6 +149,14 @@ public class RemoteProvisioningLoginActivity extends Activity implements OnClick instance.ok.setEnabled(true); } }); + if (progress != null) progress.dismiss(); + runOnUiThread(new Runnable() { + @Override + public void run() { + instance.displayQrCode(); + instance.launchQrcodeReader(); + } + }); } } @@ -196,11 +221,6 @@ public class RemoteProvisioningLoginActivity extends Activity implements OnClick if (cameraAuthorize && readQRCode) { LinphoneManager.getLc().enableQrcodeVideoPreview(enable); LinphoneManager.getLc().enableVideoPreview(enable); - if (enable) { - LinphoneManager.getLc().addListener(mListener); - } else { - LinphoneManager.getLc().removeListener(mListener); - } } } @@ -214,28 +234,22 @@ public class RemoteProvisioningLoginActivity extends Activity implements OnClick String[] devices = LinphoneManager.getLc().getVideoDevicesList(); String newDevice = devices[camId]; LinphoneManager.getLc().setVideoDevice(newDevice); - + backCamera = useBackCamera; } private void launchQrcodeReader() { setBackCamera(true); androidVideoWindowImpl = new AndroidVideoWindowImpl(null, mQrcodeView, new AndroidVideoWindowImpl.VideoWindowListener() { - public void onVideoRenderingSurfaceReady(AndroidVideoWindowImpl vw, SurfaceView surface) { + public void onVideoRenderingSurfaceReady(AndroidVideoWindowImpl vw, SurfaceView surface) {} - } - - public void onVideoRenderingSurfaceDestroyed(AndroidVideoWindowImpl vw) { - - } + public void onVideoRenderingSurfaceDestroyed(AndroidVideoWindowImpl vw) {} public void onVideoPreviewSurfaceReady(AndroidVideoWindowImpl vw, SurfaceView surface) { LinphoneManager.getLc().setNativePreviewWindowId(androidVideoWindowImpl); } - public void onVideoPreviewSurfaceDestroyed(AndroidVideoWindowImpl vw) { - LinphoneManager.getLc().setNativePreviewWindowId(null); - } + public void onVideoPreviewSurfaceDestroyed(AndroidVideoWindowImpl vw) {} }); enableQrcodeReader(true); @@ -300,7 +314,18 @@ public class RemoteProvisioningLoginActivity extends Activity implements OnClick if (id == R.id.valider) { displayRemoteProvisioningInProgressDialog(); ok.setEnabled(false); - storeAccount(qrcodeString); + if (qrcodeString != null + && (qrcodeString.startsWith("http://") + || qrcodeString.startsWith("https://"))) { + storeAccount(qrcodeString); + } else { + if (decryptQrcode()) { + storeAccount(remoteUrl); + } else { + ok.setEnabled(true); + if (progress != null) progress.cancel(); + } + } } } @@ -317,6 +342,54 @@ public class RemoteProvisioningLoginActivity extends Activity implements OnClick } } + private byte[] removeUselessByte(byte[] tab, int wantedSize) { + if (wantedSize == tab.length) return tab; + byte[] newTab = new byte[wantedSize]; + for (int i = 1 ; i < tab.length ; i++) { + newTab[i-1] = tab[i]; + } + return newTab; + } + + private boolean decryptQrcode() { + try { + byte[] unBased64Data = qrcodeString.getBytes(); + ByteArrayInputStream inputStream = new ByteArrayInputStream(unBased64Data); + + byte[] salt = new byte[16]; + byte[] iv = new byte[256 / 8]; + byte[] contentToDecrypt = new byte[unBased64Data.length - 48]; + + inputStream.read(salt); + inputStream.read(iv); + inputStream.read(contentToDecrypt); + + String saltString = new String(salt); + BigInteger saltHex = new BigInteger(saltString, 16); + String ivString = new String(iv); + BigInteger ivHex = new BigInteger(ivString, 16); + + byte[] saltByte = removeUselessByte(saltHex.toByteArray(), 8); + byte[] ivByte = removeUselessByte(ivHex.toByteArray(), 16); + + SecretKeyFactory factory = SecretKeyFactory.getInstance("AES/CBC/PKCS5Padding"); + KeySpec keySpec = new PBEKeySpec(code_sms.getText().toString().toCharArray(), saltByte, 10000, 128); + SecretKey tmpSecretKey = factory.generateSecret(keySpec); + SecretKeySpec secretKeySpec = new SecretKeySpec(tmpSecretKey.getEncoded(), "AES"); + + Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding"); + cipher.init(Cipher.DECRYPT_MODE, secretKeySpec, new IvParameterSpec(ivByte)); + + remoteUrl = new String(cipher.doFinal(Base64.getDecoder().decode(contentToDecrypt))); + } catch (Exception ex) { + Toast.makeText(RemoteProvisioningLoginActivity.this, "Code mauvais", Toast.LENGTH_LONG).show(); + Log.e("RemoteProvisioningLoginActivity: Decrypt problem: " + ex); + remoteUrl = null; + return false; + } + return true; + } + private boolean storeAccount(String url) { LinphonePreferences.instance().setRemoteProvisioningUrl(url); //TODO diff --git a/submodules/bctoolbox b/submodules/bctoolbox index 3eef7b372..ed53ae3c9 160000 --- a/submodules/bctoolbox +++ b/submodules/bctoolbox @@ -1 +1 @@ -Subproject commit 3eef7b37214cc8a3fc1453fe92ac483a6b388f08 +Subproject commit ed53ae3c9da4fb15c13454153383014b3257939a diff --git a/submodules/belle-sip b/submodules/belle-sip index d7b16228a..0f999ecc3 160000 --- a/submodules/belle-sip +++ b/submodules/belle-sip @@ -1 +1 @@ -Subproject commit d7b16228a2746644a5dea76be9fff45708773130 +Subproject commit 0f999ecc3d304923b6338d3f48d44ac8ddfd9be8 diff --git a/submodules/bzrtp b/submodules/bzrtp index 7515af934..c4625d002 160000 --- a/submodules/bzrtp +++ b/submodules/bzrtp @@ -1 +1 @@ -Subproject commit 7515af934e5fa96c7e59f94f49c8bd25dd3ce071 +Subproject commit c4625d00204c2d5f3cd21de7a89f0e5ddd39c667 diff --git a/submodules/cmake-builder b/submodules/cmake-builder index 68f19de84..672d045e6 160000 --- a/submodules/cmake-builder +++ b/submodules/cmake-builder @@ -1 +1 @@ -Subproject commit 68f19de842824573dd075a4ec41483930b8de325 +Subproject commit 672d045e6a11ad723fca735879debad59ff9fb69 diff --git a/submodules/externals/decaf b/submodules/externals/decaf new file mode 160000 index 000000000..8feefdc98 --- /dev/null +++ b/submodules/externals/decaf @@ -0,0 +1 @@ +Subproject commit 8feefdc98b0a7ff6efb1442bd474dd14aa7ac9cf diff --git a/submodules/externals/zxing-cpp b/submodules/externals/zxing-cpp index 0f267e5fb..8906fb7b2 160000 --- a/submodules/externals/zxing-cpp +++ b/submodules/externals/zxing-cpp @@ -1 +1 @@ -Subproject commit 0f267e5fb66d45b32fba302bef0028dcf0dda84f +Subproject commit 8906fb7b243fa455fd9b091e4ac611536b2dbba4 diff --git a/submodules/linphone b/submodules/linphone index f9384facd..61e38e370 160000 --- a/submodules/linphone +++ b/submodules/linphone @@ -1 +1 @@ -Subproject commit f9384facd9e19c79cad20c14f7596e7c18d7b20c +Subproject commit 61e38e3704e1a37c9e884897ca5597158725b202 diff --git a/submodules/mediastreamer2 b/submodules/mediastreamer2 index 87fc60ba8..786511120 160000 --- a/submodules/mediastreamer2 +++ b/submodules/mediastreamer2 @@ -1 +1 @@ -Subproject commit 87fc60ba8beb16721df9d14229f00a44c0631d7c +Subproject commit 7865111207850fb53856fe500ae7b60d2cce379b