diff --git a/.classpath b/.classpath
index b6af78b2d..2df25a2b6 100644
--- a/.classpath
+++ b/.classpath
@@ -1,17 +1,17 @@
-
-
-
+
+
+
diff --git a/.gitignore b/.gitignore
index b04540b57..2c6cd49a5 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,13 +1,40 @@
-libs
-obj
-gen
-bin
-doc
-default.properties
-local.properties
-project.properties
-tests/*$py.class
-tests/build.xml
-res/.DS_Store
-bc-android.keystore
-res/raw/lpconfig.xsd
\ No newline at end of file
+*.orig
+*.rej
+.DS_Store
+.gradle
+.idea
+.settings
+adb.pid
+bc-android.keystore
+bin
+build
+certdata.txt
+check_tools.mk
+default.properties
+doc
+gen
+liblinphone-junit-report.xml
+liblinphonetester_*.zip
+libs
+linphone-android.iml
+linphone-junit-report*.xml
+linphonetester_*.zip
+lint.xml
+local.properties
+obj
+proguard-project.txt
+project.properties
+res/.DS_Store
+res/raw/lpconfig.xsd
+res/raw/rootca.pem
+submodules/externals/build/cunit/CUnit/
+submodules/externals/build/ffmpeg/arm/
+submodules/externals/build/ffmpeg/x86
+submodules/externals/build/libvpx/arm
+submodules/externals/build/libvpx/x86
+submodules/externals/build/openh264/arm
+submodules/externals/build/openh264/x86
+tests/*$py.class
+tests/build.xml
+tests/project.properties
+ant_password.properties
diff --git a/.gitmodules b/.gitmodules
index ddd51f3c9..3138e5888 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,12 +1,6 @@
[submodule "linphone"]
path = submodules/linphone
- url = git://git.linphone.org/linphone.git
-[submodule "submodules/externals/osip"]
- path = submodules/externals/osip
- url = git://git.linphone.org/osip.git
-[submodule "submodules/externals/exosip"]
- path = submodules/externals/exosip
- url = git://git.linphone.org/exosip.git
+ url = git://git.linphone.org/linphone
[submodule "submodules/externals/gsm"]
path = submodules/externals/gsm
url = git://git.linphone.org/gsm.git
@@ -22,27 +16,28 @@
[submodule "submodules/externals/ffmpeg"]
path = submodules/externals/ffmpeg
url = git://git.linphone.org/ffmpeg.git
+ ignore = dirty
[submodule "submodules/externals/x264"]
path = submodules/externals/x264
url = git://git.linphone.org/x264.git
+ ignore = dirty
[submodule "submodules/msx264"]
path = submodules/msx264
url = git://git.linphone.org/msx264.git
-[submodule "submodules/externals/openssl"]
- path = submodules/externals/openssl
- url = git://git.linphone.org/android-openssl.git
[submodule "submodules/externals/opencore-amr"]
path = submodules/externals/opencore-amr
- url = git://opencore-amr.git.sourceforge.net/gitroot/opencore-amr/opencore-amr
+ url = git://git.linphone.org/opencore-amr.git
+ ignore = dirty
[submodule "submodules/msamr"]
path = submodules/msamr
url = git://git.linphone.org/msamr
[submodule "submodules/externals/libvpx"]
path = submodules/externals/libvpx
- url = http://git.chromium.org/webm/libvpx.git
-[submodule "submodules/externals/libzrtpcpp"]
- path = submodules/externals/libzrtpcpp
- url = git://git.linphone.org/zrtpcpp.git
+ url = https://chromium.googlesource.com/webm/libvpx
+ ignore = dirty
+[submodule "submodules/bzrtp"]
+ path = submodules/bzrtp
+ url = git://git.linphone.org/bzrtp.git
[submodule "submodules/externals/srtp"]
path = submodules/externals/srtp
url = git://git.linphone.org/srtp.git
@@ -51,19 +46,48 @@
url = git://git.linphone.org/mssilk.git
[submodule "submodules/externals/vo-amrwbenc"]
path = submodules/externals/vo-amrwbenc
- url = git://opencore-amr.git.sourceforge.net/gitroot/opencore-amr/vo-amrwbenc
+ url = git://git.linphone.org/vo-amrwbenc.git
[submodule "submodules/bcg729"]
path = submodules/bcg729
url = git://git.linphone.org/bcg729.git
-[submodule "submodules/externals/webrtc"]
- path = submodules/externals/webrtc
- url = git://git.linphone.org/webrtc.git
+[submodule "submodules/belle-sip"]
+ path = submodules/belle-sip
+ url = git://git.linphone.org/belle-sip
+[submodule "submodules/externals/antlr3"]
+ path = submodules/externals/antlr3
+ url = git://git.linphone.org/antlr3.git
[submodule "submodules/externals/libxml2"]
path = submodules/externals/libxml2
url = git://git.gnome.org/libxml2
[submodule "submodules/externals/libupnp"]
path = submodules/externals/libupnp
- url = git://git.code.sf.net/p/pupnp/code
+ url = git://git.linphone.org/libupnp.git
+[submodule "submodules/externals/cunit"]
+ path = submodules/externals/cunit
+ url = git://git.linphone.org/cunit.git
[submodule "submodules/externals/axmlrpc"]
path = submodules/externals/axmlrpc
url = git://git.linphone.org/axmlrpc.git
+[submodule "submodules/externals/polarssl"]
+ path = submodules/externals/polarssl
+ url = git://git.linphone.org/polarssl.git
+[submodule "submodules/externals/opus"]
+ path = submodules/externals/opus
+ url = git://git.opus-codec.org/opus.git
+[submodule "submodules/mswebrtc"]
+ path = submodules/mswebrtc
+ url = git://git.linphone.org/mswebrtc.git
+[submodule "submodules/msopenh264"]
+ path = submodules/msopenh264
+ url = git://git.linphone.org/msopenh264.git
+[submodule "submodules/externals/openh264"]
+ path = submodules/externals/openh264
+ url = https://github.com/cisco/openh264
+ ignore = dirty
+[submodule "submodules/externals/libmatroska"]
+ path = submodules/externals/libmatroska
+ url = https://github.com/Matroska-Org/foundation-source.git
+ ignore = dirty
+[submodule "submodules/externals/webrtc"]
+ path = submodules/externals/webrtc
+ url = git://git.linphone.org/webrtc.git
diff --git a/.tx/config b/.tx/config
new file mode 100644
index 000000000..a1399b7b7
--- /dev/null
+++ b/.tx/config
@@ -0,0 +1,15 @@
+[main]
+host = https://www.transifex.com
+lang_map = fr_CA:fr-rCA,pt_BR:pt-rBR,zh_CN:zh-rCN,zh_HK:zh-rHK,zh_TW:zh-rTW,da_DK:da-rDK,sv_SE:sv-rSE,kn_IN:kn-rIN,nl_NL:nl-rNL,en_NL:en-rNL
+minimum_perc = 1
+type = ANDROID
+
+[linphone-android.stringsxml]
+file_filter = res/values-/strings.xml
+source_file = res/values/strings.xml
+source_lang = en
+
+[linphone-android.customxml]
+file_filter = res/values-/custom.xml
+source_file = res/values/custom.xml
+source_lang = en
diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index 6990d4d42..4bda42092 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -1,14 +1,13 @@
-
+ android:versionCode="2411" android:installLocation="auto">
+
-
-
+
+
-
@@ -36,7 +35,12 @@
-
+
+
+
+
+
+
@@ -44,6 +48,7 @@
@@ -55,7 +60,7 @@
-
+ />
@@ -63,17 +68,25 @@
+
+
+
+
+
+
+
+
+
-
-
-
-
+ android:launchMode="singleTop">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
+
@@ -127,18 +195,21 @@
+
+
+
-
+
-
-
diff --git a/Makefile b/Makefile
index 2dbde39b7..08ed199c8 100644
--- a/Makefile
+++ b/Makefile
@@ -1,37 +1,134 @@
NDK_PATH=$(shell dirname `which ndk-build`)
+NDK_MAJOR_VERSION=$(shell cat $(NDK_PATH)/RELEASE.TXT | sed "s/r\([0-9]\{1,2\}\).*/\1/")
SDK_PATH=$(shell dirname `which android`)
SDK_PLATFORM_TOOLS_PATH=$(shell dirname `which adb`)
-NUMCPUS=$(shell grep -c '^processor' /proc/cpuinfo || echo "4" )
+ARM_COMPILER_PATH=`find "$(NDK_PATH)" -name "arm-linux-androideabi-gcc-4*" -print | tail -1`
+ARM_TOOLCHAIN_PATH=$(shell dirname $(ARM_COMPILER_PATH))/arm-linux-androideabi-
+X86_COMPILER_PATH=`find "$(NDK_PATH)" -name "i686-linux-android-gcc-4*" -print | tail -1`
+X86_TOOLCHAIN_PATH=$(shell dirname $(X86_COMPILER_PATH))/i686-linux-android-
+NUMCPUS=$(shell grep -c '^processor' /proc/cpuinfo 2>/dev/null || echo "4" )
TOPDIR=$(shell pwd)
-PATCH_FFMPEG=$(shell cd submodules/externals/ffmpeg && git status | grep neon)
-LINPHONE_VERSION=$(shell cd submodules/linphone && git describe --always)
+LIBLINPHONE_VERSION=$(shell cd submodules/linphone && git describe --always)
LINPHONE_ANDROID_DEBUG_VERSION=$(shell git describe --always)
-ANDROID_MOST_RECENT_TARGET=$(shell android list target -c | grep android | tail -n1)
+BELLESIP_VERSION_SCRIPT:=cat submodules/belle-sip/configure.ac | grep "AC_INIT(" | sed -e "s/.*belle-sip\]//" | sed -e "s/].*//" | sed -e "s/.*\[//"
+BELLESIP_VERSION=$(shell $(BELLESIP_VERSION_SCRIPT))
+ANDROID_MOST_RECENT_TARGET=$(shell android list target -c | grep -E 'android-[0-9]+' | tail -n1)
+#We force target 19 because 21 creates binaries incompatible with older versions due to rand() function no longer inline (congrats to Google's developers)
+NDKBUILD_TARGET=android-19
+#The NDK target used to compile external third parties (ffmpeg, x264)
+EXTERNAL_MAKE_TARGET=14
+ARM_SYSROOT=${NDK_PATH}/platforms/android-$(EXTERNAL_MAKE_TARGET)/arch-arm
+X86_SYSROOT=${NDK_PATH}/platforms/android-$(EXTERNAL_MAKE_TARGET)/arch-x86
+SQLITE_VERSION=3071700
+SQLITE_BASENAME=sqlite-amalgamation-$(SQLITE_VERSION)
+SQLITE_URL=http://www.sqlite.org/2013/$(SQLITE_BASENAME).zip
+ENABLE_GPL_THIRD_PARTIES=1
+#override CC variable to disable compiler specific FLAGS in configure using the system compiler instead of the android one
+CC=
+PACKAGE_NAME=$(shell sed -nE 's||\1|p' custom_rules.xml)
+#default options, can be overidden using make OPTION=value .
+
+ifeq ($(ENABLE_GPL_THIRD_PARTIES),1)
+BUILD_G729=1
+else
+#x264 and g729 requires additional licensing agreements.
+BUILD_X264=0
+BUILD_G729=0
+endif
NDK_DEBUG=0
+BUILD_VIDEO=1
+BUILD_OPENH264=1
+BUILD_NON_FREE_CODECS=1
+ENABLE_OPENH264_DECODER=1
BUILD_UPNP=1
-BUILD_REMOTE_PROVISIONING=1
-BUILD_X264=1
BUILD_AMRNB=full # 0, light or full
-BUILD_AMRWB=0
-BUILD_GPLV3_ZRTP=0
+BUILD_AMRWB=1
+BUILD_ZRTP=1
BUILD_SILK=1
-BUILD_G729=0
BUILD_TUNNEL=0
BUILD_WEBRTC_AECM=1
+BUILD_OPUS=1
+BUILD_MATROSKA=1
+BUILD_WEBRTC_ISAC=1
BUILD_FOR_X86=1
+BUILD_FOR_ARM=1
USE_JAVAH=1
+BUILD_TLS=1
+BUILD_SQLITE=1
+BUILD_CONTACT_HEADER=0
+BUILD_RTP_MAP=0
+BUILD_DONT_CHECK_HEADERS_IN_MESSAGE=0
+BUILD_ILBC=1
+LIBLINPHONE_EXTENDED_SRC_FILES=
+LIBLINPHONE_EXTENDED_C_INCLUDES=
+LIBLINPHONE_EXTENDED_CFLAGS=
+APP_STL=stlport_static
+ANT_SILENT=$(shell ant -h | grep -q -- -S && echo 1 || echo 0)
-NDK_BUILD_OPTIONS=NDK_DEBUG=$(NDK_DEBUG) LINPHONE_VERSION=$(LINPHONE_VERSION) BUILD_UPNP=$(BUILD_UPNP) BUILD_REMOTE_PROVISIONING=$(BUILD_REMOTE_PROVISIONING) BUILD_X264=$(BUILD_X264) BUILD_AMRNB=$(BUILD_AMRNB) BUILD_AMRWB=$(BUILD_AMRWB) BUILD_GPLV3_ZRTP=$(BUILD_GPLV3_ZRTP) BUILD_SILK=$(BUILD_SILK) BUILD_G729=$(BUILD_G729) BUILD_TUNNEL=$(BUILD_TUNNEL) BUILD_WEBRTC_AECM=$(BUILD_WEBRTC_AECM) BUILD_FOR_X86=$(BUILD_FOR_X86) USE_JAVAH=$(USE_JAVAH) -j$(NUMCPUS)
+# Checks
+CHECK_MSG=$(shell ./check_tools.sh)
-all: update-project prepare-sources generate-apk
+ifneq ($(CHECK_MSG),)
+ $(error Some tools are missing.)
+else
+ ifeq ($(BUILD_OPENH264),1)
+ ifneq ($(shell echo $(NDK_MAJOR_VERSION)\>=10 | bc),1)
+$(error ndk version [$(NDK_MAJOR_VERSION)] not compatible with openh264.)
+ endif
+ endif
+ include check_tools.mk
+endif
+
+OPENSSL_DIR=$(shell openssl version -d | sed "s/OPENSSLDIR: \"\(.*\)\"/\1/")
+ifneq ($(shell ls $(OPENSSL_DIR)/certs),)
+ HTTPS_CA_DIR=$(OPENSSL_DIR)/certs
+else
+ HTTPS_CA_DIR=$(OPENSSL_DIR)
+endif
+
+ifeq ($(ANT_SILENT), 1)
+ ANT=ant -e -S
+else
+ ANT=ant -e
+endif
+
+# Temporary check: in case of MediastreamActivity.java file existing while it should not anymore, print an error message
+# and abort build since otherwise java compilation will fail.
+ifneq ($(shell ls ./submodules/linphone/mediastreamer2/java/src/org/linphone/mediastream/MediastreamerActivity.java 2>/dev/null),)
+$(error ./submodules/linphone/mediastreamer2/java/src/org/linphone/mediastream/MediastreamerActivity.java found: please either remove it or move it to MediastreamActivity.java.ignored before continuing.)
+endif
+
+ifeq ($(BUILD_NON_FREE_CODECS), 0)
+BUILD_OPENH264=0
+ENABLE_OPENH264_DECODER=0
+BUILD_AMRNB=0
+BUILD_AMRWB=0
+BUILD_G729=0
+BUILD_X264=0
+endif
+
+all: update-project generate-apk
+ifeq ($(ENABLE_GPL_THIRD_PARTIES),1)
+ @echo "***************************************************************************"
+ @echo "***** CAUTION, this liblinphone SDK is built using 3rd party GPL code *****"
+ @echo "***** Even if you acquired a proprietary license from Belledonne *****"
+ @echo "***** Communications, this SDK is GPL and GPL only. *****"
+ @echo "***** To disable 3rd party gpl code, please use: *****"
+ @echo "***** $$ make ENABLE_GPL_THIRD_PARTIES=0 *****"
+ @echo "***************************************************************************"
+else
+ @echo
+ @echo "*****************************************************************"
+ @echo "***** Linphone SDK without 3rd party GPL software *****"
+ @echo "***** If you acquired a proprietary license from Belledonne *****"
+ @echo "***** Communications, this SDK can be used to create *****"
+ @echo "***** a proprietary linphone-based application. *****"
+ @echo "*****************************************************************"
+endif
install: install-apk run-linphone
-prepare-ffmpeg:
-ifeq ($(PATCH_FFMPEG),)
- @patch -p0 < $(TOPDIR)/patches/ffmpeg_scalar_product_remove_alignment_hints.patch
-endif
#libilbc
LIBILBC_SRC_DIR=$(TOPDIR)/submodules/libilbc-rfc3951
LIBILBC_BUILD_DIR=$(LIBILBC_SRC_DIR)
@@ -45,41 +142,206 @@ $(LIBILBC_BUILD_DIR)/Makefile: $(LIBILBC_SRC_DIR)/configure
$(LIBILBC_BUILD_DIR)/src/iLBC_decode.c: $(LIBILBC_BUILD_DIR)/Makefile
cd $(LIBILBC_BUILD_DIR)/downloads && make \
|| ( echo "iLBC prepare stage failed" ; exit 1 )
-
+
+ifeq ($(BUILD_ILBC),1)
prepare-ilbc: $(LIBILBC_BUILD_DIR)/src/iLBC_decode.c
+else
+prepare-ilbc:
+endif
+
+#ffmpeg
+ifeq ($(BUILD_VIDEO),1)
+BUILD_FFMPEG_DEPS=$(FFMPEG_SRC_DIR)/non_versioned_soname_patch_applied.txt $(FFMPEG_BUILD_DIR)/arm/libffmpeg-linphone-arm.so
+ifeq ($(BUILD_FOR_X86), 1)
+ BUILD_FFMPEG_DEPS+=$(FFMPEG_BUILD_DIR)/x86/libffmpeg-linphone-x86.so
+endif
+endif
+FFMPEG_SRC_DIR=$(TOPDIR)/submodules/externals/ffmpeg
+FFMPEG_BUILD_DIR=$(TOPDIR)/submodules/externals/build/ffmpeg
+FFMPEG_CONFIGURE_OPTIONS=--target-os=linux --enable-cross-compile --enable-runtime-cpudetect \
+ --disable-everything --disable-doc --disable-ffplay --disable-ffmpeg --disable-ffprobe --disable-ffserver \
+ --disable-avdevice --disable-avfilter --disable-avformat --disable-swresample --disable-network \
+ --enable-decoder=mjpeg --enable-encoder=mjpeg --enable-decoder=mpeg4 --enable-encoder=mpeg4 --enable-decoder=h264 \
+ --enable-decoder=h263p --enable-encoder=h263p --enable-decoder=h263 --enable-encoder=h263 --extra-cflags="-w" \
+ --disable-static --enable-shared --disable-symver
+FFMPEG_ARM_CONFIGURE_OPTIONS=--build-suffix=-linphone-arm --arch=arm --sysroot=$(ARM_SYSROOT) --cross-prefix=$(ARM_TOOLCHAIN_PATH) --enable-pic
+FFMPEG_X86_CONFIGURE_OPTIONS=--build-suffix=-linphone-x86 --arch=x86 --sysroot=$(X86_SYSROOT) --cross-prefix=$(X86_TOOLCHAIN_PATH) --disable-mmx --disable-sse2 --disable-ssse3 --extra-cflags='-O3'
+
+$(FFMPEG_SRC_DIR)/non_versioned_soname_patch_applied.txt:
+ @patch -p0 < $(TOPDIR)/patches/ffmpeg_non_versioned_soname.patch
+ touch $@
+
+$(FFMPEG_BUILD_DIR)/arm/config.h:
+ mkdir -p $(FFMPEG_BUILD_DIR)/arm && \
+ cd $(FFMPEG_BUILD_DIR)/arm && \
+ $(FFMPEG_SRC_DIR)/configure $(FFMPEG_CONFIGURE_OPTIONS) $(FFMPEG_ARM_CONFIGURE_OPTIONS)
+ sed -i.bak 's/#define HAVE_SYSCTL 1/#define HAVE_SYSCTL 0/g' $(FFMPEG_BUILD_DIR)/arm/config.h
+ sed -i.bak 's/#define HAVE_GETHRTIME 1/#define HAVE_GETHRTIME 0/g' $(FFMPEG_BUILD_DIR)/arm/config.h
+
+$(FFMPEG_BUILD_DIR)/arm/libavcodec/libavcodec-linphone-arm.so: $(FFMPEG_BUILD_DIR)/arm/config.h
+ cd $(FFMPEG_BUILD_DIR)/arm && \
+ make -j${NUMCPUS} \
+ || ( echo "Build of ffmpeg for arm failed." ; exit 1 )
+
+$(FFMPEG_BUILD_DIR)/arm/libffmpeg-linphone-arm.so: $(FFMPEG_BUILD_DIR)/arm/libavcodec/libavcodec-linphone-arm.so
+ cd $(FFMPEG_BUILD_DIR)/arm && \
+ rm libavcodec/log2_tab.o && \
+ $(ARM_TOOLCHAIN_PATH)gcc -lm -lz --sysroot=$(ARM_SYSROOT) -Wl,--no-undefined -Wl,-z,noexecstack -shared libavutil/*.o libavutil/arm/*.o libavcodec/*.o libavcodec/arm/*.o libswscale/*.o -o libffmpeg-linphone-arm.so
+
+$(FFMPEG_BUILD_DIR)/x86/config.h:
+ mkdir -p $(FFMPEG_BUILD_DIR)/x86 && \
+ cd $(FFMPEG_BUILD_DIR)/x86 && \
+ $(FFMPEG_SRC_DIR)/configure $(FFMPEG_CONFIGURE_OPTIONS) $(FFMPEG_X86_CONFIGURE_OPTIONS)
+ sed -i.bak 's/#define HAVE_SYSCTL 1/#define HAVE_SYSCTL 0/g' $(FFMPEG_BUILD_DIR)/x86/config.h
+ sed -i.bak 's/#define HAVE_GETHRTIME 1/#define HAVE_GETHRTIME 0/g' $(FFMPEG_BUILD_DIR)/x86/config.h
+
+$(FFMPEG_BUILD_DIR)/x86/libavcodec/libavcodec-linphone-x86.so: $(FFMPEG_BUILD_DIR)/x86/config.h
+ cd $(FFMPEG_BUILD_DIR)/x86 && \
+ make -j${NUMCPUS} \
+ || ( echo "Build of ffmpeg for x86 failed." ; exit 1 )
+
+$(FFMPEG_BUILD_DIR)/x86/libffmpeg-linphone-x86.so: $(FFMPEG_BUILD_DIR)/x86/libavcodec/libavcodec-linphone-x86.so
+ cd $(FFMPEG_BUILD_DIR)/x86 && \
+ rm libavcodec/log2_tab.o && \
+ $(X86_TOOLCHAIN_PATH)gcc -lm -lz --sysroot=$(X86_SYSROOT) -Wl,--no-undefined -Wl,-z,noexecstack -shared libavutil/*.o libavutil/x86/*.o libavcodec/*.o libavcodec/x86/*.o libswscale/*.o -o libffmpeg-linphone-x86.so
+
+build-ffmpeg: $(BUILD_FFMPEG_DEPS)
+
+clean-ffmpeg:
+ rm -rf $(FFMPEG_BUILD_DIR)/arm && \
+ rm -rf $(FFMPEG_BUILD_DIR)/x86
+
+#x264
+ifeq ($(BUILD_VIDEO),1)
+ifeq ($(BUILD_X264), 1)
+BUILD_X264_DEPS=$(X264_SRC_DIR)/log2f_fix_patch_applied.txt $(X264_BUILD_DIR)/arm/libx264.a
+ifeq ($(BUILD_FOR_X86), 1)
+ BUILD_X264_DEPS+=$(X264_BUILD_DIR)/x86/libx264.a
+endif
+endif
+
+X264_SRC_DIR=$(TOPDIR)/submodules/externals/x264
+X264_BUILD_DIR=$(TOPDIR)/submodules/externals/build/x264
+X264_CONFIGURE_OPTIONS=--enable-static
+X264_ARM_CONFIGURE_OPTIONS=--host=arm-none-linux-gnueabi --sysroot=$(ARM_SYSROOT) --cross-prefix=$(ARM_TOOLCHAIN_PATH) --enable-pic
+X264_X86_CONFIGURE_OPTIONS=--host=i686-linux-gnueabi --sysroot=$(X86_SYSROOT) --cross-prefix=$(X86_TOOLCHAIN_PATH)
+
+$(X264_SRC_DIR)/log2f_fix_patch_applied.txt:
+ @patch -p0 < $(TOPDIR)/patches/x264_log2f_fix.patch
+ touch $@
+
+$(X264_BUILD_DIR)/arm/libx264.a:
+ mkdir -p $(X264_BUILD_DIR)/arm && \
+ cd $(X264_SRC_DIR) && \
+ $(X264_SRC_DIR)/configure $(X264_CONFIGURE_OPTIONS) $(X264_ARM_CONFIGURE_OPTIONS) && \
+ make -j$(NUMCPUS) STRIP= && \
+ cp libx264.a $(X264_BUILD_DIR)/arm/libx264.a && \
+ make clean \
+ || ( echo "Build of x264 for arm failed." ; exit 1 )
+
+$(X264_BUILD_DIR)/x86/libx264.a:
+ mkdir -p $(X264_BUILD_DIR)/x86 && \
+ cd $(X264_SRC_DIR) && \
+ $(X264_SRC_DIR)/configure $(X264_CONFIGURE_OPTIONS) $(X264_X86_CONFIGURE_OPTIONS) && \
+ make -j$(NUMCPUS) STRIP= && \
+ cp libx264.a $(X264_BUILD_DIR)/x86/libx264.a && \
+ make clean \
+ || ( echo "Build of x264 for x86 failed." ; exit 1 )
+
+endif
+build-x264: $(BUILD_X264_DEPS)
+
+clean-x264:
+ rm -rf $(X264_BUILD_DIR)/arm && \
+ rm -rf $(X264_BUILD_DIR)/x86
+
+#openh264
+ifeq ($(BUILD_VIDEO),1)
+ifeq ($(BUILD_OPENH264), 1)
+BUILD_OPENH264_DEPS=build-openh264-arm
+ifeq ($(BUILD_FOR_X86), 1)
+ BUILD_OPENH264_DEPS+=build-openh264-x86
+endif
+endif
+endif
+
+OPENH264_SRC_DIR=$(TOPDIR)/submodules/externals/openh264
+OPENH264_BUILD_DIR=$(TOPDIR)/submodules/externals/build/openh264
+OPENH264_BUILD_DIR_ARM=$(OPENH264_BUILD_DIR)/arm
+OPENH264_BUILD_DIR_X86=$(OPENH264_BUILD_DIR)/x86
+
+$(OPENH264_SRC_DIR)/patch.stamp: $(TOPDIR)/patches/openh264-permissive.patch
+ cd $(OPENH264_SRC_DIR) && patch -p1 < $(TOPDIR)/patches/openh264-permissive.patch && touch $(OPENH264_SRC_DIR)/patch.stamp
+
+openh264-patch: $(OPENH264_SRC_DIR)/patch.stamp
+
+openh264-install-headers:
+ mkdir -p $(OPENH264_SRC_DIR)/include/wels
+ rsync -rvLpgoc --exclude ".git" $(OPENH264_SRC_DIR)/codec/api/svc/* $(OPENH264_SRC_DIR)/include/wels/.
+
+copy-openh264-x86: openh264-patch openh264-install-headers
+ mkdir -p $(OPENH264_BUILD_DIR)
+ mkdir -p $(OPENH264_BUILD_DIR_X86)
+ cd $(OPENH264_BUILD_DIR_X86) \
+ && rsync -rvLpgoc --exclude ".git" $(OPENH264_SRC_DIR)/* .
+
+copy-openh264-arm: openh264-patch openh264-install-headers
+ mkdir -p $(OPENH264_BUILD_DIR)
+ mkdir -p $(OPENH264_BUILD_DIR_ARM)
+ cd $(OPENH264_BUILD_DIR_ARM) \
+ && rsync -rvLpgoc --exclude ".git" $(OPENH264_SRC_DIR)/* .
+
+build-openh264-x86: copy-openh264-x86
+ cd $(OPENH264_BUILD_DIR_X86) && \
+ make libraries -j$(NUMCPUS) OS=android ARCH=x86 NDKROOT=$(NDK_PATH) TARGET=$(NDKBUILD_TARGET)
+
+build-openh264-arm: copy-openh264-arm
+ cd $(OPENH264_BUILD_DIR_ARM) && \
+ make libraries -j$(NUMCPUS) OS=android ARCH=arm NDKROOT=$(NDK_PATH) TARGET=$(NDKBUILD_TARGET)
+
+build-openh264: $(BUILD_OPENH264_DEPS)
+
+clean-openh264:
+ cd $(OPENH264_SRC_DIR) && git clean -dfx && git reset --hard
+ rm -rf $(OPENH264_BUILD_DIR_ARM)
+ rm -rf $(OPENH264_BUILD_DIR_X86)
+
#libvpx
+ifeq ($(BUILD_VIDEO),1)
+BUILD_VPX_DEPS=$(LIBVPX_SRC_DIR)/configure_android_x86_patch_applied.txt $(LIBVPX_BUILD_DIR)/arm/libvpx.a
+ifeq ($(BUILD_FOR_X86), 1)
+ BUILD_VPX_DEPS+=$(LIBVPX_BUILD_DIR)/x86/libvpx.a
+endif
+endif
LIBVPX_SRC_DIR=$(TOPDIR)/submodules/externals/libvpx
-$(LIBVPX_SRC_DIR)/vp8/common/asm_com_offsets.c.S:
- cd $(LIBVPX_SRC_DIR) && \
- ./configure --target=armv7-android-gcc --sdk-path=$(NDK_PATH) --enable-error-concealment && \
- make asm_com_offsets.asm \
- || ( echo "VP8 prepare stage failed." ; exit 1 )
-
-prepare-vpx: $(LIBVPX_SRC_DIR)/vp8/common/asm_com_offsets.c.S
-#SILK
-LIBMSSILK_SRC_DIR=$(TOPDIR)/submodules/mssilk
-LIBMSSILK_BUILD_DIR=$(LIBMSSILK_SRC_DIR)
-$(LIBMSSILK_SRC_DIR)/configure:
- cd $(LIBMSSILK_SRC_DIR) && ./autogen.sh
+LIBVPX_BUILD_DIR=$(TOPDIR)/submodules/externals/build/libvpx
+LIBVPX_CONFIGURE_OPTIONS=--disable-vp9 --disable-examples --disable-unit-tests --disable-postproc --enable-error-concealment --enable-debug
-$(LIBMSSILK_BUILD_DIR)/Makefile: $(LIBMSSILK_SRC_DIR)/configure
- cd $(LIBMSSILK_BUILD_DIR) && \
- $(LIBMSSILK_SRC_DIR)/configure --host=arm-linux MEDIASTREAMER_CFLAGS=" " MEDIASTREAMER_LIBS=" "
+$(LIBVPX_SRC_DIR)/configure_android_x86_patch_applied.txt:
+ @patch -p1 < $(TOPDIR)/patches/libvpx_configure_android_x86.patch
+ touch $@
-#make sure to update this path if SILK sdk is changed
-$(LIBMSSILK_BUILD_DIR)/sdk/SILK_SDK_SRC_v1.0.8/SILK_SDK_SRC_ARM_v1.0.8/src/SKP_Silk_resampler.c: $(LIBMSSILK_BUILD_DIR)/Makefile
- cd $(LIBMSSILK_BUILD_DIR)/sdk && \
- make extract-sources \
- || ( echo "SILK audio plugin prepare state failed." ; exit 1 )
+$(LIBVPX_BUILD_DIR)/arm/libvpx.a:
+ mkdir -p $(LIBVPX_BUILD_DIR)/arm && \
+ cd $(LIBVPX_BUILD_DIR)/arm && \
+ $(LIBVPX_SRC_DIR)/configure --target=armv7-android-gcc --sdk-path=$(NDK_PATH) $(LIBVPX_CONFIGURE_OPTIONS) && \
+ make -j${NUMCPUS} \
+ || ( echo "Build of libvpx for arm failed." ; exit 1 )
-prepare-silk: $(LIBMSSILK_BUILD_DIR)/sdk/SILK_SDK_SRC_v1.0.8/SILK_SDK_SRC_ARM_v1.0.8/src/SKP_Silk_resampler.c
+$(LIBVPX_BUILD_DIR)/x86/libvpx.a:
+ mkdir -p $(LIBVPX_BUILD_DIR)/x86 && \
+ cd $(LIBVPX_BUILD_DIR)/x86 && \
+ $(LIBVPX_SRC_DIR)/configure --target=x86-android-gcc --sdk-path=$(NDK_PATH) $(LIBVPX_CONFIGURE_OPTIONS) && \
+ make -j${NUMCPUS} \
+ || ( echo "Build of libvpx for x86 failed." ; exit 1 )
+
+build-vpx: $(BUILD_VPX_DEPS)
+
+clean-vpx:
+ cd $(LIBVPX_SRC_DIR) && git clean -dfx && git reset --hard
+ rm -rf submodules/externals/build/libvpx/arm && \
+ rm -rf submodules/externals/build/libvpx/x86
-#Zrtp
-$(TOPDIR)/submodules/externals/libzrtpcpp/libzrtpcpp-config.h : $(TOPDIR)/submodules/externals/build/libzrtpcpp/libzrtpcpp-config.h
- @cd $(TOPDIR)/submodules/externals/libzrtpcpp/ && \
- cp ../build/libzrtpcpp/libzrtpcpp-config.h . \
- || ( echo "ZRTP prepare state failed." ; exit 1 )
-prepare-zrtp: $(TOPDIR)/submodules/externals/libzrtpcpp/libzrtpcpp-config.h
@@ -91,6 +353,7 @@ $(TOPDIR)/submodules/externals/srtp/config.h : $(TOPDIR)/submodules/externals/bu
prepare-srtp: $(TOPDIR)/submodules/externals/srtp/config.h
+#ms2
prepare-mediastreamer2:
@cd $(TOPDIR)/submodules/linphone/mediastreamer2/src/ && \
eval `cat Makefile.am | grep xxd | grep yuv2rgb.vs | sed 's/\$$(abs_builddir)/./'` && \
@@ -98,45 +361,169 @@ prepare-mediastreamer2:
if ! [ -e yuv2rgb.vs.h ]; then echo "yuv2rgb.vs.h creation error (do you have 'xxd' application installed ?)"; exit 1; fi && \
if ! [ -e yuv2rgb.fs.h ]; then echo "yuv2rgb.fs.h creation error (do you have 'xxd' application installed ?)"; exit 1; fi
-prepare-sources: prepare-ffmpeg prepare-ilbc prepare-vpx prepare-silk prepare-srtp prepare-zrtp prepare-mediastreamer2
+#antlr3
+ANLTR3_SRC_DIR=$(TOPDIR)/submodules/externals/antlr3/runtime/C/include/
+ANTLR3_BUILD_DIR=$(ANTLR3_SRC_DIR)
+$(ANLTR3_SRC_DIR)/antlr3config.h: $(TOPDIR)/submodules/externals/build/antlr3/antlr3config.h
+ cp $(TOPDIR)/submodules/externals/build/antlr3/antlr3config.h $(ANLTR3_SRC_DIR)
+prepare-antlr3: $(ANLTR3_SRC_DIR)/antlr3config.h
-generate-libs:
- $(NDK_PATH)/ndk-build $(NDK_BUILD_OPTIONS)
+%.tokens: %.g
+ $(ANTLR) -make -fo $(dir $^) $^
-update-project:
+#Belle-sip
+BELLESIP_SRC_DIR=$(TOPDIR)/submodules/belle-sip
+BELLESIP_BUILD_DIR=$(BELLESIP_SRC_DIR)
+prepare-belle-sip: $(BELLESIP_SRC_DIR)/src/grammars/belle_sip_message.tokens $(BELLESIP_SRC_DIR)/src/grammars/belle_sdp.tokens
+
+#CUnit
+prepare-cunit: $(TOPDIR)/submodules/externals/cunit/CUnit/Headers/*.h
+ [ -d $(TOPDIR)/submodules/externals/build/cunit/CUnit ] || mkdir $(TOPDIR)/submodules/externals/build/cunit/CUnit
+ cp $^ $(TOPDIR)/submodules/externals/build/cunit/CUnit
+
+$(TOPDIR)/res/raw/rootca.pem:
+ HTTPS_CA_DIR=$(HTTPS_CA_DIR) $(TOPDIR)/submodules/linphone/scripts/mk-ca-bundle.pl $@
+
+prepare-liblinphone_tester: $(TOPDIR)/submodules/linphone/tester/tester_hosts $(TOPDIR)/res/raw/rootca.pem $(TOPDIR)/submodules/linphone/tester/messages.db
+ rm -rf liblinphone_tester/assets/config_files
+ mkdir -p liblinphone_tester/assets/config_files
+ for file in $^; do \
+ cp -rf $$file $(TOPDIR)/liblinphone_tester/assets/config_files/. \
+ ;done
+ cp -rf $(TOPDIR)/submodules/linphone/tester/certificates $(TOPDIR)/liblinphone_tester/assets/config_files
+ cp -rf $(TOPDIR)/submodules/linphone/tester/sounds $(TOPDIR)/liblinphone_tester/assets/config_files
+ cp -rf $(TOPDIR)/submodules/linphone/tester/images $(TOPDIR)/liblinphone_tester/assets/config_files
+ cp -rf $(TOPDIR)/submodules/linphone/tester/rcfiles $(TOPDIR)/liblinphone_tester/assets/config_files
+
+
+#Matroska2
+MATROSKA_SRC_DIR=$(TOPDIR)/submodules/externals/libmatroska
+MATROSKA_BUILD_DIR=$(TOPDIR)/submodules/externals/build/libmatroska
+ifeq ($(BUILD_MATROSKA), 1)
+prepare-matroska2: $(MATROSKA_SRC_DIR)/patch_applied.txt
+else
+prepare-matroska2:
+endif
+
+$(MATROSKA_SRC_DIR)/patch_applied.txt: $(MATROSKA_BUILD_DIR)/fix_libmatroska2.patch
+ cd $(MATROSKA_SRC_DIR); patch -p1 < $<; touch $@
+
+#Build targets
+prepare-sources: build-ffmpeg build-x264 build-openh264 prepare-ilbc build-vpx prepare-srtp prepare-mediastreamer2 prepare-antlr3 prepare-belle-sip $(TOPDIR)/res/raw/rootca.pem prepare-matroska2
+
+GENERATE_OPTIONS = NDK_DEBUG=$(NDK_DEBUG) BUILD_FOR_X86=$(BUILD_FOR_X86) \
+ BUILD_AMRNB=$(BUILD_AMRNB) BUILD_AMRWB=$(BUILD_AMRWB) BUILD_SILK=$(BUILD_SILK) BUILD_G729=$(BUILD_G729) BUILD_OPUS=$(BUILD_OPUS) \
+ BUILD_VIDEO=$(BUILD_VIDEO) BUILD_X264=$(BUILD_X264) BUILD_OPENH264=$(BUILD_OPENH264) ENABLE_OPENH264_DECODER=$(ENABLE_OPENH264_DECODER) BUILD_MATROSKA=$(BUILD_MATROSKA) \
+ BUILD_UPNP=$(BUILD_UPNP) BUILD_ZRTP=$(BUILD_ZRTP) BUILD_WEBRTC_AECM=$(BUILD_WEBRTC_AECM) BUILD_WEBRTC_ISAC=$(BUILD_WEBRTC_ISAC) BUILD_ILBC=$(BUILD_ILBC) \
+ BUILD_FOR_ARM=$(BUILD_FOR_ARM) BUILD_NON_FREE_CODECS=$(BUILD_NON_FREE_CODECS)
+
+
+LIBLINPHONE_OPTIONS = $(GENERATE_OPTIONS) \
+ LIBLINPHONE_VERSION=$(LIBLINPHONE_VERSION) BELLESIP_VERSION=$(BELLESIP_VERSION) USE_JAVAH=$(USE_JAVAH) \
+ BUILD_TUNNEL=$(BUILD_TUNNEL) BUILD_TLS=$(BUILD_TLS) BUILD_SQLITE=$(BUILD_SQLITE) \
+ BUILD_CONTACT_HEADER=$(BUILD_CONTACT_HEADER) BUILD_RTP_MAP=$(BUILD_RTP_MAP) \
+ LIBLINPHONE_EXTENDED_SRC_FILES="$(LIBLINPHONE_EXTENDED_SRC_FILES)" \
+ LIBLINPHONE_EXTENDED_C_INCLUDES="$(LIBLINPHONE_EXTENDED_C_INCLUDES)" \
+ LIBLINPHONE_EXTENDED_CFLAGS="$(LIBLINPHONE_EXTENDED_CFLAGS)" \
+ APP_STL="$(APP_STL)" \
+ BUILD_DONT_CHECK_HEADERS_IN_MESSAGE=$(BUILD_DONT_CHECK_HEADERS_IN_MESSAGE)
+
+MEDIASTREAMER2_OPTIONS = $(GENERATE_OPTIONS) BUILD_MEDIASTREAMER2_SDK=1
+
+
+generate-libs: prepare-sources javah
+ $(NDK_PATH)/ndk-build $(LIBLINPHONE_OPTIONS) -j$(NUMCPUS) TARGET_PLATFORM=$(NDKBUILD_TARGET)
+ ./bsed.sh # Fix path to libffmpeg library in linphone.so because of Android M Preview issue: https://code.google.com/p/android-developer-preview/issues/detail?id=2239
+
+generate-mediastreamer2-libs: prepare-sources
+ @cd $(TOPDIR)/submodules/linphone/mediastreamer2/java && \
+ $(NDK_PATH)/ndk-build $(MEDIASTREAMER2_OPTIONS) -j$(NUMCPUS) TARGET_PLATFORM=$(NDKBUILD_TARGET)
+
+update-project: $(TOPDIR)/res/raw/rootca.pem
+ $(SDK_PATH)/android update project --path . --target $(ANDROID_MOST_RECENT_TARGET)
+ $(SDK_PATH)/android update test-project --path tests -m .
+ $(SDK_PATH)/android update project --path liblinphone_tester --target $(ANDROID_MOST_RECENT_TARGET)
+
+update-mediastreamer2-project:
+ @cd $(TOPDIR)/submodules/linphone/mediastreamer2/java && \
$(SDK_PATH)/android update project --path . --target $(ANDROID_MOST_RECENT_TARGET)
-generate-apk:
- ant partial-clean
+liblinphone_tester: update-project prepare-sources prepare-cunit prepare-liblinphone_tester javah
+ $(NDK_PATH)/ndk-build -C liblinphone_tester $(LIBLINPHONE_OPTIONS) -j$(NUMCPUS) TARGET_PLATFORM=$(NDKBUILD_TARGET)
+ $(MAKE) -C liblinphone_tester
+
+javah:
+ $(ANT) javah
+
+generate-apk: java-clean generate-libs
echo "version.name=$(LINPHONE_ANDROID_DEBUG_VERSION)" > default.properties
- ant debug
+ $(ANT) debug
+
+generate-mediastreamer2-apk: java-clean generate-mediastreamer2-libs
+ @cd $(TOPDIR)/submodules/linphone/mediastreamer2/java && \
+ echo "version.name=$(LINPHONE_ANDROID_DEBUG_VERSION)" > default.properties && \
+ $(ANT) debug
+
+uninstall:
+ adb uninstall $(PACKAGE_NAME)
install-apk:
ant installd
release: update-project
- ant clean
- echo "What is the version name for the release ?"; \
- read version; \
- echo "version.name=$$version" > default.properties
- ant release
+ $(ANT) clean
+ patch -p1 < release.patch
+ cat ant.properties | grep version.name > default.properties
+ $(ANT) release
+ patch -Rp1 < release.patch
run-linphone:
ant run
-run-tests:
- ant partial-clean && \
- $(SDK_PLATFORM_TOOLS_PATH)/adb uninstall org.linphone.test
- $(SDK_PLATFORM_TOOLS_PATH)/adb uninstall org.linphone
- @cd $(TOPDIR)/tests/ && \
- $(SDK_PATH)/android update test-project --path . -m ../ && \
- ant debug && \
- ant installd && \
- adb shell am instrument -w -e size small org.linphone.test/android.test.InstrumentationTestRunner
+run-liblinphone-tests: liblinphone_tester
+ $(MAKE) -C liblinphone_tester run-all-tests
-clean:
- $(NDK_PATH)/ndk-build $(NDK_BUILD_OPTIONS) clean
- ant clean
+run-basic-tests: update-project
+ $(ANT) partial-clean
+ $(MAKE) -C tests run-basic-tests ANT_SILENT=$(ANT_SILENT)
-.PHONY: clean
+run-all-tests: update-project
+ $(ANT) partial-clean
+ $(MAKE) -C tests run-all-tests ANT_SILENT=$(ANT_SILENT)
+clean-ndk-build:
+ - $(NDK_PATH)/ndk-build clean $(LIBLINPHONE_OPTIONS)
+ $(ANT) clean
+ @if [ -f $(TOPDIR)/submodules/linphone/mediastreamer2/java/project.properties ]; then \
+ cd $(TOPDIR)/submodules/linphone/mediastreamer2/java && $(ANT) clean; \
+ fi
+
+.NOTPARALLEL clean-native: clean-ndk-build clean-ffmpeg clean-x264 clean-openh264 clean-vpx
+
+
+java-clean:
+ $(ANT) clean
+
+clean: clean-native java-clean
+
+veryclean: clean
+
+.PHONY: clean install-apk run-linphone
+
+generate-sdk: liblinphone-android-sdk
+
+liblinphone-android-sdk: generate-apk
+ $(ANT) liblinphone-android-sdk
+
+linphone-android-sdk: generate-apk
+ $(ANT) linphone-android-sdk
+
+mediastreamer2-sdk: update-mediastreamer2-project generate-mediastreamer2-apk
+ @cd $(TOPDIR)/submodules/linphone/mediastreamer2/java && \
+ $(ANT) mediastreamer2-sdk
+
+pull-transifex:
+ tx pull -af
+
+push-transifex:
+ tx push -s -t -f --no-interactive
diff --git a/README b/README
index a655c6113..1ceb2271b 100644
--- a/README
+++ b/README
@@ -1,38 +1,146 @@
- LINPHONE for ANDROID
- ****************************
+ ****************************
+ * LINPHONE for ANDROID *
+ ****************************
+
+COMPILATION INSTRUCTIONS
+************************
To build liblinphone for Android, you must:
+-------------------------------------------
0) download the Android sdk with platform-tools and tools updated to latest revision (at least API 16 is needed), then add both 'tools' and 'platform-tools' folders in your path.
-1) download the Android ndk (>=r8b) from google and add it to your path.
-2) install the autotools: autoconf, automake, aclocal, libtoolize, pkgconfig
-2bis) on some 64 bits systems you'll need the ia32-libs package
+1) download the Android ndk (=r10c) from google and add it to your path (no symlink !!!).
+2) install yasm, nasm, curl, ant, rsync and the autotools: autoconf, automake, aclocal, libtoolize, pkgconfig
+ On 64 bits linux systems you'll need the ia32-libs package
+ With the latest Debian (multiarch), you need this:
+ dpkg --add-architecture i386
+ aptitude update
+ aptitude install libstdc++6:i386 libgcc1:i386 zlib1g:i386 libncurses5:i386
3) run the Makefile script in the top level directory. This will download iLBC source files and convert some assembly files in VP8 project.
$ make
-4) To install the generated apk into a plugged device, run
+4) (Optional) To install the generated apk into a plugged device, run
$ make install
+5) (Optional) To generate a liblinphone SDK zip containing a full jar and native libraries, run
+ $ make liblinphone-android-sdk
+6) (Optional) To generate a libmediastreamer2 SDK zip containing a full jar and native libraries, run
+ $ make mediastreamer2-sdk
+7) (Optional) To generate a signed apk to publish on the Google Play, run
+ $ make release
+Make sure you filled the ant.properties values for version.name, key.store and key.alias in order to correctly sign the generated apk.
+You also may want to create a file name ant_password.properties with the following:
+key.store.password=[your_password]
+key.alias.password=[your_password]
+If you don't, the passwords will be asked at the signing phase.
To run the tutorials:
+--------------------
1) open the res/values/non_localizable_custom.xml file and change the value of the show_tutorials_instead_of_app to true.
2) compile again using make && make install.
3) /!\ don't forget to put it back to false to run the linphone application normally. /!\
-To create an apk with a different package name, you need to edit the custom_rules.xml file:
+To create an apk with a different package name
+----------------------------------------------
+You need to edit the custom_rules.xml file:
1) look for the property named "linphone.package.name" and change it value accordingly
-2) run again the Makefile script by calling "make"
+2) also update the values in the AndroidManifest file where the comment appears
+3) update the path to the sounds in the linphonerc-factory files in the res folders and optionally change default sip account on linphonerc-default
+4) run again the Makefile script by calling "make"
+
+To run the liblinphone test suite on android
+--------------------------------------------
+Simply run
+ $ make liblinphone_tester
+This will be build everything, generate an apk, and install it on the connected device if any.
+
+You can speed up the compilation by using ccache (compiler cache, see https://ccache.samba.org/). Simply export:
+export NDK_CCACHE=ccache
+
+TROUBLESHOOTING
+***************
+If you encounter the following issue:
+E/dalvikvm( 2465): dlopen("/data/app-lib/org.linphone-1/liblinphone-armeabi-v7a.so") failed: Cannot load library: soinfo_relocate(linker.cpp:975): cannot locate symbol "rand" referenced by "liblinphone-armeabi-v7a.so"...
+it's because you have installed the android-21 platform (which is chosen automatically because it's the most recent) and you deployed the apk on a android < 5 device.
+To fix this, in the Makefile, force ANDROID_MOST_RECENT_TARGET=android-19
+
+If you encounter troubles with the make clean target and you are using the 8e android ndk, the solution can be found here: https://groups.google.com/forum/?fromgroups=#!topic/android-ndk/3wIbb-h3nDU
+
+If you built the app using eclipse, ensure you ran at least once the make command (see above steps 0 to 3) ! Else you'll have this exceptions:
+FATAL EXCEPTION: main
+java.lang.ExceptionInInitializerError
+...
+Caused by: java.lang.UnsatisfiedLinkError: Couldn't load linphone-armeabi-v7a: findLibrary returned null
+...
+
+BUILD OPTIONS
+*************
Some options can be passed to make, like "make SOME_OPTION=SOME_VALUE".
-Option Name | Possible values | Default value
--------------------------------------------------------------------------------------------------------------------------------------------------------
-BUILD_X264 0 (don't build x264) or 1 (build x264) | 0
-BUILD_AMRNB 0 (don't build amrnb codec), light (try to use amrnb codec from android), full (build your own amrnb codec) | full
-BUILD_AMRWB 0 (don't build amrwb codec), 1 (build your own amrwb codec) | 0
-BUILD_GPLV3_ZRTP 0 (don't support ZRTP), 1 (support ZRTP and make the whole program GPLv3) | 0
-BUILD_SILK 0 (don't build silk plugin), 1 (build silk) [silk is Skype nonfree patented audio codec] | 1
-BUILD_G729 0 (don't build g729 plugin), 1 (build g729) [g729 is nonfree patented audio codec, contact Sipro lab for more details] | 0
-BUILD_TUNNEL 0 (don't build tunnel), 1 (build tunnel) [requires a tunnel implementation in submodules/linphone/tunnel] | 0
-BUILD_WEBRTC_AECM 0 (don't build echo canceler), 1 (build echo canceler) | 1
-USE_JAVAH 0 (don't generate header), 1 (generate header for linphone_core_jni) [used to check errors at liblinphone compilation] | 1
-BUILD_FOR_X86 0 (don't generate liblinphone libraries for x86 architecture), 1 (build liblinphone libraries for x86 architecture) | 1
+ENABLE_GPL_THIRD_PARTIES
+ values: 0 (GPL third parties disabled) or 1 (GPL third parties enabled), default value: 1
+ GPL third parties are: X264 and G729
-If you encounter troubles with the make clean target and you are using the 8e android ndk, the solution can be found here: https://groups.google.com/forum/?fromgroups=#!topic/android-ndk/3wIbb-h3nDU
+BUILD_VIDEO
+ values: 0 (no video) or 1 (video enabled), default value: 1
+
+BUILD_OPENH264
+ values: 0 (don't build openH264) or 1 (build openH264), default value: 1
+
+ENABLE_OPENH264_DECODER
+ values: 0 (disable openh264 decoder) or 1 (enable openh264 decoder), default value: 1
+
+BUILD_X264
+ values: 0 (don't build x264) or 1 (build x264), default value: 0
+
+BUILD_AMRNB
+ values: 0 (don't build amrnb codec), light (try to use amrnb codec from android), full (build your own amrnb codec), default value: full
+
+BUILD_AMRWB
+ values: 0 (don't build amrwb codec), 1 (build your own amrwb codec): default value: 1
+
+BUILD_ZRTP
+ values: 0 (don't support ZRTP), 1 (support ZRTP), default value: 1
+
+BUILD_SILK
+ values: 0 (don't build silk plugin), 1 (build silk) [silk is Skype nonfree patented audio codec], default value: 1
+
+BUILD_G729
+ values: 0 (don't build g729 plugin), 1 (build g729) [g729 is nonfree patented audio codec, contact Sipro lab for more details]
+ default value: 1
+
+BUILD_TUNNEL
+ values: 0 (don't build tunnel), 1 (build tunnel) [requires a non-free tunnel implementation in submodules/linphone/tunnel]
+ default value: 0
+
+BUILD_WEBRTC_AECM
+ values: 0 (don't build echo canceler), 1 (build echo canceler)
+ default value: 1
+
+USE_JAVAH
+ values: 0 (don't generate header), 1 (generate header for linphone_core_jni) [used to check errors at liblinphone compilation]
+ default value: 1
+
+BUILD_FOR_X86
+ values: 0 (don't generate liblinphone libraries for x86 architecture), 1 (build liblinphone libraries for x86 architecture)
+ default value: 1
+
+BUILD_SQLITE
+ values: 0 (don't build sqlite3), 1 (build sqlite3) [used to store chat messages inside liblinphone]
+ default value: 1
+
+BUILD_TLS
+ values: 0 (don't build tls), 1 (do build tls), default value: 1
+
+BUILD_WEBRTC_ISAC
+ values: 0 (don't build isac), 1 (do build isac), default value: 1
+
+BUILD_OPUS
+ values: 0 (don't build opus), 1 (do build opus), default value: 1
+
+BUILD_UPNP
+ values: 0 (don't build upnp), 1 (do build upnp), default value: 1
+
+BUILD_MATROSKA
+ values: 0 (don't build matroska and ebml), 1 (do build matroska and ebml), default value: 0
+
+BUILD_ILBC
+ values: 0 (don't build iLBC), 1 (do build iLBC), default value: 1
diff --git a/ant.properties b/ant.properties
index 7f65258e5..d2cc146d1 100644
--- a/ant.properties
+++ b/ant.properties
@@ -1,3 +1,4 @@
source.dir=src:submodules/linphone/mediastreamer2/java/src:submodules/linphone/java/j2se:submodules/linphone/java/common:submodules/linphone/java/impl:submodules/linphone/coreapi/help/java:submodules/externals/axmlrpc/src/main/java
key.store=bc-android.keystore
key.alias=nw8000
+version.name=2.4.0
diff --git a/bsed.sh b/bsed.sh
new file mode 100755
index 000000000..b357ae14e
--- /dev/null
+++ b/bsed.sh
@@ -0,0 +1,48 @@
+#!/bin/bash
+
+# Script found at http://everydaywithlinux.blogspot.fr/2012/11/patch-strings-in-binary-files-with-sed.html
+
+function patch_strings_in_file() {
+ local FILE="$1"
+ local PATTERN="$2"
+ local REPLACEMENT="$3"
+
+ # Find all unique strings in FILE that contain the pattern
+ STRINGS=$(strings ${FILE} | grep ${PATTERN} | sort -u -r)
+
+ if [ "${STRINGS}" != "" ] ; then
+ echo "File '${FILE}' contain strings with '${PATTERN}' in them:"
+
+ for OLD_STRING in ${STRINGS} ; do
+ # Create the new string with a simple bash-replacement
+ NEW_STRING=${OLD_STRING//${PATTERN}/${REPLACEMENT}}
+
+ # Create null terminated ASCII HEX representations of the strings
+ OLD_STRING_HEX="$(echo -n ${OLD_STRING} | xxd -g 0 -u -ps -c 256)00"
+ NEW_STRING_HEX="$(echo -n ${NEW_STRING} | xxd -g 0 -u -ps -c 256)00"
+
+ if [ ${#NEW_STRING_HEX} -le ${#OLD_STRING_HEX} ] ; then
+ # Pad the replacement string with null terminations so the
+ # length matches the original string
+ while [ ${#NEW_STRING_HEX} -lt ${#OLD_STRING_HEX} ] ; do
+ NEW_STRING_HEX="${NEW_STRING_HEX}00"
+ done
+
+ # Now, replace every occurrence of OLD_STRING with NEW_STRING
+ echo -n "Replacing ${OLD_STRING} with ${NEW_STRING}... "
+ hexdump -ve '1/1 "%.2X"' ${FILE} | \
+ sed "s/${OLD_STRING_HEX}/${NEW_STRING_HEX}/g" | \
+ xxd -r -p > ${FILE}.tmp
+ chmod --reference ${FILE} ${FILE}.tmp
+ mv ${FILE}.tmp ${FILE}
+ echo "Done!"
+ else
+ echo "New string '${NEW_STRING}' is longer than old" \
+ "string '${OLD_STRING}'. Skipping."
+ fi
+ done
+ fi
+}
+
+patch_strings_in_file libs/armeabi-v7a/liblinphone-armeabi-v7a.so "./obj/local/armeabi-v7a/libffmpeg-linphone-arm.so" "libffmpeg-linphone-arm.so"
+patch_strings_in_file libs/x86/liblinphone-x86.so "./obj/local/x86/libffmpeg-linphone-x86.so" "libffmpeg-linphone-x86.so"
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 000000000..c341bf0f5
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,45 @@
+buildscript {
+ repositories {
+ mavenCentral()
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:1.0.0'
+ }
+}
+apply plugin: 'android'
+
+dependencies {
+ compile fileTree(dir: 'libs', include: '*.jar')
+}
+
+android {
+ compileSdkVersion 22
+ buildToolsVersion "20.0.0"
+
+ sourceSets {
+ main {
+ manifest.srcFile 'AndroidManifest.xml'
+ java.srcDirs = ['submodules/linphone/mediastreamer2/java/src','submodules/linphone/java/j2se','submodules/linphone/java/common','submodules/linphone/java/impl','submodules/externals/axmlrpc/src/main/java','submodules/linphone/coreapi/help/java','src']
+ resources.srcDirs = ['submodules/linphone/mediastreamer2/java/src','submodules/linphone/java/j2se','submodules/linphone/java/common','submodules/linphone/java/impl','submodules/externals/axmlrpc/src/main/java','submodules/linphone/coreapi/help/java','src']
+ aidl.srcDirs = ['submodules/linphone/mediastreamer2/java/src','submodules/linphone/java/j2se','submodules/linphone/java/common','submodules/linphone/java/impl','submodules/externals/axmlrpc/src/main/java','submodules/linphone/coreapi/help/java','src']
+ renderscript.srcDirs = ['submodules/linphone/mediastreamer2/java/src','submodules/linphone/java/j2se','submodules/linphone/java/common','submodules/linphone/java/impl','submodules/externals/axmlrpc/src/main/java','submodules/linphone/coreapi/help/java','src']
+ res.srcDirs = ['res']
+ assets.srcDirs = ['assets']
+ jniLibs.srcDir 'libs'
+
+ java.exclude '**/mediastream/MediastreamerActivity.java'
+ }
+
+ // Move the tests to tests/java, tests/res, etc...
+ instrumentTest.setRoot('tests')
+
+ // Move the build types to build-types/
+ // For instance, build-types/debug/java, build-types/debug/AndroidManifest.xml, ...
+ // This moves them out of them default location under src//... which would
+ // conflict with src/ being used by the main source set.
+ // Adding new build types or product flavors should be accompanied
+ // by a similar customization.
+ debug.setRoot('build-types/debug')
+ release.setRoot('build-types/release')
+ }
+}
diff --git a/build.xml b/build.xml
index cc1aeac67..c23990f28 100644
--- a/build.xml
+++ b/build.xml
@@ -26,8 +26,9 @@
application and should be checked into Version Control Systems.
-->
-
+
+
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/check_tools.sh b/check_tools.sh
new file mode 100755
index 000000000..cba82f787
--- /dev/null
+++ b/check_tools.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+
+error_on_quit=0
+
+echo_err() {
+ echo "$@" >&2
+ error_on_quit=1
+}
+
+check_installed() {
+ if [ -z "$(which $1)" ]; then
+ echo_err "Could not find $1. Please install $2."
+ return 1
+ fi
+ return 0
+}
+
+for prog in automake autoconf pkg-config java ant yasm nasm wget; do
+ check_installed "$prog" "it"
+done
+check_installed "libtoolize" "libtool"
+check_installed "ndk-build" "android NDK"
+if check_installed "android" "android SDK"; then
+ check_installed "adb" "android SDK platform tools"
+ # check that at least one target is installed
+ if [ -z "$(android list target -c)" ]; then
+ echo_err "Install at least one android target in the android SDK"
+ fi
+fi
+if nasm -f elf32 2>&1 | grep -q "fatal: unrecognised output format"; then
+ echo_err "Invalid version of nasm: your version does not support elf32 output format. If you have installed nasm, please check that your PATH env variable is set correctly."
+fi
+if ! (find submodules/linphone/mediastreamer2 -mindepth 1 2>/dev/null | grep -q . \
+ || find submodules/linphone/oRTP -mindepth 1 2>/dev/null | grep -q .); then
+ echo_err "Missing some git submodules. Did you run 'git submodule update --init --recursive'?"
+fi
+# Android NDK should NOT be simlinked!
+if [ -L "$ANDROID_NDK" ] && [ -d "$ANDROID_NDK" ]; then
+ echo_err "ANDROID_NDK=$ANDROID_NDK must NOT be a symbolic link, please modify it accordingly"
+fi
+
+if [ $error_on_quit = 0 ]; then
+ rm -f check_tools.mk
+ touch check_tools.mk
+ echo "JAVA=\"$(which java)\"" >> check_tools.mk
+ echo "ANTLR=\"$(which java)\" -jar \"submodules/externals/antlr3/antlr-3.2.jar\"" >> check_tools.mk
+else
+ echo "Failed to detect required tools, aborting."
+fi
+
+exit $error_on_quit
diff --git a/custom_rules.xml b/custom_rules.xml
index 2e6e2dde5..bbf9ae858 100644
--- a/custom_rules.xml
+++ b/custom_rules.xml
@@ -3,21 +3,12 @@
-
-
-
-
-
-
+
Generate JNI header
@@ -37,6 +28,14 @@
+
+
+
+
+
+
+
+
@@ -51,34 +50,25 @@
-
+
-
-
-
-
-
-
-
-
-
Generate Javadoc
-
-
+ stylesheetfile="${sdk.dir}/docs/assets/android-developer-docs.css">
+
-
+
@@ -106,7 +96,7 @@
-
+
@@ -121,4 +111,39 @@
+
+
+ Creating library output jar file...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Creating library output jar file...
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 000000000..8c0fb64a8
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 000000000..ab2cc719c
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Tue Dec 09 14:35:04 CET 2014
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.2.1-all.zip
diff --git a/jni/Android.mk b/jni/Android.mk
index 6390ab9c2..c1951fdde 100755
--- a/jni/Android.mk
+++ b/jni/Android.mk
@@ -1,31 +1,31 @@
# script expect linphone-root-dir variable to be set by parent !
-#default values
-ifeq ($(BUILD_AMRNB),)
-BUILD_AMRNB=light
-endif
-ifeq ($(BUILD_AMRWB),)
-BUILD_AMRWB=0
-endif
-ifeq ($(BUILD_G729),)
-BUILD_G729=0
-endif
-BUILD_SRTP=1
-
-BUILD_X264=0
-LINPHONE_VIDEO=0
-ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
-BUILD_X264=1
-LINPHONE_VIDEO=1
+#enable video on armv7 and x86 targets only
+#since we want to modify BUILD_VIDEO and BUILD_X264 depending on platform, we need to make a copy because the
+#variables given on command line take precedence over the ones defined internally.
+ifeq ($(TARGET_ARCH_ABI), armeabi)
+_BUILD_X264=0
+_BUILD_OPENH264=0
+_BUILD_VIDEO=0
+else
+_BUILD_X264=$(BUILD_X264)
+_BUILD_OPENH264=$(BUILD_OPENH264)
+_BUILD_VIDEO=$(BUILD_VIDEO)
endif
-include $(linphone-root-dir)/submodules/linphone/mediastreamer2/src/android/libneon/Android.mk
+ifeq ($(_BUILD_VIDEO),0)
+ifeq (,$(DUMP_VAR))
+$(info $(TARGET_ARCH_ABI): Video is disabled for targets other than armeabi-v7a and x86)
+endif
+endif
-##ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
-ifeq ($(BUILD_GPLV3_ZRTP), 1)
+#libxml2
+include $(linphone-root-dir)/submodules/externals/build/libxml2/Android.mk
+
+ifeq ($(BUILD_ZRTP), 1)
BUILD_SRTP=1
ZRTP_C_INCLUDE= \
- $(linphone-root-dir)/submodules/externals/libzrtpcpp/src
+ $(linphone-root-dir)/submodules/bzrtp/include
endif
ifeq ($(BUILD_SRTP), 1)
@@ -34,32 +34,35 @@ SRTP_C_INCLUDE= \
$(linphone-root-dir)/submodules/externals/srtp/include \
$(linphone-root-dir)/submodules/externals/srtp/crypto/include
endif
-#endif
+
+
+#sqlite
+ifeq ($(BUILD_SQLITE),1)
+include $(linphone-root-dir)/submodules/externals/build/sqlite/Android.mk
+endif
#libupnp
ifeq ($(BUILD_UPNP),1)
include $(linphone-root-dir)/submodules/externals/build/libupnp/Android.mk
endif
-#libxml2 + xml2lpc + lpc2xml
-ifeq ($(BUILD_REMOTE_PROVISIONING),1)
-include $(linphone-root-dir)/submodules/externals/build/libxml2/Android.mk
-include $(linphone-root-dir)/submodules/linphone/build/android/xml2lpc.mk
-include $(linphone-root-dir)/submodules/linphone/build/android/lpc2xml.mk
-endif
-
# Speex
include $(linphone-root-dir)/submodules/externals/build/speex/Android.mk
# Gsm
include $(linphone-root-dir)/submodules/externals/build/gsm/Android.mk
-include $(linphone-root-dir)/submodules/externals/build/exosip/Android.mk
+# Matroska
+ifeq ($(BUILD_MATROSKA), 1)
+include $(linphone-root-dir)/submodules/externals/build/libmatroska/Android.mk
+endif
-include $(linphone-root-dir)/submodules/externals/build/osip/Android.mk
+include $(linphone-root-dir)/submodules/externals/build/polarssl/Android.mk
+ifeq ($(BUILD_MEDIASTREAMER2_SDK), 0)
+include $(linphone-root-dir)/submodules/externals/build/antlr3/Android.mk
+include $(linphone-root-dir)/submodules/belle-sip/build/android/Android.mk
+endif
-# Openssl
-include $(linphone-root-dir)/submodules/externals/openssl/Android.mk
include $(linphone-root-dir)/submodules/linphone/oRTP/build/android/Android.mk
@@ -67,51 +70,59 @@ include $(linphone-root-dir)/submodules/linphone/mediastreamer2/build/android/An
include $(linphone-root-dir)/submodules/linphone/mediastreamer2/tools/Android.mk
+#tunnel
ifeq ($(BUILD_TUNNEL), 1)
include $(linphone-root-dir)/submodules/tunnel/Android.mk
endif
ifeq ($(BUILD_SILK), 1)
ifeq (,$(DUMP_VAR))
-$(info Build proprietary SILK plugin for mediastreamer2)
+$(info $(TARGET_ARCH_ABI): Build proprietary SILK plugin for mediastreamer2)
endif
include $(linphone-root-dir)/submodules/mssilk/Android.mk
endif
-
-ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+ifeq ($(BUILD_ILBC), 1)
include $(linphone-root-dir)/submodules/msilbc/Android.mk
+endif
-ifeq ($(BUILD_X264), 1)
+ifeq ($(_BUILD_VIDEO),1)
+
+ifeq ($(_BUILD_X264),1)
ifeq (,$(DUMP_VAR))
-$(info Build X264 plugin for mediastreamer2)
+$(info $(TARGET_ARCH_ABI): Build X264 plugin for mediastreamer2)
endif
include $(linphone-root-dir)/submodules/msx264/Android.mk
include $(linphone-root-dir)/submodules/externals/build/x264/Android.mk
endif
-include $(linphone-root-dir)/submodules/externals/build/ffmpeg/Android.mk
-include $(linphone-root-dir)/submodules/externals/build/ffmpeg-no-neon/Android.mk
-
-include $(linphone-root-dir)/submodules/externals/build/libvpx/Android.mk
-endif #armeabi-v7a
-
-
-ifeq ($(BUILD_GPLV3_ZRTP), 1)
+ifeq ($(_BUILD_OPENH264),1)
ifeq (,$(DUMP_VAR))
-$(info Build ZRTP support - makes application GPLv3)
+$(info $(TARGET_ARCH_ABI): Build OpenH264 plugin for mediastreamer2)
endif
-include $(linphone-root-dir)/submodules/externals/build/libzrtpcpp/Android.mk
+include $(linphone-root-dir)/submodules/msopenh264/Android.mk
+include $(linphone-root-dir)/submodules/externals/build/openh264/Android.mk
+endif
+
+include $(linphone-root-dir)/submodules/externals/build/ffmpeg/Android.mk
+include $(linphone-root-dir)/submodules/externals/build/libvpx/Android.mk
+
+
+endif #_BUILD_VIDEO
+
+
+ifeq ($(BUILD_ZRTP), 1)
+ifeq (,$(DUMP_VAR))
+$(info $(TARGET_ARCH_ABI): Build ZRTP support)
+endif
+include $(linphone-root-dir)/submodules/bzrtp/Android.mk
endif
ifeq ($(BUILD_SRTP), 1)
include $(linphone-root-dir)/submodules/externals/build/srtp/Android.mk
endif
-ifeq ($(TARGET_ARCH_ABI), armeabi-v7a)
include $(linphone-root-dir)/submodules/linphone/build/android/Android.mk
-endif
-include $(linphone-root-dir)/submodules/linphone/build/android/Android-no-neon.mk
_BUILD_AMR=0
ifneq ($(BUILD_AMRNB), 0)
@@ -136,14 +147,40 @@ include $(linphone-root-dir)/submodules/bcg729/Android.mk
include $(linphone-root-dir)/submodules/bcg729/msbcg729/Android.mk
endif
-ifneq ($(BUILD_WEBRTC_AECM), 0)
-ifneq ($(TARGET_ARCH), x86)
+ifneq ($(BUILD_OPUS), 0)
+include $(linphone-root-dir)/submodules/externals/build/opus/Android.mk
+endif
+
+WEBRTC_BUILD_NEON_LIBS=false
+
+# AECM
+ifneq ($(BUILD_WEBRTC_AECM),0)
ifeq ($(TARGET_ARCH_ABI), armeabi-v7a)
+$(info $(TARGET_ARCH_ABI): Build NEON modules for AECM)
WEBRTC_BUILD_NEON_LIBS=true
endif
+
+$(info $(TARGET_ARCH_ABI): Build AECM from WebRTC)
include $(linphone-root-dir)/submodules/externals/build/webrtc/system_wrappers/Android.mk
-include $(linphone-root-dir)/submodules/externals/build/webrtc/common_audio/signal_processing/Android.mk
include $(linphone-root-dir)/submodules/externals/build/webrtc/modules/audio_processing/utility/Android.mk
include $(linphone-root-dir)/submodules/externals/build/webrtc/modules/audio_processing/aecm/Android.mk
endif
+
+# iSAC
+ifneq ($(BUILD_WEBRTC_ISAC),0)
+# don't build for neon in x86
+ifeq ($(TARGET_ARCH_ABI), armeabi-v7a)
+$(info $(TARGET_ARCH_ABI): Build NEON modules for ISAC)
+WEBRTC_BUILD_NEON_LIBS=true
+endif
+
+$(info $(TARGET_ARCH_ABI): Build iSAC plugin for mediastreamer2)
+include $(linphone-root-dir)/submodules/externals/build/webrtc/modules/audio_coding/codecs/isac/fix/source/Android.mk
+endif
+
+# common modules for ISAC and AECM
+ifneq ($(BUILD_WEBRTC_AECM)$(BUILD_WEBRTC_ISAC),00)
+$(info $(TARGET_ARCH_ABI): Build common modules for iSAC and AECM ($(BUILD_WEBRTC_AECM)$(BUILD_WEBRTC_ISAC)))
+include $(linphone-root-dir)/submodules/externals/build/webrtc/common_audio/signal_processing/Android.mk
+include $(linphone-root-dir)/submodules/mswebrtc/Android.mk
endif
diff --git a/jni/Application.mk b/jni/Application.mk
index a2c7ff6fb..62337407e 100644
--- a/jni/Application.mk
+++ b/jni/Application.mk
@@ -1,33 +1,74 @@
APP_PROJECT_PATH := $(call my-dir)/../
-APP_MODULES :=libspeex libgsm libortp libosip2 libeXosip2 libmediastreamer2 liblinphone liblinphonenoneon libneon
-APP_STL := stlport_static
+NDK_TOOLCHAIN_VERSION := 4.8
+
+ifeq ($(BUILD_MEDIASTREAMER2_SDK),)
+BUILD_MEDIASTREAMER2_SDK=0
+endif
+
+APP_MODULES :=libspeex libgsm libortp libmediastreamer2
+ifeq ($(BUILD_MEDIASTREAMER2_SDK), 0)
+APP_MODULES += antlr3 libbellesip liblinphone liblpxml2
+endif
+
+#default values:
+
+ifeq ($(BUILD_AMRNB),)
+BUILD_AMRNB=light
+endif
+
+ifeq ($(BUILD_AMRWB),)
+BUILD_AMRWB=0
+endif
+
+ifeq ($(BUILD_SRTP),)
+BUILD_SRTP=1
+endif
+
+ifeq ($(BUILD_X264),)
+BUILD_X264=0
+endif
+
+ifeq ($(BUILD_OPENH264),)
+BUILD_OPENH264=0
+endif
+
+ifeq ($(BUILD_G729),)
+BUILD_G729=0
+endif
+
+ifeq ($(BUILD_VIDEO),)
+BUILD_VIDEO=1
+endif
+
+ifeq ($(BUILD_MEDIASTREAMER2_SDK), 0)
+#sqlite
+ifeq ($(BUILD_SQLITE),1)
+APP_MODULES += liblinsqlite
+endif
#uPnp
ifeq ($(BUILD_UPNP),1)
APP_MODULES += libupnp
endif
-#remote provisioning
-ifeq ($(BUILD_REMOTE_PROVISIONING),1)
-APP_MODULES += liblpxml2 libxml2lpc liblpc2xml
+ifeq ($(BUILD_TLS),1)
+APP_MODULES +=polarssl
+endif
endif
-#default values
-ifeq ($(BUILD_AMRNB),)
-BUILD_AMRNB=light
-endif
-ifeq ($(BUILD_AMRWB),)
-BUILD_AMRWB=0
-endif
-ifeq ($(BUILD_SRTP),)
-BUILD_SRTP=1
-endif
-
-ifeq ($(LINPHONE_VIDEO),1)
-APP_MODULES += liblinavutil liblinavcore liblinavcodec liblinswscale
-APP_MODULES += liblinavcodecnoneon
+ifeq ($(BUILD_VIDEO),1)
+APP_MODULES += libffmpeg-linphone
APP_MODULES += libvpx
+ifeq ($(BUILD_X264),1)
+APP_MODULES +=libx264 libmsx264
endif
+ifeq ($(BUILD_OPENH264),1)
+APP_MODULES += libopenh264 libmsopenh264
+endif
+ifeq ($(BUILD_MATROSKA), 1)
+APP_MODULES += libmatroska2
+endif
+endif # BUILD_VIDEO
_BUILD_AMR=0
ifneq ($(BUILD_AMRNB), 0)
@@ -46,10 +87,6 @@ ifneq ($(BUILD_AMRWB), 0)
APP_MODULES += libvoamrwbenc
endif
-ifeq ($(BUILD_X264),1)
-APP_MODULES +=libx264 libmsx264
-endif
-
ifeq ($(BUILD_SILK),1)
APP_MODULES +=libmssilk
endif
@@ -58,11 +95,25 @@ ifeq ($(BUILD_G729),1)
APP_MODULES +=libbcg729 libmsbcg729
endif
-ifneq ($(BUILD_WEBRTC_AECM), 0)
-APP_MODULES += libwebrtc_system_wrappers libwebrtc_spl libwebrtc_apm_utility libwebrtc_aecm
-APP_MODULES += libwebrtc_spl_neon libwebrtc_aecm_neon
+ifneq ($(BUILD_OPUS), 0)
+APP_MODULES += libopus
endif
+ifneq ($(BUILD_WEBRTC_AECM), 0)
+APP_MODULES += libwebrtc_system_wrappers libwebrtc_spl libwebrtc_apm_utility libwebrtc_aecm libmswebrtc
+ifneq (,$(findstring armeabi,$(TARGET_ARCH_ABI)))
+APP_MODULES += libwebrtc_spl_neon libwebrtc_aecm_neon
+endif
+endif
+
+ifeq ($(BUILD_WEBRTC_ISAC), 1)
+APP_MODULES += libwebrtc_spl libwebrtc_isacfix libmswebrtc
+ifneq (,$(findstring armeabi,$(TARGET_ARCH_ABI)))
+APP_MODULES += libwebrtc_spl_neon libwebrtc_isacfix_neon
+endif
+endif
+
+ifeq ($(BUILD_MEDIASTREAMER2_SDK), 0)
ifeq ($(RING),yes)
APP_MODULES += libring
endif
@@ -70,27 +121,32 @@ endif
ifeq ($(BUILD_TUNNEL), 1)
APP_MODULES += libtunnelclient
endif
+endif
-ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
-APP_MODULES += liblincrypto liblinssl
+ifeq ($(BUILD_ZRTP), 1)
+APP_MODULES += libbzrtp
+endif
+
+ifeq ($(BUILD_ILBC), 1)
APP_MODULES +=libmsilbc
-
-ifeq ($(BUILD_GPLV3_ZRTP), 1)
-APP_MODULES += libzrtpcpp
endif
ifeq ($(BUILD_SRTP), 1)
APP_MODULES += libsrtp
endif
-endif #armeabi-v7a
-
linphone-root-dir:=$(APP_PROJECT_PATH)
APP_BUILD_SCRIPT:=$(call my-dir)/Android.mk
APP_PLATFORM := android-8
-APP_ABI := armeabi-v7a armeabi
+APP_ABI := armeabi-v7a
+ifeq ($(BUILD_FOR_ARM), 1)
+APP_ABI += armeabi
+endif
ifeq ($(BUILD_FOR_X86), 1)
APP_ABI += x86
endif
-APP_CFLAGS:=-DDISABLE_NEON
+
+APP_CFLAGS += -Werror -Wall -Wno-strict-aliasing -Wno-unused-function
+# Thanks cpufeature.c imported from the NDK...
+APP_CFLAGS += -Wno-unused-variable
diff --git a/liblinphone_tester/.classpath b/liblinphone_tester/.classpath
new file mode 100644
index 000000000..7e1fd65d7
--- /dev/null
+++ b/liblinphone_tester/.classpath
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/liblinphone_tester/.gitignore b/liblinphone_tester/.gitignore
new file mode 100644
index 000000000..9e04b4e45
--- /dev/null
+++ b/liblinphone_tester/.gitignore
@@ -0,0 +1,20 @@
+# built application files
+*.apk
+*.ap_
+
+# files for the dex VM
+*.dex
+
+# Java class files
+*.class
+
+# generated files
+bin/
+gen/
+libs/
+obj/
+
+# Local configuration file (sdk path, etc)
+local.properties
+
+assets
diff --git a/liblinphone_tester/.project b/liblinphone_tester/.project
new file mode 100644
index 000000000..0877c21b1
--- /dev/null
+++ b/liblinphone_tester/.project
@@ -0,0 +1,45 @@
+
+
+ liblinphoneTester
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
+
+ linphone
+ 2
+ PARENT-1-PROJECT_LOCATION/submodules/linphone/java
+
+
+ mediastreamer2
+ 2
+ PARENT-1-PROJECT_LOCATION/submodules/linphone/mediastreamer2/java/src
+
+
+
diff --git a/liblinphone_tester/AndroidManifest.xml b/liblinphone_tester/AndroidManifest.xml
new file mode 100644
index 000000000..0bf9ab62a
--- /dev/null
+++ b/liblinphone_tester/AndroidManifest.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/liblinphone_tester/Makefile b/liblinphone_tester/Makefile
new file mode 100644
index 000000000..42b2637c1
--- /dev/null
+++ b/liblinphone_tester/Makefile
@@ -0,0 +1,5 @@
+all:
+ ant debug install
+
+run-all-tests: all
+ ant test
diff --git a/liblinphone_tester/adb-log-start.sh b/liblinphone_tester/adb-log-start.sh
new file mode 100755
index 000000000..73ec81563
--- /dev/null
+++ b/liblinphone_tester/adb-log-start.sh
@@ -0,0 +1,4 @@
+#! /bin/bash
+adb logcat -v time > $1 &
+echo $! >adb.pid
+
diff --git a/liblinphone_tester/ant.properties b/liblinphone_tester/ant.properties
new file mode 100644
index 000000000..1c4ad6f9f
--- /dev/null
+++ b/liblinphone_tester/ant.properties
@@ -0,0 +1,2 @@
+source.dir=src:../submodules/linphone/mediastreamer2/java/src:../submodules/linphone/java/j2se:../submodules/linphone/java/common:../submodules/linphone/java/impl
+test.runner=com.zutubi.android.junitreport.JUnitReportTestRunner
diff --git a/liblinphone_tester/build.xml b/liblinphone_tester/build.xml
new file mode 100644
index 000000000..4eb05f07c
--- /dev/null
+++ b/liblinphone_tester/build.xml
@@ -0,0 +1,92 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/liblinphone_tester/custom_rules.xml b/liblinphone_tester/custom_rules.xml
new file mode 100644
index 000000000..9adcb8c2f
--- /dev/null
+++ b/liblinphone_tester/custom_rules.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Adb log files are put in ${archive.name}.zip
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/liblinphone_tester/jni/Android.mk b/liblinphone_tester/jni/Android.mk
new file mode 100644
index 000000000..bacf8a993
--- /dev/null
+++ b/liblinphone_tester/jni/Android.mk
@@ -0,0 +1,3 @@
+include ../jni/Android.mk
+include $(linphone-root-dir)/submodules/externals/build/cunit/Android.mk
+include $(linphone-root-dir)/submodules/linphone/build/android/liblinphone_tester.mk
diff --git a/liblinphone_tester/jni/Application.mk b/liblinphone_tester/jni/Application.mk
new file mode 100644
index 000000000..a6da504c7
--- /dev/null
+++ b/liblinphone_tester/jni/Application.mk
@@ -0,0 +1,7 @@
+LOCAL_PATH:= $(call my-dir)
+include ../jni/Application.mk
+APP_PROJECT_PATH := $(LOCAL_PATH)/../
+APP_BUILD_SCRIPT := $(LOCAL_PATH)/Android.mk
+APP_OPTIM := debug
+
+APP_MODULES += cunit liblinphone_tester
diff --git a/liblinphone_tester/libs/android-junit-report-1.5.8.jar b/liblinphone_tester/libs/android-junit-report-1.5.8.jar
new file mode 100644
index 000000000..09e6a2d4f
Binary files /dev/null and b/liblinphone_tester/libs/android-junit-report-1.5.8.jar differ
diff --git a/tests/res/drawable-hdpi/ic_launcher.png b/liblinphone_tester/res/drawable-hdpi/ic_launcher.png
similarity index 100%
rename from tests/res/drawable-hdpi/ic_launcher.png
rename to liblinphone_tester/res/drawable-hdpi/ic_launcher.png
diff --git a/tests/res/drawable-mdpi/ic_launcher.png b/liblinphone_tester/res/drawable-mdpi/ic_launcher.png
similarity index 100%
rename from tests/res/drawable-mdpi/ic_launcher.png
rename to liblinphone_tester/res/drawable-mdpi/ic_launcher.png
diff --git a/tests/res/drawable-xhdpi/ic_launcher.png b/liblinphone_tester/res/drawable-xhdpi/ic_launcher.png
similarity index 100%
rename from tests/res/drawable-xhdpi/ic_launcher.png
rename to liblinphone_tester/res/drawable-xhdpi/ic_launcher.png
diff --git a/liblinphone_tester/res/layout/activity_logs.xml b/liblinphone_tester/res/layout/activity_logs.xml
new file mode 100644
index 000000000..353062eb8
--- /dev/null
+++ b/liblinphone_tester/res/layout/activity_logs.xml
@@ -0,0 +1,12 @@
+
+
+
\ No newline at end of file
diff --git a/liblinphone_tester/res/layout/activity_main.xml b/liblinphone_tester/res/layout/activity_main.xml
new file mode 100644
index 000000000..751318d94
--- /dev/null
+++ b/liblinphone_tester/res/layout/activity_main.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/liblinphone_tester/res/layout/activity_suites.xml b/liblinphone_tester/res/layout/activity_suites.xml
new file mode 100644
index 000000000..2c8294d5e
--- /dev/null
+++ b/liblinphone_tester/res/layout/activity_suites.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/liblinphone_tester/res/menu/activity_logs.xml b/liblinphone_tester/res/menu/activity_logs.xml
new file mode 100644
index 000000000..77f358b68
--- /dev/null
+++ b/liblinphone_tester/res/menu/activity_logs.xml
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/liblinphone_tester/res/menu/activity_main.xml b/liblinphone_tester/res/menu/activity_main.xml
new file mode 100644
index 000000000..77f358b68
--- /dev/null
+++ b/liblinphone_tester/res/menu/activity_main.xml
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/liblinphone_tester/res/menu/activity_suites.xml b/liblinphone_tester/res/menu/activity_suites.xml
new file mode 100644
index 000000000..77f358b68
--- /dev/null
+++ b/liblinphone_tester/res/menu/activity_suites.xml
@@ -0,0 +1,9 @@
+
\ No newline at end of file
diff --git a/liblinphone_tester/res/values-v11/styles.xml b/liblinphone_tester/res/values-v11/styles.xml
new file mode 100644
index 000000000..541752f6e
--- /dev/null
+++ b/liblinphone_tester/res/values-v11/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/liblinphone_tester/res/values-v14/styles.xml b/liblinphone_tester/res/values-v14/styles.xml
new file mode 100644
index 000000000..f20e01501
--- /dev/null
+++ b/liblinphone_tester/res/values-v14/styles.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/liblinphone_tester/res/values/strings.xml b/liblinphone_tester/res/values/strings.xml
new file mode 100644
index 000000000..941a872da
--- /dev/null
+++ b/liblinphone_tester/res/values/strings.xml
@@ -0,0 +1,10 @@
+
+
+
+ liblinphone tester
+ All
+ Settings
+ LogsActivity
+ SuitesActivity
+
+
\ No newline at end of file
diff --git a/liblinphone_tester/res/values/styles.xml b/liblinphone_tester/res/values/styles.xml
new file mode 100644
index 000000000..4a10ca492
--- /dev/null
+++ b/liblinphone_tester/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/liblinphone_tester/src/org/linphone/tester/LogsActivity.java b/liblinphone_tester/src/org/linphone/tester/LogsActivity.java
new file mode 100644
index 000000000..02df05446
--- /dev/null
+++ b/liblinphone_tester/src/org/linphone/tester/LogsActivity.java
@@ -0,0 +1,92 @@
+package org.linphone.tester;
+
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import android.os.Bundle;
+import android.app.Activity;
+import android.view.Menu;
+import android.widget.TextView;
+
+public class LogsActivity extends Activity {
+ private String mLogs = "";
+ private LogsThread mLogsThread;
+ private class LogsThread extends Thread {
+ LogsActivity mLogsActivity;
+ String mArgs[];
+ TesterLogger tester;
+ public LogsThread(LogsActivity logsActivity, String[] args) {
+ mLogsActivity = logsActivity;
+ mArgs = args;
+ }
+
+ @Override
+ public void run() {
+ String path = mLogsActivity.getFilesDir().getAbsolutePath()+"/config_files";
+ tester = new TesterLogger(mLogsActivity);
+ List list = new LinkedList(Arrays.asList(new String[]{"tester", "--verbose", "--config", path}));
+ list.addAll(Arrays.asList(mArgs));
+ String[] array = list.toArray(new String[list.size()]);
+ tester.run(array);
+ Tester.clearAccounts();
+ mLogsActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mLogsActivity.done();
+ }
+ });
+ }
+ }
+
+ private static String join(String [] array, String separator) {
+ String ret = "";
+ for(int i = 0; i < array.length; ++i) {
+ if(i != 0) {
+ ret += separator;
+ }
+ ret += array[i];
+ }
+ return ret;
+ }
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_logs);
+ ((TextView)findViewById(R.id.textView1)).setText(mLogs);
+ Bundle extras = getIntent().getExtras();
+ if (extras != null) {
+ String[] values = extras.getStringArray("args");
+ if(values != null) {
+ if(mLogsThread == null || !mLogsThread.isAlive()) {
+ this.setTitle("Test Logs (" + join(values, " ") + ")");
+ mLogs = "";
+ ((TextView)findViewById(R.id.textView1)).setText(mLogs);
+ mLogsThread = new LogsThread(this, values);
+ mLogsThread.start();
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.activity_logs, menu);
+ return true;
+ }
+
+ public void addLog(int level, String message) {
+ mLogs += message;
+ ((TextView)findViewById(R.id.textView1)).append(message);
+ }
+ @Override
+ public void onBackPressed() {
+ if(mLogsThread == null || !mLogsThread.isAlive()) {
+ finish();
+ }
+ }
+
+ public void done() {
+ }
+}
diff --git a/liblinphone_tester/src/org/linphone/tester/MainActivity.java b/liblinphone_tester/src/org/linphone/tester/MainActivity.java
new file mode 100644
index 000000000..0c64e6ef5
--- /dev/null
+++ b/liblinphone_tester/src/org/linphone/tester/MainActivity.java
@@ -0,0 +1,80 @@
+package org.linphone.tester;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.lang.Override;
+
+import android.os.Bundle;
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.res.AssetManager;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.Menu;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+public class MainActivity extends Activity {
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ setContentView(R.layout.activity_main);
+ try {
+ TestUnit.copyAssetsFromPackage(getApplicationContext());
+ } catch (IOException e) {
+ Log.e("liblinphone_tester", "Cannot install rc files",e);
+ }
+ Tester.keepAccounts(true);
+ TesterList suitesTest = new TesterList();
+ suitesTest.run(new String[]{"tester", "--list-suites"});
+ LinearLayout layout = ((LinearLayout)findViewById(R.id.suites_list));
+ layout.removeAllViews();
+ addButton(layout, "All", null);
+ for(String str: suitesTest.getList()) {
+ str = str.trim();
+ addButton(layout, str, str);
+ }
+ }
+
+ @Override
+ protected void onDestroy(){
+ Tester.clearAccounts();
+ super.onDestroy();
+ }
+
+ private void addButton(LinearLayout layout, String text, String data) {
+ Button button = new Button(this);
+ button.setText(text);
+ button.setTag(data);
+ button.setGravity(Gravity.CENTER);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ Button button = (Button) v;
+ String data = (String)button.getTag();
+ if(data == null) {
+ Intent intent = new Intent(getBaseContext(), LogsActivity.class);
+ intent.putExtra("args", new String[]{});
+ startActivity(intent);
+ } else {
+ Intent intent = new Intent(getBaseContext(), SuitesActivity.class);
+ intent.putExtra("suite", data);
+ startActivity(intent);
+ }
+ }
+ });
+ layout.addView(button);
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.activity_main, menu);
+ return true;
+ }
+}
diff --git a/liblinphone_tester/src/org/linphone/tester/SuitesActivity.java b/liblinphone_tester/src/org/linphone/tester/SuitesActivity.java
new file mode 100644
index 000000000..ffaa91bd7
--- /dev/null
+++ b/liblinphone_tester/src/org/linphone/tester/SuitesActivity.java
@@ -0,0 +1,70 @@
+package org.linphone.tester;
+
+import android.os.Bundle;
+import android.app.Activity;
+import android.content.Intent;
+import android.view.Gravity;
+import android.view.Menu;
+import android.view.View;
+import android.widget.Button;
+import android.widget.LinearLayout;
+
+public class SuitesActivity extends Activity {
+ String mSuite;
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_suites);
+ Bundle extras = getIntent().getExtras();
+ if (extras != null) {
+ mSuite = extras.getString("suite");
+ if(mSuite != null) {
+ this.setTitle(this.getResources().getString(R.string.app_name) + " | " + mSuite);
+ TesterList suitesTest = new TesterList();
+ suitesTest.run(new String[]{"tester", "--list-tests", mSuite});
+ LinearLayout layout = ((LinearLayout)findViewById(R.id.tests_list));
+ layout.removeAllViews();
+ addButton(layout, "All", null);
+ for(String str: suitesTest.getList()) {
+ str = str.trim();
+ addButton(layout, str, str);
+ }
+ }
+ }
+
+ }
+ private void addButton(LinearLayout layout, String text, String data) {
+ Button button = new Button(this);
+ button.setText(text);
+ button.setTag(data);
+ button.setGravity(Gravity.CENTER);
+ button.setOnClickListener(new Button.OnClickListener() {
+ public void onClick(View v) {
+ Button button = (Button) v;
+ String data = (String)button.getTag();
+ if(mSuite != null) {
+ if(data == null) {
+ Intent intent = new Intent(getBaseContext(), LogsActivity.class);
+ intent.putExtra("args", new String[]{"--suite", mSuite});
+ startActivity(intent);
+ } else {
+ Intent intent = new Intent(getBaseContext(), LogsActivity.class);
+ intent.putExtra("args", new String[]{"--suite", mSuite, "--test", data});
+ startActivity(intent);
+ }
+ }
+ }
+ });
+ layout.addView(button);
+ }
+
+
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.activity_suites, menu);
+ return true;
+ }
+
+}
diff --git a/liblinphone_tester/src/org/linphone/tester/TestRunner.java b/liblinphone_tester/src/org/linphone/tester/TestRunner.java
new file mode 100644
index 000000000..af83f0005
--- /dev/null
+++ b/liblinphone_tester/src/org/linphone/tester/TestRunner.java
@@ -0,0 +1,59 @@
+package org.linphone.tester;
+
+import junit.framework.TestSuite;
+import android.os.Bundle;
+
+import com.zutubi.android.junitreport.JUnitReportTestRunner;
+
+import java.lang.Override;
+
+
+public class TestRunner extends JUnitReportTestRunner {
+ String mSuite = null;
+ String mTest = null;
+
+ @Override
+ public void onCreate(Bundle arguments) {
+ mSuite = arguments.getString("suite");
+ mTest = arguments.getString("test");
+ Tester.keepAccounts(true);
+
+ super.onCreate(arguments);
+ }
+
+ @Override
+ public void onDestroy() {
+ Tester.clearAccounts();
+ super.onDestroy();
+ }
+
+ @Override
+ public TestSuite getAllTests () {
+ TestSuite suite = new TestSuite("Tests");
+ suite.addTest(new WrapperTester());
+ addSuites(suite, mSuite, mTest);
+ return suite;
+ }
+
+ public static void addSuites(TestSuite suite, String suiteCheck, String testCheck) {
+ TesterList testerList = new TesterList();
+ testerList.run(new String[]{"tester", "--list-suites"});
+ for(String str: testerList.getList()) {
+ str = str.trim();
+ if(suiteCheck == null || suiteCheck.equals(str)) {
+ addSuite(suite, str, testCheck);
+ }
+ }
+ }
+
+ public static void addSuite(TestSuite suite, String suiteStr, String testCheck) {
+ TesterList testerList = new TesterList();
+ testerList.run(new String[]{"tester", "--list-tests", suiteStr});
+ for(String str: testerList.getList()) {
+ str = str.trim();
+ if(testCheck == null || testCheck.equals(str)) {
+ suite.addTest(new TestUnit(suiteStr, str));
+ }
+ }
+ }
+}
diff --git a/liblinphone_tester/src/org/linphone/tester/TestUnit.java b/liblinphone_tester/src/org/linphone/tester/TestUnit.java
new file mode 100644
index 000000000..d33211495
--- /dev/null
+++ b/liblinphone_tester/src/org/linphone/tester/TestUnit.java
@@ -0,0 +1,87 @@
+package org.linphone.tester;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+
+import junit.framework.Assert;
+import android.content.Context;
+import android.test.AndroidTestCase;
+
+public class TestUnit extends AndroidTestCase {
+ private String mSuite;
+ private String mTest;
+ static Boolean isAssetCopied=false;
+
+ public TestUnit(String suite, String test) {
+ mSuite = suite;
+ mTest = test;
+ setName(suite + "/" + test);
+ }
+
+ public TestUnit(String name) {
+ String[] tab = name.split("/");
+ mSuite = tab[0];
+ mTest = tab[1];
+ setName(name);
+ }
+
+ static public void copyAssetsFromPackage(Context ctx) throws IOException {
+ copyAssetsFromPackage(ctx,"config_files");
+ }
+
+
+ public static void copyAssetsFromPackage(Context ctx,String fromPath) throws IOException {
+ new File(ctx.getFilesDir().getPath()+"/"+fromPath).mkdir();
+
+ for (String f :ctx.getAssets().list(fromPath)) {
+ String current_name=fromPath+"/"+f;
+ InputStream lInputStream;
+ try {
+ lInputStream = ctx.getAssets().open(current_name);
+ } catch (IOException e) {
+ //probably a dir
+ new File(ctx.getFilesDir().getPath()+"/"+current_name).mkdir();
+ copyAssetsFromPackage(ctx,current_name);
+ continue;
+ }
+ FileOutputStream lOutputStream = new FileOutputStream(new File(ctx.getFilesDir().getPath()+"/"+current_name));//ctx.openFileOutput (fromPath+"/"+f, 0);
+
+
+ int readByte;
+ byte[] buff = new byte[8048];
+ while (( readByte = lInputStream.read(buff)) != -1) {
+ lOutputStream.write(buff,0, readByte);
+ }
+ lOutputStream.flush();
+ lOutputStream.close();
+ lInputStream.close();
+ }
+ }
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ if (isAssetCopied ==false) {
+ copyAssetsFromPackage(getContext());
+ isAssetCopied=true;
+ }
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ @Override
+ protected void runTest() {
+ String path = getContext().getFilesDir().getPath()+"/config_files";
+ Tester tester = new Tester();
+ List list = new LinkedList(Arrays.asList(new String[]{"tester", "--verbose", "--config", path, "--suite", mSuite, "--test", mTest}));
+ String[] array = list.toArray(new String[list.size()]);
+ Assert.assertTrue(tester.run(array) == 0);
+ }
+}
\ No newline at end of file
diff --git a/liblinphone_tester/src/org/linphone/tester/Tester.java b/liblinphone_tester/src/org/linphone/tester/Tester.java
new file mode 100644
index 000000000..59c3887b3
--- /dev/null
+++ b/liblinphone_tester/src/org/linphone/tester/Tester.java
@@ -0,0 +1,76 @@
+package org.linphone.tester;
+
+import java.util.List;
+
+import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.mediastream.Version;
+
+import android.util.Log;
+
+public class Tester {
+ public static String TAG = "liblinphone-tester";
+ private static boolean loadOptionalLibrary(String s) {
+ try {
+ System.loadLibrary(s);
+ return true;
+ } catch (Throwable e) {
+ Log.w("Unable to load optional library lib", s);
+ }
+ return false;
+ }
+
+ public static boolean isArmv7()
+ {
+ return System.getProperty("os.arch").contains("armv7");
+ }
+
+ static {
+ System.loadLibrary("cunit");
+ List cpuabis=Version.getCpuAbis();
+ String ffmpegAbi;
+ boolean libLoaded=false;
+ Throwable firstException=null;
+ for (String abi : cpuabis){
+ Log.i("LinphoneCoreFactoryImpl","Trying to load liblinphone for " + abi);
+ ffmpegAbi=abi;
+ // FFMPEG (audio/video)
+ if (abi.startsWith("armeabi")) {
+ ffmpegAbi="arm";
+ }
+ loadOptionalLibrary("ffmpeg-linphone-"+ffmpegAbi);
+ //Main library
+ try {
+ System.loadLibrary("linphone-" + abi);
+ System.loadLibrary("linphone_tester-" + abi);
+
+ Log.i("LinphoneCoreFactoryImpl","Loading done with " + abi);
+ libLoaded=true;
+ break;
+ }catch(Throwable e) {
+ if (firstException == null) firstException=e;
+ }
+ }
+
+ if (!libLoaded){
+ throw new RuntimeException(firstException);
+
+ }else{
+ Version.dumpCapabilities();
+ }
+ }
+
+ public native int run(String args[]);
+ public static native void keepAccounts(boolean keep);
+ public static native void clearAccounts();
+
+ public void printLog(final int level, final String message) {
+ switch(level) {
+ case 0:
+ android.util.Log.i(TAG, message);
+ break;
+ case 1:
+ android.util.Log.e(TAG, message);
+ break;
+ }
+ }
+}
diff --git a/liblinphone_tester/src/org/linphone/tester/TesterList.java b/liblinphone_tester/src/org/linphone/tester/TesterList.java
new file mode 100644
index 000000000..4dceb606b
--- /dev/null
+++ b/liblinphone_tester/src/org/linphone/tester/TesterList.java
@@ -0,0 +1,16 @@
+package org.linphone.tester;
+
+import java.util.LinkedList;
+import java.util.List;
+
+public class TesterList extends Tester {
+ private List list = new LinkedList();
+ public void printLog(final int level, final String message) {
+ super.printLog(level, message);
+ list.add(message);
+ }
+
+ public List getList() {
+ return list;
+ }
+}
diff --git a/liblinphone_tester/src/org/linphone/tester/TesterLogger.java b/liblinphone_tester/src/org/linphone/tester/TesterLogger.java
new file mode 100644
index 000000000..516763589
--- /dev/null
+++ b/liblinphone_tester/src/org/linphone/tester/TesterLogger.java
@@ -0,0 +1,16 @@
+package org.linphone.tester;
+
+public class TesterLogger extends Tester {
+ private LogsActivity mLogsActivity;
+ TesterLogger(LogsActivity logsActivity) {
+ mLogsActivity = logsActivity;
+ }
+ public void printLog(final int level, final String message) {
+ super.printLog(level, message);
+ mLogsActivity.runOnUiThread(new Runnable() {
+ public void run() {
+ mLogsActivity.addLog(level, message);
+ }
+ });
+ }
+}
diff --git a/liblinphone_tester/src/org/linphone/tester/WrapperTester.java b/liblinphone_tester/src/org/linphone/tester/WrapperTester.java
new file mode 100644
index 000000000..c84ed980b
--- /dev/null
+++ b/liblinphone_tester/src/org/linphone/tester/WrapperTester.java
@@ -0,0 +1,110 @@
+package org.linphone.tester;
+
+import org.linphone.core.LinphoneCallParams;
+import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.core.LinphoneCoreListenerBase;
+import org.linphone.core.LinphoneFriend;
+import org.linphone.core.PayloadType;
+import org.linphone.mediastream.MediastreamerAndroidContext;
+
+import android.test.AndroidTestCase;
+import junit.framework.Assert;
+
+public class WrapperTester extends AndroidTestCase {
+
+ public WrapperTester() {
+ super();
+ setName("wrapper tester");
+ }
+
+ LinphoneCore mCore;
+ @Override
+ protected void runTest() throws Throwable {
+ //multicast begin
+ mCore.enableAudioMulticast(true);
+ Assert.assertEquals(true, mCore.audioMulticastEnabled());
+ mCore.enableAudioMulticast(false);
+ Assert.assertEquals(false, mCore.audioMulticastEnabled());
+
+ mCore.enableVideoMulticast(true);
+ Assert.assertEquals(true, mCore.videoMulticastEnabled());
+ mCore.enableVideoMulticast(false);
+ Assert.assertEquals(false, mCore.videoMulticastEnabled());
+
+ LinphoneCallParams params = mCore.createDefaultCallParameters();
+ params.enableAudioMulticast(true);
+ Assert.assertEquals(true, params.audioMulticastEnabled());
+ params.enableAudioMulticast(false);
+ Assert.assertEquals(false, params.audioMulticastEnabled());
+
+ params.enableVideoMulticast(true);
+ Assert.assertEquals(true, params.videoMulticastEnabled());
+ params.enableVideoMulticast(false);
+ Assert.assertEquals(false, params.videoMulticastEnabled());
+
+
+ String ip = "224.3.2.1";
+ mCore.setAudioMulticastAddr(ip);
+ Assert.assertEquals(ip, mCore.getAudioMulticastAddr());
+
+ ip = "224.3.2.3";
+ mCore.setVideoMulticastAddr(ip);
+ Assert.assertEquals(ip, mCore.getVideoMulticastAddr());
+
+ mCore.setAudioMulticastTtl(3);
+ Assert.assertEquals(3, mCore.getAudioMulticastTtl());
+
+ mCore.setVideoMulticastTtl(4);
+ Assert.assertEquals(4, mCore.getVideoMulticastTtl());
+ //multicast end
+
+ //Test setPrimaryContact
+ String address = "Linphone Android ";
+ mCore.setPrimaryContact(address);
+ Assert.assertEquals(LinphoneCoreFactory.instance().createLinphoneAddress(address).getDisplayName(),
+ LinphoneCoreFactory.instance().createLinphoneAddress(mCore.getPrimaryContact()).getDisplayName());
+ Assert.assertEquals(LinphoneCoreFactory.instance().createLinphoneAddress(address).getUserName(),
+ LinphoneCoreFactory.instance().createLinphoneAddress(mCore.getPrimaryContact()).getUserName());
+
+ //Test setPayloadTypeNumber
+ mCore.setPayloadTypeNumber(mCore.findPayloadType("PCMU"),12);
+ Assert.assertEquals(mCore.getPayloadTypeNumber(mCore.findPayloadType("PCMU")),12);
+
+ PayloadType[] audioCodecs = mCore.getAudioCodecs();
+ int audioCodecsNb = audioCodecs.length;
+ if (audioCodecsNb >= 1) {
+ PayloadType[] newAudioCodecs = new PayloadType[audioCodecsNb - 1];
+ System.arraycopy(audioCodecs, 1, newAudioCodecs, 0, audioCodecsNb - 1);
+ mCore.setAudioCodecs(newAudioCodecs);
+ audioCodecs = mCore.getAudioCodecs();
+ Assert.assertEquals(audioCodecs.length, audioCodecsNb - 1);
+ }
+
+ //Test LinphoneFriend ref key
+ String key = "12";
+ LinphoneFriend friend = LinphoneCoreFactory.instance().createLinphoneFriend("sip:lala@test.linphone.org");
+ friend.setRefKey(key);
+ Assert.assertEquals(friend.getRefKey(),key);
+
+ MediastreamerAndroidContext.enableFilterFromName("MSUlawEnc", false);
+ Assert.assertFalse(MediastreamerAndroidContext.filterFromNameEnabled("MSUlawEnc"));
+ MediastreamerAndroidContext.enableFilterFromName("MSUlawEnc", true);
+ }
+
+ @Override
+ protected void setUp() throws Exception {
+ // TODO Auto-generated method stub
+ super.setUp();
+ mCore = LinphoneCoreFactory.instance().createLinphoneCore(new LinphoneCoreListenerBase(),null);
+ }
+
+ @Override
+ protected void tearDown() throws Exception {
+ // TODO Auto-generated method stub
+ super.tearDown();
+ mCore.destroy();
+ mCore=null;
+ }
+
+}
diff --git a/libs/android-support-v4.jar b/libs/android-support-v4.jar
index 018c1272b..e74b0d77d 100644
Binary files a/libs/android-support-v4.jar and b/libs/android-support-v4.jar differ
diff --git a/patches/ffmpeg_non_versioned_soname.patch b/patches/ffmpeg_non_versioned_soname.patch
new file mode 100644
index 000000000..34a0ecaf0
--- /dev/null
+++ b/patches/ffmpeg_non_versioned_soname.patch
@@ -0,0 +1,11 @@
+--- submodules/externals/ffmpeg/library.mak.orig 2013-09-26 10:58:19.000000000 +0200
++++ submodules/externals/ffmpeg/library.mak 2013-09-26 10:58:13.000000000 +0200
+@@ -54,7 +54,7 @@
+
+ $(SUBDIR)$(SLIBNAME_WITH_MAJOR): $(OBJS) $(SUBDIR)lib$(NAME).ver
+ $(SLIB_CREATE_DEF_CMD)
+- $$(LD) $(SHFLAGS) $(LDFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS)
++ $$(LD) $(subst $$(@F),$(SLIBNAME),$(SHFLAGS)) $(LDFLAGS) $$(LD_O) $$(filter %.o,$$^) $(FFEXTRALIBS)
+ $(SLIB_EXTRA_CMD)
+
+ ifdef SUBDIR
diff --git a/patches/ffmpeg_scalar_product_remove_alignment_hints.patch b/patches/ffmpeg_scalar_product_remove_alignment_hints.patch
deleted file mode 100644
index 6d9b48650..000000000
--- a/patches/ffmpeg_scalar_product_remove_alignment_hints.patch
+++ /dev/null
@@ -1,30 +0,0 @@
---- submodules/externals/ffmpeg/libavcodec/arm/int_neon.S.orig 2011-09-30 19:43:21.935593025 +0200
-+++ submodules/externals/ffmpeg/libavcodec/arm/int_neon.S 2011-09-30 19:44:21.115168033 +0200
-@@ -35,11 +35,11 @@
-
- vdup.s32 q12, r3
- 1: vld1.16 {d16-d17}, [r0]!
-- vld1.16 {d20-d21}, [r1,:128]!
-+ vld1.16 {d20-d21}, [r1]!
- vmull.s16 q12, d16, d20
- vld1.16 {d18-d19}, [r0]!
- vmull.s16 q13, d17, d21
-- vld1.16 {d22-d23}, [r1,:128]!
-+ vld1.16 {d22-d23}, [r1]!
- vmull.s16 q14, d18, d22
- vmull.s16 q15, d19, d23
- vshl.s32 q8, q12, q12
-@@ -55,11 +55,11 @@
- b 3f
-
- 2: vld1.16 {d16-d17}, [r0]!
-- vld1.16 {d20-d21}, [r1,:128]!
-+ vld1.16 {d20-d21}, [r1]!
- vmlal.s16 q0, d16, d20
- vld1.16 {d18-d19}, [r0]!
- vmlal.s16 q1, d17, d21
-- vld1.16 {d22-d23}, [r1,:128]!
-+ vld1.16 {d22-d23}, [r1]!
- vmlal.s16 q2, d18, d22
- vmlal.s16 q3, d19, d23
- subs r2, r2, #16
diff --git a/patches/libvpx_configure_android_x86.patch b/patches/libvpx_configure_android_x86.patch
new file mode 100644
index 000000000..3496853dd
--- /dev/null
+++ b/patches/libvpx_configure_android_x86.patch
@@ -0,0 +1,36 @@
+--- a/submodules/externals/libvpx/build/make/configure.sh
++++ b/submodules/externals/libvpx/build/make/configure.sh
+@@ -1037,6 +1037,33 @@ EOF
+ os2)
+ AS=${AS:-nasm}
+ ;;
++ android*)
++ SDK_PATH=${sdk_path}
++ COMPILER_LOCATION=`find "${SDK_PATH}" \
++ -name "i686-linux-android-gcc*" -print -quit`
++ TOOLCHAIN_PATH=${COMPILER_LOCATION%/*}/i686-linux-android-
++ CC=${TOOLCHAIN_PATH}gcc
++ CXX=${TOOLCHAIN_PATH}g++
++ AR=${TOOLCHAIN_PATH}ar
++ LD=${TOOLCHAIN_PATH}gcc
++ STRIP=${TOOLCHAIN_PATH}strip
++ NM=${TOOLCHAIN_PATH}nm
++
++ if [ -z "${alt_libc}" ]; then
++ alt_libc=`find "${SDK_PATH}" -name arch-x86 -print | \
++ awk '{n = split($0,a,"/"); \
++ split(a[n-1],b,"-"); \
++ print $0 " " b[2]}' | \
++ sort -g -k 2 | \
++ awk '{ print $1 }' | tail -1`
++ fi
++
++ add_cflags "--sysroot=${alt_libc}"
++ add_ldflags "--sysroot=${alt_libc}"
++
++ soft_enable realtime_only
++ ;;
++
+ esac
+
+ AS="${alt_as:-${AS:-auto}}"
diff --git a/patches/openh264-permissive.patch b/patches/openh264-permissive.patch
new file mode 100644
index 000000000..bff18b6ce
--- /dev/null
+++ b/patches/openh264-permissive.patch
@@ -0,0 +1,40 @@
+commit 6b3de978d928b6c0baec3305c9803c21a4367d0c
+Author: Simon Morlat
+Date: Tue Apr 15 15:19:37 2014 +0200
+
+ permissive mode: allow reference frames to be used even if there were lost slices.
+
+diff --git a/codec/decoder/core/src/manage_dec_ref.cpp b/codec/decoder/core/src/manage_dec_ref.cpp
+index dcf61ca..5582ec9 100644
+--- a/codec/decoder/core/src/manage_dec_ref.cpp
++++ b/codec/decoder/core/src/manage_dec_ref.cpp
+@@ -165,6 +165,7 @@ int32_t WelsReorderRefList (PWelsDecoderContext pCtx) {
+ && (pSliceHeader->iSpsId != ppRefList[i]->iSpsId)) { //check;
+ WelsLog (pCtx, WELS_LOG_WARNING, "WelsReorderRefList()-1::::BASE LAYER::::iSpsId:%d, ref_sps_id:%d\n",
+ pSliceHeader->iSpsId, ppRefList[i]->iSpsId);
++ return ERR_NONE;
+ pCtx->iErrorCode = dsNoParamSets; //cross-IDR reference frame selection, SHOULD request IDR.--
+ return ERR_INFO_REFERENCE_PIC_LOST;
+ } else {
+
+commit a1f3b95ad18d0788c2c803fac80e78d6365673ce
+Author: Simon Morlat
+Date: Tue Apr 15 17:54:58 2014 +0200
+
+ permissive mode (2)
+
+diff --git a/codec/decoder/core/src/decoder_core.cpp b/codec/decoder/core/src/decoder_core.cpp
+index a14e971..e742dbf 100644
+--- a/codec/decoder/core/src/decoder_core.cpp
++++ b/codec/decoder/core/src/decoder_core.cpp
+@@ -1738,8 +1738,8 @@ int32_t DecodeCurrentAccessUnit (PWelsDecoderContext pCtx, uint8_t** ppDst, int3
+ if ((iLastIdD < 0) || //case 1: first layer
+ (iLastIdD == iCurrIdD)) { //case 2: same uiDId
+ InitDqLayerInfo (dq_cur, &pLayerInfo, pNalCur, pCtx->pDec);
+-
+- if (!dq_cur->sLayerInfo.pSps->bGapsInFrameNumValueAllowedFlag) {
++ if (0){
++ //if (!dq_cur->sLayerInfo.pSps->bGapsInFrameNumValueAllowedFlag) {
+ const bool kbIdrFlag = dq_cur->sLayerInfo.sNalHeaderExt.bIdrFlag
+ || (dq_cur->sLayerInfo.sNalHeaderExt.sNalUnitHeader.eNalUnitType == NAL_UNIT_CODED_SLICE_IDR);
+ // Subclause 8.2.5.2 Decoding process for gaps in frame_num
diff --git a/patches/x264_log2f_fix.patch b/patches/x264_log2f_fix.patch
new file mode 100644
index 000000000..e5d0647a0
--- /dev/null
+++ b/patches/x264_log2f_fix.patch
@@ -0,0 +1,41 @@
+diff -urN submodules/externals/x264/common/osdep.h.orig submodules/externals/x264/common/osdep.h
+--- submodules/externals/x264/common/osdep.h.orig 2014-02-06 13:56:59.243663951 +0100
++++ submodules/externals/x264/common/osdep.h 2014-02-06 13:57:17.215685078 +0100
+@@ -35,11 +35,6 @@
+
+ #include "config.h"
+
+-#if !HAVE_LOG2F
+-#define log2f(x) (logf(x)/0.693147180559945f)
+-#define log2(x) (log(x)/0.693147180559945)
+-#endif
+-
+ #ifdef _WIN32
+ #include // _setmode()
+ #include // _O_BINARY
+@@ -55,6 +60,11 @@
+ #include
+ #endif
+
++#if !HAVE_LOG2F
++#define log2f(x) (logf(x)/0.693147180559945f)
++#define log2(x) (log(x)/0.693147180559945)
++#endif
++
+ #if (defined(__GNUC__) || defined(__INTEL_COMPILER)) && (ARCH_X86 || ARCH_X86_64)
+ #define HAVE_X86_INLINE_ASM 1
+ #endif
+diff -urN submodules/externals/x264/configure.orig submodules/externals/x264/configure
+--- submodules/externals/x264/configure.orig 2014-02-06 13:56:59.231663937 +0100
++++ submodules/externals/x264/configure 2014-02-06 13:57:17.219685083 +0100
+@@ -816,10 +816,6 @@
+ fi
+ [ "$thread" != "no" ] && define HAVE_THREAD
+
+-if cc_check "math.h" "-Werror" "return log2f(2);" ; then
+- define HAVE_LOG2F
+-fi
+-
+ if [ "$vis" = "yes" ] ; then
+ save_CFLAGS="$CFLAGS"
+ CFLAGS="$CFLAGS -I/usr/X11R6/include"
diff --git a/project.properties b/project.properties
deleted file mode 100644
index 019cc5583..000000000
--- a/project.properties
+++ /dev/null
@@ -1,15 +0,0 @@
-# This file is automatically generated by Android Tools.
-# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
-#
-# This file must be checked in Version Control Systems.
-#
-# To customize properties used by the Ant build system edit
-# "ant.properties", and override values to adapt the script to your
-# project structure.
-#
-# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
-#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
-
-# Project target.
-target=android-17
-android.library=false
diff --git a/release.patch b/release.patch
new file mode 100644
index 000000000..c6f3f3c2f
--- /dev/null
+++ b/release.patch
@@ -0,0 +1,13 @@
+diff --git a/AndroidManifest.xml b/AndroidManifest.xml
+index 5ef1374..86e13be 100644
+--- a/AndroidManifest.xml
++++ b/AndroidManifest.xml
+@@ -45,7 +45,7 @@
+
+
+
+-
++
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/drawable-sw600dp-land-xhdpi/add_call_more_default.png b/res/drawable-sw533dp-land-xhdpi/add_call_more_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/add_call_more_default.png
rename to res/drawable-sw533dp-land-xhdpi/add_call_more_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/add_call_more_disabled.png b/res/drawable-sw533dp-land-xhdpi/add_call_more_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/add_call_more_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/add_call_more_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/add_call_more_over.png b/res/drawable-sw533dp-land-xhdpi/add_call_more_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/add_call_more_over.png
rename to res/drawable-sw533dp-land-xhdpi/add_call_more_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/add_contact_default.png b/res/drawable-sw533dp-land-xhdpi/add_contact_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/add_contact_default.png
rename to res/drawable-sw533dp-land-xhdpi/add_contact_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/add_contact_disabled.png b/res/drawable-sw533dp-land-xhdpi/add_contact_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/add_contact_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/add_contact_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/add_contact_over.png b/res/drawable-sw533dp-land-xhdpi/add_contact_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/add_contact_over.png
rename to res/drawable-sw533dp-land-xhdpi/add_contact_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/back_default.png b/res/drawable-sw533dp-land-xhdpi/back_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/back_default.png
rename to res/drawable-sw533dp-land-xhdpi/back_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/back_disabled.png b/res/drawable-sw533dp-land-xhdpi/back_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/back_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/back_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/back_over.png b/res/drawable-sw533dp-land-xhdpi/back_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/back_over.png
rename to res/drawable-sw533dp-land-xhdpi/back_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/background_alt.png b/res/drawable-sw533dp-land-xhdpi/background_alt.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/background_alt.png
rename to res/drawable-sw533dp-land-xhdpi/background_alt.png
diff --git a/res/drawable-sw600dp-land-xhdpi/background_logo.png b/res/drawable-sw533dp-land-xhdpi/background_logo.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/background_logo.png
rename to res/drawable-sw533dp-land-xhdpi/background_logo.png
diff --git a/res/drawable-sw600dp-land-xhdpi/backspace_default.png b/res/drawable-sw533dp-land-xhdpi/backspace_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/backspace_default.png
rename to res/drawable-sw533dp-land-xhdpi/backspace_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/backspace_disabled.png b/res/drawable-sw533dp-land-xhdpi/backspace_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/backspace_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/backspace_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/backspace_over.png b/res/drawable-sw533dp-land-xhdpi/backspace_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/backspace_over.png
rename to res/drawable-sw533dp-land-xhdpi/backspace_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/bottom.png b/res/drawable-sw533dp-land-xhdpi/bottom.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/bottom.png
rename to res/drawable-sw533dp-land-xhdpi/bottom.png
diff --git a/res/drawable-sw600dp-land-xhdpi/call_default.png b/res/drawable-sw533dp-land-xhdpi/call_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/call_default.png
rename to res/drawable-sw533dp-land-xhdpi/call_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/call_disabled.png b/res/drawable-sw533dp-land-xhdpi/call_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/call_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/call_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/call_over.png b/res/drawable-sw533dp-land-xhdpi/call_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/call_over.png
rename to res/drawable-sw533dp-land-xhdpi/call_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/cancel_white_bg_default.png b/res/drawable-sw533dp-land-xhdpi/cancel_white_bg_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/cancel_white_bg_default.png
rename to res/drawable-sw533dp-land-xhdpi/cancel_white_bg_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/cancel_white_bg_disabled.png b/res/drawable-sw533dp-land-xhdpi/cancel_white_bg_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/cancel_white_bg_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/cancel_white_bg_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/cancel_white_bg_over.png b/res/drawable-sw533dp-land-xhdpi/cancel_white_bg_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/cancel_white_bg_over.png
rename to res/drawable-sw533dp-land-xhdpi/cancel_white_bg_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/chat_default.png b/res/drawable-sw533dp-land-xhdpi/chat_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/chat_default.png
rename to res/drawable-sw533dp-land-xhdpi/chat_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/chat_over.png b/res/drawable-sw533dp-land-xhdpi/chat_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/chat_over.png
rename to res/drawable-sw533dp-land-xhdpi/chat_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/chat_selected.png b/res/drawable-sw533dp-land-xhdpi/chat_selected.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/chat_selected.png
rename to res/drawable-sw533dp-land-xhdpi/chat_selected.png
diff --git a/res/drawable-sw600dp-land-xhdpi/conference_default.png b/res/drawable-sw533dp-land-xhdpi/conference_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/conference_default.png
rename to res/drawable-sw533dp-land-xhdpi/conference_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/conference_over.png b/res/drawable-sw533dp-land-xhdpi/conference_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/conference_over.png
rename to res/drawable-sw533dp-land-xhdpi/conference_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/contacts_default.png b/res/drawable-sw533dp-land-xhdpi/contacts_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/contacts_default.png
rename to res/drawable-sw533dp-land-xhdpi/contacts_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/contacts_over.png b/res/drawable-sw533dp-land-xhdpi/contacts_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/contacts_over.png
rename to res/drawable-sw533dp-land-xhdpi/contacts_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/contacts_selected.png b/res/drawable-sw533dp-land-xhdpi/contacts_selected.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/contacts_selected.png
rename to res/drawable-sw533dp-land-xhdpi/contacts_selected.png
diff --git a/res/drawable-sw600dp-land-xhdpi/dialer_address_background.png b/res/drawable-sw533dp-land-xhdpi/dialer_address_background.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/dialer_address_background.png
rename to res/drawable-sw533dp-land-xhdpi/dialer_address_background.png
diff --git a/res/drawable-sw600dp-land-xhdpi/dialer_alt_back_default.png b/res/drawable-sw533dp-land-xhdpi/dialer_alt_back_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/dialer_alt_back_default.png
rename to res/drawable-sw533dp-land-xhdpi/dialer_alt_back_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/dialer_alt_back_over.png b/res/drawable-sw533dp-land-xhdpi/dialer_alt_back_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/dialer_alt_back_over.png
rename to res/drawable-sw533dp-land-xhdpi/dialer_alt_back_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/dialer_alt_default.png b/res/drawable-sw533dp-land-xhdpi/dialer_alt_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/dialer_alt_default.png
rename to res/drawable-sw533dp-land-xhdpi/dialer_alt_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/dialer_alt_disabled.png b/res/drawable-sw533dp-land-xhdpi/dialer_alt_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/dialer_alt_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/dialer_alt_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/dialer_alt_over.png b/res/drawable-sw533dp-land-xhdpi/dialer_alt_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/dialer_alt_over.png
rename to res/drawable-sw533dp-land-xhdpi/dialer_alt_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/dialer_default.png b/res/drawable-sw533dp-land-xhdpi/dialer_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/dialer_default.png
rename to res/drawable-sw533dp-land-xhdpi/dialer_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/dialer_over.png b/res/drawable-sw533dp-land-xhdpi/dialer_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/dialer_over.png
rename to res/drawable-sw533dp-land-xhdpi/dialer_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/dialer_selected.png b/res/drawable-sw533dp-land-xhdpi/dialer_selected.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/dialer_selected.png
rename to res/drawable-sw533dp-land-xhdpi/dialer_selected.png
diff --git a/res/drawable-sw600dp-land-xhdpi/hangup_default.png b/res/drawable-sw533dp-land-xhdpi/hangup_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/hangup_default.png
rename to res/drawable-sw533dp-land-xhdpi/hangup_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/hangup_over.png b/res/drawable-sw533dp-land-xhdpi/hangup_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/hangup_over.png
rename to res/drawable-sw533dp-land-xhdpi/hangup_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/history_default.png b/res/drawable-sw533dp-land-xhdpi/history_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/history_default.png
rename to res/drawable-sw533dp-land-xhdpi/history_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/history_over.png b/res/drawable-sw533dp-land-xhdpi/history_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/history_over.png
rename to res/drawable-sw533dp-land-xhdpi/history_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/history_selected.png b/res/drawable-sw533dp-land-xhdpi/history_selected.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/history_selected.png
rename to res/drawable-sw533dp-land-xhdpi/history_selected.png
diff --git a/res/drawable-sw600dp-land-xhdpi/mark.png b/res/drawable-sw533dp-land-xhdpi/mark.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/mark.png
rename to res/drawable-sw533dp-land-xhdpi/mark.png
diff --git a/res/drawable-sw600dp-land-xhdpi/micro_off_default.png b/res/drawable-sw533dp-land-xhdpi/micro_off_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/micro_off_default.png
rename to res/drawable-sw533dp-land-xhdpi/micro_off_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/micro_off_disabled.png b/res/drawable-sw533dp-land-xhdpi/micro_off_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/micro_off_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/micro_off_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/micro_off_over.png b/res/drawable-sw533dp-land-xhdpi/micro_off_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/micro_off_over.png
rename to res/drawable-sw533dp-land-xhdpi/micro_off_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/micro_on_default.png b/res/drawable-sw533dp-land-xhdpi/micro_on_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/micro_on_default.png
rename to res/drawable-sw533dp-land-xhdpi/micro_on_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/micro_on_disabled.png b/res/drawable-sw533dp-land-xhdpi/micro_on_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/micro_on_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/micro_on_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/micro_on_over.png b/res/drawable-sw533dp-land-xhdpi/micro_on_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/micro_on_over.png
rename to res/drawable-sw533dp-land-xhdpi/micro_on_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_add_default.png b/res/drawable-sw533dp-land-xhdpi/options_add_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_add_default.png
rename to res/drawable-sw533dp-land-xhdpi/options_add_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_add_default_alt.png b/res/drawable-sw533dp-land-xhdpi/options_add_default_alt.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_add_default_alt.png
rename to res/drawable-sw533dp-land-xhdpi/options_add_default_alt.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_add_disabled.png b/res/drawable-sw533dp-land-xhdpi/options_add_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_add_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/options_add_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_add_disabled_alt.png b/res/drawable-sw533dp-land-xhdpi/options_add_disabled_alt.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_add_disabled_alt.png
rename to res/drawable-sw533dp-land-xhdpi/options_add_disabled_alt.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_add_over.png b/res/drawable-sw533dp-land-xhdpi/options_add_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_add_over.png
rename to res/drawable-sw533dp-land-xhdpi/options_add_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_add_over_alt.png b/res/drawable-sw533dp-land-xhdpi/options_add_over_alt.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_add_over_alt.png
rename to res/drawable-sw533dp-land-xhdpi/options_add_over_alt.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_default.png b/res/drawable-sw533dp-land-xhdpi/options_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_default.png
rename to res/drawable-sw533dp-land-xhdpi/options_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_default_alt.png b/res/drawable-sw533dp-land-xhdpi/options_default_alt.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_default_alt.png
rename to res/drawable-sw533dp-land-xhdpi/options_default_alt.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_disabled.png b/res/drawable-sw533dp-land-xhdpi/options_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/options_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_disabled_alt.png b/res/drawable-sw533dp-land-xhdpi/options_disabled_alt.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_disabled_alt.png
rename to res/drawable-sw533dp-land-xhdpi/options_disabled_alt.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_over.png b/res/drawable-sw533dp-land-xhdpi/options_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_over.png
rename to res/drawable-sw533dp-land-xhdpi/options_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_over_alt.png b/res/drawable-sw533dp-land-xhdpi/options_over_alt.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_over_alt.png
rename to res/drawable-sw533dp-land-xhdpi/options_over_alt.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_selected.png b/res/drawable-sw533dp-land-xhdpi/options_selected.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_selected.png
rename to res/drawable-sw533dp-land-xhdpi/options_selected.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_selected_alt.png b/res/drawable-sw533dp-land-xhdpi/options_selected_alt.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_selected_alt.png
rename to res/drawable-sw533dp-land-xhdpi/options_selected_alt.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_transfer_default.png b/res/drawable-sw533dp-land-xhdpi/options_transfer_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_transfer_default.png
rename to res/drawable-sw533dp-land-xhdpi/options_transfer_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_transfer_disabled.png b/res/drawable-sw533dp-land-xhdpi/options_transfer_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_transfer_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/options_transfer_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/options_transfer_over.png b/res/drawable-sw533dp-land-xhdpi/options_transfer_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/options_transfer_over.png
rename to res/drawable-sw533dp-land-xhdpi/options_transfer_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/pause_off_default.png b/res/drawable-sw533dp-land-xhdpi/pause_off_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/pause_off_default.png
rename to res/drawable-sw533dp-land-xhdpi/pause_off_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/pause_off_disabled.png b/res/drawable-sw533dp-land-xhdpi/pause_off_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/pause_off_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/pause_off_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/pause_off_over.png b/res/drawable-sw533dp-land-xhdpi/pause_off_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/pause_off_over.png
rename to res/drawable-sw533dp-land-xhdpi/pause_off_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/pause_on_default.png b/res/drawable-sw533dp-land-xhdpi/pause_on_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/pause_on_default.png
rename to res/drawable-sw533dp-land-xhdpi/pause_on_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/pause_on_over.png b/res/drawable-sw533dp-land-xhdpi/pause_on_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/pause_on_over.png
rename to res/drawable-sw533dp-land-xhdpi/pause_on_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/settings_default.png b/res/drawable-sw533dp-land-xhdpi/settings_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/settings_default.png
rename to res/drawable-sw533dp-land-xhdpi/settings_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/settings_over.png b/res/drawable-sw533dp-land-xhdpi/settings_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/settings_over.png
rename to res/drawable-sw533dp-land-xhdpi/settings_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/settings_selected.png b/res/drawable-sw533dp-land-xhdpi/settings_selected.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/settings_selected.png
rename to res/drawable-sw533dp-land-xhdpi/settings_selected.png
diff --git a/res/drawable-sw600dp-land-xhdpi/setup_back_default.png b/res/drawable-sw533dp-land-xhdpi/setup_back_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/setup_back_default.png
rename to res/drawable-sw533dp-land-xhdpi/setup_back_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/setup_back_disabled.png b/res/drawable-sw533dp-land-xhdpi/setup_back_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/setup_back_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/setup_back_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/setup_back_over.png b/res/drawable-sw533dp-land-xhdpi/setup_back_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/setup_back_over.png
rename to res/drawable-sw533dp-land-xhdpi/setup_back_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/setup_cancel_default.png b/res/drawable-sw533dp-land-xhdpi/setup_cancel_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/setup_cancel_default.png
rename to res/drawable-sw533dp-land-xhdpi/setup_cancel_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/setup_cancel_disabled.png b/res/drawable-sw533dp-land-xhdpi/setup_cancel_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/setup_cancel_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/setup_cancel_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/setup_cancel_over.png b/res/drawable-sw533dp-land-xhdpi/setup_cancel_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/setup_cancel_over.png
rename to res/drawable-sw533dp-land-xhdpi/setup_cancel_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/setup_start_default.png b/res/drawable-sw533dp-land-xhdpi/setup_start_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/setup_start_default.png
rename to res/drawable-sw533dp-land-xhdpi/setup_start_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/setup_start_disabled.png b/res/drawable-sw533dp-land-xhdpi/setup_start_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/setup_start_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/setup_start_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/setup_start_over.png b/res/drawable-sw533dp-land-xhdpi/setup_start_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/setup_start_over.png
rename to res/drawable-sw533dp-land-xhdpi/setup_start_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/speaker_off_default.png b/res/drawable-sw533dp-land-xhdpi/speaker_off_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/speaker_off_default.png
rename to res/drawable-sw533dp-land-xhdpi/speaker_off_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/speaker_off_disabled.png b/res/drawable-sw533dp-land-xhdpi/speaker_off_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/speaker_off_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/speaker_off_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/speaker_off_over.png b/res/drawable-sw533dp-land-xhdpi/speaker_off_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/speaker_off_over.png
rename to res/drawable-sw533dp-land-xhdpi/speaker_off_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/speaker_on_default.png b/res/drawable-sw533dp-land-xhdpi/speaker_on_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/speaker_on_default.png
rename to res/drawable-sw533dp-land-xhdpi/speaker_on_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/speaker_on_disabled.png b/res/drawable-sw533dp-land-xhdpi/speaker_on_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/speaker_on_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/speaker_on_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/speaker_on_over.png b/res/drawable-sw533dp-land-xhdpi/speaker_on_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/speaker_on_over.png
rename to res/drawable-sw533dp-land-xhdpi/speaker_on_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/splashscreen.png b/res/drawable-sw533dp-land-xhdpi/splashscreen.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/splashscreen.png
rename to res/drawable-sw533dp-land-xhdpi/splashscreen.png
diff --git a/res/drawable-sw600dp-land-xhdpi/statebar_background.png b/res/drawable-sw533dp-land-xhdpi/statebar_background.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/statebar_background.png
rename to res/drawable-sw533dp-land-xhdpi/statebar_background.png
diff --git a/res/drawable-sw600dp-land-xhdpi/unknown_small.png b/res/drawable-sw533dp-land-xhdpi/unknown_small.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/unknown_small.png
rename to res/drawable-sw533dp-land-xhdpi/unknown_small.png
diff --git a/res/drawable-sw600dp-land-xhdpi/video_off_default.png b/res/drawable-sw533dp-land-xhdpi/video_off_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/video_off_default.png
rename to res/drawable-sw533dp-land-xhdpi/video_off_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/video_off_disabled.png b/res/drawable-sw533dp-land-xhdpi/video_off_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/video_off_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/video_off_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/video_off_over.png b/res/drawable-sw533dp-land-xhdpi/video_off_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/video_off_over.png
rename to res/drawable-sw533dp-land-xhdpi/video_off_over.png
diff --git a/res/drawable-sw600dp-land-xhdpi/video_on_default.png b/res/drawable-sw533dp-land-xhdpi/video_on_default.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/video_on_default.png
rename to res/drawable-sw533dp-land-xhdpi/video_on_default.png
diff --git a/res/drawable-sw600dp-land-xhdpi/video_on_disabled.png b/res/drawable-sw533dp-land-xhdpi/video_on_disabled.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/video_on_disabled.png
rename to res/drawable-sw533dp-land-xhdpi/video_on_disabled.png
diff --git a/res/drawable-sw600dp-land-xhdpi/video_on_over.png b/res/drawable-sw533dp-land-xhdpi/video_on_over.png
similarity index 100%
rename from res/drawable-sw600dp-land-xhdpi/video_on_over.png
rename to res/drawable-sw533dp-land-xhdpi/video_on_over.png
diff --git a/res/drawable-xhdpi/add_call_over.png b/res/drawable-xhdpi/add_call_over.png
deleted file mode 100644
index 50fefa47f..000000000
Binary files a/res/drawable-xhdpi/add_call_over.png and /dev/null differ
diff --git a/res/drawable-xhdpi/chat_back_default.9.png b/res/drawable-xhdpi/chat_back_default.9.png
new file mode 100644
index 000000000..0979d7605
Binary files /dev/null and b/res/drawable-xhdpi/chat_back_default.9.png differ
diff --git a/res/drawable-xhdpi/chat_back_over.9.png b/res/drawable-xhdpi/chat_back_over.9.png
new file mode 100644
index 000000000..841fb620d
Binary files /dev/null and b/res/drawable-xhdpi/chat_back_over.9.png differ
diff --git a/res/drawable-xhdpi/chat_background.png b/res/drawable-xhdpi/chat_background.png
new file mode 100644
index 000000000..8a28fcd3b
Binary files /dev/null and b/res/drawable-xhdpi/chat_background.png differ
diff --git a/res/drawable-xhdpi/chat_field_background.9.png b/res/drawable-xhdpi/chat_field_background.9.png
index 75b262e7c..5c406644c 100644
Binary files a/res/drawable-xhdpi/chat_field_background.9.png and b/res/drawable-xhdpi/chat_field_background.9.png differ
diff --git a/res/drawable-xhdpi/chat_progressbar_background.png b/res/drawable-xhdpi/chat_progressbar_background.png
deleted file mode 100644
index abd966e86..000000000
Binary files a/res/drawable-xhdpi/chat_progressbar_background.png and /dev/null differ
diff --git a/res/drawable-xhdpi/contact_delete_default.9.png b/res/drawable-xhdpi/contact_delete_default.9.png
new file mode 100644
index 000000000..993639f69
Binary files /dev/null and b/res/drawable-xhdpi/contact_delete_default.9.png differ
diff --git a/res/drawable-xhdpi/contact_delete_over.9.png b/res/drawable-xhdpi/contact_delete_over.9.png
new file mode 100644
index 000000000..bf0fdcd75
Binary files /dev/null and b/res/drawable-xhdpi/contact_delete_over.9.png differ
diff --git a/res/drawable/chat_back.xml b/res/drawable/chat_back.xml
new file mode 100644
index 000000000..80e8f379b
--- /dev/null
+++ b/res/drawable/chat_back.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/res/drawable/contact_delete.xml b/res/drawable/contact_delete.xml
new file mode 100644
index 000000000..32694f1e5
--- /dev/null
+++ b/res/drawable/contact_delete.xml
@@ -0,0 +1,8 @@
+
+
+
+
+
+
diff --git a/res/layout-FR/chat.xml b/res/layout-FR/chat.xml
deleted file mode 100644
index 5eeb2081a..000000000
--- a/res/layout-FR/chat.xml
+++ /dev/null
@@ -1,144 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/layout-RU/chat.xml b/res/layout-RU/chat.xml
deleted file mode 100644
index d6cb7d588..000000000
--- a/res/layout-RU/chat.xml
+++ /dev/null
@@ -1,144 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/layout-land/incall.xml b/res/layout-land/incall.xml
index 4acbe4f79..ad33b6530 100644
--- a/res/layout-land/incall.xml
+++ b/res/layout-land/incall.xml
@@ -44,6 +44,7 @@
android:visibility="invisible" />
-
+ android:background="@drawable/pause_off"
+ android:gravity="center"
+ android:paddingTop="30dp" />
-
-
-
+ android:paddingTop="30dp" />
+
+
+
+
+
+
+
+
+
+
+
-
+ android:background="@drawable/hangup"
+ android:gravity="center"
+ android:paddingTop="30dp" />
-
+
diff --git a/res/layout-small/about.xml b/res/layout-small/about.xml
deleted file mode 100644
index ec5bfef5a..000000000
--- a/res/layout-small/about.xml
+++ /dev/null
@@ -1,51 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/layout-small/chat.xml b/res/layout-small/chat.xml
deleted file mode 100644
index 794705cc3..000000000
--- a/res/layout-small/chat.xml
+++ /dev/null
@@ -1,144 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/layout-small/dialer.xml b/res/layout-small/dialer.xml
index 5e1bc13eb..d4bdcb803 100644
--- a/res/layout-small/dialer.xml
+++ b/res/layout-small/dialer.xml
@@ -40,6 +40,7 @@
+ android:textColor="@color/text_contrast" />
+ android:textColor="@color/text_contrast" />
@@ -58,7 +58,7 @@
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:textSize="13sp"
- android:textColor="@android:color/black" />
+ android:textColor="@color/text_contrast" />
+ android:textColor="@color/text_contrast" />
+ android:textColor="@color/text_contrast" />
diff --git a/res/layout-small/incall.xml b/res/layout-small/incall.xml
index 7bbdfe504..c8b9322d5 100644
--- a/res/layout-small/incall.xml
+++ b/res/layout-small/incall.xml
@@ -144,7 +144,14 @@
android:layout_height="wrap_content"
android:orientation="horizontal" >
-
+
+
+ android:layout_height="wrap_content" />
+
+
+
+
-
+ android:background="@drawable/pause_off" />
-
+ android:background="@drawable/conference" />
-
+ android:background="@drawable/hangup" />
-
+ android:background="@drawable/dialer_alt" />
diff --git a/res/layout-small/main.xml b/res/layout-small/main.xml
index a5fd43cb9..7b13f8df0 100644
--- a/res/layout-small/main.xml
+++ b/res/layout-small/main.xml
@@ -153,5 +153,14 @@
+
+
+
+
diff --git a/res/layout-small/menu_chat_button.xml b/res/layout-small/menu_chat_button.xml
index 5b86bbdd5..6daec2864 100644
--- a/res/layout-small/menu_chat_button.xml
+++ b/res/layout-small/menu_chat_button.xml
@@ -10,7 +10,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
- android:contentDescription="@string/content_description_chat"
+ android:contentDescription="@string/content_description_chat_button"
android:scaleType="fitXY"
android:src="@drawable/chat" />
diff --git a/res/layout-small/menu_settings_button.xml b/res/layout-small/menu_settings_button.xml
index 060b56776..9f1ea3a9d 100644
--- a/res/layout-small/menu_settings_button.xml
+++ b/res/layout-small/menu_settings_button.xml
@@ -11,7 +11,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
- android:contentDescription="@string/content_description_about"
+ android:contentDescription="@string/content_description_settings"
android:scaleType="fitXY"
android:src="@drawable/settings" />
diff --git a/res/layout-small/setup_generic_login.xml b/res/layout-small/setup_generic_login.xml
index 0af4722f8..68c52a87b 100644
--- a/res/layout-small/setup_generic_login.xml
+++ b/res/layout-small/setup_generic_login.xml
@@ -4,13 +4,16 @@
android:layout_height="match_parent"
android:orientation="vertical" >
-
+ android:text="@string/setup_title_assistant"/>
-
+ android:text="@string/setup_title_assistant"/>
-
+ android:text="@string/setup_title_assistant"/>
@@ -27,6 +31,7 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout-small/setup_wizard.xml b/res/layout-small/setup_wizard.xml
index d04f65fe8..addb837a7 100644
--- a/res/layout-small/setup_wizard.xml
+++ b/res/layout-small/setup_wizard.xml
@@ -4,13 +4,16 @@
android:layout_height="match_parent"
android:orientation="vertical" >
-
+ android:text="@string/setup_title_assistant"/>
-
-
-
-
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
\ No newline at end of file
diff --git a/res/layout-small/setup_wizard_confirm.xml b/res/layout-small/setup_wizard_confirm.xml
index cd76d7a35..bdd1c7bfe 100644
--- a/res/layout-small/setup_wizard_confirm.xml
+++ b/res/layout-small/setup_wizard_confirm.xml
@@ -5,12 +5,16 @@
android:gravity="center_horizontal"
android:orientation="vertical" >
-
+ android:text="@string/setup_title_assistant"/>
+ android:textSize="18sp"/>
@@ -55,7 +55,7 @@
android:text="@string/call_stats_codec"
android:textStyle="bold"
android:textColor="@android:color/white"
- android:textSize="12dp"/>
+ android:textSize="12sp"/>
+ android:textSize="12sp"/>
@@ -79,7 +79,7 @@
android:text="@string/call_stats_upload"
android:textStyle="bold"
android:textColor="@android:color/white"
- android:textSize="12dp"/>
+ android:textSize="12sp"/>
+ android:textSize="12sp"/>
@@ -103,7 +103,7 @@
android:text="@string/call_stats_download"
android:textColor="@android:color/white"
android:textStyle="bold"
- android:textSize="12dp"/>
+ android:textSize="12sp"/>
+ android:textSize="12sp"/>
@@ -127,7 +127,7 @@
android:text="@string/call_stats_ice"
android:textStyle="bold"
android:textColor="@android:color/white"
- android:textSize="12dp"/>
+ android:textSize="12sp"/>
+ android:textSize="12sp"/>
+
+
+
+
+
+
+
+
@@ -179,7 +204,7 @@
android:id="@+id/statusText"
android:text="@string/status_not_connected"
android:textColor="@android:color/white"
- android:textSize="14dp"
+ android:textSize="14sp"
android:paddingLeft="5dp"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
@@ -216,6 +241,32 @@
android:adjustViewBounds="true"
android:visibility="gone"
android:layout_alignParentRight="true" />
+
+
+
+
diff --git a/res/layout-sw600dp-land/audio.xml b/res/layout-sw533dp-land/audio.xml
similarity index 100%
rename from res/layout-sw600dp-land/audio.xml
rename to res/layout-sw533dp-land/audio.xml
diff --git a/res/layout-sw533dp-land/chat.xml b/res/layout-sw533dp-land/chat.xml
new file mode 100644
index 000000000..2c2e5dd2c
--- /dev/null
+++ b/res/layout-sw533dp-land/chat.xml
@@ -0,0 +1,159 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout-sw600dp-land/contact.xml b/res/layout-sw533dp-land/contact.xml
similarity index 77%
rename from res/layout-sw600dp-land/contact.xml
rename to res/layout-sw533dp-land/contact.xml
index d8f4ba2c3..206bf91f5 100644
--- a/res/layout-sw600dp-land/contact.xml
+++ b/res/layout-sw533dp-land/contact.xml
@@ -11,6 +11,20 @@
android:layout_height="wrap_content"
android:orientation="horizontal">
+
+
-
-
+ android:textColor="@color/text_contrast" />
@@ -79,4 +79,4 @@
-
\ No newline at end of file
+
diff --git a/res/layout-sw600dp-land/dialer.xml b/res/layout-sw533dp-land/dialer.xml
similarity index 90%
rename from res/layout-sw600dp-land/dialer.xml
rename to res/layout-sw533dp-land/dialer.xml
index 2a034ca3b..577582bad 100644
--- a/res/layout-sw600dp-land/dialer.xml
+++ b/res/layout-sw533dp-land/dialer.xml
@@ -30,6 +30,7 @@
+ android:layout_height="match_parent"
+ android:paddingBottom="10dp">
+ android:orientation="horizontal" />
@@ -67,7 +65,13 @@
android:gravity="bottom"
android:orientation="horizontal" >
-
+
+
+
+
+
+
-
+ android:background="@drawable/conference" />
-
+ android:background="@drawable/pause_off" />
-
+ android:background="@drawable/dialer_alt" />
-
+ android:background="@drawable/hangup" />
diff --git a/res/layout-sw600dp-land/main.xml b/res/layout-sw533dp-land/main.xml
similarity index 96%
rename from res/layout-sw600dp-land/main.xml
rename to res/layout-sw533dp-land/main.xml
index f88231705..ac85fef4b 100644
--- a/res/layout-sw600dp-land/main.xml
+++ b/res/layout-sw533dp-land/main.xml
@@ -90,14 +90,16 @@
android:id="@+id/fragmentContainer"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:layout_weight="0.67" />
+ android:layout_weight="0.67"
+ android:orientation="horizontal" />
+ android:layout_weight="0.33"
+ android:orientation="horizontal"/>
diff --git a/res/layout-sw600dp-land/menu_about_chat_button.xml b/res/layout-sw533dp-land/menu_about_chat_button.xml
similarity index 100%
rename from res/layout-sw600dp-land/menu_about_chat_button.xml
rename to res/layout-sw533dp-land/menu_about_chat_button.xml
diff --git a/res/layout-sw600dp-land/menu_about_settings_button.xml b/res/layout-sw533dp-land/menu_about_settings_button.xml
similarity index 100%
rename from res/layout-sw600dp-land/menu_about_settings_button.xml
rename to res/layout-sw533dp-land/menu_about_settings_button.xml
diff --git a/res/layout-sw600dp-land/menu_chat_button.xml b/res/layout-sw533dp-land/menu_chat_button.xml
similarity index 90%
rename from res/layout-sw600dp-land/menu_chat_button.xml
rename to res/layout-sw533dp-land/menu_chat_button.xml
index 53c892cef..6ef0f0b70 100644
--- a/res/layout-sw600dp-land/menu_chat_button.xml
+++ b/res/layout-sw533dp-land/menu_chat_button.xml
@@ -10,7 +10,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
- android:contentDescription="@string/content_description_chat"
+ android:contentDescription="@string/content_description_chat_button"
android:scaleType="fitXY"
android:src="@drawable/chat" />
diff --git a/res/layout-sw600dp-land/menu_contact_button.xml b/res/layout-sw533dp-land/menu_contact_button.xml
similarity index 100%
rename from res/layout-sw600dp-land/menu_contact_button.xml
rename to res/layout-sw533dp-land/menu_contact_button.xml
diff --git a/res/layout-sw600dp-land/menu_history_button.xml b/res/layout-sw533dp-land/menu_history_button.xml
similarity index 100%
rename from res/layout-sw600dp-land/menu_history_button.xml
rename to res/layout-sw533dp-land/menu_history_button.xml
diff --git a/res/layout-sw600dp-land/menu_settings_button.xml b/res/layout-sw533dp-land/menu_settings_button.xml
similarity index 91%
rename from res/layout-sw600dp-land/menu_settings_button.xml
rename to res/layout-sw533dp-land/menu_settings_button.xml
index 2e1dcdf3d..739e3bc0e 100644
--- a/res/layout-sw600dp-land/menu_settings_button.xml
+++ b/res/layout-sw533dp-land/menu_settings_button.xml
@@ -11,7 +11,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:adjustViewBounds="true"
- android:contentDescription="@string/content_description_about"
+ android:contentDescription="@string/content_description_settings"
android:scaleType="fitXY"
android:src="@drawable/settings" />
diff --git a/res/layout-sw600dp-land/settings.xml b/res/layout-sw533dp-land/settings.xml
similarity index 81%
rename from res/layout-sw600dp-land/settings.xml
rename to res/layout-sw533dp-land/settings.xml
index d1a62c698..b6b4694a1 100644
--- a/res/layout-sw600dp-land/settings.xml
+++ b/res/layout-sw533dp-land/settings.xml
@@ -1,9 +1,9 @@
+ android:layout_height="match_parent"
+ android:background="@android:color/black">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout-sw600dp-land/setup_back_button.xml b/res/layout-sw533dp-land/setup_back_button.xml
similarity index 100%
rename from res/layout-sw600dp-land/setup_back_button.xml
rename to res/layout-sw533dp-land/setup_back_button.xml
diff --git a/res/layout-sw600dp-land/setup_cancel_button.xml b/res/layout-sw533dp-land/setup_cancel_button.xml
similarity index 97%
rename from res/layout-sw600dp-land/setup_cancel_button.xml
rename to res/layout-sw533dp-land/setup_cancel_button.xml
index 5564cccd9..a03d1825b 100644
--- a/res/layout-sw600dp-land/setup_cancel_button.xml
+++ b/res/layout-sw533dp-land/setup_cancel_button.xml
@@ -8,7 +8,7 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout-sw533dp-land/setup_linphone_login.xml b/res/layout-sw533dp-land/setup_linphone_login.xml
new file mode 100644
index 000000000..430786096
--- /dev/null
+++ b/res/layout-sw533dp-land/setup_linphone_login.xml
@@ -0,0 +1,86 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout-sw533dp-land/setup_menu.xml b/res/layout-sw533dp-land/setup_menu.xml
new file mode 100644
index 000000000..b3d8f4779
--- /dev/null
+++ b/res/layout-sw533dp-land/setup_menu.xml
@@ -0,0 +1,129 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout-sw600dp-land/setup_next_button.xml b/res/layout-sw533dp-land/setup_next_button.xml
similarity index 100%
rename from res/layout-sw600dp-land/setup_next_button.xml
rename to res/layout-sw533dp-land/setup_next_button.xml
diff --git a/res/layout-sw533dp-land/setup_wizard.xml b/res/layout-sw533dp-land/setup_wizard.xml
new file mode 100644
index 000000000..7f838ce1f
--- /dev/null
+++ b/res/layout-sw533dp-land/setup_wizard.xml
@@ -0,0 +1,177 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout-sw533dp-land/video.xml b/res/layout-sw533dp-land/video.xml
new file mode 100644
index 000000000..06ced7910
--- /dev/null
+++ b/res/layout-sw533dp-land/video.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout-sw600dp-land/avatar.xml b/res/layout-sw600dp-land/avatar.xml
deleted file mode 100644
index 361ea0b10..000000000
--- a/res/layout-sw600dp-land/avatar.xml
+++ /dev/null
@@ -1,29 +0,0 @@
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/res/layout-sw720dp-land/incall.xml b/res/layout-sw720dp-land/incall.xml
new file mode 100644
index 000000000..7166bdea8
--- /dev/null
+++ b/res/layout-sw720dp-land/incall.xml
@@ -0,0 +1,190 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout-sw720dp-land/main.xml b/res/layout-sw720dp-land/main.xml
index 84db874be..4279d244f 100644
--- a/res/layout-sw720dp-land/main.xml
+++ b/res/layout-sw720dp-land/main.xml
@@ -15,6 +15,7 @@
+ android:layout_weight="0.33"
+ android:paddingBottom="10dp" />
diff --git a/res/layout-sw720dp-land/settings.xml b/res/layout-sw720dp-land/settings.xml
new file mode 100644
index 000000000..b6b4694a1
--- /dev/null
+++ b/res/layout-sw720dp-land/settings.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout-sw720dp-land/video.xml b/res/layout-sw720dp-land/video.xml
new file mode 100644
index 000000000..48c9ca2b1
--- /dev/null
+++ b/res/layout-sw720dp-land/video.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/about.xml b/res/layout/about.xml
index e850a1609..d0b492e13 100644
--- a/res/layout/about.xml
+++ b/res/layout/about.xml
@@ -1,44 +1,86 @@
-
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="vertical"
+ android:background="@drawable/background"
+ android:gravity="center">
+
+
+
+
+
-
-
-
-
+
+
+
+
+
+
+
-
-
\ No newline at end of file
+ android:gravity="center">
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/chat.xml b/res/layout/chat.xml
index b2038a8f7..33cf7b76b 100644
--- a/res/layout/chat.xml
+++ b/res/layout/chat.xml
@@ -1,19 +1,58 @@
-
+ android:id="@+id/top_layout"
+ android:background="@drawable/background" >
+
+
+
+
+
+
+
+
-
+ android:orientation="horizontal"
+ android:layout_below="@+id/topbar"
+ android:layout_centerHorizontal="true">
-
+ android:textColor="@color/text_contrast" />
-
-
-
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
-
-
+
+
+
+
+
+
+
+
-
-
-
-
+ android:layout_height="wrap_content"
+ android:layout_alignBottom="@id/cancelUpload"
+ android:layout_toLeftOf="@id/cancelUpload"
+ android:paddingBottom="20dp"
+ android:orientation="vertical"
+ android:gravity="center">
+
+
+
+
+
+
+
+
-
\ No newline at end of file
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/chat_activity.xml b/res/layout/chat_activity.xml
new file mode 100644
index 000000000..b70f9391a
--- /dev/null
+++ b/res/layout/chat_activity.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/chat_bubble_alt_incoming.xml b/res/layout/chat_bubble_alt_incoming.xml
index 50919279b..5a5cea187 100644
--- a/res/layout/chat_bubble_alt_incoming.xml
+++ b/res/layout/chat_bubble_alt_incoming.xml
@@ -7,6 +7,7 @@
+ android:layout_weight="1"
+ android:maxWidth="250dp"
+ android:maxHeight="250dp" />
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/chat_bubble_incoming.xml b/res/layout/chat_bubble_incoming.xml
index d0d2e9862..97a41d860 100644
--- a/res/layout/chat_bubble_incoming.xml
+++ b/res/layout/chat_bubble_incoming.xml
@@ -9,15 +9,19 @@
+ android:layout_height="wrap_content"
+ android:maxWidth="250dp"
+ android:maxHeight="250dp" />
+
+
+
+
diff --git a/res/layout/contact.xml b/res/layout/contact.xml
index 040e12e04..500f29ddd 100644
--- a/res/layout/contact.xml
+++ b/res/layout/contact.xml
@@ -11,6 +11,20 @@
android:layout_height="wrap_content"
android:orientation="horizontal">
+
+
@@ -47,7 +62,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="@android:color/black" />
+ android:textColor="@color/text_contrast" />
diff --git a/res/layout/contact_add_row.xml b/res/layout/contact_add_row.xml
index 5587cbad0..e712d2f93 100644
--- a/res/layout/contact_add_row.xml
+++ b/res/layout/contact_add_row.xml
@@ -7,7 +7,7 @@
android:padding="10dp">
@@ -26,7 +26,7 @@
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="0.2"
- android:contentDescription="@string/content_description_dial_back"
+ android:contentDescription="@string/content_description_call"
android:gravity="right"
android:paddingLeft="5dp"
android:paddingRight="5dp"
@@ -34,7 +34,7 @@
android:src="@drawable/call_answer" />
-
-
\ No newline at end of file
diff --git a/res/layout/contacts_list.xml b/res/layout/contacts_list.xml
index ff9a324e5..63c2db697 100644
--- a/res/layout/contacts_list.xml
+++ b/res/layout/contacts_list.xml
@@ -1,108 +1,139 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/background"
+ android:orientation="vertical" >
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/dialer.xml b/res/layout/dialer.xml
index 7578d8447..bf0ed1ac8 100644
--- a/res/layout/dialer.xml
+++ b/res/layout/dialer.xml
@@ -1,59 +1,68 @@
-
+ android:background="@drawable/background">
-
-
+ android:layout_gravity="center"
+ android:layout_alignParentTop="true"
+ android:layout_centerHorizontal="true"/>
+ android:layout_height="wrap_content">
-
+
+
+
diff --git a/res/layout/edit_contact.xml b/res/layout/edit_contact.xml
index f5e050883..fa2e0479a 100644
--- a/res/layout/edit_contact.xml
+++ b/res/layout/edit_contact.xml
@@ -43,6 +43,7 @@
@@ -77,7 +78,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/contact_last_name"
- android:textColor="@android:color/black"
+ android:textColor="@color/text_contrast"
android:background="@drawable/chat_fast_address_background"
android:gravity="left"
android:paddingRight="5dp"
@@ -89,7 +90,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/contact_first_name"
- android:textColor="@android:color/black"
+ android:textColor="@color/text_contrast"
android:background="@drawable/chat_fast_address_background"
android:gravity="left"
android:paddingRight="5dp"
diff --git a/res/layout/history.xml b/res/layout/history.xml
index df3f24b62..c6deac8fe 100644
--- a/res/layout/history.xml
+++ b/res/layout/history.xml
@@ -1,115 +1,115 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/background"
+ android:orientation="vertical" >
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/history_cell.xml b/res/layout/history_cell.xml
index e3d41b7a6..e537d693f 100644
--- a/res/layout/history_cell.xml
+++ b/res/layout/history_cell.xml
@@ -22,7 +22,7 @@
android:layout_height="wrap_content"
android:layout_weight="0.3"
android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="@android:color/black"
+ android:textColor="@color/text_contrast"
android:layout_marginLeft="10dp" />
+ android:textColor="@color/text_contrast" />
+ android:textColor="@color/text_contrast" />
@@ -57,7 +57,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
- android:textColor="@android:color/black" />
+ android:textColor="@color/text_contrast" />
+ android:textColor="@color/text_contrast" />
+ android:textColor="@color/text_contrast" />
diff --git a/res/layout/history_group.xml b/res/layout/history_group.xml
index df4882a05..65f4018e9 100644
--- a/res/layout/history_group.xml
+++ b/res/layout/history_group.xml
@@ -21,7 +21,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceLarge"
- android:textColor="@android:color/black"
+ android:textColor="@color/text_contrast"
android:layout_marginLeft="30dp"
android:layout_alignParentLeft="true"
android:layout_toLeftOf="@id/delete" />
diff --git a/res/layout/history_simple.xml b/res/layout/history_simple.xml
index 6d7a969be..f2569307d 100644
--- a/res/layout/history_simple.xml
+++ b/res/layout/history_simple.xml
@@ -1,120 +1,120 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:background="@drawable/background"
+ android:orientation="vertical" >
-
\ No newline at end of file
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/incall.xml b/res/layout/incall.xml
index e87660a6c..a8a9a870f 100644
--- a/res/layout/incall.xml
+++ b/res/layout/incall.xml
@@ -44,6 +44,7 @@
android:src="@drawable/switch_camera" />
+ android:orientation="horizontal">
-
+
+
+
+
+ android:layout_height="wrap_content"/>
+
+
-
+
+
-
+ android:background="@drawable/pause_off" />
-
+ android:background="@drawable/conference" />
-
+ android:background="@drawable/hangup" />
-
+ android:background="@drawable/dialer_alt" />
diff --git a/res/layout/incoming.xml b/res/layout/incoming.xml
index 1446ab81e..edab449f9 100644
--- a/res/layout/incoming.xml
+++ b/res/layout/incoming.xml
@@ -16,7 +16,7 @@
+ android:layout_height="75dp">
-
+
+ android:layout_weight="1"
+ android:adjustViewBounds="true">
@@ -117,9 +118,9 @@
+ android:layout_weight="1"
+ android:adjustViewBounds="true">
@@ -153,5 +155,14 @@
+
+
+
+
diff --git a/res/layout/menu_about_chat_button.xml b/res/layout/menu_about_chat_button.xml
index 13c061450..f5b189018 100644
--- a/res/layout/menu_about_chat_button.xml
+++ b/res/layout/menu_about_chat_button.xml
@@ -3,9 +3,10 @@
android:id="@+id/about_chat"
android:visibility="gone"
xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_weight="0.2"
- android:layout_width="wrap_content"
- android:layout_height="wrap_content">
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:adjustViewBounds="true">
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:adjustViewBounds="true">
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:adjustViewBounds="true">
+ android:layout_weight="1"
+ android:layout_width="0dp"
+ android:layout_height="wrap_content"
+ android:adjustViewBounds="true">
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/setup_cancel_button.xml b/res/layout/setup_cancel_button.xml
index be0cbf564..49aa03085 100644
--- a/res/layout/setup_cancel_button.xml
+++ b/res/layout/setup_cancel_button.xml
@@ -8,7 +8,7 @@
-
+ android:text="@string/setup_title_assistant"/>
-
+ android:text="@string/setup_title_assistant"/>
-
+ android:text="@string/setup_title_assistant"/>
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/setup_remote_provisioning_login.xml b/res/layout/setup_remote_provisioning_login.xml
new file mode 100644
index 000000000..f3022b9fb
--- /dev/null
+++ b/res/layout/setup_remote_provisioning_login.xml
@@ -0,0 +1,135 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/setup_wizard.xml b/res/layout/setup_wizard.xml
index 3c4ecbc37..ac1804a66 100644
--- a/res/layout/setup_wizard.xml
+++ b/res/layout/setup_wizard.xml
@@ -4,12 +4,15 @@
android:layout_height="match_parent"
android:orientation="vertical" >
-
+ android:text="@string/setup_title_assistant"/>
+ android:textSize="18sp"/>
@@ -55,7 +55,7 @@
android:text="@string/call_stats_codec"
android:textStyle="bold"
android:textColor="@android:color/white"
- android:textSize="12dp"/>
+ android:textSize="12sp"/>
+ android:textSize="12sp"/>
@@ -79,7 +79,7 @@
android:text="@string/call_stats_upload"
android:textStyle="bold"
android:textColor="@android:color/white"
- android:textSize="12dp"/>
+ android:textSize="12sp"/>
+ android:textSize="12sp"/>
@@ -103,7 +103,7 @@
android:text="@string/call_stats_download"
android:textColor="@android:color/white"
android:textStyle="bold"
- android:textSize="12dp"/>
+ android:textSize="12sp"/>
+ android:textSize="12sp"/>
@@ -127,7 +127,7 @@
android:text="@string/call_stats_ice"
android:textStyle="bold"
android:textColor="@android:color/white"
- android:textSize="12dp"/>
+ android:textSize="12sp"/>
+ android:textSize="12sp"/>
+
+
+
+
+
+
+
+
@@ -179,7 +204,7 @@
android:id="@+id/statusText"
android:text="@string/status_not_connected"
android:textColor="@android:color/white"
- android:textSize="18dp"
+ android:textSize="18sp"
android:paddingLeft="5dp"
android:layout_centerVertical="true"
android:layout_width="wrap_content"
@@ -205,20 +230,50 @@
android:layout_centerHorizontal="true"
android:visibility="gone" />
-
+ android:textSize="18sp" />
+
+
+
+
\ No newline at end of file
diff --git a/res/raw-sw600dp/linphonerc_default b/res/raw-sw600dp/linphonerc_default
new file mode 100644
index 000000000..8ee2fbaba
--- /dev/null
+++ b/res/raw-sw600dp/linphonerc_default
@@ -0,0 +1,21 @@
+[net]
+download_bw=512
+upload_bw=512
+
+[sip]
+contact="Linphone Android"
+use_info=0
+use_ipv6=0
+keepalive_period=30000
+
+[video]
+size=vga
+
+[app]
+sharing_server=https://www.linphone.org:444/lft.php
+tunnel=disabled
+push_notification=1
+
+[tunnel]
+host=
+port=443
diff --git a/res/raw/linphonerc b/res/raw-sw600dp/linphonerc_factory
similarity index 72%
rename from res/raw/linphonerc
rename to res/raw-sw600dp/linphonerc_factory
index c64658e33..982a552fc 100644
--- a/res/raw/linphonerc
+++ b/res/raw-sw600dp/linphonerc_factory
@@ -1,24 +1,15 @@
[net]
-download_bw=380
-upload_bw=380
-firewall_policy=0
mtu=1300
[sip]
-sip_port=5060
-sip_random_port=1
guess_hostname=1
-contact=sip:unknown@unknown-host
inc_timeout=15
-use_info=0
-use_ipv6=0
register_only_when_network_is_up=1
-default_proxy=0
auto_net_state_mon=0
-keepalive_period=30000
auto_answer_replacing_calls=1
media_encryption_mandatory=0
ping_with_options=0
+root_ca=/data/data/org.linphone/files/rootca.pem
[rtp]
audio_rtp_port=7076
@@ -26,6 +17,7 @@ video_rtp_port=9078
audio_jitt_comp=60
video_jitt_comp=60
nortp_timeout=30
+disable_upnp=1
[sound]
playback_dev_id=
@@ -35,8 +27,6 @@ remote_ring=/data/data/org.linphone/files/ringback.wav
local_ring=/data/data/org.linphone/files/oldphone_mono.wav
dtmf_player_amp=0.1
-[video]
-size=qvga
-
[misc]
max_calls=10
+log_collection_upload_server_url=https://www.linphone.org:444/lft.php
\ No newline at end of file
diff --git a/res/raw/incoming_chat.wav b/res/raw/incoming_chat.wav
new file mode 100644
index 000000000..99a2e7dfc
Binary files /dev/null and b/res/raw/incoming_chat.wav differ
diff --git a/res/raw/linphonerc_default b/res/raw/linphonerc_default
new file mode 100644
index 000000000..27dcac0ab
--- /dev/null
+++ b/res/raw/linphonerc_default
@@ -0,0 +1,21 @@
+[net]
+download_bw=380
+upload_bw=380
+
+[sip]
+contact="Linphone Android"
+use_info=0
+use_ipv6=0
+keepalive_period=30000
+
+[video]
+size=qvga
+
+[app]
+sharing_server=https://www.linphone.org:444/lft.php
+tunnel=disabled
+push_notification=1
+
+[tunnel]
+host=
+port=443
diff --git a/res/raw-sw600dp/linphonerc b/res/raw/linphonerc_factory
similarity index 70%
rename from res/raw-sw600dp/linphonerc
rename to res/raw/linphonerc_factory
index 290c05f42..0b0a6c92c 100644
--- a/res/raw-sw600dp/linphonerc
+++ b/res/raw/linphonerc_factory
@@ -1,23 +1,15 @@
[net]
-download_bw=512
-upload_bw=512
-firewall_policy=0
mtu=1300
[sip]
-sip_port=5060
-sip_random_port=1
guess_hostname=1
-contact=sip:unknown@unknown-host
inc_timeout=15
-use_info=0
-use_ipv6=0
register_only_when_network_is_up=1
-default_proxy=0
auto_net_state_mon=0
-keepalive_period=30000
auto_answer_replacing_calls=1
media_encryption_mandatory=0
+ping_with_options=0
+root_ca=/data/data/org.linphone/files/rootca.pem
[rtp]
audio_rtp_port=7076
@@ -25,6 +17,7 @@ video_rtp_port=9078
audio_jitt_comp=60
video_jitt_comp=60
nortp_timeout=30
+disable_upnp=1
[sound]
playback_dev_id=
@@ -34,8 +27,7 @@ remote_ring=/data/data/org.linphone/files/ringback.wav
local_ring=/data/data/org.linphone/files/oldphone_mono.wav
dtmf_player_amp=0.1
-[video]
-size=vga
-
[misc]
max_calls=10
+log_collection_upload_server_url=https://www.linphone.org:444/lft.php
+user_certificates_path=/data/data/org.linphone/files
\ No newline at end of file
diff --git a/res/raw/rootca.pem b/res/raw/rootca.pem
deleted file mode 100644
index 16f4fe95b..000000000
--- a/res/raw/rootca.pem
+++ /dev/null
@@ -1,3989 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UE
-AwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00x
-CzAJBgNVBAYTAkVTMB4XDTA4MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEW
-MBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZF
-RElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKC
-AgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHkWLn7
-09gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7
-XBZXehuDYAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5P
-Grjm6gSSrj0RuVFCPYewMYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAK
-t0SdE3QrwqXrIhWYENiLxQSfHY9g5QYbm8+5eaA9oiM/Qj9r+hwDezCNzmzAv+Yb
-X79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbkHQl/Sog4P75n/TSW9R28
-MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTTxKJxqvQU
-fecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI
-2Sf23EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyH
-K9caUPgn6C9D4zq92Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEae
-ZAwUswdbxcJzbPEHXEUkFDWug/FqTYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAP
-BgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz4SsrSbbXc6GqlPUB53NlTKxQ
-MA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU9QHnc2VMrFAw
-RAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv
-bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWIm
-fQwng4/F9tqgaHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3
-gvoFNTPhNahXwOf9jU8/kzJPeGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKe
-I6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1PwkzQSulgUV1qzOMPPKC8W64iLgpq0i
-5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1ThCojz2GuHURwCRi
-ipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oIKiMn
-MCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZ
-o5NjEFIqnxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6
-zqylfDJKZ0DcMDQj3dcEI2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacN
-GHk0vFQYXlPKNFHtRQrmjseCNj6nOGOpMCwXEGCSn1WHElkQwg9naRHMTh5+Spqt
-r0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3otkYNbn5XOmeUwssfnHdK
-Z05phkOTOPu220+DkdRgfks+KzgHVZhepA==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsx
-CzAJBgNVBAYTAkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRp
-ZmljYWNpw7NuIERpZ2l0YWwgLSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwa
-QUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4wHhcNMDYxMTI3MjA0NjI5WhcNMzAw
-NDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+U29jaWVkYWQgQ2Ft
-ZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJhIFMu
-QS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkq
-hkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeG
-qentLhM0R7LQcNzJPNCNyu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzL
-fDe3fezTf3MZsGqy2IiKLUV0qPezuMDU2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQ
-Y5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU34ojC2I+GdV75LaeHM/J4
-Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP2yYe68yQ
-54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+b
-MMCm8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48j
-ilSH5L887uvDdUhfHjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++Ej
-YfDIJss2yKHzMI+ko6Kh3VOz3vCaMh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/zt
-A/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK5lw1omdMEWux+IBkAC1vImHF
-rEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1bczwmPS9KvqfJ
-pxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
-AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCB
-lTCBkgYEVR0gADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFy
-YS5jb20vZHBjLzBaBggrBgEFBQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW50
-7WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2UgcHVlZGVuIGVuY29udHJhciBlbiBs
-YSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEfAygPU3zmpFmps4p6
-xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuXEpBc
-unvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/
-Jre7Ir5v/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dp
-ezy4ydV/NgIlqmjCMRW3MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42
-gzmRkBDI8ck1fj+404HGIGQatlDCIaR43NAvO2STdPCWkPHv+wlaNECW8DYSwaN0
-jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wkeZBWN7PGKX6jD/EpOe9+
-XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f/RWmnkJD
-W2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/
-RL5hRqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35r
-MDOhYil/SrnhLecUIw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxk
-BYn8eNZcLCZDqQ==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFs
-IFRUUCBOZXR3b3JrMSIwIAYDVQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290
-MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEwNDgzOFowbzELMAkGA1UEBhMCU0Ux
-FDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRUcnVzdCBFeHRlcm5h
-bCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0EgUm9v
-dDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvt
-H7xsD821+iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9
-uMq/NzgtHj6RQa1wVsfwTz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzX
-mk6vBbOmcZSccbNQYArHE504B4YCqOmoaSYYkKtMsE8jqzpPhNjfzp/haW+710LX
-a0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy2xSoRcRdKn23tNbE7qzN
-E0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv77+ldU9U0
-WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYD
-VR0PBAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0
-Jvf6xCZU7wO94CTLVBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRU
-cnVzdCBBQjEmMCQGA1UECxMdQWRkVHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsx
-IjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENBIFJvb3SCAQEwDQYJKoZIhvcN
-AQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZlj7DYd7usQWxH
-YINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
-6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvC
-Nr4TDea9Y355e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEX
-c4g/VhsxOBi0cQ+azcgOno4uG+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5a
-mnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
-b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMw
-MTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
-QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYD
-VQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUA
-A4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ul
-CDtbKRY654eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6n
-tGO0/7Gcrjyvd7ZWxbWroulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyl
-dI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1Zmne3yzxbrww2ywkEtvrNTVokMsAsJch
-PXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJuiGMx1I4S+6+JNM3GOGvDC
-+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8wHQYDVR0O
-BBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8E
-BTADAQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBl
-MQswCQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFk
-ZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENB
-IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxtZBsfzQ3duQH6lmM0MkhHma6X
-7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0PhiVYrqW9yTkkz
-43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
-eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJl
-pz/+0WatC7xrmYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOA
-WiFeIc9TVPC6b4nbqKqVz4vjccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
-b3JrMSAwHgYDVQQDExdBZGRUcnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAx
-MDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtB
-ZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIDAeBgNV
-BAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOC
-AQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV
-6tsfSlbunyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nX
-GCwwfQ56HmIexkvA/X1id9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnP
-dzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSGAa2Il+tmzV7R/9x98oTaunet3IAIx6eH
-1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAwHM+A+WD+eeSI8t0A65RF
-62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0GA1UdDgQW
-BBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUw
-AwEB/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDEL
-MAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRU
-cnVzdCBUVFAgTmV0d29yazEgMB4GA1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJv
-b3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4JNojVhaTdt02KLmuG7jD8WS6
-IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL+YPoRNWyQSW/
-iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
-GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh
-4SINhwBk/ox9Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQm
-XiLsks3/QppEIW1cxeMiHV9HEufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEU
-MBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3
-b3JrMSMwIQYDVQQDExpBZGRUcnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1
-MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcxCzAJBgNVBAYTAlNFMRQwEgYDVQQK
-EwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5ldHdvcmsxIzAh
-BgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG9w0B
-AQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwq
-xBb/4Oxx64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G
-87B4pfYOQnrjfxvM0PC3KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i
-2O+tCBGaKZnhqkRFmhJePp1tUvznoD1oL/BLcHwTOK28FSXx1s6rosAx1i+f4P8U
-WfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GRwVY18BTcZTYJbqukB8c1
-0cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HUMIHRMB0G
-A1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0T
-AQH/BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6Fr
-pGkwZzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQL
-ExRBZGRUcnVzdCBUVFAgTmV0d29yazEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlm
-aWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBABmrder4i2VhlRO6aQTv
-hsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxGGuoYQ992zPlm
-hpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
-dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3
-P6CxB9bpT9zeRXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9Y
-iQBCYz95OdBEsIJuQRno3eDBiFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5no
-xqE=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc
-MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP
-bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2
-MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft
-ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg
-Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lk
-hsmj76CGv2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym
-1BW32J/X3HGrfpq/m44zDyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsW
-OqMFf6Dch9Wc/HKpoH145LcxVR5lu9RhsCFg7RAycsWSJR74kEoYeEfffjA3PlAb
-2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP8c9GsEsPPt2IYriMqQko
-O3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0TAQH/BAUw
-AwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAU
-AK3Zo/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
-BQUAA4IBAQB8itEfGDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkF
-Zu90821fnZmv9ov761KyBZiibyrFVL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAb
-LjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft3OJvx8Fi8eNy1gTIdGcL+oir
-oQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43gKd8hdIaC2y+C
-MMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds
-sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEc
-MBoGA1UEChMTQW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBP
-bmxpbmUgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2
-MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0Ft
-ZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2EgT25saW5lIFJvb3Qg
-Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQADggIP
-ADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC
-206B89enfHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFci
-KtZHgVdEglZTvYYUAQv8f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2
-JxhP7JsowtS013wMPgwr38oE18aO6lhOqKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9
-BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JNRvCAOVIyD+OEsnpD8l7e
-Xz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0gBe4lL8B
-PeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67
-Xnfn6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEq
-Z8A9W6Wa6897GqidFEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZ
-o2C7HK2JNDJiuEMhBnIMoVxtRsX6Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3
-+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnjB453cMor9H124HhnAgMBAAGj
-YzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3OpaaEg5+31IqEj
-FNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE
-AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmn
-xPBUlgtk87FYT15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2
-LHo1YGwRgJfMqZJS5ivmae2p+DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzccc
-obGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXgJXUjhx5c3LqdsKyzadsXg8n33gy8
-CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//ZoyzH1kUQ7rVyZ2OuMe
-IjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgOZtMA
-DjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2F
-AjgQ5ANh1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUX
-Om/9riW99XJZZLF0KjhfGEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPb
-AZO1XB4Y3WRayhgoPmMEEf0cjQAPuDffZ4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQl
-Zvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuPcX/9XhmgD0uRuMRUvAaw
-RY8mkaKO/qk=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIID5jCCAs6gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx
-HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh
-IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0
-aWZpY2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyOTA2MDAwMFoXDTM3MTEyMDE1
-MDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg
-SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M
-IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIw
-DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJnej8Mlo2k06AX3dLm/WpcZuS+U
-0pPlLYnKhHw/EEMbjIt8hFj4JHxIzyr9wBXZGH6EGhfT257XyuTZ16pYUYfw8ItI
-TuLCxFlpMGK2MKKMCxGZYTVtfu/FsRkGIBKOQuHfD5YQUqjPnF+VFNivO3ULMSAf
-RC+iYkGzuxgh28pxPIzstrkNn+9R7017EvILDOGsQI93f7DKeHEMXRZxcKLXwjqF
-zQ6axOAAsNUl6twr5JQtOJyJQVdkKGUZHLZEtMgxa44Be3ZZJX8VHIQIfHNlIAqh
-BC4aMqiaILGcLCFZ5/vP7nAtCMpjPiybkxlqpMKX/7eGV4iFbJ4VFitNLLMCAwEA
-AaNjMGEwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUoTYwFsuGkABFgFOxj8jY
-PXy+XxIwHwYDVR0jBBgwFoAUoTYwFsuGkABFgFOxj8jYPXy+XxIwDgYDVR0PAQH/
-BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQCKIBilvrMvtKaEAEAwKfq0FHNMeUWn
-9nDg6H5kHgqVfGphwu9OH77/yZkfB2FK4V1Mza3u0FIy2VkyvNp5ctZ7CegCgTXT
-Ct8RHcl5oIBN/lrXVtbtDyqvpxh1MwzqwWEFT2qaifKNuZ8u77BfWgDrvq2g+EQF
-Z7zLBO+eZMXpyD8Fv8YvBxzDNnGGyjhmSs3WuEvGbKeXO/oTLW4jYYehY0KswsuX
-n2Fozy1MBJ3XJU8KDk2QixhWqJNIV9xvrr2eZ1d3iVCzvhGbRWeDhhmH05i9CBoW
-H1iCC+GWaQVLjuyDUTEH1dSf/1l7qG6Fz9NLqUmwX7A5KGgOc90lmt4S
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIF5jCCA86gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBgzELMAkGA1UEBhMCVVMx
-HTAbBgNVBAoTFEFPTCBUaW1lIFdhcm5lciBJbmMuMRwwGgYDVQQLExNBbWVyaWNh
-IE9ubGluZSBJbmMuMTcwNQYDVQQDEy5BT0wgVGltZSBXYXJuZXIgUm9vdCBDZXJ0
-aWZpY2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyOTA2MDAwMFoXDTM3MDkyODIz
-NDMwMFowgYMxCzAJBgNVBAYTAlVTMR0wGwYDVQQKExRBT0wgVGltZSBXYXJuZXIg
-SW5jLjEcMBoGA1UECxMTQW1lcmljYSBPbmxpbmUgSW5jLjE3MDUGA1UEAxMuQU9M
-IFRpbWUgV2FybmVyIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIw
-DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBALQ3WggWmRToVbEbJGv8x4vmh6mJ
-7ouZzU9AhqS2TcnZsdw8TQ2FTBVsRotSeJ/4I/1n9SQ6aF3Q92RhQVSji6UI0ilb
-m2BPJoPRYxJWSXakFsKlnUWsi4SVqBax7J/qJBrvuVdcmiQhLE0OcR+mrF1FdAOY
-xFSMFkpBd4aVdQxHAWZg/BXxD+r1FHjHDtdugRxev17nOirYlxcwfACtCJ0zr7iZ
-YYCLqJV+FNwSbKTQ2O9ASQI2+W6p1h2WVgSysy0WVoaP2SBXgM1nEG2wTPDaRrbq
-JS5Gr42whTg0ixQmgiusrpkLjhTXUr2eacOGAgvqdnUxCc4zGSGFQ+aJLZ8lN2fx
-I2rSAG2X+Z/nKcrdH9cG6rjJuQkhn8g/BsXS6RJGAE57COtCPStIbp1n3UsC5ETz
-kxmlJ85per5n0/xQpCyrw2u544BMzwVhSyvcG7mm0tCq9Stz+86QNZ8MUhy/XCFh
-EVsVS6kkUfykXPcXnbDS+gfpj1bkGoxoigTTfFrjnqKhynFbotSg5ymFXQNoKk/S
-Btc9+cMDLz9l+WceR0DTYw/j1Y75hauXTLPXJuuWCpTehTacyH+BCQJJKg71ZDIM
-gtG6aoIbs0t0EfOMd9afv9w3pKdVBC/UMejTRrkDfNoSTllkt1ExMVCgyhwn2RAu
-rda9EGYrw7AiShJbAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
-FE9pbQN+nZ8HGEO8txBO1b+pxCAoMB8GA1UdIwQYMBaAFE9pbQN+nZ8HGEO8txBO
-1b+pxCAoMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAO/Ouyugu
-h4X7ZVnnrREUpVe8WJ8kEle7+z802u6teio0cnAxa8cZmIDJgt43d15Ui47y6mdP
-yXSEkVYJ1eV6moG2gcKtNuTxVBFT8zRFASbI5Rq8NEQh3q0l/HYWdyGQgJhXnU7q
-7C+qPBR7V8F+GBRn7iTGvboVsNIYvbdVgaxTwOjdaRITQrcCtQVBynlQboIOcXKT
-RuidDV29rs4prWPVVRaAMCf/drr3uNZK49m1+VLQTkCpx+XCMseqdiThawVQ68W/
-ClTluUI8JPu3B5wwn3la5uBAUhX0/Kr0VvlEl4ftDmVyXr4m+02kLQgH3thcoNyB
-M5kYJRF3p+v9WAksmWsbivNSPxpNSGDxoPYzAlOL7SUJuA0t7Zdz7NeWH45gDtoQ
-my8YJPamTQr5O8t1wswvziRpyQoijlmn94IM19drNZxDAGrElWe6nEXLuA4399xO
-AU++CrYD062KRffaJ00psUjf5BHklka9bAI+1lHIlRcBFanyqqryvy9lG2/QuRqT
-9Y41xICHPpQvZuTpqP9BnHAqTyo5GJUefvthATxRCC4oGKQWDzH9OmwjkyB24f0H
-hdFbP9IcczLd+rn4jM8Ch3qaluTtT4mNU0OrDhPAARW0eTjb/G49nlG2uBOLZ8/5
-fNkiHfZdxRwBL5joeiQYvITX+txyW/fBOmg=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEc
-MBoGA1UEChMTSmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRp
-b25DQTAeFw0wNzEyMTIxNTAwMDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYT
-AkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zlcm5tZW50MRYwFAYDVQQLEw1BcHBs
-aWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAp23gdE6H
-j6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4fl+K
-f5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55
-IrmTwcrNwVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cw
-FO5cjFW6WY2H/CPek9AEjP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDiht
-QWEjdnjDuGWk81quzMKq2edY3rZ+nYVunyoKb58DKTCXKB28t89UKU5RMfkntigm
-/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRUWssmP3HMlEYNllPqa0jQ
-k/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNVBAYTAkpQ
-MRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOC
-seODvOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
-ggEBADlqRHZ3ODrso2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJ
-hyzjVOGjprIIC8CFqMjSnHH2HZ9g/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+
-eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYDio+nEhEMy/0/ecGc/WLuo89U
-DNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmWdupwX3kSa+Sj
-B1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL
-rosot4LKGAfmt1t06SAZf7IbiVQ=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UE
-BhMCRVMxQjBABgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1h
-cHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEy
-MzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIwQAYDVQQDDDlBdXRvcmlkYWQgZGUg
-Q2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBBNjI2MzQwNjgwggIi
-MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDDUtd9
-thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQM
-cas9UX4PB99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefG
-L9ItWY16Ck6WaVICqjaY7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15i
-NA9wBj4gGFrO93IbJWyTdBSTo3OxDqqHECNZXyAFGUftaI6SEspd/NYrspI8IM/h
-X68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyIplD9amML9ZMWGxmPsu2b
-m8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctXMbScyJCy
-Z/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirja
-EbsXLZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/T
-KI8xWVvTyQKmtFLKbpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF
-6NkBiDkal4ZkQdU7hwxu+g/GvUgUvzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVh
-OSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1UdEwEB/wQIMAYBAf8CAQEwDgYD
-VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNHDhpkLzCBpgYD
-VR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
-cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBv
-ACAAZABlACAAbABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBl
-AGwAbwBuAGEAIAAwADgAMAAxADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF
-661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx51tkljYyGOylMnfX40S2wBEqgLk9
-am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qkR71kMrv2JYSiJ0L1
-ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaPT481
-PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS
-3a/DTg4fJl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5k
-SeTy36LssUzAKh3ntLFlosS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF
-3dvd6qJ2gHN99ZwExEWN57kci57q13XRcrHedUTnQn3iV2t93Jm8PYMo6oCTjcVM
-ZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoRsaS8I8nkvof/uZS2+F0g
-StRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTDKCOM/icz
-Q0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQB
-jLMi6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJ
-RTESMBAGA1UEChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYD
-VQQDExlCYWx0aW1vcmUgQ3liZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoX
-DTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMCSUUxEjAQBgNVBAoTCUJhbHRpbW9y
-ZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFsdGltb3JlIEN5YmVy
-VHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKMEuyKr
-mD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjr
-IZ3AQSsBUnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeK
-mpYcqWe4PwzV9/lSEy/CG9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSu
-XmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9XbIGevOF6uvUA65ehD5f/xXtabz5OTZy
-dc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjprl3RjM71oGDHweI12v/ye
-jl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoIVDaGezq1
-BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3
-DQEBBQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT92
-9hkTI7gQCvlYpNRhcL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3Wgx
-jkzSswF07r51XgdIGn9w/xZchMB5hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0
-Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsaY71k5h+3zvDyny67G7fyUIhz
-ksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9HRCwBXbsdtTLS
-R9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEuDCCA6CgAwIBAgIBBDANBgkqhkiG9w0BAQUFADCBtDELMAkGA1UEBhMCQlIx
-EzARBgNVBAoTCklDUC1CcmFzaWwxPTA7BgNVBAsTNEluc3RpdHV0byBOYWNpb25h
-bCBkZSBUZWNub2xvZ2lhIGRhIEluZm9ybWFjYW8gLSBJVEkxETAPBgNVBAcTCEJy
-YXNpbGlhMQswCQYDVQQIEwJERjExMC8GA1UEAxMoQXV0b3JpZGFkZSBDZXJ0aWZp
-Y2Fkb3JhIFJhaXogQnJhc2lsZWlyYTAeFw0wMTExMzAxMjU4MDBaFw0xMTExMzAy
-MzU5MDBaMIG0MQswCQYDVQQGEwJCUjETMBEGA1UEChMKSUNQLUJyYXNpbDE9MDsG
-A1UECxM0SW5zdGl0dXRvIE5hY2lvbmFsIGRlIFRlY25vbG9naWEgZGEgSW5mb3Jt
-YWNhbyAtIElUSTERMA8GA1UEBxMIQnJhc2lsaWExCzAJBgNVBAgTAkRGMTEwLwYD
-VQQDEyhBdXRvcmlkYWRlIENlcnRpZmljYWRvcmEgUmFpeiBCcmFzaWxlaXJhMIIB
-IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAwPMudwX/hvm+Uh2b/lQAcHVA
-isamaLkWdkwP9/S/tOKIgRrL6Oy+ZIGlOUdd6uYtk9Ma/3pUpgcfNAj0vYm5gsyj
-Qo9emsc+x6m4VWwk9iqMZSCK5EQkAq/Ut4n7KuLE1+gdftwdIgxfUsPt4CyNrY50
-QV57KM2UT8x5rrmzEjr7TICGpSUAl2gVqe6xaii+bmYR1QrmWaBSAG59LrkrjrYt
-bRhFboUDe1DK+6T8s5L6k8c8okpbHpa9veMztDVC9sPJ60MWXh6anVKo1UcLcbUR
-yEeNvZneVRKAAU6ouwdjDvwlsaKydFKwed0ToQ47bmUKgcm+wV3eTRk36UOnTwID
-AQABo4HSMIHPME4GA1UdIARHMEUwQwYFYEwBAQAwOjA4BggrBgEFBQcCARYsaHR0
-cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0RQQ2FjcmFpei5wZGYwPQYDVR0f
-BDYwNDAyoDCgLoYsaHR0cDovL2FjcmFpei5pY3BicmFzaWwuZ292LmJyL0xDUmFj
-cmFpei5jcmwwHQYDVR0OBBYEFIr68VeEERM1kEL6V0lUaQ2kxPA3MA8GA1UdEwEB
-/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAZA5c1
-U/hgIh6OcgLAfiJgFWpvmDZWqlV30/bHFpj8iBobJSm5uDpt7TirYh1Uxe3fQaGl
-YjJe+9zd+izPRbBqXPVQA34EXcwk4qpWuf1hHriWfdrx8AcqSqr6CuQFwSr75Fos
-SzlwDADa70mT7wZjAmQhnZx2xJ6wfWlT9VQfS//JYeIc7Fue2JNLd00UOSMMaiK/
-t79enKNHEA2fupH3vEigf5Eh4bVAN5VohrTm6MY53x7XQZZr1ME7a55lFEnSeT0u
-mlOAjR2mAbvSM5X5oSZNrmetdzyTj2flCM8CC7MLab0kkdngRIlUBGHF1/S5nmPb
-K+9A46sd33oqK8n8
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd
-MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg
-Q2xhc3MgMiBDQSAxMB4XDTA2MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzEL
-MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD
-VQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7McXA0
-ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLX
-l18xoS830r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVB
-HfCuuCkslFJgNJQ72uA40Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B
-5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/RuFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3
-WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
-AwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0PAQH/BAQD
-AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLP
-gcIV1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+
-DKhQ7SLHrQVMdvvt7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKu
-BctN518fV4bVIJwo+28TOPX2EZL2fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHs
-h7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5wwDX3OaJdZtB7WZ+oRxKaJyOk
-LY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEd
-MBsGA1UECgwUQnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3Mg
-Q2xhc3MgMyBDQSAxMB4XDTA1MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzEL
-MAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBhc3MgQVMtOTgzMTYzMzI3MR0wGwYD
-VQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKxifZg
-isRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//z
-NIqeKNc0n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI
-+MkcVyzwPX6UvCWThOiaAJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2R
-hzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+
-mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
-AwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0PAQH/BAQD
-AgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFP
-Bdy7pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27s
-EzNxZy5p+qksP2bAEllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2
-mSlf56oBzKwzqBwKu5HEA6BvtjT5htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yC
-e/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQjel/wroQk5PMr+4okoyeYZdow
-dXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIHPTCCBSWgAwIBAgIBADANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290
-IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB
-IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA
-Y2FjZXJ0Lm9yZzAeFw0wMzAzMzAxMjI5NDlaFw0zMzAzMjkxMjI5NDlaMHkxEDAO
-BgNVBAoTB1Jvb3QgQ0ExHjAcBgNVBAsTFWh0dHA6Ly93d3cuY2FjZXJ0Lm9yZzEi
-MCAGA1UEAxMZQ0EgQ2VydCBTaWduaW5nIEF1dGhvcml0eTEhMB8GCSqGSIb3DQEJ
-ARYSc3VwcG9ydEBjYWNlcnQub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
-CgKCAgEAziLA4kZ97DYoB1CW8qAzQIxL8TtmPzHlawI229Z89vGIj053NgVBlfkJ
-8BLPRoZzYLdufujAWGSuzbCtRRcMY/pnCujW0r8+55jE8Ez64AO7NV1sId6eINm6
-zWYyN3L69wj1x81YyY7nDl7qPv4coRQKFWyGhFtkZip6qUtTefWIonvuLwphK42y
-fk1WpRPs6tqSnqxEQR5YYGUFZvjARL3LlPdCfgv3ZWiYUQXw8wWRBB0bF4LsyFe7
-w2t6iPGwcswlWyCR7BYCEo8y6RcYSNDHBS4CMEK4JZwFaz+qOqfrU0j36NK2B5jc
-G8Y0f3/JHIJ6BVgrCFvzOKKrF11myZjXnhCLotLddJr3cQxyYN/Nb5gznZY0dj4k
-epKwDpUeb+agRThHqtdB7Uq3EvbXG4OKDy7YCbZZ16oE/9KTfWgu3YtLq1i6L43q
-laegw1SJpfvbi1EinbLDvhG+LJGGi5Z4rSDTii8aP8bQUWWHIbEZAWV/RRyH9XzQ
-QUxPKZgh/TMfdQwEUfoZd9vUFBzugcMd9Zi3aQaRIt0AUMyBMawSB3s42mhb5ivU
-fslfrejrckzzAeVLIL+aplfKkQABi6F1ITe1Yw1nPkZPcCBnzsXWWdsC4PDSy826
-YreQQejdIOQpvGQpQsgi3Hia/0PsmBsJUUtaWsJx8cTLc6nloQsCAwEAAaOCAc4w
-ggHKMB0GA1UdDgQWBBQWtTIb1Mfz4OaO873SsDrusjkY0TCBowYDVR0jBIGbMIGY
-gBQWtTIb1Mfz4OaO873SsDrusjkY0aF9pHsweTEQMA4GA1UEChMHUm9vdCBDQTEe
-MBwGA1UECxMVaHR0cDovL3d3dy5jYWNlcnQub3JnMSIwIAYDVQQDExlDQSBDZXJ0
-IFNpZ25pbmcgQXV0aG9yaXR5MSEwHwYJKoZIhvcNAQkBFhJzdXBwb3J0QGNhY2Vy
-dC5vcmeCAQAwDwYDVR0TAQH/BAUwAwEB/zAyBgNVHR8EKzApMCegJaAjhiFodHRw
-czovL3d3dy5jYWNlcnQub3JnL3Jldm9rZS5jcmwwMAYJYIZIAYb4QgEEBCMWIWh0
-dHBzOi8vd3d3LmNhY2VydC5vcmcvcmV2b2tlLmNybDA0BglghkgBhvhCAQgEJxYl
-aHR0cDovL3d3dy5jYWNlcnQub3JnL2luZGV4LnBocD9pZD0xMDBWBglghkgBhvhC
-AQ0ESRZHVG8gZ2V0IHlvdXIgb3duIGNlcnRpZmljYXRlIGZvciBGUkVFIGhlYWQg
-b3ZlciB0byBodHRwOi8vd3d3LmNhY2VydC5vcmcwDQYJKoZIhvcNAQEEBQADggIB
-ACjH7pyCArpcgBLKNQodgW+JapnM8mgPf6fhjViVPr3yBsOQWqy1YPaZQwGjiHCc
-nWKdpIevZ1gNMDY75q1I08t0AoZxPuIrA2jxNGJARjtT6ij0rPtmlVOKTV39O9lg
-18p5aTuxZZKmxoGCXJzN600BiqXfEVWqFcofN8CCmHBh22p8lqOOLlQ+TyGpkO/c
-gr/c6EWtTZBzCDyUZbAEmXZ/4rzCahWqlwQ3JNgelE5tDlG+1sSPypZt90Pf6DBl
-Jzt7u0NDY8RD97LsaMzhGY4i+5jhe1o+ATc7iwiwovOVThrLm82asduycPAtStvY
-sONvRUgzEv/+PDIqVPfE94rwiCPCR/5kenHA0R6mY7AHfqQv0wGP3J8rtsYIqQ+T
-SCX8Ev2fQtzzxD72V7DX3WnRBnc0CkvSyqD/HMaMyRa+xMwyN2hzXwj7UfdJUzYF
-CpUCTPJ5GhD22Dp1nPMd8aINcGeGG7MW9S/lpOt5hvk9C8JzC6WZrG/8Z7jlLwum
-GCSNe9FINSkYQKyTYOGWhlC0elnYjyELn8+CkcY7v2vcB5G5l1YjqrZslMZIBjzk
-zk6q5PYvCdxTby78dOs6Y5nCpqyJvKeyRKANihDjbPIky/qbn3BHLt4Ui9SyIAmW
-omTxJBzcoTWcFbLUvFUufQb1nA5V9FrWk9p2rSVzTMVD
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIGCDCCA/CgAwIBAgIBATANBgkqhkiG9w0BAQQFADB5MRAwDgYDVQQKEwdSb290
-IENBMR4wHAYDVQQLExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNB
-IENlcnQgU2lnbmluZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRA
-Y2FjZXJ0Lm9yZzAeFw0wNTEwMTQwNzM2NTVaFw0zMzAzMjgwNzM2NTVaMFQxFDAS
-BgNVBAoTC0NBY2VydCBJbmMuMR4wHAYDVQQLExVodHRwOi8vd3d3LkNBY2VydC5v
-cmcxHDAaBgNVBAMTE0NBY2VydCBDbGFzcyAzIFJvb3QwggIiMA0GCSqGSIb3DQEB
-AQUAA4ICDwAwggIKAoICAQCrSTURSHzSJn5TlM9Dqd0o10Iqi/OHeBlYfA+e2ol9
-4fvrcpANdKGWZKufoCSZc9riVXbHF3v1BKxGuMO+f2SNEGwk82GcwPKQ+lHm9WkB
-Y8MPVuJKQs/iRIwlKKjFeQl9RrmK8+nzNCkIReQcn8uUBByBqBSzmGXEQ+xOgo0J
-0b2qW42S0OzekMV/CsLj6+YxWl50PpczWejDAz1gM7/30W9HxM3uYoNSbi4ImqTZ
-FRiRpoWSR7CuSOtttyHshRpocjWr//AQXcD0lKdq1TuSfkyQBX6TwSyLpI5idBVx
-bgtxA+qvFTia1NIFcm+M+SvrWnIl+TlG43IbPgTDZCciECqKT1inA62+tC4T7V2q
-SNfVfdQqe1z6RgRQ5MwOQluM7dvyz/yWk+DbETZUYjQ4jwxgmzuXVjit89Jbi6Bb
-6k6WuHzX1aCGcEDTkSm3ojyt9Yy7zxqSiuQ0e8DYbF/pCsLDpyCaWt8sXVJcukfV
-m+8kKHA4IC/VfynAskEDaJLM4JzMl0tF7zoQCqtwOpiVcK01seqFK6QcgCExqa5g
-eoAmSAC4AcCTY1UikTxW56/bOiXzjzFU6iaLgVn5odFTEcV7nQP2dBHgbbEsPyyG
-kZlxmqZ3izRg0RS0LKydr4wQ05/EavhvE/xzWfdmQnQeiuP43NJvmJzLR5iVQAX7
-6QIDAQABo4G/MIG8MA8GA1UdEwEB/wQFMAMBAf8wXQYIKwYBBQUHAQEEUTBPMCMG
-CCsGAQUFBzABhhdodHRwOi8vb2NzcC5DQWNlcnQub3JnLzAoBggrBgEFBQcwAoYc
-aHR0cDovL3d3dy5DQWNlcnQub3JnL2NhLmNydDBKBgNVHSAEQzBBMD8GCCsGAQQB
-gZBKMDMwMQYIKwYBBQUHAgEWJWh0dHA6Ly93d3cuQ0FjZXJ0Lm9yZy9pbmRleC5w
-aHA/aWQ9MTAwDQYJKoZIhvcNAQEEBQADggIBAH8IiKHaGlBJ2on7oQhy84r3HsQ6
-tHlbIDCxRd7CXdNlafHCXVRUPIVfuXtCkcKZ/RtRm6tGpaEQU55tiKxzbiwzpvD0
-nuB1wT6IRanhZkP+VlrRekF490DaSjrxC1uluxYG5sLnk7mFTZdPsR44Q4Dvmw2M
-77inYACHV30eRBzLI++bPJmdr7UpHEV5FpZNJ23xHGzDwlVks7wU4vOkHx4y/CcV
-Bc/dLq4+gmF78CEQGPZE6lM5+dzQmiDgxrvgu1pPxJnIB721vaLbLmINQjRBvP+L
-ivVRIqqIMADisNS8vmW61QNXeZvo3MhN+FDtkaVSKKKs+zZYPumUK5FQhxvWXtaM
-zPcPEAxSTtAWYeXlCmy/F8dyRlecmPVsYGN6b165Ti/Iubm7aoW8mA3t+T6XhDSU
-rgCvoeXnkm5OvfPi2RSLXNLrAWygF6UtEOucekq9ve7O/e0iQKtwOIj1CodqwqsF
-YMlIBdpTwd5Ed2qz8zw87YC8pjhKKSRf/lk7myV6VmMAZLldpGJ9VzZPrYPvH5JT
-oI53V93lYRE9IwCQTDz6o2CTBKOvNfYOao9PSmCnhQVsRqGP9Md246FZV/dxssRu
-FFxtbUFm3xuTsdQAw+7Lzzw9IYCpX2Nl/N3gX6T0K/CFcUHUZyX7GrGXrtaZghNB
-0m6lG5kngOcLqagA
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzET
-MBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UE
-AxMIQ0EgRGlzaWcwHhcNMDYwMzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQsw
-CQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcg
-YS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgmGErE
-Nx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnX
-mjxUizkDPw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYD
-XcDtab86wYqg6I7ZuUUohwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhW
-S8+2rT+MitcE5eN4TPWGqvWP+j1scaMtymfraHtuM6kMgiioTGohQBUgDCZbg8Kp
-FhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8wgfwwDwYDVR0TAQH/BAUw
-AwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0PAQH/BAQD
-AgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cu
-ZGlzaWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5z
-ay9jYS9jcmwvY2FfZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2sv
-Y2EvY3JsL2NhX2Rpc2lnLmNybDAaBgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEw
-DQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59tWDYcPQuBDRIrRhCA/ec8J9B6
-yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3mkkp7M5+cTxq
-EEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/
-CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeB
-EicTXxChds6KezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFN
-PGO+I++MzVpQuGhU+QqZMxEA4Z7CRneC9VkGjCFMhwnN5ag=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEn
-MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL
-ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMg
-b2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAxNjEzNDNaFw0zNzA5MzAxNjEzNDRa
-MH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZpcm1hIFNBIENJRiBB
-ODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3JnMSIw
-IAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0B
-AQEFAAOCAQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtb
-unXF/KGIJPov7coISjlUxFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0d
-BmpAPrMMhe5cG3nCYsS4No41XQEMIwRHNaqbYE6gZj3LJgqcQKH0XZi/caulAGgq
-7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jWDA+wWFjbw2Y3npuRVDM3
-0pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFVd9oKDMyX
-roDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIG
-A1UdEwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5j
-aGFtYmVyc2lnbi5vcmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p
-26EpW1eLTXYGduHRooowDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIA
-BzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hhbWJlcnNpZ24ub3JnMCcGA1Ud
-EgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYDVR0gBFEwTzBN
-BgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
-aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEB
-AAxBl8IahsAifJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZd
-p0AJPaxJRUXcLo0waLIJuvvDL8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi
-1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wNUPf6s+xCX6ndbcj0dc97wXImsQEc
-XCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/nADydb47kMgkdTXg0
-eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1erfu
-tGWaIZDgqtCYvDi1czyL+Nw=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEn
-MCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQL
-ExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENo
-YW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYxNDE4WhcNMzcwOTMwMTYxNDE4WjB9
-MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgy
-NzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEgMB4G
-A1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUA
-A4IBDQAwggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0
-Mi+ITaFgCPS3CU6gSS9J1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/s
-QJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8Oby4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpV
-eAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl6DJWk0aJqCWKZQbua795
-B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c8lCrEqWh
-z0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0T
-AQH/BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1i
-ZXJzaWduLm9yZy9jaGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4w
-TcbOX60Qq+UDpfqpFDAOBgNVHQ8BAf8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAH
-MCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBjaGFtYmVyc2lnbi5vcmcwKgYD
-VR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9yZzBbBgNVHSAE
-VDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh
-bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0B
-AQUFAAOCAQEAPDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUM
-bKGKfKX0j//U2K0X1S0E0T9YgOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXi
-ryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJPJ7oKXqJ1/6v/2j1pReQvayZzKWG
-VwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4IBHNfTIzSJRUTN3c
-ecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREest2d/
-AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIESzCCAzOgAwIBAgIJAJigUTEEXRQpMA0GCSqGSIb3DQEBBQUAMHYxCzAJBgNV
-BAYTAkRFMQ8wDQYDVQQIEwZIZXNzZW4xDjAMBgNVBAcTBUZ1bGRhMRAwDgYDVQQK
-EwdEZWJjb25mMRMwEQYDVQQDEwpEZWJjb25mIENBMR8wHQYJKoZIhvcNAQkBFhBq
-b2VyZ0BkZWJpYW4ub3JnMB4XDTA1MTEwNTE3NTUxNFoXDTE1MTEwMzE3NTUxNFow
-djELMAkGA1UEBhMCREUxDzANBgNVBAgTBkhlc3NlbjEOMAwGA1UEBxMFRnVsZGEx
-EDAOBgNVBAoTB0RlYmNvbmYxEzARBgNVBAMTCkRlYmNvbmYgQ0ExHzAdBgkqhkiG
-9w0BCQEWEGpvZXJnQGRlYmlhbi5vcmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQCvbOo0SrIwI5IMlsshH8WF3dHB9r9JlSKhMPaybawa1EyvZspMQ3wa
-F5qxNf3Sj+NElEmjseEqvCZiIIzqwerHu0Qw62cDYCdCd2+Wb5m0bPYB5CGHiyU1
-eNP0je42O0YeXG2BvUujN8AviocVo39X2YwNQ0ryy4OaqYgm2pRlbtT2ESbF+SfV
-Y2iqQj/f8ymF+lHo/pz8tbAqxWcqaSiHFAVQJrdqtFhtoodoNiE3q76zJoUkZTXB
-k60Yc3MJSnatZCpnsSBr/D7zpntl0THrUjjtdRWCjQVhqfhM1yZJV+ApbLdheFh0
-ZWlSxdnp25p0q0XYw/7G92ELyFDfBUUNAgMBAAGjgdswgdgwHQYDVR0OBBYEFMuV
-dFNb4mCWUFbcP5LOtxFLrEVTMIGoBgNVHSMEgaAwgZ2AFMuVdFNb4mCWUFbcP5LO
-txFLrEVToXqkeDB2MQswCQYDVQQGEwJERTEPMA0GA1UECBMGSGVzc2VuMQ4wDAYD
-VQQHEwVGdWxkYTEQMA4GA1UEChMHRGViY29uZjETMBEGA1UEAxMKRGViY29uZiBD
-QTEfMB0GCSqGSIb3DQEJARYQam9lcmdAZGViaWFuLm9yZ4IJAJigUTEEXRQpMAwG
-A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAGZXxHg4mnkvilRIM1EQfGdY
-S5b/WcyF2MYSTeTvK4aIB6VHwpZoZCnDGj2m2D3CkHT0upAD9o0zM1tdsfncLzV+
-mDT/jNmBtYo4QXx5vEPwvEIcgrWjwk7SyaEUhZjtolTkHB7ACl0oD0r71St4iEPR
-qTUCEXk2E47bg1Fz58wNt/yo2+4iqiRjg1XCH4evkQuhpW+dTZnDyFNqwSYZapOE
-TBA+9zBb6xD1KM2DdY7r4GiyYItN0BKLfuWbh9LXGbl1C+f4P11g+m2MPiavIeCe
-1iazG5pcS3KoTLACsYlEX24TINtg4kcuS81XdllcnsV3Kdts0nIqPj6uhTTZD0k=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDvjCCA3ygAwIBAgIFJQaThoEwCwYHKoZIzjgEAwUAMIGFMQswCQYDVQQGEwJG
-UjEPMA0GA1UECBMGRnJhbmNlMQ4wDAYDVQQHEwVQYXJpczEQMA4GA1UEChMHUE0v
-U0dETjEOMAwGA1UECxMFRENTU0kxDjAMBgNVBAMTBUlHQy9BMSMwIQYJKoZIhvcN
-AQkBFhRpZ2NhQHNnZG4ucG0uZ291di5mcjAeFw0wMjEyMTMxNDM5MTVaFw0yMDEw
-MTcxNDM5MTRaMIGFMQswCQYDVQQGEwJGUjEPMA0GA1UECBMGRnJhbmNlMQ4wDAYD
-VQQHEwVQYXJpczEQMA4GA1UEChMHUE0vU0dETjEOMAwGA1UECxMFRENTU0kxDjAM
-BgNVBAMTBUlHQy9BMSMwIQYJKoZIhvcNAQkBFhRpZ2NhQHNnZG4ucG0uZ291di5m
-cjCCAbYwggErBgcqhkjOOAQBMIIBHgKBgQCFkMImdk9zDzJfTO4XPdAAmLbAdWws
-ZiEMZh19RyTo3CyhFqO77OIXrwY6vc1pcc3MgWJ0dgQpAgrDMtmFFxpUu4gmjVsx
-8GpxQC+4VOgLY8Cvmcd/UDzYg07EIRto8BwCpPJ/JfUxwzV2V3N713aAX+cEoKZ/
-s+kgxC6nZCA7oQIVALME/JYjkdW2uKIGngsEPbXAjdhDAoGADh/uqWJx94UBm31c
-9d8ZTBfRGRnmSSRVFDgPWgA69JD4BR5da8tKz+1HjfMhDXljbMH86ixpD5Ka1Z0V
-pRYUPbyAoB37tsmXMJY7kjyD19d5VdaZboUjVvhH6UJy5lpNNNGSvFl4fqkxyvw+
-pq1QV0N5RcvK120hlXdfHUX+YKYDgYQAAoGAQGr7IuKJcYIvJRMjxwl43KxXY2xC
-aoCiM/bv117MfI94aNf1UusGhp7CbYAY9CXuL60P0oPMAajbaTE5Z34AuITeHq3Y
-CNMHwxalip8BHqSSGmGiQsXeK7T+r1rPXsccZ1c5ikGDZ4xn5gUaCyy2rCmb+fOJ
-6VAfCbAbAjmNKwejdzB1MA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgFGMBUG
-A1UdIAQOMAwwCgYIKoF6AXkBAQEwHQYDVR0OBBYEFPkeNRcUf8idzpKblYbLNxs0
-MQhSMB8GA1UdIwQYMBaAFPkeNRcUf8idzpKblYbLNxs0MQhSMAsGByqGSM44BAMF
-AAMvADAsAhRVh+CJA5eVyEYU5AO9Tm7GxX0rmQIUBCqsU5u1WxoZ5lEXicDX5/Ob
-sRQ=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYT
-AkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQ
-TS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG
-9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMB4XDTAyMTIxMzE0MjkyM1oXDTIw
-MTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAM
-BgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEO
-MAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2
-LmZyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaI
-s9z4iPf930Pfeo2aSVz2TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2
-xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCWSo7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4
-u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYyHF2fYPepraX/z9E0+X1b
-F8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNdfrGoRpAx
-Vs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGd
-PDPQtQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNV
-HSAEDjAMMAoGCCqBegF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAx
-NjAfBgNVHSMEGDAWgBSjBS8YYFDCiQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUF
-AAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RKq89toB9RlPhJy3Q2FLwV3duJ
-L92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3QMZsyK10XZZOY
-YLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg
-Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2a
-NjSaTFR+FwNIlQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R
-0982gaEbeC9xs/FZTEYYKKuF0mBWWg==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNV
-BAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4X
-DTA3MDYyOTE1MTMwNVoXDTI3MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQ
-BgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwIQ2VydGlnbmEwggEiMA0GCSqGSIb3
-DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7qXOEm7RFHYeGifBZ4
-QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyHGxny
-gQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbw
-zBfsV1/pogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q
-130yGLMLLGq/jj8UEYkgDncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2
-JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKfIrjxwo1p3Po6WAbfAgMBAAGjgbwwgbkw
-DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQtCRZvgHyUtVF9lo53BEw
-ZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJBgNVBAYT
-AkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzj
-AQ/JSP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG
-9w0BAQUFAAOCAQEAhQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8h
-bV6lUmPOEvjvKtpv6zf+EwLHyzs+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFnc
-fca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1kluPBS1xp81HlDQwY9qcEQCYsuu
-HWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY1gkIl2PlwS6w
-t0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
-WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAw
-PTELMAkGA1UEBhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFz
-cyAyIFByaW1hcnkgQ0EwHhcNOTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9
-MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2VydHBsdXMxGzAZBgNVBAMTEkNsYXNz
-IDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANxQ
-ltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR5aiR
-VhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyL
-kcAbmXuZVg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCd
-EgETjdyAYveVqUSISnFOYFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yas
-H7WLO7dDWWuwJKZtkIvEcupdM5i3y95ee++U8Rs+yskhwcWYAqqi9lt3m/V+llU0
-HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRMECDAGAQH/AgEKMAsGA1Ud
-DwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJYIZIAYb4
-QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMu
-Y29tL0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/
-AN9WM2K191EBkOvDP9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8
-yfFC82x/xXp8HVGIutIKPidd3i1RTtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMR
-FcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+7UCmnYR0ObncHoUW2ikbhiMA
-ybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW//1IMwrh3KWB
-kJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
-l7+ijrRU
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYT
-AlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBD
-QTAeFw0wNjA3MDQxNzIwMDRaFw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJP
-MREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTCC
-ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7IJUqOtdu0KBuqV5Do
-0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHHrfAQ
-UySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5d
-RdY4zTW2ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQ
-OA7+j0xbm0bqQfWwCHTD0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwv
-JoIQ4uNllAoEwF73XVv4EOLQunpL+943AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08C
-AwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAcYwHQYDVR0O
-BBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IBAQA+0hyJ
-LjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecY
-MnQ8SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ
-44gx+FkagQnIl6Z0x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6I
-Jd1hJyMctTEHBDa0GpC9oHRxUIltvBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNw
-i/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7NzTogVZ96edhBiIL5VaZVDADlN
-9u6wWk5JRFRYX0KD
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBM
-MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD
-QTAeFw0wMjA2MTExMDQ2MzlaFw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBM
-MRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBD
-QTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6xwS7TT3zNJc4YPk/E
-jG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdLkKWo
-ePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GI
-ULdtlkIJ89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapu
-Ob7kky/ZR6By6/qmW6/KUz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUg
-AKpoC6EahQGcxEZjgoi2IrHu/qpGWX7PNSzVttpd90gzFFS269lvzs2I1qsb2pY7
-HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEA
-uI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+GXYkHAQa
-TOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTg
-xSvgGrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1q
-CjqTE5s7FCMTY5w/0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5x
-O/fIR/RpbxXyEV6DHpx8Uq79AtoSqFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs
-6GAqm4VKQPNriiTsBhYscw==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYD
-VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0
-IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3
-MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xKTAnBgNVBAMTIENoYW1iZXJz
-IG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEyMjk1MFoXDTM4MDcz
-MTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBj
-dXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIw
-EAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEp
-MCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0G
-CSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW9
-28sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKAXuFixrYp4YFs8r/lfTJq
-VKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorjh40G072Q
-DuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR
-5gN/ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfL
-ZEFHcpOrUMPrCXZkNNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05a
-Sd+pZgvMPMZ4fKecHePOjlO+Bd5gD2vlGts/4+EhySnB8esHnFIbAURRPHsl18Tl
-UlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331lubKgdaX8ZSD6e2wsWsSaR6s
-+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ0wlf2eOKNcx5
-Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
-ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAx
-hduub+84Mxh2EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNV
-HQ4EFgQU+SSsD7K1+HnA+mCIG8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1
-+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpN
-YWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29t
-L2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVy
-ZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAt
-IDIwMDiCCQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRV
-HSAAMCowKAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20w
-DQYJKoZIhvcNAQEFBQADggIBAJASryI1wqM58C7e6bXpeHxIvj99RZJe6dqxGfwW
-PJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH3qLPaYRgM+gQDROpI9CF
-5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbURWpGqOt1
-glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaH
-FoI6M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2
-pSB7+R5KBWIBpih1YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MD
-xvbxrN8y8NmBGuScvfaAFPDRLLmF9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QG
-tjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcKzBIKinmwPQN/aUv0NCB9szTq
-jktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvGnrDQWzilm1De
-fhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
-OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZ
-d0jQ
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJD
-TjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2
-MDcwOTE0WhcNMjcwNDE2MDcwOTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMF
-Q05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwggEiMA0GCSqGSIb3DQEBAQUAA4IB
-DwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzDo+/hn7E7SIX1mlwh
-IhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tizVHa6
-dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZO
-V/kbZKKTVrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrC
-GHn2emU1z5DrvTOTn1OrczvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gN
-v7Sg2Ca+I19zN38m5pIEo3/PIKe38zrKy5nLAgMBAAGjczBxMBEGCWCGSAGG+EIB
-AQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscCwQ7vptU7ETAPBgNVHRMB
-Af8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991SlgrHAsEO
-76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnK
-OOK5Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvH
-ugDnuL8BV8F3RTIMO/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7Hgvi
-yJA/qIYM/PmLXoXLT1tLYhFHxUV8BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fL
-buXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2G8kS1sHNzYDzAgE8yGnLRUhj
-2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5mmxE=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEb
-MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
-GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmlj
-YXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVowezEL
-MAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
-BwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNVBAMM
-GEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
-ADCCAQoCggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQua
-BtDFcCLNSS1UY8y2bmhGC1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe
-3M/vg4aijJRPn2jymJBGhCfHdr/jzDUsi14HZGWCwEiwqJH5YZ92IFCokcdmtet4
-YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszWY19zjNoFmag4qMsXeDZR
-rOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjHYpy+g8cm
-ez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQU
-oBEKIz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
-MAMBAf8wewYDVR0fBHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20v
-QUFBQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29t
-b2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2VzLmNybDANBgkqhkiG9w0BAQUF
-AAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm7l3sAg9g1o1Q
-GE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
-Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2
-G9w84FoVxp7Z8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsi
-l2D4kF501KKaU73yqWjgom7C12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3
-smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCB
-gTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
-A1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNV
-BAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEyMDEwMDAw
-MDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3Jl
-YXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01P
-RE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3
-UcEbVASY06m/weaKXTuH+7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI
-2GqGd0S7WWaXUF601CxwRM/aN5VCaTwwxHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8
-Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV4EajcNxo2f8ESIl33rXp
-+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA1KGzqSX+
-DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5O
-nKVIrLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW
-/zAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6g
-PKA6hjhodHRwOi8vY3JsLmNvbW9kb2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9u
-QXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOCAQEAPpiem/Yb6dc5t3iuHXIY
-SdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CPOGEIqB6BCsAv
-IC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
-RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4
-zJVSk/BwJVmcIGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5dd
-BA6+C4OmF4O5MBKgxTMVBbkN+8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IB
-ZQ==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTEL
-MAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UE
-BxMHU2FsZm9yZDEaMBgGA1UEChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMT
-IkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDgwMzA2MDAw
-MDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0IxGzAZBgNVBAgTEkdy
-ZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMRQ09N
-T0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlv
-biBBdXRob3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSR
-FtSrYpn1PlILBs5BAH+X4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0J
-cfRK9ChQtP6IHG4/bC8vCVlbpVsLM5niwz2J+Wos77LTBumjQjBAMB0GA1UdDgQW
-BBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
-BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VGFAkK+qDm
-fQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdv
-GDeAU/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEb
-MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
-GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRp
-ZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAwMFoXDTI4MTIzMTIzNTk1OVow
-fjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4G
-A1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAiBgNV
-BAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEB
-BQADggEPADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPM
-cm3ye5drswfxdySRXyWP9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3S
-HpR7LZQdqnXXs5jLrLxkU0C8j6ysNstcrbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996
-CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rCoznl2yY4rYsK7hljxxwk
-3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3Vp6ea5EQz
-6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNV
-HQ4EFgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
-EwEB/wQFMAMBAf8wgYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2Rv
-Y2EuY29tL1NlY3VyZUNlcnRpZmljYXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRw
-Oi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlmaWNhdGVTZXJ2aWNlcy5jcmww
-DQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm4J4oqF7Tt/Q0
-5qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
-Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtI
-gKvcnDe4IRRLDXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJ
-aD61JlfutuC23bkpgHl9j6PwpCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDl
-izeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1HRR3B7Hzs/Sk=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEb
-MBkGA1UECAwSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRow
-GAYDVQQKDBFDb21vZG8gQ0EgTGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0
-aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEwMDAwMDBaFw0yODEyMzEyMzU5NTla
-MH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1hbmNoZXN0ZXIxEDAO
-BgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUwIwYD
-VQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0B
-AQEFAAOCAQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWW
-fnJSoBVC21ndZHoa0Lh73TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMt
-TGo87IvDktJTdyR0nAducPy9C1t2ul/y/9c3S0pgePfw+spwtOpZqqPOSC+pw7IL
-fhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6juljatEPmsbS9Is6FARW
-1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsSivnkBbA7
-kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0G
-A1UdDgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYD
-VR0TAQH/BAUwAwEB/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21v
-ZG9jYS5jb20vVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRo
-dHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENlcnRpZmljYXRlU2VydmljZXMu
-Y3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8NtwuleGFTQQuS9/
-HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
-pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxIS
-jBc/lDb+XbDABHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+
-xqFx7D+gIIxmOom0jtTYsU0lR+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/Atyjcn
-dBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O9y5Xt5hwXsjEeLBi
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDkzCCAnugAwIBAgIQFBOWgxRVjOp7Y+X8NId3RDANBgkqhkiG9w0BAQUFADA0
-MRMwEQYDVQQDEwpDb21TaWduIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQG
-EwJJTDAeFw0wNDAzMjQxMTMyMThaFw0yOTAzMTkxNTAyMThaMDQxEzARBgNVBAMT
-CkNvbVNpZ24gQ0ExEDAOBgNVBAoTB0NvbVNpZ24xCzAJBgNVBAYTAklMMIIBIjAN
-BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ORUaSvTx49qROR+WCf4C9DklBKK
-8Rs4OC8fMZwG1Cyn3gsqrhqg455qv588x26i+YtkbDqthVVRVKU4VbirgwTyP2Q2
-98CNQ0NqZtH3FyrV7zb6MBBC11PN+fozc0yz6YQgitZBJzXkOPqUm7h65HkfM/sb
-2CEJKHxNGGleZIp6GZPKfuzzcuc3B1hZKKxC+cX/zT/npfo4sdAMx9lSGlPWgcxC
-ejVb7Us6eva1jsz/D3zkYDaHL63woSV9/9JLEYhwVKZBqGdTUkJe5DSe5L6j7Kpi
-Xd3DTKaCQeQzC6zJMw9kglcq/QytNuEMrkvF7zuZ2SOzW120V+x0cAwqTwIDAQAB
-o4GgMIGdMAwGA1UdEwQFMAMBAf8wPQYDVR0fBDYwNDAyoDCgLoYsaHR0cDovL2Zl
-ZGlyLmNvbXNpZ24uY28uaWwvY3JsL0NvbVNpZ25DQS5jcmwwDgYDVR0PAQH/BAQD
-AgGGMB8GA1UdIwQYMBaAFEsBmz5WGmU2dst7l6qSBe4y5ygxMB0GA1UdDgQWBBRL
-AZs+VhplNnbLe5eqkgXuMucoMTANBgkqhkiG9w0BAQUFAAOCAQEA0Nmlfv4pYEWd
-foPPbrxHbvUanlR2QnG0PFg/LUAlQvaBnPGJEMgOqnhPOAlXsDzACPw1jvFIUY0M
-cXS6hMTXcpuEfDhOZAYnKuGntewImbQKDdSFc8gS4TXt8QUxHXOZDOuWyt3T5oWq
-8Ir7dcHyCTxlZWTzTNity4hp8+SDtwy9F1qWF8pb/627HOkthIDYIb6FUtnUdLlp
-hbpN7Sgy6/lhSuTENh4Z3G+EER+V9YMoGKgzkkMn3V0TBEVPh9VGzT2ouvDzuFYk
-Res3x+F2T3I5GN9+dHLHcy056mDmrRGiVod7w2ia/viMcKjfZTL0pECMocJEAw6U
-AGegcQCCSA==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAw
-PDEbMBkGA1UEAxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWdu
-MQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwx
-GzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBDQTEQMA4GA1UEChMHQ29tU2lnbjEL
-MAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGtWhf
-HZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs49oh
-gHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sW
-v+bznkqH7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ue
-Mv5WJDmyVIRD9YTC2LxBkMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr
-9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d19guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt
-6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUwAwEB/zBEBgNVHR8EPTA7
-MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29tU2lnblNl
-Y3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58
-ADsAj8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkq
-hkiG9w0BAQUFAAOCAQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7p
-iL1DRYHjZiM/EoZNGeQFsOY3wo3aBijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtC
-dsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtpFhpFfTMDZflScZAmlaxMDPWL
-kz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP51qJThRv4zdL
-hfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz
-OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYG
-A1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2Jh
-bCBSb290MB4XDTA2MTIxNTA4MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UE
-ChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBS
-b290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA+Mi8vRRQZhP/8NN5
-7CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW0ozS
-J8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2y
-HLtgwEZLAfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iP
-t3sMpTjr3kfb1V05/Iin89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNz
-FtApD0mpSPCzqrdsxacwOUBdrsTiXSZT8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAY
-XSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/
-MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2MDSgMqAw
-hi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3Js
-MB8GA1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUA
-A4IBAQBW7wojoFROlZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMj
-Wqd8BfP9IjsO0QbE2zZMcwSO5bAi5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUx
-XOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2hO0j9n0Hq0V+09+zv+mKts2o
-omcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+TX3EJIrduPuoc
-A06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
-WL1WMRJOEcgh4LMRkWXbtKaIOM5V
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEc
-MBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2Vj
-IFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENB
-IDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5MjM1OTAwWjBxMQswCQYDVQQGEwJE
-RTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxl
-U2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290
-IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEU
-ha88EOQ5bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhC
-QN/Po7qCWWqSG6wcmtoIKyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1Mjwr
-rFDa1sPeg5TKqAyZMg4ISFZbavva4VhYAUlfckE8FQYBjl2tqriTtM2e66foai1S
-NNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aKSe5TBY8ZTNXeWHmb0moc
-QqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTVjlsB9WoH
-txa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAP
-BgNVHRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOC
-AQEAlGRZrTlk5ynrE/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756Abrsp
-tJh6sTtU6zkXR34ajgv8HzFZMQSyzhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpa
-IzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8rZ7/gFnkm0W09juwzTkZmDLl
-6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4Gdyd1Lx+4ivn+
-xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
-Cm26OWMohpLzGITY+9HPBVZkVw==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBl
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJv
-b3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzExMTEwMDAwMDAwWjBlMQswCQYDVQQG
-EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNl
-cnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwggEi
-MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7c
-JpSIqvTO9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYP
-mDI2dsze3Tyoou9q+yHyUmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+
-wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4
-VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpyoeb6pNnVFzF1roV9Iq4/
-AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whfGHdPAgMB
-AAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQW
-BBRF66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYun
-pyGd823IDzANBgkqhkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRC
-dWKuh+vy1dneVrOfzM4UKLkNl2BcEkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTf
-fwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38FnSbNd67IJKusm7Xi+fT8r87cm
-NW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i8b5QZ7dsvfPx
-H2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
-+o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBh
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBD
-QTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAwMDAwMDBaMGExCzAJBgNVBAYTAlVT
-MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j
-b20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkqhkiG
-9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsB
-CSDMAZOnTjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97
-nh6Vfe63SKMI2tavegw5BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt
-43C/dxC//AH2hdmoRBBYMql1GNXRor5H4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7P
-T19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y7vrTC0LUq7dBMtoM1O/4
-gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQABo2MwYTAO
-BgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbR
-TLtm8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUw
-DQYJKoZIhvcNAQEFBQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/Esr
-hMAtudXH/vTBH1jLuG2cenTnmCmrEbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg
-06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIttep3Sp+dWOIrWcBAI+0tKIJF
-PnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886UAb3LujEV0ls
-YSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
-CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBs
-MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3
-d3cuZGlnaWNlcnQuY29tMSswKQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5j
-ZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAwMFoXDTMxMTExMDAwMDAwMFowbDEL
-MAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZMBcGA1UECxMQd3d3
-LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFuY2Ug
-RVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm
-+9S75S0tMqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTW
-PNt0OKRKzE0lgvdKpVMSOO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEM
-xChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFB
-Ik5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQNAQTXKFx01p8VdteZOE3
-hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUeh10aUAsg
-EsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQF
-MAMBAf8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaA
-FLE+w2kD+L9HAdSYJhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3Nec
-nzyIZgYIVyHbIUf4KmeqvxgydkAQV8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6z
-eM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFpmyPInngiK3BD41VHMWEZ71jF
-hS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkKmNEVX58Svnw2
-Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
-vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep
-+OkuE6N36B9K
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFijCCA3KgAwIBAgIQDHbanJEMTiye/hXQWJM8TDANBgkqhkiG9w0BAQUFADBf
-MQswCQYDVQQGEwJOTDESMBAGA1UEChMJRGlnaU5vdGFyMRowGAYDVQQDExFEaWdp
-Tm90YXIgUm9vdCBDQTEgMB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmww
-HhcNMDcwNTE2MTcxOTM2WhcNMjUwMzMxMTgxOTIxWjBfMQswCQYDVQQGEwJOTDES
-MBAGA1UEChMJRGlnaU5vdGFyMRowGAYDVQQDExFEaWdpTm90YXIgUm9vdCBDQTEg
-MB4GCSqGSIb3DQEJARYRaW5mb0BkaWdpbm90YXIubmwwggIiMA0GCSqGSIb3DQEB
-AQUAA4ICDwAwggIKAoICAQCssFjBAL3YIQgLK5r+blYwBZ8bd5AQQVzDDYcRd46B
-8cp86Yxq7Th0Nbva3/m7wAk3tJZzgX0zGpg595NvlX89ubF1h7pRSOiLcD6VBMXY
-tsMW2YiwsYcdcNqGtA8Ui3rPENF0NqISe3eGSnnme98CEWilToauNFibJBN4ViIl
-HgGLS1Fx+4LMWZZpiFpoU8W5DQI3y0u8ZkqQfioLBQftFl9VkHXYRskbg+IIvvEj
-zJkd1ioPgyAVWCeCLvriIsJJsbkBgWqdbZ1Ad2h2TiEqbYRAhU52mXyC8/O3AlnU
-JgEbjt+tUwbRrhjd4rI6y9eIOI6sWym5GdOY+RgDz0iChmYLG2kPyes4iHomGgVM
-ktck1JbyrFIto0fVUvY//s6EBnCmqj6i8rZWNBhXouSBbefK8GrTx5FrAoNBfBXv
-a5pkXuPQPOWx63tdhvvL5ndJzaNl3Pe5nLjkC1+Tz8wwGjIczhxjlaX56uF0i57p
-K6kwe6AYHw4YC+VbqdPRbB4HZ4+RS6mKvNJmqpMBiLKR+jFc1abBUggJzQpjotMi
-puih2TkGl/VujQKQjBR7P4DNG5y6xFhyI6+2Vp/GekIzKQc/gsnmHwUNzUwoNovT
-yD4cxojvXu6JZOkd69qJfjKmadHdzIif0dDJZiHcBmfFlHqabWJMfczgZICynkeO
-owIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
-HQ4EFgQUiGi/4I41xDs4a2L3KDuEgcgM100wDQYJKoZIhvcNAQEFBQADggIBADsC
-jcs8MOhuoK3yc7NfniUTBAXT9uOLuwt5zlPe5JbF0a9zvNXD0EBVfEB/zRtfCdXy
-fJ9oHbtdzno5wozWmHvFg1Wo1X1AyuAe94leY12hE8JdiraKfADzI8PthV9xdvBo
-Y6pFITlIYXg23PFDk9Qlx/KAZeFTAnVR/Ho67zerhChXDNjU1JlWbOOi/lmEtDHo
-M/hklJRRl6s5xUvt2t2AC298KQ3EjopyDedTFLJgQT2EkTFoPSdE2+Xe9PpjRchM
-Ppj1P0G6Tss3DbpmmPHdy59c91Q2gmssvBNhl0L4eLvMyKKfyvBovWsdst+Nbwed
-2o5nx0ceyrm/KkKRt2NTZvFCo+H0Wk1Ya7XkpDOtXHAd3ODy63MUkZoDweoAZbwH
-/M8SESIsrqC9OuCiKthZ6SnTGDWkrBFfGbW1G/8iSlzGeuQX7yCpp/Q/rYqnmgQl
-nQ7KN+ZQ/YxCKQSa7LnPS3K94gg2ryMvYuXKAdNw23yCIywWMQzGNgeQerEfZ1jE
-O1hZibCMjFCz2IbLaKPECudpSyDOwR5WS5WpI2jYMNjD67BVUc3l/Su49bsRn1NU
-9jQZjHkJNsphFyUXC4KYcwx3dMPVDceoEkzHp1RxRy4sGn3J4ys7SN4nhKdjNrN9
-j6BkOSQNPXuHr2ZcdBtLc7LljPCGmbjlxd+Ewbfr
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV
-UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL
-EwhEU1RDQSBFMTAeFw05ODEyMTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJ
-BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x
-ETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQCg
-bIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJENySZ
-j9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlV
-Sn5JTe2io74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCG
-SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx
-JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI
-RFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMTAxODEw
-MjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFGp5
-fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i
-+DAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG
-SIb3DQEBBQUAA4GBACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lN
-QseSJqBcNJo4cvj9axY+IO6CizEqkzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+
-gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4RbyhkwS7hp86W0N6w4pl
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJV
-UzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQL
-EwhEU1RDQSBFMjAeFw05ODEyMDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJ
-BgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4x
-ETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQC/
-k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGODVvso
-LeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3o
-TQPMx7JSxhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCG
-SAGG+EIBAQQEAwIABzBoBgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMx
-JDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0dXJlIFRydXN0IENvLjERMA8GA1UECxMI
-RFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQwIoAPMTk5ODEyMDkxOTE3
-MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQYMBaAFB6C
-TShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5
-WzAMBgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqG
-SIb3DQEBBQUAA4GBAEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHR
-xdf0CiUPPXiBng+xZ8SQTGPdXqfiup/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVL
-B3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1mPnHfxsb1gYgAlihw6ID
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBb
-MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3Qx
-ETAPBgNVBAsTCERTVCBBQ0VTMRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0w
-MzExMjAyMTE5NThaFw0xNzExMjAyMTE5NThaMFsxCzAJBgNVBAYTAlVTMSAwHgYD
-VQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UECxMIRFNUIEFDRVMx
-FzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
-MIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPu
-ktKe1jzIDZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7
-gLFViYsx+tC3dr5BPTCapCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZH
-fAjIgrrep4c9oW24MFbCswKBXy314powGCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4a
-ahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPyMjwmR/onJALJfh1biEIT
-ajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1UdEwEB/wQF
-MAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rk
-c3QuY29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjto
-dHRwOi8vd3d3LnRydXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMt
-aW5kZXguaHRtbDAdBgNVHQ4EFgQUCXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZI
-hvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V25FYrnJmQ6AgwbN99Pe7lv7Uk
-QIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6tFr8hlxCBPeP/
-h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq
-nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpR
-rscL9yuwNwXsvFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf2
-9w4LTJxoeHtxMcfrHuBnQfO3oKfN5XozNmr6mis=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/
-MSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT
-DkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow
-PzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD
-Ew5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
-AN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O
-rz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq
-OLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b
-xiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw
-7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD
-aeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV
-HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG
-SIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69
-ikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr
-AvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz
-R8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5
-JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo
-Ob8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNV
-BAMML0VCRyBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx
-c8SxMTcwNQYDVQQKDC5FQkcgQmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXpt
-ZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAeFw0wNjA4MTcwMDIxMDlaFw0xNjA4
-MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25payBTZXJ0aWZpa2Eg
-SGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2ltIFRl
-a25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIi
-MA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h
-4fuXd7hxlugTlkaDT7byX3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAk
-tiHq6yOU/im/+4mRDGSaBUorzAzu8T2bgmmkTPiab+ci2hC6X5L8GCcKqKpE+i4s
-tPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfreYteIAbTdgtsApWjluTL
-dlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZTqNGFav4
-c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8Um
-TDGyY5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z
-+kI2sSXFCjEmN1ZnuqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0O
-Lna9XvNRiYuoP1Vzv9s6xiQFlpJIqkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMW
-OeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vmExH8nYQKE3vwO9D8owrXieqW
-fo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0Nokb+Clsi7n2
-l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
-/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgw
-FoAU587GT/wWZ5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+
-8ygjdsZs93/mQJ7ANtyVDR2tFcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI
-6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgmzJNSroIBk5DKd8pNSe/iWtkqvTDO
-TLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64kXPBfrAowzIpAoHME
-wfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqTbCmY
-Iai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJn
-xk1Gj7sURT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4Q
-DgZxGhBM/nV+/x5XOULK1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9q
-Kd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11t
-hie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQY9iJSrSq3RZj9W6+YKH4
-7ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9AahH3eU7
-QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1
-MQswCQYDVQQGEwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxp
-Z2kgQS5TLjE8MDoGA1UEAxMzZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZp
-a2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3MDEwNDExMzI0OFoXDTE3MDEwNDEx
-MzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0cm9uaWsgQmlsZ2kg
-R3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9uaWsg
-U2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQAD
-ggEPADCCAQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdU
-MZTe1RK6UxYC6lhj71vY8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlT
-L/jDj/6z/P2douNffb7tC+Bg62nsM+3YjfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H
-5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAIJjjcJRFHLfO6IxClv7wC
-90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk9Ok0oSy1
-c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/
-BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoE
-VtstxNulMA0GCSqGSIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLP
-qk/CaOv/gKlR6D1id4k9CnU58W5dF4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S
-/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwqD2fK/A+JYZ1lpTzlvBNbCNvj
-/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4Vwpm+Vganf2X
-KWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq
-fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML
-RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp
-bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5
-IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp
-ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy
-MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3
-LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp
-YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG
-A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq
-K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe
-sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX
-MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT
-XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/
-HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH
-4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA
-vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G
-CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA
-WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo
-oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ
-h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18
-f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN
-B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy
-vUxFnmG6v4SBkgPR0ml8xQ==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMC
-VVMxFDASBgNVBAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5u
-ZXQvQ1BTIGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMc
-KGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDE6MDgGA1UEAxMxRW50cnVzdC5u
-ZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw05OTA1
-MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIGA1UE
-ChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5j
-b3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
-bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUg
-U2VydmVyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUA
-A4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQaO2f55M28Qpku0f1BBc/
-I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5gXpa0zf3
-wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OC
-AdcwggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHb
-oIHYpIHVMIHSMQswCQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5
-BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1p
-dHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1pdGVk
-MTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRp
-b24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
-dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0
-MFqBDzIwMTkwNTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8Bdi
-E1U9s/8KAGv7UISX8+1i0BowHQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAa
-MAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EABAwwChsEVjQuMAMCBJAwDQYJKoZI
-hvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyNEwr75Ji174z4xRAN
-95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9n9cd
-2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMC
-VVMxFjAUBgNVBAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0
-Lm5ldC9DUFMgaXMgaW5jb3Jwb3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMW
-KGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsGA1UEAxMkRW50cnVzdCBSb290IENl
-cnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0MloXDTI2MTEyNzIw
-NTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMuMTkw
-NwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSBy
-ZWZlcmVuY2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNV
-BAMTJEVudHJ1c3QgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJ
-KoZIhvcNAQEBBQADggEPADCCAQoCggEBALaVtkNC+sZtKm9I35RMOVcF7sN5EUFo
-Nu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYszA9u3g3s+IIRe7bJWKKf4
-4LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOwwCj0Yzfv9
-KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGI
-rb68j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi
-94DkZfs0Nw4pgHBNrziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOB
-sDCBrTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAi
-gA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1MzQyWjAfBgNVHSMEGDAWgBRo
-kORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DHhmak8fdLQ/uE
-vW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
-A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9t
-O1KzKtvn1ISMY/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6Zua
-AGAT/3B+XxFNSRuzFVJ7yVTav52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP
-9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTSW3iDVuycNsMm4hH2Z0kdkquM++v/
-eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0tHuu2guQOHXvgR1m
-0vdXcDazv/wor3ElhVsT/h5/WrQ8
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBe
-MQswCQYDVQQGEwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0
-ZC4xKjAoBgNVBAsMIWVQS0kgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
-Fw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMxMjdaMF4xCzAJBgNVBAYTAlRXMSMw
-IQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEqMCgGA1UECwwhZVBL
-SSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0BAQEF
-AAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAH
-SyZbCUNsIZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAh
-ijHyl3SJCRImHJ7K2RKilTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3X
-DZoTM1PRYfl61dd4s5oz9wCGzh1NlDivqOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1
-TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX12ruOzjjK9SXDrkb5wdJ
-fzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0OWQqraffA
-sgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uU
-WH1+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLS
-nT0IFaUQAS2zMnaolQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pH
-dmX2Os+PYhcZewoozRrSgx4hxyy/vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJip
-NiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXiZo1jDiVN1Rmy5nk3pyKdVDEC
-AwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/QkqiMAwGA1UdEwQF
-MAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
-ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGB
-uvl2ICO1J2B01GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6Yl
-PwZpVnPDimZI+ymBV3QGypzqKOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkP
-JXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdVxrsStZf0X4OFunHB2WyBEXYKCrC/
-gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEPNXubrjlpC2JgQCA2
-j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+rGNm6
-5ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUB
-o2M3IUxExJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS
-/jQ6fbjpKdx2qcgw+BRxgMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2z
-Gp1iro2C6pSe3VkQw63d4k3jMdXH7OjysP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTE
-W9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmODBCEIZ43ygknQW/2xzQ+D
-hNQ+IIX3Sj0rnP0qCglN6oH4EZw=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
-UzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2Vy
-dGlmaWNhdGUgQXV0aG9yaXR5MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1
-MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0VxdWlmYXgxLTArBgNVBAsTJEVx
-dWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPRfM6f
-BeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+A
-cJkVV5MW8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kC
-AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQ
-MA4GA1UEChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlm
-aWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTgw
-ODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvSspXXR9gj
-IBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQF
-MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
-A4GBAFjOKer89961zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y
-7qj/WsjTVbJmcVfewCHrPSqnI0kBBIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh
-1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee9570+sB3c4
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEc
-MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBT
-ZWN1cmUgZUJ1c2luZXNzIENBLTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQw
-MDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5j
-LjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENBLTEwgZ8wDQYJ
-KoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ1MRo
-RvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBu
-WqDZQu4aIZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKw
-Env+j6YDAgMBAAGjZjBkMBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTAD
-AQH/MB8GA1UdIwQYMBaAFEp4MlIR21kWNl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRK
-eDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQFAAOBgQB1W6ibAxHm6VZM
-zfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5lSE/9dR+
-WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN
-/Bf+KpYrtWKmpj29f5JZzVoqgrI3eQ==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJV
-UzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2Vj
-dXJlIGVCdXNpbmVzcyBDQS0yMB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0
-NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDkVxdWlmYXggU2VjdXJlMSYwJAYD
-VQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn2Z0G
-vxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/
-BPO3QSQ5BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0C
-AwEAAaOCAQkwggEFMHAGA1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEX
-MBUGA1UEChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJl
-IGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoGA1UdEAQTMBGBDzIwMTkw
-NjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9euSBIplBq
-y/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQF
-MAMBAf8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUA
-A4GBAAyGgq3oThr1jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy
-0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1
-E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUmV+GRMOrN
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEc
-MBoGA1UEChMTRXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBT
-ZWN1cmUgR2xvYmFsIGVCdXNpbmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIw
-MDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMxHDAaBgNVBAoTE0VxdWlmYXggU2Vj
-dXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEdsb2JhbCBlQnVzaW5l
-c3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRVPEnC
-UdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc
-58O/gGzNqfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/
-o5brhTMhHD4ePmBudpxnhcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAH
-MA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUvqigdHJQa0S3ySPY+6j/s1dr
-aGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hsMA0GCSqGSIb3DQEBBAUA
-A4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okENI7SS+RkA
-Z70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv
-8qIYNMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMx
-IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1
-dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
-MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w
-HhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTELMAkGA1UEBhMCRVMx
-IjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1
-dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
-MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20w
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5u
-Cp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5Vj1H5WuretXDE7aTt/6MNbg9kUDGvASdY
-rv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJHlShbz++AbOCQl4oBPB3z
-hxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf3H5idPay
-BQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcL
-iam8NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcb
-AgMBAAGjgZ8wgZwwKgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lv
-bmFsLmNvbTASBgNVHRMBAf8ECDAGAQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0
-MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4E
-FgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQADggEBAEdz/o0n
-VPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq
-u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36m
-hoEyIwOdyPdfwUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzfl
-ZKG+TQyTmAyX9odtsz/ny4Cm7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBp
-QWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YGVM+h4k0460tQtcsm9MracEpqoeJ5
-quGnM/b9Sh/22WA=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEW
-MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFs
-IENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQG
-EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3Qg
-R2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDvPE1A
-PRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/NTL8
-Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hL
-TytCOb1kLUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL
-5mkWRxHCJ1kDs6ZgwiFAVvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7
-S4wMcoKK+xfNAGw6EzywhIdLFnopsk/bHdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe
-2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
-FHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNHK266ZUap
-EBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6td
-EPx7srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv
-/NgdRN3ggX+d6YvhZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywN
-A0ZF66D0f0hExghAzN4bcLUprbqLOzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0
-abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkCx1YAzUm5s2x7UwQa4qjJqhIF
-I8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqFH4z1Ir+rzoPz
-4iIprn2DQKi6bA==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVT
-MRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9i
-YWwgQ0EwHhcNMDIwNTIxMDQwMDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQG
-EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEbMBkGA1UEAxMSR2VvVHJ1c3Qg
-R2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2swYYzD9
-9BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjoBbdq
-fnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDv
-iS2Aelet8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU
-1XupGc1V3sjs0l44U+VcT4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+
-bw8HHa8sHo9gOeL6NlMTOdReJivbPagUvTLrGAMoUgRx5aszPeE4uwc2hGKceeoW
-MPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBTA
-ephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVkDBF9qn1l
-uMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKIn
-Z57QzxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfS
-tQWVYrmm3ok9Nns4d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcF
-PseKUgzbFbS9bZvlxrFUaKnjaZC2mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Un
-hw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6pXE0zX5IJL4hmXXeXxx12E6nV
-5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvmMw==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDEL
-MAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChj
-KSAyMDA3IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2
-MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
-eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1OVowgZgxCzAJBgNV
-BAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykgMjAw
-NyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNV
-BAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH
-MjB2MBAGByqGSM49AgEGBSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcL
-So17VDs6bl8VAsBQps8lL33KSLjHUGMcKiEIfJo22Av+0SbFWDEwKCXzXV2juLal
-tJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAO
-BgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+EVXVMAoG
-CCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGT
-qQ7mndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBucz
-rD6ogRLQy7rQkgu2npaqBA+K
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCB
-mDELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsT
-MChjKSAyMDA4IEdlb1RydXN0IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
-eTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhv
-cml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIzNTk1OVowgZgxCzAJ
-BgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
-MjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0
-BgNVBAMTLUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz
-+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5jK/BGvESyiaHAKAxJcCGVn2TAppMSAmUm
-hsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdEc5IiaacDiGydY8hS2pgn
-5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3CIShwiP/W
-JmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exAL
-DmKudlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZC
-huOl1UcCAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYw
-HQYDVR0OBBYEFMR5yo6hTgMdHNxr2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IB
-AQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9cr5HqQ6XErhK8WTTOd8lNNTB
-zU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbEAp7aDHdlDkQN
-kv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
-AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUH
-SJsMC8tJP33st/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2G
-spki4cErx5z481+oghLrGREt
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBY
-MQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMo
-R2VvVHJ1c3QgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjEx
-MjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
-Ew1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQcmltYXJ5IENlcnRp
-ZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
-AQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9
-AWbK7hWNb6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjA
-ZIVcFU2Ix7e64HXprQU9nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE0
-7e9GceBrAqg1cmuXm2bgyxx5X9gaBGgeRwLmnWDiNpcB3841kt++Z8dtd1k7j53W
-kBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGttm/81w7a4DSwDRp35+MI
-mO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4G
-A1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJ
-KoZIhvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ1
-6CePbJC/kRYkRj5KTs4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl
-4b7UVXGYNTq+k+qurUKykG/g/CFNNWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6K
-oKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHaFloxt/m0cYASSJlyc1pZU8Fj
-UjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG1riR/aYNKxoU
-AT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEW
-MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVy
-c2FsIENBIDIwHhcNMDQwMzA0MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYD
-VQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1
-c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
-AQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0DE81
-WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUG
-FF+3Qs17j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdq
-XbboW0W63MOhBW9Wjo8QJqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxL
-se4YuU6W3Nx2/zu+z18DwPw76L5GG//aQMJS9/7jOvdqdzXQ2o3rXhhqMcceujwb
-KNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2WP0+GfPtDCapkzj4T8Fd
-IgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP20gaXT73
-y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRt
-hAAnZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgoc
-QIgfksILAAX/8sgCSqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4
-Lt1ZrtmhN79UNdxzMk+MBB4zsslG8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNV
-HRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAfBgNV
-HSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8EBAMCAYYwDQYJ
-KoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
-dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQ
-L1EuxBRa3ugZ4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgr
-Fg5fNuH8KrUwJM/gYwx7WBr+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSo
-ag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpqA1Ihn0CoZ1Dy81of398j9tx4TuaY
-T1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpgY+RdM4kX2TGq2tbz
-GDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiPpm8m
-1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJV
-OCiNUW7dFGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH
-6aLcr34YEoP9VhdBLtUpgn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwX
-QMAJKOSLakhT2+zNVVXxxvjpoixMptEmX36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEW
-MBQGA1UEChMNR2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVy
-c2FsIENBMB4XDTA0MDMwNDA1MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UE
-BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xHjAcBgNVBAMTFUdlb1RydXN0
-IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKYV
-VaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9tJPi8
-cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTT
-QjOgNB0eRXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFh
-F7em6fgemdtzbvQKoiFs7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2v
-c7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d8Lsrlh/eezJS/R27tQahsiFepdaVaH/w
-mZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7VqnJNk22CDtucvc+081xd
-VHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3CgaRr0BHdCX
-teGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZ
-f9hBZ3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfRe
-Bi9Fi1jUIxaS5BZuKGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+
-nhutxx9z3SxPGWX9f5NAEC7S8O08ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB
-/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0XG0D08DYj3rWMB8GA1UdIwQY
-MBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG
-9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
-aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fX
-IwjhmF7DWgh2qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzyn
-ANXH/KttgCJwpQzgXQQpAvvLoJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0z
-uzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsKxr2EoyNB3tZ3b4XUhRxQ4K5RirqN
-Pnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxFKyDuSN/n3QmOGKja
-QI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2DFKW
-koRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9
-ER/frslKxfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQt
-DF4JbAiXfKM9fJP/P6EUp8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/Sfuvm
-bJxPgWp6ZKy7PtXny3YuxadIwVyQD8vIP/rmMuGNG2+k5o7Y+SlIis5z/iw=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYD
-VQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0
-IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3
-MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
-aGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMxNDBaFw0zODA3MzEx
-MjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUgY3Vy
-cmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAG
-A1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAl
-BgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZI
-hvcNAQEBBQADggIPADCCAgoCggIBAMDfVtPkOpt2RbQT2//BthmLN0EYlVJH6xed
-KYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXfXjaOcNFccUMd2drvXNL7
-G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0ZJJ0YPP2
-zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4
-ddPB/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyG
-HoiMvvKRhI9lNNgATH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2
-Id3UwD2ln58fQ1DJu7xsepeY7s2MH/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3V
-yJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfeOx2YItaswTXbo6Al/3K1dh3e
-beksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSFHTynyQbehP9r
-6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
-wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsog
-zCtLkykPAgMBAAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQW
-BBS5CcqcHtvTbDprru1U8VuTBjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDpr
-ru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UEBhMCRVUxQzBBBgNVBAcTOk1hZHJp
-ZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJmaXJtYS5jb20vYWRk
-cmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJmaXJt
-YSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiC
-CQDJzdPp1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCow
-KAYIKwYBBQUHAgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZI
-hvcNAQEFBQADggIBAICIf3DekijZBZRG/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZ
-UohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6ReAJ3spED8IXDneRRXoz
-X1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/sdZ7LoR/x
-fxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVz
-a2Mg9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yyd
-Yhz2rXzdpjEetrHHfoUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMd
-SqlapskD7+3056huirRXhOukP9DuqqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9O
-AP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETrP3iZ8ntxPjzxmKfFGBI/5rso
-M0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVqc5iJWzouE4ge
-v8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
-09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG
-A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv
-b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw
-MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i
-YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT
-aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ
-jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp
-xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp
-1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG
-snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ
-U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8
-9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E
-BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B
-AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz
-yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE
-38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP
-AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad
-DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME
-HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4G
-A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNp
-Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1
-MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMjETMBEG
-A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
-hvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6ErPL
-v4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8
-eoLrvozps6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklq
-tTleiDTsvHgMCJiEbKjNS7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzd
-C9XZzPnqJworc5HGnRusyMvo4KD0L5CLTfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pa
-zq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6CygPCm48CAwEAAaOBnDCB
-mTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUm+IH
-V2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5n
-bG9iYWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG
-3lm0mi3f3BmGLjANBgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4Gs
-J0/WwbgcQ3izDJr86iw8bmEbTUsp9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO
-291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu01yiPqFbQfXf5WRDLenVOavS
-ot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG79G+dwfCMNYxd
-AfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
-TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4G
-A1UECxMXR2xvYmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNp
-Z24xEzARBgNVBAMTCkdsb2JhbFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4
-MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxTaWduIFJvb3QgQ0EgLSBSMzETMBEG
-A1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2lnbjCCASIwDQYJKoZI
-hvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWtiHL8
-RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsT
-gHeMCOFJ0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmm
-KPZpO/bLyCiR5Z2KYVc3rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zd
-QQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjlOCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZ
-XriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2xmmFghcCAwEAAaNCMEAw
-DgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFI/wS3+o
-LkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZU
-RUm7lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMp
-jjM5RcOO5LlXbKr8EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK
-6fBdRoyV3XpYKBovHd7NADdBj+1EbddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQX
-mcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18YIvDQVETI53O9zJrlAGomecs
-Mx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7rkpeDMdmztcpH
-WD9f
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
-MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
-YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
-MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
-ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
-MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
-ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
-PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
-wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
-EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
-avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
-YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
-sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
-/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
-IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
-YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
-ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
-OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
-TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
-HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
-dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
-ReYNnyicsbkqWletNw+vHX/bvZ8=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYD
-VQQKEw9HVEUgQ29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNv
-bHV0aW9ucywgSW5jLjEjMCEGA1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJv
-b3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEzMjM1OTAwWjB1MQswCQYDVQQGEwJV
-UzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQLEx5HVEUgQ3liZXJU
-cnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0IEds
-b2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrH
-iM3dFw4usJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTS
-r41tiGeA5u2ylc9yMcqlHHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X4
-04Wqk2kmhXBIgD8SFcd5tB8FLztimQIDAQABMA0GCSqGSIb3DQEBBAUAA4GBAG3r
-GwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMWM4ETCJ57NE7fQMh017l9
-3PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OFNMQkpw0P
-lZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsx
-FjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3Qg
-Um9vdCBDQSAxMB4XDTAzMDUxNTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkG
-A1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdr
-b25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
-AQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1ApzQ
-jVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEn
-PzlTCeqrauh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjh
-ZY4bXSNmO7ilMlHIhqqhqZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9
-nnV0ttgCXjqQesBCNnLsak3c78QA3xMYV18meMjWCnl3v/evt3a5pQuEF10Q6m/h
-q5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNVHRMBAf8ECDAGAQH/AgED
-MA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7ih9legYsC
-mEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI3
-7piol7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clB
-oiMBdDhViw+5LmeiIAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJs
-EhTkYY2sEJCehFC78JZvRZ+K88psT/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpO
-fMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilTc4afU9hDDl3WY4JxHYB0yvbi
-AmvZWg==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYT
-AkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQ
-TS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG
-9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMB4XDTAyMTIxMzE0MjkyM1oXDTIw
-MTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQIEwZGcmFuY2UxDjAM
-BgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NTSTEO
-MAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2
-LmZyMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaI
-s9z4iPf930Pfeo2aSVz2TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2
-xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCWSo7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4
-u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYyHF2fYPepraX/z9E0+X1b
-F8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNdfrGoRpAx
-Vs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGd
-PDPQtQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNV
-HSAEDjAMMAoGCCqBegF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAx
-NjAfBgNVHSMEGDAWgBSjBS8YYFDCiQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUF
-AAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RKq89toB9RlPhJy3Q2FLwV3duJ
-L92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3QMZsyK10XZZOY
-YLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg
-Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2a
-NjSaTFR+FwNIlQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R
-0982gaEbeC9xs/FZTEYYKKuF0mBWWg==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4
-MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6
-ZW5wZS5jb20wHhcNMDcxMjEzMTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYD
-VQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5j
-b20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ03rKDx6sp4boFmVq
-scIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAKClaO
-xdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6H
-LmYRY2xU+zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFX
-uaOKmMPsOzTFlUFpfnXCPCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQD
-yCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxTOTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+
-JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbKF7jJeodWLBoBHmy+E60Q
-rLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK0GqfvEyN
-BjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8L
-hij+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIB
-QFqNeb+Lz0vPqhbBleStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+
-HMh3/1uaD7euBUbl8agW7EekFwIDAQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2lu
-Zm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+SVpFTlBFIFMuQS4gLSBDSUYg
-QTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBGNjIgUzgxQzBB
-BgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
-MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
-AQYwHQYDVR0OBBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUA
-A4ICAQB4pgwWSp9MiDrAyw6lFn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWb
-laQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbgakEyrkgPH7UIBzg/YsfqikuFgba56
-awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8qhT/AQKM6WfxZSzwo
-JNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Csg1lw
-LDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCT
-VyvehQP5aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGk
-LhObNA5me0mrZJfQRsN5nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJb
-UjWumDqtujWTI6cfSN01RpiyEGjkpTHCClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/
-QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZoQ0iy2+tzJOeRf1SktoA+
-naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1ZWrOZyGls
-QyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcN
-AQkBFglwa2lAc2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZp
-dHNlZXJpbWlza2Vza3VzMRAwDgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMw
-MVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMQsw
-CQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEQ
-MA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
-AIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOB
-SvZiF3tfTQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkz
-ABpTpyHhOEvWgxutr2TC+Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvH
-LCu3GFH+4Hv2qEivbDtPL+/40UceJlfwUR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMP
-PbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDaTpxt4brNj3pssAki14sL
-2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQFMAMBAf8w
-ggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwIC
-MIHDHoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDk
-AGwAagBhAHMAdABhAHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0
-AHMAZQBlAHIAaQBtAGkAcwBrAGUAcwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABz
-AGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABrAGkAbgBuAGkAdABhAG0AaQBz
-AGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nwcy8wKwYDVR0f
-BCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE
-FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcY
-P2/v6X2+MA4GA1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOi
-CfP+JmeaUOTDBS8rNXiRTHyoERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+g
-kcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyLabVAyJRld/JXIWY7zoVAtjNjGr95
-HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678IIbsSt4beDI3poHS
-na9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkhMp6q
-qIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0Z
-TbvGRNs2yyqcjg==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYD
-VQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0
-ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0G
-CSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTAeFw0wOTA2MTYxMTMwMThaFw0y
-OTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UEBwwIQnVkYXBlc3Qx
-FjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUtU3pp
-Z25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
-dTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvP
-kd6mJviZpWNwrZuuyjNAfW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tc
-cbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG0IMZfcChEhyVbUr02MelTTMuhTlAdX4U
-fIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKApxn1ntxVUwOXewdI/5n7
-N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm1HxdrtbC
-xkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1
-+rUCAwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
-A1UdDgQWBBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPM
-Pcu1SCOhGnqmKrs0aDAbBgNVHREEFDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqG
-SIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0olZMEyL/azXm4Q5DwpL7v8u8h
-mLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfXI/OMn74dseGk
-ddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
-tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c
-2Pm2G2JwCz02yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5t
-HMN1Rq41Bab2XD0h7lbwyYIiLXpUq3DDfSJlgnCW
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAw
-cjELMAkGA1UEBhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNy
-b3NlYyBMdGQuMRQwEgYDVQQLEwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9z
-ZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0MDYxMjI4NDRaFw0xNzA0MDYxMjI4
-NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEWMBQGA1UEChMN
-TWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMTGU1p
-Y3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
-ggEKAoIBAQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2u
-uO/TEdyB5s87lozWbxXGd36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+
-LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/NoqdNAoI/gqyFxuEPkEeZlApxcpMqyabA
-vjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjcQR/Ji3HWVBTji1R4P770
-Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJPqW+jqpx
-62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcB
-AQRbMFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3Aw
-LQYIKwYBBQUHMAKGIWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAP
-BgNVHRMBAf8EBTADAQH/MIIBcwYDVR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIB
-AQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3LmUtc3ppZ25vLmh1L1NaU1ov
-MIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0AdAB2AOEAbgB5
-ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn
-AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABT
-AHoAbwBsAGcA4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABh
-ACAAcwB6AGUAcgBpAG4AdAAgAGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABo
-AHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMAegBpAGcAbgBvAC4AaAB1AC8AUwBa
-AFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6Ly93d3cuZS1zemln
-bm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NOPU1p
-Y3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxP
-PU1pY3Jvc2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZv
-Y2F0aW9uTGlzdDtiaW5hcnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuB
-EGluZm9AZS1zemlnbm8uaHWkdzB1MSMwIQYDVQQDDBpNaWNyb3NlYyBlLVN6aWdu
-w7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhTWjEWMBQGA1UEChMNTWlj
-cm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhVMIGsBgNV
-HSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJI
-VTERMA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDAS
-BgNVBAsTC2UtU3ppZ25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBS
-b290IENBghEAzLjnv04pGv2i3GalHCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS
-8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMTnGZjWS7KXHAM/IO8VbH0jgds
-ZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FEaGAHQzAxQmHl
-7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a
-86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfR
-hUZLphK3dehKyVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/
-MPMMNz7UwiiAc7EBt51alhQBS6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQG
-EwJIVTERMA8GA1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3
-MDUGA1UECwwuVGFuw7pzw610dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNl
-cnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBBcmFueSAoQ2xhc3MgR29sZCkgRsWR
-dGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgxMjA2MTUwODIxWjCB
-pzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxOZXRM
-b2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlm
-aWNhdGlvbiBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNz
-IEdvbGQpIEbFkXRhbsO6c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
-MIIBCgKCAQEAxCRec75LbRTDofTjl5Bu0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrT
-lF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw/HpYzY6b7cNGbIRwXdrz
-AZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAkH3B5r9s5
-VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRG
-ILdwfzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2
-BJtr+UBdADTHLpl1neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAG
-AQH/AgEEMA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2M
-U9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwWqZw8UQCgwBEIBaeZ5m8BiFRh
-bvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTtaYtOUZcTh5m2C
-+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
-bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2F
-uLjbvrW5KfnaNwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2
-XjG4Kvte9nHfRCaexOYNkbQudZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUx
-ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0
-b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQD
-EylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikgVGFudXNpdHZhbnlraWFkbzAeFw05
-OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYDVQQGEwJIVTERMA8G
-A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh
-Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5l
-dExvY2sgVXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqG
-SIb3DQEBAQUAA4GNADCBiQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xK
-gZjupNTKihe5In+DCnVMm8Bp2GQ5o+2So/1bXHQawEfKOml2mrriRBf8TKPV/riX
-iK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr1nGTLbO/CVRY7QbrqHvc
-Q7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8E
-BAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1G
-SUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFu
-b3MgU3pvbGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBh
-bGFwamFuIGtlc3p1bHQuIEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExv
-Y2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGln
-aXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0
-IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh
-c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGph
-biBhIGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJo
-ZXRvIGF6IGVsbGVub3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBP
-UlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmlj
-YXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBo
-dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNA
-bmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06
-sPgzTEdM43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXa
-n3BukxowOR0w2y7jfLKRstE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKS
-NitjrFgBazMpUIaD8QFI
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUx
-ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0
-b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQD
-EytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBDKSBUYW51c2l0dmFueWtpYWRvMB4X
-DTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJBgNVBAYTAkhVMREw
-DwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9u
-c2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMr
-TmV0TG9jayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzAN
-BgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNA
-OoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3ZW3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC
-2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63euyucYT2BDMIJTLrdKwW
-RMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQwDgYDVR0P
-AQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEW
-ggJNRklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0
-YWxhbm9zIFN6b2xnYWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFz
-b2sgYWxhcGphbiBrZXN6dWx0LiBBIGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBO
-ZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1iaXp0b3NpdGFzYSB2ZWRpLiBB
-IGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0ZWxlIGF6IGVs
-b2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs
-ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25s
-YXBqYW4gYSBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kg
-a2VyaGV0byBheiBlbGxlbm9yemVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4g
-SU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5kIHRoZSB1c2Ugb2YgdGhpcyBjZXJ0
-aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQUyBhdmFpbGFibGUg
-YXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwgYXQg
-Y3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmY
-ta3UzbM2xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2g
-pO0u9f38vf5NNwgMvOOWgyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4
-Fp1hBWeAyNDYpQcCNJgEjTME1A==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhV
-MRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMe
-TmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0
-dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFzcyBB
-KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oXDTE5MDIxOTIzMTQ0
-N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQHEwhC
-dWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQu
-MRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBL
-b3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG
-9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSMD7tM9DceqQWC2ObhbHDqeLVu0ThEDaiD
-zl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZz+qMkjvN9wfcZnSX9EUi
-3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC/tmwqcm8
-WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LY
-Oph7tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2Esi
-NCubMvJIH5+hCoR64sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCC
-ApswDgYDVR0PAQH/BAQDAgAGMBIGA1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4
-QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZRUxFTSEgRXplbiB0
-YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRhdGFz
-aSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu
-IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtm
-ZWxlbG9zc2VnLWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMg
-ZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVs
-amFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJhc2EgbWVndGFsYWxoYXRv
-IGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBzOi8vd3d3
-Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6
-ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1
-YW5jZSBhbmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3Qg
-dG8gdGhlIE5ldExvY2sgQ1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRs
-b2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBjcHNAbmV0bG9jay5uZXQuMA0G
-CSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5ayZrU3/b39/zcT0mwBQO
-xmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjPytoUMaFP
-0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQ
-QeJBCWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxk
-f1qbFFgBJ34TUMdrKuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK
-8CtmdWOMovsEPoMOmzbwGOQmIMOM8CgHrTwXZoi1/baI
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUx
-ETAPBgNVBAcTCEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0
-b25zYWdpIEtmdC4xGjAYBgNVBAsTEVRhbnVzaXR2YW55a2lhZG9rMUIwQAYDVQQD
-EzlOZXRMb2NrIE1pbm9zaXRldHQgS296amVneXpvaSAoQ2xhc3MgUUEpIFRhbnVz
-aXR2YW55a2lhZG8xHjAcBgkqhkiG9w0BCQEWD2luZm9AbmV0bG9jay5odTAeFw0w
-MzAzMzAwMTQ3MTFaFw0yMjEyMTUwMTQ3MTFaMIHJMQswCQYDVQQGEwJIVTERMA8G
-A1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNh
-Z2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxQjBABgNVBAMTOU5l
-dExvY2sgTWlub3NpdGV0dCBLb3pqZWd5em9pIChDbGFzcyBRQSkgVGFudXNpdHZh
-bnlraWFkbzEeMBwGCSqGSIb3DQEJARYPaW5mb0BuZXRsb2NrLmh1MIIBIjANBgkq
-hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1Ilstg91IRVCacbvWy5FPSKAtt2/Goq
-eKvld/Bu4IwjZ9ulZJm53QE+b+8tmjwi8F3JV6BVQX/yQ15YglMxZc4e8ia6AFQe
-r7C8HORSjKAyr7c3sVNnaHRnUPYtLmTeriZ539+Zhqurf4XsoPuAzPS4DB6TRWO5
-3Lhbm+1bOdRfYrCnjnxmOCyqsQhjF2d9zL2z8cM/z1A57dEZgxXbhxInlrfa6uWd
-vLrqOU+L73Sa58XQ0uqGURzk/mQIKAR5BevKxXEOC++r6uwSEaEYBTJp0QwsGj0l
-mT+1fMptsK6ZmfoIYOcZwvK9UdPM0wKswREMgM6r3JSda6M5UzrWhQIDAMV9o4IC
-wDCCArwwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNVHQ8BAf8EBAMCAQYwggJ1Bglg
-hkgBhvhCAQ0EggJmFoICYkZJR1lFTEVNISBFemVuIHRhbnVzaXR2YW55IGEgTmV0
-TG9jayBLZnQuIE1pbm9zaXRldHQgU3pvbGdhbHRhdGFzaSBTemFiYWx5emF0YWJh
-biBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIG1pbm9zaXRldHQg
-ZWxla3Ryb25pa3VzIGFsYWlyYXMgam9naGF0YXMgZXJ2ZW55ZXN1bGVzZW5laywg
-dmFsYW1pbnQgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUgYSBNaW5vc2l0ZXR0IFN6
-b2xnYWx0YXRhc2kgU3phYmFseXphdGJhbiwgYXogQWx0YWxhbm9zIFN6ZXJ6b2Rl
-c2kgRmVsdGV0ZWxla2JlbiBlbG9pcnQgZWxsZW5vcnplc2kgZWxqYXJhcyBtZWd0
-ZXRlbGUuIEEgZG9rdW1lbnR1bW9rIG1lZ3RhbGFsaGF0b2sgYSBodHRwczovL3d3
-dy5uZXRsb2NrLmh1L2RvY3MvIGNpbWVuIHZhZ3kga2VyaGV0b2sgYXogaW5mb0Bu
-ZXRsb2NrLm5ldCBlLW1haWwgY2ltZW4uIFdBUk5JTkchIFRoZSBpc3N1YW5jZSBh
-bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGFyZSBzdWJqZWN0IHRvIHRo
-ZSBOZXRMb2NrIFF1YWxpZmllZCBDUFMgYXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3
-Lm5ldGxvY2suaHUvZG9jcy8gb3IgYnkgZS1tYWlsIGF0IGluZm9AbmV0bG9jay5u
-ZXQwHQYDVR0OBBYEFAlqYhaSsFq7VQ7LdTI6MuWyIckoMA0GCSqGSIb3DQEBBQUA
-A4IBAQCRalCc23iBmz+LQuM7/KbD7kPgz/PigDVJRXYC4uMvBcXxKufAQTPGtpvQ
-MznNwNuhrWw3AkxYQTvyl5LGSKjN5Yo5iWH5Upfpvfb5lHTocQ68d4bDBsxafEp+
-NFAwLvt/MpqNPfMgW/hqyobzMUwsWYACff44yTB1HLdV47yfuqhthCgFdbOLDcCR
-VCHnpgu0mfVRQdzNo0ci2ccBgcTcR08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY
-83ZmiVSkpj7EUFy6iRiCdUgh0k8T6GB+B3bbELVR5qq5aKrN9p2QdRLqOBrKROi3
-macqaJVmlaut74nLYKkGEsaUR+ko
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBi
-MQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
-MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3Jp
-dHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMxMjM1OTU5WjBiMQswCQYDVQQGEwJV
-UzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydO
-ZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG
-SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwz
-c7MEL7xxjOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPP
-OCwGJgl6cvf6UDL4wpPTaaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rl
-mGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXTcrA/vGp97Eh/jcOrqnErU2lBUzS1sLnF
-BgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc/Qzpf14Dl847ABSHJ3A4
-qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMBAAGjgZcw
-gZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIB
-BjAPBgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwu
-bmV0c29sc3NsLmNvbS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3Jp
-dHkuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc8
-6fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q4LqILPxFzBiwmZVRDuwduIj/
-h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/GGUsyfJj4akH
-/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
-wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHN
-pGxlaKFJdlxDydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCB
-ijELMAkGA1UEBhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHly
-aWdodCAoYykgMjAwNTEiMCAGA1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNl
-ZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBHbG9iYWwgUm9vdCBHQSBDQTAeFw0w
-NTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYDVQQGEwJDSDEQMA4G
-A1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIwIAYD
-VQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBX
-SVNlS2V5IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
-MIIBCgKCAQEAy0+zAJs9Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxR
-VVuuk+g3/ytr6dTqvirdqFEr12bDYVxgAsj1znJ7O7jyTmUIms2kahnBAbtzptf2
-w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbDd50kc3vkDIzh2TbhmYsF
-mQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ/yxViJGg
-4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t9
-4B3RLoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYw
-DwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQw
-EAYJKwYBBAGCNxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOx
-SPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vImMMkQyh2I+3QZH4VFvbBsUfk2
-ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4+vg1YFkCExh8
-vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
-hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZi
-Fj4A4xylNoEYokxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ
-/L7fCg0=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
-GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
-b3QgQ0EgMjAeFw0wNjExMjQxODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNV
-BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
-YWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCa
-GMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6XJxg
-Fyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55J
-WpzmM+Yklvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bB
-rrcCaoF6qUWD4gXmuVbBlDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp
-+ARz8un+XJiM9XOva7R+zdRcAitMOeGylZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1
-ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt66/3FsvbzSUr5R/7mp/i
-Ucw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1JdxnwQ5hYIiz
-PtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og
-/zOhD7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UH
-oycR7hYQe7xFSkyyBNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuI
-yV77zGHcizN300QyNQliBJIWENieJ0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1Ud
-EwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1UdDgQWBBQahGK8SEwzJQTU7tD2
-A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGUa6FJpEcwRTEL
-MAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
-ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2f
-BluornFdLwUvZ+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzn
-g/iN/Ae42l9NLmeyhP3ZRPx3UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2Bl
-fF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodmVjB3pjd4M1IQWK4/YY7yarHvGH5K
-WWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK+JDSV6IZUaUtl0Ha
-B0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrWIozc
-hLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPR
-TUIZ3Ph1WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWD
-mbA4CD/pXvk1B+TJYm5Xf6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0Z
-ohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y
-4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8VCLAAVBpQ570su9t+Oza
-8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0x
-GTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJv
-b3QgQ0EgMzAeFw0wNjExMjQxOTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNV
-BAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMRswGQYDVQQDExJRdW9W
-YWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDM
-V0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNggDhoB
-4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUr
-H556VOijKTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd
-8lyyBTNvijbO0BNO/79KDDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9Cabwv
-vWhDFlaJKjdhkf2mrk7AyxRllDdLkgbvBNDInIjbC3uBr7E9KsRlOni27tyAsdLT
-mZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwpp5ijJUMv7/FfJuGITfhe
-btfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8nT8KKdjc
-T5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDt
-WAEXMJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZ
-c6tsgLjoC2SToJyMGf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A
-4iLItLRkT9a6fUg+qGkM17uGcclzuD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYD
-VR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHTBgkrBgEEAb5YAAMwgcUwgZMG
-CCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmljYXRlIGNvbnN0
-aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
-aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVu
-dC4wLQYIKwYBBQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2Nw
-czALBgNVHQ8EBAMCAQYwHQYDVR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4G
-A1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4ywLQoUmkRzBFMQswCQYDVQQGEwJC
-TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UEAxMSUXVvVmFkaXMg
-Um9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZVqyM0
-7ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSem
-d1o417+shvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd
-+LJ2w/w4E6oM3kJpK27zPOuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B
-4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadN
-t54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp8kokUvd0/bpO5qgdAm6x
-DYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBCbjPsMZ57
-k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6s
-zHXug/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0j
-Wy10QJLZYxkNc91pvGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeT
-mJlglFwjz1onl14LBQaTNx47aTbrqZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK
-4SVhM7JZG+Ju1zdXtg2pEto=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJC
-TTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0
-aWZpY2F0aW9uIEF1dGhvcml0eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0
-aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAzMTkxODMzMzNaFw0yMTAzMTcxODMz
-MzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUw
-IwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQDEyVR
-dW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG
-9w0BAQEFAAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Yp
-li4kVEAkOPcahdxYTMukJ0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2D
-rOpm2RgbaIr1VxqYuvXtdj182d6UajtLF8HVj71lODqV0D1VNk7feVcxKh7YWWVJ
-WCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeLYzcS19Dsw3sgQUSj7cug
-F+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWenAScOospU
-xbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCC
-Ak4wPQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVv
-dmFkaXNvZmZzaG9yZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREw
-ggENMIIBCQYJKwYBBAG+WAABMIH7MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNl
-IG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmljYXRlIGJ5IGFueSBwYXJ0eSBh
-c3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJsZSBzdGFuZGFy
-ZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
-Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYI
-KwYBBQUHAgEWFmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3T
-KbkGGew5Oanwl4Rqy+/fMIGuBgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rq
-y+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBMaW1p
-dGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYD
-VQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6tlCL
-MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSk
-fnIYj9lofFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf8
-7C9TqnN7Az10buYWnuulLsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1R
-cHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2xgI4JVrmcGmD+XcHXetwReNDWXcG31a0y
-mQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi5upZIof4l/UO/erMkqQW
-xFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi5nrQNiOK
-SnQ2+Q==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
-IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
-BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
-aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
-9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMjIzM1oXDTE5MDYy
-NjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
-azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
-YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
-Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
-cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDjmFGWHOjVsQaBalfD
-cnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td3zZxFJmP3MKS8edgkpfs
-2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89HBFx1cQqY
-JJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliE
-Zwgs3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJ
-n0WuPIqpsHEzXcjFV9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/A
-PhmcGcwTTYJBtYze4D1gCCAPRX5ron+jjBXu
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6
-MRkwFwYDVQQKExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJp
-dHkgMjA0OCBWMzAeFw0wMTAyMjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAX
-BgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAbBgNVBAsTFFJTQSBTZWN1cml0eSAy
-MDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAt49VcdKA3Xtp
-eafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7Jylg
-/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGl
-wSMiuLgbWhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnh
-AMFRD0xS+ARaqn1y07iHKrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2
-PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP+Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpu
-AWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIB
-BjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4EFgQUB8NR
-MKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYc
-HnmYv/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/
-Zb5gEydxiKRz44Rj0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+
-f00/FGj1EVDVwfSQpQgdMWD/YIwjVAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVO
-rSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395nzIlQnQFgCi/vcEkllgVsRch
-6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kApKnXwiJPZ9d3
-7CAFYd4=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBK
-MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
-GTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkx
-MjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3Qg
-Q29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwgQ0EwggEiMA0GCSqG
-SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jxYDiJ
-iQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa
-/FHtaMbQbqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJ
-jnIFHovdRIWCQtBJwB1g8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnI
-HmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYVHDGA76oYa8J719rO+TMg1fW9ajMtgQT7
-sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi0XPnj3pDAgMBAAGjgZ0w
-gZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1UdEwEB/wQF
-MAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCsw
-KaAnoCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsG
-AQQBgjcVAQQDAgEAMA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0L
-URYD7xh8yOOvaliTFGCRsoTciE6+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXO
-H0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cnCDpOGR86p1hcF895P4vkp9Mm
-I50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/53CYNv6ZHdAbY
-iNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
-f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDEr
-MCkGA1UEChMiSmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoG
-A1UEAxMTU2VjdXJlU2lnbiBSb290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0
-MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSswKQYDVQQKEyJKYXBhbiBDZXJ0aWZp
-Y2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1cmVTaWduIFJvb3RD
-QTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvLTJsz
-i1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8
-h9uuywGOwvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOV
-MdrAG/LuYpmGYz+/3ZMqg6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9
-UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rPO7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni
-8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitAbpSACW22s293bzUIUPsC
-h8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZXt94wDgYD
-VR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEB
-AKChOBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xm
-KbabfSVSSUOrTC4rbnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQ
-X5Ucv+2rIrVls4W6ng+4reV6G4pQOh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWr
-QbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01y8hSyn+B/tlr0/cR7SXf+Of5
-pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061lgeLKBObjBmN
-QSdJQO7e5iNEOdyhIta6A/I=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBI
-MQswCQYDVQQGEwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24x
-FzAVBgNVBAMTDlNlY3VyZVRydXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIz
-MTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAeBgNVBAoTF1NlY3VyZVRydXN0IENv
-cnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCCASIwDQYJKoZIhvcN
-AQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQXOZEz
-Zum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO
-0gMdA+9tDWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIao
-wW8xQmxSPmjL8xk037uHGFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj
-7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b01k/unK8RCSc43Oz969XL0Imnal0ugBS
-8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmHursCAwEAAaOBnTCBmjAT
-BgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB
-/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCeg
-JYYjaHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGC
-NxUBBAMCAQAwDQYJKoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt3
-6Z3q059c4EVlew3KW+JwULKUBRSuSceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/
-3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHfmbx8IVQr5Fiiu1cprp6poxkm
-D5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZnMUFdAvnZyPS
-CPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
-3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDEl
-MCMGA1UEChMcU0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMh
-U2VjdXJpdHkgQ29tbXVuaWNhdGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIz
-MloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UEBhMCSlAxJTAjBgNVBAoTHFNFQ09N
-IFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNlY3VyaXR5IENvbW11
-bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
-ggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSE
-RMqm4miO/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gO
-zXppFodEtZDkBp2uoQSXWHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5
-bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4zZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDF
-MxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4bepJz11sS6/vmsJWXMY1
-VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK9U2vP9eC
-OKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0G
-CSqGSIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HW
-tWS3irO4G8za+6xmiEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZ
-q51ihPZRwSzJIxXYKLerJRO1RuGGAv8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDb
-EJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnWmHyojf6GPgcWkuF75x3sM3Z+
-Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEWT1MKZPlO9L9O
-VL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEY
-MBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21t
-dW5pY2F0aW9uIFJvb3RDQTEwHhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5
-WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMPU0VDT00gVHJ1c3QubmV0MScwJQYD
-VQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEwggEiMA0GCSqGSIb3
-DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw8yl8
-9f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJ
-DKaVv0uMDPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9
-Ms+k2Y7CI9eNqPPYJayX5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/N
-QV3Is00qVUarH9oe4kA92819uZKAnDfdDJZkndwi92SL32HeFZRSFaB9UslLqCHJ
-xrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2JChzAgMBAAGjPzA9MB0G
-A1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYwDwYDVR0T
-AQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vG
-kl3g0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfr
-Uj94nK9NrvjVT8+amCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5
-Bw+SUEmK3TGXX8npN6o7WWWXlDLJs58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJU
-JRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ6rBK+1YWc26sTfcioU+tHXot
-RSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAiFL39vmwLAw==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIETzCCAzegAwIBAgIEO63vKTANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQTDEfMB0GA1UE
-ChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2Fjamkg
-U2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBSb290Q0EwHhcNMDEwOTIzMTQxODE3WhcNMTEw
-OTIzMTMxODE3WjB1MQswCQYDVQQGEwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5v
-LjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWdu
-ZXQgLSBDQSBLbGFzYSAxMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC4SRW9Q58g5DY1Hw7h
-gCRKBEdPdGn0MFHsfw7rlu/oQm7IChI/uWd9q5wwo77YojtTDjRnpgZsjqBeynX8T90vFILqsY2K
-5CF1OESalwvVr3sZiQX79lisuFKat92u6hBFikFIVxfHHB67Af+g7u0dEHdDW7lwy81MwFYxBTRy
-9wIDAQABo4IBbTCCAWkwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwggEEBgNVHSAE
-gfwwgfkwgfYGDSsGAQQBvj8CAQoBAQAwgeQwgZoGCCsGAQUFBwICMIGNGoGKQ2VydHlmaWthdCB3
-eXN0YXdpb255IHpnb2RuaWUgeiBkb2t1bWVudGVtOiAiUG9saXR5a2EgQ2VydHlmaWthY2ppIGRs
-YSBSb290Q0EiLiBDZXJ0eWZpa2F0IHd5c3Rhd2lvbnkgcHJ6ZXogUm9vdENBIHcgaGllcmFyY2hp
-aSBDQyBTaWduZXQuMEUGCCsGAQUFBwIBFjlodHRwOi8vd3d3LnNpZ25ldC5wbC9yZXBvenl0b3Jp
-dW0vZG9rdW1lbnR5L3BjX3Jvb3RjYS50eHQwHwYDVR0jBBgwFoAUwJvFIw0C4aZOSGsfAOnjmhQb
-sa8wHQYDVR0OBBYEFMODHtVZd1T7TftXR/nEI1zR54njMA0GCSqGSIb3DQEBBQUAA4IBAQBRIHQB
-FIGh8Jpxt87AgSLwIEEk4+oGy769u3NtoaR0R3WNMdmt7fXTi0tyTQ9V4AIszxVjhnUPaKnF1KYy
-f8Tl+YTzk9ZfFkZ3kCdSaILZAOIrmqWNLPmjUQ5/JiMGho0e1YmWUcMci84+pIisTsytFzVP32/W
-+sz2H4FQAvOIMmxB7EJX9AdbnXn9EXZ+4nCqi0ft5z96ZqOJJiCB3vSaoYg+wdkcvb6souMJzuc2
-uptXtR1Xf3ihlHaGW+hmnpcwFA6AoNrom6Vgzk6U1ienx0Cw28BhRSKqzKkyXkuK8gRflZUx84uf
-tXncwKJrMiE3lvgOOBITRzcahirLer4c
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIE9zCCA9+gAwIBAgIEPL/xoTANBgkqhkiG9w0BAQUFADB2MQswCQYDVQQGEwJQTDEfMB0GA1UE
-ChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2Fjamkg
-U2lnbmV0MSAwHgYDVQQDExdDQyBTaWduZXQgLSBQQ0EgS2xhc2EgMjAeFw0wMjA0MTkxMDI5NTNa
-Fw0xNzA0MTgxMjUzMDdaMHUxCzAJBgNVBAYTAlBMMR8wHQYDVQQKExZUUCBJbnRlcm5ldCBTcC4g
-eiBvLm8uMSQwIgYDVQQLExtDZW50cnVtIENlcnR5ZmlrYWNqaSBTaWduZXQxHzAdBgNVBAMTFkND
-IFNpZ25ldCAtIENBIEtsYXNhIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCqgLJu
-QqY4yavbSgHg8CyfKTx4BokNSDOVz4eD9vptUr11Kqd06ED1hlH7Sg0goBFAfntNU/QTKwSBaNui
-me7C4sSEdgsKrPoAhGb4Mq8y7Ty7RqZz7mkzNMqzL2L2U4yQ2QjvpH8MH0IBqOWEcpSkpwnrCDIm
-RoTfd+YlZWKi2JceQixUUYIQ45Ox8+x8hHbvvZdgqtcvo8PW27qoHkp/7hMuJ44kDAGrmxffBXl/
-OBRZp0uO1CSLcMcVJzyr2phKhy406MYdWrtNPEluGs0GFDzd0nrIctiWAO4cmct4S72S9Q6e//0G
-O9f3/Ca5Kb2I1xYLj/xE+HgjHX9aD2MhAgMBAAGjggGMMIIBiDAPBgNVHRMBAf8EBTADAQH/MA4G
-A1UdDwEB/wQEAwIBBjCB4wYDVR0gBIHbMIHYMIHVBg0rBgEEAb4/AhQKAQEAMIHDMHUGCCsGAQUF
-BwICMGkaZ0NlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmllIHogZG9rdW1lbnRlbTogIlBvbGl0
-eWthIENlcnR5ZmlrYWNqaSBQQ0EyIC0gQ2VydHlmaWthdHkgVXJ6ZWRvdyBLbGFzeSAyIi4wSgYI
-KwYBBQUHAgEWPmh0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9kb2t1bWVudHkva2xh
-c2EyL3BjX3BjYTIudHh0MD8GA1UdHwQ4MDYwNKAyoDCGLmh0dHA6Ly93d3cuc2lnbmV0LnBsL3Jl
-cG96eXRvcml1bS9jcmwvcGNhMi5jcmwwHwYDVR0jBBgwFoAUwGxGyl2CfpYHRonE82AVXO08kMIw
-HQYDVR0OBBYEFLtFBlILy4HNKVSzvHxBTM0HDowlMA0GCSqGSIb3DQEBBQUAA4IBAQBWTsCbqXrX
-hBBev5v5cIuc6gJM8ww7oR0uMQRZoFSqvQUPWBYM2/TLI/f8UM9hSShUVj3zEsSj/vFHagUVmzuV
-Xo5u0WK8iaqATSyEVBhADHrPG6wYcLKJlagge/ILA0m+SieyP2sjYD9MUB9KZIEyBKv0429UuDTw
-6P7pslxMWJBSNyQxaLIs0SRKsqZZWkc7ZYAj2apSkBMX2Is1oHA+PwkF6jQMwCao/+CndXPUzfCF
-6caa9WwW31W26MlXCvSmJgfiTPwGvm4PkPmOnmWZ3CczzhHl4q7ztHFzshJH3sZWDnrWwBFjzz5e
-Pr3WHV1wA7EY6oT4zBx+2gT9XBTB
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEUzCCAzugAwIBAgIEPq+qjzANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQGEwJQTDE3MDUGA1UE
-ChMuQ1ppQyBDZW50cmFzdCBTQSB3IGltaWVuaXUgTWluaXN0cmEgR29zcG9kYXJraTEZMBcGA1UE
-AxMQQ1ppQyBDZW50cmFzdCBTQTAeFw0wMzA0MzAxMDUwNTVaFw0wODA0MjgxMDUwNTVaMGgxCzAJ
-BgNVBAYTAlBMMR8wHQYDVQQKExZUUCBJbnRlcm5ldCBTcC4geiBvLm8uMR8wHQYDVQQDExZDQyBT
-aWduZXQgLSBDQSBLbGFzYSAzMRcwFQYDVQQFEw5OdW1lciB3cGlzdTogNDCCASIwDQYJKoZIhvcN
-AQEBBQADggEPADCCAQoCggEBALVdeOM62cPH2NERFxbS5FIp/HSv3fgesdVsTUFxZbGtE+/E0RMl
-KZQJHH9emx7vRYubsi4EOLCjYsCOTFvgGRIpZzx7R7T5c0Di5XFkRU4gjBl7aHJoKb5SLzGlWdoX
-GsekVtl6keEACrizV2EafqjI8cnBWY7OxQ1ooLQp5AeFjXg+5PT0lO6TUZAubqjFbhVbxSWjqvdj
-93RGfyYE76MnNn4c2xWySD07n7uno06TC0IJe6+3WSX1h+76VsIFouWBXOoM7cxxiLjoqdBVu24+
-P8e81SukE7qEvOwDPmk9ZJFtt1nBNg8a1kaixcljrA/43XwOPz6qnJ+cIj/xywECAwEAAaOCAQow
-ggEGMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMDMGA1UdIAEB/wQpMCcwJQYEVR0g
-ADAdMBsGCCsGAQUFBwIBFg93d3cuY2VudHJhc3QucGwwgY4GA1UdIwSBhjCBg4AU2a7r85Cp1iJN
-W0Ca1LR6VG3996ShZaRjMGExCzAJBgNVBAYTAlBMMTcwNQYDVQQKEy5DWmlDIENlbnRyYXN0IFNB
-IHcgaW1pZW5pdSBNaW5pc3RyYSBHb3Nwb2RhcmtpMRkwFwYDVQQDExBDWmlDIENlbnRyYXN0IFNB
-ggQ9/0sQMB0GA1UdDgQWBBR7Y8wZkHq0zrY7nn1tFSdQ0PlJuTANBgkqhkiG9w0BAQUFAAOCAQEA
-ldt/svO5c1MU08FKgrOXCGEbEPbQxhpM0xcd6Iv3dCo6qugEgjEs9Qm5CwUNKMnFsvR27cJWUvZb
-MVcvwlwCwclOdwF6u/QRS8bC2HYErhYo9bp9yuxxzuow2A94c5fPqfVrjXy+vDouchAm6+A5Wjzv
-J8wxVFDCs+9iGACmyUWr/JGXCYiQIbQkwlkRKHHlan9ymKf1NvIej/3EpeT8fKr6ywxGuhAfqofW
-pg3WJY/RCB4lTzD8vZGNwfMFGkWhJkypad3i9w3lGmDVpsHaWtCgGfd0H7tUtWPkP+t7EjIRCD9J
-HYnTR+wbbewc5vOI+UobR15ynGfFIaSIiMTVtQ==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEejCCA2KgAwIBAgIEP4vk6TANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJQ
-TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2Vu
-dHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQgLSBD
-QSBLbGFzYSAyMB4XDTAzMTAxNDExNTgyMloXDTE3MDQxODEyNTMwN1owdzELMAkG
-A1UEBhMCUEwxHzAdBgNVBAoTFlRQIEludGVybmV0IFNwLiB6IG8uby4xJDAiBgNV
-BAsTG0NlbnRydW0gQ2VydHlmaWthY2ppIFNpZ25ldDEhMB8GA1UEAxMYQ0MgU2ln
-bmV0IC0gT0NTUCBLbGFzYSAyMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCo
-VCsaBStblXQYVNthe3dvaCrfvKpPXngh4almm988iIlEv9CVTaAdCfaJNihvA+Vs
-Qw8++ix1VqteMQE474/MV/YaXigP0Zr0QB+g+/7PWVlv+5U9Gzp9+Xx4DJay8AoI
-iB7Iy5Qf9iZiHm5BiPRIuUXT4ZRbZRYPh0/76vgRsQIDAQABo4IBkjCCAY4wDgYD
-VR0PAQH/BAQDAgeAMBMGA1UdJQQMMAoGCCsGAQUFBwMJMEEGA1UdHwQ6MDgwNqA0
-oDKGMGh0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9jcmwva2xhc2Ey
-LmNybDCB2AYDVR0gBIHQMIHNMIHKBg4rBgEEAb4/AoFICgwBADCBtzBsBggrBgEF
-BQcCAjBgGl5DZXJ0eWZpa2F0IHd5ZGFueSB6Z29kbmllIHogZG9rdW1lbnRlbSAi
-UG9saXR5a2EgQ2VydHlmaWthY2ppIC0gQ2VydHlmaWthdHkgcmVzcG9uZGVyb3cg
-T0NTUCIuMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnNpZ25ldC5wbC9yZXBvenl0
-b3JpdW0vZG9rdW1lbnR5L3BjX29jc3BfMV8wLnBkZjAfBgNVHSMEGDAWgBS7RQZS
-C8uBzSlUs7x8QUzNBw6MJTAdBgNVHQ4EFgQUKEVrOY7cEHvsVgvoyZdytlbtgwEw
-CQYDVR0TBAIwADANBgkqhkiG9w0BAQUFAAOCAQEAQrRg5MV6dxr0HU2IsLInxhvt
-iUVmSFkIUsBCjzLoewOXA16d2oDyHhI/eE+VgAsp+2ANjZu4xRteHIHoYMsN218M
-eD2MLRsYS0U9xxAFK9gDj/KscPbrrdoqLvtPSMhUb4adJS9HLhvUe6BicvBf3A71
-iCNe431axGNDWKnpuj2KUpj4CFHYsWCXky847YtTXDjri9NIwJJauazsrSjK+oXp
-ngRS506mdQ7vWrtApkh8zhhWp7duCkjcCo1O8JxqYr2qEW1fXmgOISe010v2mmuv
-hHxPyVwoAU4KkOw0nbXZn53yak0is5+XmAjh0wWue44AssHrjC9nUh3mkLt6eQ==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEezCCA2OgAwIBAgIEP4vnLzANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJQ
-TDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEfMB0GA1UEAxMWQ0Mg
-U2lnbmV0IC0gQ0EgS2xhc2EgMzEXMBUGA1UEBRMOTnVtZXIgd3Bpc3U6IDQwHhcN
-MDMxMDE0MTIwODAwWhcNMDgwNDI4MTA1MDU1WjB3MQswCQYDVQQGEwJQTDEfMB0G
-A1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBD
-ZXJ0eWZpa2FjamkgU2lnbmV0MSEwHwYDVQQDExhDQyBTaWduZXQgLSBPQ1NQIEts
-YXNhIDMwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM/9GwvARNuCVN+PqZmO
-4FqH8vTqhenUyqRkmAVT4YhLu0a9AXeLAYVDu+NTkYzsAUMAfu55rIKHNLlm6WbF
-KvLiKKz4p4pbUr+ToPcwl/TDotidloUdBAxDg0SL+PmQqACZDe3seJho2IYf2vDL
-/G4TLMbKmNB0mlWFuN0f4fJNAgMBAAGjggGgMIIBnDAOBgNVHQ8BAf8EBAMCB4Aw
-EwYDVR0lBAwwCgYIKwYBBQUHAwkwTwYDVR0fBEgwRjBEoEKgQIY+aHR0cDovL3d3
-dy5zaWduZXQucGwva3dhbGlmaWtvd2FuZS9yZXBvenl0b3JpdW0vY3JsL2tsYXNh
-My5jcmwwgdgGA1UdIASB0DCBzTCBygYOKwYBBAG+PwKCLAoCAQAwgbcwbAYIKwYB
-BQUHAgIwYBpeQ2VydHlmaWthdCB3eWRhbnkgemdvZG5pZSB6IGRva3VtZW50ZW0g
-IlBvbGl0eWthIENlcnR5ZmlrYWNqaSAtIENlcnR5ZmlrYXR5IHJlc3BvbmRlcm93
-IE9DU1AiLjBHBggrBgEFBQcCARY7aHR0cDovL3d3dy5zaWduZXQucGwvcmVwb3p5
-dG9yaXVtL2Rva3VtZW50eS9wY19vY3NwXzFfMC5wZGYwHwYDVR0jBBgwFoAUe2PM
-GZB6tM62O559bRUnUND5SbkwHQYDVR0OBBYEFG4jnCMvBALRQXtmDn9TyXQ/EKP+
-MAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADggEBACXrKG5Def5lpRwmZom3UEDq
-bl7y4U3qomG4B+ok2FVZGgPZti+ZgvrenPj7PtbYCUBPsCSTNrznKinoT3gD9lQQ
-xkEHwdc6VD1GlFp+qI64u0+wS9Epatrdf7aBnizrOIB4LJd4E2TWQ6trspetjMIU
-upyWls1BmYUxB91R7QkTiAUSNZ87s3auhZuG4f0V0JLVCcg2rn7AN1rfMkgxCbHk
-GxiQbYWFljl6aatxR3odnnzVUe1I8uoY2JXpmmUcOG4dNGuQYziyKG3mtXCQWvug
-5qi9Mf3KUh1oSTKx6HfLjjNl1+wMB5Mdb8LF0XyZLdJM9yIZh7SBRsYm9QiXevY=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFGjCCBAKgAwIBAgIEPL7eEDANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQTDEfMB0GA1UE
-ChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2Fjamkg
-U2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBSb290Q0EwHhcNMDIwNDE4MTQ1NDA4WhcNMjYw
-OTIxMTU0MjE5WjB2MQswCQYDVQQGEwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5v
-LjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MSAwHgYDVQQDExdDQyBTaWdu
-ZXQgLSBQQ0EgS2xhc2EgMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM7BrBlbN5ma
-M5eg0BOTqoZ+9NBDvU8Lm5rTdrMswFTCathzpVVLK/JD4K3+4oCZ9SRAspEXE4gvwb08ASY6w5s+
-HpRkeJw8YzMFR5kDZD5adgnCAy4vDfIXYZgppXPaTQ8wnfUZ7BZ7Zfa7QBemUIcJIzJBB0UqgtxW
-Ceol9IekpBRVmuuSA6QG0Jkm+pGDJ05yj2eQG8jTcBENM7sVA8rGRMyFA4skSZ+D0OG6FS2xC1i9
-JyN0ag1yII/LPx8HK5J4W9MaPRNjAEeaa2qI9EpchwrOxnyVbQfSedCG1VRJfAsE/9tT9CMUPZ3x
-W20QjQcSZJqVcmGW9gVsXKQOVLsCAwEAAaOCAbMwggGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
-AQH/BAQDAgEGMIIBBAYDVR0gBIH8MIH5MIH2Bg0rBgEEAb4/AgEKAQEBMIHkMIGaBggrBgEFBQcC
-AjCBjRqBikNlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmllIHogZG9rdW1lbnRlbTogIlBvbGl0
-eWthIENlcnR5ZmlrYWNqaSBkbGEgUm9vdENBIi4gQ2VydHlmaWthdCB3eXN0YXdpb255IHByemV6
-IFJvb3RDQSB3IGhpZXJhcmNoaWkgQ0MgU2lnbmV0LjBFBggrBgEFBQcCARY5aHR0cDovL3d3dy5z
-aWduZXQucGwvcmVwb3p5dG9yaXVtL2Rva3VtZW50eS9wY19yb290Y2EudHh0MEQGA1UdHwQ9MDsw
-OaA3oDWGM2h0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9yb290Y2Evcm9vdGNhLmNy
-bDAfBgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAdBgNVHQ4EFgQUwGxGyl2CfpYHRonE
-82AVXO08kMIwDQYJKoZIhvcNAQEFBQADggEBABp1TAUsa+BeVWg4cjowc8yTJ5XN3GvN96GObMkx
-UGY7U9kVrLI71xBgoNVyzXTiMNDBvjh7vdPWjpl5SDiRpnnKiOFXA43HvNWzUaOkTu1mxjJsZsan
-ot1Xt6j0ZDC+03FjLHdYMyM9kSWp6afb4980EPYZCcSzgM5TOGfJmNii5Tq468VFKrX+52Aou1G2
-2Ohu+EEOlOrG7ylKv1hHUJJCjwN0ZVEIn1nDbrU9FeGCz8J9ihVUvnENEBbBkU37PWqWuHitKQDV
-tcwTwJJdR8cmKq3NmkwAm9fPacidQLpaw0WkuGrS+fEDhu1Nhy9xELP6NA9GRTCNxm/dXlcwnmY=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFGjCCBAKgAwIBAgIEPV0tNDANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQTDEfMB0GA1UE
-ChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2Fjamkg
-U2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBSb290Q0EwHhcNMDIwODE2MTY0OTU2WhcNMjYw
-OTIxMTU0MjE5WjB2MQswCQYDVQQGEwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5v
-LjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MSAwHgYDVQQDExdDQyBTaWdu
-ZXQgLSBQQ0EgS2xhc2EgMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALN3LanJtdue
-Ne6geWUTFENa+lEuzqELcoqhYB+a/tJcPEkc6TX/bYPzalRRjqs+quMP6KZTU0DixOrV+K7iWaqA
-iQ913HX5IBLmKDCrTVW/ZvSDpiBKbxlHfSNuJxAuVT6HdbzK7yAW38ssX+yS2tZYHZ5FhZcfqzPE
-OpO94mAKcBUhk6T/ki0evXX/ZvvktwmF3hKattzwtM4JMLurAEl8SInyEYULw5JdlfcBez2Tg6Db
-w34hA1A+ckTwhxzecrB8TUe2BnQKOs9vr2cCACpFFcOmPkM0Drtjctr1QHm1tYSqRFRf9VcV5tfC
-3P8QqoK4ONjtLPHc9x5NE1uK/FMCAwEAAaOCAbMwggGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0P
-AQH/BAQDAgEGMIIBBAYDVR0gBIH8MIH5MIH2Bg0rBgEEAb4/AgEKAQECMIHkMIGaBggrBgEFBQcC
-AjCBjRqBikNlcnR5ZmlrYXQgd3lzdGF3aW9ueSB6Z29kbmllIHogZG9rdW1lbnRlbTogIlBvbGl0
-eWthIENlcnR5ZmlrYWNqaSBkbGEgUm9vdENBIi4gQ2VydHlmaWthdCB3eXN0YXdpb255IHByemV6
-IFJvb3RDQSB3IGhpZXJhcmNoaWkgQ0MgU2lnbmV0LjBFBggrBgEFBQcCARY5aHR0cDovL3d3dy5z
-aWduZXQucGwvcmVwb3p5dG9yaXVtL2Rva3VtZW50eS9wY19yb290Y2EudHh0MEQGA1UdHwQ9MDsw
-OaA3oDWGM2h0dHA6Ly93d3cuc2lnbmV0LnBsL3JlcG96eXRvcml1bS9yb290Y2Evcm9vdGNhLmNy
-bDAfBgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAdBgNVHQ4EFgQUXvthcPHlH5BgGhlM
-ErJNXWlhlgAwDQYJKoZIhvcNAQEFBQADggEBACIce95Mvn710KCAISA0CuHD4aznTU6pLoCDShW4
-7OR+GTpJUm1coTcUqlBHV9mra4VFrBcBuOkHZoBLq/jmE0QJWnpSEULDcH9J3mF0nqO9SM+mWyJG
-dsJF/XU/7smummgjMNQXwzQTtWORF+6v5KUbWX85anO2wR+M6YTBWC55zWpWi4RG3vkHFs5Ze2oF
-JTlpuxw9ZgxTnWlwI9QR2MvEhYIUMKMOWxw1nt0kKj+5TCNQQGh/VJJ1dsiroGh/io1DOcePEhKz
-1Ag52y6Wf0nJJB9yk0sFakqZH18F7eQecQImgZyyeRtsG95leNugB3BXWCW+KxwiBrtQTXv4dTE=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEzzCCA7egAwIBAgIEO6ocGTANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJQTDEfMB0GA1UE
-ChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2Fjamkg
-U2lnbmV0MRswGQYDVQQDExJDQyBTaWduZXQgLSBSb290Q0EwHhcNMDEwOTIwMTY0MjE5WhcNMjYw
-OTIxMTU0MjE5WjBxMQswCQYDVQQGEwJQTDEfMB0GA1UEChMWVFAgSW50ZXJuZXQgU3AuIHogby5v
-LjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2FjamkgU2lnbmV0MRswGQYDVQQDExJDQyBTaWdu
-ZXQgLSBSb290Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrr2vydnNpELfGW3Ks
-ARiDhJvwDtUe4AbWev+OfMc3+vA29nX8ZmIwno3gmItjo5DbUCCRiCMq5c9epcGu+kg4a3BJChVX
-REl8gVh0ST15rr3RKrSc4VgsvQzl0ZUraeQLl8JoRT5PLsUj3qwF78jUCQVckiiLVcnGfZtFCm+D
-CJXliQBDMB9XFAUEiO/DtEBs0B7wJGx7lgJeJpQUcGiaOPjcJDYOk7rNAYmmD2gWeSlepufO8luU
-YG/YDxTC4mqhRqfa4MnVO5dqy+ICj2UvUpHbZDB0KfGRibgBYeQP1kuqgIzJN4UqknVAJb0aMBSP
-l+9k2fAUdchx1njlbdcbAgMBAAGjggFtMIIBaTAPBgNVHRMBAf8EBTADAQH/MIIBBAYDVR0gBIH8
-MIH5MIH2Bg0rBgEEAb4/AgEKAQEAMIHkMIGaBggrBgEFBQcCAjCBjRqBikNlcnR5ZmlrYXQgd3lz
-dGF3aW9ueSB6Z29kbmllIHogZG9rdW1lbnRlbTogIlBvbGl0eWthIENlcnR5ZmlrYWNqaSBkbGEg
-Um9vdENBIi4gQ2VydHlmaWthdCB3eXN0YXdpb255IHByemV6IFJvb3RDQSB3IGhpZXJhcmNoaWkg
-Q0MgU2lnbmV0LjBFBggrBgEFBQcCARY5aHR0cDovL3d3dy5zaWduZXQucGwvcmVwb3p5dG9yaXVt
-L2Rva3VtZW50eS9wY19yb290Y2EudHh0MB0GA1UdDgQWBBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAf
-BgNVHSMEGDAWgBTAm8UjDQLhpk5Iax8A6eOaFBuxrzAOBgNVHQ8BAf8EBAMCAQYwDQYJKoZIhvcN
-AQEFBQADggEBAGnY5QmYqnnO9OqFOWZxxb25UHRnaRF6IV9aaGit5BZufZj2Tq3v8L3SgE34GOoI
-cdRMMG5JEpEU4mN/Ef3oY6Eo+7HfqaPHI4KFmbDSPiK5s+wmf+bQSm0Yq5/h4ZOdcAESlLQeLSt1
-CQk2JoKQJ6pyAf6xJBgWEIlm4RXE4J3324PUiOp83kW6MDvaa1xY976WyInr4rwoLgxVl11LZeKW
-ha0RJJxJgw/NyWpKG7LWCm1fglF8JH51vZNndGYq1iKtfnrIOvLZq6bzaCiZm1EurD8HE6P7pmAB
-KK6o3C2OXlNfNIgwkDN/cDqk5TYsTkrpfriJPdxXBH8hQOkW89g=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIID/TCCA2agAwIBAgIEP4/gkTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQGEwJQTDEfMB0GA1UE
-ChMWVFAgSW50ZXJuZXQgU3AuIHogby5vLjEkMCIGA1UECxMbQ2VudHJ1bSBDZXJ0eWZpa2Fjamkg
-U2lnbmV0MR8wHQYDVQQDExZDQyBTaWduZXQgLSBDQSBLbGFzYSAxMB4XDTAzMTAxNzEyMjkwMloX
-DTExMDkyMzExMTgxN1owdjELMAkGA1UEBhMCUEwxHzAdBgNVBAoTFlRQIEludGVybmV0IFNwLiB6
-IG8uby4xJDAiBgNVBAsTG0NlbnRydW0gQ2VydHlmaWthY2ppIFNpZ25ldDEgMB4GA1UEAxMXQ0Mg
-U2lnbmV0IC0gVFNBIEtsYXNhIDEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAOJYrISEtSsd
-uHajROh5/n7NGrkpYTT9NEaPe9+ucuQ37KxIbfJwXJjgUc1dw4wCkcQ12FJarD1X6mSQ4cfN/60v
-LfKI5ZD4nhJTMKlAj1pX9ScQ/MuyvKStCbn5WTkjPhjRAM0tdwXSnzuTEunfw0Oup559y3Iqxg1c
-ExflB6cfAgMBAAGjggGXMIIBkzBBBgNVHR8EOjA4MDagNKAyhjBodHRwOi8vd3d3LnNpZ25ldC5w
-bC9yZXBvenl0b3JpdW0vY3JsL2tsYXNhMS5jcmwwDgYDVR0PAQH/BAQDAgeAMBYGA1UdJQEB/wQM
-MAoGCCsGAQUFBwMIMIHaBgNVHSAEgdIwgc8wgcwGDSsGAQQBvj8CZAoRAgEwgbowbwYIKwYBBQUH
-AgIwYxphQ2VydHlmaWthdCB3eXN0YXdpb255IHpnb2RuaWUgeiBkb2t1bWVudGVtICJQb2xpdHlr
-YSBDZXJ0eWZpa2FjamkgQ0MgU2lnbmV0IC0gWm5ha293YW5pZSBjemFzZW0iLjBHBggrBgEFBQcC
-ARY7aHR0cDovL3d3dy5zaWduZXQucGwvcmVwb3p5dG9yaXVtL2Rva3VtZW50eS9wY190c2ExXzJf
-MS5wZGYwHwYDVR0jBBgwFoAUw4Me1Vl3VPtN+1dH+cQjXNHnieMwHQYDVR0OBBYEFJdDwEqtcavO
-Yd9u9tej53vWXwNBMAkGA1UdEwQCMAAwDQYJKoZIhvcNAQEFBQADgYEAnpiQkqLCJQYXUrqMHUEz
-+z3rOqS0XzSFnVVLhkVssvXc8S3FkJIiQTUrkScjI4CToCzujj3EyfNxH6yiLlMbskF8I31JxIeB
-vueqV+s+o76CZm3ycu9hb0I4lswuxoT+q5ZzPR8Irrb51rZXlolR+7KtwMg4sFDJZ8RNgOf7tbA=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP
-MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAx
-MDQwNjEwNDkxM1oXDTIxMDQwNjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNV
-BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMSBDQTCCASIwDQYJKoZI
-hvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H887dF+2rDNbS82rDTG
-29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9EJUk
-oVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk
-3w0LBUXl0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBL
-qdReLjVQCfOAl/QMF6452F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIIN
-nvmLVz5MxxftLItyM19yejhW1ebZrgUaHXVFsculJRwSVzb9IjcCAwEAAaMzMDEw
-DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZTiFIwCwYDVR0PBAQDAgEG
-MA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE928Jj2VuX
-ZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0H
-DjxVyhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VO
-TzF2nBBhjrZTOqMRvq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2Uv
-kVrCqIexVmiUefkl98HVrhq4uz2PqYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4w
-zMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9ZIRlXvVWa
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEP
-MA0GA1UEChMGU29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAx
-MDQwNjA3Mjk0MFoXDTIxMDQwNjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNV
-BAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJhIENsYXNzMiBDQTCCASIwDQYJKoZI
-hvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3/Ei9vX+ALTU74W+o
-Z6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybTdXnt
-5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s
-3TmVToMGf+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2Ej
-vOr7nQKV0ba5cTppCD8PtOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu
-8nYybieDwnPz3BjotJPqdURrBGAgcVeHnfO+oJAjPYok4doh28MCAwEAAaMzMDEw
-DwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITTXjwwCwYDVR0PBAQDAgEG
-MA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt0jSv9zil
-zqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/
-3DEIcbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvD
-FNr450kkkdAdavphOe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6
-Tk6ezAyNlNzZRZxe7EJQY670XcSxEtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2
-ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLHllpwrN9M
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEFTCCA36gAwIBAgIBADANBgkqhkiG9w0BAQQFADCBvjELMAkGA1UEBhMCVVMx
-EDAOBgNVBAgTB0luZGlhbmExFTATBgNVBAcTDEluZGlhbmFwb2xpczEoMCYGA1UE
-ChMfU29mdHdhcmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDETMBEGA1UECxMKaG9z
-dG1hc3RlcjEgMB4GA1UEAxMXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxJTAjBgkq
-hkiG9w0BCQEWFmhvc3RtYXN0ZXJAc3BpLWluYy5vcmcwHhcNMDMwMTE1MTYyOTE3
-WhcNMDcwMTE0MTYyOTE3WjCBvjELMAkGA1UEBhMCVVMxEDAOBgNVBAgTB0luZGlh
-bmExFTATBgNVBAcTDEluZGlhbmFwb2xpczEoMCYGA1UEChMfU29mdHdhcmUgaW4g
-dGhlIFB1YmxpYyBJbnRlcmVzdDETMBEGA1UECxMKaG9zdG1hc3RlcjEgMB4GA1UE
-AxMXQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxJTAjBgkqhkiG9w0BCQEWFmhvc3Rt
-YXN0ZXJAc3BpLWluYy5vcmcwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAPB6
-rdoiLR3RodtM22LMcfwfqb5OrJNl7fwmvskgF7yP6sdD2bOfDIXhg9852jhY8/kL
-VOFe1ELAL2OyN4RAxk0rliZQVgeTgqvgkOVIBbNwgnjN6mqtuWzFiPL+NXQExq40
-I3whM+4lEiwSHaV+MYxWanMdhc+kImT50LKfkxcdAgMBAAGjggEfMIIBGzAdBgNV
-HQ4EFgQUB63oQR1/vda/G4F6P4xLiN4E0vowgesGA1UdIwSB4zCB4IAUB63oQR1/
-vda/G4F6P4xLiN4E0vqhgcSkgcEwgb4xCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdJ
-bmRpYW5hMRUwEwYDVQQHEwxJbmRpYW5hcG9saXMxKDAmBgNVBAoTH1NvZnR3YXJl
-IGluIHRoZSBQdWJsaWMgSW50ZXJlc3QxEzARBgNVBAsTCmhvc3RtYXN0ZXIxIDAe
-BgNVBAMTF0NlcnRpZmljYXRpb24gQXV0aG9yaXR5MSUwIwYJKoZIhvcNAQkBFhZo
-b3N0bWFzdGVyQHNwaS1pbmMub3JnggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcN
-AQEEBQADgYEAm/Abn8c2y1nO3fgpAIslxvi9iNBZDhQtJ0VQZY6wgSfANyDOR4DW
-iexO/AlorB49KnkFS7TjCAoLOZhcg5FaNiKnlstMI5krQmau1Qnb/vGSNsE/UGms
-1ts+QYPUs0KmGEAFUri2XzLy+aQo9Kw74VBvqnxvaaMeY5yMcKNOieY=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIIDjCCBfagAwIBAgIJAOiOtsn4KhQoMA0GCSqGSIb3DQEBBQUAMIG8MQswCQYD
-VQQGEwJVUzEQMA4GA1UECBMHSW5kaWFuYTEVMBMGA1UEBxMMSW5kaWFuYXBvbGlz
-MSgwJgYDVQQKEx9Tb2Z0d2FyZSBpbiB0aGUgUHVibGljIEludGVyZXN0MRMwEQYD
-VQQLEwpob3N0bWFzdGVyMR4wHAYDVQQDExVDZXJ0aWZpY2F0ZSBBdXRob3JpdHkx
-JTAjBgkqhkiG9w0BCQEWFmhvc3RtYXN0ZXJAc3BpLWluYy5vcmcwHhcNMDgwNTEz
-MDgwNzU2WhcNMTgwNTExMDgwNzU2WjCBvDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
-B0luZGlhbmExFTATBgNVBAcTDEluZGlhbmFwb2xpczEoMCYGA1UEChMfU29mdHdh
-cmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDETMBEGA1UECxMKaG9zdG1hc3RlcjEe
-MBwGA1UEAxMVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSUwIwYJKoZIhvcNAQkBFhZo
-b3N0bWFzdGVyQHNwaS1pbmMub3JnMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
-CgKCAgEA3DbmR0LCxFF1KYdAw9iOIQbSGE7r7yC9kDyFEBOMKVuUY/b0LfEGQpG5
-GcRCaQi/izZF6igFM0lIoCdDkzWKQdh4s/Dvs24t3dHLfer0dSbTPpA67tfnLAS1
-fOH1fMVO73e9XKKTM5LOfYFIz2u1IiwIg/3T1c87Lf21SZBb9q1NE8re06adU1Fx
-Y0b4ShZcmO4tbZoWoXaQ4mBDmdaJ1mwuepiyCwMs43pPx93jzONKao15Uvr0wa8u
-jyoIyxspgpJyQ7zOiKmqp4pRQ1WFmjcDeJPI8L20QcgHQprLNZd6ioFl3h1UCAHx
-ZFy3FxpRvB7DWYd2GBaY7r/2Z4GLBjXFS21ZGcfSxki+bhQog0oQnBv1b7ypjvVp
-/rLBVcznFMn5WxRTUQfqzj3kTygfPGEJ1zPSbqdu1McTCW9rXRTunYkbpWry9vjQ
-co7qch8vNGopCsUK7BxAhRL3pqXTT63AhYxMfHMgzFMY8bJYTAH1v+pk1Vw5xc5s
-zFNaVrpBDyXfa1C2x4qgvQLCxTtVpbJkIoRRKFauMe5e+wsWTUYFkYBE7axt8Feo
-+uthSKDLG7Mfjs3FIXcDhB78rKNDCGOM7fkn77SwXWfWT+3Qiz5dW8mRvZYChD3F
-TbxCP3T9PF2sXEg2XocxLxhsxGjuoYvJWdAY4wCAs1QnLpnwFVMCAwEAAaOCAg8w
-ggILMB0GA1UdDgQWBBQ0cdE41xU2g0dr1zdkQjuOjVKdqzCB8QYDVR0jBIHpMIHm
-gBQ0cdE41xU2g0dr1zdkQjuOjVKdq6GBwqSBvzCBvDELMAkGA1UEBhMCVVMxEDAO
-BgNVBAgTB0luZGlhbmExFTATBgNVBAcTDEluZGlhbmFwb2xpczEoMCYGA1UEChMf
-U29mdHdhcmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDETMBEGA1UECxMKaG9zdG1h
-c3RlcjEeMBwGA1UEAxMVQ2VydGlmaWNhdGUgQXV0aG9yaXR5MSUwIwYJKoZIhvcN
-AQkBFhZob3N0bWFzdGVyQHNwaS1pbmMub3JnggkA6I62yfgqFCgwDwYDVR0TAQH/
-BAUwAwEB/zARBglghkgBhvhCAQEEBAMCAAcwCQYDVR0SBAIwADAuBglghkgBhvhC
-AQ0EIRYfU29mdHdhcmUgaW4gdGhlIFB1YmxpYyBJbnRlcmVzdDAwBglghkgBhvhC
-AQQEIxYhaHR0cHM6Ly9jYS5zcGktaW5jLm9yZy9jYS1jcmwucGVtMDIGCWCGSAGG
-+EIBAwQlFiNodHRwczovL2NhLnNwaS1pbmMub3JnL2NlcnQtY3JsLnBlbTAhBgNV
-HREEGjAYgRZob3N0bWFzdGVyQHNwaS1pbmMub3JnMA4GA1UdDwEB/wQEAwIBBjAN
-BgkqhkiG9w0BAQUFAAOCAgEAtM294LnqsgMrfjLp3nI/yUuCXp3ir1UJogxU6M8Y
-PCggHam7AwIvUjki+RfPrWeQswN/2BXja367m1YBrzXU2rnHZxeb1NUON7MgQS4M
-AcRb+WU+wmHo0vBqlXDDxm/VNaSsWXLhid+hoJ0kvSl56WEq2dMeyUakCHhBknIP
-qxR17QnwovBc78MKYiC3wihmrkwvLo9FYyaW8O4x5otVm6o6+YI5HYg84gd1GuEP
-sTC8cTLSOv76oYnzQyzWcsR5pxVIBcDYLXIC48s9Fmq6ybgREOJJhcyWR2AFJS7v
-dVkz9UcZFu/abF8HyKZQth3LZjQl/GaD68W2MEH4RkRiqMEMVObqTFoo5q7Gt/5/
-O5aoLu7HaD7dAD0prypjq1/uSSotxdz70cbT0ZdWUoa2lOvUYFG3/B6bzAKb1B+P
-+UqPti4oOxfMxaYF49LTtcYDyeFIQpvLP+QX4P4NAZUJurgNceQJcHdC2E3hQqlg
-g9cXiUPS1N2nGLar1CQlh7XU4vwuImm9rWgs/3K1mKoGnOcqarihk3bOsPN/nOHg
-T7jYhkalMwIsJWE3KpLIrIF0aGOHM3a9BX9e1dUCbb2v/ypaqknsmHlHU5H2DjRa
-yaXG67Ljxay2oHA1u8hRadDytaIybrw/oDc5fHE2pgXfDBLkFqfF1stjo5VwP+YE
-o2A=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIICqDCCAZACCQCHc5eBqnSyFTANBgkqhkiG9w0BAQUFADAWMRQwEgYDVQQDEwt0
-aGlua3BhZC1wZTAeFw0xMTA3MTExNzU4NTVaFw0yMTA3MDgxNzU4NTVaMBYxFDAS
-BgNVBAMTC3RoaW5rcGFkLXBlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
-AQEAtS6SgGwg+IEzl85WsXc2TnfLPZZTjoNGL/tb/fLIyaEx1/YopEyo0zSsenyA
-95RFvPs4fK6+onmiRLq3YgYtbxSbv83/no/ggMkhMZw7Il2cguoxaiTpf6Z+zGNA
-nX98M7ig5ISPnq+06Sw869NEAsYbiReNgazAJM53RdfSqZsok1A5CyXd3XUERLNm
-UoCw917DNhu+N3xed/1t376yW4Bo/kkyrn1CRTG8jxi5xe+tCsDTWSjJzkS0e6WJ
-MVK6PJxP0if7lw28Qh0zd9orR26HDbQ6TPpAF2sj7UhPleA4xkKjtiir3nITHkRR
-bMvyd22gDAPIhZsF19X+dua8UwIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQCm+aKc
-dvClUqqhe/wACAHn+NOLGAYK6kLVJaWUzvcSFMU9M6iyJllpxO0BwhdxXrmLtG72
-lermeKh4wTiREP16Qdh0nNbtiB4cOAzBvHNzj6RymGAL50RBugu0zlY3wDUxDGS8
-M/7c4ZAB/BvieA09o2tnUGmL7PijDGPLE5bclIwVAkXaeXKa6bG0kJnr0ndxX68d
-AJGNoSFTdxBMPw6gau77w7wQULFKFj4xTEKkYngNDsKERc/u/yrYRfkeehehRNmT
-BcKocK4dDPPPzcJ12AjBnYtxitTRlJyXAkNVjLMTSg7lAU36JjNkvXqhSqDQJf04
-yW2ZnchxqK6f0gWO
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJO
-TDEeMBwGA1UECgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFh
-dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oX
-DTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMCTkwxHjAcBgNVBAoMFVN0YWF0IGRl
-ciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5lZGVybGFuZGVuIFJv
-b3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ5291
-qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8Sp
-uOUfiUtnvWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPU
-Z5uW6M7XxgpT0GtJlvOjCwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvE
-pMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiile7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp
-5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCROME4HYYEhLoaJXhena/M
-UGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpICT0ugpTN
-GmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy
-5V6548r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv
-6q012iDTiIJh8BIitrzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEK
-eN5KzlW/HdXZt1bv8Hb/C3m1r737qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6
-B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMBAAGjgZcwgZQwDwYDVR0TAQH/
-BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcCARYxaHR0cDov
-L3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
-HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqG
-SIb3DQEBCwUAA4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLyS
-CZa59sCrI2AGeYwRTlHSeYAz+51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen
-5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwjf/ST7ZwaUb7dRUG/kSS0H4zpX897
-IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaNkqbG9AclVMwWVxJK
-gnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfkCpYL
-+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxL
-vJxxcypFURmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkm
-bEgeqmiSBeGCc1qb3AdbCG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvk
-N1trSt8sV4pAWja63XVECDdCcAz+3F4hoKOKwJCcaNpQ5kUQR3i2TtJlycM33+FC
-Y7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoVIPVVYpbtbZNQvOSqeK3Z
-ywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm66+KAQ==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJO
-TDEeMBwGA1UEChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFh
-dCBkZXIgTmVkZXJsYW5kZW4gUm9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEy
-MTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4wHAYDVQQKExVTdGFhdCBkZXIgTmVk
-ZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxhbmRlbiBSb290IENB
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFtvszn
-ExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw71
-9tV2U02PjLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MO
-hXeiD+EwR+4A5zN9RGcaC1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+U
-tFE5A3+y3qcym7RHjm+0Sq7lr7HcsBthvJly3uSJt3omXdozSVtSnA71iq3DuD3o
-BmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn622r+I/q85Ej0ZytqERAh
-SQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRVHSAAMDww
-OgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMv
-cm9vdC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA
-7Jbg0zTBLL9s+DANBgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k
-/rvuFbQvBgwp8qiSpGEN/KtcCFtREytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzm
-eafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbwMVcoEoJz6TMvplW0C5GUR5z6
-u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3ynGQI0DvDKcWy
-7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR
-iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzEl
-MCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMp
-U3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQw
-NjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBoMQswCQYDVQQGEwJVUzElMCMGA1UE
-ChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZp
-ZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqGSIb3
-DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf
-8MOh2tTYbitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN
-+lq2cwQlZut3f+dZxkqZJRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0
-X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVmepsZGD3/cVE8MC5fvj13c7JdBmzDI1aa
-K4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSNF4Azbl5KXZnJHoe0nRrA
-1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HFMIHCMB0G
-A1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fR
-zt0fhvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0
-YXJmaWVsZCBUZWNobm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBD
-bGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8w
-DQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGsafPzWdqbAYcaT1epoXkJKtv3
-L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLMPUxA2IGvd56D
-eruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
-xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynp
-VSJYACPq4xJDKVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEY
-WQPJIrSPnNVeKtelttQKbfi3QBFGmh95DmK/D5fs4C8fF5Q=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEW
-MBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwg
-Q2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNh
-dGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0NjM2WhcNMzYwOTE3MTk0NjM2WjB9
-MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRkLjErMCkGA1UECxMi
-U2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMgU3Rh
-cnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUA
-A4ICDwAwggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZk
-pMyONvg45iPwbm2xPN1yo4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rf
-OQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/C
-Ji/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/deMotHweXMAEtcnn6RtYT
-Kqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt2PZE4XNi
-HzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMM
-Av+Z6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w
-+2OqqGwaVLRcJXrJosmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+
-Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3
-Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVcUjyJthkqcwEKDwOzEmDyei+B
-26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT37uMdBNSSwID
-AQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
-FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9j
-ZXJ0LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3Js
-LnN0YXJ0Y29tLm9yZy9zZnNjYS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFM
-BgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUHAgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0
-Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRwOi8vY2VydC5zdGFy
-dGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYgU3Rh
-cnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlh
-YmlsaXR5LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2Yg
-dGhlIFN0YXJ0Q29tIENlcnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFp
-bGFibGUgYXQgaHR0cDovL2NlcnQuc3RhcnRjb20ub3JnL3BvbGljeS5wZGYwEQYJ
-YIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBGcmVlIFNT
-TCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOCAgEAFmyZ
-9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8
-jhvh3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUW
-FjgKXlf2Ysd6AgXmvB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJz
-ewT4F+irsfMuXGRuczE6Eri8sxHkfY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1
-ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3fsNrarnDy0RLrHiQi+fHLB5L
-EUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZEoalHmdkrQYu
-L6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
-yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuC
-O3NJo2pXh5Tl1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6V
-um0ABj6y6koQOdjQK/W/7HW/lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkySh
-NOsF/5oirpt9P/FlUQqmMGqz9IgcgA38corog14=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEezCCA2OgAwIBAgIQNxkY5lNUfBq1uMtZWts1tzANBgkqhkiG9w0BAQUFADCB
-rjELMAkGA1UEBhMCREUxIDAeBgNVBAgTF0JhZGVuLVd1ZXJ0dGVtYmVyZyAoQlcp
-MRIwEAYDVQQHEwlTdHV0dGdhcnQxKTAnBgNVBAoTIERldXRzY2hlciBTcGFya2Fz
-c2VuIFZlcmxhZyBHbWJIMT4wPAYDVQQDEzVTLVRSVVNUIEF1dGhlbnRpY2F0aW9u
-IGFuZCBFbmNyeXB0aW9uIFJvb3QgQ0EgMjAwNTpQTjAeFw0wNTA2MjIwMDAwMDBa
-Fw0zMDA2MjEyMzU5NTlaMIGuMQswCQYDVQQGEwJERTEgMB4GA1UECBMXQmFkZW4t
-V3VlcnR0ZW1iZXJnIChCVykxEjAQBgNVBAcTCVN0dXR0Z2FydDEpMCcGA1UEChMg
-RGV1dHNjaGVyIFNwYXJrYXNzZW4gVmVybGFnIEdtYkgxPjA8BgNVBAMTNVMtVFJV
-U1QgQXV0aGVudGljYXRpb24gYW5kIEVuY3J5cHRpb24gUm9vdCBDQSAyMDA1OlBO
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA2bVKwdMz6tNGs9HiTNL1
-toPQb9UY6ZOvJ44TzbUlNlA0EmQpoVXhOmCTnijJ4/Ob4QSwI7+Vio5bG0F/WsPo
-TUzVJBY+h0jUJ67m91MduwwA7z5hca2/OnpYH5Q9XIHV1W/fuJvS9eXLg3KSwlOy
-ggLrra1fFi2SU3bxibYs9cEv4KdKb6AwajLrmnQDaHgTncovmwsdvs91DSaXm8f1
-XgqfeN+zvOyauu9VjxuapgdjKRdZYgkqeQd3peDRF2npW932kKvimAoA0SVtnteF
-hy+S8dF2g08LOlk3KC8zpxdQ1iALCvQm+Z845y2kuJuJja2tyWp9iRe79n+Ag3rm
-7QIDAQABo4GSMIGPMBIGA1UdEwEB/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEG
-MCkGA1UdEQQiMCCkHjAcMRowGAYDVQQDExFTVFJvbmxpbmUxLTIwNDgtNTAdBgNV
-HQ4EFgQUD8oeXHngovMpttKFswtKtWXsa1IwHwYDVR0jBBgwFoAUD8oeXHngovMp
-ttKFswtKtWXsa1IwDQYJKoZIhvcNAQEFBQADggEBAK8B8O0ZPCjoTVy7pWMciDMD
-pwCHpB8gq9Yc4wYfl35UvbfRssnV2oDsF9eK9XvCAPbpEW+EoFolMeKJ+aQAPzFo
-LtU96G7m1R08P7K9n3frndOMusDXtk3sU5wPBG7qNWdX4wple5A64U8+wwCSersF
-iXOMy6ZNwPv2AtawB6MDwidAnwzkhYItr5pCHdDHjfhA7p0GVxzZotiAFP7hYy0y
-h9WUUpY6RsZxlj33mA6ykaqP2vROJAA5VeitF7nTNCtKqUDMFypVZUF0Qn71wK/I
-k63yGFs9iQzbRzkk+OBM8h+wPQrKBU6JIRrjKpms/H+h8Q8bHz2eBIPdltkdOpQ=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBk
-MQswCQYDVQQGEwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0
-YWwgQ2VydGlmaWNhdGUgU2VydmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3Qg
-Q0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4MTgyMjA2MjBaMGQxCzAJBgNVBAYT
-AmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGlnaXRhbCBDZXJ0aWZp
-Y2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIICIjAN
-BgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9
-m2BtRsiMMW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdih
-FvkcxC7mlSpnzNApbjyFNDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/
-TilftKaNXXsLmREDA/7n29uj/x2lzZAeAR81sH8A25Bvxn570e56eqeqDFdvpG3F
-EzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkCb6dJtDZd0KTeByy2dbco
-kdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn7uHbHaBu
-HYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNF
-vJbNcA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo
-19AOeCMgkckkKmUpWyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjC
-L3UcPX7ape8eYIVpQtPM+GP+HkM5haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJW
-bjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNYMUJDLXT5xp6mig/p/r+D5kNX
-JLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYwHQYDVR0hBBYw
-FDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j
-BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzc
-K6FptWfUjNP9MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzf
-ky9NfEBWMXrrpA9gzXrzvsMnjgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7Ik
-Vh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQMbFamIp1TpBcahQq4FJHgmDmHtqB
-sfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4HVtA4oJVwIHaM190e
-3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtlvrsR
-ls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ip
-mXeascClOS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HH
-b6D0jqTsNFFbjCYDcKF31QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksf
-rK/7DZBaZmBwXarNeNQk7shBoJMBkpxqnvy5JMWzFYJ+vq6VK+uxwNrjAWALXmms
-hFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCyx/yP2FS1k2Kdzs9Z+z0Y
-zirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMWNY6E0F/6
-MBr1mmz0DlP5OlvRHA==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNV
-BAYTAkNIMRUwEwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2ln
-biBHb2xkIENBIC0gRzIwHhcNMDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBF
-MQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMR8wHQYDVQQDExZT
-d2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIIC
-CgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUqt2/8
-76LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+
-bbqBHH5CjCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c
-6bM8K8vzARO/Ws/BtQpgvd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqE
-emA8atufK+ze3gE/bk3lUIbLtK/tREDFylqM2tIrfKjuvqblCqoOpd8FUrdVxyJd
-MmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvRAiTysybUa9oEVeXBCsdt
-MDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuendjIj3o02y
-MszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69y
-FGkOpeUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPi
-aG59je883WX0XaxR7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxM
-gI93e2CaHt+28kgeDrpOVG2Y4OGiGqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCB
-qTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUWyV7
-lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64OfPAeGZe6Drn
-8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
-L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe6
-45R88a7A3hfm5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczO
-UYrHUDFu4Up+GC9pWbY9ZIEr44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5
-O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOfMke6UiI0HTJ6CVanfCU2qT1L2sCC
-bwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6mGu6uLftIdxf+u+yv
-GPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxpmo/a
-77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCC
-hdiDyyJkvC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid3
-92qgQmwLOM7XdVAyksLfKzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEpp
-Ld6leNcG2mqeSz53OiATIgHQv2ieY2BrNU0LbbqhPcCT4H8js1WtciVORvnSFu+w
-ZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6LqjviOvrv1vA+ACOzB2+htt
-Qc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UE
-BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWdu
-IFBsYXRpbnVtIENBIC0gRzIwHhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAw
-WjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dpc3NTaWduIEFHMSMwIQYDVQQD
-ExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQAD
-ggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu669y
-IIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2Htn
-IuJpX+UFeNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+
-6ixuEFGSzH7VozPY1kneWCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5ob
-jM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIoj5+saCB9bzuohTEJfwvH6GXp43gOCWcw
-izSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/68++QHkwFix7qepF6w9fl
-+zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34TaNhxKFrY
-zt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaP
-pZjydomyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtF
-KwH3HBqi7Ri6Cr2D+m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuW
-ae5ogObnmLo2t/5u7Su9IPhlGdpVCX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMB
-AAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0O
-BBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCvzAeHFUdvOMW0
-ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW
-IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUA
-A4ICAQAIhab1Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0
-uMoI3LQwnkAHFmtllXcBrqS3NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+
-FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4U99REJNi54Av4tHgvI42Rncz7Lj7
-jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8KV2LwUvJ4ooTHbG/
-u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl9x8D
-YSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1
-puEa+S1BaYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXa
-icYwu+uPyyIIoK6q8QNsOktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbG
-DI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSYMdp08YSTcU1f+2BY0fvEwW2JorsgH51x
-kcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAciIfNAChs0B0QTwoRqjt8Z
-Wr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UE
-BhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWdu
-IFNpbHZlciBDQSAtIEcyMB4XDTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0Nlow
-RzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMY
-U3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
-MIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644N0Mv
-Fz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7br
-YT7QbNHm+/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieF
-nbAVlDLaYQ1HTWBCrpJH6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH
-6ATK72oxh9TAtvmUcXtnZLi2kUpCe2UuMGoM9ZDulebyzYLs2aFK7PayS+VFheZt
-eJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5hqAaEuSh6XzjZG6k4sIN/
-c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5FZGkECwJ
-MoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRH
-HTBsROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTf
-jNFusB3hB48IHpmccelM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb6
-5i/4z3GcRm25xBWNOHkDRUjvxF3XCO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOB
-rDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU
-F6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRBtjpbO8tFnb0c
-wpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
-cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIB
-AHPGgeAn0i0P4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShp
-WJHckRE1qTodvBqlYJ7YH39FkWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9
-xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L3XWgwF15kIwb4FDm3jH+mHtwX6WQ
-2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx/uNncqCxv1yL5PqZ
-IseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFaDGi8
-aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2X
-em1ZqSqPe97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQR
-dAtq/gsD/KNVV4n+SsuuWxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/
-OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJDIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+
-hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ubDgEj8Z+7fNzcbBGXJbLy
-tGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/
-MQswCQYDVQQGEwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmlj
-YXRpb24gQXV0aG9yaXR5MB4XDTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1ow
-PzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dvdmVybm1lbnQgUm9vdCBDZXJ0aWZp
-Y2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIB
-AJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qNw8XR
-IePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1q
-gQdW8or5BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKy
-yhwOeYHWtXBiCAEuTk8O1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAts
-F/tnyMKtsc2AtJfcdgEWFelq16TheEfOhtX7MfP6Mb40qij7cEwdScevLJ1tZqa2
-jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wovJ5pGfaENda1UhhXcSTvx
-ls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7Q3hub/FC
-VGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHK
-YS1tB6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoH
-EgKXTiCQ8P8NHuJBO9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThN
-Xo+EHWbNxWCWtFJaBYmOlXqYwZE8lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1Ud
-DgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNVHRMEBTADAQH/MDkGBGcqBwAE
-MTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg209yewDL7MTqK
-UWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
-TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyf
-qzvS/3WXy6TjZwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaK
-ZEk9GhiHkASfQlK3T8v+R0F2Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFE
-JPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlUD7gsL0u8qV1bYH+Mh6XgUmMqvtg7
-hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6QzDxARvBMB1uUO07+1
-EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+HbkZ6Mm
-nD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WX
-udpVBrkk7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44Vbnz
-ssQwmSNOXfJIoRIM3BKQCZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDe
-LMDDav7v3Aun+kbfYNucpllQdSNpc5Oy+fwC00fmcc4QAu4njIT/rEUNE1yDMuAl
-pYYsfPQS
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjEL
-MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV
-BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0
-Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYwMTEyMTQzODQzWhcNMjUxMjMxMjI1
-OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i
-SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UEAxMc
-VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD
-ggEPADCCAQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jf
-tMjWQ+nEdVl//OEd+DFwIxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKg
-uNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2J
-XjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQXa7pIXSSTYtZgo+U4+lK
-8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7uSNQZu+99
-5OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1Ud
-EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3
-kUrL84J6E1wIqzCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy
-dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6
-Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz
-JTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290
-Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
-TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iS
-GNn3Bzn1LL4GdXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprt
-ZjluS5TmVfwLG4t3wVMTZonZKNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8
-au0WOB9/WIFaGusyiC2y8zl3gK9etmF1KdsjTYjKUCjLhdLTEKJZbtOTVAB6okaV
-hgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kPJOzHdiEoZa5X6AeI
-dUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfkvQ==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjEL
-MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNV
-BAsTGVRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0
-Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYwMTEyMTQ0MTU3WhcNMjUxMjMxMjI1
-OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIgR21i
-SDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UEAxMc
-VEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQAD
-ggEPADCCAQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJW
-Ht4bNwcwIi9v8Qbxq63WyKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+Q
-Vl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo6SI7dYnWRBpl8huXJh0obazovVkdKyT2
-1oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZuV3bOx4a+9P/FRQI2Alq
-ukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk2ZyqBwi1
-Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1Ud
-EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NX
-XAek0CSnwPIA1DCB7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRy
-dXN0Y2VudGVyLmRlL2NybC92Mi90Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6
-Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBUcnVzdENlbnRlciUyMENsYXNz
-JTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21iSCxPVT1yb290
-Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
-TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlN
-irTzwppVMXzEO2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8
-TtXqluJucsG7Kv5sbviRmEb8yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6
-g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9IJqDnxrcOfHFcqMRA/07QlIp2+gB
-95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal092Y+tTmBvTwtiBj
-S+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc5A==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDXDCCAsWgAwIBAgICA+owDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYTAkRF
-MRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFU
-QyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJI
-MSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBDbGFzcyAyIENBMSkwJwYJKoZIhvcN
-AQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05ODAzMDkxMTU5NTla
-Fw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFtYnVy
-ZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9y
-IFNlY3VyaXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1
-c3RDZW50ZXIgQ2xhc3MgMiBDQTEpMCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVA
-dHJ1c3RjZW50ZXIuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANo46O0y
-AClxgwENv4wB3NrGrTmkqYov1YtcaF9QxmL1Zr3KkSLsqh1R1z2zUbKDTl3LSbDw
-TFXlay3HhQswHJJOgtTKAu33b77c4OMUuAVT8pr0VotanoWT0bSCVq5Nu6hLVxa8
-/vhYnvgpjbB7zXjJT6yLZwzxnPv8V5tXXE8NAgMBAAGjazBpMA8GA1UdEwEB/wQF
-MAMBAf8wDgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3
-LnRydXN0Y2VudGVyLmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0G
-CSqGSIb3DQEBBAUAA4GBAIRS+yjf/x91AbwBvgRWl2p0QiQxg/lGsQaKic+WLDO/
-jLVfenKhhQbOhvgFjuj5Jcrag4wGrOs2bYWRNAQ29ELw+HkuCkhcq8xRT3h2oNms
-Gb0q0WkEKJHKNhAngFdb0lz1wlurZIFjdFH0l7/NEij3TWZ/p/AcASZ4smZHcFFk
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDXDCCAsWgAwIBAgICA+swDQYJKoZIhvcNAQEEBQAwgbwxCzAJBgNVBAYTAkRF
-MRAwDgYDVQQIEwdIYW1idXJnMRAwDgYDVQQHEwdIYW1idXJnMTowOAYDVQQKEzFU
-QyBUcnVzdENlbnRlciBmb3IgU2VjdXJpdHkgaW4gRGF0YSBOZXR3b3JrcyBHbWJI
-MSIwIAYDVQQLExlUQyBUcnVzdENlbnRlciBDbGFzcyAzIENBMSkwJwYJKoZIhvcN
-AQkBFhpjZXJ0aWZpY2F0ZUB0cnVzdGNlbnRlci5kZTAeFw05ODAzMDkxMTU5NTla
-Fw0xMTAxMDExMTU5NTlaMIG8MQswCQYDVQQGEwJERTEQMA4GA1UECBMHSGFtYnVy
-ZzEQMA4GA1UEBxMHSGFtYnVyZzE6MDgGA1UEChMxVEMgVHJ1c3RDZW50ZXIgZm9y
-IFNlY3VyaXR5IGluIERhdGEgTmV0d29ya3MgR21iSDEiMCAGA1UECxMZVEMgVHJ1
-c3RDZW50ZXIgQ2xhc3MgMyBDQTEpMCcGCSqGSIb3DQEJARYaY2VydGlmaWNhdGVA
-dHJ1c3RjZW50ZXIuZGUwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBALa0wTUF
-Lg2N7KBAahwOJ6ZQkmtQGwfeLud2zODa/ISoXoxjaitN2U4CdhHBC/KNecoAtvGw
-Dtf7pBc9r6tpepYnv68zoZoqWarEtTcI8hKlMbZD9TKWcSgoq40oht+77uMMfTDW
-w1Krj10nnGvAo+cFa1dJRLNu6mTP0o56UHd3AgMBAAGjazBpMA8GA1UdEwEB/wQF
-MAMBAf8wDgYDVR0PAQH/BAQDAgGGMDMGCWCGSAGG+EIBCAQmFiRodHRwOi8vd3d3
-LnRydXN0Y2VudGVyLmRlL2d1aWRlbGluZXMwEQYJYIZIAYb4QgEBBAQDAgAHMA0G
-CSqGSIb3DQEBBAUAA4GBABY9xs3Bu4VxhUafPiCPUSiZ7C1FIWMjWwS7TJC4iJIE
-Tb19AaM/9uzO8d7+feXhPrvGq14L3T2WxMup1Pkm5gZOngylerpuw3yCGdHHsbHD
-2w2Om0B8NwvxXej9H5CIpQ5ON2QhqE6NtJ/x3kit1VYYUimLRzQSCdS7kjXvD9s0
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezEL
-MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV
-BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1
-c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAeFw0wOTA5MDkwODE1MjdaFw0yOTEy
-MzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNUQyBUcnVzdENlbnRl
-ciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0ExKDAm
-BgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqG
-SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF
-5+cvAqBNLaT6hdqbJYUtQCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYv
-DIRlzg9uwliT6CwLOunBjvvya8o84pxOjuT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8v
-zArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+EutCHnNaYlAJ/Uqwa1D7KRT
-yGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1M4BDj5yj
-dipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBh
-MB8GA1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMB
-Af8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI
-4jANBgkqhkiG9w0BAQUFAAOCAQEAg8ev6n9NCjw5sWi+e22JLumzCecYV42Fmhfz
-dkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+KGwWaODIl0YgoGhnYIg5IFHY
-aAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhKBgePxLcHsU0G
-DeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV
-CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPH
-LQNjO9Po5KIqwoIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTEL
-MAkGA1UEBhMCREUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNV
-BAsTG1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1
-c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcNMDYwMzIyMTU1NDI4WhcNMjUxMjMx
-MjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1c3RDZW50ZXIg
-R21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYwJAYD
-VQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcN
-AQEBBQADggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSR
-JJZ4Hgmgm5qVSkr1YnwCqMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3T
-fCZdzHd55yx4Oagmcw6iXSVphU9VDprvxrlE4Vc93x9UIuVvZaozhDrzznq+VZeu
-jRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtwag+1m7Z3W0hZneTvWq3z
-wZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9OgdwZu5GQ
-fezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYD
-VR0jBBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAO
-BgNVHQ8BAf8EBAMCAYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0G
-CSqGSIb3DQEBBQUAA4IBAQAo0uCG1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X1
-7caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/CyvwbZ71q+s2IhtNerNXxTPqYn
-8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3ghUJGooWMNjs
-ydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT
-ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/
-2TYcuiUaUj0a7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJE
-SzEVMBMGA1UEChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQg
-Um9vdCBDQTAeFw0wMTA0MDUxNjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNV
-BAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJuZXQxHTAbBgNVBAsTFFREQyBJbnRl
-cm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxLhA
-vJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20jxsNu
-Zp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a
-0vnRrEvLznWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc1
-4izbSysseLlJ28TQx5yc5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGN
-eGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcD
-R0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZIAYb4QgEBBAQDAgAHMGUG
-A1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMMVERDIElu
-dGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxME
-Q1JMMTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3
-WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAw
-HQYDVR0OBBYEFGxkAcf9hW2syNqeUAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJ
-KoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4IBAQBO
-Q8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540mgwV5dOy0uaOX
-wTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+
-2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm89
-9qNLPg7kbWzbO0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0
-jUNAE4z9mQNUecYu6oah9jrUCbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38
-aQNiuJkFBT1reBK9sG9l
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJE
-SzEMMAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEw
-ODM5MzBaFw0zNzAyMTEwOTA5MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNU
-REMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
-MIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuHnEz9pPPEXyG9VhDr
-2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0zY0s
-2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItU
-GBxIYXvViGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKj
-dGqPqcNiKXEx5TukYBdedObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+r
-TpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/
-BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB5DCB4TCB3gYIKoFQgSkB
-AQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5kay9yZXBv
-c2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRl
-ciBmcmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEu
-MS4xLiBDZXJ0aWZpY2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIg
-T0lEIDEuMi4yMDguMTY5LjEuMS4xLjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1Ud
-HwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEMMAoGA1UEChMDVERDMRQwEgYD
-VQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYmaHR0cDovL2Ny
-bC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy
-MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZ
-J2cdUBVLc647+RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqG
-SIb2fQdBAAQQMA4bCFY2LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACrom
-JkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4A9G28kNBKWKnctj7fAXmMXAnVBhO
-inxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYscA+UYyAFMP8uXBV2Y
-caaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9AOoB
-mbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQ
-YqbsFbS1AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9
-BKNDLdr8C2LqL19iUw==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDLTCCApagAwIBAgIBADANBgkqhkiG9w0BAQQFADCB0TELMAkGA1UEBhMCWkEx
-FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMRowGAYD
-VQQKExFUaGF3dGUgQ29uc3VsdGluZzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBT
-ZXJ2aWNlcyBEaXZpc2lvbjEkMCIGA1UEAxMbVGhhd3RlIFBlcnNvbmFsIEZyZWVt
-YWlsIENBMSswKQYJKoZIhvcNAQkBFhxwZXJzb25hbC1mcmVlbWFpbEB0aGF3dGUu
-Y29tMB4XDTk2MDEwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgdExCzAJBgNVBAYT
-AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEa
-MBgGA1UEChMRVGhhd3RlIENvbnN1bHRpbmcxKDAmBgNVBAsTH0NlcnRpZmljYXRp
-b24gU2VydmljZXMgRGl2aXNpb24xJDAiBgNVBAMTG1RoYXd0ZSBQZXJzb25hbCBG
-cmVlbWFpbCBDQTErMCkGCSqGSIb3DQEJARYccGVyc29uYWwtZnJlZW1haWxAdGhh
-d3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA1GnX1LCUZFtx6UfY
-DFG26nKRsIRefS0Nj3sS34UldSh0OkIsYyeflXtL734Zhx2G6qPduc6WZBrCFG5E
-rHzmj+hND3EfQDimAKOHePb5lIZererAXnbr2RSjXW56fAylS1V/Bhkpf56aJtVq
-uzgkCGqYx7Hao5iR/Xnb5VrEHLkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zAN
-BgkqhkiG9w0BAQQFAAOBgQDH7JJ+Tvj1lqVnYiqk8E0RYNBvjWBYYawmu1I1XAjP
-MPuoSpaKH2JCI4wXD/S6ZJwXrEcp352YXtJsYHFcoqzceePnbgBHH7UNKOgCneSa
-/RP0ptl8sfjcXyMmCZGAc9AUG95DqYMl8uacLxXK/qarigd1iwzdUYRr5PjRznei
-gQ==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkEx
-FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
-VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
-biBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UEAxMYVGhhd3RlIFByZW1pdW0gU2Vy
-dmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZlckB0aGF3dGUuY29t
-MB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYTAlpB
-MRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsG
-A1UEChMUVGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRp
-b24gU2VydmljZXMgRGl2aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNl
-cnZlciBDQTEoMCYGCSqGSIb3DQEJARYZcHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNv
-bTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2aovXwlue2oFBYo847kkE
-VdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIhUdib0GfQ
-ug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMR
-uHM/qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG
-9w0BAQQFAAOBgQAmSCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUI
-hfzJATj/Tb7yFkJD57taRvvBxhEf8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JM
-pAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7tUCemDaYj+bvLpgcUQg==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDEL
-MAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMp
-IDIwMDcgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAi
-BgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMjAeFw0wNzExMDUwMDAw
-MDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
-d3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBGb3Ig
-YXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9v
-dCBDQSAtIEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/
-BebfowJPDQfGAFG6DAJSLSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6
-papu+7qzcMBniKI11KOasf2twu8x+qi58/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8E
-BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUmtgAMADna3+FGO6Lts6K
-DPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUNG4k8VIZ3
-KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41ox
-XZ3Krr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCB
-rjELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
-Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
-MDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNV
-BAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0wODA0MDIwMDAwMDBa
-Fw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhhd3Rl
-LCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9u
-MTgwNgYDVQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXpl
-ZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEcz
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsr8nLPvb2FvdeHsbnndm
-gcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2AtP0LMqmsywCPLLEHd5N/8
-YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC+BsUa0Lf
-b1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS9
-9irY7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2S
-zhkGcuYMXDhpxwTWvGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUk
-OQIDAQABo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNV
-HQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJKoZIhvcNAQELBQADggEBABpA
-2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweKA3rD6z8KLFIW
-oCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
-t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7c
-KUGRIjxpp7sC8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fM
-m7v/OeZWYdMKp8RcTGB7BXcmer/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZu
-MdRAGmI0Nj81Aa6sY6A=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCB
-qTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMf
-Q2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIw
-MDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNV
-BAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3MDAwMDAwWhcNMzYw
-NzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5j
-LjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYG
-A1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
-IG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqG
-SIb3DQEBAQUAA4IBDwAwggEKAoIBAQCsoPD7gFnUnMekz52hWXMJEEUMDSxuaPFs
-W0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ1CRfBsDMRJSUjQJib+ta
-3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGcq/gcfomk
-6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6
-Sk/KaAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94J
-NqR32HuHUETVPm4pafs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBA
-MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XP
-r87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUFAAOCAQEAeRHAS7ORtvzw6WfU
-DW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeEuzLlQRHAd9mz
-YJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
-xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2
-/qxAeeWsEG89jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/
-LHbTY5xZ3Y+m4Q6gLkH3LpVHz7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7
-jVaMaA==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkEx
-FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYD
-VQQKExRUaGF3dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlv
-biBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEm
-MCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wHhcNOTYwODAx
-MDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT
-DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3
-dGUgQ29uc3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNl
-cyBEaXZpc2lvbjEZMBcGA1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3
-DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQAD
-gY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl/Kj0R1HahbUgdJSGHg91
-yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg71CcEJRCX
-L+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGj
-EzARMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG
-7oWDTSEwjsrZqG9JGubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6e
-QNuozDJ0uW8NxuOzRAvZim+aKZuZGCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZ
-qdq5snUb9kLy78fyGPmJvKP/iiMucEc=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIICoTCCAgqgAwIBAgIBADANBgkqhkiG9w0BAQQFADCBizELMAkGA1UEBhMCWkEx
-FTATBgNVBAgTDFdlc3Rlcm4gQ2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzAN
-BgNVBAoTBlRoYXd0ZTEdMBsGA1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAd
-BgNVBAMTFlRoYXd0ZSBUaW1lc3RhbXBpbmcgQ0EwHhcNOTcwMTAxMDAwMDAwWhcN
-MjAxMjMxMjM1OTU5WjCBizELMAkGA1UEBhMCWkExFTATBgNVBAgTDFdlc3Rlcm4g
-Q2FwZTEUMBIGA1UEBxMLRHVyYmFudmlsbGUxDzANBgNVBAoTBlRoYXd0ZTEdMBsG
-A1UECxMUVGhhd3RlIENlcnRpZmljYXRpb24xHzAdBgNVBAMTFlRoYXd0ZSBUaW1l
-c3RhbXBpbmcgQ0EwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANYrWHhhRYZT
-6jR7UZztsOYuGA7+4F+oJ9O0yeB8WU4WDnNUYMF/9p8u6TqFJBU820cEY8OexJQa
-Wt9MevPZQx08EHp5JduQ/vBR5zDWQQD9nyjfeb6Uu522FOMjhdepQeBMpHmwKxqL
-8vg7ij5FrHGSALSQQZj7X+36ty6K+Ig3AgMBAAGjEzARMA8GA1UdEwEB/wQFMAMB
-Af8wDQYJKoZIhvcNAQEEBQADgYEAZ9viwuaHPUCDhjc1fR/OmsMMZiCouqoEiYbC
-9RAIDb/LogWK0E02PvTX72nGXuSwlG9KuefeW4i2e9vjJ+V2w/A1wcu1J5szedyQ
-pgCed/r8zSeUQhac0xxo7L9c3eWpexAKMnRUEzGLhQOEkbdYATAUOK8oyvyxUBkZ
-CayJSdM=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRS
-MRgwFgYDVQQHDA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJp
-bGltc2VsIHZlIFRla25vbG9qaWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSw
-VEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ryb25payB2ZSBLcmlwdG9sb2ppIEFy
-YcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNVBAsMGkthbXUgU2Vy
-dGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUgS8O2
-ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAe
-Fw0wNzA4MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIx
-GDAWBgNVBAcMD0dlYnplIC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmls
-aW1zZWwgdmUgVGVrbm9sb2ppayBBcmHFn3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBU
-QUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZlIEtyaXB0b2xvamkgQXJh
-xZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2FtdSBTZXJ0
-aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7Zr
-IFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIB
-IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4h
-gb46ezzb8R1Sf1n68yJMlaCQvEhOEav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yK
-O7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1xnnRFDDtG1hba+818qEhTsXO
-fJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR6Oqeyjh1jmKw
-lZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL
-hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQID
-AQABo0IwQDAdBgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/
-BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmP
-NOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4N5EY3ATIZJkrGG2AA1nJrvhY0D7t
-wyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLTy9LQQfMmNkqblWwM
-7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYhLBOh
-gLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5n
-oN+J1q2MdqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUs
-yZyQ2uypQjyttgI=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOc
-UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx
-c8SxMQswCQYDVQQGDAJUUjEPMA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykg
-MjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8
-dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMxMDI3MTdaFw0xNTAz
-MjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsgU2Vy
-dGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYD
-VQQHDAZBTktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kg
-xLBsZXRpxZ9pbSB2ZSBCaWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEu
-xZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7
-XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GXyGl8hMW0kWxsE2qkVa2k
-heiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8iSi9BB35J
-YbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5C
-urKZ8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1
-JuTm5Rh8i27fbMx4W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51
-b0dewQIDAQABoxAwDjAMBgNVHRMEBTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV
-9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46sWrv7/hg0Uw2ZkUd82YCdAR7
-kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxEq8Sn5RTOPEFh
-fEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy
-B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdA
-aLX/7KfS0zgYnNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKS
-RGQDJereW26fyfJOrN3H
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOc
-UktUUlVTVCBFbGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sx
-c8SxMQswCQYDVQQGEwJUUjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xS
-S1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kg
-SGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcNMDUxMTA3MTAwNzU3
-WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVrdHJv
-bmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJU
-UjEPMA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSw
-bGV0acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWe
-LiAoYykgS2FzxLFtIDIwMDUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
-AQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqeLCDe2JAOCtFp0if7qnef
-J1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKIx+XlZEdh
-R3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJ
-Qv2gQrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGX
-JHpsmxcPbe9TmJEr5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1p
-zpwACPI2/z7woQ8arBT9pmAPAgMBAAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58S
-Fq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8GA1UdEwEB/wQFMAMBAf8wDQYJ
-KoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/nttRbj2hWyfIvwq
-ECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4
-Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFz
-gw2lGh1uEpJ+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotH
-uFEJjOp9zYhys2AzsfAKRO8P9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LS
-y3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5UrbnBEI=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCB
-kzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
-Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
-dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZBgNVBAMTElVUTiAtIERBVEFDb3Jw
-IFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBaMIGTMQswCQYDVQQG
-EwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYD
-VQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cu
-dXNlcnRydXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjAN
-BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6
-E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ysraP6LnD43m77VkIVni5c7yPeIbkFdicZ
-D0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlowHDyUwDAXlCCpVZvNvlK
-4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA9P4yPykq
-lXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulW
-bfXv33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQAB
-o4GrMIGoMAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRT
-MtGzz3/64PGgXYVOktKeRR20TzA9BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3Js
-LnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dDLmNybDAqBgNVHSUEIzAhBggr
-BgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3DQEBBQUAA4IB
-AQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft
-Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyj
-j98C5OBxOvG0I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVH
-KWss5nbZqSl9Mt3JNjy9rjXxEZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv
-2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwPDPafepE39peC4N1xaf92P2BNPM/3
-mfnGV/TJVTl4uix5yaaIK/QI
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCB
-rjELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
-Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
-dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0BgNVBAMTLVVUTi1VU0VSRmlyc3Qt
-Q2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05OTA3MDkxNzI4NTBa
-Fw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAV
-BgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5l
-dHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UE
-AxMtVVROLVVTRVJGaXJzdC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWls
-MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3B
-YHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIxB8dOtINknS4p1aJkxIW9
-hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8om+rWV6l
-L8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLm
-SGHGTPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM
-1tZUOt4KpLoDd7NlyP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws
-6wIDAQABo4G5MIG2MAsGA1UdDwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1Ud
-DgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNVHR8EUTBPME2gS6BJhkdodHRw
-Oi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGllbnRBdXRoZW50
-aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH
-AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u
-7mFVbwQ+zznexRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0
-xtcgBEXkzYABurorbs6q15L+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQ
-rfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarVNZ1yQAOJujEdxRBoUp7fooXFXAim
-eOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZw7JHpsIyYdfHb0gk
-USeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCB
-lzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2Ug
-Q2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
-dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3Qt
-SGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgxOTIyWjCBlzELMAkG
-A1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEe
-MBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8v
-d3d3LnVzZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdh
-cmUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn
-0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlIwrthdBKWHTxqctU8EGc6Oe0rE81m65UJ
-M6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFdtqdt++BxF2uiiPsA3/4a
-MXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8i4fDidNd
-oI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqI
-DsjfPe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9Ksy
-oUhbAgMBAAGjgbkwgbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYD
-VR0OBBYEFKFyXyYbKJhDlV0HN9WFlp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0
-dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LUhhcmR3YXJlLmNy
-bDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUFBwMGBggrBgEF
-BQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
-//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28Gpgoiskli
-CE7/yMgUsogWXecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gE
-CJChicsZUN/KHAG8HQQZexB2lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t
-3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kniCrVWFCVH/A7HFe7fRQ5YiuayZSS
-KqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67nfhmqA==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
-IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
-BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
-aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
-9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIyMjM0OFoXDTE5MDYy
-NTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
-azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
-YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
-Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
-cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9Y
-LqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIiGQj4/xEjm84H9b9pGib+
-TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCmDuJWBQ8Y
-TfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0
-LBwGlN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLW
-I8sogTLDAHkY7FkXicnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPw
-nXS3qT6gpf+2SQMT2iLM7XGCK5nPOrf1LXLI
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0
-IFZhbGlkYXRpb24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAz
-BgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9y
-aXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG
-9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAwMTk1NFoXDTE5MDYy
-NjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0d29y
-azEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
-YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRw
-Oi8vd3d3LnZhbGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNl
-cnQuY29tMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDOOnHK5avIWZJV16vY
-dA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVCCSRrCl6zfN1SLUzm1NZ9
-WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7RfZHM047QS
-v4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9v
-UJSZSWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTu
-IYEZoDJJKPTEjlbVUjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwC
-W/POuZ6lcg5Ktz885hZo+L7tdEy8W9ViH0Pd
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
-c3MgMSBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
-MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
-emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
-DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
-FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMg
-UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
-YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
-MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgdk4xWArzZbxpvUjZudVYK
-VdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIqWpDBucSm
-Fc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQID
-AQABMA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0J
-h9ZrbWB85a7FkCMMXErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2ul
-uIncrKTdcu1OofdPvAbT6shkdHvClUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68
-DzFc6PLZ
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
-cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
-LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
-aWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
-VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
-aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
-bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
-IENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAN2E1Lm0+afY8wR4
-nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/EbRrsC+MO
-8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjV
-ojYJrKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjb
-PG7PoBMAGrgnoeS+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP2
-6KbqxzcSXKMpHgLZ2x87tNcPVkeBFQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vr
-n5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAq2aN17O6x5q25lXQBfGfMY1a
-qtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/Ny9Sn2WCVhDr4
-wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3
-ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrs
-pSCAaWihT37ha88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4
-E1Z5T21Q6huwtVexN2ZYI/PcD98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkG
-A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
-cyAxIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
-MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
-BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmlt
-YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0f
-zGVuDLDQVoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHi
-TkVWaR94AoDa3EeRKbs2yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0G
-CSqGSIb3DQEBBQUAA4GBAFgVKTk8d6PaXCUDfGD67gmZPCcQcMgMCeazh88K4hiW
-NWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n0a3hUKw8fGJLj7qE1xIV
-Gx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZRjXZ+Hxb
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0Ns
-YXNzIDIgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBH
-MjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y
-aXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazAe
-Fw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJVUzEX
-MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGlj
-IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMx
-KGMpIDE5OTggVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25s
-eTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29yazCBnzANBgkqhkiG9w0B
-AQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjxnNuX6Zr8wgQGE75fUsjM
-HiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRCwiNPStjw
-DqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cC
-AwEAATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9ji
-nb3/7aHmZuovCfTK1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAX
-rXfMSTWqz9iP0b63GJZHc2pUIjRkLbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnIn
-jBJ7xUS0rg==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVy
-aVNpZ24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24s
-IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNp
-Z24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
-eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJBgNV
-BAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNp
-Z24gVHJ1c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIElu
-Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24g
-Q2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAt
-IEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArwoNwtUs22e5LeWU
-J92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6tW8UvxDO
-JxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUY
-wZF7C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9o
-koqQHgiBVrKtaaNS0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjN
-qWm6o+sdDZykIKbBoMXRRkwXbdKsZj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/E
-Srg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0JhU8wI1NQ0kdvekhktdmnLfe
-xbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf0xwLRtxyID+u
-7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU
-sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RI
-sH/7NiXaldDxJBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTP
-cjnhsUPgKM+351psE2tJs//jGHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIICPDCCAaUCEC0b/EoXjaOR6+f/9YtFvgswDQYJKoZIhvcNAQECBQAwXzELMAkG
-A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
-cyAyIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
-MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
-BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAyIFB1YmxpYyBQcmlt
-YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQC2WoujDWojg4BrzzmH9CETMwZMJaLtVRKXxaeAufqDwSCg+i8VDXyh
-YGt+eSz6Bg86rvYbb7HS/y8oUl+DfUvEerf4Zh+AVPy3wo5ZShRXRtGak75BkQO7
-FYCTXOvnzAhsPz6zSvz/S2wj1VCCJkQZjiPDceoZJEcEnnW/yKYAHwIDAQABMA0G
-CSqGSIb3DQEBAgUAA4GBAIobK/o5wXTXXtgZZKJYSi034DNHD6zt96rbHuSLBlxg
-J8pFUs4W7z8GZOeUaHxgMxURaa+dYo2jA1Rrpr7l7gUYYAS/QoD90KioHgE796Nc
-r6Pc5iaAIzy4RHT3Cq5Ji2F4zCS/iIqnDupzGUH9TQPwiNHleI2lKk/2lw0Xd8rY
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
-c3MgMyBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
-MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
-emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
-DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
-FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMg
-UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
-YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
-MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCOFoUgRm1HP9SFIIThbbP4
-pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71lSk8UOg0
-13gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwID
-AQABMA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSk
-U01UbSuvDV1Ai2TT1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7i
-F6YM40AIOw7n60RzKprxaZLvcRTDOaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpY
-oJ2daZH9
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
-cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
-LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
-aWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
-VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
-aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
-bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
-IENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMu6nFL8eB8aHm8b
-N3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1EUGO+i2t
-KmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGu
-kxUccLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBm
-CC+Vk7+qRy+oRpfwEuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJ
-Xwzw3sJ2zq/3avL6QaaiMxTJ5Xpj055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWu
-imi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAERSWwauSCPc/L8my/uRan2Te
-2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5fj267Cz3qWhMe
-DGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
-/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565p
-F4ErWjfJXir0xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGt
-TxzhT5yvDwyd93gN2PQ1VoDat20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjEL
-MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
-ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2ln
-biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
-U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
-aXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjELMAkG
-A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJp
-U2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwg
-SW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2ln
-biBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5
-IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8Utpkmw4tXNherJI9/gHm
-GUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGzrl0Bp3ve
-fLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUw
-AwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJ
-aW1hZ2UvZ2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYj
-aHR0cDovL2xvZ28udmVyaXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMW
-kf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMDA2gAMGUCMGYhDBgmYFo4e1ZC
-4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIxAJw9SDkjOVga
-FRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCB
-yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
-ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJp
-U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxW
-ZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0
-aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCByjEL
-MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZW
-ZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2ln
-biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJp
-U2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9y
-aXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvJAgIKXo1
-nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKzj/i5Vbex
-t0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIz
-SdhDY2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQG
-BO+QueQA5N06tRn/Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+
-rCpSx4/VBEnkjWNHiDxpg8v+R70rfk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/
-NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8E
-BAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEwHzAH
-BgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
-aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKv
-MzEzMA0GCSqGSIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzE
-p6B4Eq1iDkVwZMXnl2YtmAl+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y
-5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKEKQsTb47bDN0lAtukixlE0kF6BWlK
-WE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiCKm0oHw0LxOXnGiYZ
-4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vEZV8N
-hnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkG
-A1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFz
-cyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2
-MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVowXzELMAkGA1UEBhMCVVMxFzAVBgNV
-BAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmlt
-YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUAA4GN
-ADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhE
-BarsAx94f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/is
-I19wKTakyYbnsZogy1Olhec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0G
-CSqGSIb3DQEBBQUAA4GBABByUqkFFBkyCEHwxWsKzH4PIRnN5GfcX6kb5sroc50i
-2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWXbj9T/UWZYB2oK0z5XqcJ
-2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/D/xwzoiQ
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDAjCCAmsCEDKIjprS9esTR/h/xCA3JfgwDQYJKoZIhvcNAQEFBQAwgcExCzAJ
-BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xh
-c3MgNCBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcy
-MTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3Jp
-emVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMB4X
-DTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVTMRcw
-FQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgNCBQdWJsaWMg
-UHJpbWFyeSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEo
-YykgMTk5OCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5
-MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEB
-AQUAA4GNADCBiQKBgQC68OTP+cSuhVS5B1f5j8V/aBH4xBewRNzjMHPVKmIquNDM
-HO0oW369atyzkSTKQWI8/AIBvxwWMZQFl3Zuoq29YRdsTjCG8FE3KlDHqGKB3FtK
-qsGgtG7rL+VXxbErQHDbWk2hjh+9Ax/YA9SPTJlxvOKCzFjomDqG04Y48wApHwID
-AQABMA0GCSqGSIb3DQEBBQUAA4GBAIWMEsGnuVAVess+rLhDityq3RS6iYF+ATwj
-cSGIL4LcY/oCRaxFWdcqWERbt5+BO5JoPeI3JPV7bI92NZYJqFmduc4jq3TWg/0y
-cyfYaT5DdPauxYma51N86Xv2S/PBZYPejYqcPIiNOVn8qj8ijaHBZlCBckztImRP
-T8qAkbYp
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQsw
-CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZl
-cmlTaWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWdu
-LCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlT
-aWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
-dHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQswCQYD
-VQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlT
-aWduIFRydXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJ
-bmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWdu
-IENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
-LSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAK3LpRFpxlmr8Y+1
-GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaStBO3IFsJ
-+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0Gbd
-U6LM8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLm
-NxdLMEYH5IBtptiWLugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XY
-ufTsgsbSPZUd5cBPhMnZo0QoBmrXRazwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/
-ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEAj/ola09b5KROJ1WrIhVZPMq1
-CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXttmhwwjIDLk5Mq
-g6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm
-fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c
-2NU8Qh0XwRJdRTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/
-bLvSHgCwIe34QWKCudiyxLtGUPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCB
-vTELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQL
-ExZWZXJpU2lnbiBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJp
-U2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MTgwNgYDVQQDEy9W
-ZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAe
-Fw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJVUzEX
-MBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0
-IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9y
-IGF1dGhvcml6ZWQgdXNlIG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNh
-bCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
-AAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj1mCOkdeQmIN65lgZOIzF
-9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGPMiJhgsWH
-H26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+H
-LL729fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN
-/BMReYTtXlT2NJ8IAfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPT
-rJ9VAMf2CGqUuV/c4DPxhGD5WycRtPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1Ud
-EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0GCCsGAQUFBwEMBGEwX6FdoFsw
-WTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2Oa8PPgGrUSBgs
-exkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
-DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4
-sAPmLGd75JR3Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+
-seQxIcaBlVZaDrHC1LGmWazxY8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz
-4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTxP/jgdFcrGJ2BtMQo2pSXpXDrrB2+
-BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+PwGZsY6rp2aQW9IHR
-lRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4mJO3
-7M2CYfE45k+XmCpajQ==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBr
-MQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRl
-cm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
-bW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2WhcNMjIwNjI0MDAxNjEyWjBrMQsw
-CQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5h
-dGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1l
-cmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h
-2mCxlCfLF9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4E
-lpF7sDPwsRROEW+1QK8bRaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdV
-ZqW1LS7YgFmypw23RuwhY/81q6UCzyr0TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq
-299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI/k4+oKsGGelT84ATB+0t
-vz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzsGHxBvfaL
-dXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQD
-AgEGMB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUF
-AAOCAQEAX/FBfXxcCLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcR
-zCSs00Rsca4BIGsDoo8Ytyk6feUWYFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3
-LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pzzkWKsKZJ/0x9nXGIxHYdkFsd
-7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBuYQa7FkKMcPcw
-++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
-398znM/jra6O1I7mT1GvFpLgXPYHDw==
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMC
-VVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBD
-ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9v
-dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDAxMDExMTY0MTI4WhcNMjEwMTE0
-MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dlbGxzIEZhcmdvMSww
-KgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEvMC0G
-A1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEi
-MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n13
-5zHCLielTWi5MbqNQ1mXx3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHE
-SxP9cMIlrCL1dQu3U+SlK93OvRw6esP3E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4O
-JgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5OEL8pahbSCOz6+MlsoCu
-ltQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4jsNtlAHCE
-AQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMB
-AAGjYTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcB
-CzAyMDAGCCsGAQUFBwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRw
-b2xpY3kwDQYJKoZIhvcNAQEFBQADggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo
-7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrvm+0fazbuSCUlFLZWohDo7qd/
-0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0ROhPs7fpvcmR7
-nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx
-x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ
-33ZwmVxwQ023tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMx
-IDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxs
-cyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9v
-dCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDcxMjEzMTcwNzU0WhcNMjIxMjE0
-MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdl
-bGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQD
-DC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkw
-ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+r
-WxxTkqxtnt3CxC5FlAM1iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjU
-Dk/41itMpBb570OYj7OeUt9tkTmPOL13i0Nj67eT/DBMHAGTthP796EfvyXhdDcs
-HqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8bJVhHlfXBIEyg1J55oNj
-z7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiBK0HmOFaf
-SZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/Slwxl
-AgMBAAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqG
-KGh0dHA6Ly9jcmwucGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0P
-AQH/BAQDAgHGMB0GA1UdDgQWBBQmlRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0j
-BIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGBi6SBiDCBhTELMAkGA1UEBhMC
-VVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNX
-ZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg
-Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEB
-ALkVsUSRzCPIK0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd
-/ZDJPHV3V3p9+N701NX3leZ0bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pB
-A4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSljqHyita04pO2t/caaH/+Xc/77szWn
-k4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+esE2fDbbFwRnzVlhE9
-iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJtylv
-2G0xffX8oRAHh84vWdw+WNs=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCB
-gjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEk
-MCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRY
-UmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQxMTAxMTcx
-NDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMxHjAcBgNVBAsTFXd3
-dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkgU2Vy
-dmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
-dXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS6
-38eMpSe2OAtp87ZOqCwuIR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCP
-KZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMxfoArtYzAQDsRhtDLooY2YKTVMIJt2W7Q
-DxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FEzG+gSqmUsE3a56k0enI4
-qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqsAxcZZPRa
-JSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNVi
-PvryxS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0P
-BAQDAgGGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASs
-jVy16bYbMDYGA1UdHwQvMC0wK6ApoCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0
-eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQEwDQYJKoZIhvcNAQEFBQAD
-ggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc/Kh4ZzXxHfAR
-vbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
-qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLa
-IR9NmXmd4c8nnxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSy
-i6mx5O+aGtA9aZnuqCij4Tyz8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQ
-O+7ETPTsJ3xCwnR8gooJybQDJbw=
------END CERTIFICATE-----
------BEGIN CERTIFICATE-----
-MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEh
-MB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBE
-YWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3
-MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkGA1UEBhMCVVMxITAfBgNVBAoTGFRo
-ZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28gRGFkZHkgQ2xhc3Mg
-MiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQADggEN
-ADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCA
-PVYYYwhv2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6w
-wdhFJ2+qN1j3hybX2C32qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXi
-EqITLdiOr18SPaAIBQi2XKVlOARFmR6jYGB0xUGlcmIbYsUfb18aQr4CUWWoriMY
-avx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmYvLEHZ6IVDd2gWMZEewo+
-YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0OBBYEFNLE
-sNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h
-/t2oatTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5
-IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmlj
-YXRpb24gQXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQAD
-ggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wimPQoZ+YeAEW5p5JYXMP80kWNy
-OO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKtI3lpjbi2Tc7P
-TMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
-HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mER
-dEr/VxqHD3VILs9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5Cuf
-ReYNnyicsbkqWletNw+vHX/bvZ8=
------END CERTIFICATE-----
diff --git a/res/values-FR/custom.xml b/res/values-FR/custom.xml
deleted file mode 100644
index 1fc54f5d0..000000000
--- a/res/values-FR/custom.xml
+++ /dev/null
@@ -1,25 +0,0 @@
-
-
-
- EEEE d MMM HH:mm
-
- Linphone
- Linphone
- Démarrage
- Enregistré comme %s
- Erreur lors de l\'enregistrement en tant que %s
- Linphone %s téléphone compatible SIP (rfc 3261) sous licence GPL V2\n http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications
-
- Cet assistant va vous aider à configurer un compte SIP pour vos appels.
- Créer un compte linphone.org
- J\'ai déjà un compte linphone.org
- J\'ai déjà un compte SIP
- Entrez votre nom d\'utilisateur et votre mot de passe linphone.org
- Entrez votre nom d\'utilisateur, votre mot de passe et le domaine de votre compte SIP
-
- nom d\'utilisateur
-
-
- @string/tunnel_mode_entry_value_disabled
-
-
diff --git a/res/values-FR/strings.xml b/res/values-FR/strings.xml
deleted file mode 100644
index 6f902ca3b..000000000
--- a/res/values-FR/strings.xml
+++ /dev/null
@@ -1,374 +0,0 @@
-
-
- Désactiver
-
- Tunnel
- Hôte
- Port
- Mode
-
-
-
- - désactivé
- - 3G seulement
- - toujours
- - auto
-
-
- Appel audio en cours
- Appel en pause
- Appel vidéo en cours
-
- Pas prêt pour un nouvel appel
- Mauvais contact : %s
- Annuler vérification %s
- Vérifier %s
- Encrypté
-
- Démarrage…
- Une erreur est survenue pendant l\'acceptation d\'un appel
-
- Erreur lors de l\'ajout de l\'appel
- Transfert commencé
- Transférer l\'appel vers
- Nouvel appel
- Reprendre l\'appel
- Impossible de reprendre l\'appel mis en pause par votre correspondant
- Montrer les détails
-
- Attention : le service n\'est pas prêt
-
- Fermer
-
- conf
- actif
- en pause
- mis en pause par le correspondant
-
- entrant
- sonnant
- sortant
-
- Silence
- HP
- Bluetooth
-
- Annuler
- Ajouter un appel
- Transférer appel
-
- Raccrocher
- Fusionner
- Transférer
- Vidéo
-
- Dialpad
-
- Utiliser volume logiciel
-
- Utiliser ipv6 au lieu de ipv4
-
- Erreur pendant l\'acceptation de l\'appel
- %s vous apelle
- Accepter
- Refuser
- Inconnu
-
- Réseau
- Transport
- Utiliser des ports aléatoires
- Port SIP à utiliser si port aléatoire désactivé
- Au moins un est requis
-
-
- Enregistré avec succès
- Erreur
- Commencer
- Application pas prête
-
- Ajouter un compte
- Aucun numéro trouvé pour %s
- Filtrer contacts
- Numéros de %s
- Supprimer ce compte
- Utiliser par défaut
- Calibration de l\'annulateur d\'écho
- Utiliser la caméra en façade
- Vidéo
- Préférences
- Codecs
-
- Paramètres vidéo
- Partager ma vidéo
- Accepter appels vidéo
- Envoyer ma vidéo automatiquement
- Toujours accepter les demandes d\'appels vidéo
- Initier les appels en vidéo
- Toujours envoyer des demandes d\'appels vidéo
- Activer la vidéo
- Activer les animations
- Remplacer + par 00
- iLBC peut être indisponible suivant le processeur ARM et la version d\'Android.
- Annulateur d\'écho
- Démarrer au lancement du téléphone
- Outbound proxy
- Codecs
- Time out de communication
- Time out d\'appel entrant
- Port ou plage de port vidéo
- Port ou plage de port audio
- Port ou plage (min-max) pour l\'audio
- Port ou plage (min-max) pour la video
- Timeout (en secondes) pour les appels entrants
-
- Activer les traces de débogage
- Reporter un problème
- Décrivez le problème ici
- Erreur pendant la génération du rapport d\'incident
- Traces non trouvées.
- En train de lire les traces, peut prendre du temps…
- Envoyer le rapport avec…
- A propos
- Audio
- Quitter
- Préfixe
- Avancé
- Paramètres
- Serveur mandataire
- Domaine*
- Mot de passe*
- Nom d\'utilisateur*
- Compte SIP
- Mauvais nom d\'utilisateur
- Mauvais mot de passe
- Mauvais domaine
- Mauvais paramètre(s)
- Dialer
- Contact
- Erreur lors de l\'appel de %s
- Oui
- Non
- Annuler
- Continuer
- Ne plus me le rapeller
- %s, voulez-vous aller dans les paramètres ?
- Démarrage de la calibration de l\'annulateur d\'écho
- Impossible de démarrer un nouvel appel, un appel est en cours
- Historique
- Impossible de construire l\'adresse de destination depuis [%s]
- Nettoyer
- Impossible de récupérer les paramètres de l\'appel
- Impossible de créer les paramètres par défaut de l\'appel
- Impossible d\'inviter l\'adresse [%s]
-
- démarré
- Supprime l\'écho entendu de l\'autre côté
- Serveur Stun
- Activer ICE
- Un serveur STUN doit être configuré pour utiliser ICE
- Calibration…
- Calibré [%s ms]
- Pas d\'écho
- échoué
- Entrez votre nom d\'utilisateur et votre mot de passe pour vous connecter au service.
- Nom d\'utilisateur
- Mot de passe
- Connexion
- Entrez votre nom d\'utilisateur et votre mot de passe
- Impossible de se connecter; Vérifiez vos informations de connexion et réessayez
-
- Le codec AMR codec peut ne pas être disponible sur votre téléphone
- Encryption
- Aucune
-
- Codec désactivé, compilez l\'application depuis le code source pour l\'activer
- Codec désactivé, compilez l\'application depuis le code source pour l\'activer
-
- Comptes SIP
- Wi-Fi uniquement
- Activer les notifications poussées
-
- Une erreur est survenue, réessayez plus tard.
- Serveur injoignable, vérifiez votre connexion internet.
- Ce nom d\'utilisateur est déjà pris.
- Votre nom d\'utilisateur n\'est pas valide.
- Votre courriel n\'est pas valide.
- Votre mot de passe n\'est pas valide (6 caractères min).
- Les mots de passe sont différents.
-
- Adresse IP ou nom de domaine du serveur mandataire SIP (facultatif)
- Faire passer tous les appels via le serveur mandataire SIP
- Exemple: john si votre compte est john@sip.example.org
- sip.example.org si votre compte est john@sip.example.org
-
- Supprimer
- Chat
- Appel
- Ajouter aux contacts
- Enregistré
- Pas Enregistré
- Enregistrement en cours
- Enregistrement échoué
-
- Numéro ou adresse
- Conférence
- Appel entrant
- Brouillon
- Entrez une adresse SIP…
- Aucun appel dans votre historique.
- Aucun appel manqué dans votre historique.
- Aucun contact dans votre carnet d\'adresse.
- Aucun contact SIP dans votre carnet d\'adresse.
- Aucun historique de chat.
-
- Audio
- Vidéo
- Codec :
- Bande passante envoi :
- Bande passante réception :
- Connexion ICE :
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Assistant de configuration des comptes
- Appliquer
- mot de passe
- domaine
- confirmez le mot de passe
- courriel
- Créer le compte
- Un courriel vous à été envoyé. Pour activer votre compte, vous devez cliquer sur le lien qu\'il contient. Une fois ceci fait, revenez ici et cliquez sur le bouton ci-dessous.
- Vérifier
- Votre compte n\'a pas encore été validé.
- Votre compte à été validé.
-
- Historique
- Contacts
- Options
- Chat
- A propos
-
- Annuler
- Retour
- Allons-y
-
- + Chat
- Modifier
- Annuler
- Valider
- Tous
- SIP
- + Contact
- Tous
- Manqués
- Supprimer
-
- Transfert
- + Appel
- Vidéo
- Micro
- HP
- Route
- Ecouteur
- Bluetooth
- Options
-
- Envoyer
- Img
- Envoi en cours…
-
- Mise à jour de l\'appel
- Votre correspondant souhaite ajouter la vidéo à l\'appel en cours.
- Accepter
- Refuser
-
- Petite
- Moyenne
- Grande
- Taille réelle
- Sauvegarder l\'image
- Copier le texte
- Texte copié dans le presse papier
- Choisissez la source
- Image sauvegardée
- Erreur, image non sauvegardée
-
- Amis
- Nouveaux amis
- Toujours accepter les nouvelles demandes d\'amis
- Requête d\'ami
- voudrait être partager son status avec vous et voir le votre.
-
- Calibration de l\'annulateur d\'écho en cours
- Serveur de partage
-
- Supprimer contact
- Adresse SIP
- Numéro de téléphone
- Prénom
- Nom
-
- Compte principal
- Nom d\'affichage
- Nom d\'utilisateur
- Expiration
-
- Envoyer les DTMFs RFC2833
- Envoyer les DTMFs en SIP INFO
-
- Appel rejeté
- Utilisateur non trouvé
- Paramètres média incompatibles
- Votre correspondant à un débit faible, la vidéo ne peut démarrer
- Le réseau n\'est pas joignable
-
- Aujourd\'hui
- Hier
-
- Manqué
- Émis
- Reçu
-
- Actif en arrière plan
-
- Télécharger
- Téléchargement échoué. Vérifiez votre connexion internet ou reéssayez plus tard.
-
diff --git a/res/values-RU/custom.xml b/res/values-RU/custom.xml
deleted file mode 100755
index f920a5a65..000000000
--- a/res/values-RU/custom.xml
+++ /dev/null
@@ -1,23 +0,0 @@
-
-
-
- EEEE d MMM HH:mm
-
- Linphone
- Linphone
- Загружается
- Зарегистрирован в %s
- Ошибка регистрации в %s
- Linphone %s SIP (rfc 3261) совместимый телефон под GPL V2 лицензией\n http://www.linphone.org\n\nИнструкции\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications
-
- Этот помощник поможет Вам настроить учётную запись SIP для звонков.
- Создать учётную запись на linphone.org
- Уже есть учётная запись на linphone.org
- Уже есть учётная запись SIP
- Введите имя пользователя и пароль учётной записи linphone.org
- Введите имя пользователя, пароль и сервер учётной записи SIP
-
-
- @string/tunnel_mode_entry_value_disabled
-
-
\ No newline at end of file
diff --git a/res/values-RU/strings.xml b/res/values-RU/strings.xml
deleted file mode 100755
index 0a501cfa1..000000000
--- a/res/values-RU/strings.xml
+++ /dev/null
@@ -1,423 +0,0 @@
-
-
- Деактивировать
-
- Туннель
- Сервер
- Порт
- Режим
-
-
-
- - выключено
- - только 3G
- - всегда
- - авто
-
-
- Идёт Аудио звонок
- Звонок на Паузе
- Идёт Видео звонок
-
- Невозможно совершить новый звонок
- Плохой контакт: %s
- Сброс подтверждён %s
- Подтвердить %s
- Зашифровано
-
- Загружается…
- При приёме звонка произошла ошибка
-
- Ошибка при добавлении звонка
- Начат перевод
- Перевод звонка на
- Новый звонок
- Возобновить звонок
- Невозможно возобновить звонок поставленный на паузу оппонентом
- Показать детали
-
- Внимание : сервис не готов
-
- Закрыть
-
- конф
- активен
- на паузе
- поставлен на паузу оппонентом
-
- входящий
- звонящий
- в процессе
-
- Выключить микрофон
- Громкоговоритель
- Bluetooth
-
- Отменить
- Добавить звонок
- Перевести звонок
-
- Присоединиться к конференции
- Покинуть конференцию
- Прервать конференцию
-
- Положить трубку
- Объединить
- Перевести
- Видео
-
- Клавиатура
-
- Конференция
- Вы часть её
- Выйти
- Вы вышли
- Войти
-
- Audio хаки
- Использовать хаки спец. режима
- 0=MODE_NORMAL (по умолчанию), 2=MODE_IN_CALL
- Использовать хак API маршрутизации
- Использовать аудио хак Galaxy S
-
- Использовать "программную" громкость
-
- Использовать ipv6 вместо ipv4
-
- Ошибка во время приёма входящего звонка
- %s звонит Вам
- Принять
- Отклонить
- Неизвестнвй
-
- Сеть
- Транспорт
- UDP
- TCP
- TLS
- Использовать случайный порт
- SIP порт занят
- По крайней мере 1 протокол обязателен
-
- Регистрация успешна
- Ошибка
- Начать
- Приложение не готово
-
- Добавить учётную запись
- Телефонных номеров для %s не найдено
- Фильтровать контакты
- Телефонные номера %s
- Удалить учётную запись
- Использовать как основную
- Настроить шумоподавление
- Использовать фронтальную камеру
- Видео
- Настройки
- H263
- MPEG4
- H264
- Кодеки
- pref_video_codecs_key
- Показать клавиатуру
- Лицевая/Задняя камера
- Высокое разрешение
- Низкое разрешение
- Сменить разрешение
- Включить/Выключить камеру
- Запретить камеру
- Разрешить камеру
- Прекратить звонок
- Настройки видео
- Совмесный доступ к камере
- Принимать входящие видео звонки
- Автоматически посылать видео
- Всегда принимать видео запросы
- Начинать видео звонки
- Всегда посылать видео запросы
- Разрешить видео
- Разрешить анимацию
- Заменить + на 00
- iLBC может быть недоступно в Вашей версии ARM процессора и Android OS.
- Шумоподавление
- Запускаться с системой
- Исходящий прокси
- pcma
- pcmu
- gsm
- g722
- amr
- amr-wb
- ilbc
- speex 8 Khz
- speex 16 Khz
- silk 8 Khz
- silk 12 Khz
- silk 16 Khz
- silk 24 Khz
- g729
- Кодеки
- Таймаут соединения
- Таймаут входящего соединения
- Видео порт или диапазон портов
- Аудио порт или диапазон портов
- Видео порт или диапазон портов (минимум-максимум)
- Аудио порт или диапазон портов (минимум-максимум)
- Таймаут входящего соединения (в секундах)
- Разместить звонок
-
- Отладка
- Сообщить об ошибке
- Опишите проблему
- Ошибка при генерации отчёта об ошибке
- Логи не найдены.
- Читаю логи, может занять время…
- Послать отчёт об ошибке с…
- О программе
- Аудио
- Выход
- Префикс
- Продвинутые
- Настройки
- Прокси
- Сервер*
- Пароль*
- Имя пользователя*
- Имя SIP
- неправильное имя поьлзователя
- неправильный пароль
- Неправильный сервер
- Неправильные настройки
- Клавиатура
- Контакт
- Невозможно набрать %s
- Да
- Нет
- Убрать
- Продолжить
- Больше не напоминать
- %s, хотите ли вы перейти к настройкам ?
- Начинаем автоматическую настройку шумоподавления
- Невозможно начать новый звонок, звонок уже идёт
- История
- Невозможно создать адрес получателя из [%s]
- Очистить
- Невозможно получить параметры звонка
- Невозможно создать параметры звонка по умолчанию
- Невозможно пригласить получателя [%s]
-
- начат
- Удаляет эхо, слышимое другой стороной
- Сервер Stun
- Разрешить ICE
- Сервер STUN должен быть настроен чтобы использовать ICE
- Настраиваем…
- Настроено за [%s ms]
- Нет эханеудавшийся
- Введите имя пользователя и пароль для соединения с сервисом.
- Имя пользователя
- Пароль
- Соединиться
- Пожалуйста введите имя пользователя и пароль
- Невозможно соединиться; проверьте имя пользователя и пароль и попробуйте ещё
-
- Кодек AMR возможно отсутствует в телефоне
- VP8
- Шифрование потока
- Отсутствует
- SRTP
- ZRTP
-
- Кодек поддерживается только если построено из исходников
- Кодек поддерживается только если построено из исходников
-
- Учётные записи SIP
- Использовать только wifi
- Разрешить серверные уведомления
-
- Произошла ошибка, попробуйте повторить позже.
- Сервер недоступен, проверьте Ваше соединение с интернетом.
- Это имя пользователя уже использовано.
- Имя пользователя недопустимо.
- Недопустимый адрес электронной почты.
- Недопустимый пароль (минимум 6 знаков).
- Введённые пароли отличаются.
-
- Имя сервера SIP прокси или адрес ip (необязательно)
- Отправить все звонки через SIP прокси
- Например: john если Ваш адрес john@sip.example.org
- sip.example.org если Ваш адрес john@sip.example.org
-
- Удалить
- Чат
- Звонок
- Добавить к контактам
- Зарегистрирован
- Незарегистрирован
- В процессе регистрации
- Ошибка регистрации
-
- Номер или Адрес
- Конференция
- Входящий звонок
- Черновик
- Введите адрес SIP для чата…
- Нет звонков в вашей истории.
- Нет пропущенных звонков в вашей истории.
- Нет контакта в Вашей адресной книге.
- Нет SIP контакта в Вашей адресной книге.
- Нет истории чата.
-
- Аудио
- Видео
- Кодек:
- Полоса пропускания загрузки:
- Полоса пропускания скачивания:
- Подключение ICE:
-
-
- Кнопка добавить к контактам
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Помощник Настройки учётной записи
- Применить
- имя пользователя
- пароль
- сервер
- подтвердить пароль
- адрес электронной почты
- Создать учётную запись
- Электронное письмо было послано на указанный адрес. Пройдите по ссылке из этого письма, чтобы активировать Вашу учётную запись. После этого вернитесь сюда и нажмите на кнопку выше.
- Проверить
- Ваша учётная запись ещё не подтверждена.
- Ваша учётная запись подтверждена.
-
- История
- Контакты
- Настройки
- Чат
- О программе
-
- Отменить
- Назад
- Далее
-
- Новый разговор
- Редактировать
- Отменить
- ОК
- Все
- SIP
- Новый контакт
- Все
- Пропущенные
- Удалить
-
- Перевести
- Добавить звонок
- Видео
- Микрофон
- Громкость
- Маршрут
- Получатель
- Bluetooth
- Настройки
-
- Послать
- Рис.
- Загружаем…
-
- Запрошено обновление звонка
- Ваш собеседник хотел бы добавить видео к звонку.
- Принять
- Отклонить
-
- Маленький
- Средний
- Большой
- Оригинальный размер
- Сохранить картинку
- Текст скопирован в буфер обмена
- Скопировать текст
- Выбрать источник
- Картинка сохранена
- Ошибка, картинка не сохранена
-
- Друзья
- Новые друзья
- Автоматически принимать запросы дружбы
- Запрос дружбы
- хочет поделиться своим статусом с Вами и получать обновления Вашего статуса.
- Идёт настройка шумоподавления
- Общий сервер
- Удалённое резервирование
-
- Удалить контакт
- адрес SIP
- Номер телефона
- Имя
- Фамилия
-
- Основная учётная запись
- Отображаемое имя
- Имя пользователя
- Истекает
-
- Послать RFC2833 DTMFs
- Послать SIP INFO DTMFs
-
- Звонок сброшен
- Пользователь не найден
- Несовместимые параметры потока
- У ваш собеседника низкая скорость подключения, видео не может быть использовано
- Сеть недоступна
-
- Сегодня
- Вчера
-
- Пропущенный
- Исходящий
- Входящий
-
- Фоновый режим
-
- Скачать
- Ошибка скачивания. Проверьте ваше интернет соединение или попробуйте позже.
-
diff --git a/res/values-ar/custom.xml b/res/values-ar/custom.xml
new file mode 100644
index 000000000..537faaccf
--- /dev/null
+++ b/res/values-ar/custom.xml
@@ -0,0 +1,25 @@
+
+
+ d MMM
+ EEEE MMM d HH:mm
+ HH:mm d MMM
+ HH:mm
+ linphone-mms-%s.jpg
+ لِنْفُونْ
+ خدمة لِنْفُونْ
+ لِنْفُونْ
+ لِنْفُونْ
+ يجري التشغيل
+ مُسجَّل في %s
+ فشِل التسجيل في %s
+ لِنْفُونْ %s الهاتف الموافق لـ SIP (rfc 3261) برخصة جْنُو العمومية الإصدار 2
+ http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications
+ سيمكنك هذا المرشد من إعداد حسابك SIP لإجراء المكالمات.
+ إنشاء حساب في linphone.org
+ أتوفر على حساب في linphone.org
+ أتوفر على حساب SIP
+ ادخل إسم المستخدم وكلمة السر لحسابك في linphone.org
+ ادخل إسم المستخدم وكلمة السر وكذا نطاق SIP.
+ إسم المستخدم
+
+
diff --git a/res/values-ar/strings.xml b/res/values-ar/strings.xml
new file mode 100644
index 000000000..2fd95f0d3
--- /dev/null
+++ b/res/values-ar/strings.xml
@@ -0,0 +1,407 @@
+
+
+ إيقاف
+ النفق
+ إسم المضيف
+ المنفذ
+ الوضع
+
+
+ - غير مُشغَّل
+ - 3G فقط
+ - دائما
+ - تلقائي
+
+ المكالمة الصوتية الجارية
+ المكالمة الموقَّفة مؤقتا الجارية
+ المكالمة المرئية الجارية
+ غير جاهز لإجراء مكالمة جديدة
+ جهة اتصال سيئة : %s
+ إلغاء التحقق %s
+ تحقق من %s
+ مُعمَّى
+ يجري التشغيل...
+ حدث خطأ خلال قبول المكالمة
+ خطأ خلال إضافة مكالمة
+ بدأ التحويل
+ تحويل المكالمة إلى
+ مكالمة جديدة
+ استرجاع المكالمة
+ تعذر استرجاع المكالمة الموقَّفة مؤقتا من طرف المُراسِل
+ إظهار التفاصيل
+ تحذير : الخدمة غير جاهزة
+ إغلاق
+ اجتماع
+ نشيط
+ مُوقَّف مؤقتا
+ مُوقَّف مؤقتا من طرف المُراسِل
+
+ وارد
+ يَرنّ
+ يتصل
+ كتم
+ مكبر الصوت
+ بلوتوث
+ إلغاء
+ إضافة مكالمة
+ تحويل المكالمة
+ دخول اجتماع
+ مغادرة الاجتماع مؤقتا
+ إنهاء الاجتماع
+ ضع السماعة
+ دمج
+ تحويل
+ فيديو
+
+ لوحة الاتصال الهاتفي
+ اجتماع
+ أنت ضِمنها
+ الخروج
+ أنت خارج الاجتماع
+ الدخول
+ تطويعات الصوت
+ استخدم وضع محددا للتطويع
+ 0=MODE_NORMAL (افتراضي)، 2=MODE_IN_CALL
+ استخدم تطويعات API التوجيه
+ استخدم تطويعات الصوت لـ Galaxy S
+ استخدام شدة صوت البرمجي
+ استخدم ipv6 عوض ipv4
+ خطأ خلال قبول المكالمة المنتظرة
+ %s يتصل بك
+ قبول
+ رفض
+ مجهول
+ الشبكة
+ النقل
+ UDP
+ TCP
+ TLS
+ استخدم منافذ عشوائية
+ منفذ SIP المُراد استخدامه
+ عنصر واحد على الأقل ضروري
+ نجح التسجيل
+ خطأ
+ البدء
+ التطبيق غير جاهز
+ إضافة حساب
+ لم يعثر على أرقام هاتف %s
+ ترشيح جهات الاتصال
+ أرقام هاتف %s
+ حذف هذا الحساب
+ استخدام كافتراضي
+ معايرة مزيل الصدى
+ استخدام الكاميرا الأمامية
+ الفيديو
+ التفضيلات
+ المراميز
+ حجم الفيديو المفضل
+ عرض لوحة المفاتيح
+ الكاميرا الأمامية/الخلفية
+ جرِّب الدقة العالية
+ منخفض الدقة
+ تغيير الدقة
+ كتم/إزالة كتم الكاميرا
+ إيقاف الكاميرا
+ تشغيل الكاميرا
+ إنهاء المكالمة
+ إعدادات الفيديو
+ شارك الكاميرا
+ قبول طلبات الفيديو الواردة
+ أرسِل تلقائيا الكاميرا الخاصة بي
+ قبول طلبات الفيديو دائما
+ بدء اتصالات بالصورة
+ أرسِل دائما طلبات الفيديو
+ تشغيل الفيديو
+ تشغيل التحريكات
+ استبدال + بـ 00
+ قد يكون iLBC غير متاحة وذلك حسب معالج ARM وإصدار نظام تشغيل أندرويد.
+ إزالة الصدى
+ البدء خلال الإقلاع
+ وسيط التوجُّه
+ المراميز
+ مهلة الاتصال
+ مهلة المكالمة الواردة
+ منفذ الفيديو أو نطاق المنفذ
+ منفذ الصوت أو نطاق المنفذ
+ منفذ الفيديو أو نطاق المنفذ (الأدنى – الأقصى)
+ منفذ الصوت أو نطاق المنفذ (الأدنى – الأقصى)
+ مهلة المكالمة الواردة (بالثواني)
+ إجراء مكالمة
+ التحكم في ملائمة الصبيب
+ خوارزمية ملائمة الصبيب
+ حد صبيب المِرماز
+
+ - 10 ك.بِتْ/ثانية
+ - 15 ك.بِتْ/ثانية
+ - 20 ك.بِتْ/ثانية
+ - 36 ك.بِتْ/ثانية
+ - 64 ك.بِتْ/ثانية
+ - 128 ك.بِتْ/ثانية
+
+ التنقيح
+ ابلغْ عن عطب
+ اشرح المشكل هنا
+ حدث خطأ في توليد تقرير العلل
+ لم يعثر على السجلات.
+ يقرأ السجلات، قد تأخذ بعض الوقت...
+ إرسال تقرير العلل مع...
+ حول
+ إرسال السجل
+ إعادة تعيين السجل
+ الصوت
+ الخروج
+ البادِئة
+ متقدم
+ اﻹعدادات
+ الوسيط
+ النطاق*
+ كلمة السر*
+ إسم المستخدم*
+ حساب SIP
+ إسم المستخدم خاطئ
+ كلمة السر خاطئة
+ النطاق خاطئ
+ الإعدادات خاطئة
+ لوحة المفاتيح
+ جهة الاتصال
+ لا يمكن الاتصال بـ %s
+ نعم
+ لا
+ تجاهل
+ استمرار
+ لا تذكرني أبدا
+ %s، هل تريد الذهاب إلى صفحة الإعدادات ؟
+ يبدأ في معايرة إزالة صدى الصوت
+ تعذر بدء المكالمة لأنها جارية مسبقا
+ التاريخ
+ تعذر تركيب عنوان الوجهة من [%s]
+ محو
+ تعذر جلب مُعامِلات المكالمة
+ تعذر إنشاء مُعامِلات المكالمة الافتراضية
+ تعذرت دعوة عنوان الوجهة [%s]
+ بدَأ
+ إزالة الصدى المسموع من الطرف الآخر
+ خادم STUN
+ تشغيل ICE
+ يجب تهيئة خادم STUN لاستخدام ICE
+ يُعايِر...
+ تمت المعايرة [%s ميلي-ث]
+ لا وجود لصدى
+ فشِل
+ ادخل إسم المستخدم وكلمة السر للاتصال بالخدمة.
+ إسم المستخدم
+ كلمة السر
+ اتصال
+ يُرجى إدخال إسم المستخدم وكلمة السر
+ تعذر الاتصال ؛ تحقق من إسم المستخدم وكلمة السر ثم أعد مرة أخرى
+ لا وجود مِرماز AMR في هاتفك
+ وسيط التعمية
+ بدون
+ المِرماز غير مُشغَّل، ابْنِ التطبيق من مصادره لتشغيله
+ المِرماز غير مُشغَّل، ابْنِ التطبيق من مصادره لتشغيله
+ حسابات SIP
+ استخدم WiFi فقط
+ تشغيل إشعارات التنبيه
+ حدث خطأ، حاول لاحقا.
+ تعذر الوصول للخادم، تحقق من اتصالك باﻹنترنت.
+ إن إسم المستخدم هذا مُستعمَل.
+ إسم المستخدم غير صحيح.
+ عنوانك الإلكتروني غير صحيح.
+ كلمة السر غير صالحة (على الأقل 6 حروف).
+ كلمتا السر غير متطابقتين.
+ إسم مضيف وسيط SIP أو عنوان IP (اختياري)
+ توجيه كل المكالمات عبر وسيط SIP
+ مثلا : john إذا كان حسابك john@sip.example.org
+ sip.example.org إذا كان حسابك john@sip.example.org
+ يجب عليك إدخال كلمة السر مرة أخرى إذا أردت تحرير إسم المستخدم أو النطاق
+ حذف
+ محادثة
+ مكالمة
+ إضافة إلى جهات الاتصال
+ مُسجَّل
+ غير مُسجَّل
+ يجري التسجيل
+ فشِل التسجيل
+ الرقم أو العنوان
+ اجتماع
+ المكالمة الواردة
+ مسودة
+ ادخل عنوان SIP للتحدث مع...
+ لا وجود لأي مكالمة في التاريخ.
+ لا وجود لأي مكالمة فائتة في التاريخ.
+ لا وجود لأي جهة اتصال في دفتر عناوينك.
+ لا وجود لأي جهة اتصال SIP في دفتر عناوينك.
+ لا وجود لتاريخ أي محادثة.
+ الصوت
+ الفيديو
+ المِرماز :
+ صبيب الرفع :
+ صبيب التنزيل :
+ توصيل ICE :
+ حجم الفيديو :
+
+ إضافة إلى زر جهات الاتصال
+ جهة اتصال جديدة
+ مكالمة
+ مسافة
+ صفحة \"حَوْلَ\"
+ المحادثة
+ إعادة الاتصال
+ صورة جهة الاتصال
+ إرسال رسالة
+ التفاصيل
+ حذف الزر
+ إضافة زر
+ محادثة جديدة
+ تحرير الزر
+ التحقق من الزر
+ بحث
+ كل جهات الاتصال
+ جهات اتصال Linphone
+ اتجاه الاتصال
+ كل الاتصالات
+ الاتصالات الفائتة
+ تبديل الفيديو
+ تبديل مكبر الصوت
+ تبديل الميكروفون
+ إضافة مكالمة
+ توقيف مؤقت
+ ضع السماعة
+ لوحة الأرقام
+ زر الإعدادات
+ لوحة المفاتيح
+ زر التاريخ
+ زر المحادثات
+ رز جهات الاتصال
+
+ جودة المكالمة
+ التعمية
+ تبديل الكاميرا
+ مرحبا بك في مرشد إعداد الحساب
+ إلغاء
+ زر الإلغاء
+ زر التالي
+ زر الرجوع
+ موافق
+ حالة الرسالة
+ اجتماع
+
+ مرشد إعداد الحساب
+ تطبيق
+ كلمة السر
+ النطاق
+ تأكيد كلمة السر
+ البريد الإلكتروني
+ إنشاء حساب
+ أُرسِلت رسالة إلى العنوان الذي أدخلتَ. لتنشيط حسابك، يجب عليك الضغط على الوصلة التي داخلها. حالما تقوم بذلك، ارجع إلى هنا واضغط على الزر أعلاه.
+ تحقق
+ لم يتم تأكيد حسابك بعد.
+ تم تأكيد حسابك.
+ التاريخ
+ الأسماء
+ اﻹعدادات
+ المحادثة
+ حول
+ إلغاء
+ الرجوع
+ هيا بنا
+ محادثة جديدة
+ تحرير
+ إلغاء
+ حسنا
+ الرجوع
+ الكل
+ SIP
+ جهة اتصال جديدة
+ الكل
+ الفائتة
+ حذف
+ تحويل
+ إضافة مكالمة
+ الفيديو
+ الميكروفون
+ مكبر الصوت
+ توجيه
+ السماعة
+ بلوتوث
+ الخيارات
+ إرسال
+ صورة
+ يجري الرفع...
+ هناك طلب لتحديث المكالمة
+ يريد المُراسِل إضافة الصورة إلى هذه المكالمة.
+ قبول
+ رفض
+ صغيرة
+ متوسطة
+ كبيرة
+ الحجم الحقيقي
+ حفظ الصورة
+ نُسخ النص في الحافظة
+ نسخ النص
+ اختر المصدر
+ حُفظَت الصورة
+ خطأ، لم تُحفَظ الصورة
+ الأصدقاء
+ أصدقاء جدد
+ اقبل تلقائيا طلبات الأصدقاء الجدد
+ طلب صديق
+ يريد مشاركة حالة حضوره معك ويريد كذلك أن يكون مطَّلعا على حالة حضورك.
+ تجري معايرة مزيل الصدى
+ خادم المشاركة
+ التهيئة عن بعد
+ حذف
+ عنوان SIP
+ رقم الهاتف
+ اﻹسم
+ اللقب
+ الحساب اﻷوَّلي
+ الإسم المعروض
+ إسم المستخدم
+ انتهاء الصلاحية
+ AVPF
+ نطاق RTCP الاعتيادي لـ AVPF بالثواني (ما بين 1 و 5)
+ إرسال RFC2833 DTMFs
+ إرسال SIP INFO DTMFs
+ عنوان العلبة الصوتية
+ الرسائل غير المقروءة
+ خطأ مجهول
+ مكالمة مرفوضة
+ لم يعثر على المستخدم
+ مُعامِلات الوسائط غير متوافقة
+ سعة قناة مُراسِلك ضعيفة، لا يمكن بدء الصورة
+ تعذر الوصول إلى الشبكة
+ اليوم
+ اﻷمس
+ الفائتة
+ الصادرة
+ الواردة
+ وضع الخلفية
+ إظهار
+ تنزيل
+ فشِل التنزيل. يُرجى التحقق من الوصول للإنترنت أو الإعادة لاحقا.
+ مُعرِّف استيثاق المستخدم
+ ادخل مُعرِّف استيثاق المستخدم (اختيارية)
+ الإسم المعروض
+ ادخل الإسم المعروض (اختياري)
+ تشغيل UPnP
+ الإدارة
+ يُرجى الانتظار...
+ يجري تحديث قاعدة بيانات الرسائل
+ الحساب الافتراضي
+ تنزيل التهيئة
+ سينزِّل هذا المرشد تهيئة موجودة
+ عنوان التهيئة
+ لا تتضمن التهيئة التي نزَّلت هذا الحساب. يُرجى ملؤه فيها.
+ سيكون إسم المستخدم الخاص بك هو %s (الأحرف الكبيرة غير مسموح بها). هل أنت موافق ؟
+ مرشد تهيئة الحساب
+ قبول
+ رفض
+ يتحتم عليك القبول فقط إذا كان لك ولمُراسِلك نفس الرمز (انظر أعلاه)
+ المُراسِل يكتب...
+ %i رسائل غير مقروءة
+ إعادة المحاولة
+ فشِل تنزيل أو تطبيق تشكيلة التهيئة عن بعد
+ التهيئة عن بعد
+ هل تريد تغيير عنوان التهيئة ؟
+
diff --git a/res/values-de/strings.xml b/res/values-de/strings.xml
new file mode 100644
index 000000000..39e0ae112
--- /dev/null
+++ b/res/values-de/strings.xml
@@ -0,0 +1,351 @@
+
+
+ Deaktivieren
+ Tunnel
+ Hostname
+ Port
+ Modus
+
+
+ - deaktiviert
+ - nur 3G
+ - immer
+ - auto
+
+ Anruf fortsetzen
+ Pausierten Anruf fortsetzen
+ Video-Anruf fortsetzen
+ Nicht bereit für einen neuen Anruf
+ Falscher Kontakt: %s
+ Geprüfte %s zurücksetzen
+ Überprüfe %s
+ verschlüsselt
+ Starte...
+ Beim Annehmen des Anrufs ist ein Fehler aufgetreten
+ Fehler beim Hinzufügen eines neuen Anrufs
+ Übertragung gestartet
+ Anruf weiterleiten zu
+ Neuer Anruf
+ Anruf fortsetzen
+ Kann pausierten Anruf nicht fortsetzen
+ Zeige Details
+ Warnung: Dienst ist nicht verfügbar
+ Schließen
+ conf
+ Aktiv
+ Pausiert
+ Pausiert durch Partner
+
+ Eingehend
+ Klingelt
+ Anrufen
+ Stumm
+ Lautsprecher
+ Bluetooth
+ Abbrechen
+ Anruf hinzufügen
+ Anruf weiterleiten
+ Konferenz beitreten
+ Konferenz vorübergehend verlassen
+ Konferenz beenden
+ Auflegen
+ Zusammenführen
+ Weiterleiten
+ Video
+
+ Wähltasten
+ Konferenz
+ Du bist ein Teil davon
+ ausgehen
+ Sie sind außen vor
+ hineingehen
+ Audio Hacks
+ Speziellen Modus Hack verwenden
+ 0=MODE_NORMAL (Standard), 2=MODE_IN_CALL
+ Routing API Hack verwenden
+ Galaxy S Audio Hack verwenden
+ Software-Lautstärke verwenden
+ IPv6 anstatt Ipv4 verwenden
+ Fehler beim Annehmen des wartenden Anrufs
+ %s ruft an
+ Annehmen
+ Ablehnen
+ Unbekannt
+ Netzwerk
+ Transport
+ UDP
+ TCP
+ TLS
+ zufällige Ports verwenden
+ zu benutzender SIP-Port
+ Es wird mindestens ein Element benötigt
+ Registrierung erfolgreich
+ Fehler
+ Start
+ Anwendung nicht bereit
+ Konto hinzufügen
+ Keine Telefonummern gefunden für %s
+ Kontakte filtern
+ %s\'s Telefonnummer
+ Konto löschen
+ als Standard benutzen
+ Echounterdrückung kalibrieren
+ Frontkamera benutzen
+ Video
+ Einstellungen
+ Codecs
+ bevorzugte Video-Größe
+ Zeige Wählgerät
+ Vorder-/Rück-Kamera
+ Hohe Auflösung benutzen
+ geringe Auflösung
+ Auflösung ändern
+ De-/Aktiviere Kamera
+ Deaktiviere Kamera
+ Aktiviere Kamera
+ Anruf beenden
+ Video-Einstellungen
+ Aktiviere meine Kamera
+ Nehme eingehende Video-Anfragen an
+ Aktiviere meine Kamera automatisch
+ Nehme Video-Anfragen immer an
+ starte Video-Anrufe
+ Sende immer Video-Anfragen
+ Aktiviere Video
+ Aktiviere Animationen
+ Ersetze + durch 00
+ iLBC ist möglicherweise nicht verfügbar, abhängig vom ARM Prozessor und Android Version.
+ Echounterdrückung
+ Starte beim Einschalten
+ Ausgehender Proxy
+ Codecs
+ Zeitüberschreitung der Kommunikation
+ Zeitüberschreitung bei eingehendem Anruf
+ Video-Port oder Port-Bereich
+ Audio-Port oder Port-Bereich
+ Video-Port oder Port-Bereich (Min.Port-Max.Port)
+ Audio-Port oder Port-Bereich (Min.Port-Max.Port)
+ Zeitüberschreitung bei eingehendem Anruf (in Sekunden)
+ Anrufen
+ Starte Kalibrierung der Echounterdrückung
+
+ - 10 kbits/s
+ - 15 kbits/s
+ - 20 kbits/s
+ - 36 kbits/s
+ - 64 kbits/s
+ - 128 kbits/s
+
+ Debug
+ Problembeschreibung
+ Problembeschreibung
+ Fehler beim Erstellen des Fehlerberichts
+ Protokolle nicht gefunden.
+ Protokolle laden, kann etwas Zeit in Anspruch nehmen...
+ Sende Fehlerbericht per...
+ Über
+ Sende Protokoll
+ Audio
+ Ausgang
+ Prefix
+ Erweitert
+ Einstellungen
+ Proxy
+ Domain*
+ Passwort*
+ Benutzername*
+ SIP-Konto
+ falscher Benutzername
+ falsches Passwort
+ falsche Domain
+ falsche Einstellungen
+ Wählgerät
+ Kontakt
+ Kann %s nicht anrufen
+ Ja
+ Nein
+ Fortsetzen
+ Niemals erinnern
+ %s. Wollen Sie zu den Einstellungen wechseln?
+ Starte Kalibrierung der Echounterdrückung
+ Historie
+ Leeren
+ Kann Anrufparameter nicht empfangen
+ Kann Standard-Anrufparameter nicht erstellen
+ Kann Zieladresse [%s] nicht einladen
+ begonnen
+ Stun-Server
+ aktiviere ICE
+ aktiviere ICE
+ Kalibrierung...
+ Kalibriert [%s ms]
+ Kein Echo
+ fehlgeschlagen
+ Benutzername und Passwort eingeben, um sich zum Dienst zu verbinden.
+ Benutzername
+ Passwort
+ Verbinden
+ Bitte Benutzername und Passwort eingeben
+ Verbindung nicht möglich; Prüfen Sie Ihre Zugangsdaten und versuchen Sie es erneut
+ AMR Codec ist möglicherweise nicht auf Ihrem Telefon vorhanden
+ Medien-Verschlüsselung
+ Keine
+ Codec deaktiviert, Erstellen Sie die App aus dem Source-Code, um Ihn zu aktivieren.
+ Codec deaktiviert, Erstellen Sie die App aus dem Source-Code, um Ihn zu aktivieren.
+ SIP-Konten
+ nur WLAN verwenden
+ Aktiviere Push-Benachrichtigungen
+ Es ist ein Fehler aufgetreten, versuchen Sie es später nochmal
+ Server nicht erreichbar, prüfen Sie Ihre Internetverbindung
+ Der Benutzername wird bereits verwendet.
+ Ihr Benutzername ist nicht gültig
+ Ihre E-Mailadresse ist nicht gültig
+ Ihr Passwort ist nicht gültig (min. 6 Zeichen)
+ Passwörter stimmen nicht überein.
+ SIP Proxy Hostname oder IP-Adresse (optional)
+ Leite alle Anrufe üder einen SIP Proxy
+ Beispiel: John, wenn ihr Konto john@sip.example.org ist
+ sip.example.org, wenn Ihr Konto john@sip.example.org ist
+ Sie müssen Ihr Passwort erneut eingeben, wenn Sie Ihren Benutzernamen und/oder Domain ändern
+ Löschen
+ Nachrichten
+ Call
+ zu Kontakten hinzufügen
+ registriert
+ nicht registriert
+ Registrierung in Arbeit
+ Registierung fehlgeschlagen
+ Nummer oder Adresse
+ Konferenz
+ Eingehender Anruf
+ Entwurf
+ Kein Anruf in Ihrer Historie.
+ Kein verpasster Anruf in Ihrer Historie.
+ Kein Kontakt in Ihrem Adressbuch.
+ Kein SIP-Kontakt in Ihrem Adressbuch.
+ Keine Nachrichtenhistorie.
+ Audio
+ Video
+ Codec:
+ Upload-Bandbreite:
+ Download-Bandbreite:
+ ICE-Konnektivität:
+ Video-Größe:
+
+ zu Kontakten hinzufügen
+ Neuer Kontakt
+ Call
+ Nachrichten
+ Anruf hinzufügen
+ Auflegen
+ Wählgerät
+
+ Abbrechen
+ Konferenz
+
+ Kontoeinrichtungsassistent
+ Anwenden
+ Passwort
+ Domain
+ Passwort bestätigen
+ E-Mail
+ Konto erstellen
+ Prüfe
+ Ihr Konto wurde noch nicht überprüft.
+ Ihr Konto wurde überprüft.
+ Historie
+ Kontakte
+ Einstellungen
+ Nachrichten
+ Über
+ Abbrechen
+ Zurück
+ Los geht\'s
+ Neues Gespräch
+ Ändern
+ Abbrechen
+ OK
+ Zurück
+ Alle
+ SIP
+ Neuer Kontakt
+ Alle
+ Verpasst
+ Löschen
+ Weiterleiten
+ Anruf hinzufügen
+ Video
+ Mikrofon
+ Lautsprecher
+ Weiterleiten
+ Empfänger
+ Bluetooth
+ Optionen
+ Senden
+ Bild
+ Hochladen...
+ Anrufaktualisierung angefordert
+ Annehmen
+ Ablehnen
+ Klein
+ Mittel
+ Groß
+ Echte Größe
+ Bild speichern
+ Text in die Zwischenablage kopiert
+ Kopiere Text
+ Wähle Quelle
+ Bild gespeichert
+ Fehler, Bild nicht gespeichert
+ Freunde
+ Neue Freunde
+ Neue Freundschaftsanfragen automatisch annehmen
+ Freundschaftsanfrage
+ Echounterdrückung kalibrieren in Arbeit
+ Löschen
+ SIP-Adresse
+ Telefonnummer
+ Vorname
+ Nachname
+ Primäres Konto
+ Anzeigename
+ Benutzername
+ Ablaufen
+ AVPF
+ AVPF Standard RTCP Interval in Sekunden (zwischen 1 und 5)
+ Sende RFC2833 DTMFs
+ Sende SIP INFO DTMFs
+ Sprachnachricht uri
+ Anruf abgelehnt
+ Benutzer nicht gefunden
+ Inkompatible Medien-Parameter
+ Ihr Partner hat eine geringe Bandbreite, Video kann nicht gestartet werden
+ Netzwerk ist nicht erreichbar
+ Heute
+ Gestern
+ Verpasst
+ Ausgehend
+ Eingehend
+ Hintergrundmodus
+ Zeige
+ Herunterladen
+ Herunterladen fehlgeschlagen. Bitte prüfen Sie Ihre Internetverbindung oder versuchen Sie es später nochmal.
+ Auth Benutzer-ID
+ Benutzer-ID eingeben (optional)
+ Anzeigename
+ Anzeigename eingeben (optional)
+ Aktiviere UPNP
+ Verwalten
+ Bitte warten...
+ Aktualisiere Nachrichtendatenbank
+ Standardkonto
+ Dieser Assistent lädt eine existierende Konfiguration herunter.
+ Ihr Benutzername lautet %s (Großbuchstaben sind nicht zuläßig). Sind Sie einverstanden?
+ Kontoeinrichtungsassistent
+ Annehmen
+ Verweigern
+ Sie sollten nur annehmen, wenn Sie den selben Code (siehe oben) sehen, wie ihr Gesprächspartner.
+ Partner schreibt...
+ %i ungelesene Nachrichten
+ Erneut versuchen
+
diff --git a/res/values-es/strings.xml b/res/values-es/strings.xml
new file mode 100644
index 000000000..da5c13535
--- /dev/null
+++ b/res/values-es/strings.xml
@@ -0,0 +1,124 @@
+
+
+ Deshabilitar
+ Túnel
+ Puerto
+ Modo
+
+
+ - deshabilitado
+ - sólo 3G
+ - siempre
+ - auto
+
+ No preparado para una nueva llamada
+ Contacto erróneo: %s
+ Verifica %s
+ Cifrado
+ Comenzando...
+ Ocurrió un error al aceptar la llamada
+ Error al añadir nueva llamada
+ Transferencia iniciada
+ Transferir llamada a
+ Nueva llamada
+ Continuar llamada
+ No puedo continuar una llamada puesta en pausa remotamente
+ Mostrar detalles
+ Aviso: el servicio no está preparado
+ Cerrar
+ activa
+ puesta en pausa
+ puesta en pausa remotamente
+
+ entrante
+ sonando
+ llamando
+ Silenciar
+ Altavoz
+ Bluetooth
+ Cancelar
+ Añadir llamada
+ Transferir llamada
+ Entrar en conferencia
+ Dejar momentáneamente la conferencia
+ Terminar la conferencia
+ Colgar
+ Unir
+ Transferir
+ vídeo
+
+ Teclado numérico
+ Conferencia
+ Eres parte de ella
+ Salir
+ Has salido de ella
+ Entrar
+ Usar volumen por software
+ Usar ipv6 en vez de ipv4
+ %s le está llamando
+ Aceptar
+ Declinar
+ Desconocido
+ Red
+ Transporte
+ UDP
+ TCP
+ TLS
+ Usar puertos aleatorios
+ Puerto SIP a usar
+ Se requiere al menos un elemento
+ Error
+ Empezar
+ Aplicación no preparado
+ Añadir cuenta
+ No se encontraron números de teléfono para %s
+ Filtrar contactos
+ números de teléfono de %s
+ Borrar ésta cuenta
+ Usar como predeterminada
+ Calibrado del cancelador de eco
+ Usar cámara frontal
+ Vídeo
+ Preferencias
+ Codecs
+ Tamaño de vídeo preferido
+ Cámara frontal/trasera
+ Probar alta resolución
+ Baja resolución
+ Cambiar resolución
+ Deshabilitar cámara
+ Habilitar cámara
+ Terminar llamada
+ Compartir mi cámara
+ Aceptar peticiones de vídeo entrantes
+ Enviar mi cámara automáticamente
+ Aceptar peticiones de vídeo siempre
+ Iniciar videollamadas
+ Siempre enviar peticiones de vídeo
+ Habilitar Vídeo
+ Habilitar animaciones
+ Sustituir + por 00
+ iLBC puede no estar disponible dependiendo del procesador ARM y la versión de S.O. Android
+ Cancelación de eco
+ Proxy saliente
+ Codecs
+ Conferencia
+ Vídeo
+
+ Añadir llamada
+ Colgar
+
+ Cancelar
+ Conferencia
+
+ Cancelar
+ Cancelar
+ Transferir
+ Añadir llamada
+ Vídeo
+ Altavoz
+ Bluetooth
+ Aceptar
+ Declinar
+ Aceptar
+
diff --git a/res/values-fr/custom.xml b/res/values-fr/custom.xml
new file mode 100644
index 000000000..07a4feb90
--- /dev/null
+++ b/res/values-fr/custom.xml
@@ -0,0 +1,25 @@
+
+
+ d MMM
+ EEEE MMM d HH:mm
+ HH:mm d MMM
+ HH:mm
+ linphone-mms-%s.jpg
+ Linphone
+ Linphone Service
+ Linphone
+ Linphone
+ Démarrage
+ Enregistré sur %s
+ Échec d\'enregistrement sur %s
+ Linphone %s SIP (rfc 3261) compatible téléphone, sous licence GNU Public License V2
+ http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications
+ Cet assistant va vous guider pour réaliser des appels à l\'aide d\'un compte SIP.
+ Créer un compte sur linphone.org
+ J\'ai déjà un compte sur linphone.org
+ J\'ai déjà un compte SIP
+ Entrez votre nom d\'utilisateur et mot de passe de linphone.org
+ Entrez votre nom d\'utilisateur, mot de passe et nom de domaine de votre compte SIP
+ nom d\'utilisateur
+
+
diff --git a/res/values-fr/strings.xml b/res/values-fr/strings.xml
new file mode 100644
index 000000000..d328d0d43
--- /dev/null
+++ b/res/values-fr/strings.xml
@@ -0,0 +1,407 @@
+
+
+ Désactiver
+ Tunnel
+ Hôte
+ Port
+ Mode
+
+
+ - désactivé
+ - 3G seulement
+ - toujours
+ - auto
+
+ Appel audio en cours
+ Appel en pause
+ Appel vidéo en cours
+ Pas prêt pour un nouvel appel
+ Mauvais contact : %s
+ Annuler vérification %s
+ Vérifier %s
+ Encrypté
+ Démarrage…
+ Une erreur est survenue pendant l\'acceptation d\'un appel
+ Erreur lors de l\'ajout de l\'appel
+ Transfert commencé
+ Transférer l\'appel vers
+ Nouvel appel
+ Reprendre l\'appel
+ Impossible de reprendre l\'appel mis en pause par votre correspondant
+ Montrer les détails
+ Attention : le service n\'est pas prêt
+ Fermer
+ conf
+ actif
+ en pause
+ mis en pause par le correspondant
+
+ entrant
+ sonnant
+ sortant
+ Silence
+ HP
+ Bluetooth
+ Annuler
+ Ajouter un appel
+ Transférer appel
+ Entrer dans la onférence
+ Quitter temporairement la conférence
+ Terminer la conférence
+ Raccrocher
+ Fusionner
+ Transférer
+ Vidéo
+
+ Dialpad
+ Conférence
+ Conférence en cours
+ Sortir
+ Conférence terminée
+ Rentrer
+ Bidouilles audio
+ Utiliser la bidouille de mode spécifique
+ 0=MODE_NORMAL (défaut), 2=MODE_IN_CALL
+ Utiliser la bidouille de l\'API de routage
+ Utiliser la bidouille d\'audio pour Galaxy S
+ Utiliser volume logiciel
+ Utiliser ipv6 au lieu de ipv4
+ Erreur pendant l\'acceptation de l\'appel
+ %s vous apelle
+ Accepter
+ Refuser
+ Inconnu
+ Réseau
+ Transport
+ UDP
+ TCP
+ TLS
+ Utiliser des ports aléatoires
+ Port SIP à utiliser si port aléatoire désactivé
+ Au moins un est requis
+ Enregistré avec succès
+ Erreur
+ Commencer
+ Application pas prête
+ Ajouter un compte
+ Aucun numéro trouvé pour %s
+ Filtrer contacts
+ Numéros de %s
+ Supprimer ce compte
+ Utiliser par défaut
+ Calibration de l\'annulateur d\'écho
+ Utiliser la caméra en façade
+ Vidéo
+ Préférences
+ Codecs
+ Taille de vidéo préférée
+ Afficher le dialer
+ Caméra frontale / arrière
+ Tester haute résolution
+ Basse résolution
+ Changer résolution
+ Activer / Désactiver caméra
+ Désactiver caméra
+ Activer caméra
+ Terminer l\'appel
+ Paramètres vidéo
+ Partager ma vidéo
+ Accepter appels vidéo
+ Envoyer ma vidéo automatiquement
+ Toujours accepter les demandes d\'appels vidéo
+ Initier les appels en vidéo
+ Toujours envoyer des demandes d\'appels vidéo
+ Activer la vidéo
+ Activer les animations
+ Remplacer + par 00
+ iLBC peut être indisponible suivant le processeur ARM et la version d\'Android.
+ Annulateur d\'écho
+ Démarrer au lancement du téléphone
+ Outbound proxy
+ Codecs
+ Time out de communication
+ Time out d\'appel entrant
+ Port ou plage de port vidéo
+ Port ou plage de port audio
+ Port ou plage (min-max) pour l\'audio
+ Port ou plage (min-max) pour la video
+ Timeout (en secondes) pour les appels entrants
+ Réaliser un appel
+ Contrôle qualité adaptatif
+ Algorithme de contrôle adaptatif
+ Limite de débit du codec
+
+ - 10 kbits/s
+ - 15 kbits/s
+ - 20 kbits/s
+ - 36 kbits/s
+ - 64 kbits/s
+ - 128 kbits/s
+
+ Activer les traces de débogage
+ Reporter un problème
+ Décrivez le problème ici
+ Erreur pendant la génération du rapport d\'incident
+ Traces non trouvées.
+ En train de lire les traces, peut prendre du temps…
+ Envoyer le rapport avec…
+ A propos
+ Envoyer les logs
+ Vider les logs
+ Audio
+ Quitter
+ Préfixe
+ Avancé
+ Paramètres
+ Serveur mandataire
+ Domaine*
+ Mot de passe*
+ Nom d\'utilisateur*
+ Compte SIP
+ Mauvais nom d\'utilisateur
+ Mauvais mot de passe
+ Mauvais domaine
+ Mauvais paramètre(s)
+ Dialer
+ Contact
+ Erreur lors de l\'appel de %s
+ Oui
+ Non
+ Annuler
+ Continuer
+ Ne plus me le rapeller
+ %s, voulez-vous aller dans les paramètres ?
+ Démarrage de la calibration de l\'annulateur d\'écho
+ Impossible de démarrer un nouvel appel, un appel est en cours
+ Historique
+ Impossible de construire l\'adresse de destination depuis [%s]
+ Nettoyer
+ Impossible de récupérer les paramètres de l\'appel
+ Impossible de créer les paramètres par défaut de l\'appel
+ Impossible d\'inviter l\'adresse [%s]
+ démarré
+ Supprime l\'écho entendu de l\'autre côté
+ Serveur Stun
+ Activer ICE
+ Un serveur STUN doit être configuré pour utiliser ICE
+ Calibration…
+ Calibré [%s ms]
+ Pas d\'écho
+ échoué
+ Entrez votre nom d\'utilisateur et votre mot de passe pour vous connecter au service.
+ Nom d\'utilisateur
+ Mot de passe
+ Connexion
+ Entrez votre nom d\'utilisateur et votre mot de passe
+ Impossible de se connecter; Vérifiez vos informations de connexion et réessayez
+ Le codec AMR codec peut ne pas être disponible sur votre téléphone
+ Encryption
+ Aucune
+ Codec désactivé, compilez l\'application depuis le code source pour l\'activer
+ Codec désactivé, compilez l\'application depuis le code source pour l\'activer
+ Comptes SIP
+ Wi-Fi uniquement
+ Activer les notifications poussées
+ Une erreur est survenue, réessayez plus tard.
+ Serveur injoignable, vérifiez votre connexion internet.
+ Ce nom d\'utilisateur est déjà pris.
+ Votre nom d\'utilisateur n\'est pas valide.
+ Votre courriel n\'est pas valide.
+ Votre mot de passe n\'est pas valide (6 caractères min).
+ Les mots de passe sont différents.
+ Adresse IP ou nom de domaine du serveur mandataire SIP (facultatif)
+ Faire passer tous les appels via le serveur mandataire SIP
+ Exemple: john si votre compte est john@sip.example.org
+ sip.example.org si votre compte est john@sip.example.org
+ Vous devrez retaper votre mot de passe si vous changez votre nom d\'utilisateur ou le domaine
+ Supprimer
+ Chat
+ Appel
+ Ajouter aux contacts
+ Enregistré
+ Pas Enregistré
+ Enregistrement en cours
+ Enregistrement échoué
+ Numéro ou adresse
+ Conférence
+ Appel entrant
+ Brouillon
+ Entrez une adresse SIP…
+ Aucun appel dans votre historique.
+ Aucun appel manqué dans votre historique.
+ Aucun contact dans votre carnet d\'adresse.
+ Aucun contact SIP dans votre carnet d\'adresse.
+ Aucun historique de chat.
+ Audio
+ Vidéo
+ Codec :
+ Bande passante envoi :
+ Bande passante réception :
+ Connexion ICE :
+ Taille vidéo:
+
+ Button Ajouter aux contacts
+ Nouveau contact
+ Appel
+ Retour
+ À propos
+ Chat
+ Rappeler
+ Photo contact
+ Envoyer message
+ Detail
+ Boutton supprimer
+ Boutton ajouter
+ Nouvelle discussion
+ Bouton éditer
+ Bouton valider
+ Rechercher
+ Tous les contacts
+ Contacts Linphone
+ Direction d\'appel
+ Tous les appels
+ Appels manqués
+ Basculer video
+ Basculer haut-parleur
+ Basculer micro
+ Ajouter un appel
+ Mettre en pause
+ Raccrocher
+ Clavier numerique
+ Bouton paramètres
+ Dialer
+ Bouton historique
+ Bouton chat
+ Bouton contacts
+
+ Qualite d\'appel
+ Chiffrement
+ Basculer camera
+ Bienvenue dans l\'assistant de configuration de compte
+ Annuler
+ Bouton annuler
+ Bouton suivant
+ Bouton precedent
+ Ok
+ Status de message
+ Conférence
+
+ Assistant de configuration des comptes
+ Appliquer
+ mot de passe
+ domaine
+ confirmez le mot de passe
+ courriel
+ Créer le compte
+ Un courriel vous à été envoyé. Pour activer votre compte, vous devez cliquer sur le lien qu\'il contient. Une fois ceci fait, revenez ici et cliquez sur le bouton ci-dessous.
+ Vérifier
+ Votre compte n\'a pas encore été validé.
+ Votre compte à été validé.
+ Historique
+ Contacts
+ Options
+ Chat
+ A propos
+ Annuler
+ Retour
+ Allons-y
+ + Chat
+ Modifier
+ Annuler
+ Valider
+ Retour
+ Tous
+ SIP
+ + Contact
+ Tous
+ Manqués
+ Supprimer
+ Transfert
+ + Appel
+ Vidéo
+ Micro
+ HP
+ Route
+ Ecouteur
+ Bluetooth
+ Options
+ Envoyer
+ Img
+ Envoi en cours…
+ Mise à jour de l\'appel
+ Votre correspondant souhaite ajouter la vidéo à l\'appel en cours.
+ Accepter
+ Refuser
+ Petite
+ Moyenne
+ Grande
+ Taille réelle
+ Sauvegarder l\'image
+ Texte copié dans le presse papier
+ Copier le texte
+ Choisissez la source
+ Image sauvegardée
+ Erreur, image non sauvegardée
+ Amis
+ Nouveaux amis
+ Toujours accepter les nouvelles demandes d\'amis
+ Requête d\'ami
+ voudrait être partager son status avec vous et voir le votre.
+ Calibration de l\'annulateur d\'écho en cours
+ Serveur de partage
+ Configuration distante
+ Supprimer
+ Adresse SIP
+ Numéro de téléphone
+ Prénom
+ Nom
+ Compte principal
+ Nom d\'affichage
+ Nom d\'utilisateur
+ Expiration
+ AVPF
+ Intervalle AVPF RTCP régulier en secondes (entre 1 et 5)
+ Envoyer les DTMFs RFC2833
+ Envoyer les DTMFs en SIP INFO
+ Adresse messagerie vocale
+ messages non lus
+ Erreur inconnue
+ Appel rejeté
+ Utilisateur non trouvé
+ Paramètres média incompatibles
+ Votre correspondant à un débit faible, la vidéo ne peut démarrer
+ Le réseau n\'est pas joignable
+ Aujourd\'hui
+ Hier
+ Manqué
+ Émis
+ Reçu
+ Actif en arrière plan
+ Afficher
+ Télécharger
+ Téléchargement échoué. Vérifiez votre connexion internet ou reéssayez plus tard.
+ Identifiant d\'authentification
+ Entrez votre identifiant (optionnel)
+ Nom d\'affichage
+ Entrez votre nom (optionnel)
+ Activer UPNP
+ Gestion
+ Merci de patienter...
+ Mise à jour de la base des messages
+ Compte par défaut
+ Télécharger ma configuration
+ Cet assistant va télécharger une configuration existante.
+ addresse où télécharger la configuration
+ La configuration téléchargée ne contient pas votre compte. Veuillez le remplir.
+ Votre nom d\'utilisateur sera %s.\r\n\r\nIl peut différer de celui que vous avez choisi afin de remplir certains critères nécessaires.\r\nAcceptez-vous ?
+ Assistant de création de compte
+ Accepter
+ Refuser
+ Vous ne devriez accepter que si vous avez le même code (ci-dessus) que votre contact
+ Votre correspondant est en train de taper...
+ %i messages non lus
+ Renvoyer
+ Erreur durant le téléchargement ou l\'application de la configuration distante...
+ Configuration distante
+ Souhaitez-vous changer l\'URI de configuration ?
+
diff --git a/res/values-he/strings.xml b/res/values-he/strings.xml
new file mode 100644
index 000000000..b8f592e23
--- /dev/null
+++ b/res/values-he/strings.xml
@@ -0,0 +1,128 @@
+
+
+ נטרל
+ שם מארח
+ פורט
+ מצב
+
+ הצג פרטים
+ סגור
+
+ השתק
+ רמקול
+ ביטול
+ הוסף שיחה
+ העבר שיחה
+ סיים
+ מזג
+ העבר
+ וידאו
+
+ לוח חיוג
+ ועידה
+ השתמש בעוצמת קול של תוכנה
+ קבל
+ דחה
+ לא מוכר
+ רשת
+ טרנספורט
+ שגיאה
+ התחל
+ הוסף חשבון
+ השתמש בתור ברירת מחדל
+ וידאו
+ העדפות
+ הצג לוח חיוג
+ נטרל מצלמה
+ אפשר מצלמה
+ סיים שיחה
+ הגדרות וידאו
+ אפשר וידאו
+ אפשר הנפשות
+ החלף + עם 00
+ אודות
+ שמע
+ יציאה
+ קידומת
+ מתקדם
+ הגדרות
+ פרוקסי
+ מתחם*
+ סיסמה*
+ שם משתמש*
+ חשבון SIP
+ איש קשר
+ כן
+ לא
+ המשך
+ היסטוריה
+ טהר
+ שרת Stun
+ אפשר ICE
+ נכשל
+ שם משתמש
+ סיסמה
+ התחבר
+ הצפנת מדיה
+ בלי
+ חשבונות SIP
+ Wifi בלבד
+ מחק
+ שיחה
+ קריאה
+ ועידה
+ אין היסטוריית שיחה.
+ שמע
+ וידאו
+ קודק:
+
+ איש קשר חדש
+ קריאה
+ שיחה
+ הוסף שיחה
+ סיים
+
+ ביטול
+ ועידה
+
+ החל
+ סיסמה
+ מתחם
+ הזן שוב סיסמה
+ צור חשבון
+ היסטוריה
+ אנשי קשר
+ הגדרות
+ שיחה
+ אודות
+ ביטול
+ חזור
+ קדימה
+ דיון חדש
+ ערוך
+ ביטול
+ אישור
+ חזור
+ הכל
+ איש קשר חדש
+ הכל
+ מחק
+ העבר
+ הוסף שיחה
+ וידאו
+ רמקול
+ אפשרויות
+ קבל
+ דחה
+ מחק
+ שם משתמש
+ היום
+ אתמול
+ הצג
+ הורד
+ אפשר UPNP
+ אנא המתן...
+ חשבון שגרתי
+ קבל
+ נסה שוב
+
diff --git a/res/values-ja/custom.xml b/res/values-ja/custom.xml
new file mode 100644
index 000000000..f7590f37a
--- /dev/null
+++ b/res/values-ja/custom.xml
@@ -0,0 +1,25 @@
+
+
+ d MMM
+ EEEE MMM d HH:mm
+ d MMM HH:mm
+ HH:mm
+ linphone-mms-%s.jpg
+ Linphone
+ Linphone サービス
+ Linphone
+ Linphone
+ はじめる
+ %s に登録しました
+ %s への登録に失敗しました
+ Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2
+ http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications
+ アシスタントがSIPアカウントを使ってあなたの通話を助けます。
+ linphone.orgのアカウントを作成する
+ linphone.orgのアカウントをすでに持っている
+ SIPアカウントをすでに持っている
+ linphone.orgのユーザー名とパスワードを入力してください
+ SIPアカウントのユーザー名とパスワードとドメインを入力してください
+ ユーザー名
+
+
diff --git a/res/values-ja/strings.xml b/res/values-ja/strings.xml
new file mode 100644
index 000000000..9b579622c
--- /dev/null
+++ b/res/values-ja/strings.xml
@@ -0,0 +1,407 @@
+
+
+ 無効
+ トンネル
+ ホスト名
+ ポート
+ モード
+
+
+ - 無効
+ - 3Gのみ
+ - 常に
+ - 自動
+
+ オーディオの呼び出し継続中
+ コールの一時停止中
+ ビデオキャプチャーコール進行中
+ 呼び出しの準備ができていません
+ 不正規な接続 : %s
+ リセットを検証 %s
+ %s を確認してください
+ 暗号化
+ 起動中...
+ コールの受け入れにエラーが発生しました
+ 新しいコールにエラーが発生しました
+ 転送を開始する
+ 転送コール
+ 新しい呼び出し
+ 呼び出しを再開
+ リモートで呼び出しの一時停止を再開することはできません
+ 詳細を表示
+ 警告:サービスが準備できていません
+ 閉じる
+ 設定
+ 活動
+ 停止
+ リモート停止
+
+ 着信
+ 鳴動
+ 呼び出し中
+ ミュート
+ スピーカー
+ Bluetooth
+ キャンセル
+ 呼び出し追加
+ 呼び出し転送
+ 会議を入力してください
+ 会議を瞬間的に残す
+ 会議を終了
+ ハングアップ
+ 結合
+ 転送
+ ビデオ
+
+ ダイヤル画面
+ 会議
+ あなたはそこの一員です
+ 外出
+ あなたはそこの一員ではありません
+ 入る
+ オーディオ設定
+ 特定のハックを使用する
+ 0=MODE_NORMAL (デフォルト), 2=MODE_IN_CALL
+ ルーティングAPIを使用する
+ Galaxy Sハックを使用する
+ ソフトウェアボリュームを使用する
+ IPv4ではなくIPv6を使用する
+ エラー保留中の通話を受け入れる
+ %s があなたを呼び出しています
+ 受理
+ 辞退
+ 不明
+ ネットワーク
+ トランスポート
+ UDP
+ TCP
+ TLS
+ ランダムポートを使用する
+ SIPポートを使用する
+ 少なくとも一つの選択が必要です
+ 正常に登録されました
+ エラー
+ スタート
+ 準備ができていません
+ アカウントを追加する
+ %s 用の電話番号が見つかりません
+ フィルターの連絡先
+ %s の電話番号
+ このアカウントを削除する
+ デフォルトで使用する
+ エコーキャンセラーの調整
+ フロントカメラを使用する
+ ビデオ
+ 設定
+ コーデック
+ 動画の大きさ
+ ダイヤル画面を表示
+ フロント/リア カメラ
+ 高解像度にする
+ 低解像度にする
+ 解像度を変更する
+ 停止/再開 カメラ
+ カメラを無効にする
+ カメラを有効にする
+ 呼び出しを終了する
+ ビデオ設定
+ カメラを共有する
+ ビデオ表示の要求を受け入れる
+ カメラ映像を自動で送信する
+ ビデオ表示の要求を常に受け入れる
+ ビデオ通話を開始する
+ ビデオ表示の要請を常に送信
+ ビデオを有効にする
+ アニメーションを有効にする
+ 00 で置き換える
+ iLBCは、 ARMプロセッサとAndroid OSのバージョンによっては使用できないことがあります。
+ エコーキャンセル
+ 起動時に開始する
+ Outbound proxy
+ Codecs
+ 通信がタイムアウト
+ 呼び出し時間のタイムアウト
+ ビデオのポートまたはポート範囲
+ オーディオのポートまたはポート範囲
+ ビデオのポートまたはポート範囲 (最小-最大)
+ オーディオのポートまたはポート範囲 (最小-最大)
+ 呼び出しを終了する (秒単位)
+ 電話をかける
+ 適応レート制御
+ 適応レート方式
+ コーデックのビットレート制限
+
+ - 10 kbits/s
+ - 15 kbits/s
+ - 20 kbits/s
+ - 36 kbits/s
+ - 64 kbits/s
+ - 128 kbits/s
+
+ デバッグ
+ 問題をレポート
+ 問題点を説明してください
+ 問題点の報告にエラーが発生しました
+ ログが見つかりません。
+ ログを読むには時間がかかります...
+ これでバグレポートを送信
+ アバウト
+ ログを送信する
+ ログをリセットする
+ オーディオ
+ 退出
+ プレフィックス
+ 拡張
+ 設定
+ プロキシ
+ ドメイン*
+ パスワード*
+ ユーザー名*
+ SIPアカウント
+ ユーザー名が間違っています
+ パスワードが間違っています
+ ドメイン名が間違っています
+ 設定が間違っています
+ ダイヤラー
+ 連絡先
+ %s には呼び出しができません
+ はい
+ いいえ
+ 辞退
+ 続行
+ 思い出させない
+ %s さん、あなたは設定ページに行きたいですか?
+ エコーキャンセルのためのオーディオ調整を開始する
+ 呼び出しを実行しているため、新しい呼び出しは開始できません
+ 履歴
+ [%s] からの送信先アドレスは構築できません
+ 消去
+ 呼び出しのパラメータが取得できません
+ デフォルトのコールパラメータを作成できません
+ [%s] の宛先アドレスは招待できません
+ はじめる
+ 相手が聞こえるエコーを削除する
+ Stunサーバー
+ ICEを有効にする
+ STUNサーバーはICEを使用する必要があります
+ 調整中...
+ 調整完了 [%s ms]
+ エコーなし
+ 失敗
+ 接続するにはユーザー名とパスワードを入力します。
+ ユーザー名
+ パスワード
+ 接続
+ ユーザー名とパスワードを入力してください
+ 接続できません: ユーザー名とパスワードを確認して再度実行する
+ AMRコーデックは、お使いの電話で使用できない場合があります
+ メディアの暗号化
+ なし
+ 無効なコーデックです。有効にするには、ソースコードからアプリを構築する必要があります。
+ 無効なコーデックです。有効にするには、ソースコードからアプリを構築する必要があります。
+ SIPアカウント
+ WiFIでのみ使用
+ プッシュ通知を有効にする
+ エラーが発生しました。のちほど再試行してください。
+ サーバーに接続できません。インターネットへの接続を確認してください。
+ このユーザー名はすでに使われています。
+ 不正なユーザー名です。
+ 不正なメールアドレスです。
+ 不正なパスワードです (6文字以上の必要があります)。
+ パスワードが異なっています。
+ SIP のプロキシ名 もしくは IPアドレス (任意)
+ SIP プロキシ経由で呼び出しを実行する
+ 一例: john であればあなたのアカウント は john@sip.example.org
+ sip.example.org であればあなたのアカウント は john@sip.example.org
+ あなたのユーザ名/またはドメインを編集した場合はパスワードを再入力する必要があります。
+ 削除
+ チャット
+ 呼び出し
+ 連絡相手に登録する
+ 登録済
+ 未登録
+ 登録に問題があります
+ 登録できませんでした
+ 番号もしくはアドレス
+ 会議
+ 着信
+ 計画
+ ...とチャットするSIPアドレスを入力してください
+ 呼び出し履歴がありません
+ 呼び出しミス履歴がありません
+ 電話帳に連絡先がありません
+ 電話帳にSIPの連絡先がありません
+ チャット履歴はありません。
+ オーディオ
+ ビデオ
+ コーデック:
+ アップロード幅:
+ ダウンロード幅:
+ ICE 接続:
+ ビデオ解像度:
+
+ 連絡先に追加
+ 新しい連絡先
+ 発信
+ バックスペース
+ ページについて
+ チャット
+ コールバック
+ 連絡相手の画像
+ 送信メッセージ
+ 詳細
+ 削除ボタン
+ 追加ボタン
+ 新しいやりとりを行う
+ 編集ボタン
+ 有効化ボタン
+ 検索
+ すべての連絡先
+ Linphoneの連絡先
+ 宛先を指定
+ すべての呼出
+ 失敗した呼出
+ ビデオの切り替え
+ スピーカー切り替えトグルスイッチ
+ マイク切り替えトグルスイッチ
+ 追加発信
+ 一時停止
+ ハングアップ
+ キーパッド
+ 設定ボタン
+ ダイヤラー
+ 履歴ボタン
+ チャットボタン
+ 連絡ボタン
+
+ 通話品質
+ 暗号化
+ カメラをスイッチする
+ アカウント設定にようこそ
+ キャンセル
+ キャンセルボタン
+ 進むボタン
+ 戻るボタン
+ OK
+ メッセージ状態
+ 会談
+
+ アカウント設定アシスタント
+ 適用
+ パスワード
+ ドメイン
+ パスワード再入力
+ メール
+ アカウントを作成する
+ あなたのメールアドレスにメールが送信されました。アカウントを作成するため、あなたはメール内にあるリンクをクリックする必要があります。それが完了次第、こちらに戻って、上のボタンをクリックしてください。
+ 確認
+ あなたのアカウントはまだ確認されていません。
+ あなたのアカウントは確認されています。
+ 履歴
+ コンタクト
+ 設定
+ チャット
+ アバウト
+ キャンセル
+ 戻る
+ はじめましょう
+ 新しい会話
+ 編集
+ キャンセル
+ はい
+ 戻る
+ すべて
+ SIP
+ 新しい連絡先
+ すべて
+ ミス
+ 削除
+ 転送
+ 追加発信
+ ビデオ
+ マイクロ
+ スピーカー
+ ルート
+ レシーバー
+ Bluetooth
+ オプション
+ 送信
+ Pic
+ アップロード中...
+ コール更新が要求されました
+ あなたの通話相手は現在の通話にビデオを追加しようとしています。
+ 受理
+ 辞退
+ 小さい
+ 中くらい
+ 大きい
+ 原寸大
+ 写真を保存する
+ テキストをクリップボードにコピーする
+ コピーしたテキスト
+ 選択したソース
+ 保存した画像
+ エラー、画像が保存できません。
+ 友だち
+ 新しい友だち
+ utomaticallyで新しい友だちリクエストを受け入れる
+ 友だちリクエスト
+ あなたとプレゼンス状態のシェアをしたいと考えています。
+ エコーキャンセラーの調整進行中
+ 共有サーバー
+ 遠隔準備
+ 削除
+ SIPアドレス
+ 電話番号
+ 名前
+ 名字
+ 優先アカウント
+ 表示名
+ ユーザー名
+ Expire
+ AVPF
+ AVPFによる正規のRTCP間隔 (1秒 から 5秒)
+ DTMFをRFC2833で送信する
+ DTMFをSIP情報で送信する
+ ボイスメールのuri
+ 未読メッセージ
+ 不明なエラー
+ 呼び出しが辞退されました
+ ユーザーがおりません
+ 互換性のないメディアパラメーター
+ あなたの通話相手は低帯域幅なのでビデオを開始できませんでした。
+ ネットワークに到達できません
+ 今日
+ 昨日
+ ミス
+ 発信
+ 着信
+ 背後作動モード
+ 見せる
+ ダウンロード
+ ダウンロードに失敗しました。インターネット接続を確認するか、のちほどお試しください。
+ ユーザーIDを認証
+ 認証したいユーザーIDを入力します (任意)
+ 表示名
+ 表示名を入力 (オプション)
+ UPNPを有効にする
+ 管理
+ お待ちください...
+ メッセージのデータベースを更新する
+ デフォルトのアカウント
+ プロビジョニングを保存
+ このアシスタントは、既存の設定をダウンロードします。
+ プロビジョニングのURL
+ ダウンロードした設定にはあなたのアカウント情報が含まれていませんのでそれを記入してください。
+ あなたのユーザー名は %s のになります(大文字は使用できません)。こちらでよろしいですか?
+ アカウント設定アシスタント
+ 受理
+ 拒否
+ あなたの通話相手と同じコード(上記参照)を持っている場合のみ受け入れてください
+ リモート先が入力中...
+ %i 未読メッセージ
+ 再送
+ ダウンロードした、リモートプロビジョニング設定を適用できませんでした...
+ 遠隔準備
+ プロビジョニングURIを変更しますか?
+
diff --git a/res/values-nl/custom.xml b/res/values-nl/custom.xml
new file mode 100644
index 000000000..63058ac6e
--- /dev/null
+++ b/res/values-nl/custom.xml
@@ -0,0 +1,25 @@
+
+
+ d MMM
+ EEEE MMM d HH:mm
+ HH:mm d MMM
+ HH:mm
+ linphone-mms-%s.jpg
+ Linphone
+ Linphone-dienst
+ Linphone
+ Linphone
+ Bezig met opstarten
+ Geregistreerd naar %s
+ Het registreren naar %s is mislukt
+ Linphone %s SIP (rfc 3261)-compatibele telefoonapp onder de licentie van GNU Public License V2
+ http://www.linphone.org\n\nGebruikershandleidingen\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications
+ Deze wizard zal u helpen bij het gebruiken van een SIP-account voor uw oproepen.
+ Creëer een account op linphone.org
+ Ik heb al een linphone.org-account
+ Ik heb al een SIP-account
+ Vul uw linphone.org-gebruikersnaam en -wachtwoord in
+ Vul uw SIP-account-gebruikersnaam, -wachtwoord en -domeinnaam in
+ gebruikersnaam
+
+
diff --git a/res/values-nl/strings.xml b/res/values-nl/strings.xml
new file mode 100644
index 000000000..064920bed
--- /dev/null
+++ b/res/values-nl/strings.xml
@@ -0,0 +1,178 @@
+
+
+ Uitschakelen
+ Tunnel
+ Hostnaam
+ Poort
+ Modus
+
+ %s verifiëren
+ Versleuteld
+ Opstarten…
+ Nieuwe oproep
+ Oproep hervatten
+ Details tonen
+ Sluiten
+ conf
+ actief
+ gepauzeerd
+
+ inkomend
+ bellen
+ Luidspreker
+ Bluetoot
+ Annuleren
+ Oproep toevoegen
+ Doorschakelen
+ Ophangen
+ video
+
+ Toetsenblok
+ Audiohacks
+ 0=MODE_NORMAL (standaard), 2=MODE_IN_CALL
+ Routing API-hack gebruiken
+ Galaxy S-audiohack gebruiken
+ Softwarevolume gebruiken
+ IPv6 in plaats van IPv4 gebruiken
+ Accepteren
+ Weigeren
+ Onbekend
+ Netwerk
+ Transport
+ UDP
+ TCP
+ TLS
+ Willekeurige poorten gebruiken
+ Fout
+ Account toevoegen
+ Video
+ Voorkeuren
+ Codecs
+ Hoge resolutie proberen
+ Lage resolutie
+ Resolutie veranderen
+ Camera uitschakelen
+ Camera inschakelen
+ Oproep beëindigen
+ Video-instellingen
+ Video inschakelen
+ Animaties inschakelen
+ + door 00 vervangen
+ Codecs
+
+ - 10 kbits/s
+ - 15 kbits/s
+ - 20 kbits/s
+ - 36 kbits/s
+ - 64 kbits/s
+ - 128 kbits/s
+
+ Foutopsporing
+ Problem rapporteren
+ Over
+ Log versturen
+ Audio
+ Afsluiten
+ Voorvoegsel
+ Geavanceerd
+ Instellingen
+ Proxy
+ Domein*
+ Wachtwoord*
+ Gebruikersnaam*
+ SIP-account
+ verkeerde gebruikersnaam
+ verkeerd wachtwoord
+ Verkeerd domein
+ Verkeerde instellingen
+ Contact
+ Ja
+ Nee
+ Nooit onthouden
+ Geschiedenis
+ Wissen
+ Stun-server
+ ICE inschakelen
+ gefaald
+ Gebruikersnaam
+ Wachtwoord
+ Verbinden
+ Mediaversleuteling
+ Geen
+ SIP-accounts
+ Verwijderen
+ Chat
+ Oproep
+ Geregistreerd
+ Niet geregistreerd
+ Geen chatgeschiedenis.
+ Audio
+ Video
+ Codec:
+ Uploadbandbreedte:
+ Downloadbandbreedte:
+ Videogrootte:
+
+ Nieuw contact
+ Oproep
+ Chat
+ Oproep toevoegen
+ Ophangen
+
+ Annuleren
+
+ Toepassen
+ wachtwoord
+ domein
+ e-mail
+ Geschiedenis
+ Contacten
+ Instellingen
+ Chat
+ Over
+ Annuleren
+ Annuleren
+ Alle
+ SIP
+ Nieuw contact
+ Alle
+ Gemist
+ Verwijderen
+ Oproep toevoegen
+ Video
+ Micro
+ Luidspreker
+ Bluetooth
+ Opties
+ Accepteren
+ Weigeren
+ Klein
+ Middel
+ Groot
+ Afbeelding opslaan
+ Vrienden
+ Nieuwe vrienden
+ Vriendverzoek
+ Verwijderen
+ SIP-adres
+ Telefoonnummer
+ Voornaam
+ Achternaam
+ Primaire account
+ Weergavenaam
+ Gebruikersnaam
+ AVPF
+ Vandaag
+ Gisteren
+ Gemist
+ Uitgaande
+ Inkomende
+ Achtergrondsmodus
+ Weergeven
+ Weergavenaam
+ UPNP inschakelen
+ Beheren
+ Standaard account
+ Accepteren
+ Weigeren
+
diff --git a/res/values-ru/custom.xml b/res/values-ru/custom.xml
new file mode 100755
index 000000000..beed19a4d
--- /dev/null
+++ b/res/values-ru/custom.xml
@@ -0,0 +1,19 @@
+
+
+ EEEE d MMM HH:mm
+ Linphone
+ Linphone
+ Linphone
+ Загружается
+ Зарегистрирован в %s
+ Ошибка регистрации в %s
+ Linphone %s SIP (rfc 3261) совместимый телефон под GPL V2 лицензией
+ http://www.linphone.org\n\nИнструкции\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications
+ Этот помощник поможет Вам настроить учётную запись SIP для звонков.
+ Создать учётную запись на linphone.org
+ Уже есть учётная запись на linphone.org
+ Уже есть учётная запись SIP
+ Введите имя пользователя и пароль учётной записи linphone.org
+ Введите имя пользователя, пароль и сервер учётной записи SIP
+
+
diff --git a/res/values-ru/strings.xml b/res/values-ru/strings.xml
new file mode 100755
index 000000000..f982fb0db
--- /dev/null
+++ b/res/values-ru/strings.xml
@@ -0,0 +1,353 @@
+
+
+ Деактивировать
+ Туннель
+ Сервер
+ Порт
+ Режим
+
+
+ - выключено
+ - только 3G
+ - всегда
+ - авто
+
+ Идёт Аудио звонок
+ Звонок на Паузе
+ Идёт Видео звонок
+ Невозможно совершить новый звонок
+ Плохой контакт: %s
+ Сброс подтверждён %s
+ Подтвердить %s
+ Зашифровано
+ Загружается…
+ При приёме звонка произошла ошибка
+ Ошибка при добавлении звонка
+ Начат перевод
+ Перевод звонка на
+ Новый звонок
+ Возобновить звонок
+ Невозможно возобновить звонок поставленный на паузу оппонентом
+ Показать детали
+ Внимание : сервис не готов
+ Закрыть
+ конф
+ активен
+ на паузе
+ поставлен на паузу оппонентом
+
+ входящий
+ звонящий
+ в процессе
+ Выключить микрофон
+ Громкоговоритель
+ Bluetooth
+ Отменить
+ Добавить звонок
+ Перевести звонок
+ Присоединиться к конференции
+ Покинуть конференцию
+ Прервать конференцию
+ Положить трубку
+ Объединить
+ Перевести
+ Видео
+
+ Клавиатура
+ Конференция
+ Вы часть её
+ Выйти
+ Вы вышли
+ Войти
+ Audio хаки
+ Использовать хаки спец. режима
+ 0=MODE_NORMAL (по умолчанию), 2=MODE_IN_CALL
+ Использовать хак API маршрутизации
+ Использовать аудио хак Galaxy S
+ Использовать \"программную\" громкость
+ Использовать ipv6 вместо ipv4
+ Ошибка во время приёма входящего звонка
+ %s звонит Вам
+ Принять
+ Отклонить
+ Неизвестнвй
+ Сеть
+ Транспорт
+ UDP
+ TCP
+ TLS
+ Использовать случайный порт
+ SIP порт занят
+ По крайней мере 1 протокол обязателен
+ Регистрация успешна
+ Ошибка
+ Начать
+ Приложение не готово
+ Добавить учётную запись
+ Телефонных номеров для %s не найдено
+ Фильтровать контакты
+ Телефонные номера %s
+ Удалить учётную запись
+ Использовать как основную
+ Настроить шумоподавление
+ Использовать фронтальную камеру
+ Видео
+ Настройки
+ Кодеки
+ Preferred video size
+ Показать клавиатуру
+ Лицевая/Задняя камера
+ Высокое разрешение
+ Низкое разрешение
+ Сменить разрешение
+ Включить/Выключить камеру
+ Запретить камеру
+ Разрешить камеру
+ Прекратить звонок
+ Настройки видео
+ Совмесный доступ к камере
+ Принимать входящие видео звонки
+ Автоматически посылать видео
+ Всегда принимать видео запросы
+ Начинать видео звонки
+ Всегда посылать видео запросы
+ Разрешить видео
+ Разрешить анимацию
+ Заменить + на 00
+ iLBC может быть недоступно в Вашей версии ARM процессора и Android OS.
+ Шумоподавление
+ Запускаться с системой
+ Исходящий прокси
+ Кодеки
+ Таймаут соединения
+ Таймаут входящего соединения
+ Видео порт или диапазон портов
+ Аудио порт или диапазон портов
+ Видео порт или диапазон портов (минимум-максимум)
+ Аудио порт или диапазон портов (минимум-максимум)
+ Таймаут входящего соединения (в секундах)
+ Разместить звонок
+ Отладка
+ Сообщить об ошибке
+ Опишите проблему
+ Ошибка при генерации отчёта об ошибке
+ Логи не найдены.
+ Читаю логи, может занять время…
+ Послать отчёт об ошибке с…
+ О программе
+ Аудио
+ Выход
+ Префикс
+ Продвинутые
+ Настройки
+ Прокси
+ Сервер*
+ Пароль*
+ Имя пользователя*
+ Имя SIP
+ неправильное имя поьлзователя
+ неправильный пароль
+ Неправильный сервер
+ Неправильные настройки
+ Клавиатура
+ Контакт
+ Невозможно набрать %s
+ Да
+ Нет
+ Убрать
+ Продолжить
+ Больше не напоминать
+ %s, хотите ли вы перейти к настройкам ?
+ Начинаем автоматическую настройку шумоподавления
+ Невозможно начать новый звонок, звонок уже идёт
+ История
+ Невозможно создать адрес получателя из [%s]
+ Очистить
+ Невозможно получить параметры звонка
+ Невозможно создать параметры звонка по умолчанию
+ Невозможно пригласить получателя [%s]
+ начат
+ Удаляет эхо, слышимое другой стороной
+ Сервер Stun
+ Разрешить ICE
+ Сервер STUN должен быть настроен чтобы использовать ICE
+ Настраиваем…
+ Настроено за [%s ms]
+ Нет эха
+ неудавшийся
+ Введите имя пользователя и пароль для соединения с сервисом.
+ Имя пользователя
+ Пароль
+ Соединиться
+ Пожалуйста введите имя пользователя и пароль
+ Невозможно соединиться; проверьте имя пользователя и пароль и попробуйте ещё
+ Кодек AMR возможно отсутствует в телефоне
+ Шифрование потока
+ Отсутствует
+ Кодек поддерживается только если построено из исходников
+ Кодек поддерживается только если построено из исходников
+ Учётные записи SIP
+ Использовать только wifi
+ Разрешить серверные уведомления
+ Произошла ошибка, попробуйте повторить позже.
+ Сервер недоступен, проверьте Ваше соединение с интернетом.
+ Это имя пользователя уже использовано.
+ Имя пользователя недопустимо.
+ Недопустимый адрес электронной почты.
+ Недопустимый пароль (минимум 6 знаков).
+ Введённые пароли отличаются.
+ Имя сервера SIP прокси или адрес ip (необязательно)
+ Отправить все звонки через SIP прокси
+ Например: john если Ваш адрес john@sip.example.org
+ sip.example.org если Ваш адрес john@sip.example.org
+ You have to re-enter your password if you edit the username and/or the domain
+ Удалить
+ Чат
+ Звонок
+ Добавить к контактам
+ Зарегистрирован
+ Незарегистрирован
+ В процессе регистрации
+ Ошибка регистрации
+ Номер или Адрес
+ Конференция
+ Входящий звонок
+ Черновик
+ Введите адрес SIP для чата…
+ Нет звонков в вашей истории.
+ Нет пропущенных звонков в вашей истории.
+ Нет контакта в Вашей адресной книге.
+ Нет SIP контакта в Вашей адресной книге.
+ Нет истории чата.
+ Аудио
+ Видео
+ Кодек:
+ Полоса пропускания загрузки:
+ Полоса пропускания скачивания:
+ Подключение ICE:
+ Video size:
+
+ Кнопка добавить к контактам
+ Новый контакт
+ Звонок
+ Чат
+ Добавить звонок
+ Положить трубку
+ Клавиатура
+
+ Отменить
+ Конференция
+
+ Помощник Настройки учётной записи
+ Применить
+ пароль
+ сервер
+ подтвердить пароль
+ адрес электронной почты
+ Создать учётную запись
+ Электронное письмо было послано на указанный адрес. Пройдите по ссылке из этого письма, чтобы активировать Вашу учётную запись. После этого вернитесь сюда и нажмите на кнопку выше.
+ Проверить
+ Ваша учётная запись ещё не подтверждена.
+ Ваша учётная запись подтверждена.
+ История
+ Контакты
+ Настройки
+ Чат
+ О программе
+ Отменить
+ Назад
+ Далее
+ Новый разговор
+ Редактировать
+ Отменить
+ ОК
+ Назад
+ Все
+ SIP
+ Новый контакт
+ Все
+ Пропущенные
+ Удалить
+ Перевести
+ Добавить звонок
+ Видео
+ Микрофон
+ Громкость
+ Маршрут
+ Получатель
+ Bluetooth
+ Настройки
+ Послать
+ Рис.
+ Загружаем…
+ Запрошено обновление звонка
+ Ваш собеседник хотел бы добавить видео к звонку.
+ Принять
+ Отклонить
+ Маленький
+ Средний
+ Большой
+ Оригинальный размер
+ Сохранить картинку
+ Текст скопирован в буфер обмена
+ Скопировать текст
+ Выбрать источник
+ Картинка сохранена
+ Ошибка, картинка не сохранена
+ Друзья
+ Новые друзья
+ Автоматически принимать запросы дружбы
+ Запрос дружбы
+ хочет поделиться своим статусом с Вами и получать обновления Вашего статуса.
+ Идёт настройка шумоподавления
+ Общий сервер
+ Удалённое резервирование
+ Удалить
+ адрес SIP
+ Номер телефона
+ Имя
+ Фамилия
+ Основная учётная запись
+ Отображаемое имя
+ Имя пользователя
+ Истекает
+ Послать RFC2833 DTMFs
+ Послать SIP INFO DTMFs
+ Звонок сброшен
+ Пользователь не найден
+ Несовместимые параметры потока
+ У ваш собеседника низкая скорость подключения, видео не может быть использовано
+ Сеть недоступна
+ Сегодня
+ Вчера
+ Пропущенный
+ Исходящий
+ Входящий
+ Фоновый режим
+ Show
+ Скачать
+ Ошибка скачивания. Проверьте ваше интернет соединение или попробуйте позже.
+ Auth userid
+ Enter authentication userid (optionnal)
+ Display name
+ Enter display name (optionnal)
+ Enable UPNP
+ Manage
+ Please wait...
+ Updating messages database
+ Default account
+ Download provisioning
+ This assistant will download an existing configuration.
+ provisioning url
+ Your username will be %s (uppercase characters are not allowed). Do you accept ?
+ Account setup assistant
+ Accept
+ Deny
+ You should only accept if you have the same code (see above) as your correspondent
+ Remote is writing...
+ %i unread messages
+ Retry
+ Failed to download or apply remote provisioning profile...
+ Remote provisioning
+ Do you want to change the provisioning URI ?
+
diff --git a/res/values-sr/custom.xml b/res/values-sr/custom.xml
new file mode 100644
index 000000000..0d003a3e4
--- /dev/null
+++ b/res/values-sr/custom.xml
@@ -0,0 +1,25 @@
+
+
+ д МММ
+ ГГГГ МММ д ЧЧ:мм
+ ЧЧ:мм д МММ
+ ЧЧ:мм
+ linphone-mms-%s.jpg
+ Линфон
+ Услуга Линфона
+ Линфон
+ Линфон
+ Покрећем се
+ Уписан на „%s“
+ Нисам успео да се упишем на „%s“
+ Линфон %s телефон сагласан са СИП-ом (rfc 3261) под Гнуовом Јавном Лиценцом и2
+ http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications
+ Овај помоћник ће вам помоћи да користите СИП налог за ваше позиве.
+ Направи налог на линфон.орг-у
+ Већ имам налог линфон.орг-а
+ Већ имам СИП налог
+ Унесите ваше корисничко име и лозинку линфон.орг-а
+ Унесите ваше корисничко име, лозинку и домен СИП налога
+ корисничко име
+
+
diff --git a/res/values-sw600dp/non_localizable_strings.xml b/res/values-sw533dp/non_localizable_strings.xml
similarity index 100%
rename from res/values-sw600dp/non_localizable_strings.xml
rename to res/values-sw533dp/non_localizable_strings.xml
diff --git a/res/values/color.xml b/res/values/color.xml
index f07034e8d..eb868c090 100644
--- a/res/values/color.xml
+++ b/res/values/color.xml
@@ -25,4 +25,7 @@
#00000000
#CCCCCC
+
+ #ff000000
+ #ff262a2e
diff --git a/res/values/custom.xml b/res/values/custom.xml
index e767c7538..516f0f4a6 100644
--- a/res/values/custom.xml
+++ b/res/values/custom.xml
@@ -1,20 +1,23 @@
-
d MMM
EEEE MMM d HH:mm
HH:mm d MMM
HH:mm
linphone-mms-%s.jpg
-
+
Linphone
Linphone Service
Linphone
+ org.linphone
+ linphone contacts
+ vnd.android.cursor.item/org.linphone.profile
Linphone
Starting up
- Registered to %s
+ Registered to %s
Fails to register to %s
- Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2\n http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/m/help\n\n© 2011 Belledonne Communications
+ Linphone %s SIP (rfc 3261) compatible phone under GNU Public License V2
+ http://www.linphone.org\n\nInstructions\nhttp://www.linphone.org/user-guide.html\n\n© 2015 Belledonne Communications
This assistant will help you to use a SIP account for your calls.
Create an account on linphone.org
@@ -22,8 +25,8 @@
I already have a SIP account
Enter your linphone.org username and password
Enter your SIP account username, password and domain
-
- username
+ username
+ SIP
diff --git a/res/values/non_localizable_custom.xml b/res/values/non_localizable_custom.xml
index 50248a500..18ac3ec9c 100644
--- a/res/values/non_localizable_custom.xml
+++ b/res/values/non_localizable_custom.xml
@@ -2,12 +2,13 @@
false
-
+
true
622464153529
sip.linphone.org
+ stun.linphone.org
false
https://www.linphone.org/wizard.php
@@ -16,7 +17,8 @@
false
false
true
-
+ false
+
false
false
false
@@ -26,15 +28,19 @@
false
false
false
+ false
+ true
false
true
-
+ true
+ false
+
false
false
false
- false
-
+ true
+
false
true
false
@@ -43,13 +49,14 @@
false
true
false
-
+
false
-
+ true
+
true
false
false
-
+
true
false
@@ -59,19 +66,30 @@
true
false
false
+ false
false
-
+ true
+ false
+ false
+ true
+ false
+
+ false
+ false
+ false
+
true
-
+
false
false
false
false
-
+
linphone-android@belledonne-communications.com
linphone-android-photo-temp.jpg
linphone-android-photo-%s.jpg
-
+
true
+ true
-
+
diff --git a/res/values/non_localizable_defaults.xml b/res/values/non_localizable_defaults.xml
deleted file mode 100644
index 271048727..000000000
--- a/res/values/non_localizable_defaults.xml
+++ /dev/null
@@ -1,67 +0,0 @@
-
-
-
-
- 443
- @string/tunnel_mode_entry_value_disabled
-
- true
-
- true
- true
- true
- false
- true
- false
- true
- false
- false
- true
- false
- true
- true
-
-
- true
- true
- true
- true
- true
-
- true
- false
- false
- false
-
-
- false
- stun.linphone.org
- false
- true
- 5060
- @string/pref_transport_udp_key
- 7078
- 9078
- @string/pref_media_encryption_key_none
- false
- false
-
-
- false
- false
- false
- 30
- https://www.linphone.org:444/upload.php
-
- 0
- 3600
- Linphone Android
- linphone.android
-
- false
-
- false
- true
-
- true
-
\ No newline at end of file
diff --git a/res/values/non_localizable_strings.xml b/res/values/non_localizable_strings.xml
index cf20690e0..8830a329b 100644
--- a/res/values/non_localizable_strings.xml
+++ b/res/values/non_localizable_strings.xml
@@ -16,8 +16,8 @@
- @string/tunnel_mode_entry_value_disabled
- @string/tunnel_mode_entry_value_3G_only
- @string/tunnel_mode_entry_value_always
- - @string/tunnel_mode_entry_value_auto
-
+ - @string/tunnel_mode_entry_value_auto
+
pref_tunnel_host_key
pref_tunnel_port_key
auto
@@ -27,13 +27,15 @@
pref_audio_hacks_use_routing_api_key
pref_audio_soft_volume_key
pref_audio_ringtone
-
+
pref_ipv6_key
-
+
menu_about_key
pref_sipaccounts_key
setup_key
+ pref_add_account_key
pref_video_key
+ pref_video_codecs_key
pref_linphone_friend_key
pref_transport_key
@@ -49,13 +51,14 @@
pref_domain_key
pref_passwd_key
pref_username_key
+ pref_auth_userid_key
pref_wizard_key
pref_activated_key
pref_debug_key
first_launch_suceeded_once_key
pref_wifi_only_key
-
+
pref_video_use_front_camera_key
pref_video_codec_h263_key
pref_video_codec_mpeg4_key
@@ -64,6 +67,10 @@
pref_video_automatically_accept_video_key
pref_video_initiate_call_with_video_key
pref_video_enable_key
+ pref_video_preset_key
+ pref_preferred_video_size_key
+ pref_preferred_video_fps_key
+ pref_bandwidth_limit_key
pref_animation_enable_key
pref_escape_plus_key
pref_echo_cancellation_key
@@ -84,6 +91,7 @@
pref_codec_silk12_key
pref_codec_silk16_key
pref_codec_silk24_key
+ pref_codec_opus_key
pref_codecs_key
pref_stun_server_key
pref_ice_enable_key
@@ -92,24 +100,87 @@
none
srtp
zrtp
+ dtls
pref_background_mode_key
-
+ pref_codec_bitrate_limit_key
+ pref_adaptive_rate_control_key
+ pref_adaptive_rate_algorithm
+ pref_adaptive_rate_algorithm_simple_key
+ pref_adaptive_rate_algorithm_stateful_key
+
push_reg_id_key
push_sender_id_key
pref_push_notification_key
-
+
pref_auto_accept_friends_key
pref_image_sharing_server_key
pref_remote_provisioning_key
-
+
pref_video_port_key
pref_audio_port_key
pref_incoming_expire_key
-
+
pref_display_name_key
pref_user_name_key
pref_expire_key
-
+ pref_avpf_key
+ pref_avpf_rr_interval_key
+
pref_rfc2833_dtmf_key
pref_sipinfo_dtmf_key
+ pref_voice_mail_key
+ pref_upnp_enable_key
+
+ pref_first_time_linphone_chat_storage
+
+ pref_sipaccount_key
+ pref_advanced_key
+ pref_manage_key
+
+
+ H263
+ MP4V-ES
+ H264
+ pcma
+ pcmu
+ gsm
+ g722
+ amr
+ amr-wb
+ ilbc
+ speex 8 Khz
+ speex 16 Khz
+ opus 48Khz
+ silk 8 Khz
+ silk 12 Khz
+ silk 16 Khz
+ silk 24 Khz
+ g729
+
+ - 10
+ - 15
+ - 20
+ - 36
+ - 64
+ - 128
+
+
+ - Simple
+ - Stateful
+
+ VP8
+ SRTP
+ ZRTP
+ DTLS
+
+ Debug
+
+ - Enable logs
+ - Cancel
+
+
+ - Disable logs
+ - Send logs
+ - Cancel
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index 74c9b9f7a..baf5f687c 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -1,422 +1,410 @@
-
+
- Disable
-
- Tunnel
- Hostname
- Port
- Mode
+ Disable
+ Tunnel
+ Hostname
+ Port
+ Mode
+
+
+ - disabled
+ - 3G only
+ - always
+ - auto
+
+ Audio call ongoing
+ Paused call ongoing
+ Video capturing call ongoing
+ Not ready for a new call
+ Bad contact : %s
+ Reset verified %s
+ Verify %s
+ Encrypted
+ Starting up…
+ An error occurred while accepting call
+ Error adding new call
+ Transfer initiated
+ Transfer call to
+ New call
+ Resume call
+ Cannot resume call paused by remote
+ Show details
+ Warning: service is not ready
+ Close
+ conf
+ active
+ paused
+ paused by remote
+
+ incoming
+ ringing
+ calling
+ Mute
+ Speaker
+ Bluetooth
+ Cancel
+ Add call
+ Transfer call
+ Enter conference
+ Momentarily leave conference
+ Terminate conference
+ Hang up
+ Merge
+ Transfer
+ video
+
+ Dialpad
+ Conference
+ You are part of it
+ Go out
+ You are out of it
+ Go in
+ Audio hacks
+ Use specific mode hack
+ 0=MODE_NORMAL (default), 2=MODE_IN_CALL
+ Use routing API hack
+ Use Galaxy S audio hack
+ Use software volume
+ Use ipv6 instead of ipv4
+ Error while accepting pending call
+ %s is calling you
+ Accept
+ Decline
+ Unknown
+ Network
+ Transport
+ UDP
+ TCP
+ TLS
+ Use random ports
+ SIP port to use
+ At least one item is required
+ Registration successful
+ Error
+ Start
+ Application not ready
+ Add account
+ No phone numbers found for %s
+ Filter contacts
+ %s\'s phone numbers
+ Delete this account
+ Use as default
+ Echo canceller calibration
+ Use front camera
+ Video
+ Preferences
+ Codecs
+ Preferred video size
+ Display dialer
+ Front/Rear Camera
+ Try High resolution
+ Low resolution
+ Change resolution
+ Mute/Unmute camera
+ Disable camera
+ Enable camera
+ Terminate call
+ Video settings
+ Share my camera
+ Accept incoming video requests
+ Automatically send my camera
+ Always accept video requests
+ Initiate video calls
+ Always send video requests
+ Enable Video
+ Bandwidth limit in kbits/s
+ Enable Animations
+ Replace + by 00
+ iLBC might be unavailable depending on ARM processor and Android OS version.
+ Echo cancellation
+ Start at boot time
+ Outbound proxy
-
-
- - disabled
- - 3G only
- - always
- - auto
-
+ Codecs
+ Communication timeout
+ Incoming call timeout
+ Video port or port range
+ Audio port or port range
+ Video port or port range (minport-maxport)
+ Audio port or port range (minport-maxport)
+ Incoming call timeout (in seconds)
+ Place a call
+ Adaptive rate control
+ Adaptive rate algorithm
+ Codec bitrate limit
+
+ - 10 kbits/s
+ - 15 kbits/s
+ - 20 kbits/s
+ - 36 kbits/s
+ - 64 kbits/s
+ - 128 kbits/s
+
- Audio call ongoing
- Paused call ongoing
- Video capturing call ongoing
-
- Not ready for a new call
- Bad contact : %s
- Reset verified %s
- Verify %s
- Encrypted
-
- Starting up…
- An error occurred while accepting call
-
- Error adding new call
- Transfer initiated
- Transfer call to
- New call
- Resume call
- Cannot resume call paused by remote
- Show details
-
- Warning: service is not ready
-
- Close
-
- conf
- active
- paused
- paused by remote
-
- incoming
- ringing
- calling
-
- Mute
- Speaker
- Bluetooth
-
- Cancel
- Add call
- Transfer call
-
- Enter conference
- Momentarily leave conference
- Terminate conference
-
- Hang up
- Merge
- Transfer
- video
-
- Dialpad
-
- Conference
- You are part of it
- Go out
- You are out of it
- Go in
-
- Audio hacks
- Use specific mode hack
- 0=MODE_NORMAL (default), 2=MODE_IN_CALL
- Use routing API hack
- Use Galaxy S audio hack
-
- Use software volume
-
- Use ipv6 instead of ipv4
-
- Error while accepting pending call
- %s is calling you
- Accept
- Decline
- Unknown
-
- Network
- Transport
- UDP
- TCP
- TLS
- Use random ports
- SIP port to use
- At least one item is required
-
- Registration successful
- Error
- Start
- Application not ready
-
- Add account
- No phone numbers found for %s
- Filter contacts
- %s\'s phone numbers
- Delete this account
- Use as default
- Echo canceller calibration
- Use front camera
- Video
- Preferences
- H263
- MPEG4
- H264
- Codecs
- pref_video_codecs_key
- Display dialer
- Front/Rear Camera
- Try High resolution
- Low resolution
- Change resolution
- Mute/Unmute camera
- Disable camera
- Enable camera
- Terminate call
- Video settings
- Share my camera
- Accept incoming video requests
- Automatically send my camera
- Always accept video requests
- Initiate video calls
- Always send video requests
- Enable Video
- Enable Animations
- Replace + by 00
- iLBC might be unavailable depending on ARM processor and Android OS version.
- Echo cancellation
- Start at boot time
- Outbound proxy
- pcma
- pcmu
- gsm
- g722
- amr
- amr-wb
- ilbc
- speex 8 Khz
- speex 16 Khz
- silk 8 Khz
- silk 12 Khz
- silk 16 Khz
- silk 24 Khz
- g729
- Codecs
- Communication timeout
- Incoming call timeout
- Video port or port range
- Audio port or port range
- Video port or port range (minport-maxport)
- Audio port or port range (minport-maxport)
- Incoming call timeout (in seconds)
- Place a call
-
- Debug
- Report issue
- Describe problem here
- Error generating bug report
- Logs not found.
- Reading logs, may takes time…
- Send bug report with…
- About
- Audio
- Exit
- Prefix
- Advanced
- Settings
- Proxy
- Domain*
- Password*
- Username*
- SIP Account
- wrong user name
- wrong password
- Wrong domain
- Wrong settings
- Dialer
- Contact
- Cannot call %s
- Yes
- No
- Dismiss
- Continue
- Never remind me
- %s, do you want to go to the settings page ?
- Starting echo cancelation audio calibration
- Cannot initiate a new call because a call is already engaged
- History
- Cannot build destination address from [%s]
- Clear
- Cannot get call parameters
- Cannot create default call parameters
- Cannot invite destination address [%s]
-
- started
- Removes the echo heard by other end
- Stun server
- Enable ICE
- A STUN server must be configured to use ICE
- Calibrating…
- Calibrated [%s ms]
- No echofailed
- Enter your username and password to connect to the service.
- Username
- Password
- Connect
- Please enter your login and password
- Couldn\'t connect; check your login and password and start again
-
- AMR codec might not be present on your phone
- VP8
- Media encryption
- None
- SRTP
- ZRTP
-
- Codec disabled, build the app from source code to enable it
- Codec disabled, build the app from source code to enable it
-
- SIP Accounts
- Use wifi only
- Enable push notifications
-
- An error occurred, try again later.
- Server unreachable, verify your internet connection.
- This username is already in use.
- Your username is not valid.
- Your email is not valid.
- Your password is not valid (6 characters min).
- Passwords entered are different.
-
- SIP proxy hostname or ip address (optional)
- Route all calls through SIP proxy
- Example: john if your account is john@sip.example.org
- sip.example.org if your account is john@sip.example.org
-
- Delete
- Chat
- Call
- Add to contacts
- Registered
- Not Registered
- Registration in progress
- Registration failed
-
- Number or address
- Conference
- Incoming call
- Draft
- Enter a SIP address to chat with…
- No call in your history.
- No missed call in your history.
- No contact in your address book.
- No SIP contact in your address book.
- No chat history.
-
- Audio
- Video
- Codec:
- Upload bandwidth:
- Download bandwidth:
- ICE connectivity:
-
-
- Add to contacts button
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Account Setup Assistant
- Apply
- password
- domain
- confirm password
- email
- Create Account
- An email has been sent to the address you gave. In order to activate your account, you need to click on the link inside it. Once it is done, come back here and click on the button above.
- Check
- Your account has not been validated yet.
- Your account has been validated.
-
- History
- Contacts
- Settings
- Chat
- About
-
- Cancel
- Back
- Let\'s go
-
- New conversation
- Edit
- Cancel
- Okay
- All
- SIP
- New contact
- All
- Missed
- Delete
-
- Transfer
- Add call
- Video
- Micro
- Speaker
- Route
- Receiver
- Bluetooth
- Options
-
- Send
- Pic
- Uploading…
-
- Call update requested
- Your correspondent would like to add video to the current call.
- Accept
- Decline
-
- Small
- Medium
- Large
- Real size
- Save picture
- Text copied to clipboard
- Copy text
- Select source
- Image saved
- Error, image not saved
-
- Friends
- New friends
- utomatically accept new friend requests
- Friend request
- wants to share it\'s presence status with you and be aware of yours.
- Echo canceller calibration in progress
- Sharing server
- Remote provisioning
-
- Delete contact
- SIP address
- Phone number
- First name
- Last name
-
- Primary account
- Display name
- Username
- Expire
-
- Send RFC2833 DTMFs
- Send SIP INFO DTMFs
-
- Call declined
- User not found
- Incompatible media parameters
- Your correspondent has low bandwidth, video can\'t be started
- Network is unreachable
-
- Today
- Yesterday
-
- Missed
- Outgoing
- Incoming
-
- Background mode
-
- Download
- Download failed. Check your internet connection or try again later.
-
+ Debug
+ Report issue
+ Describe problem here
+ Error generating bug report
+ Logs not found.
+ Reading logs, may takes time…
+ Send bug report with…
+ About
+ Send log
+ Reset log
+ Audio
+ Exit
+ Prefix
+ Advanced
+ Settings
+ Proxy
+ Domain*
+ Password*
+ Username*
+ SIP Account
+ wrong user name
+ wrong password
+ Wrong domain
+ Wrong settings
+ Dialer
+ Contact
+ Cannot call %s
+ Yes
+ No
+ Dismiss
+ Continue
+ Never remind me
+ %s, do you want to go to the settings page ?
+ Starting echo cancelation audio calibration
+ Cannot initiate a new call because a call is already engaged
+ History
+ Cannot build destination address from [%s]
+ Clear
+ Cannot get call parameters
+ Cannot create default call parameters
+ Cannot invite destination address [%s]
+ started
+ Removes the echo heard by other end
+ Stun server
+ Enable ICE
+ A STUN server must be configured to use ICE
+ Calibrating…
+ Calibrated [%s ms]
+ No echo
+ failed
+ Enter your username and password to connect to the service.
+ Username
+ Password
+ Connect
+ Please enter your login and password
+ Couldn\'t connect; check your login and password and start again
+ AMR codec might not be present on your phone
+ Media encryption
+ None
+ Codec disabled, build the app from source code to enable it
+ Codec disabled, build the app from source code to enable it
+ SIP Accounts
+ Use wifi only
+ Enable push notifications
+ An error occurred, try again later.
+ Server unreachable, verify your internet connection.
+ This username is already in use.
+ Your username is not valid.
+ Your email is not valid.
+ Your password is not valid (6 characters min).
+ Passwords entered are different.
+ SIP proxy hostname or ip address (optional)
+ Route all calls through SIP proxy
+ Example: john if your account is john@sip.example.org
+ sip.example.org if your account is john@sip.example.org
+ You have to re-enter your password if you edit your username and/or the domain
+ Delete
+ Chat
+ Call
+ Add to contacts
+ Registered
+ Not Registered
+ Registration in progress
+ Registration failed
+ Number or address
+ Conference
+ Incoming call
+ Draft
+ Enter a SIP address to chat with…
+ No call in your history.
+ No missed call in your history.
+ No contact in your address book.
+ No SIP contact in your address book.
+ No chat history.
+ Audio
+ Video
+ Codec:
+ Upload bandwidth:
+ Download bandwidth:
+ ICE connectivity:
+ Video size:
+
+ Add to contacts
+ New contact
+ Call
+ Backspace
+ About page
+ Chat
+ Dial back
+ Contact picture
+ Send message
+ Detail
+ Delete button
+ Add button
+ New discussion
+ Edit button
+ Validate button
+ Search
+ All contacts
+ Linphone contacts
+ Call direction
+ All calls
+ Missed calls
+ Switch video
+ Toggle speaker
+ Toggle micro
+ Add call
+ Pause
+ Hang up
+ Numpad
+ Settings button
+ Dialer
+ History button
+ Chat button
+ Contacts button
+
+ Call quality
+ Encryption
+ Switch camera
+ Welcome to the account setup assistant
+ Cancel
+ Cancel button
+ Next button
+ Back button
+ Ok
+ Message status
+ Conference
+
+ Account Setup Assistant
+ Apply
+ password
+ domain
+ confirm password
+ email
+ Create Account
+ An email has been sent to the address you gave. In order to activate your account, you need to click on the link inside it. Once it is done, come back here and click on the button above.
+ Check
+ Your account has not been validated yet.
+ Your account has been validated.
+ History
+ Contacts
+ Settings
+ Chat
+ About
+ Cancel
+ Back
+ Let\'s go
+ New conversation
+ Edit
+ Cancel
+ Okay
+ Back
+ All
+ New contact
+ All
+ Missed
+ Delete
+ Transfer
+ Add call
+ Video
+ Micro
+ Speaker
+ Route
+ Receiver
+ Bluetooth
+ Options
+ Send
+ Pic
+ Uploading…
+ Call update requested
+ Your correspondent would like to add video to the current call.
+ Accept
+ Decline
+ Small
+ Medium
+ Large
+ Real size
+ Save picture
+ Text copied to clipboard
+ Copy text
+ Select source
+ Image saved
+ Error, image not saved
+ Friends
+ New friends
+ Automatically accept new friend requests
+ Friend request
+ wants to share it\'s presence status with you and be aware of yours.
+ Echo canceller calibration in progress
+ Sharing server
+ Remote provisioning
+ Delete
+ This contact will be deleted.
+ SIP address
+ Phone number
+ First name
+ Last name
+ Primary account
+ Display name
+ Username
+ Expire
+ AVPF
+ AVPF regular RTCP interval in seconds (between 1 and 5)
+ Send RFC2833 DTMFs
+ Send SIP INFO DTMFs
+ Voice mail uri
+ unread messages
+ Unknown error
+ Call declined
+ User not found
+ Incompatible media parameters
+ Your correspondent has low bandwidth, video can\'t be started
+ Network is unreachable
+ Today
+ Yesterday
+ Missed
+ Outgoing
+ Incoming
+ Background mode
+ Show
+ Download
+ Download failed. Please check your internet access or try again later.
+ Auth userid
+ Enter authentication userid (optionnal)
+ Display name
+ Enter display name (optionnal)
+ Enable UPNP
+ Manage
+ Please wait...
+ Updating messages database
+ Default account
+ Download provisioning
+ This assistant will download an existing configuration.
+ provisioning url
+ The configuration you downloaded doesn\'t include your account. Please fill it in.
+ Your username will be %s.\r\n\r\nIt may differ from what you entered to match some requierements.\r\nDo you accept ?
+ Account setup assistant
+ Accept
+ Deny
+ You should only accept if you have the same code (see above) as your correspondent
+ Remote is writing...
+ %i unread messages
+ Retry
+ Failed to download or apply remote provisioning profile...
+ Remote provisioning
+ Do you want to change the provisioning URI ?
+ Processing image, can take up to a few seconds depending on the size of the file
diff --git a/res/xml/account_preferences.xml b/res/xml/account_preferences.xml
index 2c23bfeb1..ae8bcd940 100644
--- a/res/xml/account_preferences.xml
+++ b/res/xml/account_preferences.xml
@@ -2,15 +2,22 @@
+ android:title="@string/pref_sipaccount"
+ android:key="@string/pref_sipaccount_key">
+
+
+
+
+ android:title="@string/pref_advanced"
+ android:key="@string/pref_advanced_key">
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/xml/authenticator.xml b/res/xml/authenticator.xml
new file mode 100644
index 000000000..d2516eac0
--- /dev/null
+++ b/res/xml/authenticator.xml
@@ -0,0 +1,8 @@
+
+
+
\ No newline at end of file
diff --git a/res/xml/contacts.xml b/res/xml/contacts.xml
new file mode 100644
index 000000000..f05076c82
--- /dev/null
+++ b/res/xml/contacts.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/res/xml/preferences.xml b/res/xml/preferences.xml
index 12a0438b9..23384f475 100644
--- a/res/xml/preferences.xml
+++ b/res/xml/preferences.xml
@@ -4,377 +4,286 @@
-
-
-
+
+
-
-
-
+
+
+ android:key="@string/pref_tunnel_host_key"/>
-
+ android:key="@string/pref_tunnel_port_key"
+ android:numeric="integer"/>
-
-
+ android:entryValues="@array/tunnel_mode_entry_values"/>
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
-
-
-
-
-
-
+
+
-
-
-
+ android:key="@string/pref_push_notification_key"/>
+
+
+
-
-
-
-
-
-
+
+
-
-
-
-
+
+
+
+
-
-
+
+
-
-
-
-
-
-
+
+
-
+ android:key="@string/pref_remote_provisioning_key"/>
+
-
-
-
-
-
+
-
+
-
-
-
-
-
-
+
+
+
+
-
+
-
+
-
+
-
-
-
+ android:key="@string/pref_auto_accept_friends_key"
+ android:summary="@string/pref_auto_accept_friends_desc"/>
+
diff --git a/res/xml/syncadapter.xml b/res/xml/syncadapter.xml
new file mode 100644
index 000000000..0b7795d77
--- /dev/null
+++ b/res/xml/syncadapter.xml
@@ -0,0 +1,7 @@
+
+
+
diff --git a/sample/.classpath b/sample/.classpath
new file mode 100644
index 000000000..d8c730618
--- /dev/null
+++ b/sample/.classpath
@@ -0,0 +1,13 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sample/.project b/sample/.project
new file mode 100644
index 000000000..7a87b9fca
--- /dev/null
+++ b/sample/.project
@@ -0,0 +1,33 @@
+
+
+ LinphoneMini
+
+
+
+
+
+ com.android.ide.eclipse.adt.ResourceManagerBuilder
+
+
+
+
+ com.android.ide.eclipse.adt.PreCompilerBuilder
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+ com.android.ide.eclipse.adt.ApkBuilder
+
+
+
+
+
+ com.android.ide.eclipse.adt.AndroidNature
+ org.eclipse.jdt.core.javanature
+
+
diff --git a/sample/AndroidManifest.xml b/sample/AndroidManifest.xml
new file mode 100644
index 000000000..d777f53ed
--- /dev/null
+++ b/sample/AndroidManifest.xml
@@ -0,0 +1,35 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sample/README b/sample/README
new file mode 100644
index 000000000..8b9e5ff3d
--- /dev/null
+++ b/sample/README
@@ -0,0 +1,3 @@
+Fist compile linphone libraries using the makefile in the parent folder (with the make command)
+Then set the url to your configuration in the res/raw/linphonerc_default file
+Finally install and run this app on your device (using eclipse for example)
diff --git a/sample/libs b/sample/libs
new file mode 120000
index 000000000..d4bda9b46
--- /dev/null
+++ b/sample/libs
@@ -0,0 +1 @@
+../libs
\ No newline at end of file
diff --git a/sample/res/drawable-xhdpi/ic_launcher.png b/sample/res/drawable-xhdpi/ic_launcher.png
new file mode 100644
index 000000000..71c6d760f
Binary files /dev/null and b/sample/res/drawable-xhdpi/ic_launcher.png differ
diff --git a/sample/res/raw/linphonerc_default b/sample/res/raw/linphonerc_default
new file mode 100644
index 000000000..73bc9fb1e
--- /dev/null
+++ b/sample/res/raw/linphonerc_default
@@ -0,0 +1,23 @@
+[net]
+download_bw=380
+upload_bw=380
+
+[sip]
+contact=sip:unknown@unknown-host
+use_info=0
+use_ipv6=0
+keepalive_period=30000
+
+[video]
+size=qvga
+
+[app]
+sharing_server=https://www.linphone.org:444/upload.php
+tunnel=disabled
+
+[tunnel]
+host=
+port=443
+
+[misc]
+config-uri=INSERT_URL_TO_CONFIG_TO_TRY_HERE
\ No newline at end of file
diff --git a/sample/res/raw/linphonerc_factory b/sample/res/raw/linphonerc_factory
new file mode 100644
index 000000000..2dc6a2670
--- /dev/null
+++ b/sample/res/raw/linphonerc_factory
@@ -0,0 +1,30 @@
+[net]
+mtu=1300
+
+[sip]
+guess_hostname=1
+inc_timeout=15
+register_only_when_network_is_up=1
+auto_net_state_mon=0
+auto_answer_replacing_calls=1
+media_encryption_mandatory=0
+ping_with_options=0
+
+[rtp]
+audio_rtp_port=7076
+video_rtp_port=9078
+audio_jitt_comp=60
+video_jitt_comp=60
+nortp_timeout=30
+disable_upnp=1
+
+[sound]
+playback_dev_id=
+ringer_dev_id=
+capture_dev_id=
+remote_ring=/data/data/org.linphone.mini/files/ringback.wav
+local_ring=/data/data/org.linphone.mini/files/oldphone_mono.wav
+dtmf_player_amp=0.1
+
+[misc]
+max_calls=10
diff --git a/sample/res/raw/lpconfig.xsd b/sample/res/raw/lpconfig.xsd
new file mode 100644
index 000000000..49bb56180
--- /dev/null
+++ b/sample/res/raw/lpconfig.xsd
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/sample/res/raw/oldphone_mono.wav b/sample/res/raw/oldphone_mono.wav
new file mode 100644
index 000000000..39a1c9a80
Binary files /dev/null and b/sample/res/raw/oldphone_mono.wav differ
diff --git a/sample/res/raw/ringback.wav b/sample/res/raw/ringback.wav
new file mode 100644
index 000000000..21f4b5bfb
Binary files /dev/null and b/sample/res/raw/ringback.wav differ
diff --git a/sample/res/raw/rootca.pem b/sample/res/raw/rootca.pem
new file mode 100644
index 000000000..57388a337
--- /dev/null
+++ b/sample/res/raw/rootca.pem
@@ -0,0 +1,3895 @@
+##
+## /home/viish/Work/android/linphone/res/raw/rootca.pem -- Bundle of CA Root Certificates
+##
+## Certificate data from Mozilla as of: Sat Dec 29 20:03:40 2012
+##
+## This is a bundle of X.509 certificates of public Certificate Authorities
+## (CA). These were automatically extracted from Mozilla's root certificates
+## file (certdata.txt). This file can be found in the mozilla source tree:
+## https://mxr.mozilla.org/mozilla/source/security/nss/lib/ckfw/builtins/certdata.txt?raw=1
+##
+## It contains the certificates in PEM format and therefore
+## can be directly used with curl / libcurl / php_curl, or with
+## an Apache+mod_ssl webserver for SSL client authentication.
+## Just configure this file as the SSLCACertificateFile.
+##
+
+# @(#) $RCSfile: certdata.txt,v $ $Revision: 1.87 $ $Date: 2012/12/29 16:32:45 $
+
+GTE CyberTrust Global Root
+==========================
+-----BEGIN CERTIFICATE-----
+MIICWjCCAcMCAgGlMA0GCSqGSIb3DQEBBAUAMHUxCzAJBgNVBAYTAlVTMRgwFgYDVQQKEw9HVEUg
+Q29ycG9yYXRpb24xJzAlBgNVBAsTHkdURSBDeWJlclRydXN0IFNvbHV0aW9ucywgSW5jLjEjMCEG
+A1UEAxMaR1RFIEN5YmVyVHJ1c3QgR2xvYmFsIFJvb3QwHhcNOTgwODEzMDAyOTAwWhcNMTgwODEz
+MjM1OTAwWjB1MQswCQYDVQQGEwJVUzEYMBYGA1UEChMPR1RFIENvcnBvcmF0aW9uMScwJQYDVQQL
+Ex5HVEUgQ3liZXJUcnVzdCBTb2x1dGlvbnMsIEluYy4xIzAhBgNVBAMTGkdURSBDeWJlclRydXN0
+IEdsb2JhbCBSb290MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVD6C28FCc6HrHiM3dFw4u
+sJTQGz0O9pTAipTHBsiQl8i4ZBp6fmw8U+E3KHNgf7KXUwefU/ltWJTSr41tiGeA5u2ylc9yMcql
+HHK6XALnZELn+aks1joNrI1CqiQBOeacPwGFVw1Yh0X404Wqk2kmhXBIgD8SFcd5tB8FLztimQID
+AQABMA0GCSqGSIb3DQEBBAUAA4GBAG3rGwnpXtlR22ciYaQqPEh346B8pt5zohQDhT37qw4wxYMW
+M4ETCJ57NE7fQMh017l93PR2VX2bY1QY6fDq81yx2YtCHrnAlU66+tXifPVoYb+O7AWXX1uw16OF
+NMQkpw0PlZPvy5TYnh+dXIVtx6quTx8itc2VrbqnzPmrC3p/
+-----END CERTIFICATE-----
+
+Thawte Server CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDEzCCAnygAwIBAgIBATANBgkqhkiG9w0BAQQFADCBxDELMAkGA1UEBhMCWkExFTATBgNVBAgT
+DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
+dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcGA1UE
+AxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0ZS5j
+b20wHhcNOTYwODAxMDAwMDAwWhcNMjAxMjMxMjM1OTU5WjCBxDELMAkGA1UEBhMCWkExFTATBgNV
+BAgTDFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29u
+c3VsdGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEZMBcG
+A1UEAxMQVGhhd3RlIFNlcnZlciBDQTEmMCQGCSqGSIb3DQEJARYXc2VydmVyLWNlcnRzQHRoYXd0
+ZS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBANOkUG7I/1Zr5s9dtuoMaHVHoqrC2oQl
+/Kj0R1HahbUgdJSGHg91yekIYfUGbTBuFRkC6VLAYttNmZ7iagxEOM3+vuNkCXDF/rFrKbYvScg7
+1CcEJRCXL+eQbcAoQpnXTEPew/UhbVSfXcNY4cDk2VuwuNy0e982OsK1ZiIS1ocNAgMBAAGjEzAR
+MA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEEBQADgYEAB/pMaVz7lcxG7oWDTSEwjsrZqG9J
+GubaUeNgcGyEYRGhGshIPllDfU+VPaGLtwtimHp1it2ITk6eQNuozDJ0uW8NxuOzRAvZim+aKZuZ
+GCg70eNAKJpaPNW15yAbi8qkq43pUdniTCxZqdq5snUb9kLy78fyGPmJvKP/iiMucEc=
+-----END CERTIFICATE-----
+
+Thawte Premium Server CA
+========================
+-----BEGIN CERTIFICATE-----
+MIIDJzCCApCgAwIBAgIBATANBgkqhkiG9w0BAQQFADCBzjELMAkGA1UEBhMCWkExFTATBgNVBAgT
+DFdlc3Rlcm4gQ2FwZTESMBAGA1UEBxMJQ2FwZSBUb3duMR0wGwYDVQQKExRUaGF3dGUgQ29uc3Vs
+dGluZyBjYzEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjEhMB8GA1UE
+AxMYVGhhd3RlIFByZW1pdW0gU2VydmVyIENBMSgwJgYJKoZIhvcNAQkBFhlwcmVtaXVtLXNlcnZl
+ckB0aGF3dGUuY29tMB4XDTk2MDgwMTAwMDAwMFoXDTIwMTIzMTIzNTk1OVowgc4xCzAJBgNVBAYT
+AlpBMRUwEwYDVQQIEwxXZXN0ZXJuIENhcGUxEjAQBgNVBAcTCUNhcGUgVG93bjEdMBsGA1UEChMU
+VGhhd3RlIENvbnN1bHRpbmcgY2MxKDAmBgNVBAsTH0NlcnRpZmljYXRpb24gU2VydmljZXMgRGl2
+aXNpb24xITAfBgNVBAMTGFRoYXd0ZSBQcmVtaXVtIFNlcnZlciBDQTEoMCYGCSqGSIb3DQEJARYZ
+cHJlbWl1bS1zZXJ2ZXJAdGhhd3RlLmNvbTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA0jY2
+aovXwlue2oFBYo847kkEVdbQ7xwblRZH7xhINTpS9CtqBo87L+pW46+GjZ4X9560ZXUCTe/LCaIh
+Udib0GfQug2SBhRz1JPLlyoAnFxODLz6FVL88kRu2hFKbgifLy3j+ao6hnO2RlNYyIkFvYMRuHM/
+qgeN9EJN50CdHDcCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQQFAAOBgQAm
+SCwWwlj66BZ0DKqqX1Q/8tfJeGBeXm43YyJ3Nn6yF8Q0ufUIhfzJATj/Tb7yFkJD57taRvvBxhEf
+8UqwKEbJw8RCfbz6q1lu1bdRiBHjpIUZa4JMpAwSremkrj/xw0llmozFyD4lt5SZu5IycQfwhl7t
+UCemDaYj+bvLpgcUQg==
+-----END CERTIFICATE-----
+
+Equifax Secure CA
+=================
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAomgAwIBAgIENd70zzANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEQMA4GA1UE
+ChMHRXF1aWZheDEtMCsGA1UECxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5
+MB4XDTk4MDgyMjE2NDE1MVoXDTE4MDgyMjE2NDE1MVowTjELMAkGA1UEBhMCVVMxEDAOBgNVBAoT
+B0VxdWlmYXgxLTArBgNVBAsTJEVxdWlmYXggU2VjdXJlIENlcnRpZmljYXRlIEF1dGhvcml0eTCB
+nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAwV2xWGcIYu6gmi0fCG2RFGiYCh7+2gRvE4RiIcPR
+fM6fBeC4AfBONOziipUEZKzxa1NfBbPLZ4C/QgKO/t0BCezhABRP/PvwDN1Dulsr4R+AcJkVV5MW
+8Q+XarfCaCMczE1ZMKxRHjuvK9buY0V7xdlfUNLjUA86iOe/FP3gx7kCAwEAAaOCAQkwggEFMHAG
+A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEQMA4GA1UEChMHRXF1aWZheDEtMCsGA1UE
+CxMkRXF1aWZheCBTZWN1cmUgQ2VydGlmaWNhdGUgQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMBoG
+A1UdEAQTMBGBDzIwMTgwODIyMTY0MTUxWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUSOZo+SvS
+spXXR9gjIBBPM5iQn9QwHQYDVR0OBBYEFEjmaPkr0rKV10fYIyAQTzOYkJ/UMAwGA1UdEwQFMAMB
+Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAFjOKer89961
+zgK5F7WF0bnj4JXMJTENAKaSbn+2kmOeUJXRmm/kEd5jhW6Y7qj/WsjTVbJmcVfewCHrPSqnI0kB
+BIZCe/zuf6IWUrVnZ9NA2zsmWLIodz2uFHdh1voqZiegDfqnc1zqcPGUIWVEX/r87yloqaKHee95
+70+sB3c4
+-----END CERTIFICATE-----
+
+Digital Signature Trust Co. Global CA 1
+=======================================
+-----BEGIN CERTIFICATE-----
+MIIDKTCCApKgAwIBAgIENnAVljANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE
+ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMTAeFw05ODEy
+MTAxODEwMjNaFw0xODEyMTAxODQwMjNaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs
+IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUxMIGdMA0GCSqGSIb3DQEBAQUA
+A4GLADCBhwKBgQCgbIGpzzQeJN3+hijM3oMv+V7UQtLodGBmE5gGHKlREmlvMVW5SXIACH7TpWJE
+NySZj9mDSI+ZbZUTu0M7LklOiDfBu1h//uG9+LthzfNHwJmm8fOR6Hh8AMthyUQncWlVSn5JTe2i
+o74CTADKAqjuAQIxZA9SLRN0dja1erQtcQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo
+BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0
+dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTExDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw
+IoAPMTk5ODEyMTAxODEwMjNagQ8yMDE4MTIxMDE4MTAyM1owCwYDVR0PBAQDAgEGMB8GA1UdIwQY
+MBaAFGp5fpFpRhgTCgJ3pVlbYJglDqL4MB0GA1UdDgQWBBRqeX6RaUYYEwoCd6VZW2CYJQ6i+DAM
+BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB
+ACIS2Hod3IEGtgllsofIH160L+nEHvI8wbsEkBFKg05+k7lNQseSJqBcNJo4cvj9axY+IO6CizEq
+kzaFI4iKPANo08kJD038bKTaKHKTDomAsH3+gG9lbRgzl4vCa4nuYD3Im+9/KzJic5PLPON74nZ4
+RbyhkwS7hp86W0N6w4pl
+-----END CERTIFICATE-----
+
+Digital Signature Trust Co. Global CA 3
+=======================================
+-----BEGIN CERTIFICATE-----
+MIIDKTCCApKgAwIBAgIENm7TzjANBgkqhkiG9w0BAQUFADBGMQswCQYDVQQGEwJVUzEkMCIGA1UE
+ChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMREwDwYDVQQLEwhEU1RDQSBFMjAeFw05ODEy
+MDkxOTE3MjZaFw0xODEyMDkxOTQ3MjZaMEYxCzAJBgNVBAYTAlVTMSQwIgYDVQQKExtEaWdpdGFs
+IFNpZ25hdHVyZSBUcnVzdCBDby4xETAPBgNVBAsTCERTVENBIEUyMIGdMA0GCSqGSIb3DQEBAQUA
+A4GLADCBhwKBgQC/k48Xku8zExjrEH9OFr//Bo8qhbxe+SSmJIi2A7fBw18DW9Fvrn5C6mYjuGOD
+VvsoLeE4i7TuqAHhzhy2iCoiRoX7n6dwqUcUP87eZfCocfdPJmyMvMa1795JJ/9IKn3oTQPMx7JS
+xhcxEzu1TdvIxPbDDyQq2gyd55FbgM2UnQIBA6OCASQwggEgMBEGCWCGSAGG+EIBAQQEAwIABzBo
+BgNVHR8EYTBfMF2gW6BZpFcwVTELMAkGA1UEBhMCVVMxJDAiBgNVBAoTG0RpZ2l0YWwgU2lnbmF0
+dXJlIFRydXN0IENvLjERMA8GA1UECxMIRFNUQ0EgRTIxDTALBgNVBAMTBENSTDEwKwYDVR0QBCQw
+IoAPMTk5ODEyMDkxOTE3MjZagQ8yMDE4MTIwOTE5MTcyNlowCwYDVR0PBAQDAgEGMB8GA1UdIwQY
+MBaAFB6CTShlgDzJQW6sNS5ay97u+DlbMB0GA1UdDgQWBBQegk0oZYA8yUFurDUuWsve7vg5WzAM
+BgNVHRMEBTADAQH/MBkGCSqGSIb2fQdBAAQMMAobBFY0LjADAgSQMA0GCSqGSIb3DQEBBQUAA4GB
+AEeNg61i8tuwnkUiBbmi1gMOOHLnnvx75pO2mqWilMg0HZHRxdf0CiUPPXiBng+xZ8SQTGPdXqfi
+up/1902lMXucKS1M/mQ+7LZT/uqb7YLbdHVLB3luHtgZg3Pe9T7Qtd7nS2h9Qy4qIOF+oHhEngj1
+mPnHfxsb1gYgAlihw6ID
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEHC65B0Q2Sk0tjjKewPMur8wDQYJKoZIhvcNAQECBQAwXzELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMTIzNTk1OVow
+XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz
+IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94
+f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol
+hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBAgUAA4GBALtMEivPLCYA
+TxQT3ab7/AoRhIzzKBxnki98tsX63/Dolbwdj2wsqFHMc9ikwFPwTtYmwHYBV4GSXiHx0bH/59Ah
+WM1pF+NEHJwZRDmJXNycAA9WjQKZ7aKQRUzkuxCkPfAyAw7xzvjoyVGM5mKf5p/AfbdynMk2Omuf
+Tqj/ZA1k
+-----END CERTIFICATE-----
+
+Verisign Class 1 Public Primary Certification Authority - G2
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIDAjCCAmsCEEzH6qqYPnHTkxD4PTqJkZIwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT
+MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMgUHJpbWFy
+eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
+dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT
+MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMSBQdWJsaWMgUHJpbWFy
+eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
+dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCq0Lq+Fi24g9TK0g+8djHKlNgd
+k4xWArzZbxpvUjZudVYKVdPfQ4chEWWKfo+9Id5rMj8bhDSVBZ1BNeuS65bdqlk/AVNtmU/t5eIq
+WpDBucSmFc/IReumXY6cPvBkJHalzasab7bYe1FhbqZ/h8jit+U03EGI6glAvnOSPWvndQIDAQAB
+MA0GCSqGSIb3DQEBBQUAA4GBAKlPww3HZ74sy9mozS11534Vnjty637rXC0Jh9ZrbWB85a7FkCMM
+XErQr7Fd88e2CtvgFZMN3QO8x3aKtd1Pw5sTdbgBwObJW2uluIncrKTdcu1OofdPvAbT6shkdHvC
+lUGcZXNY8ZCaPGqxmMnEh7zPRW1F4m4iP/68DzFc6PLZ
+-----END CERTIFICATE-----
+
+Verisign Class 2 Public Primary Certification Authority - G2
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIDAzCCAmwCEQC5L2DMiJ+hekYJuFtwbIqvMA0GCSqGSIb3DQEBBQUAMIHBMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1h
+cnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNp
+Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1
+c3QgTmV0d29yazAeFw05ODA1MTgwMDAwMDBaFw0yODA4MDEyMzU5NTlaMIHBMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xPDA6BgNVBAsTM0NsYXNzIDIgUHVibGljIFByaW1h
+cnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjE6MDgGA1UECxMxKGMpIDE5OTggVmVyaVNp
+Z24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1
+c3QgTmV0d29yazCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAp4gBIXQs5xoD8JjhlzwPIQjx
+nNuX6Zr8wgQGE75fUsjMHiwSViy4AWkszJkfrbCWrnkE8hM5wXuYuggs6MKEEyyqaekJ9MepAqRC
+wiNPStjwDqL7MWzJ5m+ZJwf15vRMeJ5t60aG+rmGyVTyssSv1EYcWskVMP8NbPUtDm3Of3cCAwEA
+ATANBgkqhkiG9w0BAQUFAAOBgQByLvl/0fFx+8Se9sVeUYpAmLho+Jscg9jinb3/7aHmZuovCfTK
+1+qlK5X2JGCGTUQug6XELaDTrnhpb3LabK4I8GOSN+a7xDAXrXfMSTWqz9iP0b63GJZHc2pUIjRk
+LbYWm1lbtFFZOrMLFPQS32eg9K0yZF6xRnInjBJ7xUS0rg==
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority - G2
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIDAjCCAmsCEH3Z/gfPqB63EHln+6eJNMYwDQYJKoZIhvcNAQEFBQAwgcExCzAJBgNVBAYTAlVT
+MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy
+eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
+dCBOZXR3b3JrMB4XDTk4MDUxODAwMDAwMFoXDTI4MDgwMTIzNTk1OVowgcExCzAJBgNVBAYTAlVT
+MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjE8MDoGA1UECxMzQ2xhc3MgMyBQdWJsaWMgUHJpbWFy
+eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMTowOAYDVQQLEzEoYykgMTk5OCBWZXJpU2ln
+biwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVzZSBvbmx5MR8wHQYDVQQLExZWZXJpU2lnbiBUcnVz
+dCBOZXR3b3JrMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDMXtERXVxp0KvTuWpMmR9ZmDCO
+FoUgRm1HP9SFIIThbbP4pO0M8RcPO/mn+SXXwc+EY/J8Y8+iR/LGWzOOZEAEaMGAuWQcRXfH2G71
+lSk8UOg013gfqLptQ5GVj0VXXn7F+8qkBOvqlzdUMG+7AUcyM83cV5tkaWH4mx0ciU9cZwIDAQAB
+MA0GCSqGSIb3DQEBBQUAA4GBAFFNzb5cy5gZnBWyATl4Lk0PZ3BwmcYQWpSkU01UbSuvDV1Ai2TT
+1+7eVmGSX6bEHRBhNtMsJzzoKQm5EWR0zLVznxxIqbxhAe7iF6YM40AIOw7n60RzKprxaZLvcRTD
+Oaxxp5EJb+RxBrO6WVcmeQD2+A2iMzAo1KpYoJ2daZH9
+-----END CERTIFICATE-----
+
+GlobalSign Root CA
+==================
+-----BEGIN CERTIFICATE-----
+MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkGA1UEBhMCQkUx
+GTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jvb3QgQ0ExGzAZBgNVBAMTEkds
+b2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAwMDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNV
+BAYTAkJFMRkwFwYDVQQKExBHbG9iYWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYD
+VQQDExJHbG9iYWxTaWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDa
+DuaZjc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavpxy0Sy6sc
+THAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp1Wrjsok6Vjk4bwY8iGlb
+Kk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdGsnUOhugZitVtbNV4FpWi6cgKOOvyJBNP
+c1STE4U6G7weNLWLBYy5d4ux2x8gkasJU26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrX
+gzT/LCrBbBlDSgeF59N89iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNV
+HRMBAf8EBTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0BAQUF
+AAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOzyj1hTdNGCbM+w6Dj
+Y1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE38NflNUVyRRBnMRddWQVDf9VMOyG
+j/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymPAbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhH
+hm4qxFYxldBniYUr+WymXUadDKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveC
+X4XSQRjbgbMEHMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==
+-----END CERTIFICATE-----
+
+GlobalSign Root CA - R2
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgILBAAAAAABD4Ym5g0wDQYJKoZIhvcNAQEFBQAwTDEgMB4GA1UECxMXR2xv
+YmFsU2lnbiBSb290IENBIC0gUjIxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
+bFNpZ24wHhcNMDYxMjE1MDgwMDAwWhcNMjExMjE1MDgwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
+aWduIFJvb3QgQ0EgLSBSMjETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
+bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKbPJA6+Lm8omUVCxKs+IVSbC9N/hHD6
+ErPLv4dfxn+G07IwXNb9rfF73OX4YJYJkhD10FPe+3t+c4isUoh7SqbKSaZeqKeMWhG8eoLrvozp
+s6yWJQeXSpkqBy+0Hne/ig+1AnwblrjFuTosvNYSuetZfeLQBoZfXklqtTleiDTsvHgMCJiEbKjN
+S7SgfQx5TfC4LcshytVsW33hoCmEofnTlEnLJGKRILzdC9XZzPnqJworc5HGnRusyMvo4KD0L5CL
+TfuwNhv2GXqF4G3yYROIXJ/gkwpRl4pazq+r1feqCapgvdzZX99yqWATXgAByUr6P6TqBwMhAo6C
+ygPCm48CAwEAAaOBnDCBmTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4E
+FgQUm+IHV2ccHsBqBt5ZtJot39wZhi4wNgYDVR0fBC8wLTAroCmgJ4YlaHR0cDovL2NybC5nbG9i
+YWxzaWduLm5ldC9yb290LXIyLmNybDAfBgNVHSMEGDAWgBSb4gdXZxwewGoG3lm0mi3f3BmGLjAN
+BgkqhkiG9w0BAQUFAAOCAQEAmYFThxxol4aR7OBKuEQLq4GsJ0/WwbgcQ3izDJr86iw8bmEbTUsp
+9Z8FHSbBuOmDAGJFtqkIk7mpM0sYmsL4h4hO291xNBrBVNpGP+DTKqttVCL1OmLNIG+6KYnX3ZHu
+01yiPqFbQfXf5WRDLenVOavSot+3i9DAgBkcRcAtjOj4LaR0VknFBbVPFd5uRHg5h6h+u/N5GJG7
+9G+dwfCMNYxdAfvDbbnvRG15RjF+Cv6pgsH/76tuIMRQyV+dTZsXjAzlAcmgQWpzU/qlULRuJQ/7
+TBj0/VLZjmmx6BEP3ojY+x1J96relc8geMJgEtslQIxq/H5COEBkEveegeGTLg==
+-----END CERTIFICATE-----
+
+ValiCert Class 1 VA
+===================
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp
+b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDEgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh
+bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNTIy
+MjM0OFoXDTE5MDYyNTIyMjM0OFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0
+d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDEg
+UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0
+LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDYWYJ6ibiWuqYvaG9YLqdUHAZu9OqNSLwxlBfw8068srg1knaw0KWlAdcAAxIi
+GQj4/xEjm84H9b9pGib+TunRf50sQB1ZaG6m+FiwnRqP0z/x3BkGgagO4DrdyFNFCQbmD3DD+kCm
+DuJWBQ8YTfwggtFzVXSNdnKgHZ0dwN0/cQIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFBoPUn0LBwG
+lN+VYH+Wexf+T3GtZMjdd9LvWVXoP+iOBSoh8gfStadS/pyxtuJbdxdA6nLWI8sogTLDAHkY7FkX
+icnGah5xyf23dKUlRWnFSKsZ4UWKJWsZ7uW7EvV/96aNUcPwnXS3qT6gpf+2SQMT2iLM7XGCK5nP
+Orf1LXLI
+-----END CERTIFICATE-----
+
+ValiCert Class 2 VA
+===================
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp
+b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDIgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh
+bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw
+MTk1NFoXDTE5MDYyNjAwMTk1NFowgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0
+d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDIg
+UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0
+LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDOOnHK5avIWZJV16vYdA757tn2VUdZZUcOBVXc65g2PFxTXdMwzzjsvUGJ7SVC
+CSRrCl6zfN1SLUzm1NZ9WlmpZdRJEy0kTRxQb7XBhVQ7/nHk01xC+YDgkRoKWzk2Z/M/VXwbP7Rf
+ZHM047QSv4dk+NoS/zcnwbNDu+97bi5p9wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBADt/UG9vUJSZ
+SWI4OB9L+KXIPqeCgfYrx+jFzug6EILLGACOTb2oWH+heQC1u+mNr0HZDzTuIYEZoDJJKPTEjlbV
+UjP9UNV+mWwD5MlM/Mtsq2azSiGM5bUMMj4QssxsodyamEwCW/POuZ6lcg5Ktz885hZo+L7tdEy8
+W9ViH0Pd
+-----END CERTIFICATE-----
+
+RSA Root Certificate 1
+======================
+-----BEGIN CERTIFICATE-----
+MIIC5zCCAlACAQEwDQYJKoZIhvcNAQEFBQAwgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRp
+b24gTmV0d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENs
+YXNzIDMgUG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZh
+bGljZXJ0LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMB4XDTk5MDYyNjAw
+MjIzM1oXDTE5MDYyNjAwMjIzM1owgbsxJDAiBgNVBAcTG1ZhbGlDZXJ0IFZhbGlkYXRpb24gTmV0
+d29yazEXMBUGA1UEChMOVmFsaUNlcnQsIEluYy4xNTAzBgNVBAsTLFZhbGlDZXJ0IENsYXNzIDMg
+UG9saWN5IFZhbGlkYXRpb24gQXV0aG9yaXR5MSEwHwYDVQQDExhodHRwOi8vd3d3LnZhbGljZXJ0
+LmNvbS8xIDAeBgkqhkiG9w0BCQEWEWluZm9AdmFsaWNlcnQuY29tMIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDjmFGWHOjVsQaBalfDcnWTq8+epvzzFlLWLU2fNUSoLgRNB0mKOCn1dzfnt6td
+3zZxFJmP3MKS8edgkpfs2Ejcv8ECIMYkpChMMFp2bbFc893enhBxoYjHW5tBbcqwuI4V7q0zK89H
+BFx1cQqYJJgpp0lZpd34t0NiYfPT4tBVPwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFa7AliEZwgs
+3x/be0kz9dNnnfS0ChCzycUs4pJqcXgn8nCDQtM+z6lU9PHYkhaM0QTLS6vJn0WuPIqpsHEzXcjF
+V9+vqDWzf4mH6eglkrh/hXqu1rweN1gqZ8mRzyqBPu3GOd/APhmcGcwTTYJBtYze4D1gCCAPRX5r
+on+jjBXu
+-----END CERTIFICATE-----
+
+Verisign Class 1 Public Primary Certification Authority - G3
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQCLW3VWhFSFCwDPrzhIzrGkMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
+cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
+dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDEgUHVibGljIFByaW1hcnkg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAN2E1Lm0+afY8wR4nN493GwTFtl63SRRZsDHJlkNrAYIwpTRMx/wgzUfbhvI3qpuFU5UJ+/E
+bRrsC+MO8ESlV8dAWB6jRx9x7GD2bZTIGDnt/kIYVt/kTEkQeE4BdjVjEjbdZrwBBDajVWjVojYJ
+rKshJlQGrT/KFOCsyq0GHZXi+J3x4GD/wn91K0zM2v6HmSHquv4+VNfSWXjbPG7PoBMAGrgnoeS+
+Z5bKoMWznN3JdZ7rMJpfo83ZrngZPyPpXNspva1VyBtUjGP26KbqxzcSXKMpHgLZ2x87tNcPVkeB
+FQRKr4Mn0cVYiMHd9qqnoxjaaKptEVHhv2Vrn5Z20T0CAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
+q2aN17O6x5q25lXQBfGfMY1aqtmqRiYPce2lrVNWYgFHKkTp/j90CxObufRNG7LRX7K20ohcs5/N
+y9Sn2WCVhDr4wTcdYcrnsMXlkdpUpqwxga6X3s0IrLjAl4B/bnKk52kTlWUfxJM8/XmPBNQ+T+r3
+ns7NZ3xPZQL/kYVUc8f/NveGLezQXk//EZ9yBta4GvFMDSZl4kSAHsef493oCtrspSCAaWihT37h
+a88HQfqDjrw43bAuEbFrskLMmrz5SCJ5ShkPshw+IHTZasO+8ih4E1Z5T21Q6huwtVexN2ZYI/Pc
+D98Kh8TvhgXVOBRgmaNL3gaWcSzy27YfpO8/7g==
+-----END CERTIFICATE-----
+
+Verisign Class 2 Public Primary Certification Authority - G3
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIEGTCCAwECEGFwy0mMX5hFKeewptlQW3owDQYJKoZIhvcNAQEFBQAwgcoxCzAJBgNVBAYTAlVT
+MRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1c3QgTmV0d29y
+azE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ug
+b25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eSAtIEczMB4XDTk5MTAwMTAwMDAwMFoXDTM2MDcxNjIzNTk1OVowgcoxCzAJ
+BgNVBAYTAlVTMRcwFQYDVQQKEw5WZXJpU2lnbiwgSW5jLjEfMB0GA1UECxMWVmVyaVNpZ24gVHJ1
+c3QgTmV0d29yazE6MDgGA1UECxMxKGMpIDE5OTkgVmVyaVNpZ24sIEluYy4gLSBGb3IgYXV0aG9y
+aXplZCB1c2Ugb25seTFFMEMGA1UEAxM8VmVyaVNpZ24gQ2xhc3MgMiBQdWJsaWMgUHJpbWFyeSBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEArwoNwtUs22e5LeWUJ92lvuCwTY+zYVY81nzD9M0+hsuiiOLh2KRpxbXiv8GmR1BeRjmL1Za6
+tW8UvxDOJxOeBUebMXoT2B/Z0wI3i60sR/COgQanDTAM6/c8DyAd3HJG7qUCyFvDyVZpTMUYwZF7
+C9UTAJu878NIPkZgIIUq1ZC2zYugzDLdt/1AVbJQHFauzI13TccgTacxdu9okoqQHgiBVrKtaaNS
+0MscxCM9H5n+TOgWY47GCI72MfbS+uV23bUckqNJzc0BzWjNqWm6o+sdDZykIKbBoMXRRkwXbdKs
+Zj+WjOCE1Db/IlnF+RFgqF8EffIa9iVCYQ/ESrg+iQIDAQABMA0GCSqGSIb3DQEBBQUAA4IBAQA0
+JhU8wI1NQ0kdvekhktdmnLfexbjQ5F1fdiLAJvmEOjr5jLX77GDx6M4EsMjdpwOPMPOY36TmpDHf
+0xwLRtxyID+u7gU8pDM/CzmscHhzS5kr3zDCVLCoO1Wh/hYozUK9dG6A2ydEp85EXdQbkJgNHkKU
+sQAsBNB0owIFImNjzYO1+8FtYmtpdf1dcEG59b98377BMnMiIYtYgXsVkXq642RIsH/7NiXaldDx
+JBQX3RiAa0YjOVT1jmIJBB2UkKab5iXiQkWquJCtvgiPqQtCGJTPcjnhsUPgKM+351psE2tJs//j
+GHyJizNdrDPXp/naOlXJWBD5qu9ats9LS98q
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority - G3
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQCbfgZJoz5iudXukEhxKe9XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
+cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
+dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDMgUHVibGljIFByaW1hcnkg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAMu6nFL8eB8aHm8bN3O9+MlrlBIwT/A2R/XQkQr1F8ilYcEWQE37imGQ5XYgwREGfassbqb1
+EUGO+i2tKmFZpGcmTNDovFJbcCAEWNF6yaRpvIMXZK0Fi7zQWM6NjPXr8EJJC52XJ2cybuGukxUc
+cLwgTS8Y3pKI6GyFVxEa6X7jJhFUokWWVYPKMIno3Nij7SqAP395ZVc+FSBmCC+Vk7+qRy+oRpfw
+EuL+wgorUeZ25rdGt+INpsyow0xZVYnm6FNcHOqd8GIWC6fJXwzw3sJ2zq/3avL6QaaiMxTJ5Xpj
+055iN9WFZZ4O5lMkdBteHRJTW8cs54NJOxWuimi5V5cCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
+ERSWwauSCPc/L8my/uRan2Te2yFPhpk0djZX3dAVL8WtfxUfN2JzPtTnX84XA9s1+ivbrmAJXx5f
+j267Cz3qWhMeDGBvtcC1IyIuBwvLqXTLR7sdwdela8wv0kL9Sd2nic9TutoAWii/gt/4uhMdUIaC
+/Y4wjylGsB49Ndo4YhYYSq3mtlFs3q9i6wHQHiT+eo8SGhJouPtmmRQURVyu565pF4ErWjfJXir0
+xuKhXFSbplQAz/DxwceYMBo7Nhbbo27q/a2ywtrvAkcTisDxszGtTxzhT5yvDwyd93gN2PQ1VoDa
+t20Xj50egWTh/sVFuq1ruQp6Tk9LhO5L8X3dEQ==
+-----END CERTIFICATE-----
+
+Verisign Class 4 Public Primary Certification Authority - G3
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIEGjCCAwICEQDsoKeLbnVqAc/EfMwvlF7XMA0GCSqGSIb3DQEBBQUAMIHKMQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
+cmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkgLSBHMzAeFw05OTEwMDEwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMIHKMQsw
+CQYDVQQGEwJVUzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRy
+dXN0IE5ldHdvcmsxOjA4BgNVBAsTMShjKSAxOTk5IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxRTBDBgNVBAMTPFZlcmlTaWduIENsYXNzIDQgUHVibGljIFByaW1hcnkg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAK3LpRFpxlmr8Y+1GQ9Wzsy1HyDkniYlS+BzZYlZ3tCD5PUPtbut8XzoIfzk6AzufEUiGXaS
+tBO3IFsJ+mGuqPKljYXCKtbeZjbSmwL0qJJgfJxptI8kHtCGUvYynEFYHiK9zUVilQhu0GbdU6LM
+8BDcVHOLBKFGMzNcF0C5nk3T875Vg+ixiY5afJqWIpA7iCXy0lOIAgwLePLmNxdLMEYH5IBtptiW
+Lugs+BGzOA1mppvqySNb247i8xOOGlktqgLw7KSHZtzBP/XYufTsgsbSPZUd5cBPhMnZo0QoBmrX
+Razwa2rvTl/4EYIeOGM0ZlDUPpNz+jDDZq3/ky2X7wMCAwEAATANBgkqhkiG9w0BAQUFAAOCAQEA
+j/ola09b5KROJ1WrIhVZPMq1CtRK26vdoV9TxaBXOcLORyu+OshWv8LZJxA6sQU8wHcxuzrTBXtt
+mhwwjIDLk5Mqg6sFUYICABFna/OIYUdfA5PVWw3g8dShMjWFsjrbsIKr0csKvE+MW8VLADsfKoKm
+fjaF3H48ZwC15DtS4KjrXRX5xm3wrR0OhbepmnMUWluPQSjA1egtTaRezarZ7c7c2NU8Qh0XwRJd
+RTjDOPP8hS6DRkiy1yBfkjaP53kPmF6Z6PDQpLv1U70qzlmwr25/bLvSHgCwIe34QWKCudiyxLtG
+UPMxxY8BqHTr9Xgn2uf3ZkPznoM+IKrDNWCRzg==
+-----END CERTIFICATE-----
+
+Entrust.net Secure Server CA
+============================
+-----BEGIN CERTIFICATE-----
+MIIE2DCCBEGgAwIBAgIEN0rSQzANBgkqhkiG9w0BAQUFADCBwzELMAkGA1UEBhMCVVMxFDASBgNV
+BAoTC0VudHJ1c3QubmV0MTswOQYDVQQLEzJ3d3cuZW50cnVzdC5uZXQvQ1BTIGluY29ycC4gYnkg
+cmVmLiAobGltaXRzIGxpYWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRl
+ZDE6MDgGA1UEAxMxRW50cnVzdC5uZXQgU2VjdXJlIFNlcnZlciBDZXJ0aWZpY2F0aW9uIEF1dGhv
+cml0eTAeFw05OTA1MjUxNjA5NDBaFw0xOTA1MjUxNjM5NDBaMIHDMQswCQYDVQQGEwJVUzEUMBIG
+A1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5ldC9DUFMgaW5jb3JwLiBi
+eSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBFbnRydXN0Lm5ldCBMaW1p
+dGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIGdMA0GCSqGSIb3DQEBAQUAA4GLADCBhwKBgQDNKIM0VBuJ8w+vN5Ex/68xYMmo6LIQ
+aO2f55M28Qpku0f1BBc/I0dNxScZgSYMVHINiC3ZH5oSn7yzcdOAGT9HZnuMNSjSuQrfJNqc1lB5
+gXpa0zf3wkrYKZImZNHkmGw6AIr1NJtl+O3jEP/9uElY3KDegjlrgbEWGWG5VLbmQwIBA6OCAdcw
+ggHTMBEGCWCGSAGG+EIBAQQEAwIABzCCARkGA1UdHwSCARAwggEMMIHeoIHboIHYpIHVMIHSMQsw
+CQYDVQQGEwJVUzEUMBIGA1UEChMLRW50cnVzdC5uZXQxOzA5BgNVBAsTMnd3dy5lbnRydXN0Lm5l
+dC9DUFMgaW5jb3JwLiBieSByZWYuIChsaW1pdHMgbGlhYi4pMSUwIwYDVQQLExwoYykgMTk5OSBF
+bnRydXN0Lm5ldCBMaW1pdGVkMTowOAYDVQQDEzFFbnRydXN0Lm5ldCBTZWN1cmUgU2VydmVyIENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5MQ0wCwYDVQQDEwRDUkwxMCmgJ6AlhiNodHRwOi8vd3d3LmVu
+dHJ1c3QubmV0L0NSTC9uZXQxLmNybDArBgNVHRAEJDAigA8xOTk5MDUyNTE2MDk0MFqBDzIwMTkw
+NTI1MTYwOTQwWjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAU8BdiE1U9s/8KAGv7UISX8+1i0Bow
+HQYDVR0OBBYEFPAXYhNVPbP/CgBr+1CEl/PtYtAaMAwGA1UdEwQFMAMBAf8wGQYJKoZIhvZ9B0EA
+BAwwChsEVjQuMAMCBJAwDQYJKoZIhvcNAQEFBQADgYEAkNwwAvpkdMKnCqV8IY00F6j7Rw7/JXyN
+Ewr75Ji174z4xRAN95K+8cPV1ZVqBLssziY2ZcgxxufuP+NXdYR6Ee9GTxj005i7qIcyunL2POI9
+n9cd2cNgQ4xYDiKWL2KjLB+6rQXvqzJ4h6BUcxm1XAX5Uj5tLUUL9wqT6u0G+bI=
+-----END CERTIFICATE-----
+
+Entrust.net Premium 2048 Secure Server CA
+=========================================
+-----BEGIN CERTIFICATE-----
+MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChMLRW50cnVzdC5u
+ZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBpbmNvcnAuIGJ5IHJlZi4gKGxp
+bWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNV
+BAMTKkVudHJ1c3QubmV0IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQx
+NzUwNTFaFw0xOTEyMjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3
+d3d3LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxpYWIuKTEl
+MCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEGA1UEAxMqRW50cnVzdC5u
+ZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgpMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEArU1LqRKGsuqjIAcVFmQqK0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOL
+Gp18EzoOH1u3Hs/lJBQesYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSr
+hRSGlVuXMlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVTXTzW
+nLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/HoZdenoVve8AjhUi
+VBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH4QIDAQABo3QwcjARBglghkgBhvhC
+AQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGAvtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdER
+gL7YibkIozH5oSQJFrlwMB0GCSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0B
+AQUFAAOCAQEAWUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo
+oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQh7A6tcOdBTcS
+o8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18f3v/rxzP5tsHrV7bhZ3QKw0z
+2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfNB/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjX
+OP/swNlQ8C5LWK5Gb9Auw2DaclVyvUxFnmG6v4SBkgPR0ml8xQ==
+-----END CERTIFICATE-----
+
+Baltimore CyberTrust Root
+=========================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIEAgAAuTANBgkqhkiG9w0BAQUFADBaMQswCQYDVQQGEwJJRTESMBAGA1UE
+ChMJQmFsdGltb3JlMRMwEQYDVQQLEwpDeWJlclRydXN0MSIwIAYDVQQDExlCYWx0aW1vcmUgQ3li
+ZXJUcnVzdCBSb290MB4XDTAwMDUxMjE4NDYwMFoXDTI1MDUxMjIzNTkwMFowWjELMAkGA1UEBhMC
+SUUxEjAQBgNVBAoTCUJhbHRpbW9yZTETMBEGA1UECxMKQ3liZXJUcnVzdDEiMCAGA1UEAxMZQmFs
+dGltb3JlIEN5YmVyVHJ1c3QgUm9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKME
+uyKrmD1X6CZymrV51Cni4eiVgLGw41uOKymaZN+hXe2wCQVt2yguzmKiYv60iNoS6zjrIZ3AQSsB
+UnuId9Mcj8e6uYi1agnnc+gRQKfRzMpijS3ljwumUNKoUMMo6vWrJYeKmpYcqWe4PwzV9/lSEy/C
+G9VwcPCPwBLKBsua4dnKM3p31vjsufFoREJIE9LAwqSuXmD+tqYF/LTdB1kC1FkYmGP1pWPgkAx9
+XbIGevOF6uvUA65ehD5f/xXtabz5OTZydc93Uk3zyZAsuT3lySNTPx8kmCFcB5kpvcY67Oduhjpr
+l3RjM71oGDHweI12v/yejl0qhqdNkNwnGjkCAwEAAaNFMEMwHQYDVR0OBBYEFOWdWTCCR1jMrPoI
+VDaGezq1BE3wMBIGA1UdEwEB/wQIMAYBAf8CAQMwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEB
+BQUAA4IBAQCFDF2O5G9RaEIFoN27TyclhAO992T9Ldcw46QQF+vaKSm2eT929hkTI7gQCvlYpNRh
+cL0EYWoSihfVCr3FvDB81ukMJY2GQE/szKN+OMY3EU/t3WgxjkzSswF07r51XgdIGn9w/xZchMB5
+hbgF/X++ZRGjD8ACtPhSNzkE1akxehi/oCr0Epn3o0WC4zxe9Z2etciefC7IpJ5OCBRLbf1wbWsa
+Y71k5h+3zvDyny67G7fyUIhzksLi4xaNmjICq44Y3ekQEe5+NauQrz4wlHrQMz2nZQ/1/I6eYs9H
+RCwBXbsdtTLSR9I4LtD+gdwyah617jzV/OeBHRnDJELqYzmp
+-----END CERTIFICATE-----
+
+Equifax Secure Global eBusiness CA
+==================================
+-----BEGIN CERTIFICATE-----
+MIICkDCCAfmgAwIBAgIBATANBgkqhkiG9w0BAQQFADBaMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
+RXF1aWZheCBTZWN1cmUgSW5jLjEtMCsGA1UEAxMkRXF1aWZheCBTZWN1cmUgR2xvYmFsIGVCdXNp
+bmVzcyBDQS0xMB4XDTk5MDYyMTA0MDAwMFoXDTIwMDYyMTA0MDAwMFowWjELMAkGA1UEBhMCVVMx
+HDAaBgNVBAoTE0VxdWlmYXggU2VjdXJlIEluYy4xLTArBgNVBAMTJEVxdWlmYXggU2VjdXJlIEds
+b2JhbCBlQnVzaW5lc3MgQ0EtMTCBnzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEAuucXkAJlsTRV
+PEnCUdXfp9E3j9HngXNBUmCbnaEXJnitx7HoJpQytd4zjTov2/KaelpzmKNc6fuKcxtc58O/gGzN
+qfTWK8D3+ZmqY6KxRwIP1ORROhI8bIpaVIRw28HFkM9yRcuoWcDNM50/o5brhTMhHD4ePmBudpxn
+hcXIw2ECAwEAAaNmMGQwEQYJYIZIAYb4QgEBBAQDAgAHMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0j
+BBgwFoAUvqigdHJQa0S3ySPY+6j/s1draGwwHQYDVR0OBBYEFL6ooHRyUGtEt8kj2Puo/7NXa2hs
+MA0GCSqGSIb3DQEBBAUAA4GBADDiAVGqx+pf2rnQZQ8w1j7aDRRJbpGTJxQx78T3LUX47Me/okEN
+I7SS+RkAZ70Br83gcfxaz2TE4JaY0KNA4gGK7ycH8WUBikQtBmV1UsCGECAhX2xrD2yuCRyv8qIY
+NMR1pHMc8Y3c7635s3a0kr/clRAevsvIO1qEYBlWlKlV
+-----END CERTIFICATE-----
+
+Equifax Secure eBusiness CA 1
+=============================
+-----BEGIN CERTIFICATE-----
+MIICgjCCAeugAwIBAgIBBDANBgkqhkiG9w0BAQQFADBTMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
+RXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNzIENB
+LTEwHhcNOTkwNjIxMDQwMDAwWhcNMjAwNjIxMDQwMDAwWjBTMQswCQYDVQQGEwJVUzEcMBoGA1UE
+ChMTRXF1aWZheCBTZWN1cmUgSW5jLjEmMCQGA1UEAxMdRXF1aWZheCBTZWN1cmUgZUJ1c2luZXNz
+IENBLTEwgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAM4vGbwXt3fek6lfWg0XTzQaDJj0ItlZ
+1MRoRvC0NcWFAyDGr0WlIVFFQesWWDYyb+JQYmT5/VGcqiTZ9J2DKocKIdMSODRsjQBuWqDZQu4a
+IZX5UkxVWsUPOE9G+m34LjXWHXzr4vCwdYDIqROsvojvOm6rXyo4YgKwEnv+j6YDAgMBAAGjZjBk
+MBEGCWCGSAGG+EIBAQQEAwIABzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFEp4MlIR21kW
+Nl7fwRQ2QGpHfEyhMB0GA1UdDgQWBBRKeDJSEdtZFjZe38EUNkBqR3xMoTANBgkqhkiG9w0BAQQF
+AAOBgQB1W6ibAxHm6VZMzfmpTMANmvPMZWnmJXbMWbfWVMMdzZmsGd20hdXgPfxiIKeES1hl8eL5
+lSE/9dR+WB5Hh1Q+WKG1tfgq73HnvMP2sUlG4tega+VWeponmHxGYhTnyfxuAxJ5gDgdSIKN/Bf+
+KpYrtWKmpj29f5JZzVoqgrI3eQ==
+-----END CERTIFICATE-----
+
+Equifax Secure eBusiness CA 2
+=============================
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAomgAwIBAgIEN3DPtTANBgkqhkiG9w0BAQUFADBOMQswCQYDVQQGEwJVUzEXMBUGA1UE
+ChMORXF1aWZheCBTZWN1cmUxJjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0y
+MB4XDTk5MDYyMzEyMTQ0NVoXDTE5MDYyMzEyMTQ0NVowTjELMAkGA1UEBhMCVVMxFzAVBgNVBAoT
+DkVxdWlmYXggU2VjdXJlMSYwJAYDVQQLEx1FcXVpZmF4IFNlY3VyZSBlQnVzaW5lc3MgQ0EtMjCB
+nzANBgkqhkiG9w0BAQEFAAOBjQAwgYkCgYEA5Dk5kx5SBhsoNviyoynF7Y6yEb3+6+e0dMKP/wXn
+2Z0GvxLIPw7y1tEkshHe0XMJitSxLJgJDR5QRrKDpkWNYmi7hRsgcDKqQM2mll/EcTc/BPO3QSQ5
+BxoeLmFYoBIL5aXfxavqN3HMHMg3OrmXUqesxWoklE6ce8/AatbfIb0CAwEAAaOCAQkwggEFMHAG
+A1UdHwRpMGcwZaBjoGGkXzBdMQswCQYDVQQGEwJVUzEXMBUGA1UEChMORXF1aWZheCBTZWN1cmUx
+JjAkBgNVBAsTHUVxdWlmYXggU2VjdXJlIGVCdXNpbmVzcyBDQS0yMQ0wCwYDVQQDEwRDUkwxMBoG
+A1UdEAQTMBGBDzIwMTkwNjIzMTIxNDQ1WjALBgNVHQ8EBAMCAQYwHwYDVR0jBBgwFoAUUJ4L6q9e
+uSBIplBqy/3YIHqngnYwHQYDVR0OBBYEFFCeC+qvXrkgSKZQasv92CB6p4J2MAwGA1UdEwQFMAMB
+Af8wGgYJKoZIhvZ9B0EABA0wCxsFVjMuMGMDAgbAMA0GCSqGSIb3DQEBBQUAA4GBAAyGgq3oThr1
+jokn4jVYPSm0B482UJW/bsGe68SQsoWou7dC4A8HOd/7npCy0cE+U58DRLB+S/Rv5Hwf5+Kx5Lia
+78O9zt4LMjTZ3ijtM2vE1Nc9ElirfQkty3D1E4qUoSek1nDFbZS1yX2doNLGCEnZZpum0/QL3MUm
+V+GRMOrN
+-----END CERTIFICATE-----
+
+AddTrust Low-Value Services Root
+================================
+-----BEGIN CERTIFICATE-----
+MIIEGDCCAwCgAwIBAgIBATANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEwHwYDVQQDExhBZGRU
+cnVzdCBDbGFzcyAxIENBIFJvb3QwHhcNMDAwNTMwMTAzODMxWhcNMjAwNTMwMTAzODMxWjBlMQsw
+CQYDVQQGEwJTRTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBO
+ZXR3b3JrMSEwHwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3QwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQCWltQhSWDia+hBBwzexODcEyPNwTXH+9ZOEQpnXvUGW2ulCDtbKRY6
+54eyNAbFvAWlA3yCyykQruGIgb3WntP+LVbBFc7jJp0VLhD7Bo8wBN6ntGO0/7Gcrjyvd7ZWxbWr
+oulpOj0OM3kyP3CCkplhbY0wCI9xP6ZIVxn4JdxLZlyldI+Yrsj5wAYi56xz36Uu+1LcsRVlIPo1
+Zmne3yzxbrww2ywkEtvrNTVokMsAsJchPXQhI2U0K7t4WaPW4XY5mqRJjox0r26kmqPZm9I4XJui
+GMx1I4S+6+JNM3GOGvDC+Mcdoq0Dlyz4zyXG9rgkMbFjXZJ/Y/AlyVMuH79NAgMBAAGjgdIwgc8w
+HQYDVR0OBBYEFJWxtPCUtr3H2tERCSG+wa9J/RB7MAsGA1UdDwQEAwIBBjAPBgNVHRMBAf8EBTAD
+AQH/MIGPBgNVHSMEgYcwgYSAFJWxtPCUtr3H2tERCSG+wa9J/RB7oWmkZzBlMQswCQYDVQQGEwJT
+RTEUMBIGA1UEChMLQWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSEw
+HwYDVQQDExhBZGRUcnVzdCBDbGFzcyAxIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBACxt
+ZBsfzQ3duQH6lmM0MkhHma6X7f1yFqZzR1r0693p9db7RcwpiURdv0Y5PejuvE1Uhh4dbOMXJ0Ph
+iVYrqW9yTkkz43J8KiOavD7/KCrto/8cI7pDVwlnTUtiBi34/2ydYB7YHEt9tTEv2dB8Xfjea4MY
+eDdXL+gzB2ffHsdrKpV2ro9Xo/D0UrSpUwjP4E/TelOL/bscVjby/rK25Xa71SJlpz/+0WatC7xr
+mYbvP33zGDLKe8bjq2RGlfgmadlVg3sslgf/WSxEo8bl6ancoWOAWiFeIc9TVPC6b4nbqKqVz4vj
+ccweGyBECMB6tkD9xOQ14R0WHNC8K47Wcdk=
+-----END CERTIFICATE-----
+
+AddTrust External Root
+======================
+-----BEGIN CERTIFICATE-----
+MIIENjCCAx6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBvMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxJjAkBgNVBAsTHUFkZFRydXN0IEV4dGVybmFsIFRUUCBOZXR3b3JrMSIwIAYD
+VQQDExlBZGRUcnVzdCBFeHRlcm5hbCBDQSBSb290MB4XDTAwMDUzMDEwNDgzOFoXDTIwMDUzMDEw
+NDgzOFowbzELMAkGA1UEBhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMSYwJAYDVQQLEx1BZGRU
+cnVzdCBFeHRlcm5hbCBUVFAgTmV0d29yazEiMCAGA1UEAxMZQWRkVHJ1c3QgRXh0ZXJuYWwgQ0Eg
+Um9vdDCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALf3GjPm8gAELTngTlvtH7xsD821
++iO2zt6bETOXpClMfZOfvUq8k+0DGuOPz+VtUFrWlymUWoCwSXrbLpX9uMq/NzgtHj6RQa1wVsfw
+Tz/oMp50ysiQVOnGXw94nZpAPA6sYapeFI+eh6FqUNzXmk6vBbOmcZSccbNQYArHE504B4YCqOmo
+aSYYkKtMsE8jqzpPhNjfzp/haW+710LXa0Tkx63ubUFfclpxCDezeWWkWaCUN/cALw3CknLa0Dhy
+2xSoRcRdKn23tNbE7qzNE0S3ySvdQwAl+mG5aWpYIxG3pzOPVnVZ9c0p10a3CitlttNCbxWyuHv7
+7+ldU9U0WicCAwEAAaOB3DCB2TAdBgNVHQ4EFgQUrb2YejS0Jvf6xCZU7wO94CTLVBowCwYDVR0P
+BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wgZkGA1UdIwSBkTCBjoAUrb2YejS0Jvf6xCZU7wO94CTL
+VBqhc6RxMG8xCzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEmMCQGA1UECxMdQWRk
+VHJ1c3QgRXh0ZXJuYWwgVFRQIE5ldHdvcmsxIjAgBgNVBAMTGUFkZFRydXN0IEV4dGVybmFsIENB
+IFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBALCb4IUlwtYj4g+WBpKdQZic2YR5gdkeWxQHIzZl
+j7DYd7usQWxHYINRsPkyPef89iYTx4AWpb9a/IfPeHmJIZriTAcKhjW88t5RxNKWt9x+Tu5w/Rw5
+6wwCURQtjr0W4MHfRnXnJK3s9EK0hZNwEGe6nQY1ShjTK3rMUUKhemPR5ruhxSvCNr4TDea9Y355
+e6cJDUCrat2PisP29owaQgVR1EX1n6diIWgVIEM8med8vSTYqZEXc4g/VhsxOBi0cQ+azcgOno4u
+G+GMmIPLHzHxREzGBHNJdmAPx/i9F4BrLunMTA5amnkPIAou1Z5jJh5VkpTYghdae9C8x49OhgQ=
+-----END CERTIFICATE-----
+
+AddTrust Public Services Root
+=============================
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIBATANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSAwHgYDVQQDExdBZGRU
+cnVzdCBQdWJsaWMgQ0EgUm9vdDAeFw0wMDA1MzAxMDQxNTBaFw0yMDA1MzAxMDQxNTBaMGQxCzAJ
+BgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQIE5l
+dHdvcmsxIDAeBgNVBAMTF0FkZFRydXN0IFB1YmxpYyBDQSBSb290MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA6Rowj4OIFMEg2Dybjxt+A3S72mnTRqX4jsIMEZBRpS9mVEBV6tsfSlbu
+nyNu9DnLoblv8n75XYcmYZ4c+OLspoH4IcUkzBEMP9smcnrHAZcHF/nXGCwwfQ56HmIexkvA/X1i
+d9NEHif2P0tEs7c42TkfYNVRknMDtABp4/MUTu7R3AnPdzRGULD4EfL+OHn3Bzn+UZKXC1sIXzSG
+Aa2Il+tmzV7R/9x98oTaunet3IAIx6eH1lWfl2royBFkuucZKT8Rs3iQhCBSWxHveNCD9tVIkNAw
+HM+A+WD+eeSI8t0A65RF62WUaUC6wNW0uLp9BBGo6zEFlpROWCGOn9Bg/QIDAQABo4HRMIHOMB0G
+A1UdDgQWBBSBPjfYkrAfd59ctKtzquf2NGAv+jALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zCBjgYDVR0jBIGGMIGDgBSBPjfYkrAfd59ctKtzquf2NGAv+qFopGYwZDELMAkGA1UEBhMCU0Ux
+FDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29yazEgMB4G
+A1UEAxMXQWRkVHJ1c3QgUHVibGljIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQADggEBAAP3FUr4
+JNojVhaTdt02KLmuG7jD8WS6IBh4lSknVwW8fCr0uVFV2ocC3g8WFzH4qnkuCRO7r7IgGRLlk/lL
++YPoRNWyQSW/iHVv/xD8SlTQX/D67zZzfRs2RcYhbbQVuE7PnFylPVoAjgbjPGsye/Kf8Lb93/Ao
+GEjwxrzQvzSAlsJKsW2Ox5BF3i9nrEUEo3rcVZLJR2bYGozH7ZxOmuASu7VqTITh4SINhwBk/ox9
+Yjllpu9CtoAlEmEBqCQTcAARJl/6NVDFSMwGR+gn2HCNX2TmoUQmXiLsks3/QppEIW1cxeMiHV9H
+EufOX1362KqxMy3ZdvJOOjMMK7MtkAY=
+-----END CERTIFICATE-----
+
+AddTrust Qualified Certificates Root
+====================================
+-----BEGIN CERTIFICATE-----
+MIIEHjCCAwagAwIBAgIBATANBgkqhkiG9w0BAQUFADBnMQswCQYDVQQGEwJTRTEUMBIGA1UEChML
+QWRkVHJ1c3QgQUIxHTAbBgNVBAsTFEFkZFRydXN0IFRUUCBOZXR3b3JrMSMwIQYDVQQDExpBZGRU
+cnVzdCBRdWFsaWZpZWQgQ0EgUm9vdDAeFw0wMDA1MzAxMDQ0NTBaFw0yMDA1MzAxMDQ0NTBaMGcx
+CzAJBgNVBAYTAlNFMRQwEgYDVQQKEwtBZGRUcnVzdCBBQjEdMBsGA1UECxMUQWRkVHJ1c3QgVFRQ
+IE5ldHdvcmsxIzAhBgNVBAMTGkFkZFRydXN0IFF1YWxpZmllZCBDQSBSb290MIIBIjANBgkqhkiG
+9w0BAQEFAAOCAQ8AMIIBCgKCAQEA5B6a/twJWoekn0e+EV+vhDTbYjx5eLfpMLXsDBwqxBb/4Oxx
+64r1EW7tTw2R0hIYLUkVAcKkIhPHEWT/IhKauY5cLwjPcWqzZwFZ8V1G87B4pfYOQnrjfxvM0PC3
+KP0q6p6zsLkEqv32x7SxuCqg+1jxGaBvcCV+PmlKfw8i2O+tCBGaKZnhqkRFmhJePp1tUvznoD1o
+L/BLcHwTOK28FSXx1s6rosAx1i+f4P8UWfyEk9mHfExUE+uf0S0R+Bg6Ot4l2ffTQO2kBhLEO+GR
+wVY18BTcZTYJbqukB8c10cIDMzZbdSZtQvESa0NvS3GU+jQd7RNuyoB/mC9suWXY6QIDAQABo4HU
+MIHRMB0GA1UdDgQWBBQ5lYtii1zJ1IC6WA+XPxUIQ8yYpzALBgNVHQ8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zCBkQYDVR0jBIGJMIGGgBQ5lYtii1zJ1IC6WA+XPxUIQ8yYp6FrpGkwZzELMAkGA1UE
+BhMCU0UxFDASBgNVBAoTC0FkZFRydXN0IEFCMR0wGwYDVQQLExRBZGRUcnVzdCBUVFAgTmV0d29y
+azEjMCEGA1UEAxMaQWRkVHJ1c3QgUXVhbGlmaWVkIENBIFJvb3SCAQEwDQYJKoZIhvcNAQEFBQAD
+ggEBABmrder4i2VhlRO6aQTvhsoToMeqT2QbPxj2qC0sVY8FtzDqQmodwCVRLae/DLPt7wh/bDxG
+GuoYQ992zPlmhpwsaPXpF/gxsxjE1kh9I0xowX67ARRvxdlu3rsEQmr49lx95dr6h+sNNVJn0J6X
+dgWTP5XHAeZpVTh/EGGZyeNfpso+gmNIquIISD6q8rKFYqa0p9m9N5xotS1WfbC3P6CxB9bpT9ze
+RXEwMn8bLgn5v1Kh7sKAPgZcLlVAwRv1cEWw3F369nJad9Jjzc9YiQBCYz95OdBEsIJuQRno3eDB
+iFrRHnGTHyQwdOUeqN48Jzd/g66ed8/wMLH/S5noxqE=
+-----END CERTIFICATE-----
+
+Entrust Root Certification Authority
+====================================
+-----BEGIN CERTIFICATE-----
+MIIEkTCCA3mgAwIBAgIERWtQVDANBgkqhkiG9w0BAQUFADCBsDELMAkGA1UEBhMCVVMxFjAUBgNV
+BAoTDUVudHJ1c3QsIEluYy4xOTA3BgNVBAsTMHd3dy5lbnRydXN0Lm5ldC9DUFMgaXMgaW5jb3Jw
+b3JhdGVkIGJ5IHJlZmVyZW5jZTEfMB0GA1UECxMWKGMpIDIwMDYgRW50cnVzdCwgSW5jLjEtMCsG
+A1UEAxMkRW50cnVzdCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTA2MTEyNzIwMjM0
+MloXDTI2MTEyNzIwNTM0MlowgbAxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1FbnRydXN0LCBJbmMu
+MTkwNwYDVQQLEzB3d3cuZW50cnVzdC5uZXQvQ1BTIGlzIGluY29ycG9yYXRlZCBieSByZWZlcmVu
+Y2UxHzAdBgNVBAsTFihjKSAyMDA2IEVudHJ1c3QsIEluYy4xLTArBgNVBAMTJEVudHJ1c3QgUm9v
+dCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ALaVtkNC+sZtKm9I35RMOVcF7sN5EUFoNu3s/poBj6E4KPz3EEZmLk0eGrEaTsbRwJWIsMn/MYsz
+A9u3g3s+IIRe7bJWKKf44LlAcTfFy0cOlypowCKVYhXbR9n10Cv/gkvJrT7eTNuQgFA/CYqEAOww
+Cj0Yzfv9KlmaI5UXLEWeH25DeW0MXJj+SKfFI0dcXv1u5x609mhF0YaDW6KKjbHjKYD+JXGIrb68
+j6xSlkuqUY3kEzEZ6E5Nn9uss2rVvDlUccp6en+Q3X0dgNmBu1kmwhH+5pPi94DkZfs0Nw4pgHBN
+rziGLp5/V6+eF67rHMsoIV+2HNjnogQi+dPa2MsCAwEAAaOBsDCBrTAOBgNVHQ8BAf8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zArBgNVHRAEJDAigA8yMDA2MTEyNzIwMjM0MlqBDzIwMjYxMTI3MjA1
+MzQyWjAfBgNVHSMEGDAWgBRokORnpKZTgMeGZqTx90tD+4S9bTAdBgNVHQ4EFgQUaJDkZ6SmU4DH
+hmak8fdLQ/uEvW0wHQYJKoZIhvZ9B0EABBAwDhsIVjcuMTo0LjADAgSQMA0GCSqGSIb3DQEBBQUA
+A4IBAQCT1DCw1wMgKtD5Y+iRDAUgqV8ZyntyTtSx29CW+1RaGSwMCPeyvIWonX9tO1KzKtvn1ISM
+Y/YPyyYBkVBs9F8U4pN0wBOeMDpQ47RgxRzwIkSNcUesyBrJ6ZuaAGAT/3B+XxFNSRuzFVJ7yVTa
+v52Vr2ua2J7p8eRDjeIRRDq/r72DQnNSi6q7pynP9WQcCk3RvKqsnyrQ/39/2n3qse0wJcGE2jTS
+W3iDVuycNsMm4hH2Z0kdkquM++v/eu6FSqdQgPCnXEqULl8FmTxSQeDNtGPPAUO6nIPcj2A781q0
+tHuu2guQOHXvgR1m0vdXcDazv/wor3ElhVsT/h5/WrQ8
+-----END CERTIFICATE-----
+
+RSA Security 2048 v3
+====================
+-----BEGIN CERTIFICATE-----
+MIIDYTCCAkmgAwIBAgIQCgEBAQAAAnwAAAAKAAAAAjANBgkqhkiG9w0BAQUFADA6MRkwFwYDVQQK
+ExBSU0EgU2VjdXJpdHkgSW5jMR0wGwYDVQQLExRSU0EgU2VjdXJpdHkgMjA0OCBWMzAeFw0wMTAy
+MjIyMDM5MjNaFw0yNjAyMjIyMDM5MjNaMDoxGTAXBgNVBAoTEFJTQSBTZWN1cml0eSBJbmMxHTAb
+BgNVBAsTFFJTQSBTZWN1cml0eSAyMDQ4IFYzMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKC
+AQEAt49VcdKA3XtpeafwGFAyPGJn9gqVB93mG/Oe2dJBVGutn3y+Gc37RqtBaB4Y6lXIL5F4iSj7
+Jylg/9+PjDvJSZu1pJTOAeo+tWN7fyb9Gd3AIb2E0S1PRsNO3Ng3OTsor8udGuorryGlwSMiuLgb
+WhOHV4PR8CDn6E8jQrAApX2J6elhc5SYcSa8LWrg903w8bYqODGBDSnhAMFRD0xS+ARaqn1y07iH
+KrtjEAMqs6FPDVpeRrc9DvV07Jmf+T0kgYim3WBU6JU2PcYJk5qjEoAAVZkZR73QpXzDuvsf9/UP
++Ky5tfQ3mBMY3oVbtwyCO4dvlTlYMNpuAWgXIszACwIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/
+MA4GA1UdDwEB/wQEAwIBBjAfBgNVHSMEGDAWgBQHw1EwpKrpRa41JPr/JCwz0LGdjDAdBgNVHQ4E
+FgQUB8NRMKSq6UWuNST6/yQsM9CxnYwwDQYJKoZIhvcNAQEFBQADggEBAF8+hnZuuDU8TjYcHnmY
+v/3VEhF5Ug7uMYm83X/50cYVIeiKAVQNOvtUudZj1LGqlk2iQk3UUx+LEN5/Zb5gEydxiKRz44Rj
+0aRV4VCT5hsOedBnvEbIvz8XDZXmxpBp3ue0L96VfdASPz0+f00/FGj1EVDVwfSQpQgdMWD/YIwj
+VAqv/qFuxdF6Kmh4zx6CCiC0H63lhbJqaHVOrSU3lIW+vaHU6rcMSzyd6BIA8F+sDeGscGNz9395
+nzIlQnQFgCi/vcEkllgVsRch6YlL2weIZ/QVrXA+L02FO8K32/6YaCOJ4XQP3vTFhGMpG8zLB8kA
+pKnXwiJPZ9d37CAFYd4=
+-----END CERTIFICATE-----
+
+GeoTrust Global CA
+==================
+-----BEGIN CERTIFICATE-----
+MIIDVDCCAjygAwIBAgIDAjRWMA0GCSqGSIb3DQEBBQUAMEIxCzAJBgNVBAYTAlVTMRYwFAYDVQQK
+Ew1HZW9UcnVzdCBJbmMuMRswGQYDVQQDExJHZW9UcnVzdCBHbG9iYWwgQ0EwHhcNMDIwNTIxMDQw
+MDAwWhcNMjIwNTIxMDQwMDAwWjBCMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
+LjEbMBkGA1UEAxMSR2VvVHJ1c3QgR2xvYmFsIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEA2swYYzD99BcjGlZ+W988bDjkcbd4kdS8odhM+KhDtgPpTSEHCIjaWC9mOSm9BXiLnTjo
+BbdqfnGk5sRgprDvgOSJKA+eJdbtg/OtppHHmMlCGDUUna2YRpIuT8rxh0PBFpVXLVDviS2Aelet
+8u5fa9IAjbkU+BQVNdnARqN7csiRv8lVK83Qlz6cJmTM386DGXHKTubU1XupGc1V3sjs0l44U+Vc
+T4wt/lAjNvxm5suOpDkZALeVAjmRCw7+OC7RHQWa9k0+bw8HHa8sHo9gOeL6NlMTOdReJivbPagU
+vTLrGAMoUgRx5aszPeE4uwc2hGKceeoWMPRfwCvocWvk+QIDAQABo1MwUTAPBgNVHRMBAf8EBTAD
+AQH/MB0GA1UdDgQWBBTAephojYn7qwVkDBF9qn1luMrMTjAfBgNVHSMEGDAWgBTAephojYn7qwVk
+DBF9qn1luMrMTjANBgkqhkiG9w0BAQUFAAOCAQEANeMpauUvXVSOKVCUn5kaFOSPeCpilKInZ57Q
+zxpeR+nBsqTP3UEaBU6bS+5Kb1VSsyShNwrrZHYqLizz/Tt1kL/6cdjHPTfStQWVYrmm3ok9Nns4
+d0iXrKYgjy6myQzCsplFAMfOEVEiIuCl6rYVSAlk6l5PdPcFPseKUgzbFbS9bZvlxrFUaKnjaZC2
+mqUPuLk/IH2uSrW4nOQdtqvmlKXBx4Ot2/Unhw4EbNX/3aBd7YdStysVAq45pmp06drE57xNNB6p
+XE0zX5IJL4hmXXeXxx12E6nV5fEWCRE11azbJHFwLJhWC9kXtNHjUStedejV0NxPNO3CBWaAocvm
+Mw==
+-----END CERTIFICATE-----
+
+GeoTrust Global CA 2
+====================
+-----BEGIN CERTIFICATE-----
+MIIDZjCCAk6gAwIBAgIBATANBgkqhkiG9w0BAQUFADBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
+R2VvVHJ1c3QgSW5jLjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwHhcNMDQwMzA0MDUw
+MDAwWhcNMTkwMzA0MDUwMDAwWjBEMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5j
+LjEdMBsGA1UEAxMUR2VvVHJ1c3QgR2xvYmFsIENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDvPE1APRDfO1MA4Wf+lGAVPoWI8YkNkMgoI5kF6CsgncbzYEbYwbLVjDHZ3CB5JIG/
+NTL8Y2nbsSpr7iFY8gjpeMtvy/wWUsiRxP89c96xPqfCfWbB9X5SJBri1WeR0IIQ13hLTytCOb1k
+LUCgsBDTOEhGiKEMuzozKmKY+wCdE1l/bztyqu6mD4b5BWHqZ38MN5aL5mkWRxHCJ1kDs6ZgwiFA
+Vvqgx306E+PsV8ez1q6diYD3Aecs9pYrEw15LNnA5IZ7S4wMcoKK+xfNAGw6EzywhIdLFnopsk/b
+HdQL82Y3vdj2V7teJHq4PIu5+pIaGoSe2HSPqht/XvT+RSIhAgMBAAGjYzBhMA8GA1UdEwEB/wQF
+MAMBAf8wHQYDVR0OBBYEFHE4NvICMVNHK266ZUapEBVYIAUJMB8GA1UdIwQYMBaAFHE4NvICMVNH
+K266ZUapEBVYIAUJMA4GA1UdDwEB/wQEAwIBhjANBgkqhkiG9w0BAQUFAAOCAQEAA/e1K6tdEPx7
+srJerJsOflN4WT5CBP51o62sgU7XAotexC3IUnbHLB/8gTKY0UvGkpMzNTEv/NgdRN3ggX+d6Yvh
+ZJFiCzkIjKx0nVnZellSlxG5FntvRdOW2TF9AjYPnDtuzywNA0ZF66D0f0hExghAzN4bcLUprbqL
+OzRldRtxIR0sFAqwlpW41uryZfspuk/qkZN0abby/+Ea0AzRdoXLiiW9l14sbxWZJue2Kf8i7MkC
+x1YAzUm5s2x7UwQa4qjJqhIFI8LO57sEAszAR6LkxCkvW0VXiVHuPOtSCP8HNR6fNWpHSlaY0VqF
+H4z1Ir+rzoPz4iIprn2DQKi6bA==
+-----END CERTIFICATE-----
+
+GeoTrust Universal CA
+=====================
+-----BEGIN CERTIFICATE-----
+MIIFaDCCA1CgAwIBAgIBATANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
+R2VvVHJ1c3QgSW5jLjEeMBwGA1UEAxMVR2VvVHJ1c3QgVW5pdmVyc2FsIENBMB4XDTA0MDMwNDA1
+MDAwMFoXDTI5MDMwNDA1MDAwMFowRTELMAkGA1UEBhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IElu
+Yy4xHjAcBgNVBAMTFUdlb1RydXN0IFVuaXZlcnNhbCBDQTCCAiIwDQYJKoZIhvcNAQEBBQADggIP
+ADCCAgoCggIBAKYVVaCjxuAfjJ0hUNfBvitbtaSeodlyWL0AG0y/YckUHUWCq8YdgNY96xCcOq9t
+JPi8cQGeBvV8Xx7BDlXKg5pZMK4ZyzBIle0iN430SppyZj6tlcDgFgDgEB8rMQ7XlFTTQjOgNB0e
+RXbdT8oYN+yFFXoZCPzVx5zw8qkuEKmS5j1YPakWaDwvdSEYfyh3peFhF7em6fgemdtzbvQKoiFs
+7tqqhZJmr/Z6a4LauiIINQ/PQvE1+mrufislzDoR5G2vc7J2Ha3QsnhnGqQ5HFELZ1aD/ThdDc7d
+8Lsrlh/eezJS/R27tQahsiFepdaVaH/wmZ7cRQg+59IJDTWU3YBOU5fXtQlEIGQWFwMCTFMNaN7V
+qnJNk22CDtucvc+081xdVHppCZbW2xHBjXWotM85yM48vCR85mLK4b19p71XZQvk/iXttmkQ3Cga
+Rr0BHdCXteGYO8A3ZNY9lO4L4fUorgtWv3GLIylBjobFS1J72HGrH4oVpjuDWtdYAVHGTEHZf9hB
+Z3KiKN9gg6meyHv8U3NyWfWTehd2Ds735VzZC1U0oqpbtWpU5xPKV+yXbfReBi9Fi1jUIxaS5BZu
+KGNZMN9QAZxjiRqf2xeUgnA3wySemkfWWspOqGmJch+RbNt+nhutxx9z3SxPGWX9f5NAEC7S8O08
+ni4oPmkmM8V7AgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFNq7LqqwDLiIJlF0
+XG0D08DYj3rWMB8GA1UdIwQYMBaAFNq7LqqwDLiIJlF0XG0D08DYj3rWMA4GA1UdDwEB/wQEAwIB
+hjANBgkqhkiG9w0BAQUFAAOCAgEAMXjmx7XfuJRAyXHEqDXsRh3ChfMoWIawC/yOsjmPRFWrZIRc
+aanQmjg8+uUfNeVE44B5lGiku8SfPeE0zTBGi1QrlaXv9z+ZhP015s8xxtxqv6fXIwjhmF7DWgh2
+qaavdy+3YL1ERmrvl/9zlcGO6JP7/TG37FcREUWbMPEaiDnBTzynANXH/KttgCJwpQzgXQQpAvvL
+oJHRfNbDflDVnVi+QTjruXU8FdmbyUqDWcDaU/0zuzYYm4UPFd3uLax2k7nZAY1IEKj79TiG8dsK
+xr2EoyNB3tZ3b4XUhRxQ4K5RirqNPnbiucon8l+f725ZDQbYKxek0nxru18UGkiPGkzns0ccjkxF
+KyDuSN/n3QmOGKjaQI2SJhFTYXNd673nxE0pN2HrrDktZy4W1vUAg4WhzH92xH3kt0tm7wNFYGm2
+DFKWkoRepqO1pD4r2czYG0eq8kTaT/kD6PAUyz/zg97QwVTjt+gKN02LIFkDMBmhLMi9ER/frslK
+xfMnZmaGrGiR/9nmUxwPi1xpZQomyB40w11Re9epnAahNt3ViZS82eQtDF4JbAiXfKM9fJP/P6EU
+p8+1Xevb2xzEdt+Iub1FBZUbrvxGakyvSOPOrg/SfuvmbJxPgWp6ZKy7PtXny3YuxadIwVyQD8vI
+P/rmMuGNG2+k5o7Y+SlIis5z/iw=
+-----END CERTIFICATE-----
+
+GeoTrust Universal CA 2
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFbDCCA1SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMN
+R2VvVHJ1c3QgSW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwHhcNMDQwMzA0
+MDUwMDAwWhcNMjkwMzA0MDUwMDAwWjBHMQswCQYDVQQGEwJVUzEWMBQGA1UEChMNR2VvVHJ1c3Qg
+SW5jLjEgMB4GA1UEAxMXR2VvVHJ1c3QgVW5pdmVyc2FsIENBIDIwggIiMA0GCSqGSIb3DQEBAQUA
+A4ICDwAwggIKAoICAQCzVFLByT7y2dyxUxpZKeexw0Uo5dfR7cXFS6GqdHtXr0om/Nj1XqduGdt0
+DE81WzILAePb63p3NeqqWuDW6KFXlPCQo3RWlEQwAx5cTiuFJnSCegx2oG9NzkEtoBUGFF+3Qs17
+j1hhNNwqCPkuwwGmIkQcTAeC5lvO0Ep8BNMZcyfwqph/Lq9O64ceJHdqXbboW0W63MOhBW9Wjo8Q
+JqVJwy7XQYci4E+GymC16qFjwAGXEHm9ADwSbSsVsaxLse4YuU6W3Nx2/zu+z18DwPw76L5GG//a
+QMJS9/7jOvdqdzXQ2o3rXhhqMcceujwbKNZrVMaqW9eiLBsZzKIC9ptZvTdrhrVtgrrY6slWvKk2
+WP0+GfPtDCapkzj4T8FdIgbQl+rhrcZV4IErKIM6+vR7IVEAvlI4zs1meaj0gVbi0IMJR1FbUGrP
+20gaXT73y/Zl92zxlfgCOzJWgjl6W70viRu/obTo/3+NjN8D8WBOWBFM66M/ECuDmgFz2ZRthAAn
+ZqzwcEAJQpKtT5MNYQlRJNiS1QuUYbKHsu3/mjX/hVTK7URDrBs8FmtISgocQIgfksILAAX/8sgC
+SqSqqcyZlpwvWOB94b67B9xfBHJcMTTD7F8t4D1kkCLm0ey4Lt1ZrtmhN79UNdxzMk+MBB4zsslG
+8dhcyFVQyWi9qLo2CQIDAQABo2MwYTAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBR281Xh+qQ2
++/CfXGJx7Tz0RzgQKzAfBgNVHSMEGDAWgBR281Xh+qQ2+/CfXGJx7Tz0RzgQKzAOBgNVHQ8BAf8E
+BAMCAYYwDQYJKoZIhvcNAQEFBQADggIBAGbBxiPz2eAubl/oz66wsCVNK/g7WJtAJDday6sWSf+z
+dXkzoS9tcBc0kf5nfo/sm+VegqlVHy/c1FEHEv6sFj4sNcZj/NwQ6w2jqtB8zNHQL1EuxBRa3ugZ
+4T7GzKQp5y6EqgYweHZUcyiYWTjgAA1i00J9IZ+uPTqM1fp3DRgrFg5fNuH8KrUwJM/gYwx7WBr+
+mbpCErGR9Hxo4sjoryzqyX6uuyo9DRXcNJW2GHSoag/HtPQTxORb7QrSpJdMKu0vbBKJPfEncKpq
+A1Ihn0CoZ1Dy81of398j9tx4TuaYT1U6U+Pv8vSfx3zYWK8pIpe44L2RLrB27FcRz+8pRPPphXpg
+Y+RdM4kX2TGq2tbzGDVyz4crL2MjhF2EjD9XoIj8mZEoJmmZ1I+XRL6O1UixpCgp8RW04eWe3fiP
+pm8m1wk8OhwRDqZsN/etRIcsKMfYdIKz0G9KV7s1KSegi+ghp4dkNl3M2Basx7InQJJVOCiNUW7d
+FGdTbHFcJoRNdVq2fmBWqU2t+5sel/MN2dKXVHfaPRK34B7vCAas+YWH6aLcr34YEoP9VhdBLtUp
+gn2Z9DH2canPLAEnpQW5qrJITirvn5NSUZU8UnOOVkwXQMAJKOSLakhT2+zNVVXxxvjpoixMptEm
+X36vWkzaH6byHCx+rgIW0lbQL1dTR+iS
+-----END CERTIFICATE-----
+
+UTN-USER First-Network Applications
+===================================
+-----BEGIN CERTIFICATE-----
+MIIEZDCCA0ygAwIBAgIQRL4Mi1AAJLQR0zYwS8AzdzANBgkqhkiG9w0BAQUFADCBozELMAkGA1UE
+BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
+IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzAp
+BgNVBAMTIlVUTi1VU0VSRmlyc3QtTmV0d29yayBBcHBsaWNhdGlvbnMwHhcNOTkwNzA5MTg0ODM5
+WhcNMTkwNzA5MTg1NzQ5WjCBozELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5T
+YWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExho
+dHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xKzApBgNVBAMTIlVUTi1VU0VSRmlyc3QtTmV0d29yayBB
+cHBsaWNhdGlvbnMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCz+5Gh5DZVhawGNFug
+mliy+LUPBXeDrjKxdpJo7CNKyXY/45y2N3kDuatpjQclthln5LAbGHNhSuh+zdMvZOOmfAz6F4Cj
+DUeJT1FxL+78P/m4FoCHiZMlIJpDgmkkdihZNaEdwH+DBmQWICzTSaSFtMBhf1EI+GgVkYDLpdXu
+Ozr0hAReYFmnjDRy7rh4xdE7EkpvfmUnuaRVxblvQ6TFHSyZwFKkeEwVs0CYCGtDxgGwenv1axwi
+P8vv/6jQOkt2FZ7S0cYu49tXGzKiuG/ohqY/cKvlcJKrRB5AUPuco2LkbG6gyN7igEL66S/ozjIE
+j3yNtxyjNTwV3Z7DrpelAgMBAAGjgZEwgY4wCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8w
+HQYDVR0OBBYEFPqGydvguul49Uuo1hXf8NPhahQ8ME8GA1UdHwRIMEYwRKBCoECGPmh0dHA6Ly9j
+cmwudXNlcnRydXN0LmNvbS9VVE4tVVNFUkZpcnN0LU5ldHdvcmtBcHBsaWNhdGlvbnMuY3JsMA0G
+CSqGSIb3DQEBBQUAA4IBAQCk8yXM0dSRgyLQzDKrm5ZONJFUICU0YV8qAhXhi6r/fWRRzwr/vH3Y
+IWp4yy9Rb/hCHTO967V7lMPDqaAt39EpHx3+jz+7qEUqf9FuVSTiuwL7MT++6LzsQCv4AdRWOOTK
+RIK1YSAhZ2X28AvnNPilwpyjXEAfhZOVBt5P1CeptqX8Fs1zMT+4ZSfP1FMa8Kxun08FDAOBp4Qp
+xFq9ZFdyrTvPNximmMatBrTcCKME1SmklpoSZ0qMYEWd8SOasACcaLWYUNPvji6SZbFIPiG+FTAq
+DbUMo2s/rn9X9R+WfN9v3YIwLGUbQErNaLly7HF27FSOH4UMAWr6pjisH8SE
+-----END CERTIFICATE-----
+
+America Online Root Certification Authority 1
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIDpDCCAoygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
+QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSAxMB4XDTAyMDUyODA2MDAwMFoXDTM3MTExOTIwNDMwMFowYzELMAkG
+A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg
+T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAKgv6KRpBgNHw+kqmP8ZonCaxlCyfqXfaE0bfA+2l2h9LaaLl+lkhsmj76CG
+v2BlnEtUiMJIxUo5vxTjWVXlGbR0yLQFOVwWpeKVBeASrlmLojNoWBym1BW32J/X3HGrfpq/m44z
+DyL9Hy7nBzbvYjnF3cu6JRQj3gzGPTzOggjmZj7aUTsWOqMFf6Dch9Wc/HKpoH145LcxVR5lu9Rh
+sCFg7RAycsWSJR74kEoYeEfffjA3PlAb2xzTa5qGUwew76wGePiEmf4hjUyAtgyC9mZweRrTT6PP
+8c9GsEsPPt2IYriMqQkoO3rHl+Ee5fSfwMCuJKDIodkP1nsmgmkyPacCAwEAAaNjMGEwDwYDVR0T
+AQH/BAUwAwEB/zAdBgNVHQ4EFgQUAK3Zo/Z59m50qX8zPYEX10zPM94wHwYDVR0jBBgwFoAUAK3Z
+o/Z59m50qX8zPYEX10zPM94wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEBBQUAA4IBAQB8itEf
+GDeC4Liwo+1WlchiYZwFos3CYiZhzRAW18y0ZTTQEYqtqKkFZu90821fnZmv9ov761KyBZiibyrF
+VL0lvV+uyIbqRizBs73B6UlwGBaXCBOMIOAbLjpHyx7kADCVW/RFo8AasAFOq73AI25jP4BKxQft
+3OJvx8Fi8eNy1gTIdGcL+oiroQHIb/AUr9KZzVGTfu0uOMe9zkZQPXLjeSWdm4grECDdpbgyn43g
+Kd8hdIaC2y+CMMbHNYaz+ZZfRtsMRf3zUMNvxsNIrUam4SdHCh0Om7bCd39j8uB9Gr784N/Xx6ds
+sPmuujz9dLQR6FgNgLzTqIA6me11zEZ7
+-----END CERTIFICATE-----
+
+America Online Root Certification Authority 2
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIFpDCCA4ygAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEcMBoGA1UEChMT
+QW1lcmljYSBPbmxpbmUgSW5jLjE2MDQGA1UEAxMtQW1lcmljYSBPbmxpbmUgUm9vdCBDZXJ0aWZp
+Y2F0aW9uIEF1dGhvcml0eSAyMB4XDTAyMDUyODA2MDAwMFoXDTM3MDkyOTE0MDgwMFowYzELMAkG
+A1UEBhMCVVMxHDAaBgNVBAoTE0FtZXJpY2EgT25saW5lIEluYy4xNjA0BgNVBAMTLUFtZXJpY2Eg
+T25saW5lIFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgMjCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAMxBRR3pPU0Q9oyxQcngXssNt79Hc9PwVU3dxgz6sWYFas14tNwC206B89en
+fHG8dWOgXeMHDEjsJcQDIPT/DjsS/5uN4cbVG7RtIuOx238hZK+GvFciKtZHgVdEglZTvYYUAQv8
+f3SkWq7xuhG1m1hagLQ3eAkzfDJHA1zEpYNI9FdWboE2JxhP7JsowtS013wMPgwr38oE18aO6lhO
+qKSlGBxsRZijQdEt0sdtjRnxrXm3gT+9BoInLRBYBbV4Bbkv2wxrkJB+FFk4u5QkE+XRnRTf04JN
+RvCAOVIyD+OEsnpD8l7eXz8d3eOyG6ChKiMDbi4BFYdcpnV1x5dhvt6G3NRI270qv0pV2uh9UPu0
+gBe4lL8BPeraunzgWGcXuVjgiIZGZ2ydEEdYMtA1fHkqkKJaEBEjNa0vzORKW6fIJ/KD3l67Xnfn
+6KVuY8INXWHQjNJsWiEOyiijzirplcdIz5ZvHZIlyMbGwcEMBawmxNJ10uEqZ8A9W6Wa6897Gqid
+FEXlD6CaZd4vKL3Ob5Rmg0gp2OpljK+T2WSfVVcmv2/LNzGZo2C7HK2JNDJiuEMhBnIMoVxtRsX6
+Kc8w3onccVvdtjc+31D1uAclJuW8tf48ArO3+L5DwYcRlJ4jbBeKuIonDFRH8KmzwICMoCfrHRnj
+B453cMor9H124HhnAgMBAAGjYzBhMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFE1FwWg4u3Op
+aaEg5+31IqEjFNeeMB8GA1UdIwQYMBaAFE1FwWg4u3OpaaEg5+31IqEjFNeeMA4GA1UdDwEB/wQE
+AwIBhjANBgkqhkiG9w0BAQUFAAOCAgEAZ2sGuV9FOypLM7PmG2tZTiLMubekJcmnxPBUlgtk87FY
+T15R/LKXeydlwuXK5w0MJXti4/qftIe3RUavg6WXSIylvfEWK5t2LHo1YGwRgJfMqZJS5ivmae2p
++DYtLHe/YUjRYwu5W1LtGLBDQiKmsXeu3mnFzcccobGlHBD7GL4acN3Bkku+KVqdPzW+5X1R+FXg
+JXUjhx5c3LqdsKyzadsXg8n33gy8CNyRnqjQ1xU3c6U1uPx+xURABsPr+CKAXEfOAuMRn0T//Zoy
+zH1kUQ7rVyZ2OuMeIjzCpjbdGe+n/BLzJsBZMYVMnNjP36TMzCmT/5RtdlwTCJfy7aULTd3oyWgO
+ZtMADjMSW7yV5TKQqLPGbIOtd+6Lfn6xqavT4fG2wLHqiMDn05DpKJKUe2h7lyoKZy2FAjgQ5ANh
+1NolNscIWC2hp1GvMApJ9aZphwctREZ2jirlmjvXGKL8nDgQzMY70rUXOm/9riW99XJZZLF0Kjhf
+GEzfz3EEWjbUvy+ZnOjZurGV5gJLIaFb1cFPj65pbVPbAZO1XB4Y3WRayhgoPmMEEf0cjQAPuDff
+Z4qdZqkCapH/E8ovXYO8h5Ns3CRRFgQlZvqz2cK6Kb6aSDiCmfS/O0oxGfm/jiEzFMpPVF/7zvuP
+cX/9XhmgD0uRuMRUvAawRY8mkaKO/qk=
+-----END CERTIFICATE-----
+
+Visa eCommerce Root
+===================
+-----BEGIN CERTIFICATE-----
+MIIDojCCAoqgAwIBAgIQE4Y1TR0/BvLB+WUF1ZAcYjANBgkqhkiG9w0BAQUFADBrMQswCQYDVQQG
+EwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMmVmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2Ug
+QXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNvbW1lcmNlIFJvb3QwHhcNMDIwNjI2MDIxODM2
+WhcNMjIwNjI0MDAxNjEyWjBrMQswCQYDVQQGEwJVUzENMAsGA1UEChMEVklTQTEvMC0GA1UECxMm
+VmlzYSBJbnRlcm5hdGlvbmFsIFNlcnZpY2UgQXNzb2NpYXRpb24xHDAaBgNVBAMTE1Zpc2EgZUNv
+bW1lcmNlIFJvb3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvV95WHm6h2mCxlCfL
+F9sHP4CFT8icttD0b0/Pmdjh28JIXDqsOTPHH2qLJj0rNfVIsZHBAk4ElpF7sDPwsRROEW+1QK8b
+RaVK7362rPKgH1g/EkZgPI2h4H3PVz4zHvtH8aoVlwdVZqW1LS7YgFmypw23RuwhY/81q6UCzyr0
+TP579ZRdhE2o8mCP2w4lPJ9zcc+U30rq299yOIzzlr3xF7zSujtFWsan9sYXiwGd/BmoKoMWuDpI
+/k4+oKsGGelT84ATB+0tvz8KPFUgOSwsAGl0lUq8ILKpeeUYiZGo3BxN77t+Nwtd/jmliFKMAGzs
+GHxBvfaLdXe6YJ2E5/4tAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEG
+MB0GA1UdDgQWBBQVOIMPPyw/cDMezUb+B4wg4NfDtzANBgkqhkiG9w0BAQUFAAOCAQEAX/FBfXxc
+CLkr4NWSR/pnXKUTwwMhmytMiUbPWU3J/qVAtmPN3XEolWcRzCSs00Rsca4BIGsDoo8Ytyk6feUW
+YFN4PMCvFYP3j1IzJL1kk5fui/fbGKhtcbP3LBfQdCVp9/5rPJS+TUtBjE7ic9DjkCJzQ83z7+pz
+zkWKsKZJ/0x9nXGIxHYdkFsd7v3M9+79YKWxehZx0RbQfBI8bGmX265fOZpwLwU8GUYEmSA20GBu
+YQa7FkKMcPcw++DbZqMAAb3mLNqRX6BGi01qnD093QVG/na/oAo85ADmJ7f/hC3euiInlhBx6yLt
+398znM/jra6O1I7mT1GvFpLgXPYHDw==
+-----END CERTIFICATE-----
+
+Certum Root CA
+==============
+-----BEGIN CERTIFICATE-----
+MIIDDDCCAfSgAwIBAgIDAQAgMA0GCSqGSIb3DQEBBQUAMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQK
+ExJVbml6ZXRvIFNwLiB6IG8uby4xEjAQBgNVBAMTCUNlcnR1bSBDQTAeFw0wMjA2MTExMDQ2Mzla
+Fw0yNzA2MTExMDQ2MzlaMD4xCzAJBgNVBAYTAlBMMRswGQYDVQQKExJVbml6ZXRvIFNwLiB6IG8u
+by4xEjAQBgNVBAMTCUNlcnR1bSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAM6x
+wS7TT3zNJc4YPk/EjG+AanPIW1H4m9LcuwBcsaD8dQPugfCI7iNS6eYVM42sLQnFdvkrOYCJ5JdL
+kKWoePhzQ3ukYbDYWMzhbGZ+nPMJXlVjhNWo7/OxLjBos8Q82KxujZlakE403Daaj4GIULdtlkIJ
+89eVgw1BS7Bqa/j8D35in2fE7SZfECYPCE/wpFcozo+47UX2bu4lXapuOb7kky/ZR6By6/qmW6/K
+Uz/iDsaWVhFu9+lmqSbYf5VT7QqFiLpPKaVCjF62/IUgAKpoC6EahQGcxEZjgoi2IrHu/qpGWX7P
+NSzVttpd90gzFFS269lvzs2I1qsb2pY7HVkCAwEAAaMTMBEwDwYDVR0TAQH/BAUwAwEB/zANBgkq
+hkiG9w0BAQUFAAOCAQEAuI3O7+cUus/usESSbLQ5PqKEbq24IXfS1HeCh+YgQYHu4vgRt2PRFze+
+GXYkHAQaTOs9qmdvLdTN/mUxcMUbpgIKumB7bVjCmkn+YzILa+M6wKyrO7Do0wlRjBCDxjTgxSvg
+GrZgFCdsMneMvLJymM/NzD+5yCRCFNZX/OYmQ6kd5YCQzgNUKD73P9P4Te1qCjqTE5s7FCMTY5w/
+0YcneeVMUeMBrYVdGjux1XMQpNPyvG5k9VpWkKjHDkx0Dy5xO/fIR/RpbxXyEV6DHpx8Uq79AtoS
+qFlnGNu8cN2bsWntgM6JQEhqDjXKKWYVIZQs6GAqm4VKQPNriiTsBhYscw==
+-----END CERTIFICATE-----
+
+Comodo AAA Services root
+========================
+-----BEGIN CERTIFICATE-----
+MIIEMjCCAxqgAwIBAgIBATANBgkqhkiG9w0BAQUFADB7MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
+R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
+TGltaXRlZDEhMB8GA1UEAwwYQUFBIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAwMDAw
+MFoXDTI4MTIzMTIzNTk1OVowezELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFuY2hl
+c3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxITAfBgNV
+BAMMGEFBQSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAL5AnfRu4ep2hxxNRUSOvkbIgwadwSr+GB+O5AL686tdUIoWMQuaBtDFcCLNSS1UY8y2bmhG
+C1Pqy0wkwLxyTurxFa70VJoSCsN6sjNg4tqJVfMiWPPe3M/vg4aijJRPn2jymJBGhCfHdr/jzDUs
+i14HZGWCwEiwqJH5YZ92IFCokcdmtet4YgNW8IoaE+oxox6gmf049vYnMlhvB/VruPsUK6+3qszW
+Y19zjNoFmag4qMsXeDZRrOme9Hg6jc8P2ULimAyrL58OAd7vn5lJ8S3frHRNG5i1R8XlKdH5kBjH
+Ypy+g8cmez6KJcfA3Z3mNWgQIJ2P2N7Sw4ScDV7oL8kCAwEAAaOBwDCBvTAdBgNVHQ4EFgQUoBEK
+Iz6W8Qfs4q8p74Klf9AwpLQwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wewYDVR0f
+BHQwcjA4oDagNIYyaHR0cDovL2NybC5jb21vZG9jYS5jb20vQUFBQ2VydGlmaWNhdGVTZXJ2aWNl
+cy5jcmwwNqA0oDKGMGh0dHA6Ly9jcmwuY29tb2RvLm5ldC9BQUFDZXJ0aWZpY2F0ZVNlcnZpY2Vz
+LmNybDANBgkqhkiG9w0BAQUFAAOCAQEACFb8AvCb6P+k+tZ7xkSAzk/ExfYAWMymtrwUSWgEdujm
+7l3sAg9g1o1QGE8mTgHj5rCl7r+8dFRBv/38ErjHT1r0iWAFf2C3BUrz9vHCv8S5dIa2LX1rzNLz
+Rt0vxuBqw8M0Ayx9lt1awg6nCpnBBYurDC/zXDrPbDdVCYfeU0BsWO/8tqtlbgT2G9w84FoVxp7Z
+8VlIMCFlA2zs6SFz7JsDoeA3raAVGI/6ugLOpyypEBMs1OUIJqsil2D4kF501KKaU73yqWjgom7C
+12yxow+ev+to51byrvLjKzg6CYG1a4XXvi3tPxq3smPi9WIsgtRqAEFQ8TmDn5XpNpaYbg==
+-----END CERTIFICATE-----
+
+Comodo Secure Services root
+===========================
+-----BEGIN CERTIFICATE-----
+MIIEPzCCAyegAwIBAgIBATANBgkqhkiG9w0BAQUFADB+MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
+R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
+TGltaXRlZDEkMCIGA1UEAwwbU2VjdXJlIENlcnRpZmljYXRlIFNlcnZpY2VzMB4XDTA0MDEwMTAw
+MDAwMFoXDTI4MTIzMTIzNTk1OVowfjELMAkGA1UEBhMCR0IxGzAZBgNVBAgMEkdyZWF0ZXIgTWFu
+Y2hlc3RlcjEQMA4GA1UEBwwHU2FsZm9yZDEaMBgGA1UECgwRQ29tb2RvIENBIExpbWl0ZWQxJDAi
+BgNVBAMMG1NlY3VyZSBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBAMBxM4KK0HDrc4eCQNUd5MvJDkKQ+d40uaG6EfQlhfPMcm3ye5drswfxdySRXyWP
+9nQ95IDC+DwN879A6vfIUtFyb+/Iq0G4bi4XKpVpDM3SHpR7LZQdqnXXs5jLrLxkU0C8j6ysNstc
+rbvd4JQX7NFc0L/vpZXJkMWwrPsbQ996CF23uPJAGysnnlDOXmWCiIxe004MeuoIkbY2qitC++rC
+oznl2yY4rYsK7hljxxwk3wN42ubqwUcaCwtGCd0C/N7Lh1/XMGNooa7cMqG6vv5Eq2i2pRcV/b3V
+p6ea5EQz6YiO/O1R65NxTq0B50SOqy3LqP4BSUjwwN3HaNiS/j0CAwEAAaOBxzCBxDAdBgNVHQ4E
+FgQUPNiTiMLAggnMAZkGkyDpnnAJY08wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8w
+gYEGA1UdHwR6MHgwO6A5oDeGNWh0dHA6Ly9jcmwuY29tb2RvY2EuY29tL1NlY3VyZUNlcnRpZmlj
+YXRlU2VydmljZXMuY3JsMDmgN6A1hjNodHRwOi8vY3JsLmNvbW9kby5uZXQvU2VjdXJlQ2VydGlm
+aWNhdGVTZXJ2aWNlcy5jcmwwDQYJKoZIhvcNAQEFBQADggEBAIcBbSMdflsXfcFhMs+P5/OKlFlm
+4J4oqF7Tt/Q05qo5spcWxYJvMqTpjOev/e/C6LlLqqP05tqNZSH7uoDrJiiFGv45jN5bBAS0VPmj
+Z55B+glSzAVIqMk/IQQezkhr/IXownuvf7fM+F86/TXGDe+X3EyrEeFryzHRbPtIgKvcnDe4IRRL
+DXE97IMzbtFuMhbsmMcWi1mmNKsFVy2T96oTy9IT4rcuO81rUBcJaD61JlfutuC23bkpgHl9j6Pw
+pCikFcSF9CfUa7/lXORlAnZUtOM3ZiTTGWHIUhDlizeauan5Hb/qmZJhlv8BzaFfDbxxvA6sCx1H
+RR3B7Hzs/Sk=
+-----END CERTIFICATE-----
+
+Comodo Trusted Services root
+============================
+-----BEGIN CERTIFICATE-----
+MIIEQzCCAyugAwIBAgIBATANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJHQjEbMBkGA1UECAwS
+R3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHDAdTYWxmb3JkMRowGAYDVQQKDBFDb21vZG8gQ0Eg
+TGltaXRlZDElMCMGA1UEAwwcVHJ1c3RlZCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczAeFw0wNDAxMDEw
+MDAwMDBaFw0yODEyMzEyMzU5NTlaMH8xCzAJBgNVBAYTAkdCMRswGQYDVQQIDBJHcmVhdGVyIE1h
+bmNoZXN0ZXIxEDAOBgNVBAcMB1NhbGZvcmQxGjAYBgNVBAoMEUNvbW9kbyBDQSBMaW1pdGVkMSUw
+IwYDVQQDDBxUcnVzdGVkIENlcnRpZmljYXRlIFNlcnZpY2VzMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA33FvNlhTWvI2VFeAxHQIIO0Yfyod5jWaHiWsnOWWfnJSoBVC21ndZHoa0Lh7
+3TkVvFVIxO06AOoxEbrycXQaZ7jPM8yoMa+j49d/vzMtTGo87IvDktJTdyR0nAducPy9C1t2ul/y
+/9c3S0pgePfw+spwtOpZqqPOSC+pw7ILfhdyFgymBwwbOM/JYrc/oJOlh0Hyt3BAd9i+FHzjqMB6
+juljatEPmsbS9Is6FARW1O24zG71++IsWL1/T2sr92AkWCTOJu80kTrV44HQsvAEAtdbtz6SrGsS
+ivnkBbA7kUlcsutT6vifR4buv5XAwAaf0lteERv0xwQ1KdJVXOTt6wIDAQABo4HJMIHGMB0GA1Ud
+DgQWBBTFe1i97doladL3WRaoszLAeydb9DAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB
+/zCBgwYDVR0fBHwwejA8oDqgOIY2aHR0cDovL2NybC5jb21vZG9jYS5jb20vVHJ1c3RlZENlcnRp
+ZmljYXRlU2VydmljZXMuY3JsMDqgOKA2hjRodHRwOi8vY3JsLmNvbW9kby5uZXQvVHJ1c3RlZENl
+cnRpZmljYXRlU2VydmljZXMuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQDIk4E7ibSvuIQSTI3S8Ntw
+uleGFTQQuS9/HrCoiWChisJ3DFBKmwCL2Iv0QeLQg4pKHBQGsKNoBXAxMKdTmw7pSqBYaWcOrp32
+pSxBvzwGa+RZzG0Q8ZZvH9/0BAKkn0U+yNj6NkZEUD+Cl5EfKNsYEYwq5GWDVxISjBc/lDb+XbDA
+BHcTuPQV1T84zJQ6VdCsmPW6AF/ghhmBeC8owH7TzEIK9a5QoNE+xqFx7D+gIIxmOom0jtTYsU0l
+R+4viMi14QVFwL4Ucd56/Y57fU0IlqUSc/AtyjcndBInTMu2l+nZrghtWjlA3QVHdWpaIbOjGM9O
+9y5Xt5hwXsjEeLBi
+-----END CERTIFICATE-----
+
+QuoVadis Root CA
+================
+-----BEGIN CERTIFICATE-----
+MIIF0DCCBLigAwIBAgIEOrZQizANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJCTTEZMBcGA1UE
+ChMQUXVvVmFkaXMgTGltaXRlZDElMCMGA1UECxMcUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0
+eTEuMCwGA1UEAxMlUXVvVmFkaXMgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wMTAz
+MTkxODMzMzNaFw0yMTAzMTcxODMzMzNaMH8xCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRp
+cyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MS4wLAYDVQQD
+EyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAv2G1lVO6V/z68mcLOhrfEYBklbTRvM16z/Ypli4kVEAkOPcahdxYTMuk
+J0KX0J+DisPkBgNbAKVRHnAEdOLB1Dqr1607BxgFjv2DrOpm2RgbaIr1VxqYuvXtdj182d6UajtL
+F8HVj71lODqV0D1VNk7feVcxKh7YWWVJWCCYfqtffp/p1k3sg3Spx2zY7ilKhSoGFPlU5tPaZQeL
+YzcS19Dsw3sgQUSj7cugF+FxZc4dZjH3dgEZyH0DWLaVSR2mEiboxgx24ONmy+pdpibu5cxfvWen
+AScOospUxbF6lR1xHkopigPcakXBpBlebzbNw6Kwt/5cOOJSvPhEQ+aQuwIDAQABo4ICUjCCAk4w
+PQYIKwYBBQUHAQEEMTAvMC0GCCsGAQUFBzABhiFodHRwczovL29jc3AucXVvdmFkaXNvZmZzaG9y
+ZS5jb20wDwYDVR0TAQH/BAUwAwEB/zCCARoGA1UdIASCAREwggENMIIBCQYJKwYBBAG+WAABMIH7
+MIHUBggrBgEFBQcCAjCBxxqBxFJlbGlhbmNlIG9uIHRoZSBRdW9WYWRpcyBSb290IENlcnRpZmlj
+YXRlIGJ5IGFueSBwYXJ0eSBhc3N1bWVzIGFjY2VwdGFuY2Ugb2YgdGhlIHRoZW4gYXBwbGljYWJs
+ZSBzdGFuZGFyZCB0ZXJtcyBhbmQgY29uZGl0aW9ucyBvZiB1c2UsIGNlcnRpZmljYXRpb24gcHJh
+Y3RpY2VzLCBhbmQgdGhlIFF1b1ZhZGlzIENlcnRpZmljYXRlIFBvbGljeS4wIgYIKwYBBQUHAgEW
+Fmh0dHA6Ly93d3cucXVvdmFkaXMuYm0wHQYDVR0OBBYEFItLbe3TKbkGGew5Oanwl4Rqy+/fMIGu
+BgNVHSMEgaYwgaOAFItLbe3TKbkGGew5Oanwl4Rqy+/foYGEpIGBMH8xCzAJBgNVBAYTAkJNMRkw
+FwYDVQQKExBRdW9WYWRpcyBMaW1pdGVkMSUwIwYDVQQLExxSb290IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MS4wLAYDVQQDEyVRdW9WYWRpcyBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggQ6
+tlCLMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAitQUtf70mpKnGdSkfnIYj9lo
+fFIk3WdvOXrEql494liwTXCYhGHoG+NpGA7O+0dQoE7/8CQfvbLO9Sf87C9TqnN7Az10buYWnuul
+LsS/VidQK2K6vkscPFVcQR0kvoIgR13VRH56FmjffU1RcHhXHTMe/QKZnAzNCgVPx7uOpHX6Sm2x
+gI4JVrmcGmD+XcHXetwReNDWXcG31a0ymQM6isxUJTkxgXsTIlG6Rmyhu576BGxJJnSP0nPrzDCi
+5upZIof4l/UO/erMkqQWxFIY6iHOsfHmhIHluqmGKPJDWl0Snawe2ajlCmqnf6CHKc/yiU3U7MXi
+5nrQNiOKSnQ2+Q==
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 2
+==================
+-----BEGIN CERTIFICATE-----
+MIIFtzCCA5+gAwIBAgICBQkwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
+EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMjAeFw0wNjExMjQx
+ODI3MDBaFw0zMTExMjQxODIzMzNaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDIwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQCaGMpLlA0ALa8DKYrwD4HIrkwZhR0In6spRIXzL4GtMh6QRr+jhiYaHv5+HBg6
+XJxgFyo6dIMzMH1hVBHL7avg5tKifvVrbxi3Cgst/ek+7wrGsxDp3MJGF/hd/aTa/55JWpzmM+Yk
+lvc/ulsrHHo1wtZn/qtmUIttKGAr79dgw8eTvI02kfN/+NsRE8Scd3bBrrcCaoF6qUWD4gXmuVbB
+lDePSHFjIuwXZQeVikvfj8ZaCuWw419eaxGrDPmF60Tp+ARz8un+XJiM9XOva7R+zdRcAitMOeGy
+lZUtQofX1bOQQ7dsE/He3fbE+Ik/0XX1ksOR1YqI0JDs3G3eicJlcZaLDQP9nL9bFqyS2+r+eXyt
+66/3FsvbzSUr5R/7mp/iUcw6UwxI5g69ybR2BlLmEROFcmMDBOAENisgGQLodKcftslWZvB1Jdxn
+wQ5hYIizPtGo/KPaHbDRsSNU30R2be1B2MGyIrZTHN81Hdyhdyox5C315eXbyOD/5YDXC2Og/zOh
+D7osFRXql7PSorW+8oyWHhqPHWykYTe5hnMz15eWniN9gqRMgeKh0bpnX5UHoycR7hYQe7xFSkyy
+BNKr79X9DFHOUGoIMfmR2gyPZFwDwzqLID9ujWc9Otb+fVuIyV77zGHcizN300QyNQliBJIWENie
+J0f7OyHj+OsdWwIDAQABo4GwMIGtMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgEGMB0GA1Ud
+DgQWBBQahGK8SEwzJQTU7tD2A8QZRtGUazBuBgNVHSMEZzBlgBQahGK8SEwzJQTU7tD2A8QZRtGU
+a6FJpEcwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoTEFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMT
+ElF1b1ZhZGlzIFJvb3QgQ0EgMoICBQkwDQYJKoZIhvcNAQEFBQADggIBAD4KFk2fBluornFdLwUv
+Z+YTRYPENvbzwCYMDbVHZF34tHLJRqUDGCdViXh9duqWNIAXINzng/iN/Ae42l9NLmeyhP3ZRPx3
+UIHmfLTJDQtyU/h2BwdBR5YM++CCJpNVjP4iH2BlfF/nJrP3MpCYUNQ3cVX2kiF495V5+vgtJodm
+VjB3pjd4M1IQWK4/YY7yarHvGH5KWWPKjaJW1acvvFYfzznB4vsKqBUsfU16Y8Zsl0Q80m/DShcK
++JDSV6IZUaUtl0HaB0+pUNqQjZRG4T7wlP0QADj1O+hA4bRuVhogzG9Yje0uRY/W6ZM/57Es3zrW
+IozchLsib9D45MY56QSIPMO661V6bYCZJPVsAfv4l7CUW+v90m/xd2gNNWQjrLhVoQPRTUIZ3Ph1
+WVaj+ahJefivDrkRoHy3au000LYmYjgahwz46P0u05B/B5EqHdZ+XIWDmbA4CD/pXvk1B+TJYm5X
+f6dQlfe6yJvmjqIBxdZmv3lh8zwc4bmCXF2gw+nYSL0ZohEUGW6yhhtoPkg3Goi3XZZenMfvJ2II
+4pEZXNLxId26F0KCl3GBUzGpn/Z9Yr9y4aOTHcyKJloJONDO1w2AFrR4pTqHTI2KpdVGl/IsELm8
+VCLAAVBpQ570su9t+Oza8eOx79+Rj1QqCyXBJhnEUhAFZdWCEOrCMc0u
+-----END CERTIFICATE-----
+
+QuoVadis Root CA 3
+==================
+-----BEGIN CERTIFICATE-----
+MIIGnTCCBIWgAwIBAgICBcYwDQYJKoZIhvcNAQEFBQAwRTELMAkGA1UEBhMCQk0xGTAXBgNVBAoT
+EFF1b1ZhZGlzIExpbWl0ZWQxGzAZBgNVBAMTElF1b1ZhZGlzIFJvb3QgQ0EgMzAeFw0wNjExMjQx
+OTExMjNaFw0zMTExMjQxOTA2NDRaMEUxCzAJBgNVBAYTAkJNMRkwFwYDVQQKExBRdW9WYWRpcyBM
+aW1pdGVkMRswGQYDVQQDExJRdW9WYWRpcyBSb290IENBIDMwggIiMA0GCSqGSIb3DQEBAQUAA4IC
+DwAwggIKAoICAQDMV0IWVJzmmNPTTe7+7cefQzlKZbPoFog02w1ZkXTPkrgEQK0CSzGrvI2RaNgg
+DhoB4hp7Thdd4oq3P5kazethq8Jlph+3t723j/z9cI8LoGe+AaJZz3HmDyl2/7FWeUUrH556VOij
+KTVopAFPD6QuN+8bv+OPEKhyq1hX51SGyMnzW9os2l2ObjyjPtr7guXd8lyyBTNvijbO0BNO/79K
+DDRMpsMhvVAEVeuxu537RR5kFd5VAYwCdrXLoT9CabwvvWhDFlaJKjdhkf2mrk7AyxRllDdLkgbv
+BNDInIjbC3uBr7E9KsRlOni27tyAsdLTmZw67mtaa7ONt9XOnMK+pUsvFrGeaDsGb659n/je7Mwp
+p5ijJUMv7/FfJuGITfhebtfZFG4ZM2mnO4SJk8RTVROhUXhA+LjJou57ulJCg54U7QVSWllWp5f8
+nT8KKdjcT5EOE7zelaTfi5m+rJsziO+1ga8bxiJTyPbH7pcUsMV8eFLI8M5ud2CEpukqdiDtWAEX
+MJPpGovgc2PZapKUSU60rUqFxKMiMPwJ7Wgic6aIDFUhWMXhOp8q3crhkODZc6tsgLjoC2SToJyM
+Gf+z0gzskSaHirOi4XCPLArlzW1oUevaPwV/izLmE1xr/l9A4iLItLRkT9a6fUg+qGkM17uGcclz
+uD87nSVL2v9A6wIDAQABo4IBlTCCAZEwDwYDVR0TAQH/BAUwAwEB/zCB4QYDVR0gBIHZMIHWMIHT
+BgkrBgEEAb5YAAMwgcUwgZMGCCsGAQUFBwICMIGGGoGDQW55IHVzZSBvZiB0aGlzIENlcnRpZmlj
+YXRlIGNvbnN0aXR1dGVzIGFjY2VwdGFuY2Ugb2YgdGhlIFF1b1ZhZGlzIFJvb3QgQ0EgMyBDZXJ0
+aWZpY2F0ZSBQb2xpY3kgLyBDZXJ0aWZpY2F0aW9uIFByYWN0aWNlIFN0YXRlbWVudC4wLQYIKwYB
+BQUHAgEWIWh0dHA6Ly93d3cucXVvdmFkaXNnbG9iYWwuY29tL2NwczALBgNVHQ8EBAMCAQYwHQYD
+VR0OBBYEFPLAE+CCQz777i9nMpY1XNu4ywLQMG4GA1UdIwRnMGWAFPLAE+CCQz777i9nMpY1XNu4
+ywLQoUmkRzBFMQswCQYDVQQGEwJCTTEZMBcGA1UEChMQUXVvVmFkaXMgTGltaXRlZDEbMBkGA1UE
+AxMSUXVvVmFkaXMgUm9vdCBDQSAzggIFxjANBgkqhkiG9w0BAQUFAAOCAgEAT62gLEz6wPJv92ZV
+qyM07ucp2sNbtrCD2dDQ4iH782CnO11gUyeim/YIIirnv6By5ZwkajGxkHon24QRiSemd1o417+s
+hvzuXYO8BsbRd2sPbSQvS3pspweWyuOEn62Iix2rFo1bZhfZFvSLgNLd+LJ2w/w4E6oM3kJpK27z
+POuAJ9v1pkQNn1pVWQvVDVJIxa6f8i+AxeoyUDUSly7B4f/xI4hROJ/yZlZ25w9Rl6VSDE1JUZU2
+Pb+iSwwQHYaZTKrzchGT5Or2m9qoXadNt54CrnMAyNojA+j56hl0YgCUyyIgvpSnWbWCar6ZeXqp
+8kokUvd0/bpO5qgdAm6xDYBEwa7TIzdfu4V8K5Iu6H6li92Z4b8nby1dqnuH/grdS/yO9SbkbnBC
+bjPsMZ57k8HkyWkaPcBrTiJt7qtYTcbQQcEr6k8Sh17rRdhs9ZgC06DYVYoGmRmioHfRMJ6szHXu
+g/WwYjnPbFfiTNKRCw51KBuav/0aQ/HKd/s7j2G4aSgWQgRecCocIdiP4b0jWy10QJLZYxkNc91p
+vGJHvOB0K7Lrfb5BG7XARsWhIstfTsEokt4YutUqKLsRixeTmJlglFwjz1onl14LBQaTNx47aTbr
+qZ5hHY8y2o4M1nQ+ewkk2gF3R8Q7zTSMmfXK4SVhM7JZG+Ju1zdXtg2pEto=
+-----END CERTIFICATE-----
+
+Security Communication Root CA
+==============================
+-----BEGIN CERTIFICATE-----
+MIIDWjCCAkKgAwIBAgIBADANBgkqhkiG9w0BAQUFADBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
+U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
+HhcNMDMwOTMwMDQyMDQ5WhcNMjMwOTMwMDQyMDQ5WjBQMQswCQYDVQQGEwJKUDEYMBYGA1UEChMP
+U0VDT00gVHJ1c3QubmV0MScwJQYDVQQLEx5TZWN1cml0eSBDb21tdW5pY2F0aW9uIFJvb3RDQTEw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCzs/5/022x7xZ8V6UMbXaKL0u/ZPtM7orw
+8yl89f/uKuDp6bpbZCKamm8sOiZpUQWZJtzVHGpxxpp9Hp3dfGzGjGdnSj74cbAZJ6kJDKaVv0uM
+DPpVmDvY6CKhS3E4eayXkmmziX7qIWgGmBSWh9JhNrxtJ1aeV+7AwFb9Ms+k2Y7CI9eNqPPYJayX
+5HA49LY6tJ07lyZDo6G8SVlyTCMwhwFY9k6+HGhWZq/NQV3Is00qVUarH9oe4kA92819uZKAnDfd
+DJZkndwi92SL32HeFZRSFaB9UslLqCHJxrHty8OVYNEP8Ktw+N/LTX7s1vqr2b1/VPKl6Xn62dZ2
+JChzAgMBAAGjPzA9MB0GA1UdDgQWBBSgc0mZaNyFW2XjmygvV5+9M7wHSDALBgNVHQ8EBAMCAQYw
+DwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQUFAAOCAQEAaECpqLvkT115swW1F7NgE+vGkl3g
+0dNq/vu+m22/xwVtWSDEHPC32oRYAmP6SBbvT6UL90qY8j+eG61Ha2POCEfrUj94nK9NrvjVT8+a
+mCoQQTlSxN3Zmw7vkwGusi7KaEIkQmywszo+zenaSMQVy+n5Bw+SUEmK3TGXX8npN6o7WWWXlDLJ
+s58+OmJYxUmtYg5xpTKqL8aJdkNAExNnPaJUJRDL8Try2frbSVa7pv6nQTXD4IhhyYjH3zYQIphZ
+6rBK+1YWc26sTfcioU+tHXotRSflMMFe8toTyyVCUZVHA4xsIcx0Qu1T/zOLjw9XARYvz6buyXAi
+FL39vmwLAw==
+-----END CERTIFICATE-----
+
+Sonera Class 1 Root CA
+======================
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAgigAwIBAgIBJDANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
+U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MxIENBMB4XDTAxMDQwNjEwNDkxM1oXDTIxMDQw
+NjEwNDkxM1owOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
+IENsYXNzMSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALWJHytPZwp5/8Ue+H88
+7dF+2rDNbS82rDTG29lkFwhjMDMiikzujrsPDUJVyZ0upe/3p4zDq7mXy47vPxVnqIJyY1MPQYx9
+EJUkoVqlBvqSV536pQHydekfvFYmUk54GWVYVQNYwBSujHxVX3BbdyMGNpfzJLWaRpXk3w0LBUXl
+0fIdgrvGE+D+qnr9aTCU89JFhfzyMlsy3uhsXR/LpCJ0sICOXZT3BgBLqdReLjVQCfOAl/QMF645
+2F/NM8EcyonCIvdFEu1eEpOdY6uCLrnrQkFEy0oaAIINnvmLVz5MxxftLItyM19yejhW1ebZrgUa
+HXVFsculJRwSVzb9IjcCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQIR+IMi/ZT
+iFIwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQCLGrLJXWG04bkruVPRsoWdd44W7hE9
+28Jj2VuXZfsSZ9gqXLar5V7DtxYvyOirHYr9qxp81V9jz9yw3Xe5qObSIjiHBxTZ/75Wtf0HDjxV
+yhbMp6Z3N/vbXB9OWQaHowND9Rart4S9Tu+fMTfwRvFAttEMpWT4Y14h21VOTzF2nBBhjrZTOqMR
+vq9tfB69ri3iDGnHhVNoomG6xT60eVR4ngrHAr5i0RGCS2UvkVrCqIexVmiUefkl98HVrhq4uz2P
+qYo4Ffdz0Fpg0YCw8NzVUM1O7pJIae2yIx4wzMiUyLb1O4Z/P6Yun/Y+LLWSlj7fLJOK/4GMDw9Z
+IRlXvVWa
+-----END CERTIFICATE-----
+
+Sonera Class 2 Root CA
+======================
+-----BEGIN CERTIFICATE-----
+MIIDIDCCAgigAwIBAgIBHTANBgkqhkiG9w0BAQUFADA5MQswCQYDVQQGEwJGSTEPMA0GA1UEChMG
+U29uZXJhMRkwFwYDVQQDExBTb25lcmEgQ2xhc3MyIENBMB4XDTAxMDQwNjA3Mjk0MFoXDTIxMDQw
+NjA3Mjk0MFowOTELMAkGA1UEBhMCRkkxDzANBgNVBAoTBlNvbmVyYTEZMBcGA1UEAxMQU29uZXJh
+IENsYXNzMiBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAJAXSjWdyvANlsdE+hY3
+/Ei9vX+ALTU74W+oZ6m/AxxNjG8yR9VBaKQTBME1DJqEQ/xcHf+Js+gXGM2RX/uJ4+q/Tl18GybT
+dXnt5oTjV+WtKcT0OijnpXuENmmz/V52vaMtmdOQTiMofRhj8VQ7Jp12W5dCsv+u8E7s3TmVToMG
+f+dJQMjFAbJUWmYdPfz56TwKnoG4cPABi+QjVHzIrviQHgCWctRUz2EjvOr7nQKV0ba5cTppCD8P
+tOFCx4j1P5iop7oc4HFx71hXgVB6XGt0Rg6DA5jDjqhu8nYybieDwnPz3BjotJPqdURrBGAgcVeH
+nfO+oJAjPYok4doh28MCAwEAAaMzMDEwDwYDVR0TAQH/BAUwAwEB/zARBgNVHQ4ECgQISqCqWITT
+XjwwCwYDVR0PBAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQBazof5FnIVV0sd2ZvnoiYw7JNn39Yt
+0jSv9zilzqsWuasvfDXLrNAPtEwr/IDva4yRXzZ299uzGxnq9LIR/WFxRL8oszodv7ND6J+/3DEI
+cbCdjdY0RzKQxmUk96BKfARzjzlvF4xytb1LyHr4e4PDKE6cCepnP7JnBBvDFNr450kkkdAdavph
+Oe9r5yF1BgfYErQhIHBCcYHaPJo2vqZbDWpsmh+Re/n570K6Tk6ezAyNlNzZRZxe7EJQY670XcSx
+EtzKO6gunRRaBXW37Ndj4ro1tgQIkejanZz2ZrUYrAqmVCY0M9IbwdR/GjqOC6oybtv8TyWf2TLH
+llpwrN9M
+-----END CERTIFICATE-----
+
+Staat der Nederlanden Root CA
+=============================
+-----BEGIN CERTIFICATE-----
+MIIDujCCAqKgAwIBAgIEAJiWijANBgkqhkiG9w0BAQUFADBVMQswCQYDVQQGEwJOTDEeMBwGA1UE
+ChMVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSYwJAYDVQQDEx1TdGFhdCBkZXIgTmVkZXJsYW5kZW4g
+Um9vdCBDQTAeFw0wMjEyMTcwOTIzNDlaFw0xNTEyMTYwOTE1MzhaMFUxCzAJBgNVBAYTAk5MMR4w
+HAYDVQQKExVTdGFhdCBkZXIgTmVkZXJsYW5kZW4xJjAkBgNVBAMTHVN0YWF0IGRlciBOZWRlcmxh
+bmRlbiBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAmNK1URF6gaYUmHFt
+vsznExvWJw56s2oYHLZhWtVhCb/ekBPHZ+7d89rFDBKeNVU+LCeIQGv33N0iYfXCxw719tV2U02P
+jLwYdjeFnejKScfST5gTCaI+Ioicf9byEGW07l8Y1Rfj+MX94p2i71MOhXeiD+EwR+4A5zN9RGca
+C1Hoi6CeUJhoNFIfLm0B8mBF8jHrqTFoKbt6QZ7GGX+UtFE5A3+y3qcym7RHjm+0Sq7lr7HcsBth
+vJly3uSJt3omXdozSVtSnA71iq3DuD3oBmrC1SoLbHuEvVYFy4ZlkuxEK7COudxwC0barbxjiDn6
+22r+I/q85Ej0ZytqERAhSQIDAQABo4GRMIGOMAwGA1UdEwQFMAMBAf8wTwYDVR0gBEgwRjBEBgRV
+HSAAMDwwOgYIKwYBBQUHAgEWLmh0dHA6Ly93d3cucGtpb3ZlcmhlaWQubmwvcG9saWNpZXMvcm9v
+dC1wb2xpY3kwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBSofeu8Y6R0E3QA7Jbg0zTBLL9s+DAN
+BgkqhkiG9w0BAQUFAAOCAQEABYSHVXQ2YcG70dTGFagTtJ+k/rvuFbQvBgwp8qiSpGEN/KtcCFtR
+EytNwiphyPgJWPwtArI5fZlmgb9uXJVFIGzmeafR2Bwp/MIgJ1HI8XxdNGdphREwxgDS1/PTfLbw
+MVcoEoJz6TMvplW0C5GUR5z6u3pCMuiufi3IvKwUv9kP2Vv8wfl6leF9fpb8cbDCTMjfRTTJzg3y
+nGQI0DvDKcWy7ZAEwbEpkcUwb8GpcjPM/l0WFywRaed+/sWDCN+83CI6LiBpIzlWYGeQiy52OfsR
+iJf2fL1LuCAWZwWN4jvBcj+UlTfHXbme2JOhF4//DGYVwSR8MnwDHTuhWEUykw==
+-----END CERTIFICATE-----
+
+TDC Internet Root CA
+====================
+-----BEGIN CERTIFICATE-----
+MIIEKzCCAxOgAwIBAgIEOsylTDANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJESzEVMBMGA1UE
+ChMMVERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTAeFw0wMTA0MDUx
+NjMzMTdaFw0yMTA0MDUxNzAzMTdaMEMxCzAJBgNVBAYTAkRLMRUwEwYDVQQKEwxUREMgSW50ZXJu
+ZXQxHTAbBgNVBAsTFFREQyBJbnRlcm5ldCBSb290IENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAxLhAvJHVYx/XmaCLDEAedLdInUaMArLgJF/wGROnN4NrXceO+YQwzho7+vvOi20j
+xsNuZp+Jpd/gQlBn+h9sHvTQBda/ytZO5GhgbEaqHF1j4QeGDmUApy6mcca8uYGoOn0a0vnRrEvL
+znWv3Hv6gXPU/Lq9QYjUdLP5Xjg6PEOo0pVOd20TDJ2PeAG3WiAfAzc14izbSysseLlJ28TQx5yc
+5IogCSEWVmb/Bexb4/DPqyQkXsN/cHoSxNK1EKC2IeGNeGlVRGn1ypYcNIUXJXfi9i8nmHj9eQY6
+otZaQ8H/7AQ77hPv01ha/5Lr7K7a8jcDR0G2l8ktCkEiu7vmpwIDAQABo4IBJTCCASEwEQYJYIZI
+AYb4QgEBBAQDAgAHMGUGA1UdHwReMFwwWqBYoFakVDBSMQswCQYDVQQGEwJESzEVMBMGA1UEChMM
+VERDIEludGVybmV0MR0wGwYDVQQLExRUREMgSW50ZXJuZXQgUm9vdCBDQTENMAsGA1UEAxMEQ1JM
+MTArBgNVHRAEJDAigA8yMDAxMDQwNTE2MzMxN1qBDzIwMjEwNDA1MTcwMzE3WjALBgNVHQ8EBAMC
+AQYwHwYDVR0jBBgwFoAUbGQBx/2FbazI2p5QCIUItTxWqFAwHQYDVR0OBBYEFGxkAcf9hW2syNqe
+UAiFCLU8VqhQMAwGA1UdEwQFMAMBAf8wHQYJKoZIhvZ9B0EABBAwDhsIVjUuMDo0LjADAgSQMA0G
+CSqGSIb3DQEBBQUAA4IBAQBOQ8zR3R0QGwZ/t6T609lN+yOfI1Rb5osvBCiLtSdtiaHsmGnc540m
+gwV5dOy0uaOXwTUA/RXaOYE6lTGQ3pfphqiZdwzlWqCE/xIWrG64jcN7ksKsLtB9KOy282A4aW8+
+2ARVPp7MVdK6/rtHBNcK2RYKNCn1WBPVT8+PVkuzHu7TmHnaCB4Mb7j4Fifvwm899qNLPg7kbWzb
+O0ESm70NRyN/PErQr8Cv9u8btRXE64PECV90i9kR+8JWsTz4cMo0jUNAE4z9mQNUecYu6oah9jrU
+Cbz0vGbMPVjQV0kK7iXiQe4T+Zs4NNEA9X7nlB38aQNiuJkFBT1reBK9sG9l
+-----END CERTIFICATE-----
+
+TDC OCES Root CA
+================
+-----BEGIN CERTIFICATE-----
+MIIFGTCCBAGgAwIBAgIEPki9xDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJESzEMMAoGA1UE
+ChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTAeFw0wMzAyMTEwODM5MzBaFw0zNzAyMTEwOTA5
+MzBaMDExCzAJBgNVBAYTAkRLMQwwCgYDVQQKEwNUREMxFDASBgNVBAMTC1REQyBPQ0VTIENBMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArGL2YSCyz8DGhdfjeebM7fI5kqSXLmSjhFuH
+nEz9pPPEXyG9VhDr2y5h7JNp46PMvZnDBfwGuMo2HP6QjklMxFaaL1a8z3sM8W9Hpg1DTeLpHTk0
+zY0s2RKY+ePhwUp8hjjEqcRhiNJerxomTdXkoCJHhNlktxmW/OwZ5LKXJk5KTMuPJItUGBxIYXvV
+iGjaXbXqzRowwYCDdlCqT9HU3Tjw7xb04QxQBr/q+3pJoSgrHPb8FTKjdGqPqcNiKXEx5TukYBde
+dObaE+3pHx8b0bJoc8YQNHVGEBDjkAB2QMuLt0MJIf+rTpPGWOmlgtt3xDqZsXKVSQTwtyv6e1mO
+3QIDAQABo4ICNzCCAjMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwgewGA1UdIASB
+5DCB4TCB3gYIKoFQgSkBAQEwgdEwLwYIKwYBBQUHAgEWI2h0dHA6Ly93d3cuY2VydGlmaWthdC5k
+ay9yZXBvc2l0b3J5MIGdBggrBgEFBQcCAjCBkDAKFgNUREMwAwIBARqBgUNlcnRpZmlrYXRlciBm
+cmEgZGVubmUgQ0EgdWRzdGVkZXMgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEuMS4xLiBDZXJ0aWZp
+Y2F0ZXMgZnJvbSB0aGlzIENBIGFyZSBpc3N1ZWQgdW5kZXIgT0lEIDEuMi4yMDguMTY5LjEuMS4x
+LjARBglghkgBhvhCAQEEBAMCAAcwgYEGA1UdHwR6MHgwSKBGoESkQjBAMQswCQYDVQQGEwJESzEM
+MAoGA1UEChMDVERDMRQwEgYDVQQDEwtUREMgT0NFUyBDQTENMAsGA1UEAxMEQ1JMMTAsoCqgKIYm
+aHR0cDovL2NybC5vY2VzLmNlcnRpZmlrYXQuZGsvb2Nlcy5jcmwwKwYDVR0QBCQwIoAPMjAwMzAy
+MTEwODM5MzBagQ8yMDM3MDIxMTA5MDkzMFowHwYDVR0jBBgwFoAUYLWF7FZkfhIZJ2cdUBVLc647
++RIwHQYDVR0OBBYEFGC1hexWZH4SGSdnHVAVS3OuO/kSMB0GCSqGSIb2fQdBAAQQMA4bCFY2LjA6
+NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEACromJkbTc6gJ82sLMJn9iuFXehHTuJTXCRBuo7E4
+A9G28kNBKWKnctj7fAXmMXAnVBhOinxO5dHKjHiIzxvTkIvmI/gLDjNDfZziChmPyQE+dF10yYsc
+A+UYyAFMP8uXBV2YcaaYb7Z8vTd/vuGTJW1v8AqtFxjhA7wHKcitJuj4YfD9IQl+mo6paH1IYnK9
+AOoBmbgGglGBTvH1tJFUuSN6AJqfXY3gPGS5GhKSKseCRHI53OI8xthV9RVOyAUO28bQYqbsFbS1
+AoLbrIyigfCbmTH1ICCoiGEKB5+U/NDXG8wuF/MEJ3Zn61SD/aSQfgY9BKNDLdr8C2LqL19iUw==
+-----END CERTIFICATE-----
+
+UTN DATACorp SGC Root CA
+========================
+-----BEGIN CERTIFICATE-----
+MIIEXjCCA0agAwIBAgIQRL4Mi1AAIbQR0ypoBqmtaTANBgkqhkiG9w0BAQUFADCBkzELMAkGA1UE
+BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
+IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xGzAZ
+BgNVBAMTElVUTiAtIERBVEFDb3JwIFNHQzAeFw05OTA2MjQxODU3MjFaFw0xOTA2MjQxOTA2MzBa
+MIGTMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQxFzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4w
+HAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsxITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRy
+dXN0LmNvbTEbMBkGA1UEAxMSVVROIC0gREFUQUNvcnAgU0dDMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA3+5YEKIrblXEjr8uRgnn4AgPLit6E5Qbvfa2gI5lBZMAHryv4g+OGQ0SR+ys
+raP6LnD43m77VkIVni5c7yPeIbkFdicZD0/Ww5y0vpQZY/KmEQrrU0icvvIpOxboGqBMpsn0GFlo
+wHDyUwDAXlCCpVZvNvlK4ESGoE1O1kduSUrLZ9emxAW5jh70/P/N5zbgnAVssjMiFdC04MwXwLLA
+9P4yPykqlXvY8qdOD1R8oQ2AswkDwf9c3V6aPryuvEeKaq5xyh+xKrhfQgUL7EYw0XILyulWbfXv
+33i+Ybqypa4ETLyorGkVl73v67SMvzX41MPRKA5cOp9wGDMgd8SirwIDAQABo4GrMIGoMAsGA1Ud
+DwQEAwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRTMtGzz3/64PGgXYVOktKeRR20TzA9
+BgNVHR8ENjA0MDKgMKAuhixodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLURBVEFDb3JwU0dD
+LmNybDAqBgNVHSUEIzAhBggrBgEFBQcDAQYKKwYBBAGCNwoDAwYJYIZIAYb4QgQBMA0GCSqGSIb3
+DQEBBQUAA4IBAQAnNZcAiosovcYzMB4p/OL31ZjUQLtgyr+rFywJNn9Q+kHcrpY6CiM+iVnJowft
+Gzet/Hy+UUla3joKVAgWRcKZsYfNjGjgaQPpxE6YsjuMFrMOoAyYUJuTqXAJyCyjj98C5OBxOvG0
+I3KgqgHf35g+FFCgMSa9KOlaMCZ1+XtgHI3zzVAmbQQnmt/VDUVHKWss5nbZqSl9Mt3JNjy9rjXx
+EZ4du5A/EkdOjtd+D2JzHVImOBwYSf0wdJrE5SIv2MCN7ZF6TACPcn9d2t0bi0Vr591pl6jFVkwP
+DPafepE39peC4N1xaf92P2BNPM/3mfnGV/TJVTl4uix5yaaIK/QI
+-----END CERTIFICATE-----
+
+UTN USERFirst Email Root CA
+===========================
+-----BEGIN CERTIFICATE-----
+MIIEojCCA4qgAwIBAgIQRL4Mi1AAJLQR0zYlJWfJiTANBgkqhkiG9w0BAQUFADCBrjELMAkGA1UE
+BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
+IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xNjA0
+BgNVBAMTLVVUTi1VU0VSRmlyc3QtQ2xpZW50IEF1dGhlbnRpY2F0aW9uIGFuZCBFbWFpbDAeFw05
+OTA3MDkxNzI4NTBaFw0xOTA3MDkxNzM2NThaMIGuMQswCQYDVQQGEwJVUzELMAkGA1UECBMCVVQx
+FzAVBgNVBAcTDlNhbHQgTGFrZSBDaXR5MR4wHAYDVQQKExVUaGUgVVNFUlRSVVNUIE5ldHdvcmsx
+ITAfBgNVBAsTGGh0dHA6Ly93d3cudXNlcnRydXN0LmNvbTE2MDQGA1UEAxMtVVROLVVTRVJGaXJz
+dC1DbGllbnQgQXV0aGVudGljYXRpb24gYW5kIEVtYWlsMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAsjmFpPJ9q0E7YkY3rs3BYHW8OWX5ShpHornMSMxqmNVNNRm5pELlzkniii8efNIx
+B8dOtINknS4p1aJkxIW9hVE1eaROaJB7HHqkkqgX8pgV8pPMyaQylbsMTzC9mKALi+VuG6JG+ni8
+om+rWV6lL8/K2m2qL+usobNqqrcuZzWLeeEeaYji5kbNoKXqvgvOdjp6Dpvq/NonWz1zHyLmSGHG
+TPNpsaguG7bUMSAsvIKKjqQOpdeJQ/wWWq8dcdcRWdq6hw2v+vPhwvCkxWeM1tZUOt4KpLoDd7Nl
+yP0e03RiqhjKaJMeoYV+9Udly/hNVyh00jT/MLbu9mIwFIws6wIDAQABo4G5MIG2MAsGA1UdDwQE
+AwIBxjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBSJgmd9xJ0mcABLtFBIfN49rgRufTBYBgNV
+HR8EUTBPME2gS6BJhkdodHRwOi8vY3JsLnVzZXJ0cnVzdC5jb20vVVROLVVTRVJGaXJzdC1DbGll
+bnRBdXRoZW50aWNhdGlvbmFuZEVtYWlsLmNybDAdBgNVHSUEFjAUBggrBgEFBQcDAgYIKwYBBQUH
+AwQwDQYJKoZIhvcNAQEFBQADggEBALFtYV2mGn98q0rkMPxTbyUkxsrt4jFcKw7u7mFVbwQ+zzne
+xRtJlOTrIEy05p5QLnLZjfWqo7NK2lYcYJeA3IKirUq9iiv/Cwm0xtcgBEXkzYABurorbs6q15L+
+5K/r9CYdFip/bDCVNy8zEqx/3cfREYxRmLLQo5HQrfafnoOTHh1CuEava2bwm3/q4wMC5QJRwarV
+NZ1yQAOJujEdxRBoUp7fooXFXAimeOZTT7Hot9MUnpOmw2TjrH5xzbyf6QMbzPvprDHBr3wVdAKZ
+w7JHpsIyYdfHb0gkUSeh1YdV8nuPmD0Wnu51tvjQjvLzxq4oW6fw8zYX/MMF08oDSlQ=
+-----END CERTIFICATE-----
+
+UTN USERFirst Hardware Root CA
+==============================
+-----BEGIN CERTIFICATE-----
+MIIEdDCCA1ygAwIBAgIQRL4Mi1AAJLQR0zYq/mUK/TANBgkqhkiG9w0BAQUFADCBlzELMAkGA1UE
+BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
+IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHzAd
+BgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwHhcNOTkwNzA5MTgxMDQyWhcNMTkwNzA5MTgx
+OTIyWjCBlzELMAkGA1UEBhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0
+eTEeMBwGA1UEChMVVGhlIFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVz
+ZXJ0cnVzdC5jb20xHzAdBgNVBAMTFlVUTi1VU0VSRmlyc3QtSGFyZHdhcmUwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCx98M4P7Sof885glFn0G2f0v9Y8+efK+wNiVSZuTiZFvfgIXlI
+wrthdBKWHTxqctU8EGc6Oe0rE81m65UJM6Rsl7HoxuzBdXmcRl6Nq9Bq/bkqVRcQVLMZ8Jr28bFd
+tqdt++BxF2uiiPsA3/4aMXcMmgF6sTLjKwEHOG7DpV4jvEWbe1DByTCP2+UretNb+zNAHqDVmBe8
+i4fDidNdoI6yqqr2jmmIBsX6iSHzCJ1pLgkzmykNRg+MzEk0sGlRvfkGzWitZky8PqxhvQqIDsjf
+Pe58BEydCl5rkdbux+0ojatNh4lz0G6k0B4WixThdkQDf2Os5M1JnMWS9KsyoUhbAgMBAAGjgbkw
+gbYwCwYDVR0PBAQDAgHGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFKFyXyYbKJhDlV0HN9WF
+lp1L0sNFMEQGA1UdHwQ9MDswOaA3oDWGM2h0dHA6Ly9jcmwudXNlcnRydXN0LmNvbS9VVE4tVVNF
+UkZpcnN0LUhhcmR3YXJlLmNybDAxBgNVHSUEKjAoBggrBgEFBQcDAQYIKwYBBQUHAwUGCCsGAQUF
+BwMGBggrBgEFBQcDBzANBgkqhkiG9w0BAQUFAAOCAQEARxkP3nTGmZev/K0oXnWO6y1n7k57K9cM
+//bey1WiCuFMVGWTYGufEpytXoMs61quwOQt9ABjHbjAbPLPSbtNk28GpgoiskliCE7/yMgUsogW
+XecB5BKV5UU0s4tpvc+0hY91UZ59Ojg6FEgSxvunOxqNDYJAB+gECJChicsZUN/KHAG8HQQZexB2
+lzvukJDKxA4fFm517zP4029bHpbj4HR3dHuKom4t3XbWOTCC8KucUvIqx69JXn7HaOWCgchqJ/kn
+iCrVWFCVH/A7HFe7fRQ5YiuayZSSKqMiDP+JJn1fIytH1xUdqWqeUQ0qUZ6B+dQ7XnASfxAynB67
+nfhmqA==
+-----END CERTIFICATE-----
+
+UTN USERFirst Object Root CA
+============================
+-----BEGIN CERTIFICATE-----
+MIIEZjCCA06gAwIBAgIQRL4Mi1AAJLQR0zYt4LNfGzANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UE
+BhMCVVMxCzAJBgNVBAgTAlVUMRcwFQYDVQQHEw5TYWx0IExha2UgQ2l0eTEeMBwGA1UEChMVVGhl
+IFVTRVJUUlVTVCBOZXR3b3JrMSEwHwYDVQQLExhodHRwOi8vd3d3LnVzZXJ0cnVzdC5jb20xHTAb
+BgNVBAMTFFVUTi1VU0VSRmlyc3QtT2JqZWN0MB4XDTk5MDcwOTE4MzEyMFoXDTE5MDcwOTE4NDAz
+NlowgZUxCzAJBgNVBAYTAlVTMQswCQYDVQQIEwJVVDEXMBUGA1UEBxMOU2FsdCBMYWtlIENpdHkx
+HjAcBgNVBAoTFVRoZSBVU0VSVFJVU1QgTmV0d29yazEhMB8GA1UECxMYaHR0cDovL3d3dy51c2Vy
+dHJ1c3QuY29tMR0wGwYDVQQDExRVVE4tVVNFUkZpcnN0LU9iamVjdDCCASIwDQYJKoZIhvcNAQEB
+BQADggEPADCCAQoCggEBAM6qgT+jo2F4qjEAVZURnicPHxzfOpuCaDDASmEd8S8O+r5596Uj71VR
+loTN2+O5bj4x2AogZ8f02b+U60cEPgLOKqJdhwQJ9jCdGIqXsqoc/EHSoTbL+z2RuufZcDX65OeQ
+w5ujm9M89RKZd7G3CeBo5hy485RjiGpq/gt2yb70IuRnuasaXnfBhQfdDWy/7gbHd2pBnqcP1/vu
+lBe3/IW+pKvEHDHd17bR5PDv3xaPslKT16HUiaEHLr/hARJCHhrh2JU022R5KP+6LhHC5ehbkkj7
+RwvCbNqtMoNB86XlQXD9ZZBt+vpRxPm9lisZBCzTbafc8H9vg2XiaquHhnUCAwEAAaOBrzCBrDAL
+BgNVHQ8EBAMCAcYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQU2u1kdBScFDyr3ZmpvVsoTYs8
+ydgwQgYDVR0fBDswOTA3oDWgM4YxaHR0cDovL2NybC51c2VydHJ1c3QuY29tL1VUTi1VU0VSRmly
+c3QtT2JqZWN0LmNybDApBgNVHSUEIjAgBggrBgEFBQcDAwYIKwYBBQUHAwgGCisGAQQBgjcKAwQw
+DQYJKoZIhvcNAQEFBQADggEBAAgfUrE3RHjb/c652pWWmKpVZIC1WkDdIaXFwfNfLEzIR1pp6ujw
+NTX00CXzyKakh0q9G7FzCL3Uw8q2NbtZhncxzaeAFK4T7/yxSPlrJSUtUbYsbUXBmMiKVl0+7kNO
+PmsnjtA6S4ULX9Ptaqd1y9Fahy85dRNacrACgZ++8A+EVCBibGnU4U3GDZlDAQ0Slox4nb9QorFE
+qmrPF3rPbw/U+CRVX/A0FklmPlBGyWNxODFiuGK581OtbLUrohKqGU8J2l7nk8aOFAj+8DCAGKCG
+hU3IfdeLA/5u1fedFqySLKAj5ZyRUh+U3xeUc8OzwcFxBSAAeL0TUh2oPs0AH8g=
+-----END CERTIFICATE-----
+
+Camerfirma Chambers of Commerce Root
+====================================
+-----BEGIN CERTIFICATE-----
+MIIEvTCCA6WgAwIBAgIBADANBgkqhkiG9w0BAQUFADB/MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
+QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
+ZXJzaWduLm9yZzEiMCAGA1UEAxMZQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdDAeFw0wMzA5MzAx
+NjEzNDNaFw0zNzA5MzAxNjEzNDRaMH8xCzAJBgNVBAYTAkVVMScwJQYDVQQKEx5BQyBDYW1lcmZp
+cm1hIFNBIENJRiBBODI3NDMyODcxIzAhBgNVBAsTGmh0dHA6Ly93d3cuY2hhbWJlcnNpZ24ub3Jn
+MSIwIAYDVQQDExlDaGFtYmVycyBvZiBDb21tZXJjZSBSb290MIIBIDANBgkqhkiG9w0BAQEFAAOC
+AQ0AMIIBCAKCAQEAtzZV5aVdGDDg2olUkfzIx1L4L1DZ77F1c2VHfRtbunXF/KGIJPov7coISjlU
+xFF6tdpg6jg8gbLL8bvZkSM/SAFwdakFKq0fcfPJVD0dBmpAPrMMhe5cG3nCYsS4No41XQEMIwRH
+NaqbYE6gZj3LJgqcQKH0XZi/caulAGgq7YN6D6IUtdQis4CwPAxaUWktWBiP7Zme8a7ileb2R6jW
+DA+wWFjbw2Y3npuRVDM30pQcakjJyfKl2qUMI/cjDpwyVV5xnIQFUZot/eZOKjRa3spAN2cMVCFV
+d9oKDMyXroDclDZK9D7ONhMeU+SsTjoF7Nuucpw4i9A5O4kKPnf+dQIBA6OCAUQwggFAMBIGA1Ud
+EwEB/wQIMAYBAf8CAQwwPAYDVR0fBDUwMzAxoC+gLYYraHR0cDovL2NybC5jaGFtYmVyc2lnbi5v
+cmcvY2hhbWJlcnNyb290LmNybDAdBgNVHQ4EFgQU45T1sU3p26EpW1eLTXYGduHRooowDgYDVR0P
+AQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzAnBgNVHREEIDAegRxjaGFtYmVyc3Jvb3RAY2hh
+bWJlcnNpZ24ub3JnMCcGA1UdEgQgMB6BHGNoYW1iZXJzcm9vdEBjaGFtYmVyc2lnbi5vcmcwWAYD
+VR0gBFEwTzBNBgsrBgEEAYGHLgoDATA+MDwGCCsGAQUFBwIBFjBodHRwOi8vY3BzLmNoYW1iZXJz
+aWduLm9yZy9jcHMvY2hhbWJlcnNyb290Lmh0bWwwDQYJKoZIhvcNAQEFBQADggEBAAxBl8IahsAi
+fJ/7kPMa0QOx7xP5IV8EnNrJpY0nbJaHkb5BkAFyk+cefV/2icZdp0AJPaxJRUXcLo0waLIJuvvD
+L8y6C98/d3tGfToSJI6WjzwFCm/SlCgdbQzALogi1djPHRPH8EjX1wWnz8dHnjs8NMiAT9QUu/wN
+UPf6s+xCX6ndbcj0dc97wXImsQEcXCz9ek60AcUFV7nnPKoF2YjpB0ZBzu9Bga5Y34OirsrXdx/n
+ADydb47kMgkdTXg0eDQ8lJsm7U9xxhl6vSAiSFr+S30Dt+dYvsYyTnQeaN2oaFuzPu5ifdmA6Ap1
+erfutGWaIZDgqtCYvDi1czyL+Nw=
+-----END CERTIFICATE-----
+
+Camerfirma Global Chambersign Root
+==================================
+-----BEGIN CERTIFICATE-----
+MIIExTCCA62gAwIBAgIBADANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMe
+QUMgQ2FtZXJmaXJtYSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1i
+ZXJzaWduLm9yZzEgMB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwHhcNMDMwOTMwMTYx
+NDE4WhcNMzcwOTMwMTYxNDE4WjB9MQswCQYDVQQGEwJFVTEnMCUGA1UEChMeQUMgQ2FtZXJmaXJt
+YSBTQSBDSUYgQTgyNzQzMjg3MSMwIQYDVQQLExpodHRwOi8vd3d3LmNoYW1iZXJzaWduLm9yZzEg
+MB4GA1UEAxMXR2xvYmFsIENoYW1iZXJzaWduIFJvb3QwggEgMA0GCSqGSIb3DQEBAQUAA4IBDQAw
+ggEIAoIBAQCicKLQn0KuWxfH2H3PFIP8T8mhtxOviteePgQKkotgVvq0Mi+ITaFgCPS3CU6gSS9J
+1tPfnZdan5QEcOw/Wdm3zGaLmFIoCQLfxS+EjXqXd7/sQJ0lcqu1PzKY+7e3/HKE5TWH+VX6ox8O
+by4o3Wmg2UIQxvi1RMLQQ3/bvOSiPGpVeAp3qdjqGTK3L/5cPxvusZjsyq16aUXjlg9V9ubtdepl
+6DJWk0aJqCWKZQbua795B9Dxt6/tLE2Su8CoX6dnfQTyFQhwrJLWfQTSM/tMtgsL+xrJxI0DqX5c
+8lCrEqWhz0hQpe/SyBoT+rB/sYIcd2oPX9wLlY/vQ37mRQklAgEDo4IBUDCCAUwwEgYDVR0TAQH/
+BAgwBgEB/wIBDDA/BgNVHR8EODA2MDSgMqAwhi5odHRwOi8vY3JsLmNoYW1iZXJzaWduLm9yZy9j
+aGFtYmVyc2lnbnJvb3QuY3JsMB0GA1UdDgQWBBRDnDafsJ4wTcbOX60Qq+UDpfqpFDAOBgNVHQ8B
+Af8EBAMCAQYwEQYJYIZIAYb4QgEBBAQDAgAHMCoGA1UdEQQjMCGBH2NoYW1iZXJzaWducm9vdEBj
+aGFtYmVyc2lnbi5vcmcwKgYDVR0SBCMwIYEfY2hhbWJlcnNpZ25yb290QGNoYW1iZXJzaWduLm9y
+ZzBbBgNVHSAEVDBSMFAGCysGAQQBgYcuCgEBMEEwPwYIKwYBBQUHAgEWM2h0dHA6Ly9jcHMuY2hh
+bWJlcnNpZ24ub3JnL2Nwcy9jaGFtYmVyc2lnbnJvb3QuaHRtbDANBgkqhkiG9w0BAQUFAAOCAQEA
+PDtwkfkEVCeR4e3t/mh/YV3lQWVPMvEYBZRqHN4fcNs+ezICNLUMbKGKfKX0j//U2K0X1S0E0T9Y
+gOKBWYi+wONGkyT+kL0mojAt6JcmVzWJdJYY9hXiryQZVgICsroPFOrGimbBhkVVi76SvpykBMdJ
+PJ7oKXqJ1/6v/2j1pReQvayZzKWGVwlnRtvWFsJG8eSpUPWP0ZIV018+xgBJOm5YstHRJw0lyDL4
+IBHNfTIzSJRUTN3cecQwn+uOuFW114hcxWokPbLTBQNRxgfvzBRydD1ucs4YKIxKoHflCStFREes
+t2d/AYoFWpO+ocH/+OcOZ6RHSXZddZAa9SaP8A==
+-----END CERTIFICATE-----
+
+NetLock Qualified (Class QA) Root
+=================================
+-----BEGIN CERTIFICATE-----
+MIIG0TCCBbmgAwIBAgIBezANBgkqhkiG9w0BAQUFADCByTELMAkGA1UEBhMCSFUxETAPBgNVBAcT
+CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV
+BAsTEVRhbnVzaXR2YW55a2lhZG9rMUIwQAYDVQQDEzlOZXRMb2NrIE1pbm9zaXRldHQgS296amVn
+eXpvaSAoQ2xhc3MgUUEpIFRhbnVzaXR2YW55a2lhZG8xHjAcBgkqhkiG9w0BCQEWD2luZm9AbmV0
+bG9jay5odTAeFw0wMzAzMzAwMTQ3MTFaFw0yMjEyMTUwMTQ3MTFaMIHJMQswCQYDVQQGEwJIVTER
+MA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRvbnNhZ2kgS2Z0
+LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxQjBABgNVBAMTOU5ldExvY2sgTWlub3NpdGV0
+dCBLb3pqZWd5em9pIChDbGFzcyBRQSkgVGFudXNpdHZhbnlraWFkbzEeMBwGCSqGSIb3DQEJARYP
+aW5mb0BuZXRsb2NrLmh1MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx1Ilstg91IRV
+CacbvWy5FPSKAtt2/GoqeKvld/Bu4IwjZ9ulZJm53QE+b+8tmjwi8F3JV6BVQX/yQ15YglMxZc4e
+8ia6AFQer7C8HORSjKAyr7c3sVNnaHRnUPYtLmTeriZ539+Zhqurf4XsoPuAzPS4DB6TRWO53Lhb
+m+1bOdRfYrCnjnxmOCyqsQhjF2d9zL2z8cM/z1A57dEZgxXbhxInlrfa6uWdvLrqOU+L73Sa58XQ
+0uqGURzk/mQIKAR5BevKxXEOC++r6uwSEaEYBTJp0QwsGj0lmT+1fMptsK6ZmfoIYOcZwvK9UdPM
+0wKswREMgM6r3JSda6M5UzrWhQIDAMV9o4ICwDCCArwwEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV
+HQ8BAf8EBAMCAQYwggJ1BglghkgBhvhCAQ0EggJmFoICYkZJR1lFTEVNISBFemVuIHRhbnVzaXR2
+YW55IGEgTmV0TG9jayBLZnQuIE1pbm9zaXRldHQgU3pvbGdhbHRhdGFzaSBTemFiYWx5emF0YWJh
+biBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBBIG1pbm9zaXRldHQgZWxla3Ryb25p
+a3VzIGFsYWlyYXMgam9naGF0YXMgZXJ2ZW55ZXN1bGVzZW5laywgdmFsYW1pbnQgZWxmb2dhZGFz
+YW5hayBmZWx0ZXRlbGUgYSBNaW5vc2l0ZXR0IFN6b2xnYWx0YXRhc2kgU3phYmFseXphdGJhbiwg
+YXogQWx0YWxhbm9zIFN6ZXJ6b2Rlc2kgRmVsdGV0ZWxla2JlbiBlbG9pcnQgZWxsZW5vcnplc2kg
+ZWxqYXJhcyBtZWd0ZXRlbGUuIEEgZG9rdW1lbnR1bW9rIG1lZ3RhbGFsaGF0b2sgYSBodHRwczov
+L3d3dy5uZXRsb2NrLmh1L2RvY3MvIGNpbWVuIHZhZ3kga2VyaGV0b2sgYXogaW5mb0BuZXRsb2Nr
+Lm5ldCBlLW1haWwgY2ltZW4uIFdBUk5JTkchIFRoZSBpc3N1YW5jZSBhbmQgdGhlIHVzZSBvZiB0
+aGlzIGNlcnRpZmljYXRlIGFyZSBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIFF1YWxpZmllZCBDUFMg
+YXZhaWxhYmxlIGF0IGh0dHBzOi8vd3d3Lm5ldGxvY2suaHUvZG9jcy8gb3IgYnkgZS1tYWlsIGF0
+IGluZm9AbmV0bG9jay5uZXQwHQYDVR0OBBYEFAlqYhaSsFq7VQ7LdTI6MuWyIckoMA0GCSqGSIb3
+DQEBBQUAA4IBAQCRalCc23iBmz+LQuM7/KbD7kPgz/PigDVJRXYC4uMvBcXxKufAQTPGtpvQMznN
+wNuhrWw3AkxYQTvyl5LGSKjN5Yo5iWH5Upfpvfb5lHTocQ68d4bDBsxafEp+NFAwLvt/MpqNPfMg
+W/hqyobzMUwsWYACff44yTB1HLdV47yfuqhthCgFdbOLDcCRVCHnpgu0mfVRQdzNo0ci2ccBgcTc
+R08m6h/t280NmPSjnLRzMkqWmf68f8glWPhY83ZmiVSkpj7EUFy6iRiCdUgh0k8T6GB+B3bbELVR
+5qq5aKrN9p2QdRLqOBrKROi3macqaJVmlaut74nLYKkGEsaUR+ko
+-----END CERTIFICATE-----
+
+NetLock Notary (Class A) Root
+=============================
+-----BEGIN CERTIFICATE-----
+MIIGfTCCBWWgAwIBAgICAQMwDQYJKoZIhvcNAQEEBQAwga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQI
+EwdIdW5nYXJ5MREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6
+dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9j
+ayBLb3pqZWd5em9pIChDbGFzcyBBKSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNDIzMTQ0N1oX
+DTE5MDIxOTIzMTQ0N1owga8xCzAJBgNVBAYTAkhVMRAwDgYDVQQIEwdIdW5nYXJ5MREwDwYDVQQH
+EwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6dG9uc2FnaSBLZnQuMRowGAYD
+VQQLExFUYW51c2l0dmFueWtpYWRvazE2MDQGA1UEAxMtTmV0TG9jayBLb3pqZWd5em9pIChDbGFz
+cyBBKSBUYW51c2l0dmFueWtpYWRvMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvHSM
+D7tM9DceqQWC2ObhbHDqeLVu0ThEDaiDzl3S1tWBxdRL51uUcCbbO51qTGL3cfNk1mE7PetzozfZ
+z+qMkjvN9wfcZnSX9EUi3fRc4L9t875lM+QVOr/bmJBVOMTtplVjC7B4BPTjbsE/jvxReB+SnoPC
+/tmwqcm8WgD/qaiYdPv2LD4VOQ22BFWoDpggQrOxJa1+mm9dU7GrDPzr4PN6s6iz/0b2Y6LYOph7
+tqyF/7AlT3Rj5xMHpQqPBffAZG9+pyeAlt7ULoZgx2srXnN7F+eRP2QM2EsiNCubMvJIH5+hCoR6
+4sKtlz2O1cH5VqNQ6ca0+pii7pXmKgOM3wIDAQABo4ICnzCCApswDgYDVR0PAQH/BAQDAgAGMBIG
+A1UdEwEB/wQIMAYBAf8CAQQwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaC
+Ak1GSUdZRUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pv
+bGdhbHRhdGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQu
+IEEgaGl0ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2Vn
+LWJpenRvc2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0
+ZXRlbGUgYXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFz
+IGxlaXJhc2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBh
+IGh0dHBzOi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVu
+b3J6ZXNAbmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBh
+bmQgdGhlIHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sg
+Q1BTIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFp
+bCBhdCBjcHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4IBAQBIJEb3ulZv+sgoA0BO5TE5
+ayZrU3/b39/zcT0mwBQOxmd7I6gMc90Bu8bKbjc5VdXHjFYgDigKDtIqpLBJUsY4B/6+CgmM0ZjP
+ytoUMaFP0jn8DxEsQ8Pdq5PHVT5HfBgaANzze9jyf1JsIPQLX2lS9O74silg6+NJMSEN1rUQQeJB
+CWziGppWS3cC9qCbmieH6FUpccKQn0V4GuEVZD3QDtigdp+uxdAu6tYPVuxkf1qbFFgBJ34TUMdr
+KuZoPL9coAob4Q566eKAw+np9v1sEZ7Q5SgnK1QyQhSCdeZK8CtmdWOMovsEPoMOmzbwGOQmIMOM
+8CgHrTwXZoi1/baI
+-----END CERTIFICATE-----
+
+NetLock Business (Class B) Root
+===============================
+-----BEGIN CERTIFICATE-----
+MIIFSzCCBLSgAwIBAgIBaTANBgkqhkiG9w0BAQQFADCBmTELMAkGA1UEBhMCSFUxETAPBgNVBAcT
+CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV
+BAsTEVRhbnVzaXR2YW55a2lhZG9rMTIwMAYDVQQDEylOZXRMb2NrIFV6bGV0aSAoQ2xhc3MgQikg
+VGFudXNpdHZhbnlraWFkbzAeFw05OTAyMjUxNDEwMjJaFw0xOTAyMjAxNDEwMjJaMIGZMQswCQYD
+VQQGEwJIVTERMA8GA1UEBxMIQnVkYXBlc3QxJzAlBgNVBAoTHk5ldExvY2sgSGFsb3phdGJpenRv
+bnNhZ2kgS2Z0LjEaMBgGA1UECxMRVGFudXNpdHZhbnlraWFkb2sxMjAwBgNVBAMTKU5ldExvY2sg
+VXpsZXRpIChDbGFzcyBCKSBUYW51c2l0dmFueWtpYWRvMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCB
+iQKBgQCx6gTsIKAjwo84YM/HRrPVG/77uZmeBNwcf4xKgZjupNTKihe5In+DCnVMm8Bp2GQ5o+2S
+o/1bXHQawEfKOml2mrriRBf8TKPV/riXiK+IA4kfpPIEPsgHC+b5sy96YhQJRhTKZPWLgLViqNhr
+1nGTLbO/CVRY7QbrqHvcQ7GhaQIDAQABo4ICnzCCApswEgYDVR0TAQH/BAgwBgEB/wIBBDAOBgNV
+HQ8BAf8EBAMCAAYwEQYJYIZIAYb4QgEBBAQDAgAHMIICYAYJYIZIAYb4QgENBIICURaCAk1GSUdZ
+RUxFTSEgRXplbiB0YW51c2l0dmFueSBhIE5ldExvY2sgS2Z0LiBBbHRhbGFub3MgU3pvbGdhbHRh
+dGFzaSBGZWx0ZXRlbGVpYmVuIGxlaXJ0IGVsamFyYXNvayBhbGFwamFuIGtlc3p1bHQuIEEgaGl0
+ZWxlc2l0ZXMgZm9seWFtYXRhdCBhIE5ldExvY2sgS2Z0LiB0ZXJtZWtmZWxlbG9zc2VnLWJpenRv
+c2l0YXNhIHZlZGkuIEEgZGlnaXRhbGlzIGFsYWlyYXMgZWxmb2dhZGFzYW5hayBmZWx0ZXRlbGUg
+YXogZWxvaXJ0IGVsbGVub3J6ZXNpIGVsamFyYXMgbWVndGV0ZWxlLiBBeiBlbGphcmFzIGxlaXJh
+c2EgbWVndGFsYWxoYXRvIGEgTmV0TG9jayBLZnQuIEludGVybmV0IGhvbmxhcGphbiBhIGh0dHBz
+Oi8vd3d3Lm5ldGxvY2submV0L2RvY3MgY2ltZW4gdmFneSBrZXJoZXRvIGF6IGVsbGVub3J6ZXNA
+bmV0bG9jay5uZXQgZS1tYWlsIGNpbWVuLiBJTVBPUlRBTlQhIFRoZSBpc3N1YW5jZSBhbmQgdGhl
+IHVzZSBvZiB0aGlzIGNlcnRpZmljYXRlIGlzIHN1YmplY3QgdG8gdGhlIE5ldExvY2sgQ1BTIGF2
+YWlsYWJsZSBhdCBodHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIG9yIGJ5IGUtbWFpbCBhdCBj
+cHNAbmV0bG9jay5uZXQuMA0GCSqGSIb3DQEBBAUAA4GBAATbrowXr/gOkDFOzT4JwG06sPgzTEdM
+43WIEJessDgVkcYplswhwG08pXTP2IKlOcNl40JwuyKQ433bNXbhoLXan3BukxowOR0w2y7jfLKR
+stE3Kfq51hdcR0/jHTjrn9V7lagonhVK0dHQKwCXoOKSNitjrFgBazMpUIaD8QFI
+-----END CERTIFICATE-----
+
+NetLock Express (Class C) Root
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFTzCCBLigAwIBAgIBaDANBgkqhkiG9w0BAQQFADCBmzELMAkGA1UEBhMCSFUxETAPBgNVBAcT
+CEJ1ZGFwZXN0MScwJQYDVQQKEx5OZXRMb2NrIEhhbG96YXRiaXp0b25zYWdpIEtmdC4xGjAYBgNV
+BAsTEVRhbnVzaXR2YW55a2lhZG9rMTQwMgYDVQQDEytOZXRMb2NrIEV4cHJlc3N6IChDbGFzcyBD
+KSBUYW51c2l0dmFueWtpYWRvMB4XDTk5MDIyNTE0MDgxMVoXDTE5MDIyMDE0MDgxMVowgZsxCzAJ
+BgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVzdDEnMCUGA1UEChMeTmV0TG9jayBIYWxvemF0Yml6
+dG9uc2FnaSBLZnQuMRowGAYDVQQLExFUYW51c2l0dmFueWtpYWRvazE0MDIGA1UEAxMrTmV0TG9j
+ayBFeHByZXNzeiAoQ2xhc3MgQykgVGFudXNpdHZhbnlraWFkbzCBnzANBgkqhkiG9w0BAQEFAAOB
+jQAwgYkCgYEA6+ywbGGKIyWvYCDj2Z/8kwvbXY2wobNAOoLO/XXgeDIDhlqGlZHtU/qdQPzm6N3Z
+W3oDvV3zOwzDUXmbrVWg6dADEK8KuhRC2VImESLH0iDMgqSaqf64gXadarfSNnU+sYYJ9m5tfk63
+euyucYT2BDMIJTLrdKwWRMbkQJMdf60CAwEAAaOCAp8wggKbMBIGA1UdEwEB/wQIMAYBAf8CAQQw
+DgYDVR0PAQH/BAQDAgAGMBEGCWCGSAGG+EIBAQQEAwIABzCCAmAGCWCGSAGG+EIBDQSCAlEWggJN
+RklHWUVMRU0hIEV6ZW4gdGFudXNpdHZhbnkgYSBOZXRMb2NrIEtmdC4gQWx0YWxhbm9zIFN6b2xn
+YWx0YXRhc2kgRmVsdGV0ZWxlaWJlbiBsZWlydCBlbGphcmFzb2sgYWxhcGphbiBrZXN6dWx0LiBB
+IGhpdGVsZXNpdGVzIGZvbHlhbWF0YXQgYSBOZXRMb2NrIEtmdC4gdGVybWVrZmVsZWxvc3NlZy1i
+aXp0b3NpdGFzYSB2ZWRpLiBBIGRpZ2l0YWxpcyBhbGFpcmFzIGVsZm9nYWRhc2FuYWsgZmVsdGV0
+ZWxlIGF6IGVsb2lydCBlbGxlbm9yemVzaSBlbGphcmFzIG1lZ3RldGVsZS4gQXogZWxqYXJhcyBs
+ZWlyYXNhIG1lZ3RhbGFsaGF0byBhIE5ldExvY2sgS2Z0LiBJbnRlcm5ldCBob25sYXBqYW4gYSBo
+dHRwczovL3d3dy5uZXRsb2NrLm5ldC9kb2NzIGNpbWVuIHZhZ3kga2VyaGV0byBheiBlbGxlbm9y
+emVzQG5ldGxvY2submV0IGUtbWFpbCBjaW1lbi4gSU1QT1JUQU5UISBUaGUgaXNzdWFuY2UgYW5k
+IHRoZSB1c2Ugb2YgdGhpcyBjZXJ0aWZpY2F0ZSBpcyBzdWJqZWN0IHRvIHRoZSBOZXRMb2NrIENQ
+UyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cubmV0bG9jay5uZXQvZG9jcyBvciBieSBlLW1haWwg
+YXQgY3BzQG5ldGxvY2submV0LjANBgkqhkiG9w0BAQQFAAOBgQAQrX/XDDKACtiG8XmYta3UzbM2
+xJZIwVzNmtkFLp++UOv0JhQQLdRmF/iewSf98e3ke0ugbLWrmldwpu2gpO0u9f38vf5NNwgMvOOW
+gyL1SRt/Syu0VMGAfJlOHdCM7tCs5ZL6dVb+ZKATj7i4Fp1hBWeAyNDYpQcCNJgEjTME1A==
+-----END CERTIFICATE-----
+
+XRamp Global CA Root
+====================
+-----BEGIN CERTIFICATE-----
+MIIEMDCCAxigAwIBAgIQUJRs7Bjq1ZxN1ZfvdY+grTANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UE
+BhMCVVMxHjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2Vj
+dXJpdHkgU2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwHhcNMDQxMTAxMTcxNDA0WhcNMzUwMTAxMDUzNzE5WjCBgjELMAkGA1UEBhMCVVMx
+HjAcBgNVBAsTFXd3dy54cmFtcHNlY3VyaXR5LmNvbTEkMCIGA1UEChMbWFJhbXAgU2VjdXJpdHkg
+U2VydmljZXMgSW5jMS0wKwYDVQQDEyRYUmFtcCBHbG9iYWwgQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCYJB69FbS638eMpSe2OAtp87ZOqCwu
+IR1cRN8hXX4jdP5efrRKt6atH67gBhbim1vZZ3RrXYCPKZ2GG9mcDZhtdhAoWORlsH9KmHmf4MMx
+foArtYzAQDsRhtDLooY2YKTVMIJt2W7QDxIEM5dfT2Fa8OT5kavnHTu86M/0ay00fOJIYRyO82FE
+zG+gSqmUsE3a56k0enI4qEHMPJQRfevIpoy3hsvKMzvZPTeL+3o+hiznc9cKV6xkmxnr9A8ECIqs
+AxcZZPRaJSKNNCyy9mgdEm3Tih4U2sSPpuIjhdV6Db1q4Ons7Be7QhtnqiXtRYMh/MHJfNViPvry
+xS3T/dRlAgMBAAGjgZ8wgZwwEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFMZPoj0GY4QJnM5i5ASsjVy16bYbMDYGA1UdHwQvMC0wK6Ap
+oCeGJWh0dHA6Ly9jcmwueHJhbXBzZWN1cml0eS5jb20vWEdDQS5jcmwwEAYJKwYBBAGCNxUBBAMC
+AQEwDQYJKoZIhvcNAQEFBQADggEBAJEVOQMBG2f7Shz5CmBbodpNl2L5JFMn14JkTpAuw0kbK5rc
+/Kh4ZzXxHfARvbdI4xD2Dd8/0sm2qlWkSLoC295ZLhVbO50WfUfXN+pfTXYSNrsf16GBBEYgoyxt
+qZ4Bfj8pzgCT3/3JknOJiWSe5yvkHJEs0rnOfc5vMZnT5r7SHpDwCRR5XCOrTdLaIR9NmXmd4c8n
+nxCbHIgNsIpkQTG4DmyQJKSbXHGPurt+HBvbaoAPIbzp26a3QPSyi6mx5O+aGtA9aZnuqCij4Tyz
+8LIRnM98QObd50N9otg6tamN8jSZxNQQ4Qb9CYQQO+7ETPTsJ3xCwnR8gooJybQDJbw=
+-----END CERTIFICATE-----
+
+Go Daddy Class 2 CA
+===================
+-----BEGIN CERTIFICATE-----
+MIIEADCCAuigAwIBAgIBADANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMY
+VGhlIEdvIERhZGR5IEdyb3VwLCBJbmMuMTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5MB4XDTA0MDYyOTE3MDYyMFoXDTM0MDYyOTE3MDYyMFowYzELMAkG
+A1UEBhMCVVMxITAfBgNVBAoTGFRoZSBHbyBEYWRkeSBHcm91cCwgSW5jLjExMC8GA1UECxMoR28g
+RGFkZHkgQ2xhc3MgMiBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCASAwDQYJKoZIhvcNAQEBBQAD
+ggENADCCAQgCggEBAN6d1+pXGEmhW+vXX0iG6r7d/+TvZxz0ZWizV3GgXne77ZtJ6XCAPVYYYwhv
+2vLM0D9/AlQiVBDYsoHUwHU9S3/Hd8M+eKsaA7Ugay9qK7HFiH7Eux6wwdhFJ2+qN1j3hybX2C32
+qRe3H3I2TqYXP2WYktsqbl2i/ojgC95/5Y0V4evLOtXiEqITLdiOr18SPaAIBQi2XKVlOARFmR6j
+YGB0xUGlcmIbYsUfb18aQr4CUWWoriMYavx4A6lNf4DD+qta/KFApMoZFv6yyO9ecw3ud72a9nmY
+vLEHZ6IVDd2gWMZEewo+YihfukEHU1jPEX44dMX4/7VpkI+EdOqXG68CAQOjgcAwgb0wHQYDVR0O
+BBYEFNLEsNKR1EwRcbNhyz2h/t2oatTjMIGNBgNVHSMEgYUwgYKAFNLEsNKR1EwRcbNhyz2h/t2o
+atTjoWekZTBjMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYVGhlIEdvIERhZGR5IEdyb3VwLCBJbmMu
+MTEwLwYDVQQLEyhHbyBEYWRkeSBDbGFzcyAyIENlcnRpZmljYXRpb24gQXV0aG9yaXR5ggEAMAwG
+A1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADJL87LKPpH8EsahB4yOd6AzBhRckB4Y9wim
+PQoZ+YeAEW5p5JYXMP80kWNyOO7MHAGjHZQopDH2esRU1/blMVgDoszOYtuURXO1v0XJJLXVggKt
+I3lpjbi2Tc7PTMozI+gciKqdi0FuFskg5YmezTvacPd+mSYgFFQlq25zheabIZ0KbIIOqPjCDPoQ
+HmyW74cNxA9hi63ugyuV+I6ShHI56yDqg+2DzZduCLzrTia2cyvk0/ZM/iZx4mERdEr/VxqHD3VI
+Ls9RaRegAhJhldXRQLIQTO7ErBBDpqWeCtWVYpoNz4iCxTIM5CufReYNnyicsbkqWletNw+vHX/b
+vZ8=
+-----END CERTIFICATE-----
+
+Starfield Class 2 CA
+====================
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBADANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJVUzElMCMGA1UEChMc
+U3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAGA1UECxMpU3RhcmZpZWxkIENsYXNzIDIg
+Q2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDQwNjI5MTczOTE2WhcNMzQwNjI5MTczOTE2WjBo
+MQswCQYDVQQGEwJVUzElMCMGA1UEChMcU3RhcmZpZWxkIFRlY2hub2xvZ2llcywgSW5jLjEyMDAG
+A1UECxMpU3RhcmZpZWxkIENsYXNzIDIgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEgMA0GCSqG
+SIb3DQEBAQUAA4IBDQAwggEIAoIBAQC3Msj+6XGmBIWtDBFk385N78gDGIc/oav7PKaf8MOh2tTY
+bitTkPskpD6E8J7oX+zlJ0T1KKY/e97gKvDIr1MvnsoFAZMej2YcOadN+lq2cwQlZut3f+dZxkqZ
+JRRU6ybH838Z1TBwj6+wRir/resp7defqgSHo9T5iaU0X9tDkYI22WY8sbi5gv2cOj4QyDvvBmVm
+epsZGD3/cVE8MC5fvj13c7JdBmzDI1aaK4UmkhynArPkPw2vCHmCuDY96pzTNbO8acr1zJ3o/WSN
+F4Azbl5KXZnJHoe0nRrA1W4TNSNe35tfPe/W93bC6j67eA0cQmdrBNj41tpvi/JEoAGrAgEDo4HF
+MIHCMB0GA1UdDgQWBBS/X7fRzt0fhvRbVazc1xDCDqmI5zCBkgYDVR0jBIGKMIGHgBS/X7fRzt0f
+hvRbVazc1xDCDqmI56FspGowaDELMAkGA1UEBhMCVVMxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNo
+bm9sb2dpZXMsIEluYy4xMjAwBgNVBAsTKVN0YXJmaWVsZCBDbGFzcyAyIENlcnRpZmljYXRpb24g
+QXV0aG9yaXR5ggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAAWdP4id0ckaVaGs
+afPzWdqbAYcaT1epoXkJKtv3L7IezMdeatiDh6GX70k1PncGQVhiv45YuApnP+yz3SFmH8lU+nLM
+PUxA2IGvd56Deruix/U0F47ZEUD0/CwqTRV/p2JdLiXTAAsgGh1o+Re49L2L7ShZ3U0WixeDyLJl
+xy16paq8U4Zt3VekyvggQQto8PT7dL5WXXp59fkdheMtlb71cZBDzI0fmgAKhynpVSJYACPq4xJD
+KVtHCN2MQWplBqjlIapBtJUhlbl90TSrE9atvNziPTnNvT51cKEYWQPJIrSPnNVeKtelttQKbfi3
+QBFGmh95DmK/D5fs4C8fF5Q=
+-----END CERTIFICATE-----
+
+StartCom Certification Authority
+================================
+-----BEGIN CERTIFICATE-----
+MIIHyTCCBbGgAwIBAgIBATANBgkqhkiG9w0BAQUFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
+U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
+ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
+NjM2WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
+LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
+U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
+o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
+Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
+eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
+2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
+6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
+osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
+untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
+UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
+37uMdBNSSwIDAQABo4ICUjCCAk4wDAYDVR0TBAUwAwEB/zALBgNVHQ8EBAMCAa4wHQYDVR0OBBYE
+FE4L7xqkQFulF2mHMMo0aEPQQa7yMGQGA1UdHwRdMFswLKAqoCiGJmh0dHA6Ly9jZXJ0LnN0YXJ0
+Y29tLm9yZy9zZnNjYS1jcmwuY3JsMCugKaAnhiVodHRwOi8vY3JsLnN0YXJ0Y29tLm9yZy9zZnNj
+YS1jcmwuY3JsMIIBXQYDVR0gBIIBVDCCAVAwggFMBgsrBgEEAYG1NwEBATCCATswLwYIKwYBBQUH
+AgEWI2h0dHA6Ly9jZXJ0LnN0YXJ0Y29tLm9yZy9wb2xpY3kucGRmMDUGCCsGAQUFBwIBFilodHRw
+Oi8vY2VydC5zdGFydGNvbS5vcmcvaW50ZXJtZWRpYXRlLnBkZjCB0AYIKwYBBQUHAgIwgcMwJxYg
+U3RhcnQgQ29tbWVyY2lhbCAoU3RhcnRDb20pIEx0ZC4wAwIBARqBl0xpbWl0ZWQgTGlhYmlsaXR5
+LCByZWFkIHRoZSBzZWN0aW9uICpMZWdhbCBMaW1pdGF0aW9ucyogb2YgdGhlIFN0YXJ0Q29tIENl
+cnRpZmljYXRpb24gQXV0aG9yaXR5IFBvbGljeSBhdmFpbGFibGUgYXQgaHR0cDovL2NlcnQuc3Rh
+cnRjb20ub3JnL3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilT
+dGFydENvbSBGcmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQUFAAOC
+AgEAFmyZ9GYMNPXQhV59CuzaEE44HF7fpiUFS5Eyweg78T3dRAlbB0mKKctmArexmvclmAk8jhvh
+3TaHK0u7aNM5Zj2gJsfyOZEdUauCe37Vzlrk4gNXcGmXCPleWKYK34wGmkUWFjgKXlf2Ysd6AgXm
+vB618p70qSmD+LIU424oh0TDkBreOKk8rENNZEXO3SipXPJzewT4F+irsfMuXGRuczE6Eri8sxHk
+fY+BUZo7jYn0TZNmezwD7dOaHZrzZVD1oNB1ny+v8OqCQ5j4aZyJecRDjkZy42Q2Eq/3JR44iZB3
+fsNrarnDy0RLrHiQi+fHLB5LEUTINFInzQpdn4XBidUaePKVEFMy3YCEZnXZtWgo+2EuvoSoOMCZ
+EoalHmdkrQYuL6lwhceWD3yJZfWOQ1QOq92lgDmUYMA0yZZwLKMS9R9Ie70cfmu3nZD0Ijuu+Pwq
+yvqCUqDvr0tVk+vBtfAii6w0TiYiBKGHLHVKt+V9E9e4DGTANtLJL4YSjCMJwRuCO3NJo2pXh5Tl
+1njFmUNj403gdy3hZZlyaQQaRwnmDwFWJPsfvw55qVguucQJAX6Vum0ABj6y6koQOdjQK/W/7HW/
+lwLFCRsI3FU34oH7N4RDYiDK51ZLZer+bMEkkyShNOsF/5oirpt9P/FlUQqmMGqz9IgcgA38coro
+g14=
+-----END CERTIFICATE-----
+
+Taiwan GRCA
+===========
+-----BEGIN CERTIFICATE-----
+MIIFcjCCA1qgAwIBAgIQH51ZWtcvwgZEpYAIaeNe9jANBgkqhkiG9w0BAQUFADA/MQswCQYDVQQG
+EwJUVzEwMC4GA1UECgwnR292ZXJubWVudCBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4X
+DTAyMTIwNTEzMjMzM1oXDTMyMTIwNTEzMjMzM1owPzELMAkGA1UEBhMCVFcxMDAuBgNVBAoMJ0dv
+dmVybm1lbnQgUm9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAJoluOzMonWoe/fOW1mKydGGEghU7Jzy50b2iPN86aXfTEc2pBsBHH8eV4qN
+w8XRIePaJD9IK/ufLqGU5ywck9G/GwGHU5nOp/UKIXZ3/6m3xnOUT0b3EEk3+qhZSV1qgQdW8or5
+BtD3cCJNtLdBuTK4sfCxw5w/cP1T3YGq2GN49thTbqGsaoQkclSGxtKyyhwOeYHWtXBiCAEuTk8O
+1RGvqa/lmr/czIdtJuTJV6L7lvnM4T9TjGxMfptTCAtsF/tnyMKtsc2AtJfcdgEWFelq16TheEfO
+htX7MfP6Mb40qij7cEwdScevLJ1tZqa2jWR+tSBqnTuBto9AAGdLiYa4zGX+FVPpBMHWXx1E1wov
+J5pGfaENda1UhhXcSTvxls4Pm6Dso3pdvtUqdULle96ltqqvKKyskKw4t9VoNSZ63Pc78/1Fm9G7
+Q3hub/FCVGqY8A2tl+lSXunVanLeavcbYBT0peS2cWeqH+riTcFCQP5nRhc4L0c/cZyu5SHKYS1t
+B6iEfC3uUSXxY5Ce/eFXiGvviiNtsea9P63RPZYLhY3Naye7twWb7LuRqQoHEgKXTiCQ8P8NHuJB
+O9NAOueNXdpm5AKwB1KYXA6OM5zCppX7VRluTI6uSw+9wThNXo+EHWbNxWCWtFJaBYmOlXqYwZE8
+lSOyDvR5tMl8wUohAgMBAAGjajBoMB0GA1UdDgQWBBTMzO/MKWCkO7GStjz6MmKPrCUVOzAMBgNV
+HRMEBTADAQH/MDkGBGcqBwAEMTAvMC0CAQAwCQYFKw4DAhoFADAHBgVnKgMAAAQUA5vwIhP/lSg2
+09yewDL7MTqKUWUwDQYJKoZIhvcNAQEFBQADggIBAECASvomyc5eMN1PhnR2WPWus4MzeKR6dBcZ
+TulStbngCnRiqmjKeKBMmo4sIy7VahIkv9Ro04rQ2JyftB8M3jh+Vzj8jeJPXgyfqzvS/3WXy6Tj
+Zwj/5cAWtUgBfen5Cv8b5Wppv3ghqMKnI6mGq3ZW6A4M9hPdKmaKZEk9GhiHkASfQlK3T8v+R0F2
+Ne//AHY2RTKbxkaFXeIksB7jSJaYV0eUVXoPQbFEJPPB/hprv4j9wabak2BegUqZIJxIZhm1AHlU
+D7gsL0u8qV1bYH+Mh6XgUmMqvtg7hUAV/h62ZT/FS9p+tXo1KaMuephgIqP0fSdOLeq0dDzpD6Qz
+DxARvBMB1uUO07+1EqLhRSPAzAhuYbeJq4PjJB7mXQfnHyA+z2fI56wwbSdLaG5LKlwCCDTb+Hbk
+Z6MmnD+iMsJKxYEYMRBWqoTvLQr/uB930r+lWKBi5NdLkXWNiYCYfm3LU05er/ayl4WXudpVBrkk
+7tfGOB5jGxI7leFYrPLfhNVfmS8NVVvmONsuP3LpSIXLuykTjx44VbnzssQwmSNOXfJIoRIM3BKQ
+CZBUkQM8R+XVyWXgt0t97EfTsws+rZ7QdAAO671RrcDeLMDDav7v3Aun+kbfYNucpllQdSNpc5Oy
++fwC00fmcc4QAu4njIT/rEUNE1yDMuAlpYYsfPQS
+-----END CERTIFICATE-----
+
+Firmaprofesional Root CA
+========================
+-----BEGIN CERTIFICATE-----
+MIIEVzCCAz+gAwIBAgIBATANBgkqhkiG9w0BAQUFADCBnTELMAkGA1UEBhMCRVMxIjAgBgNVBAcT
+GUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMTOUF1dG9yaWRhZCBkZSBDZXJ0aWZp
+Y2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2ODEmMCQGCSqGSIb3DQEJARYXY2FA
+ZmlybWFwcm9mZXNpb25hbC5jb20wHhcNMDExMDI0MjIwMDAwWhcNMTMxMDI0MjIwMDAwWjCBnTEL
+MAkGA1UEBhMCRVMxIjAgBgNVBAcTGUMvIE11bnRhbmVyIDI0NCBCYXJjZWxvbmExQjBABgNVBAMT
+OUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2MjYzNDA2
+ODEmMCQGCSqGSIb3DQEJARYXY2FAZmlybWFwcm9mZXNpb25hbC5jb20wggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDnIwNvbyOlXnjOlSztlB5uCp4Bx+ow0Syd3Tfom5h5VtP8c9/Qit5V
+j1H5WuretXDE7aTt/6MNbg9kUDGvASdYrv5sp0ovFy3Tc9UTHI9ZpTQsHVQERc1ouKDAA6XPhUJH
+lShbz++AbOCQl4oBPB3zhxAwJkh91/zpnZFx/0GaqUC1N5wpIE8fUuOgfRNtVLcK3ulqTgesrBlf
+3H5idPayBQC6haD9HThuy1q7hryUZzM1gywfI834yJFxzJeL764P3CkDG8A563DtwW4O2GcLiam8
+NeTvtjS0pbbELaW+0MOUJEjb35bTALVmGotmBQ/dPz/LP6pemkr4tErvlTcbAgMBAAGjgZ8wgZww
+KgYDVR0RBCMwIYYfaHR0cDovL3d3dy5maXJtYXByb2Zlc2lvbmFsLmNvbTASBgNVHRMBAf8ECDAG
+AQH/AgEBMCsGA1UdEAQkMCKADzIwMDExMDI0MjIwMDAwWoEPMjAxMzEwMjQyMjAwMDBaMA4GA1Ud
+DwEB/wQEAwIBBjAdBgNVHQ4EFgQUMwugZtHq2s7eYpMEKFK1FH84aLcwDQYJKoZIhvcNAQEFBQAD
+ggEBAEdz/o0nVPD11HecJ3lXV7cVVuzH2Fi3AQL0M+2TUIiefEaxvT8Ub/GzR0iLjJcG1+p+o1wq
+u00vR+L4OQbJnC4xGgN49Lw4xiKLMzHwFgQEffl25EvXwOaD7FnMP97/T2u3Z36mhoEyIwOdyPdf
+wUpgpZKpsaSgYMN4h7Mi8yrrW6ntBas3D7Hi05V2Y1Z0jFhyGzflZKG+TQyTmAyX9odtsz/ny4Cm
+7YjHX1BiAuiZdBbQ5rQ58SfLyEDW44YQqSMSkuBpQWOnryULwMWSyx6Yo1q6xTMPoJcB3X/ge9YG
+VM+h4k0460tQtcsm9MracEpqoeJ5quGnM/b9Sh/22WA=
+-----END CERTIFICATE-----
+
+Wells Fargo Root CA
+===================
+-----BEGIN CERTIFICATE-----
+MIID5TCCAs2gAwIBAgIEOeSXnjANBgkqhkiG9w0BAQUFADCBgjELMAkGA1UEBhMCVVMxFDASBgNV
+BAoTC1dlbGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhv
+cml0eTEvMC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN
+MDAxMDExMTY0MTI4WhcNMjEwMTE0MTY0MTI4WjCBgjELMAkGA1UEBhMCVVMxFDASBgNVBAoTC1dl
+bGxzIEZhcmdvMSwwKgYDVQQLEyNXZWxscyBGYXJnbyBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTEv
+MC0GA1UEAxMmV2VsbHMgRmFyZ28gUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0GCSqG
+SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDVqDM7Jvk0/82bfuUER84A4n135zHCLielTWi5MbqNQ1mX
+x3Oqfz1cQJ4F5aHiidlMuD+b+Qy0yGIZLEWukR5zcUHESxP9cMIlrCL1dQu3U+SlK93OvRw6esP3
+E48mVJwWa2uv+9iWsWCaSOAlIiR5NM4OJgALTqv9i86C1y8IcGjBqAr5dE8Hq6T54oN+J3N0Prj5
+OEL8pahbSCOz6+MlsoCultQKnMJ4msZoGK43YjdeUXWoWGPAUe5AeH6orxqg4bB4nVCMe+ez/I4j
+sNtlAHCEAQgAFG5Uhpq6zPk3EPbg3oQtnaSFN9OH4xXQwReQfhkhahKpdv0SAulPIV4XAgMBAAGj
+YTBfMA8GA1UdEwEB/wQFMAMBAf8wTAYDVR0gBEUwQzBBBgtghkgBhvt7hwcBCzAyMDAGCCsGAQUF
+BwIBFiRodHRwOi8vd3d3LndlbGxzZmFyZ28uY29tL2NlcnRwb2xpY3kwDQYJKoZIhvcNAQEFBQAD
+ggEBANIn3ZwKdyu7IvICtUpKkfnRLb7kuxpo7w6kAOnu5+/u9vnldKTC2FJYxHT7zmu1Oyl5GFrv
+m+0fazbuSCUlFLZWohDo7qd/0D+j0MNdJu4HzMPBJCGHHt8qElNvQRbn7a6U+oxy+hNH8Dx+rn0R
+OhPs7fpvcmR7nX1/Jv16+yWt6j4pf0zjAFcysLPp7VMX2YuyFA4w6OXVE8Zkr8QA1dhYJPz1j+zx
+x32l2w8n0cbyQIjmH/ZhqPRCyLk306m+LFZ4wnKbWV01QIroTmMatukgalHizqSQ33ZwmVxwQ023
+tqcZZE6St8WRPH9IFmV7Fv3L/PvZ1dZPIWU7Sn9Ho/s=
+-----END CERTIFICATE-----
+
+Swisscom Root CA 1
+==================
+-----BEGIN CERTIFICATE-----
+MIIF2TCCA8GgAwIBAgIQXAuFXAvnWUHfV8w/f52oNjANBgkqhkiG9w0BAQUFADBkMQswCQYDVQQG
+EwJjaDERMA8GA1UEChMIU3dpc3Njb20xJTAjBgNVBAsTHERpZ2l0YWwgQ2VydGlmaWNhdGUgU2Vy
+dmljZXMxGzAZBgNVBAMTElN3aXNzY29tIFJvb3QgQ0EgMTAeFw0wNTA4MTgxMjA2MjBaFw0yNTA4
+MTgyMjA2MjBaMGQxCzAJBgNVBAYTAmNoMREwDwYDVQQKEwhTd2lzc2NvbTElMCMGA1UECxMcRGln
+aXRhbCBDZXJ0aWZpY2F0ZSBTZXJ2aWNlczEbMBkGA1UEAxMSU3dpc3Njb20gUm9vdCBDQSAxMIIC
+IjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0LmwqAzZuz8h+BvVM5OAFmUgdbI9m2BtRsiM
+MW8Xw/qabFbtPMWRV8PNq5ZJkCoZSx6jbVfd8StiKHVFXqrWW/oLJdihFvkcxC7mlSpnzNApbjyF
+NDhhSbEAn9Y6cV9Nbc5fuankiX9qUvrKm/LcqfmdmUc/TilftKaNXXsLmREDA/7n29uj/x2lzZAe
+AR81sH8A25Bvxn570e56eqeqDFdvpG3FEzuwpdntMhy0XmeLVNxzh+XTF3xmUHJd1BpYwdnP2IkC
+b6dJtDZd0KTeByy2dbcokdaXvij1mB7qWybJvbCXc9qukSbraMH5ORXWZ0sKbU/Lz7DkQnGMU3nn
+7uHbHaBuHYwadzVcFh4rUx80i9Fs/PJnB3r1re3WmquhsUvhzDdf/X/NTa64H5xD+SpYVUNFvJbN
+cA78yeNmuk6NO4HLFWR7uZToXTNShXEuT46iBhFRyePLoW4xCGQMwtI89Tbo19AOeCMgkckkKmUp
+WyL3Ic6DXqTz3kvTaI9GdVyDCW4pa8RwjPWd1yAv/0bSKzjCL3UcPX7ape8eYIVpQtPM+GP+HkM5
+haa2Y0EQs3MevNP6yn0WR+Kn1dCjigoIlmJWbjTb2QK5MHXjBNLnj8KwEUAKrNVxAmKLMb7dxiNY
+MUJDLXT5xp6mig/p/r+D5kNXJLrvRjSq1xIBOO0CAwEAAaOBhjCBgzAOBgNVHQ8BAf8EBAMCAYYw
+HQYDVR0hBBYwFDASBgdghXQBUwABBgdghXQBUwABMBIGA1UdEwEB/wQIMAYBAf8CAQcwHwYDVR0j
+BBgwFoAUAyUv3m+CATpcLNwroWm1Z9SM0/0wHQYDVR0OBBYEFAMlL95vggE6XCzcK6FptWfUjNP9
+MA0GCSqGSIb3DQEBBQUAA4ICAQA1EMvspgQNDQ/NwNurqPKIlwzfky9NfEBWMXrrpA9gzXrzvsMn
+jgM+pN0S734edAY8PzHyHHuRMSG08NBsl9Tpl7IkVh5WwzW9iAUPWxAaZOHHgjD5Mq2eUCzneAXQ
+MbFamIp1TpBcahQq4FJHgmDmHtqBsfsUC1rxn9KVuj7QG9YVHaO+htXbD8BJZLsuUBlL0iT43R4H
+VtA4oJVwIHaM190e3p9xxCPvgxNcoyQVTSlAPGrEqdi3pkSlDfTgnXceQHAm/NrZNuR55LU/vJtl
+vrsRls/bxig5OgjOR1tTWsWZ/l2p3e9M1MalrQLmjAcSHm8D0W+go/MpvRLHUKKwf4ipmXeascCl
+OS5cfGniLLDqN2qk4Vrh9VDlg++luyqI54zb/W1elxmofmZ1a3Hqv7HHb6D0jqTsNFFbjCYDcKF3
+1QESVwA12yPeDooomf2xEG9L/zgtYE4snOtnta1J7ksfrK/7DZBaZmBwXarNeNQk7shBoJMBkpxq
+nvy5JMWzFYJ+vq6VK+uxwNrjAWALXmmshFZhvnEX/h0TD/7Gh0Xp/jKgGg0TpJRVcaUWi7rKibCy
+x/yP2FS1k2Kdzs9Z+z0YzirLNRWCXf9UIltxUvu3yf5gmwBBZPCqKuy2QkPOiWaByIufOVQDJdMW
+NY6E0F/6MBr1mmz0DlP5OlvRHA==
+-----END CERTIFICATE-----
+
+DigiCert Assured ID Root CA
+===========================
+-----BEGIN CERTIFICATE-----
+MIIDtzCCAp+gAwIBAgIQDOfg5RfYRv6P5WD8G/AwOTANBgkqhkiG9w0BAQUFADBlMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSQw
+IgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0EwHhcNMDYxMTEwMDAwMDAwWhcNMzEx
+MTEwMDAwMDAwWjBlMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQL
+ExB3d3cuZGlnaWNlcnQuY29tMSQwIgYDVQQDExtEaWdpQ2VydCBBc3N1cmVkIElEIFJvb3QgQ0Ew
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtDhXO5EOAXLGH87dg+XESpa7cJpSIqvTO
+9SA5KFhgDPiA2qkVlTJhPLWxKISKityfCgyDF3qPkKyK53lTXDGEKvYPmDI2dsze3Tyoou9q+yHy
+UmHfnyDXH+Kx2f4YZNISW1/5WBg1vEfNoTb5a3/UsDg+wRvDjDPZ2C8Y/igPs6eD1sNuRMBhNZYW
+/lmci3Zt1/GiSw0r/wty2p5g0I6QNcZ4VYcgoc/lbQrISXwxmDNsIumH0DJaoroTghHtORedmTpy
+oeb6pNnVFzF1roV9Iq4/AUaG9ih5yLHa5FcXxH4cDrC0kqZWs72yl+2qp/C3xag/lRbQ/6GW6whf
+GHdPAgMBAAGjYzBhMA4GA1UdDwEB/wQEAwIBhjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRF
+66Kv9JLLgjEtUYunpyGd823IDzAfBgNVHSMEGDAWgBRF66Kv9JLLgjEtUYunpyGd823IDzANBgkq
+hkiG9w0BAQUFAAOCAQEAog683+Lt8ONyc3pklL/3cmbYMuRCdWKuh+vy1dneVrOfzM4UKLkNl2Bc
+EkxY5NM9g0lFWJc1aRqoR+pWxnmrEthngYTffwk8lOa4JiwgvT2zKIn3X/8i4peEH+ll74fg38Fn
+SbNd67IJKusm7Xi+fT8r87cmNW1fiQG2SVufAQWbqz0lwcy2f8Lxb4bG+mRo64EtlOtCt/qMHt1i
+8b5QZ7dsvfPxH2sMNgcWfzd8qVttevESRmCD1ycEvkvOl77DZypoEd+A5wwzZr8TDRRu838fYxAe
++o0bJW1sj6W3YQGx0qMmoRBxna3iw/nDmVG3KwcIzi7mULKn+gpFL6Lw8g==
+-----END CERTIFICATE-----
+
+DigiCert Global Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDrzCCApegAwIBAgIQCDvgVpBCRrGhdWrJWZHHSjANBgkqhkiG9w0BAQUFADBhMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSAw
+HgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBDQTAeFw0wNjExMTAwMDAwMDBaFw0zMTExMTAw
+MDAwMDBaMGExCzAJBgNVBAYTAlVTMRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3
+dy5kaWdpY2VydC5jb20xIDAeBgNVBAMTF0RpZ2lDZXJ0IEdsb2JhbCBSb290IENBMIIBIjANBgkq
+hkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA4jvhEXLeqKTTo1eqUKKPC3eQyaKl7hLOllsBCSDMAZOn
+TjC3U/dDxGkAV53ijSLdhwZAAIEJzs4bg7/fzTtxRuLWZscFs3YnFo97nh6Vfe63SKMI2tavegw5
+BmV/Sl0fvBf4q77uKNd0f3p4mVmFaG5cIzJLv07A6Fpt43C/dxC//AH2hdmoRBBYMql1GNXRor5H
+4idq9Joz+EkIYIvUX7Q6hL+hqkpMfT7PT19sdl6gSzeRntwi5m3OFBqOasv+zbMUZBfHWymeMr/y
+7vrTC0LUq7dBMtoM1O/4gdW7jVg/tRvoSSiicNoxBN33shbyTApOB6jtSj1etX+jkMOvJwIDAQAB
+o2MwYTAOBgNVHQ8BAf8EBAMCAYYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUA95QNVbRTLtm
+8KPiGxvDl7I90VUwHwYDVR0jBBgwFoAUA95QNVbRTLtm8KPiGxvDl7I90VUwDQYJKoZIhvcNAQEF
+BQADggEBAMucN6pIExIK+t1EnE9SsPTfrgT1eXkIoyQY/EsrhMAtudXH/vTBH1jLuG2cenTnmCmr
+EbXjcKChzUyImZOMkXDiqw8cvpOp/2PV5Adg06O/nVsJ8dWO41P0jmP6P6fbtGbfYmbW0W5BjfIt
+tep3Sp+dWOIrWcBAI+0tKIJFPnlUkiaY4IBIqDfv8NZ5YBberOgOzW6sRBc4L0na4UU+Krk2U886
+UAb3LujEV0lsYSEY1QSteDwsOoBrp+uvFRTp2InBuThs4pFsiv9kuXclVzDAGySj4dzp30d8tbQk
+CAUw7C29C79Fv1C5qfPrmAESrciIxpg0X40KPMbp1ZWVbd4=
+-----END CERTIFICATE-----
+
+DigiCert High Assurance EV Root CA
+==================================
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIQAqxcJmoLQJuPC3nyrkYldzANBgkqhkiG9w0BAQUFADBsMQswCQYDVQQG
+EwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3d3cuZGlnaWNlcnQuY29tMSsw
+KQYDVQQDEyJEaWdpQ2VydCBIaWdoIEFzc3VyYW5jZSBFViBSb290IENBMB4XDTA2MTExMDAwMDAw
+MFoXDTMxMTExMDAwMDAwMFowbDELMAkGA1UEBhMCVVMxFTATBgNVBAoTDERpZ2lDZXJ0IEluYzEZ
+MBcGA1UECxMQd3d3LmRpZ2ljZXJ0LmNvbTErMCkGA1UEAxMiRGlnaUNlcnQgSGlnaCBBc3N1cmFu
+Y2UgRVYgUm9vdCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbM5XPm+9S75S0t
+Mqbf5YE/yc0lSbZxKsPVlDRnogocsF9ppkCxxLeyj9CYpKlBWTrT3JTWPNt0OKRKzE0lgvdKpVMS
+OO7zSW1xkX5jtqumX8OkhPhPYlG++MXs2ziS4wblCJEMxChBVfvLWokVfnHoNb9Ncgk9vjo4UFt3
+MRuNs8ckRZqnrG0AFFoEt7oT61EKmEFBIk5lYYeBQVCmeVyJ3hlKV9Uu5l0cUyx+mM0aBhakaHPQ
+NAQTXKFx01p8VdteZOE3hzBWBOURtCmAEvF5OYiiAhF8J2a3iLd48soKqDirCmTCv2ZdlYTBoSUe
+h10aUAsgEsxBu24LUTi4S8sCAwEAAaNjMGEwDgYDVR0PAQH/BAQDAgGGMA8GA1UdEwEB/wQFMAMB
+Af8wHQYDVR0OBBYEFLE+w2kD+L9HAdSYJhoIAu9jZCvDMB8GA1UdIwQYMBaAFLE+w2kD+L9HAdSY
+JhoIAu9jZCvDMA0GCSqGSIb3DQEBBQUAA4IBAQAcGgaX3NecnzyIZgYIVyHbIUf4KmeqvxgydkAQ
+V8GK83rZEWWONfqe/EW1ntlMMUu4kehDLI6zeM7b41N5cdblIZQB2lWHmiRk9opmzN6cN82oNLFp
+myPInngiK3BD41VHMWEZ71jFhS9OMPagMRYjyOfiZRYzy78aG6A9+MpeizGLYAiJLQwGXFK3xPkK
+mNEVX58Svnw2Yzi9RKR/5CYrCsSXaQ3pjOLAEFe4yHYSkVXySGnYvCoCWw9E1CAx2/S6cCZdkGCe
+vEsXCS+0yx5DaMkHJ8HSXPfqIbloEpw8nL+e/IBcm2PN7EeqJSdnoDfzAIJ9VNep+OkuE6N36B9K
+-----END CERTIFICATE-----
+
+Certplus Class 2 Primary CA
+===========================
+-----BEGIN CERTIFICATE-----
+MIIDkjCCAnqgAwIBAgIRAIW9S/PY2uNp9pTXX8OlRCMwDQYJKoZIhvcNAQEFBQAwPTELMAkGA1UE
+BhMCRlIxETAPBgNVBAoTCENlcnRwbHVzMRswGQYDVQQDExJDbGFzcyAyIFByaW1hcnkgQ0EwHhcN
+OTkwNzA3MTcwNTAwWhcNMTkwNzA2MjM1OTU5WjA9MQswCQYDVQQGEwJGUjERMA8GA1UEChMIQ2Vy
+dHBsdXMxGzAZBgNVBAMTEkNsYXNzIDIgUHJpbWFyeSBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEP
+ADCCAQoCggEBANxQltAS+DXSCHh6tlJw/W/uz7kRy1134ezpfgSN1sxvc0NXYKwzCkTsA18cgCSR
+5aiRVhKC9+Ar9NuuYS6JEI1rbLqzAr3VNsVINyPi8Fo3UjMXEuLRYE2+L0ER4/YXJQyLkcAbmXuZ
+Vg2v7tK8R1fjeUl7NIknJITesezpWE7+Tt9avkGtrAjFGA7v0lPubNCdEgETjdyAYveVqUSISnFO
+YFWe2yMZeVYHDD9jC1yw4r5+FfyUM1hBOHTE4Y+L3yasH7WLO7dDWWuwJKZtkIvEcupdM5i3y95e
+e++U8Rs+yskhwcWYAqqi9lt3m/V+llU0HGdpwPFC40es/CgcZlUCAwEAAaOBjDCBiTAPBgNVHRME
+CDAGAQH/AgEKMAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQU43Mt38sOKAze3bOkynm4jrvoMIkwEQYJ
+YIZIAYb4QgEBBAQDAgEGMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly93d3cuY2VydHBsdXMuY29t
+L0NSTC9jbGFzczIuY3JsMA0GCSqGSIb3DQEBBQUAA4IBAQCnVM+IRBnL39R/AN9WM2K191EBkOvD
+P9GIROkkXe/nFL0gt5o8AP5tn9uQ3Nf0YtaLcF3n5QRIqWh8yfFC82x/xXp8HVGIutIKPidd3i1R
+TtMTZGnkLuPT55sJmabglZvOGtd/vjzOUrMRFcEPF80Du5wlFbqidon8BvEY0JNLDnyCt6X09l/+
+7UCmnYR0ObncHoUW2ikbhiMAybuJfm6AiB4vFLQDJKgybwOaRywwvlbGp0ICcBvqQNi6BQNwB6SW
+//1IMwrh3KWBkJtN3X3n57LNXMhqlfil9o3EXXgIvnsG1knPGTZQIy4I5p4FTUcY1Rbpsda2ENW7
+l7+ijrRU
+-----END CERTIFICATE-----
+
+DST Root CA X3
+==============
+-----BEGIN CERTIFICATE-----
+MIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/MSQwIgYDVQQK
+ExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMTDkRTVCBSb290IENBIFgzMB4X
+DTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVowPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1
+cmUgVHJ1c3QgQ28uMRcwFQYDVQQDEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmT
+rE4Orz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEqOLl5CjH9
+UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9bxiqKqy69cK3FCxolkHRy
+xXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40d
+utolucbY38EVAjqr2m7xPi71XAicPNaDaeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQ
+MA0GCSqGSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69ikug
+dB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXrAvHRAosZy5Q6XkjE
+GB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZzR8srzJmwN0jP41ZL9c8PDHIyh8bw
+RLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5JDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubS
+fZGL+T0yjWW06XyxV3bqxbYoOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ
+-----END CERTIFICATE-----
+
+DST ACES CA X6
+==============
+-----BEGIN CERTIFICATE-----
+MIIECTCCAvGgAwIBAgIQDV6ZCtadt3js2AdWO4YV2TANBgkqhkiG9w0BAQUFADBbMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QxETAPBgNVBAsTCERTVCBBQ0VT
+MRcwFQYDVQQDEw5EU1QgQUNFUyBDQSBYNjAeFw0wMzExMjAyMTE5NThaFw0xNzExMjAyMTE5NTha
+MFsxCzAJBgNVBAYTAlVTMSAwHgYDVQQKExdEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdDERMA8GA1UE
+CxMIRFNUIEFDRVMxFzAVBgNVBAMTDkRTVCBBQ0VTIENBIFg2MIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAuT31LMmU3HWKlV1j6IR3dma5WZFcRt2SPp/5DgO0PWGSvSMmtWPuktKe1jzI
+DZBfZIGxqAgNTNj50wUoUrQBJcWVHAx+PhCEdc/BGZFjz+iokYi5Q1K7gLFViYsx+tC3dr5BPTCa
+pCIlF3PoHuLTrCq9Wzgh1SpL11V94zpVvddtawJXa+ZHfAjIgrrep4c9oW24MFbCswKBXy314pow
+GCi4ZtPLAZZv6opFVdbgnf9nKxcCpk4aahELfrd755jWjHZvwTvbUJN+5dCOHze4vbrGn2zpfDPy
+MjwmR/onJALJfh1biEITajV8fTXpLmaRcpPVMibEdPVTo7NdmvYJywIDAQABo4HIMIHFMA8GA1Ud
+EwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgHGMB8GA1UdEQQYMBaBFHBraS1vcHNAdHJ1c3Rkc3Qu
+Y29tMGIGA1UdIARbMFkwVwYKYIZIAWUDAgEBATBJMEcGCCsGAQUFBwIBFjtodHRwOi8vd3d3LnRy
+dXN0ZHN0LmNvbS9jZXJ0aWZpY2F0ZXMvcG9saWN5L0FDRVMtaW5kZXguaHRtbDAdBgNVHQ4EFgQU
+CXIGThhDD+XWzMNqizF7eI+og7gwDQYJKoZIhvcNAQEFBQADggEBAKPYjtay284F5zLNAdMEA+V2
+5FYrnJmQ6AgwbN99Pe7lv7UkQIRJ4dEorsTCOlMwiPH1d25Ryvr/ma8kXxug/fKshMrfqfBfBC6t
+Fr8hlxCBPeP/h40y3JTlR4peahPJlJU90u7INJXQgNStMgiAVDzgvVJT11J8smk/f3rPanTK+gQq
+nExaBqXpIK1FZg9p8d2/6eMyi/rgwYZNcjwu2JN4Cir42NInPRmJX1p7ijvMDNpRrscL9yuwNwXs
+vFcj4jjSm2jzVhKIT0J8uDHEtdvkyCE06UgRNe76x5JXxZ805Mf29w4LTJxoeHtxMcfrHuBnQfO3
+oKfN5XozNmr6mis=
+-----END CERTIFICATE-----
+
+TURKTRUST Certificate Services Provider Root 1
+==============================================
+-----BEGIN CERTIFICATE-----
+MIID+zCCAuOgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBtzE/MD0GA1UEAww2VMOcUktUUlVTVCBF
+bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGDAJUUjEP
+MA0GA1UEBwwGQU5LQVJBMVYwVAYDVQQKDE0oYykgMjAwNSBUw5xSS1RSVVNUIEJpbGdpIMSwbGV0
+acWfaW0gdmUgQmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLjAeFw0wNTA1MTMx
+MDI3MTdaFw0xNTAzMjIxMDI3MTdaMIG3MT8wPQYDVQQDDDZUw5xSS1RSVVNUIEVsZWt0cm9uaWsg
+U2VydGlmaWthIEhpem1ldCBTYcSfbGF5xLFjxLFzxLExCzAJBgNVBAYMAlRSMQ8wDQYDVQQHDAZB
+TktBUkExVjBUBgNVBAoMTShjKSAyMDA1IFTDnFJLVFJVU1QgQmlsZ2kgxLBsZXRpxZ9pbSB2ZSBC
+aWxpxZ9pbSBHw7x2ZW5sacSfaSBIaXptZXRsZXJpIEEuxZ4uMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEAylIF1mMD2Bxf3dJ7XfIMYGFbazt0K3gNfUW9InTojAPBxhEqPZW8qZSwu5GX
+yGl8hMW0kWxsE2qkVa2kheiVfrMArwDCBRj1cJ02i67L5BuBf5OI+2pVu32Fks66WJ/bMsW9Xe8i
+Si9BB35JYbOG7E6mQW6EvAPs9TscyB/C7qju6hJKjRTP8wrgUDn5CDX4EVmt5yLqS8oUBt5CurKZ
+8y1UiBAG6uEaPj1nH/vO+3yC6BFdSsG5FOpU2WabfIl9BJpiyelSPJ6c79L1JuTm5Rh8i27fbMx4
+W09ysstcP4wFjdFMjK2Sx+F4f2VsSQZQLJ4ywtdKxnWKWU51b0dewQIDAQABoxAwDjAMBgNVHRME
+BTADAQH/MA0GCSqGSIb3DQEBBQUAA4IBAQAV9VX/N5aAWSGk/KEVTCD21F/aAyT8z5Aa9CEKmu46
+sWrv7/hg0Uw2ZkUd82YCdAR7kjCo3gp2D++Vbr3JN+YaDayJSFvMgzbC9UZcWYJWtNX+I7TYVBxE
+q8Sn5RTOPEFhfEPmzcSBCYsk+1Ql1haolgxnB2+zUEfjHCQo3SqYpGH+2+oSN7wBGjSFvW5P55Fy
+B0SFHljKVETd96y5y4khctuPwGkplyqjrhgjlxxBKot8KsF8kOipKMDTkcatKIdAaLX/7KfS0zgY
+nNN9aV3wxqUeJBujR/xpB2jn5Jq07Q+hh4cCzofSSE7hvP/L8XKSRGQDJereW26fyfJOrN3H
+-----END CERTIFICATE-----
+
+TURKTRUST Certificate Services Provider Root 2
+==============================================
+-----BEGIN CERTIFICATE-----
+MIIEPDCCAySgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBF
+bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEP
+MA0GA1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUg
+QmlsacWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwHhcN
+MDUxMTA3MTAwNzU3WhcNMTUwOTE2MTAwNzU3WjCBvjE/MD0GA1UEAww2VMOcUktUUlVTVCBFbGVr
+dHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMQswCQYDVQQGEwJUUjEPMA0G
+A1UEBwwGQW5rYXJhMV0wWwYDVQQKDFRUw5xSS1RSVVNUIEJpbGdpIMSwbGV0acWfaW0gdmUgQmls
+acWfaW0gR8O8dmVubGnEn2kgSGl6bWV0bGVyaSBBLsWeLiAoYykgS2FzxLFtIDIwMDUwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCpNn7DkUNMwxmYCMjHWHtPFoylzkkBH3MOrHUTpvqe
+LCDe2JAOCtFp0if7qnefJ1Il4std2NiDUBd9irWCPwSOtNXwSadktx4uXyCcUHVPr+G1QRT0mJKI
+x+XlZEdhR3n9wFHxwZnn3M5q+6+1ATDcRhzviuyV79z/rxAc653YsKpqhRgNF8k+v/Gb0AmJQv2g
+QrSdiVFVKc8bcLyEVK3BEx+Y9C52YItdP5qtygy/p1Zbj3e41Z55SZI/4PGXJHpsmxcPbe9TmJEr
+5A++WXkHeLuXlfSfadRYhwqp48y2WBmfJiGxxFmNskF1wK1pzpwACPI2/z7woQ8arBT9pmAPAgMB
+AAGjQzBBMB0GA1UdDgQWBBTZN7NOBf3Zz58SFq62iS/rJTqIHDAPBgNVHQ8BAf8EBQMDBwYAMA8G
+A1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAHJglrfJ3NgpXiOFX7KzLXb7iNcX/ntt
+Rbj2hWyfIvwqECLsqrkw9qtY1jkQMZkpAL2JZkH7dN6RwRgLn7Vhy506vvWolKMiVW4XSf/SKfE4
+Jl3vpao6+XF75tpYHdN0wgH6PmlYX63LaL4ULptswLbcoCb6dxriJNoaN+BnrdFzgw2lGh1uEpJ+
+hGIAF728JRhX8tepb1mIvDS3LoV4nZbcFMMsilKbloxSZj2GFotHuFEJjOp9zYhys2AzsfAKRO8P
+9Qk3iCQOLGsgOqL6EfJANZxEaGM7rDNvY7wsu/LSy3Z9fYjYHcgFHW68lKlmjHdxx/qR+i9Rnuk5
+UrbnBEI=
+-----END CERTIFICATE-----
+
+SwissSign Platinum CA - G2
+==========================
+-----BEGIN CERTIFICATE-----
+MIIFwTCCA6mgAwIBAgIITrIAZwwDXU8wDQYJKoZIhvcNAQEFBQAwSTELMAkGA1UEBhMCQ0gxFTAT
+BgNVBAoTDFN3aXNzU2lnbiBBRzEjMCEGA1UEAxMaU3dpc3NTaWduIFBsYXRpbnVtIENBIC0gRzIw
+HhcNMDYxMDI1MDgzNjAwWhcNMzYxMDI1MDgzNjAwWjBJMQswCQYDVQQGEwJDSDEVMBMGA1UEChMM
+U3dpc3NTaWduIEFHMSMwIQYDVQQDExpTd2lzc1NpZ24gUGxhdGludW0gQ0EgLSBHMjCCAiIwDQYJ
+KoZIhvcNAQEBBQADggIPADCCAgoCggIBAMrfogLi2vj8Bxax3mCq3pZcZB/HL37PZ/pEQtZ2Y5Wu
+669yIIpFR4ZieIbWIDkm9K6j/SPnpZy1IiEZtzeTIsBQnIJ71NUERFzLtMKfkr4k2HtnIuJpX+UF
+eNSH2XFwMyVTtIc7KZAoNppVRDBopIOXfw0enHb/FZ1glwCNioUD7IC+6ixuEFGSzH7VozPY1kne
+WCqv9hbrS3uQMpe5up1Y8fhXSQQeol0GcN1x2/ndi5objM89o03Oy3z2u5yg+gnOI2Ky6Q0f4nIo
+j5+saCB9bzuohTEJfwvH6GXp43gOCWcwizSC+13gzJ2BbWLuCB4ELE6b7P6pT1/9aXjvCR+htL/6
+8++QHkwFix7qepF6w9fl+zC8bBsQWJj3Gl/QKTIDE0ZNYWqFTFJ0LwYfexHihJfGmfNtf9dng34T
+aNhxKFrYzt3oEBSa/m0jh26OWnA81Y0JAKeqvLAxN23IhBQeW71FYyBrS3SMvds6DsHPWhaPpZjy
+domyExI7C3d3rLvlPClKknLKYRorXkzig3R3+jVIeoVNjZpTxN94ypeRSCtFKwH3HBqi7Ri6Cr2D
++m+8jVeTO9TUps4e8aCxzqv9KyiaTxvXw3LbpMS/XUz13XuWae5ogObnmLo2t/5u7Su9IPhlGdpV
+CX4l3P5hYnL5fhgC72O00Puv5TtjjGePAgMBAAGjgawwgakwDgYDVR0PAQH/BAQDAgEGMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFFCvzAeHFUdvOMW0ZdHelarp35zMMB8GA1UdIwQYMBaAFFCv
+zAeHFUdvOMW0ZdHelarp35zMMEYGA1UdIAQ/MD0wOwYJYIV0AVkBAQEBMC4wLAYIKwYBBQUHAgEW
+IGh0dHA6Ly9yZXBvc2l0b3J5LnN3aXNzc2lnbi5jb20vMA0GCSqGSIb3DQEBBQUAA4ICAQAIhab1
+Fgz8RBrBY+D5VUYI/HAcQiiWjrfFwUF1TglxeeVtlspLpYhg0DB0uMoI3LQwnkAHFmtllXcBrqS3
+NQuB2nEVqXQXOHtYyvkv+8Bldo1bAbl93oI9ZLi+FHSjClTTLJUYFzX1UWs/j6KWYTl4a0vlpqD4
+U99REJNi54Av4tHgvI42Rncz7Lj7jposiU0xEQ8mngS7twSNC/K5/FqdOxa3L8iYq/6KUFkuozv8
+KV2LwUvJ4ooTHbG/u0IdUt1O2BReEMYxB+9xJ/cbOQncguqLs5WGXv312l0xpuAxtpTmREl0xRbl
+9x8DYSjFyMsSoEJL+WuICI20MhjzdZ/EfwBPBZWcoxcCw7NTm6ogOSkrZvqdr16zktK1puEa+S1B
+aYEUtLS17Yk9zvupnTVCRLEcFHOBzyoBNZox1S2PbYTfgE1X4z/FhHXaicYwu+uPyyIIoK6q8QNs
+OktNCaUOcsZWayFCTiMlFGiudgp8DAdwZPmaL/YFOSbGDI8Zf0NebvRbFS/bYV3mZy8/CJT5YLSY
+Mdp08YSTcU1f+2BY0fvEwW2JorsgH51xkcsymxM9Pn2SUjWskpSi0xjCfMfqr3YFFt1nJ8J+HAci
+IfNAChs0B0QTwoRqjt8ZWr9/6x3iGjjRXK9HkmuAtTClyY3YqzGBH9/CZjfTk6mFhnll0g==
+-----END CERTIFICATE-----
+
+SwissSign Gold CA - G2
+======================
+-----BEGIN CERTIFICATE-----
+MIIFujCCA6KgAwIBAgIJALtAHEP1Xk+wMA0GCSqGSIb3DQEBBQUAMEUxCzAJBgNVBAYTAkNIMRUw
+EwYDVQQKEwxTd2lzc1NpZ24gQUcxHzAdBgNVBAMTFlN3aXNzU2lnbiBHb2xkIENBIC0gRzIwHhcN
+MDYxMDI1MDgzMDM1WhcNMzYxMDI1MDgzMDM1WjBFMQswCQYDVQQGEwJDSDEVMBMGA1UEChMMU3dp
+c3NTaWduIEFHMR8wHQYDVQQDExZTd2lzc1NpZ24gR29sZCBDQSAtIEcyMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEAr+TufoskDhJuqVAtFkQ7kpJcyrhdhJJCEyq8ZVeCQD5XJM1QiyUq
+t2/876LQwB8CJEoTlo8jE+YoWACjR8cGp4QjK7u9lit/VcyLwVcfDmJlD909Vopz2q5+bbqBHH5C
+jCA12UNNhPqE21Is8w4ndwtrvxEvcnifLtg+5hg3Wipy+dpikJKVyh+c6bM8K8vzARO/Ws/BtQpg
+vd21mWRTuKCWs2/iJneRjOBiEAKfNA+k1ZIzUd6+jbqEemA8atufK+ze3gE/bk3lUIbLtK/tREDF
+ylqM2tIrfKjuvqblCqoOpd8FUrdVxyJdMmqXl2MT28nbeTZ7hTpKxVKJ+STnnXepgv9VHKVxaSvR
+AiTysybUa9oEVeXBCsdtMDeQKuSeFDNeFhdVxVu1yzSJkvGdJo+hB9TGsnhQ2wwMC3wLjEHXuend
+jIj3o02yMszYF9rNt85mndT9Xv+9lz4pded+p2JYryU0pUHHPbwNUMoDAw8IWh+Vc3hiv69yFGkO
+peUDDniOJihC8AcLYiAQZzlG+qkDzAQ4embvIIO1jEpWjpEA/I5cgt6IoMPiaG59je883WX0XaxR
+7ySArqpWl2/5rX3aYT+YdzylkbYcjCbaZaIJbcHiVOO5ykxMgI93e2CaHt+28kgeDrpOVG2Y4OGi
+GqJ3UM/EY5LsRxmd6+ZrzsECAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUWyV7lqRlUX64OfPAeGZe6Drn8O4wHwYDVR0jBBgwFoAUWyV7lqRlUX64
+OfPAeGZe6Drn8O4wRgYDVR0gBD8wPTA7BglghXQBWQECAQEwLjAsBggrBgEFBQcCARYgaHR0cDov
+L3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBACe645R88a7A3hfm
+5djV9VSwg/S7zV4Fe0+fdWavPOhWfvxyeDgD2StiGwC5+OlgzczOUYrHUDFu4Up+GC9pWbY9ZIEr
+44OE5iKHjn3g7gKZYbge9LgriBIWhMIxkziWMaa5O1M/wySTVltpkuzFwbs4AOPsF6m43Md8AYOf
+Mke6UiI0HTJ6CVanfCU2qT1L2sCCbwq7EsiHSycR+R4tx5M/nttfJmtS2S6K8RTGRI0Vqbe/vd6m
+Gu6uLftIdxf+u+yvGPUqUfA5hJeVbG4bwyvEdGB5JbAKJ9/fXtI5z0V9QkvfsywexcZdylU6oJxp
+mo/a77KwPJ+HbBIrZXAVUjEaJM9vMSNQH4xPjyPDdEFjHFWoFN0+4FFQz/EbMFYOkrCChdiDyyJk
+vC24JdVUorgG6q2SpCSgwYa1ShNqR88uC1aVVMvOmttqtKay20EIhid392qgQmwLOM7XdVAyksLf
+KzAiSNDVQTglXaTpXZ/GlHXQRf0wl0OPkKsKx4ZzYEppLd6leNcG2mqeSz53OiATIgHQv2ieY2Br
+NU0LbbqhPcCT4H8js1WtciVORvnSFu+wZMEBnunKoGqYDs/YYPIvSbjkQuE4NRb0yG5P94FW6Lqj
+viOvrv1vA+ACOzB2+httQc8Bsem4yWb02ybzOqR08kkkW8mw0FfB+j564ZfJ
+-----END CERTIFICATE-----
+
+SwissSign Silver CA - G2
+========================
+-----BEGIN CERTIFICATE-----
+MIIFvTCCA6WgAwIBAgIITxvUL1S7L0swDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCQ0gxFTAT
+BgNVBAoTDFN3aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMB4X
+DTA2MTAyNTA4MzI0NloXDTM2MTAyNTA4MzI0NlowRzELMAkGA1UEBhMCQ0gxFTATBgNVBAoTDFN3
+aXNzU2lnbiBBRzEhMB8GA1UEAxMYU3dpc3NTaWduIFNpbHZlciBDQSAtIEcyMIICIjANBgkqhkiG
+9w0BAQEFAAOCAg8AMIICCgKCAgEAxPGHf9N4Mfc4yfjDmUO8x/e8N+dOcbpLj6VzHVxumK4DV644
+N0MvFz0fyM5oEMF4rhkDKxD6LHmD9ui5aLlV8gREpzn5/ASLHvGiTSf5YXu6t+WiE7brYT7QbNHm
++/pe7R20nqA1W6GSy/BJkv6FCgU+5tkL4k+73JU3/JHpMjUi0R86TieFnbAVlDLaYQ1HTWBCrpJH
+6INaUFjpiou5XaHc3ZlKHzZnu0jkg7Y360g6rw9njxcH6ATK72oxh9TAtvmUcXtnZLi2kUpCe2Uu
+MGoM9ZDulebyzYLs2aFK7PayS+VFheZteJMELpyCbTapxDFkH4aDCyr0NQp4yVXPQbBH6TCfmb5h
+qAaEuSh6XzjZG6k4sIN/c8HDO0gqgg8hm7jMqDXDhBuDsz6+pJVpATqJAHgE2cn0mRmrVn5bi4Y5
+FZGkECwJMoBgs5PAKrYYC51+jUnyEEp/+dVGLxmSo5mnJqy7jDzmDrxHB9xzUfFwZC8I+bRHHTBs
+ROopN4WSaGa8gzj+ezku01DwH/teYLappvonQfGbGHLy9YR0SslnxFSuSGTfjNFusB3hB48IHpmc
+celM2KX3RxIfdNFRnobzwqIjQAtz20um53MGjMGg6cFZrEb65i/4z3GcRm25xBWNOHkDRUjvxF3X
+CO6HOSKGsg0PWEP3calILv3q1h8CAwEAAaOBrDCBqTAOBgNVHQ8BAf8EBAMCAQYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUF6DNweRBtjpbO8tFnb0cwpj6hlgwHwYDVR0jBBgwFoAUF6DNweRB
+tjpbO8tFnb0cwpj6hlgwRgYDVR0gBD8wPTA7BglghXQBWQEDAQEwLjAsBggrBgEFBQcCARYgaHR0
+cDovL3JlcG9zaXRvcnkuc3dpc3NzaWduLmNvbS8wDQYJKoZIhvcNAQEFBQADggIBAHPGgeAn0i0P
+4JUw4ppBf1AsX19iYamGamkYDHRJ1l2E6kFSGG9YrVBWIGrGvShpWJHckRE1qTodvBqlYJ7YH39F
+kWnZfrt4csEGDyrOj4VwYaygzQu4OSlWhDJOhrs9xCrZ1x9y7v5RoSJBsXECYxqCsGKrXlcSH9/L
+3XWgwF15kIwb4FDm3jH+mHtwX6WQ2K34ArZv02DdQEsixT2tOnqfGhpHkXkzuoLcMmkDlm4fS/Bx
+/uNncqCxv1yL5PqZIseEuRuNI5c/7SXgz2W79WEE790eslpBIlqhn10s6FvJbakMDHiqYMZWjwFa
+DGi8aRl5xB9+lwW/xekkUV7U1UtT7dkjWjYDZaPBA61BMPNGG4WQr2W11bHkFlt4dR2Xem1ZqSqP
+e97Dh4kQmUlzeMg9vVE1dCrV8X5pGyq7O70luJpaPXJhkGaH7gzWTdQRdAtq/gsD/KNVV4n+Ssuu
+WxcFyPKNIzFTONItaj+CuY0IavdeQXRuwxF+B6wpYJE/OMpXEA29MC/HpeZBoNquBYeaoKRlbEwJ
+DIm6uNO5wJOKMPqN5ZprFQFOZ6raYlY+hAhm0sQ2fac+EPyI4NSA5QC9qvNOBqN6avlicuMJT+ub
+DgEj8Z+7fNzcbBGXJbLytGMU0gYqZ4yD9c7qB9iaah7s5Aq7KkzrCWA5zspi2C5u
+-----END CERTIFICATE-----
+
+GeoTrust Primary Certification Authority
+========================================
+-----BEGIN CERTIFICATE-----
+MIIDfDCCAmSgAwIBAgIQGKy1av1pthU6Y2yv2vrEoTANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQG
+EwJVUzEWMBQGA1UEChMNR2VvVHJ1c3QgSW5jLjExMC8GA1UEAxMoR2VvVHJ1c3QgUHJpbWFyeSBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNjExMjcwMDAwMDBaFw0zNjA3MTYyMzU5NTlaMFgx
+CzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTEwLwYDVQQDEyhHZW9UcnVzdCBQ
+cmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAvrgVe//UfH1nrYNke8hCUy3f9oQIIGHWAVlqnEQRr+92/ZV+zmEwu3qDXwK9AWbK7hWN
+b6EwnL2hhZ6UOvNWiAAxz9juapYC2e0DjPt1befquFUWBRaa9OBesYjAZIVcFU2Ix7e64HXprQU9
+nceJSOC7KMgD4TCTZF5SwFlwIjVXiIrxlQqD17wxcwE07e9GceBrAqg1cmuXm2bgyxx5X9gaBGge
+RwLmnWDiNpcB3841kt++Z8dtd1k7j53WkBWUvEI0EME5+bEnPn7WinXFsq+W06Lem+SYvn3h6YGt
+tm/81w7a4DSwDRp35+MImO9Y+pyEtzavwt+s0vQQBnBxNQIDAQABo0IwQDAPBgNVHRMBAf8EBTAD
+AQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQULNVQQZcVi/CPNmFbSvtr2ZnJM5IwDQYJKoZI
+hvcNAQEFBQADggEBAFpwfyzdtzRP9YZRqSa+S7iq8XEN3GHHoOo0Hnp3DwQ16CePbJC/kRYkRj5K
+Ts4rFtULUh38H2eiAkUxT87z+gOneZ1TatnaYzr4gNfTmeGl4b7UVXGYNTq+k+qurUKykG/g/CFN
+NWMziUnWm07Kx+dOCQD32sfvmWKZd7aVIl6KoKv0uHiYyjgZmclynnjNS6yvGaBzEi38wkG6gZHa
+Floxt/m0cYASSJlyc1pZU8FjUjPtp8nSOQJw+uCxQmYpqptR7TBUIhRf2asdweSU8Pj1K/fqynhG
+1riR/aYNKxoUAT6A8EKglQdebc3MS6RFjasS6LPeWuWgfOgPIh1a6Vk=
+-----END CERTIFICATE-----
+
+thawte Primary Root CA
+======================
+-----BEGIN CERTIFICATE-----
+MIIEIDCCAwigAwIBAgIQNE7VVyDV7exJ9C/ON9srbTANBgkqhkiG9w0BAQUFADCBqTELMAkGA1UE
+BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
+aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMTFnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwHhcNMDYxMTE3
+MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCBqTELMAkGA1UEBhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwg
+SW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMv
+KGMpIDIwMDYgdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxHzAdBgNVBAMT
+FnRoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCs
+oPD7gFnUnMekz52hWXMJEEUMDSxuaPFsW0hoSVk3/AszGcJ3f8wQLZU0HObrTQmnHNK4yZc2AreJ
+1CRfBsDMRJSUjQJib+ta3RGNKJpchJAQeg29dGYvajig4tVUROsdB58Hum/u6f1OCyn1PoSgAfGc
+q/gcfomk6KHYcWUNo1F77rzSImANuVud37r8UVsLr5iy6S7pBOhih94ryNdOwUxkHt3Ph1i6Sk/K
+aAcdHJ1KxtUvkcx8cXIcxcBn6zL9yZJclNqFwJu/U30rCfSMnZEfl2pSy94JNqR32HuHUETVPm4p
+afs5SSYeCaWAe0At6+gnhcn+Yf1+5nyXHdWdAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wDgYD
+VR0PAQH/BAQDAgEGMB0GA1UdDgQWBBR7W0XPr87Lev0xkhpqtvNG61dIUDANBgkqhkiG9w0BAQUF
+AAOCAQEAeRHAS7ORtvzw6WfUDW5FvlXok9LOAz/t2iWwHVfLHjp2oEzsUHboZHIMpKnxuIvW1oeE
+uzLlQRHAd9mzYJ3rG9XRbkREqaYB7FViHXe4XI5ISXycO1cRrK1zN44veFyQaEfZYGDm/Ac9IiAX
+xPcW6cTYcvnIc3zfFi8VqT79aie2oetaupgf1eNNZAqdE8hhuvU5HIe6uL17In/2/qxAeeWsEG89
+jxt5dovEN7MhGITlNgDrYyCZuen+MwS7QcjBAvlEYyCegc5C09Y/LHbTY5xZ3Y+m4Q6gLkH3LpVH
+z7z9M/P2C2F+fpErgUfCJzDupxBdN49cOSvkBPB7jVaMaA==
+-----END CERTIFICATE-----
+
+VeriSign Class 3 Public Primary Certification Authority - G5
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIE0zCCA7ugAwIBAgIQGNrRniZ96LtKIVjNzGs7SjANBgkqhkiG9w0BAQUFADCByjELMAkGA1UE
+BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
+ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
+IHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRp
+ZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwHhcNMDYxMTA4MDAwMDAwWhcNMzYwNzE2MjM1OTU5WjCB
+yjELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2ln
+biBUcnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNiBWZXJpU2lnbiwgSW5jLiAtIEZvciBh
+dXRob3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmlt
+YXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzUwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQCvJAgIKXo1nmAMqudLO07cfLw8RRy7K+D+KQL5VwijZIUVJ/XxrcgxiV0i6CqqpkKz
+j/i5Vbext0uz/o9+B1fs70PbZmIVYc9gDaTY3vjgw2IIPVQT60nKWVSFJuUrjxuf6/WhkcIzSdhD
+Y2pSS9KP6HBRTdGJaXvHcPaz3BJ023tdS1bTlr8Vd6Gw9KIl8q8ckmcY5fQGBO+QueQA5N06tRn/
+Arr0PO7gi+s3i+z016zy9vA9r911kTMZHRxAy3QkGSGT2RT+rCpSx4/VBEnkjWNHiDxpg8v+R70r
+fk/Fla4OndTRQ8Bnc+MUCH7lP59zuDMKz10/NIeWiu5T6CUVAgMBAAGjgbIwga8wDwYDVR0TAQH/
+BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2Uv
+Z2lmMCEwHzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVy
+aXNpZ24uY29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFH/TZafC3ey78DAJ80M5+gKvMzEzMA0GCSqG
+SIb3DQEBBQUAA4IBAQCTJEowX2LP2BqYLz3q3JktvXf2pXkiOOzEp6B4Eq1iDkVwZMXnl2YtmAl+
+X6/WzChl8gGqCBpH3vn5fJJaCGkgDdk+bW48DW7Y5gaRQBi5+MHt39tBquCWIMnNZBU4gcmU7qKE
+KQsTb47bDN0lAtukixlE0kF6BWlKWE9gyn6CagsCqiUXObXbf+eEZSqVir2G3l6BFoMtEMze/aiC
+Km0oHw0LxOXnGiYZ4fQRbxC1lfznQgUy286dUV4otp6F01vvpX1FQHKOtw5rDgb7MzVIcbidJ4vE
+ZV8NhnacRHr2lVz2XTIIM6RUthg/aFzyQkqFOFSDX9HoLPKsEdao7WNq
+-----END CERTIFICATE-----
+
+SecureTrust CA
+==============
+-----BEGIN CERTIFICATE-----
+MIIDuDCCAqCgAwIBAgIQDPCOXAgWpa1Cf/DrJxhZ0DANBgkqhkiG9w0BAQUFADBIMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xFzAVBgNVBAMTDlNlY3VyZVRy
+dXN0IENBMB4XDTA2MTEwNzE5MzExOFoXDTI5MTIzMTE5NDA1NVowSDELMAkGA1UEBhMCVVMxIDAe
+BgNVBAoTF1NlY3VyZVRydXN0IENvcnBvcmF0aW9uMRcwFQYDVQQDEw5TZWN1cmVUcnVzdCBDQTCC
+ASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAKukgeWVzfX2FI7CT8rU4niVWJxB4Q2ZQCQX
+OZEzZum+4YOvYlyJ0fwkW2Gz4BERQRwdbvC4u/jep4G6pkjGnx29vo6pQT64lO0pGtSO0gMdA+9t
+DWccV9cGrcrI9f4Or2YlSASWC12juhbDCE/RRvgUXPLIXgGZbf2IzIaowW8xQmxSPmjL8xk037uH
+GFaAJsTQ3MBv396gwpEWoGQRS0S8Hvbn+mPeZqx2pHGj7DaUaHp3pLHnDi+BeuK1cobvomuL8A/b
+01k/unK8RCSc43Oz969XL0Imnal0ugBS8kvNU3xHCzaFDmapCJcWNFfBZveA4+1wVMeT4C4oFVmH
+ursCAwEAAaOBnTCBmjATBgkrBgEEAYI3FAIEBh4EAEMAQTALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/
+BAUwAwEB/zAdBgNVHQ4EFgQUQjK2FvoE/f5dS3rD/fdMQB1aQ68wNAYDVR0fBC0wKzApoCegJYYj
+aHR0cDovL2NybC5zZWN1cmV0cnVzdC5jb20vU1RDQS5jcmwwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
+KoZIhvcNAQEFBQADggEBADDtT0rhWDpSclu1pqNlGKa7UTt36Z3q059c4EVlew3KW+JwULKUBRSu
+SceNQQcSc5R+DCMh/bwQf2AQWnL1mA6s7Ll/3XpvXdMc9P+IBWlCqQVxyLesJugutIxq/3HcuLHf
+mbx8IVQr5Fiiu1cprp6poxkmD5kuCLDv/WnPmRoJjeOnnyvJNjR7JLN4TJUXpAYmHrZkUjZfYGfZ
+nMUFdAvnZyPSCPyI6a6Lf+Ew9Dd+/cYy2i2eRDAwbO4H3tI0/NL/QPZL9GZGBlSm8jIKYyYwa5vR
+3ItHuuG51WLQoqD0ZwV4KWMabwTW+MZMo5qxN7SN5ShLHZ4swrhovO0C7jE=
+-----END CERTIFICATE-----
+
+Secure Global CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDvDCCAqSgAwIBAgIQB1YipOjUiolN9BPI8PjqpTANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQG
+EwJVUzEgMB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBH
+bG9iYWwgQ0EwHhcNMDYxMTA3MTk0MjI4WhcNMjkxMjMxMTk1MjA2WjBKMQswCQYDVQQGEwJVUzEg
+MB4GA1UEChMXU2VjdXJlVHJ1c3QgQ29ycG9yYXRpb24xGTAXBgNVBAMTEFNlY3VyZSBHbG9iYWwg
+Q0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCvNS7YrGxVaQZx5RNoJLNP2MwhR/jx
+YDiJiQPpvepeRlMJ3Fz1Wuj3RSoC6zFh1ykzTM7HfAo3fg+6MpjhHZevj8fcyTiW89sa/FHtaMbQ
+bqR8JNGuQsiWUGMu4P51/pinX0kuleM5M2SOHqRfkNJnPLLZ/kG5VacJjnIFHovdRIWCQtBJwB1g
+8NEXLJXr9qXBkqPFwqcIYA1gBBCWeZ4WNOaptvolRTnIHmX5k/Wq8VLcmZg9pYYaDDUz+kulBAYV
+HDGA76oYa8J719rO+TMg1fW9ajMtgQT7sFzUnKPiXB3jqUJ1XnvUd+85VLrJChgbEplJL4hL/VBi
+0XPnj3pDAgMBAAGjgZ0wgZowEwYJKwYBBAGCNxQCBAYeBABDAEEwCwYDVR0PBAQDAgGGMA8GA1Ud
+EwEB/wQFMAMBAf8wHQYDVR0OBBYEFK9EBMJBfkiD2045AuzshHrmzsmkMDQGA1UdHwQtMCswKaAn
+oCWGI2h0dHA6Ly9jcmwuc2VjdXJldHJ1c3QuY29tL1NHQ0EuY3JsMBAGCSsGAQQBgjcVAQQDAgEA
+MA0GCSqGSIb3DQEBBQUAA4IBAQBjGghAfaReUw132HquHw0LURYD7xh8yOOvaliTFGCRsoTciE6+
+OYo68+aCiV0BN7OrJKQVDpI1WkpEXk5X+nXOH0jOZvQ8QCaSmGwb7iRGDBezUqXbpZGRzzfTb+cn
+CDpOGR86p1hcF895P4vkp9MmI50mD1hp/Ed+stCNi5O/KU9DaXR2Z0vPB4zmAve14bRDtUstFJ/5
+3CYNv6ZHdAbYiNE6KTCEztI5gGIbqMdXSbxqVVFnFUq+NQfk1XWYN3kwFNspnWzFacxHVaIw98xc
+f8LDmBxrThaA63p4ZUWiABqvDA1VZDRIuJK58bRQKfJPIx/abKwfROHdI3hRW8cW
+-----END CERTIFICATE-----
+
+COMODO Certification Authority
+==============================
+-----BEGIN CERTIFICATE-----
+MIIEHTCCAwWgAwIBAgIQToEtioJl4AsC7j41AkblPTANBgkqhkiG9w0BAQUFADCBgTELMAkGA1UE
+BhMCR0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgG
+A1UEChMRQ09NT0RPIENBIExpbWl0ZWQxJzAlBgNVBAMTHkNPTU9ETyBDZXJ0aWZpY2F0aW9uIEF1
+dGhvcml0eTAeFw0wNjEyMDEwMDAwMDBaFw0yOTEyMzEyMzU5NTlaMIGBMQswCQYDVQQGEwJHQjEb
+MBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFD
+T01PRE8gQ0EgTGltaXRlZDEnMCUGA1UEAxMeQ09NT0RPIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA0ECLi3LjkRv3UcEbVASY06m/weaKXTuH
++7uIzg3jLz8GlvCiKVCZrts7oVewdFFxze1CkU1B/qnI2GqGd0S7WWaXUF601CxwRM/aN5VCaTww
+xHGzUvAhTaHYujl8HJ6jJJ3ygxaYqhZ8Q5sVW7euNJH+1GImGEaaP+vB+fGQV+useg2L23IwambV
+4EajcNxo2f8ESIl33rXp+2dtQem8Ob0y2WIC8bGoPW43nOIv4tOiJovGuFVDiOEjPqXSJDlqR6sA
+1KGzqSX+DT+nHbrTUcELpNqsOO9VUCQFZUaTNE8tja3G1CEZ0o7KBWFxB3NH5YoZEr0ETc5OnKVI
+rLsm9wIDAQABo4GOMIGLMB0GA1UdDgQWBBQLWOWLxkwVN6RAqTCpIb5HNlpW/zAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zBJBgNVHR8EQjBAMD6gPKA6hjhodHRwOi8vY3JsLmNvbW9k
+b2NhLmNvbS9DT01PRE9DZXJ0aWZpY2F0aW9uQXV0aG9yaXR5LmNybDANBgkqhkiG9w0BAQUFAAOC
+AQEAPpiem/Yb6dc5t3iuHXIYSdOH5EOC6z/JqvWote9VfCFSZfnVDeFs9D6Mk3ORLgLETgdxb8CP
+OGEIqB6BCsAvIC9Bi5HcSEW88cbeunZrM8gALTFGTO3nnc+IlP8zwFboJIYmuNg4ON8qa90SzMc/
+RxdMosIGlgnW2/4/PEZB31jiVg88O8EckzXZOFKs7sjsLjBOlDW0JB9LeGna8gI4zJVSk/BwJVmc
+IGfE7vmLV2H0knZ9P4SNVbfo5azV8fUZVqZa+5Acr5Pr5RzUZ5ddBA6+C4OmF4O5MBKgxTMVBbkN
++8cFduPYSo38NBejxiEovjBFMR7HeL5YYTisO+IBZQ==
+-----END CERTIFICATE-----
+
+Network Solutions Certificate Authority
+=======================================
+-----BEGIN CERTIFICATE-----
+MIID5jCCAs6gAwIBAgIQV8szb8JcFuZHFhfjkDFo4DANBgkqhkiG9w0BAQUFADBiMQswCQYDVQQG
+EwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMuMTAwLgYDVQQDEydOZXR3b3Jr
+IFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcNMDYxMjAxMDAwMDAwWhcNMjkxMjMx
+MjM1OTU5WjBiMQswCQYDVQQGEwJVUzEhMB8GA1UEChMYTmV0d29yayBTb2x1dGlvbnMgTC5MLkMu
+MTAwLgYDVQQDEydOZXR3b3JrIFNvbHV0aW9ucyBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDkvH6SMG3G2I4rC7xGzuAnlt7e+foS0zwzc7MEL7xx
+jOWftiJgPl9dzgn/ggwbmlFQGiaJ3dVhXRncEg8tCqJDXRfQNJIg6nPPOCwGJgl6cvf6UDL4wpPT
+aaIjzkGxzOTVHzbRijr4jGPiFFlp7Q3Tf2vouAPlT2rlmGNpSAW+Lv8ztumXWWn4Zxmuk2GWRBXT
+crA/vGp97Eh/jcOrqnErU2lBUzS1sLnFBgrEsEX1QV1uiUV7PTsmjHTC5dLRfbIR1PtYMiKagMnc
+/Qzpf14Dl847ABSHJ3A4qY5usyd2mFHgBeMhqxrVhSI8KbWaFsWAqPS7azCPL0YCorEMIuDTAgMB
+AAGjgZcwgZQwHQYDVR0OBBYEFCEwyfsA106Y2oeqKtCnLrFAMadMMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MFIGA1UdHwRLMEkwR6BFoEOGQWh0dHA6Ly9jcmwubmV0c29sc3NsLmNv
+bS9OZXR3b3JrU29sdXRpb25zQ2VydGlmaWNhdGVBdXRob3JpdHkuY3JsMA0GCSqGSIb3DQEBBQUA
+A4IBAQC7rkvnt1frf6ott3NHhWrB5KUd5Oc86fRZZXe1eltajSU24HqXLjjAV2CDmAaDn7l2em5Q
+4LqILPxFzBiwmZVRDuwduIj/h1AcgsLj4DKAv6ALR8jDMe+ZZzKATxcheQxpXN5eNK4CtSbqUN9/
+GGUsyfJj4akH/nxxH2szJGoeBfcFaMBqEssuXmHLrijTfsK0ZpEmXzwuJF/LWA/rKOyvEZbz3Htv
+wKeI8lN3s2Berq4o2jUsbzRF0ybh3uxbTydrFny9RAQYgrOJeRcQcT16ohZO9QHNpGxlaKFJdlxD
+ydi8NmdspZS11My5vWo1ViHe2MPr+8ukYEywVaCge1ey
+-----END CERTIFICATE-----
+
+WellsSecure Public Root Certificate Authority
+=============================================
+-----BEGIN CERTIFICATE-----
+MIIEvTCCA6WgAwIBAgIBATANBgkqhkiG9w0BAQUFADCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoM
+F1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYw
+NAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwHhcN
+MDcxMjEzMTcwNzU0WhcNMjIxMjE0MDAwNzU0WjCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dl
+bGxzIEZhcmdvIFdlbGxzU2VjdXJlMRwwGgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYD
+VQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDub7S9eeKPCCGeOARBJe+rWxxTkqxtnt3CxC5FlAM1
+iGd0V+PfjLindo8796jE2yljDpFoNoqXjopxaAkH5OjUDk/41itMpBb570OYj7OeUt9tkTmPOL13
+i0Nj67eT/DBMHAGTthP796EfvyXhdDcsHqRePGj4S78NuR4uNuip5Kf4D8uCdXw1LSLWwr8L87T8
+bJVhHlfXBIEyg1J55oNjz7fLY4sR4r1e6/aN7ZVyKLSsEmLpSjPmgzKuBXWVvYSV2ypcm44uDLiB
+K0HmOFafSZtsdvqKXfcBeYF8wYNABf5x/Qw/zE5gCQ5lRxAvAcAFP4/4s0HvWkJ+We/SlwxlAgMB
+AAGjggE0MIIBMDAPBgNVHRMBAf8EBTADAQH/MDkGA1UdHwQyMDAwLqAsoCqGKGh0dHA6Ly9jcmwu
+cGtpLndlbGxzZmFyZ28uY29tL3dzcHJjYS5jcmwwDgYDVR0PAQH/BAQDAgHGMB0GA1UdDgQWBBQm
+lRkQ2eihl5H/3BnZtQQ+0nMKajCBsgYDVR0jBIGqMIGngBQmlRkQ2eihl5H/3BnZtQQ+0nMKaqGB
+i6SBiDCBhTELMAkGA1UEBhMCVVMxIDAeBgNVBAoMF1dlbGxzIEZhcmdvIFdlbGxzU2VjdXJlMRww
+GgYDVQQLDBNXZWxscyBGYXJnbyBCYW5rIE5BMTYwNAYDVQQDDC1XZWxsc1NlY3VyZSBQdWJsaWMg
+Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHmCAQEwDQYJKoZIhvcNAQEFBQADggEBALkVsUSRzCPI
+K0134/iaeycNzXK7mQDKfGYZUMbVmO2rvwNa5U3lHshPcZeG1eMd/ZDJPHV3V3p9+N701NX3leZ0
+bh08rnyd2wIDBSxxSyU+B+NemvVmFymIGjifz6pBA4SXa5M4esowRBskRDPQ5NHcKDj0E0M1NSlj
+qHyita04pO2t/caaH/+Xc/77szWnk4bGdpEA5qxRFsQnMlzbc9qlk1eOPm01JghZ1edE13YgY+es
+E2fDbbFwRnzVlhE9iW9dqKHrjQrawx0zbKPqZxmamX9LPYNRKh3KL4YMon4QLSvUFpULB6ouFJJJ
+tylv2G0xffX8oRAHh84vWdw+WNs=
+-----END CERTIFICATE-----
+
+COMODO ECC Certification Authority
+==================================
+-----BEGIN CERTIFICATE-----
+MIICiTCCAg+gAwIBAgIQH0evqmIAcFBUTAGem2OZKjAKBggqhkjOPQQDAzCBhTELMAkGA1UEBhMC
+R0IxGzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UE
+ChMRQ09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBB
+dXRob3JpdHkwHhcNMDgwMzA2MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCBhTELMAkGA1UEBhMCR0Ix
+GzAZBgNVBAgTEkdyZWF0ZXIgTWFuY2hlc3RlcjEQMA4GA1UEBxMHU2FsZm9yZDEaMBgGA1UEChMR
+Q09NT0RPIENBIExpbWl0ZWQxKzApBgNVBAMTIkNPTU9ETyBFQ0MgQ2VydGlmaWNhdGlvbiBBdXRo
+b3JpdHkwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAAQDR3svdcmCFYX7deSRFtSrYpn1PlILBs5BAH+X
+4QokPB0BBO490o0JlwzgdeT6+3eKKvUDYEs2ixYjFq0JcfRK9ChQtP6IHG4/bC8vCVlbpVsLM5ni
+wz2J+Wos77LTBumjQjBAMB0GA1UdDgQWBBR1cacZSBm8nZ3qQUfflMRId5nTeTAOBgNVHQ8BAf8E
+BAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAKBggqhkjOPQQDAwNoADBlAjEA7wNbeqy3eApyt4jf/7VG
+FAkK+qDmfQjGGoe9GKhzvSbKYAydzpmfz1wPMOG+FDHqAjAU9JM8SaczepBGR7NjfRObTrdvGDeA
+U/7dIOA1mjbRxwG55tzd8/8dLDoWV9mSOdY=
+-----END CERTIFICATE-----
+
+IGC/A
+=====
+-----BEGIN CERTIFICATE-----
+MIIEAjCCAuqgAwIBAgIFORFFEJQwDQYJKoZIhvcNAQEFBQAwgYUxCzAJBgNVBAYTAkZSMQ8wDQYD
+VQQIEwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVE
+Q1NTSTEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZy
+MB4XDTAyMTIxMzE0MjkyM1oXDTIwMTAxNzE0MjkyMlowgYUxCzAJBgNVBAYTAkZSMQ8wDQYDVQQI
+EwZGcmFuY2UxDjAMBgNVBAcTBVBhcmlzMRAwDgYDVQQKEwdQTS9TR0ROMQ4wDAYDVQQLEwVEQ1NT
+STEOMAwGA1UEAxMFSUdDL0ExIzAhBgkqhkiG9w0BCQEWFGlnY2FAc2dkbi5wbS5nb3V2LmZyMIIB
+IjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsh/R0GLFMzvABIaIs9z4iPf930Pfeo2aSVz2
+TqrMHLmh6yeJ8kbpO0px1R2OLc/mratjUMdUC24SyZA2xtgv2pGqaMVy/hcKshd+ebUyiHDKcMCW
+So7kVc0dJ5S/znIq7Fz5cyD+vfcuiWe4u0dzEvfRNWk68gq5rv9GQkaiv6GFGvm/5P9JhfejcIYy
+HF2fYPepraX/z9E0+X1bF8bc1g4oa8Ld8fUzaJ1O/Id8NhLWo4DoQw1VYZTqZDdH6nfK0LJYBcNd
+frGoRpAxVs5wKpayMLh35nnAvSk7/ZR3TL0gzUEl4C7HG7vupARB0l2tEmqKm0f7yd1GQOGdPDPQ
+tQIDAQABo3cwdTAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIBRjAVBgNVHSAEDjAMMAoGCCqB
+egF5AQEBMB0GA1UdDgQWBBSjBS8YYFDCiQrdKyFP/45OqDAxNjAfBgNVHSMEGDAWgBSjBS8YYFDC
+iQrdKyFP/45OqDAxNjANBgkqhkiG9w0BAQUFAAOCAQEABdwm2Pp3FURo/C9mOnTgXeQp/wYHE4RK
+q89toB9RlPhJy3Q2FLwV3duJL92PoF189RLrn544pEfMs5bZvpwlqwN+Mw+VgQ39FuCIvjfwbF3Q
+MZsyK10XZZOYYLxuj7GoPB7ZHPOpJkL5ZB3C55L29B5aqhlSXa/oovdgoPaN8In1buAKBQGVyYsg
+Crpa/JosPL3Dt8ldeCUFP1YUmwza+zpI/pdpXsoQhvdOlgQITeywvl3cO45Pwf2aNjSaTFR+FwNI
+lQgRHAdvhQh+XU3Endv7rs6y0bO4g2wdsrN58dhwmX7wEwLOXt1R0982gaEbeC9xs/FZTEYYKKuF
+0mBWWg==
+-----END CERTIFICATE-----
+
+Security Communication EV RootCA1
+=================================
+-----BEGIN CERTIFICATE-----
+MIIDfTCCAmWgAwIBAgIBADANBgkqhkiG9w0BAQUFADBgMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
+U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEqMCgGA1UECxMhU2VjdXJpdHkgQ29tbXVuaWNh
+dGlvbiBFViBSb290Q0ExMB4XDTA3MDYwNjAyMTIzMloXDTM3MDYwNjAyMTIzMlowYDELMAkGA1UE
+BhMCSlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xKjAoBgNVBAsTIVNl
+Y3VyaXR5IENvbW11bmljYXRpb24gRVYgUm9vdENBMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALx/7FebJOD+nLpCeamIivqA4PUHKUPqjgo0No0c+qe1OXj/l3X3L+SqawSERMqm4miO
+/VVQYg+kcQ7OBzgtQoVQrTyWb4vVog7P3kmJPdZkLjjlHmy1V4qe70gOzXppFodEtZDkBp2uoQSX
+WHnvIEqCa4wiv+wfD+mEce3xDuS4GBPMVjZd0ZoeUWs5bmB2iDQL87PRsJ3KYeJkHcFGB7hj3R4z
+ZbOOCVVSPbW9/wfrrWFVGCypaZhKqkDFMxRldAD5kd6vA0jFQFTcD4SQaCDFkpbcLuUCRarAX1T4
+bepJz11sS6/vmsJWXMY1VkJqMF/Cq/biPT+zyRGPMUzXn0kCAwEAAaNCMEAwHQYDVR0OBBYEFDVK
+9U2vP9eCOKyrcWUXdYydVZPmMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqG
+SIb3DQEBBQUAA4IBAQCoh+ns+EBnXcPBZsdAS5f8hxOQWsTvoMpfi7ent/HWtWS3irO4G8za+6xm
+iEHO6Pzk2x6Ipu0nUBsCMCRGef4Eh3CXQHPRwMFXGZpppSeZq51ihPZRwSzJIxXYKLerJRO1RuGG
+Av8mjMSIkh1W/hln8lXkgKNrnKt34VFxDSDbEJrbvXZ5B3eZKK2aXtqxT0QsNY6llsf9g/BYxnnW
+mHyojf6GPgcWkuF75x3sM3Z+Qi5KhfmRiWiEA4Glm5q+4zfFVKtWOxgtQaQM+ELbmaDgcm+7XeEW
+T1MKZPlO9L9OVL14bIjqv5wTJMJwaaJ/D8g8rQjJsJhAoyrniIPtd490
+-----END CERTIFICATE-----
+
+OISTE WISeKey Global Root GA CA
+===============================
+-----BEGIN CERTIFICATE-----
+MIID8TCCAtmgAwIBAgIQQT1yx/RrH4FDffHSKFTfmjANBgkqhkiG9w0BAQUFADCBijELMAkGA1UE
+BhMCQ0gxEDAOBgNVBAoTB1dJU2VLZXkxGzAZBgNVBAsTEkNvcHlyaWdodCAoYykgMjAwNTEiMCAG
+A1UECxMZT0lTVEUgRm91bmRhdGlvbiBFbmRvcnNlZDEoMCYGA1UEAxMfT0lTVEUgV0lTZUtleSBH
+bG9iYWwgUm9vdCBHQSBDQTAeFw0wNTEyMTExNjAzNDRaFw0zNzEyMTExNjA5NTFaMIGKMQswCQYD
+VQQGEwJDSDEQMA4GA1UEChMHV0lTZUtleTEbMBkGA1UECxMSQ29weXJpZ2h0IChjKSAyMDA1MSIw
+IAYDVQQLExlPSVNURSBGb3VuZGF0aW9uIEVuZG9yc2VkMSgwJgYDVQQDEx9PSVNURSBXSVNlS2V5
+IEdsb2JhbCBSb290IEdBIENBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAy0+zAJs9
+Nt350UlqaxBJH+zYK7LG+DKBKUOVTJoZIyEVRd7jyBxRVVuuk+g3/ytr6dTqvirdqFEr12bDYVxg
+Asj1znJ7O7jyTmUIms2kahnBAbtzptf2w93NvKSLtZlhuAGio9RN1AU9ka34tAhxZK9w8RxrfvbD
+d50kc3vkDIzh2TbhmYsFmQvtRTEJysIA2/dyoJaqlYfQjse2YXMNdmaM3Bu0Y6Kff5MTMPGhJ9vZ
+/yxViJGg4E8HsChWjBgbl0SOid3gF27nKu+POQoxhILYQBRJLnpB5Kf+42TMwVlxSywhp1t94B3R
+LoGbw9ho972WG6xwsRYUC9tguSYBBQIDAQABo1EwTzALBgNVHQ8EBAMCAYYwDwYDVR0TAQH/BAUw
+AwEB/zAdBgNVHQ4EFgQUswN+rja8sHnR3JQmthG+IbJphpQwEAYJKwYBBAGCNxUBBAMCAQAwDQYJ
+KoZIhvcNAQEFBQADggEBAEuh/wuHbrP5wUOxSPMowB0uyQlB+pQAHKSkq0lPjz0e701vvbyk9vIm
+MMkQyh2I+3QZH4VFvbBsUfk2ftv1TDI6QU9bR8/oCy22xBmddMVHxjtqD6wU2zz0c5ypBd8A3HR4
++vg1YFkCExh8vPtNsCBtQ7tgMHpnM1zFmdH4LTlSc/uMqpclXHLZCB6rTjzjgTGfA6b7wP4piFXa
+hNVQA7bihKOmNqoROgHhGEvWRGizPflTdISzRpFGlgC3gCy24eMQ4tui5yiPAZZiFj4A4xylNoEY
+okxSdsARo27mHbrjWr42U8U+dY+GaSlYU7Wcu2+fXMUY7N0v4ZjJ/L7fCg0=
+-----END CERTIFICATE-----
+
+S-TRUST Authentication and Encryption Root CA 2005 PN
+=====================================================
+-----BEGIN CERTIFICATE-----
+MIIEezCCA2OgAwIBAgIQNxkY5lNUfBq1uMtZWts1tzANBgkqhkiG9w0BAQUFADCBrjELMAkGA1UE
+BhMCREUxIDAeBgNVBAgTF0JhZGVuLVd1ZXJ0dGVtYmVyZyAoQlcpMRIwEAYDVQQHEwlTdHV0dGdh
+cnQxKTAnBgNVBAoTIERldXRzY2hlciBTcGFya2Fzc2VuIFZlcmxhZyBHbWJIMT4wPAYDVQQDEzVT
+LVRSVVNUIEF1dGhlbnRpY2F0aW9uIGFuZCBFbmNyeXB0aW9uIFJvb3QgQ0EgMjAwNTpQTjAeFw0w
+NTA2MjIwMDAwMDBaFw0zMDA2MjEyMzU5NTlaMIGuMQswCQYDVQQGEwJERTEgMB4GA1UECBMXQmFk
+ZW4tV3VlcnR0ZW1iZXJnIChCVykxEjAQBgNVBAcTCVN0dXR0Z2FydDEpMCcGA1UEChMgRGV1dHNj
+aGVyIFNwYXJrYXNzZW4gVmVybGFnIEdtYkgxPjA8BgNVBAMTNVMtVFJVU1QgQXV0aGVudGljYXRp
+b24gYW5kIEVuY3J5cHRpb24gUm9vdCBDQSAyMDA1OlBOMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEA2bVKwdMz6tNGs9HiTNL1toPQb9UY6ZOvJ44TzbUlNlA0EmQpoVXhOmCTnijJ4/Ob
+4QSwI7+Vio5bG0F/WsPoTUzVJBY+h0jUJ67m91MduwwA7z5hca2/OnpYH5Q9XIHV1W/fuJvS9eXL
+g3KSwlOyggLrra1fFi2SU3bxibYs9cEv4KdKb6AwajLrmnQDaHgTncovmwsdvs91DSaXm8f1Xgqf
+eN+zvOyauu9VjxuapgdjKRdZYgkqeQd3peDRF2npW932kKvimAoA0SVtnteFhy+S8dF2g08LOlk3
+KC8zpxdQ1iALCvQm+Z845y2kuJuJja2tyWp9iRe79n+Ag3rm7QIDAQABo4GSMIGPMBIGA1UdEwEB
+/wQIMAYBAf8CAQAwDgYDVR0PAQH/BAQDAgEGMCkGA1UdEQQiMCCkHjAcMRowGAYDVQQDExFTVFJv
+bmxpbmUxLTIwNDgtNTAdBgNVHQ4EFgQUD8oeXHngovMpttKFswtKtWXsa1IwHwYDVR0jBBgwFoAU
+D8oeXHngovMpttKFswtKtWXsa1IwDQYJKoZIhvcNAQEFBQADggEBAK8B8O0ZPCjoTVy7pWMciDMD
+pwCHpB8gq9Yc4wYfl35UvbfRssnV2oDsF9eK9XvCAPbpEW+EoFolMeKJ+aQAPzFoLtU96G7m1R08
+P7K9n3frndOMusDXtk3sU5wPBG7qNWdX4wple5A64U8+wwCSersFiXOMy6ZNwPv2AtawB6MDwidA
+nwzkhYItr5pCHdDHjfhA7p0GVxzZotiAFP7hYy0yh9WUUpY6RsZxlj33mA6ykaqP2vROJAA5Veit
+F7nTNCtKqUDMFypVZUF0Qn71wK/Ik63yGFs9iQzbRzkk+OBM8h+wPQrKBU6JIRrjKpms/H+h8Q8b
+Hz2eBIPdltkdOpQ=
+-----END CERTIFICATE-----
+
+Microsec e-Szigno Root CA
+=========================
+-----BEGIN CERTIFICATE-----
+MIIHqDCCBpCgAwIBAgIRAMy4579OKRr9otxmpRwsDxEwDQYJKoZIhvcNAQEFBQAwcjELMAkGA1UE
+BhMCSFUxETAPBgNVBAcTCEJ1ZGFwZXN0MRYwFAYDVQQKEw1NaWNyb3NlYyBMdGQuMRQwEgYDVQQL
+EwtlLVN6aWdubyBDQTEiMCAGA1UEAxMZTWljcm9zZWMgZS1Temlnbm8gUm9vdCBDQTAeFw0wNTA0
+MDYxMjI4NDRaFw0xNzA0MDYxMjI4NDRaMHIxCzAJBgNVBAYTAkhVMREwDwYDVQQHEwhCdWRhcGVz
+dDEWMBQGA1UEChMNTWljcm9zZWMgTHRkLjEUMBIGA1UECxMLZS1Temlnbm8gQ0ExIjAgBgNVBAMT
+GU1pY3Jvc2VjIGUtU3ppZ25vIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIB
+AQDtyADVgXvNOABHzNuEwSFpLHSQDCHZU4ftPkNEU6+r+ICbPHiN1I2uuO/TEdyB5s87lozWbxXG
+d36hL+BfkrYn13aaHUM86tnsL+4582pnS4uCzyL4ZVX+LMsvfUh6PXX5qqAnu3jCBspRwn5mS6/N
+oqdNAoI/gqyFxuEPkEeZlApxcpMqyabAvjxWTHOSJ/FrtfX9/DAFYJLG65Z+AZHCabEeHXtTRbjc
+QR/Ji3HWVBTji1R4P770Yjtb9aPs1ZJ04nQw7wHb4dSrmZsqa/i9phyGI0Jf7Enemotb9HI6QMVJ
+PqW+jqpx62z69Rrkav17fVVA71hu5tnVvCSrwe+3AgMBAAGjggQ3MIIEMzBnBggrBgEFBQcBAQRb
+MFkwKAYIKwYBBQUHMAGGHGh0dHBzOi8vcmNhLmUtc3ppZ25vLmh1L29jc3AwLQYIKwYBBQUHMAKG
+IWh0dHA6Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNydDAPBgNVHRMBAf8EBTADAQH/MIIBcwYD
+VR0gBIIBajCCAWYwggFiBgwrBgEEAYGoGAIBAQEwggFQMCgGCCsGAQUFBwIBFhxodHRwOi8vd3d3
+LmUtc3ppZ25vLmh1L1NaU1ovMIIBIgYIKwYBBQUHAgIwggEUHoIBEABBACAAdABhAG4A+gBzAO0A
+dAB2AOEAbgB5ACAA6QByAHQAZQBsAG0AZQB6AOkAcwDpAGgAZQB6ACAA6QBzACAAZQBsAGYAbwBn
+AGEAZADhAHMA4QBoAG8AegAgAGEAIABTAHoAbwBsAGcA4QBsAHQAYQB0APMAIABTAHoAbwBsAGcA
+4QBsAHQAYQB0AOEAcwBpACAAUwB6AGEAYgDhAGwAeQB6AGEAdABhACAAcwB6AGUAcgBpAG4AdAAg
+AGsAZQBsAGwAIABlAGwAagDhAHIAbgBpADoAIABoAHQAdABwADoALwAvAHcAdwB3AC4AZQAtAHMA
+egBpAGcAbgBvAC4AaAB1AC8AUwBaAFMAWgAvMIHIBgNVHR8EgcAwgb0wgbqggbeggbSGIWh0dHA6
+Ly93d3cuZS1zemlnbm8uaHUvUm9vdENBLmNybIaBjmxkYXA6Ly9sZGFwLmUtc3ppZ25vLmh1L0NO
+PU1pY3Jvc2VjJTIwZS1Temlnbm8lMjBSb290JTIwQ0EsT1U9ZS1Temlnbm8lMjBDQSxPPU1pY3Jv
+c2VjJTIwTHRkLixMPUJ1ZGFwZXN0LEM9SFU/Y2VydGlmaWNhdGVSZXZvY2F0aW9uTGlzdDtiaW5h
+cnkwDgYDVR0PAQH/BAQDAgEGMIGWBgNVHREEgY4wgYuBEGluZm9AZS1zemlnbm8uaHWkdzB1MSMw
+IQYDVQQDDBpNaWNyb3NlYyBlLVN6aWduw7MgUm9vdCBDQTEWMBQGA1UECwwNZS1TemlnbsOzIEhT
+WjEWMBQGA1UEChMNTWljcm9zZWMgS2Z0LjERMA8GA1UEBxMIQnVkYXBlc3QxCzAJBgNVBAYTAkhV
+MIGsBgNVHSMEgaQwgaGAFMegSXUWYYTbMUuE0vE3QJDvTtz3oXakdDByMQswCQYDVQQGEwJIVTER
+MA8GA1UEBxMIQnVkYXBlc3QxFjAUBgNVBAoTDU1pY3Jvc2VjIEx0ZC4xFDASBgNVBAsTC2UtU3pp
+Z25vIENBMSIwIAYDVQQDExlNaWNyb3NlYyBlLVN6aWdubyBSb290IENBghEAzLjnv04pGv2i3Gal
+HCwPETAdBgNVHQ4EFgQUx6BJdRZhhNsxS4TS8TdAkO9O3PcwDQYJKoZIhvcNAQEFBQADggEBANMT
+nGZjWS7KXHAM/IO8VbH0jgdsZifOwTsgqRy7RlRw7lrMoHfqaEQn6/Ip3Xep1fvj1KcExJW4C+FE
+aGAHQzAxQmHl7tnlJNUb3+FKG6qfx1/4ehHqE5MAyopYse7tDk2016g2JnzgOsHVV4Lxdbb9iV/a
+86g4nzUGCM4ilb7N1fy+W955a9x6qWVmvrElWl/tftOsRm1M9DKHtCAE4Gx4sHfRhUZLphK3dehK
+yVZs15KrnfVJONJPU+NVkBHbmJbGSfI+9J8b4PeI3CVimUTYc78/MPMMNz7UwiiAc7EBt51alhQB
+S6kRnSlqLtBdgcDPsiBDxwPgN05dCtxZICU=
+-----END CERTIFICATE-----
+
+Certigna
+========
+-----BEGIN CERTIFICATE-----
+MIIDqDCCApCgAwIBAgIJAP7c4wEPyUj/MA0GCSqGSIb3DQEBBQUAMDQxCzAJBgNVBAYTAkZSMRIw
+EAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hMB4XDTA3MDYyOTE1MTMwNVoXDTI3
+MDYyOTE1MTMwNVowNDELMAkGA1UEBhMCRlIxEjAQBgNVBAoMCURoaW15b3RpczERMA8GA1UEAwwI
+Q2VydGlnbmEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDIaPHJ1tazNHUmgh7stL7q
+XOEm7RFHYeGifBZ4QCHkYJ5ayGPhxLGWkv8YbWkj4Sti993iNi+RB7lIzw7sebYs5zRLcAglozyH
+GxnygQcPOJAZ0xH+hrTy0V4eHpbNgGzOOzGTtvKg0KmVEn2lmsxryIRWijOp5yIVUxbwzBfsV1/p
+ogqYCd7jX5xv3EjjhQsVWqa6n6xI4wmy9/Qy3l40vhx4XUJbzg4ij02Q130yGLMLLGq/jj8UEYkg
+DncUtT2UCIf3JR7VsmAA7G8qKCVuKj4YYxclPz5EIBb2JsglrgVKtOdjLPOMFlN+XPsRGgjBRmKf
+Irjxwo1p3Po6WAbfAgMBAAGjgbwwgbkwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGu3+QTmQ
+tCRZvgHyUtVF9lo53BEwZAYDVR0jBF0wW4AUGu3+QTmQtCRZvgHyUtVF9lo53BGhOKQ2MDQxCzAJ
+BgNVBAYTAkZSMRIwEAYDVQQKDAlEaGlteW90aXMxETAPBgNVBAMMCENlcnRpZ25hggkA/tzjAQ/J
+SP8wDgYDVR0PAQH/BAQDAgEGMBEGCWCGSAGG+EIBAQQEAwIABzANBgkqhkiG9w0BAQUFAAOCAQEA
+hQMeknH2Qq/ho2Ge6/PAD/Kl1NqV5ta+aDY9fm4fTIrv0Q8hbV6lUmPOEvjvKtpv6zf+EwLHyzs+
+ImvaYS5/1HI93TDhHkxAGYwP15zRgzB7mFncfca5DClMoTOi62c6ZYTTluLtdkVwj7Ur3vkj1klu
+PBS1xp81HlDQwY9qcEQCYsuuHWhBp6pX6FOqB9IG9tUUBguRA3UsbHK1YZWaDYu5Def131TN3ubY
+1gkIl2PlwS6wt0QmwCbAr1UwnjvVNioZBPRcHv/PLLf/0P2HQBHVESO7SMAhqaQoLf0V+LBOK/Qw
+WyH8EZE0vkHve52Xdf+XlcCWWC/qu0bXu+TZLg==
+-----END CERTIFICATE-----
+
+AC Ra\xC3\xADz Certic\xC3\xA1mara S.A.
+======================================
+-----BEGIN CERTIFICATE-----
+MIIGZjCCBE6gAwIBAgIPB35Sk3vgFeNX8GmMy+wMMA0GCSqGSIb3DQEBBQUAMHsxCzAJBgNVBAYT
+AkNPMUcwRQYDVQQKDD5Tb2NpZWRhZCBDYW1lcmFsIGRlIENlcnRpZmljYWNpw7NuIERpZ2l0YWwg
+LSBDZXJ0aWPDoW1hcmEgUy5BLjEjMCEGA1UEAwwaQUMgUmHDrXogQ2VydGljw6FtYXJhIFMuQS4w
+HhcNMDYxMTI3MjA0NjI5WhcNMzAwNDAyMjE0MjAyWjB7MQswCQYDVQQGEwJDTzFHMEUGA1UECgw+
+U29jaWVkYWQgQ2FtZXJhbCBkZSBDZXJ0aWZpY2FjacOzbiBEaWdpdGFsIC0gQ2VydGljw6FtYXJh
+IFMuQS4xIzAhBgNVBAMMGkFDIFJhw616IENlcnRpY8OhbWFyYSBTLkEuMIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEAq2uJo1PMSCMI+8PPUZYILrgIem08kBeGqentLhM0R7LQcNzJPNCN
+yu5LF6vQhbCnIwTLqKL85XXbQMpiiY9QngE9JlsYhBzLfDe3fezTf3MZsGqy2IiKLUV0qPezuMDU
+2s0iiXRNWhU5cxh0T7XrmafBHoi0wpOQY5fzp6cSsgkiBzPZkc0OnB8OIMfuuzONj8LSWKdf/WU3
+4ojC2I+GdV75LaeHM/J4Ny+LvB2GNzmxlPLYvEqcgxhaBvzz1NS6jBUJJfD5to0EfhcSM2tXSExP
+2yYe68yQ54v5aHxwD6Mq0Do43zeX4lvegGHTgNiRg0JaTASJaBE8rF9ogEHMYELODVoqDA+bMMCm
+8Ibbq0nXl21Ii/kDwFJnmxL3wvIumGVC2daa49AZMQyth9VXAnow6IYm+48jilSH5L887uvDdUhf
+HjlvgWJsxS3EF1QZtzeNnDeRyPYL1epjb4OsOMLzP96a++EjYfDIJss2yKHzMI+ko6Kh3VOz3vCa
+Mh+DkXkwwakfU5tTohVTP92dsxA7SH2JD/ztA/X7JWR1DhcZDY8AFmd5ekD8LVkH2ZD6mq093ICK
+5lw1omdMEWux+IBkAC1vImHFrEsm5VoQgpukg3s0956JkSCXjrdCx2bD0Omk1vUgjcTDlaxECp1b
+czwmPS9KvqfJpxAe+59QafMCAwEAAaOB5jCB4zAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQE
+AwIBBjAdBgNVHQ4EFgQU0QnQ6dfOeXRU+Tows/RtLAMDG2gwgaAGA1UdIASBmDCBlTCBkgYEVR0g
+ADCBiTArBggrBgEFBQcCARYfaHR0cDovL3d3dy5jZXJ0aWNhbWFyYS5jb20vZHBjLzBaBggrBgEF
+BQcCAjBOGkxMaW1pdGFjaW9uZXMgZGUgZ2FyYW507WFzIGRlIGVzdGUgY2VydGlmaWNhZG8gc2Ug
+cHVlZGVuIGVuY29udHJhciBlbiBsYSBEUEMuMA0GCSqGSIb3DQEBBQUAA4ICAQBclLW4RZFNjmEf
+AygPU3zmpFmps4p6xbD/CHwso3EcIRNnoZUSQDWDg4902zNc8El2CoFS3UnUmjIz75uny3XlesuX
+EpBcunvFm9+7OSPI/5jOCk0iAUgHforA1SBClETvv3eiiWdIG0ADBaGJ7M9i4z0ldma/Jre7Ir5v
+/zlXdLp6yQGVwZVR6Kss+LGGIOk/yzVb0hfpKv6DExdA7ohiZVvVO2Dpezy4ydV/NgIlqmjCMRW3
+MGXrfx1IebHPOeJCgBbT9ZMj/EyXyVo3bHwi2ErN0o42gzmRkBDI8ck1fj+404HGIGQatlDCIaR4
+3NAvO2STdPCWkPHv+wlaNECW8DYSwaN0jJN+Qd53i+yG2dIPPy3RzECiiWZIHiCznCNZc6lEc7wk
+eZBWN7PGKX6jD/EpOe9+XCgycDWs2rjIdWb8m0w5R44bb5tNAlQiM+9hup4phO9OSzNHdpdqy35f
+/RWmnkJDW2ZaiogN9xa5P1FlK2Zqi9E4UqLWRhH6/JocdJ6PlwsCT2TG9WjTSy3/pDceiz+/RL5h
+RqGEPQgnTIEgd4kI6mdAXmwIUV80WoyWaM3X94nCHNMyAK9Sy9NgWyo6R35rMDOhYil/SrnhLecU
+Iw4OGEfhefwVVdCx/CVxY3UzHCMrr1zZ7Ud3YA47Dx7SwNxkBYn8eNZcLCZDqQ==
+-----END CERTIFICATE-----
+
+TC TrustCenter Class 2 CA II
+============================
+-----BEGIN CERTIFICATE-----
+MIIEqjCCA5KgAwIBAgIOLmoAAQACH9dSISwRXDswDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC
+REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy
+IENsYXNzIDIgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDIgQ0EgSUkwHhcNMDYw
+MTEyMTQzODQzWhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1
+c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQTElMCMGA1UE
+AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMiBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAKuAh5uO8MN8h9foJIIRszzdQ2Lu+MNF2ujhoF/RKrLqk2jftMjWQ+nEdVl//OEd+DFw
+IxuInie5e/060smp6RQvkL4DUsFJzfb95AhmC1eKokKguNV/aVyQMrKXDcpK3EY+AlWJU+MaWss2
+xgdW94zPEfRMuzBwBJWl9jmM/XOBCH2JXjIeIqkiRUuwZi4wzJ9l/fzLganx4Duvo4bRierERXlQ
+Xa7pIXSSTYtZgo+U4+lK8edJsBTj9WLL1XK9H7nSn6DNqPoByNkN39r8R52zyFTfSUrxIan+GE7u
+SNQZu+995OKdy1u2bv/jzVrndIIFuoAlOMvkaZ6vQaoahPUCAwEAAaOCATQwggEwMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTjq1RMgKHbVkO3kUrL84J6E1wIqzCB
+7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90
+Y19jbGFzc18yX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU
+cnVzdENlbnRlciUyMENsYXNzJTIwMiUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i
+SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
+TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEAjNfffu4bgBCzg/XbEeprS6iSGNn3Bzn1LL4G
+dXpoUxUc6krtXvwjshOg0wn/9vYua0Fxec3ibf2uWWuFHbhOIprtZjluS5TmVfwLG4t3wVMTZonZ
+KNaL80VKY7f9ewthXbhtvsPcW3nS7Yblok2+XnR8au0WOB9/WIFaGusyiC2y8zl3gK9etmF1Kdsj
+TYjKUCjLhdLTEKJZbtOTVAB6okaVhgWcqRmY5TFyDADiZ9lA4CQze28suVyrZZ0srHbqNZn1l7kP
+JOzHdiEoZa5X6AeIdUpWoNIFOqTmjZKILPPy4cHGYdtBxceb9w4aUUXCYWvcZCcXjFq32nQozZfk
+vQ==
+-----END CERTIFICATE-----
+
+TC TrustCenter Class 3 CA II
+============================
+-----BEGIN CERTIFICATE-----
+MIIEqjCCA5KgAwIBAgIOSkcAAQAC5aBd1j8AUb8wDQYJKoZIhvcNAQEFBQAwdjELMAkGA1UEBhMC
+REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxIjAgBgNVBAsTGVRDIFRydXN0Q2VudGVy
+IENsYXNzIDMgQ0ExJTAjBgNVBAMTHFRDIFRydXN0Q2VudGVyIENsYXNzIDMgQ0EgSUkwHhcNMDYw
+MTEyMTQ0MTU3WhcNMjUxMjMxMjI1OTU5WjB2MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMgVHJ1
+c3RDZW50ZXIgR21iSDEiMCAGA1UECxMZVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQTElMCMGA1UE
+AxMcVEMgVHJ1c3RDZW50ZXIgQ2xhc3MgMyBDQSBJSTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBALTgu1G7OVyLBMVMeRwjhjEQY0NVJz/GRcekPewJDRoeIMJWHt4bNwcwIi9v8Qbxq63W
+yKthoy9DxLCyLfzDlml7forkzMA5EpBCYMnMNWju2l+QVl/NHE1bWEnrDgFPZPosPIlY2C8u4rBo
+6SI7dYnWRBpl8huXJh0obazovVkdKyT21oQDZogkAHhg8fir/gKya/si+zXmFtGt9i4S5Po1auUZ
+uV3bOx4a+9P/FRQI2AlqukWdFHlgfa9Aigdzs5OW03Q0jTo3Kd5c7PXuLjHCINy+8U9/I1LZW+Jk
+2ZyqBwi1Rb3R0DHBq1SfqdLDYmAD8bs5SpJKPQq5ncWg/jcCAwEAAaOCATQwggEwMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTUovyfs8PYA9NXXAek0CSnwPIA1DCB
+7QYDVR0fBIHlMIHiMIHfoIHcoIHZhjVodHRwOi8vd3d3LnRydXN0Y2VudGVyLmRlL2NybC92Mi90
+Y19jbGFzc18zX2NhX0lJLmNybIaBn2xkYXA6Ly93d3cudHJ1c3RjZW50ZXIuZGUvQ049VEMlMjBU
+cnVzdENlbnRlciUyMENsYXNzJTIwMyUyMENBJTIwSUksTz1UQyUyMFRydXN0Q2VudGVyJTIwR21i
+SCxPVT1yb290Y2VydHMsREM9dHJ1c3RjZW50ZXIsREM9ZGU/Y2VydGlmaWNhdGVSZXZvY2F0aW9u
+TGlzdD9iYXNlPzANBgkqhkiG9w0BAQUFAAOCAQEANmDkcPcGIEPZIxpC8vijsrlNirTzwppVMXzE
+O2eatN9NDoqTSheLG43KieHPOh6sHfGcMrSOWXaiQYUlN6AT0PV8TtXqluJucsG7Kv5sbviRmEb8
+yRtXW+rIGjs/sFGYPAfaLFkB2otE6OF0/ado3VS6g0bsyEa1+K+XwDsJHI/OcpY9M1ZwvJbL2NV9
+IJqDnxrcOfHFcqMRA/07QlIp2+gB95tejNaNhk4Z+rwcvsUhpYeeeC422wlxo3I0+GzjBgnyXlal
+092Y+tTmBvTwtiBjS+opvaqCZh77gaqnN60TGOaSw4HBM7uIHqHn4rS9MWwOUT1v+5ZWgOI2F9Hc
+5A==
+-----END CERTIFICATE-----
+
+TC TrustCenter Universal CA I
+=============================
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIOHaIAAQAC7LdggHiNtgYwDQYJKoZIhvcNAQEFBQAweTELMAkGA1UEBhMC
+REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy
+IFVuaXZlcnNhbCBDQTEmMCQGA1UEAxMdVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIEkwHhcN
+MDYwMzIyMTU1NDI4WhcNMjUxMjMxMjI1OTU5WjB5MQswCQYDVQQGEwJERTEcMBoGA1UEChMTVEMg
+VHJ1c3RDZW50ZXIgR21iSDEkMCIGA1UECxMbVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBMSYw
+JAYDVQQDEx1UQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0EgSTCCASIwDQYJKoZIhvcNAQEBBQAD
+ggEPADCCAQoCggEBAKR3I5ZEr5D0MacQ9CaHnPM42Q9e3s9B6DGtxnSRJJZ4Hgmgm5qVSkr1YnwC
+qMqs+1oEdjneX/H5s7/zA1hV0qq34wQi0fiU2iIIAI3TfCZdzHd55yx4Oagmcw6iXSVphU9VDprv
+xrlE4Vc93x9UIuVvZaozhDrzznq+VZeujRIPFDPiUHDDSYcTvFHe15gSWu86gzOSBnWLknwSaHtw
+ag+1m7Z3W0hZneTvWq3zwZ7U10VOylY0Ibw+F1tvdwxIAUMpsN0/lm7mlaoMwCC2/T42J5zjXM9O
+gdwZu5GQfezmlwQek8wiSdeXhrYTCjxDI3d+8NzmzSQfO4ObNDqDNOMCAwEAAaNjMGEwHwYDVR0j
+BBgwFoAUkqR1LKSevoFE63n8isWVpesQdXMwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AYYwHQYDVR0OBBYEFJKkdSyknr6BROt5/IrFlaXrEHVzMA0GCSqGSIb3DQEBBQUAA4IBAQAo0uCG
+1eb4e/CX3CJrO5UUVg8RMKWaTzqwOuAGy2X17caXJ/4l8lfmXpWMPmRgFVp/Lw0BxbFg/UU1z/Cy
+vwbZ71q+s2IhtNerNXxTPqYn8aEt2hojnczd7Dwtnic0XQ/CNnm8yUpiLe1r2X1BQ3y2qsrtYbE3
+ghUJGooWMNjsydZHcnhLEEYUjl8Or+zHL6sQ17bxbuyGssLoDZJz3KL0Dzq/YSMQiZxIQG5wALPT
+ujdEWBF6AmqI8Dc08BnprNRlc/ZpjGSUOnmFKbAWKwyCPwacx/0QK54PLLae4xW/2TYcuiUaUj0a
+7CIMHOCkoj3w6DnPgcB77V0fb8XQC9eY
+-----END CERTIFICATE-----
+
+Deutsche Telekom Root CA 2
+==========================
+-----BEGIN CERTIFICATE-----
+MIIDnzCCAoegAwIBAgIBJjANBgkqhkiG9w0BAQUFADBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMT
+RGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0GA1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEG
+A1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBSb290IENBIDIwHhcNOTkwNzA5MTIxMTAwWhcNMTkwNzA5
+MjM1OTAwWjBxMQswCQYDVQQGEwJERTEcMBoGA1UEChMTRGV1dHNjaGUgVGVsZWtvbSBBRzEfMB0G
+A1UECxMWVC1UZWxlU2VjIFRydXN0IENlbnRlcjEjMCEGA1UEAxMaRGV1dHNjaGUgVGVsZWtvbSBS
+b290IENBIDIwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCrC6M14IspFLEUha88EOQ5
+bzVdSq7d6mGNlUn0b2SjGmBmpKlAIoTZ1KXleJMOaAGtuU1cOs7TuKhCQN/Po7qCWWqSG6wcmtoI
+KyUn+WkjR/Hg6yx6m/UTAtB+NHzCnjwAWav12gz1MjwrrFDa1sPeg5TKqAyZMg4ISFZbavva4VhY
+AUlfckE8FQYBjl2tqriTtM2e66foai1SNNs671x1Udrb8zH57nGYMsRUFUQM+ZtV7a3fGAigo4aK
+Se5TBY8ZTNXeWHmb0mocQqvF1afPaA+W5OFhmHZhyJF81j4A4pFQh+GdCuatl9Idxjp9y7zaAzTV
+jlsB9WoHtxa2bkp/AgMBAAGjQjBAMB0GA1UdDgQWBBQxw3kbuvVT1xfgiXotF2wKsyudMzAPBgNV
+HRMECDAGAQH/AgEFMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAlGRZrTlk5ynr
+E/5aw4sTV8gEJPB0d8Bg42f76Ymmg7+Wgnxu1MM9756AbrsptJh6sTtU6zkXR34ajgv8HzFZMQSy
+zhfzLMdiNlXiItiJVbSYSKpk+tYcNthEeFpaIzpXl/V6ME+un2pMSyuOoAPjPuCp1NJ70rOo4nI8
+rZ7/gFnkm0W09juwzTkZmDLl6iFhkOQxIY40sfcvNUqFENrnijchvllj4PKFiDFT1FQUhXB59C4G
+dyd1Lx+4ivn+xbrYNuSD7Odlt79jWvNGr4GUN9RBjNYj1h7P9WgbRGOiWrqnNVmh5XAFmw4jV5mU
+Cm26OWMohpLzGITY+9HPBVZkVw==
+-----END CERTIFICATE-----
+
+ComSign CA
+==========
+-----BEGIN CERTIFICATE-----
+MIIDkzCCAnugAwIBAgIQFBOWgxRVjOp7Y+X8NId3RDANBgkqhkiG9w0BAQUFADA0MRMwEQYDVQQD
+EwpDb21TaWduIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0wNDAzMjQxMTMy
+MThaFw0yOTAzMTkxNTAyMThaMDQxEzARBgNVBAMTCkNvbVNpZ24gQ0ExEDAOBgNVBAoTB0NvbVNp
+Z24xCzAJBgNVBAYTAklMMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA8ORUaSvTx49q
+ROR+WCf4C9DklBKK8Rs4OC8fMZwG1Cyn3gsqrhqg455qv588x26i+YtkbDqthVVRVKU4VbirgwTy
+P2Q298CNQ0NqZtH3FyrV7zb6MBBC11PN+fozc0yz6YQgitZBJzXkOPqUm7h65HkfM/sb2CEJKHxN
+GGleZIp6GZPKfuzzcuc3B1hZKKxC+cX/zT/npfo4sdAMx9lSGlPWgcxCejVb7Us6eva1jsz/D3zk
+YDaHL63woSV9/9JLEYhwVKZBqGdTUkJe5DSe5L6j7KpiXd3DTKaCQeQzC6zJMw9kglcq/QytNuEM
+rkvF7zuZ2SOzW120V+x0cAwqTwIDAQABo4GgMIGdMAwGA1UdEwQFMAMBAf8wPQYDVR0fBDYwNDAy
+oDCgLoYsaHR0cDovL2ZlZGlyLmNvbXNpZ24uY28uaWwvY3JsL0NvbVNpZ25DQS5jcmwwDgYDVR0P
+AQH/BAQDAgGGMB8GA1UdIwQYMBaAFEsBmz5WGmU2dst7l6qSBe4y5ygxMB0GA1UdDgQWBBRLAZs+
+VhplNnbLe5eqkgXuMucoMTANBgkqhkiG9w0BAQUFAAOCAQEA0Nmlfv4pYEWdfoPPbrxHbvUanlR2
+QnG0PFg/LUAlQvaBnPGJEMgOqnhPOAlXsDzACPw1jvFIUY0McXS6hMTXcpuEfDhOZAYnKuGntewI
+mbQKDdSFc8gS4TXt8QUxHXOZDOuWyt3T5oWq8Ir7dcHyCTxlZWTzTNity4hp8+SDtwy9F1qWF8pb
+/627HOkthIDYIb6FUtnUdLlphbpN7Sgy6/lhSuTENh4Z3G+EER+V9YMoGKgzkkMn3V0TBEVPh9VG
+zT2ouvDzuFYkRes3x+F2T3I5GN9+dHLHcy056mDmrRGiVod7w2ia/viMcKjfZTL0pECMocJEAw6U
+AGegcQCCSA==
+-----END CERTIFICATE-----
+
+ComSign Secured CA
+==================
+-----BEGIN CERTIFICATE-----
+MIIDqzCCApOgAwIBAgIRAMcoRwmzuGxFjB36JPU2TukwDQYJKoZIhvcNAQEFBQAwPDEbMBkGA1UE
+AxMSQ29tU2lnbiBTZWN1cmVkIENBMRAwDgYDVQQKEwdDb21TaWduMQswCQYDVQQGEwJJTDAeFw0w
+NDAzMjQxMTM3MjBaFw0yOTAzMTYxNTA0NTZaMDwxGzAZBgNVBAMTEkNvbVNpZ24gU2VjdXJlZCBD
+QTEQMA4GA1UEChMHQ29tU2lnbjELMAkGA1UEBhMCSUwwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAw
+ggEKAoIBAQDGtWhfHZQVw6QIVS3joFd67+l0Kru5fFdJGhFeTymHDEjWaueP1H5XJLkGieQcPOqs
+49ohgHMhCu95mGwfCP+hUH3ymBvJVG8+pSjsIQQPRbsHPaHA+iqYHU4Gk/v1iDurX8sWv+bznkqH
+7Rnqwp9D5PGBpX8QTz7RSmKtUxvLg/8HZaWSLWapW7ha9B20IZFKF3ueMv5WJDmyVIRD9YTC2LxB
+kMyd1mja6YJQqTtoz7VdApRgFrFD2UNd3V2Hbuq7s8lr9gOUCXDeFhF6K+h2j0kQmHe5Y1yLM5d1
+9guMsqtb3nQgJT/j8xH5h2iGNXHDHYwt6+UarA9z1YJZQIDTAgMBAAGjgacwgaQwDAYDVR0TBAUw
+AwEB/zBEBgNVHR8EPTA7MDmgN6A1hjNodHRwOi8vZmVkaXIuY29tc2lnbi5jby5pbC9jcmwvQ29t
+U2lnblNlY3VyZWRDQS5jcmwwDgYDVR0PAQH/BAQDAgGGMB8GA1UdIwQYMBaAFMFL7XC29z58ADsA
+j8c+DkWfHl3sMB0GA1UdDgQWBBTBS+1wtvc+fAA7AI/HPg5Fnx5d7DANBgkqhkiG9w0BAQUFAAOC
+AQEAFs/ukhNQq3sUnjO2QiBq1BW9Cav8cujvR3qQrFHBZE7piL1DRYHjZiM/EoZNGeQFsOY3wo3a
+BijJD4mkU6l1P7CW+6tMM1X5eCZGbxs2mPtCdsGCuY7e+0X5YxtiOzkGynd6qDwJz2w2PQ8KRUtp
+FhpFfTMDZflScZAmlaxMDPWLkz/MdXSFmLr/YnpNH4n+rr2UAJm/EaXc4HnFFgt9AmEd6oX5AhVP
+51qJThRv4zdLhfXBPGHg/QVBspJ/wx2g0K5SZGBrGMYmnNj1ZOQ2GmKfig8+/21OGVZOIJFsnzQz
+OjRXUDpvgV4GxvU+fE6OK85lBi5d0ipTdF7Tbieejw==
+-----END CERTIFICATE-----
+
+Cybertrust Global Root
+======================
+-----BEGIN CERTIFICATE-----
+MIIDoTCCAomgAwIBAgILBAAAAAABD4WqLUgwDQYJKoZIhvcNAQEFBQAwOzEYMBYGA1UEChMPQ3li
+ZXJ0cnVzdCwgSW5jMR8wHQYDVQQDExZDeWJlcnRydXN0IEdsb2JhbCBSb290MB4XDTA2MTIxNTA4
+MDAwMFoXDTIxMTIxNTA4MDAwMFowOzEYMBYGA1UEChMPQ3liZXJ0cnVzdCwgSW5jMR8wHQYDVQQD
+ExZDeWJlcnRydXN0IEdsb2JhbCBSb290MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA
++Mi8vRRQZhP/8NN57CPytxrHjoXxEnOmGaoQ25yiZXRadz5RfVb23CO21O1fWLE3TdVJDm71aofW
+0ozSJ8bi/zafmGWgE07GKmSb1ZASzxQG9Dvj1Ci+6A74q05IlG2OlTEQXO2iLb3VOm2yHLtgwEZL
+AfVJrn5GitB0jaEMAs7u/OePuGtm839EAL9mJRQr3RAwHQeWP032a7iPt3sMpTjr3kfb1V05/Iin
+89cqdPHoWqI7n1C6poxFNcJQZZXcY4Lv3b93TZxiyWNzFtApD0mpSPCzqrdsxacwOUBdrsTiXSZT
+8M4cIwhhqJQZugRiQOwfOHB3EgZxpzAYXSUnpQIDAQABo4GlMIGiMA4GA1UdDwEB/wQEAwIBBjAP
+BgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBS2CHsNesysIEyGVjJez6tuhS1wVzA/BgNVHR8EODA2
+MDSgMqAwhi5odHRwOi8vd3d3Mi5wdWJsaWMtdHJ1c3QuY29tL2NybC9jdC9jdHJvb3QuY3JsMB8G
+A1UdIwQYMBaAFLYIew16zKwgTIZWMl7Pq26FLXBXMA0GCSqGSIb3DQEBBQUAA4IBAQBW7wojoFRO
+lZfJ+InaRcHUowAl9B8Tq7ejhVhpwjCt2BWKLePJzYFa+HMjWqd8BfP9IjsO0QbE2zZMcwSO5bAi
+5MXzLqXZI+O4Tkogp24CJJ8iYGd7ix1yCcUxXOl5n4BHPa2hCwcUPUf/A2kaDAtE52Mlp3+yybh2
+hO0j9n0Hq0V+09+zv+mKts2oomcrUtW3ZfA5TGOgkXmTUg9U3YO7n9GPp1Nzw8v/MOx8BLjYRB+T
+X3EJIrduPuocA06dGiBh+4E37F78CkWr1+cXVdCg6mCbpvbjjFspwgZgFJ0tl0ypkxWdYcQBX0jW
+WL1WMRJOEcgh4LMRkWXbtKaIOM5V
+-----END CERTIFICATE-----
+
+ePKI Root Certification Authority
+=================================
+-----BEGIN CERTIFICATE-----
+MIIFsDCCA5igAwIBAgIQFci9ZUdcr7iXAF7kBtK8nTANBgkqhkiG9w0BAQUFADBeMQswCQYDVQQG
+EwJUVzEjMCEGA1UECgwaQ2h1bmdod2EgVGVsZWNvbSBDby4sIEx0ZC4xKjAoBgNVBAsMIWVQS0kg
+Um9vdCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTAeFw0wNDEyMjAwMjMxMjdaFw0zNDEyMjAwMjMx
+MjdaMF4xCzAJBgNVBAYTAlRXMSMwIQYDVQQKDBpDaHVuZ2h3YSBUZWxlY29tIENvLiwgTHRkLjEq
+MCgGA1UECwwhZVBLSSBSb290IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIICIjANBgkqhkiG9w0B
+AQEFAAOCAg8AMIICCgKCAgEA4SUP7o3biDN1Z82tH306Tm2d0y8U82N0ywEhajfqhFAHSyZbCUNs
+IZ5qyNUD9WBpj8zwIuQf5/dqIjG3LBXy4P4AakP/h2XGtRrBp0xtInAhijHyl3SJCRImHJ7K2RKi
+lTza6We/CKBk49ZCt0Xvl/T29de1ShUCWH2YWEtgvM3XDZoTM1PRYfl61dd4s5oz9wCGzh1NlDiv
+qOx4UXCKXBCDUSH3ET00hl7lSM2XgYI1TBnsZfZrxQWh7kcT1rMhJ5QQCtkkO7q+RBNGMD+XPNjX
+12ruOzjjK9SXDrkb5wdJfzcq+Xd4z1TtW0ado4AOkUPB1ltfFLqfpo0kR0BZv3I4sjZsN/+Z0V0O
+WQqraffAsgRFelQArr5T9rXn4fg8ozHSqf4hUmTFpmfwdQcGlBSBVcYn5AGPF8Fqcde+S/uUWH1+
+ETOxQvdibBjWzwloPn9s9h6PYq2lY9sJpx8iQkEeb5mKPtf5P0B6ebClAZLSnT0IFaUQAS2zMnao
+lQ2zepr7BxB4EW/hj8e6DyUadCrlHJhBmd8hh+iVBmoKs2pHdmX2Os+PYhcZewoozRrSgx4hxyy/
+vv9haLdnG7t4TY3OZ+XkwY63I2binZB1NJipNiuKmpS5nezMirH4JYlcWrYvjB9teSSnUmjDhDXi
+Zo1jDiVN1Rmy5nk3pyKdVDECAwEAAaNqMGgwHQYDVR0OBBYEFB4M97Zn8uGSJglFwFU5Lnc/Qkqi
+MAwGA1UdEwQFMAMBAf8wOQYEZyoHAAQxMC8wLQIBADAJBgUrDgMCGgUAMAcGBWcqAwAABBRFsMLH
+ClZ87lt4DJX5GFPBphzYEDANBgkqhkiG9w0BAQUFAAOCAgEACbODU1kBPpVJufGBuvl2ICO1J2B0
+1GqZNF5sAFPZn/KmsSQHRGoqxqWOeBLoR9lYGxMqXnmbnwoqZ6YlPwZpVnPDimZI+ymBV3QGypzq
+KOg4ZyYr8dW1P2WT+DZdjo2NQCCHGervJ8A9tDkPJXtoUHRVnAxZfVo9QZQlUgjgRywVMRnVvwdV
+xrsStZf0X4OFunHB2WyBEXYKCrC/gpf36j36+uwtqSiUO1bd0lEursC9CBWMd1I0ltabrNMdjmEP
+NXubrjlpC2JgQCA2j6/7Nu4tCEoduL+bXPjqpRugc6bY+G7gMwRfaKonh+3ZwZCc7b3jajWvY9+r
+GNm65ulK6lCKD2GTHuItGeIwlDWSXQ62B68ZgI9HkFFLLk3dheLSClIKF5r8GrBQAuUBo2M3IUxE
+xJtRmREOc5wGj1QupyheRDmHVi03vYVElOEMSyycw5KFNGHLD7ibSkNS/jQ6fbjpKdx2qcgw+BRx
+gMYeNkh0IkFch4LoGHGLQYlE535YW6i4jRPpp2zDR+2zGp1iro2C6pSe3VkQw63d4k3jMdXH7Ojy
+sP6SHhYKGvzZ8/gntsm+HbRsZJB/9OTEW9c3rkIO3aQab3yIVMUWbuF6aC74Or8NpDyJO3inTmOD
+BCEIZ43ygknQW/2xzQ+DhNQ+IIX3Sj0rnP0qCglN6oH4EZw=
+-----END CERTIFICATE-----
+
+T\xc3\x9c\x42\xC4\xB0TAK UEKAE K\xC3\xB6k Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1 - S\xC3\xBCr\xC3\xBCm 3
+=============================================================================================================================
+-----BEGIN CERTIFICATE-----
+MIIFFzCCA/+gAwIBAgIBETANBgkqhkiG9w0BAQUFADCCASsxCzAJBgNVBAYTAlRSMRgwFgYDVQQH
+DA9HZWJ6ZSAtIEtvY2FlbGkxRzBFBgNVBAoMPlTDvHJraXllIEJpbGltc2VsIHZlIFRla25vbG9q
+aWsgQXJhxZ90xLFybWEgS3VydW11IC0gVMOcQsSwVEFLMUgwRgYDVQQLDD9VbHVzYWwgRWxla3Ry
+b25payB2ZSBLcmlwdG9sb2ppIEFyYcWfdMSxcm1hIEVuc3RpdMO8c8O8IC0gVUVLQUUxIzAhBgNV
+BAsMGkthbXUgU2VydGlmaWthc3lvbiBNZXJrZXppMUowSAYDVQQDDEFUw5xCxLBUQUsgVUVLQUUg
+S8O2ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsSAtIFPDvHLDvG0gMzAeFw0wNzA4
+MjQxMTM3MDdaFw0xNzA4MjExMTM3MDdaMIIBKzELMAkGA1UEBhMCVFIxGDAWBgNVBAcMD0dlYnpl
+IC0gS29jYWVsaTFHMEUGA1UECgw+VMO8cmtpeWUgQmlsaW1zZWwgdmUgVGVrbm9sb2ppayBBcmHF
+n3TEsXJtYSBLdXJ1bXUgLSBUw5xCxLBUQUsxSDBGBgNVBAsMP1VsdXNhbCBFbGVrdHJvbmlrIHZl
+IEtyaXB0b2xvamkgQXJhxZ90xLFybWEgRW5zdGl0w7xzw7wgLSBVRUtBRTEjMCEGA1UECwwaS2Ft
+dSBTZXJ0aWZpa2FzeW9uIE1lcmtlemkxSjBIBgNVBAMMQVTDnELEsFRBSyBVRUtBRSBLw7ZrIFNl
+cnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxIC0gU8O8csO8bSAzMIIBIjANBgkqhkiG9w0B
+AQEFAAOCAQ8AMIIBCgKCAQEAim1L/xCIOsP2fpTo6iBkcK4hgb46ezzb8R1Sf1n68yJMlaCQvEhO
+Eav7t7WNeoMojCZG2E6VQIdhn8WebYGHV2yKO7Rm6sxA/OOqbLLLAdsyv9Lrhc+hDVXDWzhXcLh1
+xnnRFDDtG1hba+818qEhTsXOfJlfbLm4IpNQp81McGq+agV/E5wrHur+R84EpW+sky58K5+eeROR
+6Oqeyjh1jmKwlZMq5d/pXpduIF9fhHpEORlAHLpVK/swsoHvhOPc7Jg4OQOFCKlUAwUp8MmPi+oL
+hmUZEdPpCSPeaJMDyTYcIW7OjGbxmTDY17PDHfiBLqi9ggtm/oLL4eAagsNAgQIDAQABo0IwQDAd
+BgNVHQ4EFgQUvYiHyY/2pAoLquvF/pEjnatKijIwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQF
+MAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAB18+kmPNOm3JpIWmgV050vQbTlswyb2zrgxvMTfvCr4
+N5EY3ATIZJkrGG2AA1nJrvhY0D7twyOfaTyGOBye79oneNGEN3GKPEs5z35FBtYt2IpNeBLWrcLT
+y9LQQfMmNkqblWwM7uXRQydmwYj3erMgbOqwaSvHIOgMA8RBBZniP+Rr+KCGgceExh/VS4ESshYh
+LBOhgLJeDEoTniDYYkCrkOpkSi+sDQESeUWoL4cZaMjihccwsnX5OD+ywJO0a+IDRM5noN+J1q2M
+dqMTw5RhK2vZbMEHCiIHhWyFJEapvj+LeISCfiQMnf2BN+MlqO02TpUsyZyQ2uypQjyttgI=
+-----END CERTIFICATE-----
+
+Buypass Class 2 CA 1
+====================
+-----BEGIN CERTIFICATE-----
+MIIDUzCCAjugAwIBAgIBATANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMiBDQSAxMB4XDTA2
+MTAxMzEwMjUwOVoXDTE2MTAxMzEwMjUwOVowSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh
+c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDIgQ0EgMTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAIs8B0XY9t/mx8q6jUPFR42wWsE425KEHK8T1A9vNkYgxC7M
+cXA0ojTTNy7Y3Tp3L8DrKehc0rWpkTSHIln+zNvnma+WwajHQN2lFYxuyHyXA8vmIPLXl18xoS83
+0r7uvqmtqEyeIWZDO6i88wmjONVZJMHCR3axiFyCO7srpgTXjAePzdVBHfCuuCkslFJgNJQ72uA4
+0Z0zPhX0kzLFANq1KWYOOngPIVJfAuWSeyXTkh4vFZ2B5J2O6O+JzhRMVB0cgRJNcKi+EAUXfh/R
+uFdV7c27UsKwHnjCTTZoy1YmwVLBvXb3WNVyfh9EdrsAiR0WnVE1703CVu9r4Iw7DekCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUP42aWYv8e3uco684sDntkHGA1sgwDgYDVR0P
+AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQAVGn4TirnoB6NLJzKyQJHyIdFkhb5jatLPgcIV
+1Xp+DCmsNx4cfHZSldq1fyOhKXdlyTKdqC5Wq2B2zha0jX94wNWZUYN/Xtm+DKhQ7SLHrQVMdvvt
+7h5HZPb3J31cKA9FxVxiXqaakZG3Uxcu3K1gnZZkOb1naLKuBctN518fV4bVIJwo+28TOPX2EZL2
+fZleHwzoq0QkKXJAPTZSr4xYkHPB7GEseaHsh7U/2k3ZIQAw3pDaDtMaSKk+hQsUi4y8QZ5q9w5w
+wDX3OaJdZtB7WZ+oRxKaJyOkLY4ng5IgodcVf/EuGO70SH8vf/GhGLWhC5SgYiAynB321O+/TIho
+-----END CERTIFICATE-----
+
+Buypass Class 3 CA 1
+====================
+-----BEGIN CERTIFICATE-----
+MIIDUzCCAjugAwIBAgIBAjANBgkqhkiG9w0BAQUFADBLMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxHTAbBgNVBAMMFEJ1eXBhc3MgQ2xhc3MgMyBDQSAxMB4XDTA1
+MDUwOTE0MTMwM1oXDTE1MDUwOTE0MTMwM1owSzELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1eXBh
+c3MgQVMtOTgzMTYzMzI3MR0wGwYDVQQDDBRCdXlwYXNzIENsYXNzIDMgQ0EgMTCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAKSO13TZKWTeXx+HgJHqTjnmGcZEC4DVC69TB4sSveZn8AKx
+ifZgisRbsELRwCGoy+Gb72RRtqfPFfV0gGgEkKBYouZ0plNTVUhjP5JW3SROjvi6K//zNIqeKNc0
+n6wv1g/xpC+9UrJJhW05NfBEMJNGJPO251P7vGGvqaMU+8IXF4Rs4HyI+MkcVyzwPX6UvCWThOia
+AJpFBUJXgPROztmuOfbIUxAMZTpHe2DC1vqRycZxbL2RhzyRhkmr8w+gbCZ2Xhysm3HljbybIR6c
+1jh+JIAVMYKWsUnTYjdbiAwKYjT+p0h+mbEwi5A3lRyoH6UsjfRVyNvdWQrCrXig9IsCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUOBTmyPCppAP0Tj4io1vy1uCtQHQwDgYDVR0P
+AQH/BAQDAgEGMA0GCSqGSIb3DQEBBQUAA4IBAQABZ6OMySU9E2NdFm/soT4JXJEVKirZgCFPBdy7
+pYmrEzMqnji3jG8CcmPHc3ceCQa6Oyh7pEfJYWsICCD8igWKH7y6xsL+z27sEzNxZy5p+qksP2bA
+EllNC1QCkoS72xLvg3BweMhT+t/Gxv/ciC8HwEmdMldg0/L2mSlf56oBzKwzqBwKu5HEA6BvtjT5
+htOzdlSY9EqBs1OdTUDs5XcTRa9bqh/YL0yCe/4qxFi7T/ye/QNlGioOw6UgFpRreaaiErS7GqQj
+el/wroQk5PMr+4okoyeYZdowdXb8GZHo2+ubPzK/QJcHJrrM85SFSnonk8+QQtS4Wxam58tAA915
+-----END CERTIFICATE-----
+
+EBG Elektronik Sertifika Hizmet Sa\xC4\x9Flay\xc4\xb1\x63\xc4\xb1s\xc4\xb1
+==========================================================================
+-----BEGIN CERTIFICATE-----
+MIIF5zCCA8+gAwIBAgIITK9zQhyOdAIwDQYJKoZIhvcNAQEFBQAwgYAxODA2BgNVBAMML0VCRyBF
+bGVrdHJvbmlrIFNlcnRpZmlrYSBIaXptZXQgU2HEn2xhecSxY8Sxc8SxMTcwNQYDVQQKDC5FQkcg
+QmlsacWfaW0gVGVrbm9sb2ppbGVyaSB2ZSBIaXptZXRsZXJpIEEuxZ4uMQswCQYDVQQGEwJUUjAe
+Fw0wNjA4MTcwMDIxMDlaFw0xNjA4MTQwMDMxMDlaMIGAMTgwNgYDVQQDDC9FQkcgRWxla3Ryb25p
+ayBTZXJ0aWZpa2EgSGl6bWV0IFNhxJ9sYXnEsWPEsXPEsTE3MDUGA1UECgwuRUJHIEJpbGnFn2lt
+IFRla25vbG9qaWxlcmkgdmUgSGl6bWV0bGVyaSBBLsWeLjELMAkGA1UEBhMCVFIwggIiMA0GCSqG
+SIb3DQEBAQUAA4ICDwAwggIKAoICAQDuoIRh0DpqZhAy2DE4f6en5f2h4fuXd7hxlugTlkaDT7by
+X3JWbhNgpQGR4lvFzVcfd2NR/y8927k/qqk153nQ9dAktiHq6yOU/im/+4mRDGSaBUorzAzu8T2b
+gmmkTPiab+ci2hC6X5L8GCcKqKpE+i4stPtGmggDg3KriORqcsnlZR9uKg+ds+g75AxuetpX/dfr
+eYteIAbTdgtsApWjluTLdlHRKJ2hGvxEok3MenaoDT2/F08iiFD9rrbskFBKW5+VQarKD7JK/oCZ
+TqNGFav4c0JqwmZ2sQomFd2TkuzbqV9UIlKRcF0T6kjsbgNs2d1s/OsNA/+mgxKb8amTD8UmTDGy
+Y5lhcucqZJnSuOl14nypqZoaqsNW2xCaPINStnuWt6yHd6i58mcLlEOzrz5z+kI2sSXFCjEmN1Zn
+uqMLfdb3ic1nobc6HmZP9qBVFCVMLDMNpkGMvQQxahByCp0OLna9XvNRiYuoP1Vzv9s6xiQFlpJI
+qkuNKgPlV5EQ9GooFW5Hd4RcUXSfGenmHmMWOeMRFeNYGkS9y8RsZteEBt8w9DeiQyJ50hBs37vm
+ExH8nYQKE3vwO9D8owrXieqWfo1IhR5kX9tUoqzVegJ5a9KK8GfaZXINFHDk6Y54jzJ0fFfy1tb0
+Nokb+Clsi7n2l9GkLqq+CxnCRelwXQIDAJ3Zo2MwYTAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB
+/wQEAwIBBjAdBgNVHQ4EFgQU587GT/wWZ5b6SqMHwQSny2re2kcwHwYDVR0jBBgwFoAU587GT/wW
+Z5b6SqMHwQSny2re2kcwDQYJKoZIhvcNAQEFBQADggIBAJuYml2+8ygjdsZs93/mQJ7ANtyVDR2t
+FcU22NU57/IeIl6zgrRdu0waypIN30ckHrMk2pGI6YNw3ZPX6bqz3xZaPt7gyPvT/Wwp+BVGoGgm
+zJNSroIBk5DKd8pNSe/iWtkqvTDOTLKBtjDOWU/aWR1qeqRFsIImgYZ29fUQALjuswnoT4cCB64k
+XPBfrAowzIpAoHMEwfuJJPaaHFy3PApnNgUIMbOv2AFoKuB4j3TeuFGkjGwgPaL7s9QJ/XvCgKqT
+bCmYIai7FvOpEl90tYeY8pUm3zTvilORiF0alKM/fCL414i6poyWqD1SNGKfAB5UVUJnxk1Gj7sU
+RT0KlhaOEKGXmdXTMIXM3rRyt7yKPBgpaP3ccQfuJDlq+u2lrDgv+R4QDgZxGhBM/nV+/x5XOULK
+1+EVoVZVWRvRo68R2E7DpSvvkL/A7IITW43WciyTTo9qKd+FPNMN4KIYEsxVL0e3p5sC/kH2iExt
+2qkBR4NkJ2IQgtYSe14DHzSpyZH+r11thie3I6p1GMog57AP14kOpmciY/SDQSsGS7tY1dHXt7kQ
+Y9iJSrSq3RZj9W6+YKH47ejWkE8axsWgKdOnIaj1Wjz3x0miIZpKlVIglnKaZsv30oZDfCK+lvm9
+AahH3eU7QPl1K5srRmSGjR70j/sHd9DqSaIcjVIUpgqT
+-----END CERTIFICATE-----
+
+certSIGN ROOT CA
+================
+-----BEGIN CERTIFICATE-----
+MIIDODCCAiCgAwIBAgIGIAYFFnACMA0GCSqGSIb3DQEBBQUAMDsxCzAJBgNVBAYTAlJPMREwDwYD
+VQQKEwhjZXJ0U0lHTjEZMBcGA1UECxMQY2VydFNJR04gUk9PVCBDQTAeFw0wNjA3MDQxNzIwMDRa
+Fw0zMTA3MDQxNzIwMDRaMDsxCzAJBgNVBAYTAlJPMREwDwYDVQQKEwhjZXJ0U0lHTjEZMBcGA1UE
+CxMQY2VydFNJR04gUk9PVCBDQTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBALczuX7I
+JUqOtdu0KBuqV5Do0SLTZLrTk+jUrIZhQGpgV2hUhE28alQCBf/fm5oqrl0Hj0rDKH/v+yv6efHH
+rfAQUySQi2bJqIirr1qjAOm+ukbuW3N7LBeCgV5iLKECZbO9xSsAfsT8AzNXDe3i+s5dRdY4zTW2
+ssHQnIFKquSyAVwdj1+ZxLGt24gh65AIgoDzMKND5pCCrlUoSe1b16kQOA7+j0xbm0bqQfWwCHTD
+0IgztnzXdN/chNFDDnU5oSVAKOp4yw4sLjmdjItuFhwvJoIQ4uNllAoEwF73XVv4EOLQunpL+943
+AAAaWyjj0pxzPjKHmKHJUS/X3qwzs08CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8B
+Af8EBAMCAcYwHQYDVR0OBBYEFOCMm9slSbPxfIbWskKHC9BroNnkMA0GCSqGSIb3DQEBBQUAA4IB
+AQA+0hyJLjX8+HXd5n9liPRyTMks1zJO890ZeUe9jjtbkw9QSSQTaxQGcu8J06Gh40CEyecYMnQ8
+SG4Pn0vU9x7Tk4ZkVJdjclDVVc/6IJMCopvDI5NOFlV2oHB5bc0hH88vLbwZ44gx+FkagQnIl6Z0
+x2DEW8xXjrJ1/RsCCdtZb3KTafcxQdaIOL+Hsr0Wefmq5L6IJd1hJyMctTEHBDa0GpC9oHRxUIlt
+vBTjD4au8as+x6AJzKNI0eDbZOeStc+vckNwi/nDhDwTqn6Sm1dTk/pwwpEOMfmbZ13pljheX7Nz
+TogVZ96edhBiIL5VaZVDADlN9u6wWk5JRFRYX0KD
+-----END CERTIFICATE-----
+
+CNNIC ROOT
+==========
+-----BEGIN CERTIFICATE-----
+MIIDVTCCAj2gAwIBAgIESTMAATANBgkqhkiG9w0BAQUFADAyMQswCQYDVQQGEwJDTjEOMAwGA1UE
+ChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1QwHhcNMDcwNDE2MDcwOTE0WhcNMjcwNDE2MDcw
+OTE0WjAyMQswCQYDVQQGEwJDTjEOMAwGA1UEChMFQ05OSUMxEzARBgNVBAMTCkNOTklDIFJPT1Qw
+ggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDTNfc/c3et6FtzF8LRb+1VvG7q6KR5smzD
+o+/hn7E7SIX1mlwhIhAsxYLO2uOabjfhhyzcuQxauohV3/2q2x8x6gHx3zkBwRP9SFIhxFXf2tiz
+VHa6dLG3fdfA6PZZxU3Iva0fFNrfWEQlMhkqx35+jq44sDB7R3IJMfAw28Mbdim7aXZOV/kbZKKT
+VrdvmW7bCgScEeOAH8tjlBAKqeFkgjH5jCftppkA9nCTGPihNIaj3XrCGHn2emU1z5DrvTOTn1Or
+czvmmzQgLx3vqR1jGqCA2wMv+SYahtKNu6m+UjqHZ0gNv7Sg2Ca+I19zN38m5pIEo3/PIKe38zrK
+y5nLAgMBAAGjczBxMBEGCWCGSAGG+EIBAQQEAwIABzAfBgNVHSMEGDAWgBRl8jGtKvf33VKWCscC
+wQ7vptU7ETAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB/jAdBgNVHQ4EFgQUZfIxrSr3991S
+lgrHAsEO76bVOxEwDQYJKoZIhvcNAQEFBQADggEBAEs17szkrr/Dbq2flTtLP1se31cpolnKOOK5
+Gv+e5m4y3R6u6jW39ZORTtpC4cMXYFDy0VwmuYK36m3knITnA3kXr5g9lNvHugDnuL8BV8F3RTIM
+O/G0HAiw/VGgod2aHRM2mm23xzy54cXZF/qD1T0VoDy7HgviyJA/qIYM/PmLXoXLT1tLYhFHxUV8
+BS9BsZ4QaRuZluBVeftOhpm4lNqGOGqTo+fLbuXf6iFViZx9fX+Y9QCJ7uOEwFyWtcVG6kbghVW2
+G8kS1sHNzYDzAgE8yGnLRUhj2JTQ7IUOO04RZfSCjKY9ri4ilAnIXOo8gV0WKgOXFlUJ24pBgp5m
+mxE=
+-----END CERTIFICATE-----
+
+ApplicationCA - Japanese Government
+===================================
+-----BEGIN CERTIFICATE-----
+MIIDoDCCAoigAwIBAgIBMTANBgkqhkiG9w0BAQUFADBDMQswCQYDVQQGEwJKUDEcMBoGA1UEChMT
+SmFwYW5lc2UgR292ZXJubWVudDEWMBQGA1UECxMNQXBwbGljYXRpb25DQTAeFw0wNzEyMTIxNTAw
+MDBaFw0xNzEyMTIxNTAwMDBaMEMxCzAJBgNVBAYTAkpQMRwwGgYDVQQKExNKYXBhbmVzZSBHb3Zl
+cm5tZW50MRYwFAYDVQQLEw1BcHBsaWNhdGlvbkNBMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIB
+CgKCAQEAp23gdE6Hj6UG3mii24aZS2QNcfAKBZuOquHMLtJqO8F6tJdhjYq+xpqcBrSGUeQ3DnR4
+fl+Kf5Sk10cI/VBaVuRorChzoHvpfxiSQE8tnfWuREhzNgaeZCw7NCPbXCbkcXmP1G55IrmTwcrN
+wVbtiGrXoDkhBFcsovW8R0FPXjQilbUfKW1eSvNNcr5BViCH/OlQR9cwFO5cjFW6WY2H/CPek9AE
+jP3vbb3QesmlOmpyM8ZKDQUXKi17safY1vC+9D/qDihtQWEjdnjDuGWk81quzMKq2edY3rZ+nYVu
+nyoKb58DKTCXKB28t89UKU5RMfkntigm/qJj5kEW8DOYRwIDAQABo4GeMIGbMB0GA1UdDgQWBBRU
+WssmP3HMlEYNllPqa0jQk/5CdTAOBgNVHQ8BAf8EBAMCAQYwWQYDVR0RBFIwUKROMEwxCzAJBgNV
+BAYTAkpQMRgwFgYDVQQKDA/ml6XmnKzlm73mlL/lupwxIzAhBgNVBAsMGuOCouODl+ODquOCseOD
+vOOCt+ODp+ODs0NBMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBADlqRHZ3ODrs
+o2dGD/mLBqj7apAxzn7s2tGJfHrrLgy9mTLnsCTWw//1sogJhyzjVOGjprIIC8CFqMjSnHH2HZ9g
+/DgzE+Ge3Atf2hZQKXsvcJEPmbo0NI2VdMV+eKlmXb3KIXdCEKxmJj3ekav9FfBv7WxfEPjzFvYD
+io+nEhEMy/0/ecGc/WLuo89UDNErXxc+4z6/wCs+CZv+iKZ+tJIX/COUgb1up8WMwusRRdv4QcmW
+dupwX3kSa+SjB1oF7ydJzyGfikwJcGapJsErEU4z0g781mzSDjJkaP+tBXhfAx2o45CsJOAPQKdL
+rosot4LKGAfmt1t06SAZf7IbiVQ=
+-----END CERTIFICATE-----
+
+GeoTrust Primary Certification Authority - G3
+=============================================
+-----BEGIN CERTIFICATE-----
+MIID/jCCAuagAwIBAgIQFaxulBmyeUtB9iepwxgPHzANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UE
+BhMCVVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA4IEdlb1RydXN0
+IEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFy
+eSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEczMB4XDTA4MDQwMjAwMDAwMFoXDTM3MTIwMTIz
+NTk1OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAo
+YykgMjAwOCBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMT
+LUdlb1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMzCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBANziXmJYHTNXOTIz+uvLh4yn1ErdBojqZI4xmKU4kB6Yzy5j
+K/BGvESyiaHAKAxJcCGVn2TAppMSAmUmhsalifD614SgcK9PGpc/BkTVyetyEH3kMSj7HGHmKAdE
+c5IiaacDiGydY8hS2pgn5whMcD60yRLBxWeDXTPzAxHsatBT4tG6NmCUgLthY2xbF37fQJQeqw3C
+IShwiP/WJmxsYAQlTlV+fe+/lEjetx3dcI0FX4ilm/LC7urRQEFtYjgdVgbFA0dRIBn8exALDmKu
+dlW/X3e+PkkBUz2YJQN2JFodtNuJ6nnltrM7P7pMKEF/BqxqjsHQ9gUdfeZChuOl1UcCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMR5yo6hTgMdHNxr
+2zFblD4/MH8tMA0GCSqGSIb3DQEBCwUAA4IBAQAtxRPPVoB7eni9n64smefv2t+UXglpp+duaIy9
+cr5HqQ6XErhK8WTTOd8lNNTBzU6B8A8ExCSzNJbGpqow32hhc9f5joWJ7w5elShKKiePEI4ufIbE
+Ap7aDHdlDkQNkv39sxY2+hENHYwOB4lqKVb3cvTdFZx3NWZXqxNT2I7BQMXXExZacse3aQHEerGD
+AWh9jUGhlBjBJVz88P6DAod8DQ3PLghcSkANPuyBYeYk28rgDi0Hsj5W3I31QYUHSJsMC8tJP33s
+t/3LjWeJGqvtux6jAAgIFyqCXDFdRootD4abdNlF+9RAsXqqaC2Gspki4cErx5z481+oghLrGREt
+-----END CERTIFICATE-----
+
+thawte Primary Root CA - G2
+===========================
+-----BEGIN CERTIFICATE-----
+MIICiDCCAg2gAwIBAgIQNfwmXNmET8k9Jj1Xm67XVjAKBggqhkjOPQQDAzCBhDELMAkGA1UEBhMC
+VVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjE4MDYGA1UECxMvKGMpIDIwMDcgdGhhd3RlLCBJbmMu
+IC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3Qg
+Q0EgLSBHMjAeFw0wNzExMDUwMDAwMDBaFw0zODAxMTgyMzU5NTlaMIGEMQswCQYDVQQGEwJVUzEV
+MBMGA1UEChMMdGhhd3RlLCBJbmMuMTgwNgYDVQQLEy8oYykgMjAwNyB0aGF3dGUsIEluYy4gLSBG
+b3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIGA1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAt
+IEcyMHYwEAYHKoZIzj0CAQYFK4EEACIDYgAEotWcgnuVnfFSeIf+iha/BebfowJPDQfGAFG6DAJS
+LSKkQjnE/o/qycG+1E3/n3qe4rF8mq2nhglzh9HnmuN6papu+7qzcMBniKI11KOasf2twu8x+qi5
+8/sIxpHR+ymVo0IwQDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQU
+mtgAMADna3+FGO6Lts6KDPgR4bswCgYIKoZIzj0EAwMDaQAwZgIxAN344FdHW6fmCsO99YCKlzUN
+G4k8VIZ3KMqh9HneteY4sPBlcIx/AlTCv//YoT7ZzwIxAMSNlPzcU9LcnXgWHxUzI1NS41oxXZ3K
+rr0TKUQNJ1uo52icEvdYPy5yAlejj6EULg==
+-----END CERTIFICATE-----
+
+thawte Primary Root CA - G3
+===========================
+-----BEGIN CERTIFICATE-----
+MIIEKjCCAxKgAwIBAgIQYAGXt0an6rS0mtZLL/eQ+zANBgkqhkiG9w0BAQsFADCBrjELMAkGA1UE
+BhMCVVMxFTATBgNVBAoTDHRoYXd0ZSwgSW5jLjEoMCYGA1UECxMfQ2VydGlmaWNhdGlvbiBTZXJ2
+aWNlcyBEaXZpc2lvbjE4MDYGA1UECxMvKGMpIDIwMDggdGhhd3RlLCBJbmMuIC0gRm9yIGF1dGhv
+cml6ZWQgdXNlIG9ubHkxJDAiBgNVBAMTG3RoYXd0ZSBQcmltYXJ5IFJvb3QgQ0EgLSBHMzAeFw0w
+ODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIGuMQswCQYDVQQGEwJVUzEVMBMGA1UEChMMdGhh
+d3RlLCBJbmMuMSgwJgYDVQQLEx9DZXJ0aWZpY2F0aW9uIFNlcnZpY2VzIERpdmlzaW9uMTgwNgYD
+VQQLEy8oYykgMjAwOCB0aGF3dGUsIEluYy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTEkMCIG
+A1UEAxMbdGhhd3RlIFByaW1hcnkgUm9vdCBDQSAtIEczMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
+MIIBCgKCAQEAsr8nLPvb2FvdeHsbnndmgcs+vHyu86YnmjSjaDFxODNi5PNxZnmxqWWjpYvVj2At
+P0LMqmsywCPLLEHd5N/8YZzic7IilRFDGF/Eth9XbAoFWCLINkw6fKXRz4aviKdEAhN0cXMKQlkC
++BsUa0Lfb1+6a4KinVvnSr0eAXLbS3ToO39/fR8EtCab4LRarEc9VbjXsCZSKAExQGbY2SS99irY
+7CFJXJv2eul/VTV+lmuNk5Mny5K76qxAwJ/C+IDPXfRa3M50hqY+bAtTyr2SzhkGcuYMXDhpxwTW
+vGzOW/b3aJzcJRVIiKHpqfiYnODz1TEoYRFsZ5aNOZnLwkUkOQIDAQABo0IwQDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUrWyqlGCc7eT/+j4KdCtjA/e2Wb8wDQYJ
+KoZIhvcNAQELBQADggEBABpA2JVlrAmSicY59BDlqQ5mU1143vokkbvnRFHfxhY0Cu9qRFHqKweK
+A3rD6z8KLFIWoCtDuSWQP3CpMyVtRRooOyfPqsMpQhvfO0zAMzRbQYi/aytlryjvsvXDqmbOe1bu
+t8jLZ8HJnBoYuMTDSQPxYA5QzUbF83d597YV4Djbxy8ooAw/dyZ02SUS2jHaGh7cKUGRIjxpp7sC
+8rZcJwOJ9Abqm+RyguOhCcHpABnTPtRwa7pxpqpYrvS76Wy274fMm7v/OeZWYdMKp8RcTGB7BXcm
+er/YB1IsYvdwY9k5vG8cwnncdimvzsUsZAReiDZuMdRAGmI0Nj81Aa6sY6A=
+-----END CERTIFICATE-----
+
+GeoTrust Primary Certification Authority - G2
+=============================================
+-----BEGIN CERTIFICATE-----
+MIICrjCCAjWgAwIBAgIQPLL0SAoA4v7rJDteYD7DazAKBggqhkjOPQQDAzCBmDELMAkGA1UEBhMC
+VVMxFjAUBgNVBAoTDUdlb1RydXN0IEluYy4xOTA3BgNVBAsTMChjKSAyMDA3IEdlb1RydXN0IElu
+Yy4gLSBGb3IgYXV0aG9yaXplZCB1c2Ugb25seTE2MDQGA1UEAxMtR2VvVHJ1c3QgUHJpbWFyeSBD
+ZXJ0aWZpY2F0aW9uIEF1dGhvcml0eSAtIEcyMB4XDTA3MTEwNTAwMDAwMFoXDTM4MDExODIzNTk1
+OVowgZgxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1HZW9UcnVzdCBJbmMuMTkwNwYDVQQLEzAoYykg
+MjAwNyBHZW9UcnVzdCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNlIG9ubHkxNjA0BgNVBAMTLUdl
+b1RydXN0IFByaW1hcnkgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgLSBHMjB2MBAGByqGSM49AgEG
+BSuBBAAiA2IABBWx6P0DFUPlrOuHNxFi79KDNlJ9RVcLSo17VDs6bl8VAsBQps8lL33KSLjHUGMc
+KiEIfJo22Av+0SbFWDEwKCXzXV2juLaltJLtbCyf691DiaI8S0iRHVDsJt/WYC69IaNCMEAwDwYD
+VR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBVfNVdRVfslsq0DafwBo/q+
+EVXVMAoGCCqGSM49BAMDA2cAMGQCMGSWWaboCd6LuvpaiIjwH5HTRqjySkwCY/tsXzjbLkGTqQ7m
+ndwxHLKgpxgceeHHNgIwOlavmnRs9vuD4DPTCF+hnMJbn0bWtsuRBmOiBuczrD6ogRLQy7rQkgu2
+npaqBA+K
+-----END CERTIFICATE-----
+
+VeriSign Universal Root Certification Authority
+===============================================
+-----BEGIN CERTIFICATE-----
+MIIEuTCCA6GgAwIBAgIQQBrEZCGzEyEDDrvkEhrFHTANBgkqhkiG9w0BAQsFADCBvTELMAkGA1UE
+BhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBO
+ZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwOCBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVk
+IHVzZSBvbmx5MTgwNgYDVQQDEy9WZXJpU2lnbiBVbml2ZXJzYWwgUm9vdCBDZXJ0aWZpY2F0aW9u
+IEF1dGhvcml0eTAeFw0wODA0MDIwMDAwMDBaFw0zNzEyMDEyMzU5NTlaMIG9MQswCQYDVQQGEwJV
+UzEXMBUGA1UEChMOVmVyaVNpZ24sIEluYy4xHzAdBgNVBAsTFlZlcmlTaWduIFRydXN0IE5ldHdv
+cmsxOjA4BgNVBAsTMShjKSAyMDA4IFZlcmlTaWduLCBJbmMuIC0gRm9yIGF1dGhvcml6ZWQgdXNl
+IG9ubHkxODA2BgNVBAMTL1ZlcmlTaWduIFVuaXZlcnNhbCBSb290IENlcnRpZmljYXRpb24gQXV0
+aG9yaXR5MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAx2E3XrEBNNti1xWb/1hajCMj
+1mCOkdeQmIN65lgZOIzF9uVkhbSicfvtvbnazU0AtMgtc6XHaXGVHzk8skQHnOgO+k1KxCHfKWGP
+MiJhgsWHH26MfF8WIFFE0XBPV+rjHOPMee5Y2A7Cs0WTwCznmhcrewA3ekEzeOEz4vMQGn+HLL72
+9fdC4uW/h2KJXwBL38Xd5HVEMkE6HnFuacsLdUYI0crSK5XQz/u5QGtkjFdN/BMReYTtXlT2NJ8I
+AfMQJQYXStrxHXpma5hgZqTZ79IugvHw7wnqRMkVauIDbjPTrJ9VAMf2CGqUuV/c4DPxhGD5WycR
+tPwW8rtWaoAljQIDAQABo4GyMIGvMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMG0G
+CCsGAQUFBwEMBGEwX6FdoFswWTBXMFUWCWltYWdlL2dpZjAhMB8wBwYFKw4DAhoEFI/l0xqGrI2O
+a8PPgGrUSBgsexkuMCUWI2h0dHA6Ly9sb2dvLnZlcmlzaWduLmNvbS92c2xvZ28uZ2lmMB0GA1Ud
+DgQWBBS2d/ppSEefUxLVwuoHMnYH0ZcHGTANBgkqhkiG9w0BAQsFAAOCAQEASvj4sAPmLGd75JR3
+Y8xuTPl9Dg3cyLk1uXBPY/ok+myDjEedO2Pzmvl2MpWRsXe8rJq+seQxIcaBlVZaDrHC1LGmWazx
+Y8u4TB1ZkErvkBYoH1quEPuBUDgMbMzxPcP1Y+Oz4yHJJDnp/RVmRvQbEdBNc6N9Rvk97ahfYtTx
+P/jgdFcrGJ2BtMQo2pSXpXDrrB2+BxHw1dvd5Yzw1TKwg+ZX4o+/vqGqvz0dtdQ46tewXDpPaj+P
+wGZsY6rp2aQW9IHRlRQOfc2VNNnSj3BzgXucfr2YYdhFh5iQxeuGMMY1v/D/w1WIg0vvBZIGcfK4
+mJO37M2CYfE45k+XmCpajQ==
+-----END CERTIFICATE-----
+
+VeriSign Class 3 Public Primary Certification Authority - G4
+============================================================
+-----BEGIN CERTIFICATE-----
+MIIDhDCCAwqgAwIBAgIQL4D+I4wOIg9IZxIokYesszAKBggqhkjOPQQDAzCByjELMAkGA1UEBhMC
+VVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBUcnVzdCBOZXR3
+b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRob3JpemVkIHVz
+ZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5IENlcnRpZmlj
+YXRpb24gQXV0aG9yaXR5IC0gRzQwHhcNMDcxMTA1MDAwMDAwWhcNMzgwMTE4MjM1OTU5WjCByjEL
+MAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMR8wHQYDVQQLExZWZXJpU2lnbiBU
+cnVzdCBOZXR3b3JrMTowOAYDVQQLEzEoYykgMjAwNyBWZXJpU2lnbiwgSW5jLiAtIEZvciBhdXRo
+b3JpemVkIHVzZSBvbmx5MUUwQwYDVQQDEzxWZXJpU2lnbiBDbGFzcyAzIFB1YmxpYyBQcmltYXJ5
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5IC0gRzQwdjAQBgcqhkjOPQIBBgUrgQQAIgNiAASnVnp8
+Utpkmw4tXNherJI9/gHmGUo9FANL+mAnINmDiWn6VMaaGF5VKmTeBvaNSjutEDxlPZCIBIngMGGz
+rl0Bp3vefLK+ymVhAIau2o970ImtTR1ZmkGxvEeA3J5iw/mjgbIwga8wDwYDVR0TAQH/BAUwAwEB
+/zAOBgNVHQ8BAf8EBAMCAQYwbQYIKwYBBQUHAQwEYTBfoV2gWzBZMFcwVRYJaW1hZ2UvZ2lmMCEw
+HzAHBgUrDgMCGgQUj+XTGoasjY5rw8+AatRIGCx7GS4wJRYjaHR0cDovL2xvZ28udmVyaXNpZ24u
+Y29tL3ZzbG9nby5naWYwHQYDVR0OBBYEFLMWkf3upm7ktS5Jj4d4gYDs5bG1MAoGCCqGSM49BAMD
+A2gAMGUCMGYhDBgmYFo4e1ZC4Kf8NoRRkSAsdk1DPcQdhCPQrNZ8NQbOzWm9kA3bbEhCHQ6qQgIx
+AJw9SDkjOVgaFRJZap7v1VmyHVIsmXHNxynfGyphe3HR3vPA5Q06Sqotp9iGKt0uEA==
+-----END CERTIFICATE-----
+
+NetLock Arany (Class Gold) Főtanúsítvány
+============================================
+-----BEGIN CERTIFICATE-----
+MIIEFTCCAv2gAwIBAgIGSUEs5AAQMA0GCSqGSIb3DQEBCwUAMIGnMQswCQYDVQQGEwJIVTERMA8G
+A1UEBwwIQnVkYXBlc3QxFTATBgNVBAoMDE5ldExvY2sgS2Z0LjE3MDUGA1UECwwuVGFuw7pzw610
+dsOhbnlraWFkw7NrIChDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzKTE1MDMGA1UEAwwsTmV0TG9jayBB
+cmFueSAoQ2xhc3MgR29sZCkgRsWRdGFuw7pzw610dsOhbnkwHhcNMDgxMjExMTUwODIxWhcNMjgx
+MjA2MTUwODIxWjCBpzELMAkGA1UEBhMCSFUxETAPBgNVBAcMCEJ1ZGFwZXN0MRUwEwYDVQQKDAxO
+ZXRMb2NrIEtmdC4xNzA1BgNVBAsMLlRhbsO6c8OtdHbDoW55a2lhZMOzayAoQ2VydGlmaWNhdGlv
+biBTZXJ2aWNlcykxNTAzBgNVBAMMLE5ldExvY2sgQXJhbnkgKENsYXNzIEdvbGQpIEbFkXRhbsO6
+c8OtdHbDoW55MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxCRec75LbRTDofTjl5Bu
+0jBFHjzuZ9lk4BqKf8owyoPjIMHj9DrTlF8afFttvzBPhCf2nx9JvMaZCpDyD/V/Q4Q3Y1GLeqVw
+/HpYzY6b7cNGbIRwXdrzAZAj/E4wqX7hJ2Pn7WQ8oLjJM2P+FpD/sLj916jAwJRDC7bVWaaeVtAk
+H3B5r9s5VA1lddkVQZQBr17s9o3x/61k/iCa11zr/qYfCGSji3ZVrR47KGAuhyXoqq8fxmRGILdw
+fzzeSNuWU7c5d+Qa4scWhHaXWy+7GRWF+GmF9ZmnqfI0p6m2pgP8b4Y9VHx2BJtr+UBdADTHLpl1
+neWIA6pN+APSQnbAGwIDAKiLo0UwQzASBgNVHRMBAf8ECDAGAQH/AgEEMA4GA1UdDwEB/wQEAwIB
+BjAdBgNVHQ4EFgQUzPpnk/C2uNClwB7zU/2MU9+D15YwDQYJKoZIhvcNAQELBQADggEBAKt/7hwW
+qZw8UQCgwBEIBaeZ5m8BiFRhbvG5GK1Krf6BQCOUL/t1fC8oS2IkgYIL9WHxHG64YTjrgfpioTta
+YtOUZcTh5m2C+C8lcLIhJsFyUR+MLMOEkMNaj7rP9KdlpeuY0fsFskZ1FSNqb4VjMIDw1Z4fKRzC
+bLBQWV2QWzuoDTDPv31/zvGdg73JRm4gpvlhUbohL3u+pRVjodSVh/GeufOJ8z2FuLjbvrW5Kfna
+NwUASZQDhETnv0Mxz3WLJdH0pmT1kvarBes96aULNmLazAZfNou2XjG4Kvte9nHfRCaexOYNkbQu
+dZWAUWpLMKawYqGT8ZvYzsRjdT9ZR7E=
+-----END CERTIFICATE-----
+
+Staat der Nederlanden Root CA - G2
+==================================
+-----BEGIN CERTIFICATE-----
+MIIFyjCCA7KgAwIBAgIEAJiWjDANBgkqhkiG9w0BAQsFADBaMQswCQYDVQQGEwJOTDEeMBwGA1UE
+CgwVU3RhYXQgZGVyIE5lZGVybGFuZGVuMSswKQYDVQQDDCJTdGFhdCBkZXIgTmVkZXJsYW5kZW4g
+Um9vdCBDQSAtIEcyMB4XDTA4MDMyNjExMTgxN1oXDTIwMDMyNTExMDMxMFowWjELMAkGA1UEBhMC
+TkwxHjAcBgNVBAoMFVN0YWF0IGRlciBOZWRlcmxhbmRlbjErMCkGA1UEAwwiU3RhYXQgZGVyIE5l
+ZGVybGFuZGVuIFJvb3QgQ0EgLSBHMjCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMVZ
+5291qj5LnLW4rJ4L5PnZyqtdj7U5EILXr1HgO+EASGrP2uEGQxGZqhQlEq0i6ABtQ8SpuOUfiUtn
+vWFI7/3S4GCI5bkYYCjDdyutsDeqN95kWSpGV+RLufg3fNU254DBtvPUZ5uW6M7XxgpT0GtJlvOj
+CwV3SPcl5XCsMBQgJeN/dVrlSPhOewMHBPqCYYdu8DvEpMfQ9XQ+pV0aCPKbJdL2rAQmPlU6Yiil
+e7Iwr/g3wtG61jj99O9JMDeZJiFIhQGp5Rbn3JBV3w/oOM2ZNyFPXfUib2rFEhZgF1XyZWampzCR
+OME4HYYEhLoaJXhena/MUGDWE4dS7WMfbWV9whUYdMrhfmQpjHLYFhN9C0lK8SgbIHRrxT3dsKpI
+CT0ugpTNGmXZK4iambwYfp/ufWZ8Pr2UuIHOzZgweMFvZ9C+X+Bo7d7iscksWXiSqt8rYGPy5V65
+48r6f1CGPqI0GAwJaCgRHOThuVw+R7oyPxjMW4T182t0xHJ04eOLoEq9jWYv6q012iDTiIJh8BIi
+trzQ1aTsr1SIJSQ8p22xcik/Plemf1WvbibG/ufMQFxRRIEKeN5KzlW/HdXZt1bv8Hb/C3m1r737
+qWmRRpdogBQ2HbN/uymYNqUg+oJgYjOk7Na6B6duxc8UpufWkjTYgfX8HV2qXB72o007uPc5AgMB
+AAGjgZcwgZQwDwYDVR0TAQH/BAUwAwEB/zBSBgNVHSAESzBJMEcGBFUdIAAwPzA9BggrBgEFBQcC
+ARYxaHR0cDovL3d3dy5wa2lvdmVyaGVpZC5ubC9wb2xpY2llcy9yb290LXBvbGljeS1HMjAOBgNV
+HQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJFoMocVHYnitfGsNig0jQt8YojrMA0GCSqGSIb3DQEBCwUA
+A4ICAQCoQUpnKpKBglBu4dfYszk78wIVCVBR7y29JHuIhjv5tLySCZa59sCrI2AGeYwRTlHSeYAz
++51IvuxBQ4EffkdAHOV6CMqqi3WtFMTC6GY8ggen5ieCWxjmD27ZUD6KQhgpxrRW/FYQoAUXvQwj
+f/ST7ZwaUb7dRUG/kSS0H4zpX897IZmflZ85OkYcbPnNe5yQzSipx6lVu6xiNGI1E0sUOlWDuYaN
+kqbG9AclVMwWVxJKgnjIFNkXgiYtXSAfea7+1HAWFpWD2DU5/1JddRwWxRNVz0fMdWVSSt7wsKfk
+CpYL+63C4iWEst3kvX5ZbJvw8NjnyvLplzh+ib7M+zkXYT9y2zqR2GUBGR2tUKRXCnxLvJxxcypF
+URmFzI79R6d0lR2o0a9OF7FpJsKqeFdbxU2n5Z4FF5TKsl+gSRiNNOkmbEgeqmiSBeGCc1qb3Adb
+CG19ndeNIdn8FCCqwkXfP+cAslHkwvgFuXkajDTznlvkN1trSt8sV4pAWja63XVECDdCcAz+3F4h
+oKOKwJCcaNpQ5kUQR3i2TtJlycM33+FCY7BXN0Ute4qcvwXqZVUz9zkQxSgqIXobisQk+T8VyJoV
+IPVVYpbtbZNQvOSqeK3Zywplh6ZmwcSBo3c6WB4L7oOLnR7SUqTMHW+wmG2UMbX4cQrcufx9MmDm
+66+KAQ==
+-----END CERTIFICATE-----
+
+CA Disig
+========
+-----BEGIN CERTIFICATE-----
+MIIEDzCCAvegAwIBAgIBATANBgkqhkiG9w0BAQUFADBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMK
+QnJhdGlzbGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwHhcNMDYw
+MzIyMDEzOTM0WhcNMTYwMzIyMDEzOTM0WjBKMQswCQYDVQQGEwJTSzETMBEGA1UEBxMKQnJhdGlz
+bGF2YTETMBEGA1UEChMKRGlzaWcgYS5zLjERMA8GA1UEAxMIQ0EgRGlzaWcwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQCS9jHBfYj9mQGp2HvycXXxMcbzdWb6UShGhJd4NLxs/LxFWYgm
+GErENx+hSkS943EE9UQX4j/8SFhvXJ56CbpRNyIjZkMhsDxkovhqFQ4/61HhVKndBpnXmjxUizkD
+Pw/Fzsbrg3ICqB9x8y34dQjbYkzo+s7552oftms1grrijxaSfQUMbEYDXcDtab86wYqg6I7ZuUUo
+hwjstMoVvoLdtUSLLa2GDGhibYVW8qwUYzrG0ZmsNHhWS8+2rT+MitcE5eN4TPWGqvWP+j1scaMt
+ymfraHtuM6kMgiioTGohQBUgDCZbg8KpFhXAJIJdKxatymP2dACw30PEEGBWZ2NFAgMBAAGjgf8w
+gfwwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUjbJJaJ1yCCW5wCf1UJNWSEZx+Y8wDgYDVR0P
+AQH/BAQDAgEGMDYGA1UdEQQvMC2BE2Nhb3BlcmF0b3JAZGlzaWcuc2uGFmh0dHA6Ly93d3cuZGlz
+aWcuc2svY2EwZgYDVR0fBF8wXTAtoCugKYYnaHR0cDovL3d3dy5kaXNpZy5zay9jYS9jcmwvY2Ff
+ZGlzaWcuY3JsMCygKqAohiZodHRwOi8vY2EuZGlzaWcuc2svY2EvY3JsL2NhX2Rpc2lnLmNybDAa
+BgNVHSAEEzARMA8GDSuBHpGT5goAAAABAQEwDQYJKoZIhvcNAQEFBQADggEBAF00dGFMrzvY/59t
+WDYcPQuBDRIrRhCA/ec8J9B6yKm2fnQwM6M6int0wHl5QpNt/7EpFIKrIYwvF/k/Ji/1WcbvgAa3
+mkkp7M5+cTxqEEHA9tOasnxakZzArFvITV734VP/Q3f8nktnbNfzg9Gg4H8l37iYC5oyOGwwoPP/
+CBUz91BKez6jPiCp3C9WgArtQVCwyfTssuMmRAAOb54GvCKWU3BlxFAKRmukLyeBEicTXxChds6K
+ezfqwzlhA5WYOudsiCUI/HloDYd9Yvi0X/vF2Ey9WLw/Q1vUHgFNPGO+I++MzVpQuGhU+QqZMxEA
+4Z7CRneC9VkGjCFMhwnN5ag=
+-----END CERTIFICATE-----
+
+Juur-SK
+=======
+-----BEGIN CERTIFICATE-----
+MIIE5jCCA86gAwIBAgIEO45L/DANBgkqhkiG9w0BAQUFADBdMRgwFgYJKoZIhvcNAQkBFglwa2lA
+c2suZWUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKExlBUyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMRAw
+DgYDVQQDEwdKdXVyLVNLMB4XDTAxMDgzMDE0MjMwMVoXDTE2MDgyNjE0MjMwMVowXTEYMBYGCSqG
+SIb3DQEJARYJcGtpQHNrLmVlMQswCQYDVQQGEwJFRTEiMCAGA1UEChMZQVMgU2VydGlmaXRzZWVy
+aW1pc2tlc2t1czEQMA4GA1UEAxMHSnV1ci1TSzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
+ggEBAIFxNj4zB9bjMI0TfncyRsvPGbJgMUaXhvSYRqTCZUXP00B841oiqBB4M8yIsdOBSvZiF3tf
+TQou0M+LI+5PAk676w7KvRhj6IAcjeEcjT3g/1tf6mTll+g/mX8MCgkzABpTpyHhOEvWgxutr2TC
++Rx6jGZITWYfGAriPrsfB2WThbkasLnE+w0R9vXW+RvHLCu3GFH+4Hv2qEivbDtPL+/40UceJlfw
+UR0zlv/vWT3aTdEVNMfqPxZIe5EcgEMPPbgFPtGzlc3Yyg/CQ2fbt5PgIoIuvvVoKIO5wTtpeyDa
+Tpxt4brNj3pssAki14sL2xzVWiZbDcDq5WDQn/413z8CAwEAAaOCAawwggGoMA8GA1UdEwEB/wQF
+MAMBAf8wggEWBgNVHSAEggENMIIBCTCCAQUGCisGAQQBzh8BAQEwgfYwgdAGCCsGAQUFBwICMIHD
+HoHAAFMAZQBlACAAcwBlAHIAdABpAGYAaQBrAGEAYQB0ACAAbwBuACAAdgDkAGwAagBhAHMAdABh
+AHQAdQBkACAAQQBTAC0AaQBzACAAUwBlAHIAdABpAGYAaQB0AHMAZQBlAHIAaQBtAGkAcwBrAGUA
+cwBrAHUAcwAgAGEAbABhAG0ALQBTAEsAIABzAGUAcgB0AGkAZgBpAGsAYQBhAHQAaQBkAGUAIABr
+AGkAbgBuAGkAdABhAG0AaQBzAGUAawBzMCEGCCsGAQUFBwIBFhVodHRwOi8vd3d3LnNrLmVlL2Nw
+cy8wKwYDVR0fBCQwIjAgoB6gHIYaaHR0cDovL3d3dy5zay5lZS9qdXVyL2NybC8wHQYDVR0OBBYE
+FASqekej5ImvGs8KQKcYP2/v6X2+MB8GA1UdIwQYMBaAFASqekej5ImvGs8KQKcYP2/v6X2+MA4G
+A1UdDwEB/wQEAwIB5jANBgkqhkiG9w0BAQUFAAOCAQEAe8EYlFOiCfP+JmeaUOTDBS8rNXiRTHyo
+ERF5TElZrMj3hWVcRrs7EKACr81Ptcw2Kuxd/u+gkcm2k298gFTsxwhwDY77guwqYHhpNjbRxZyL
+abVAyJRld/JXIWY7zoVAtjNjGr95HvxcHdMdkxuLDF2FvZkwMhgJkVLpfKG6/2SSmuz+Ne6ML678
+IIbsSt4beDI3poHSna9aEhbKmVv8b20OxaAehsmR0FyYgl9jDIpaq9iVpszLita/ZEuOyoqysOkh
+Mp6qqIWYNIE5ITuoOlIyPfZrN4YGWhWY3PARZv40ILcD9EEQfTmEeZZyY7aWAuVrua0ZTbvGRNs2
+yyqcjg==
+-----END CERTIFICATE-----
+
+Hongkong Post Root CA 1
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDMDCCAhigAwIBAgICA+gwDQYJKoZIhvcNAQEFBQAwRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoT
+DUhvbmdrb25nIFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMB4XDTAzMDUx
+NTA1MTMxNFoXDTIzMDUxNTA0NTIyOVowRzELMAkGA1UEBhMCSEsxFjAUBgNVBAoTDUhvbmdrb25n
+IFBvc3QxIDAeBgNVBAMTF0hvbmdrb25nIFBvc3QgUm9vdCBDQSAxMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEArP84tulmAknjorThkPlAj3n54r15/gK97iSSHSL22oVyaf7XPwnU3ZG1
+ApzQjVrhVcNQhrkpJsLj2aDxaQMoIIBFIi1WpztUlVYiWR8o3x8gPW2iNr4joLFutbEnPzlTCeqr
+auh0ssJlXI6/fMN4hM2eFvz1Lk8gKgifd/PFHsSaUmYeSF7jEAaPIpjhZY4bXSNmO7ilMlHIhqqh
+qZ5/dpTCpmy3QfDVyAY45tQM4vM7TG1QjMSDJ8EThFk9nnV0ttgCXjqQesBCNnLsak3c78QA3xMY
+V18meMjWCnl3v/evt3a5pQuEF10Q6m/hq5URX208o1xNg1vysxmKgIsLhwIDAQABoyYwJDASBgNV
+HRMBAf8ECDAGAQH/AgEDMA4GA1UdDwEB/wQEAwIBxjANBgkqhkiG9w0BAQUFAAOCAQEADkbVPK7i
+h9legYsCmEEIjEy82tvuJxuC52pF7BaLT4Wg87JwvVqWuspube5Gi27nKi6Wsxkz67SfqLI37pio
+l7Yutmcn1KZJ/RyTZXaeQi/cImyaT/JaFTmxcdcrUehtHJjA2Sr0oYJ71clBoiMBdDhViw+5Lmei
+IAQ32pwL0xch4I+XeTRvhEgCIDMb5jREn5Fw9IBehEPCKdJsEhTkYY2sEJCehFC78JZvRZ+K88ps
+T/oROhUVRsPNH4NbLUES7VBnQRM9IauUiqpOfMGx+6fWtScvl6tu4B3i0RwsH0Ti/L6RoZz71ilT
+c4afU9hDDl3WY4JxHYB0yvbiAmvZWg==
+-----END CERTIFICATE-----
+
+SecureSign RootCA11
+===================
+-----BEGIN CERTIFICATE-----
+MIIDbTCCAlWgAwIBAgIBATANBgkqhkiG9w0BAQUFADBYMQswCQYDVQQGEwJKUDErMCkGA1UEChMi
+SmFwYW4gQ2VydGlmaWNhdGlvbiBTZXJ2aWNlcywgSW5jLjEcMBoGA1UEAxMTU2VjdXJlU2lnbiBS
+b290Q0ExMTAeFw0wOTA0MDgwNDU2NDdaFw0yOTA0MDgwNDU2NDdaMFgxCzAJBgNVBAYTAkpQMSsw
+KQYDVQQKEyJKYXBhbiBDZXJ0aWZpY2F0aW9uIFNlcnZpY2VzLCBJbmMuMRwwGgYDVQQDExNTZWN1
+cmVTaWduIFJvb3RDQTExMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA/XeqpRyQBTvL
+TJszi1oURaTnkBbR31fSIRCkF/3frNYfp+TbfPfs37gD2pRY/V1yfIw/XwFndBWW4wI8h9uuywGO
+wvNmxoVF9ALGOrVisq/6nL+k5tSAMJjzDbaTj6nU2DbysPyKyiyhFTOVMdrAG/LuYpmGYz+/3ZMq
+g6h2uRMft85OQoWPIucuGvKVCbIFtUROd6EgvanyTgp9UK31BQ1FT0Zx/Sg+U/sE2C3XZR1KG/rP
+O7AxmjVuyIsG0wCR8pQIZUyxNAYAeoni8McDWc/V1uinMrPmmECGxc0nEovMe863ETxiYAcjPitA
+bpSACW22s293bzUIUPsCh8U+iQIDAQABo0IwQDAdBgNVHQ4EFgQUW/hNT7KlhtQ60vFjmqC+CfZX
+t94wDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wDQYJKoZIhvcNAQEFBQADggEBAKCh
+OBZmLqdWHyGcBvod7bkixTgm2E5P7KN/ed5GIaGHd48HCJqypMWvDzKYC3xmKbabfSVSSUOrTC4r
+bnpwrxYO4wJs+0LmGJ1F2FXI6Dvd5+H0LgscNFxsWEr7jIhQX5Ucv+2rIrVls4W6ng+4reV6G4pQ
+Oh29Dbx7VFALuUKvVaAYga1lme++5Jy/xIWrQbJUb9wlze144o4MjQlJ3WN7WmmWAiGovVJZ6X01
+y8hSyn+B/tlr0/cR7SXf+Of5pPpyl4RTDaXQMhhRdlkUbA/r7F+AjHVDg8OFmP9Mni0N5HeDk061
+lgeLKBObjBmNQSdJQO7e5iNEOdyhIta6A/I=
+-----END CERTIFICATE-----
+
+ACEDICOM Root
+=============
+-----BEGIN CERTIFICATE-----
+MIIFtTCCA52gAwIBAgIIYY3HhjsBggUwDQYJKoZIhvcNAQEFBQAwRDEWMBQGA1UEAwwNQUNFRElD
+T00gUm9vdDEMMAoGA1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMB4XDTA4
+MDQxODE2MjQyMloXDTI4MDQxMzE2MjQyMlowRDEWMBQGA1UEAwwNQUNFRElDT00gUm9vdDEMMAoG
+A1UECwwDUEtJMQ8wDQYDVQQKDAZFRElDT00xCzAJBgNVBAYTAkVTMIICIjANBgkqhkiG9w0BAQEF
+AAOCAg8AMIICCgKCAgEA/5KV4WgGdrQsyFhIyv2AVClVYyT/kGWbEHV7w2rbYgIB8hiGtXxaOLHk
+WLn709gtn70yN78sFW2+tfQh0hOR2QetAQXW8713zl9CgQr5auODAKgrLlUTY4HKRxx7XBZXehuD
+YAQ6PmXDzQHe3qTWDLqO3tkE7hdWIpuPY/1NFgu3e3eM+SW10W2ZEi5PGrjm6gSSrj0RuVFCPYew
+MYWveVqc/udOXpJPQ/yrOq2lEiZmueIM15jO1FillUAKt0SdE3QrwqXrIhWYENiLxQSfHY9g5QYb
+m8+5eaA9oiM/Qj9r+hwDezCNzmzAv+YbX79nuIQZ1RXve8uQNjFiybwCq0Zfm/4aaJQ0PZCOrfbk
+HQl/Sog4P75n/TSW9R28MHTLOO7VbKvU/PQAtwBbhTIWdjPp2KOZnQUAqhbm84F9b32qhm2tFXTT
+xKJxqvQUfecyuB+81fFOvW8XAjnXDpVCOscAPukmYxHqC9FK/xidstd7LzrZlvvoHpKuE1XI2Sf2
+3EgbsCTBheN3nZqk8wwRHQ3ItBTutYJXCb8gWH8vIiPYcMt5bMlL8qkqyPyHK9caUPgn6C9D4zq9
+2Fdx/c6mUlv53U3t5fZvie27k5x2IXXwkkwp9y+cAS7+UEaeZAwUswdbxcJzbPEHXEUkFDWug/Fq
+TYl6+rPYLWbwNof1K1MCAwEAAaOBqjCBpzAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFKaz
+4SsrSbbXc6GqlPUB53NlTKxQMA4GA1UdDwEB/wQEAwIBhjAdBgNVHQ4EFgQUprPhKytJttdzoaqU
+9QHnc2VMrFAwRAYDVR0gBD0wOzA5BgRVHSAAMDEwLwYIKwYBBQUHAgEWI2h0dHA6Ly9hY2VkaWNv
+bS5lZGljb21ncm91cC5jb20vZG9jMA0GCSqGSIb3DQEBBQUAA4ICAQDOLAtSUWImfQwng4/F9tqg
+aHtPkl7qpHMyEVNEskTLnewPeUKzEKbHDZ3Ltvo/Onzqv4hTGzz3gvoFNTPhNahXwOf9jU8/kzJP
+eGYDdwdY6ZXIfj7QeQCM8htRM5u8lOk6e25SLTKeI6RF+7YuE7CLGLHdztUdp0J/Vb77W7tH1Pwk
+zQSulgUV1qzOMPPKC8W64iLgpq0i5ALudBF/TP94HTXa5gI06xgSYXcGCRZj6hitoocf8seACQl1
+ThCojz2GuHURwCRiipZ7SkXp7FnFvmuD5uHorLUwHv4FB4D54SMNUI8FmP8sX+g7tq3PgbUhh8oI
+KiMnMCArz+2UW6yyetLHKKGKC5tNSixthT8Jcjxn4tncB7rrZXtaAWPWkFtPF2Y9fwsZo5NjEFIq
+nxQWWOLcpfShFosOkYuByptZ+thrkQdlVV9SH686+5DdaaVbnG0OLLb6zqylfDJKZ0DcMDQj3dcE
+I2bw/FWAp/tmGYI1Z2JwOV5vx+qQQEQIHriy1tvuWacNGHk0vFQYXlPKNFHtRQrmjseCNj6nOGOp
+MCwXEGCSn1WHElkQwg9naRHMTh5+Spqtr0CodaxWkHS4oJyleW/c6RrIaQXpuvoDs3zk4E7Czp3o
+tkYNbn5XOmeUwssfnHdKZ05phkOTOPu220+DkdRgfks+KzgHVZhepA==
+-----END CERTIFICATE-----
+
+Verisign Class 1 Public Primary Certification Authority
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCED9pHoGc8JpK83P/uUii5N0wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAxIFB1YmxpYyBQcmltYXJ5
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow
+XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAx
+IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDlGb9to1ZhLZlIcfZn3rmN67eehoAKkQ76OCWvRoiC5XOooJskXQ0fzGVuDLDQ
+VoQYh5oGmxChc9+0WDlrbsH2FdWoqD+qEgaNMax/sDTXjzRniAnNFBHiTkVWaR94AoDa3EeRKbs2
+yWNcxeDXLYd7obcysHswuiovMaruo2fa2wIDAQABMA0GCSqGSIb3DQEBBQUAA4GBAFgVKTk8d6Pa
+XCUDfGD67gmZPCcQcMgMCeazh88K4hiWNWLMv5sneYlfycQJ9M61Hd8qveXbhpxoJeUwfLaJFf5n
+0a3hUKw8fGJLj7qE1xIVGx/KXQ/BUpQqEZnae88MNhPVNdwQGVnqlMEAv3WP2fr9dgTbYruQagPZ
+RjXZ+Hxb
+-----END CERTIFICATE-----
+
+Verisign Class 3 Public Primary Certification Authority
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIICPDCCAaUCEDyRMcsf9tAbDpq40ES/Er4wDQYJKoZIhvcNAQEFBQAwXzELMAkGA1UEBhMCVVMx
+FzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAzIFB1YmxpYyBQcmltYXJ5
+IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MB4XDTk2MDEyOTAwMDAwMFoXDTI4MDgwMjIzNTk1OVow
+XzELMAkGA1UEBhMCVVMxFzAVBgNVBAoTDlZlcmlTaWduLCBJbmMuMTcwNQYDVQQLEy5DbGFzcyAz
+IFB1YmxpYyBQcmltYXJ5IENlcnRpZmljYXRpb24gQXV0aG9yaXR5MIGfMA0GCSqGSIb3DQEBAQUA
+A4GNADCBiQKBgQDJXFme8huKARS0EN8EQNvjV69qRUCPhAwL0TPZ2RHP7gJYHyX3KqhEBarsAx94
+f56TuZoAqiN91qyFomNFx3InzPRMxnVx0jnvT0Lwdd8KkMaOIG+YD/isI19wKTakyYbnsZogy1Ol
+hec9vn2a/iRFM9x2Fe0PonFkTGUugWhFpwIDAQABMA0GCSqGSIb3DQEBBQUAA4GBABByUqkFFBky
+CEHwxWsKzH4PIRnN5GfcX6kb5sroc50i2JhucwNhkcV8sEVAbkSdjbCxlnRhLQ2pRdKkkirWmnWX
+bj9T/UWZYB2oK0z5XqcJ2HUw19JlYD1n1khVdWk/kfVIC0dpImmClr7JyDiGSnoscxlIaU5rfGW/
+D/xwzoiQ
+-----END CERTIFICATE-----
+
+Microsec e-Szigno Root CA 2009
+==============================
+-----BEGIN CERTIFICATE-----
+MIIECjCCAvKgAwIBAgIJAMJ+QwRORz8ZMA0GCSqGSIb3DQEBCwUAMIGCMQswCQYDVQQGEwJIVTER
+MA8GA1UEBwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jv
+c2VjIGUtU3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5o
+dTAeFw0wOTA2MTYxMTMwMThaFw0yOTEyMzAxMTMwMThaMIGCMQswCQYDVQQGEwJIVTERMA8GA1UE
+BwwIQnVkYXBlc3QxFjAUBgNVBAoMDU1pY3Jvc2VjIEx0ZC4xJzAlBgNVBAMMHk1pY3Jvc2VjIGUt
+U3ppZ25vIFJvb3QgQ0EgMjAwOTEfMB0GCSqGSIb3DQEJARYQaW5mb0BlLXN6aWduby5odTCCASIw
+DQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAOn4j/NjrdqG2KfgQvvPkd6mJviZpWNwrZuuyjNA
+fW2WbqEORO7hE52UQlKavXWFdCyoDh2Tthi3jCyoz/tccbna7P7ofo/kLx2yqHWH2Leh5TvPmUpG
+0IMZfcChEhyVbUr02MelTTMuhTlAdX4UfIASmFDHQWe4oIBhVKZsTh/gnQ4H6cm6M+f+wFUoLAKA
+pxn1ntxVUwOXewdI/5n7N4okxFnMUBBjjqqpGrCEGob5X7uxUG6k0QrM1XF+H6cbfPVTbiJfyyvm
+1HxdrtbCxkzlBQHZ7Vf8wSN5/PrIJIOV87VqUQHQd9bpEqH5GoP7ghu5sJf0dgYzQ0mg/wu1+rUC
+AwEAAaOBgDB+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBTLD8bf
+QkPMPcu1SCOhGnqmKrs0aDAfBgNVHSMEGDAWgBTLD8bfQkPMPcu1SCOhGnqmKrs0aDAbBgNVHREE
+FDASgRBpbmZvQGUtc3ppZ25vLmh1MA0GCSqGSIb3DQEBCwUAA4IBAQDJ0Q5eLtXMs3w+y/w9/w0o
+lZMEyL/azXm4Q5DwpL7v8u8hmLzU1F0G9u5C7DBsoKqpyvGvivo/C3NqPuouQH4frlRheesuCDfX
+I/OMn74dseGkddug4lQUsbocKaQY9hK6ohQU4zE1yED/t+AFdlfBHFny+L/k7SViXITwfn4fs775
+tyERzAMBVnCnEJIeGzSBHq2cGsMEPO0CYdYeBvNfOofyK/FFh+U9rNHHV4S9a67c2Pm2G2JwCz02
+yULyMtd6YebS2z3PyKnJm9zbWETXbzivf3jTo60adbocwTZ8jx5tHMN1Rq41Bab2XD0h7lbwyYIi
+LXpUq3DDfSJlgnCW
+-----END CERTIFICATE-----
+
+E-Guven Kok Elektronik Sertifika Hizmet Saglayicisi
+===================================================
+-----BEGIN CERTIFICATE-----
+MIIDtjCCAp6gAwIBAgIQRJmNPMADJ72cdpW56tustTANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
+EwJUUjEoMCYGA1UEChMfRWxla3Ryb25payBCaWxnaSBHdXZlbmxpZ2kgQS5TLjE8MDoGA1UEAxMz
+ZS1HdXZlbiBLb2sgRWxla3Ryb25payBTZXJ0aWZpa2EgSGl6bWV0IFNhZ2xheWljaXNpMB4XDTA3
+MDEwNDExMzI0OFoXDTE3MDEwNDExMzI0OFowdTELMAkGA1UEBhMCVFIxKDAmBgNVBAoTH0VsZWt0
+cm9uaWsgQmlsZ2kgR3V2ZW5saWdpIEEuUy4xPDA6BgNVBAMTM2UtR3V2ZW4gS29rIEVsZWt0cm9u
+aWsgU2VydGlmaWthIEhpem1ldCBTYWdsYXlpY2lzaTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBAMMSIJ6wXgBljU5Gu4Bc6SwGl9XzcslwuedLZYDBS75+PNdUMZTe1RK6UxYC6lhj71vY
+8+0qGqpxSKPcEC1fX+tcS5yWCEIlKBHMilpiAVDV6wlTL/jDj/6z/P2douNffb7tC+Bg62nsM+3Y
+jfsSSYMAyYuXjDtzKjKzEve5TfL0TW3H5tYmNwjy2f1rXKPlSFxYvEK+A1qBuhw1DADT9SN+cTAI
+JjjcJRFHLfO6IxClv7wC90Nex/6wN1CZew+TzuZDLMN+DfIcQ2Zgy2ExR4ejT669VmxMvLz4Bcpk
+9Ok0oSy1c+HCPujIyTQlCFzz7abHlJ+tiEMl1+E5YP6sOVkCAwEAAaNCMEAwDgYDVR0PAQH/BAQD
+AgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYEFJ/uRLOU1fqRTy7ZVZoEVtstxNulMA0GCSqG
+SIb3DQEBBQUAA4IBAQB/X7lTW2M9dTLn+sR0GstG30ZpHFLPqk/CaOv/gKlR6D1id4k9CnU58W5d
+F4dvaAXBlGzZXd/aslnLpRCKysw5zZ/rTt5S/wzw9JKp8mxTq5vSR6AfdPebmvEvFZ96ZDAYBzwq
+D2fK/A+JYZ1lpTzlvBNbCNvj/+27BrtqBrF6T2XGgv0enIu1De5Iu7i9qgi0+6N8y5/NkHZchpZ4
+Vwpm+Vganf2XKWDeEaaQHBkc7gGWIjQ0LpH5t8Qn0Xvmv/uARFoW5evg1Ao4vOSR49XrXMGs3xtq
+fJ7lddK2l4fbzIcrQzqECK+rPNv3PGYxhrCdU3nt+CPeQuMtgvEP5fqX
+-----END CERTIFICATE-----
+
+GlobalSign Root CA - R3
+=======================
+-----BEGIN CERTIFICATE-----
+MIIDXzCCAkegAwIBAgILBAAAAAABIVhTCKIwDQYJKoZIhvcNAQELBQAwTDEgMB4GA1UECxMXR2xv
+YmFsU2lnbiBSb290IENBIC0gUjMxEzARBgNVBAoTCkdsb2JhbFNpZ24xEzARBgNVBAMTCkdsb2Jh
+bFNpZ24wHhcNMDkwMzE4MTAwMDAwWhcNMjkwMzE4MTAwMDAwWjBMMSAwHgYDVQQLExdHbG9iYWxT
+aWduIFJvb3QgQ0EgLSBSMzETMBEGA1UEChMKR2xvYmFsU2lnbjETMBEGA1UEAxMKR2xvYmFsU2ln
+bjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMwldpB5BngiFvXAg7aEyiie/QV2EcWt
+iHL8RgJDx7KKnQRfJMsuS+FggkbhUqsMgUdwbN1k0ev1LKMPgj0MK66X17YUhhB5uzsTgHeMCOFJ
+0mpiLx9e+pZo34knlTifBtc+ycsmWQ1z3rDI6SYOgxXG71uL0gRgykmmKPZpO/bLyCiR5Z2KYVc3
+rHQU3HTgOu5yLy6c+9C7v/U9AOEGM+iCK65TpjoWc4zdQQ4gOsC0p6Hpsk+QLjJg6VfLuQSSaGjl
+OCZgdbKfd/+RFO+uIEn8rUAVSNECMWEZXriX7613t2Saer9fwRPvm2L7DWzgVGkWqQPabumDk3F2
+xmmFghcCAwEAAaNCMEAwDgYDVR0PAQH/BAQDAgEGMA8GA1UdEwEB/wQFMAMBAf8wHQYDVR0OBBYE
+FI/wS3+oLkUkrk1Q+mOai97i3Ru8MA0GCSqGSIb3DQEBCwUAA4IBAQBLQNvAUKr+yAzv95ZURUm7
+lgAJQayzE4aGKAczymvmdLm6AC2upArT9fHxD4q/c2dKg8dEe3jgr25sbwMpjjM5RcOO5LlXbKr8
+EpbsU8Yt5CRsuZRj+9xTaGdWPoO4zzUhw8lo/s7awlOqzJCK6fBdRoyV3XpYKBovHd7NADdBj+1E
+bddTKJd+82cEHhXXipa0095MJ6RMG3NzdvQXmcIfeg7jLQitChws/zyrVQ4PkX4268NXSb7hLi18
+YIvDQVETI53O9zJrlAGomecsMx86OyXShkDOOyyGeMlhLxS67ttVb9+E7gUJTb0o2HLO02JQZR7r
+kpeDMdmztcpHWD9f
+-----END CERTIFICATE-----
+
+TC TrustCenter Universal CA III
+===============================
+-----BEGIN CERTIFICATE-----
+MIID4TCCAsmgAwIBAgIOYyUAAQACFI0zFQLkbPQwDQYJKoZIhvcNAQEFBQAwezELMAkGA1UEBhMC
+REUxHDAaBgNVBAoTE1RDIFRydXN0Q2VudGVyIEdtYkgxJDAiBgNVBAsTG1RDIFRydXN0Q2VudGVy
+IFVuaXZlcnNhbCBDQTEoMCYGA1UEAxMfVEMgVHJ1c3RDZW50ZXIgVW5pdmVyc2FsIENBIElJSTAe
+Fw0wOTA5MDkwODE1MjdaFw0yOTEyMzEyMzU5NTlaMHsxCzAJBgNVBAYTAkRFMRwwGgYDVQQKExNU
+QyBUcnVzdENlbnRlciBHbWJIMSQwIgYDVQQLExtUQyBUcnVzdENlbnRlciBVbml2ZXJzYWwgQ0Ex
+KDAmBgNVBAMTH1RDIFRydXN0Q2VudGVyIFVuaXZlcnNhbCBDQSBJSUkwggEiMA0GCSqGSIb3DQEB
+AQUAA4IBDwAwggEKAoIBAQDC2pxisLlxErALyBpXsq6DFJmzNEubkKLF5+cvAqBNLaT6hdqbJYUt
+QCggbergvbFIgyIpRJ9Og+41URNzdNW88jBmlFPAQDYvDIRlzg9uwliT6CwLOunBjvvya8o84pxO
+juT5fdMnnxvVZ3iHLX8LR7PH6MlIfK8vzArZQe+f/prhsq75U7Xl6UafYOPfjdN/+5Z+s7Vy+Eut
+CHnNaYlAJ/Uqwa1D7KRTyGG299J5KmcYdkhtWyUB0SbFt1dpIxVbYYqt8Bst2a9c8SaQaanVDED1
+M4BDj5yjdipFtK+/fz6HP3bFzSreIMUWWMv5G/UPyw0RUmS40nZid4PxWJ//AgMBAAGjYzBhMB8G
+A1UdIwQYMBaAFFbn4VslQ4Dg9ozhcbyO5YAvxEjiMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/
+BAQDAgEGMB0GA1UdDgQWBBRW5+FbJUOA4PaM4XG8juWAL8RI4jANBgkqhkiG9w0BAQUFAAOCAQEA
+g8ev6n9NCjw5sWi+e22JLumzCecYV42FmhfzdkJQEw/HkG8zrcVJYCtsSVgZ1OK+t7+rSbyUyKu+
+KGwWaODIl0YgoGhnYIg5IFHYaAERzqf2EQf27OysGh+yZm5WZ2B6dF7AbZc2rrUNXWZzwCUyRdhK
+BgePxLcHsU0GDeGl6/R1yrqc0L2z0zIkTO5+4nYES0lT2PLpVDP85XEfPRRclkvxOvIAu2y0+pZV
+CIgJwcyRGSmwIC3/yzikQOEXvnlhgP8HA4ZMTnsGnxGGjYnuJ8Tb4rwZjgvDwxPHLQNjO9Po5KIq
+woIIlBZU8O8fJ5AluA0OKBtHd0e9HKgl8ZS0Zg==
+-----END CERTIFICATE-----
+
+Autoridad de Certificacion Firmaprofesional CIF A62634068
+=========================================================
+-----BEGIN CERTIFICATE-----
+MIIGFDCCA/ygAwIBAgIIU+w77vuySF8wDQYJKoZIhvcNAQEFBQAwUTELMAkGA1UEBhMCRVMxQjBA
+BgNVBAMMOUF1dG9yaWRhZCBkZSBDZXJ0aWZpY2FjaW9uIEZpcm1hcHJvZmVzaW9uYWwgQ0lGIEE2
+MjYzNDA2ODAeFw0wOTA1MjAwODM4MTVaFw0zMDEyMzEwODM4MTVaMFExCzAJBgNVBAYTAkVTMUIw
+QAYDVQQDDDlBdXRvcmlkYWQgZGUgQ2VydGlmaWNhY2lvbiBGaXJtYXByb2Zlc2lvbmFsIENJRiBB
+NjI2MzQwNjgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDKlmuO6vj78aI14H9M2uDD
+Utd9thDIAl6zQyrET2qyyhxdKJp4ERppWVevtSBC5IsP5t9bpgOSL/UR5GLXMnE42QQMcas9UX4P
+B99jBVzpv5RvwSmCwLTaUbDBPLutN0pcyvFLNg4kq7/DhHf9qFD0sefGL9ItWY16Ck6WaVICqjaY
+7Pz6FIMMNx/Jkjd/14Et5cS54D40/mf0PmbR0/RAz15iNA9wBj4gGFrO93IbJWyTdBSTo3OxDqqH
+ECNZXyAFGUftaI6SEspd/NYrspI8IM/hX68gvqB2f3bl7BqGYTM+53u0P6APjqK5am+5hyZvQWyI
+plD9amML9ZMWGxmPsu2bm8mQ9QEM3xk9Dz44I8kvjwzRAv4bVdZO0I08r0+k8/6vKtMFnXkIoctX
+MbScyJCyZ/QYFpM6/EfY0XiWMR+6KwxfXZmtY4laJCB22N/9q06mIqqdXuYnin1oKaPnirjaEbsX
+LZmdEyRG98Xi2J+Of8ePdG1asuhy9azuJBCtLxTa/y2aRnFHvkLfuwHb9H/TKI8xWVvTyQKmtFLK
+bpf7Q8UIJm+K9Lv9nyiqDdVF8xM6HdjAeI9BZzwelGSuewvF6NkBiDkal4ZkQdU7hwxu+g/GvUgU
+vzlN1J5Bto+WHWOWk9mVBngxaJ43BjuAiUVhOSPHG0SjFeUc+JIwuwIDAQABo4HvMIHsMBIGA1Ud
+EwEB/wQIMAYBAf8CAQEwDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBRlzeurNR4APn7VdMActHNH
+DhpkLzCBpgYDVR0gBIGeMIGbMIGYBgRVHSAAMIGPMC8GCCsGAQUFBwIBFiNodHRwOi8vd3d3LmZp
+cm1hcHJvZmVzaW9uYWwuY29tL2NwczBcBggrBgEFBQcCAjBQHk4AUABhAHMAZQBvACAAZABlACAA
+bABhACAAQgBvAG4AYQBuAG8AdgBhACAANAA3ACAAQgBhAHIAYwBlAGwAbwBuAGEAIAAwADgAMAAx
+ADcwDQYJKoZIhvcNAQEFBQADggIBABd9oPm03cXF661LJLWhAqvdpYhKsg9VSytXjDvlMd3+xDLx
+51tkljYyGOylMnfX40S2wBEqgLk9am58m9Ot/MPWo+ZkKXzR4Tgegiv/J2Wv+xYVxC5xhOW1//qk
+R71kMrv2JYSiJ0L1ILDCExARzRAVukKQKtJE4ZYm6zFIEv0q2skGz3QeqUvVhyj5eTSSPi5E6PaP
+T481PyWzOdxjKpBrIF/EUhJOlywqrJ2X3kjyo2bbwtKDlaZmp54lD+kLM5FlClrD2VQS3a/DTg4f
+Jl4N3LON7NWBcN7STyQF82xO9UxJZo3R/9ILJUFI/lGExkKvgATP0H5kSeTy36LssUzAKh3ntLFl
+osS88Zj0qnAHY7S42jtM+kAiMFsRpvAFDsYCA0irhpuF3dvd6qJ2gHN99ZwExEWN57kci57q13XR
+crHedUTnQn3iV2t93Jm8PYMo6oCTjcVMZcFwgbg4/EMxsvYDNEeyrPsiBsse3RdHHF9mudMaotoR
+saS8I8nkvof/uZS2+F0gStRf571oe2XyFR7SOqkt6dhrJKyXWERHrVkY8SFlcN7ONGCoQPHzPKTD
+KCOM/iczQ0CgFzzr6juwcqajuUpLXhZI9LK8yIySxZ2frHI2vDSANGupi5LAuBft7HZT9SQBjLMi
+6Et8Vcad+qMUu2WFbm5PEn4KPJ2V
+-----END CERTIFICATE-----
+
+Izenpe.com
+==========
+-----BEGIN CERTIFICATE-----
+MIIF8TCCA9mgAwIBAgIQALC3WhZIX7/hy/WL1xnmfTANBgkqhkiG9w0BAQsFADA4MQswCQYDVQQG
+EwJFUzEUMBIGA1UECgwLSVpFTlBFIFMuQS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wHhcNMDcxMjEz
+MTMwODI4WhcNMzcxMjEzMDgyNzI1WjA4MQswCQYDVQQGEwJFUzEUMBIGA1UECgwLSVpFTlBFIFMu
+QS4xEzARBgNVBAMMCkl6ZW5wZS5jb20wggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDJ
+03rKDx6sp4boFmVqscIbRTJxldn+EFvMr+eleQGPicPK8lVx93e+d5TzcqQsRNiekpsUOqHnJJAK
+ClaOxdgmlOHZSOEtPtoKct2jmRXagaKH9HtuJneJWK3W6wyyQXpzbm3benhB6QiIEn6HLmYRY2xU
++zydcsC8Lv/Ct90NduM61/e0aL6i9eOBbsFGb12N4E3GVFWJGjMxCrFXuaOKmMPsOzTFlUFpfnXC
+PCDFYbpRR6AgkJOhkEvzTnyFRVSa0QUmQbC1TR0zvsQDyCV8wXDbO/QJLVQnSKwv4cSsPsjLkkxT
+OTcj7NMB+eAJRE1NZMDhDVqHIrytG6P+JrUV86f8hBnp7KGItERphIPzidF0BqnMC9bC3ieFUCbK
+F7jJeodWLBoBHmy+E60QrLUk9TiRodZL2vG70t5HtfG8gfZZa88ZU+mNFctKy6lvROUbQc/hhqfK
+0GqfvEyNBjNaooXlkDWgYlwWTvDjovoDGrQscbNYLN57C9saD+veIR8GdwYDsMnvmfzAuU8Lhij+
+0rnq49qlw0dpEuDb8PYZi+17cNcC1u2HGCgsBCRMd+RIihrGO5rUD8r6ddIBQFqNeb+Lz0vPqhbB
+leStTIo+F5HUsWLlguWABKQDfo2/2n+iD5dPDNMN+9fR5XJ+HMh3/1uaD7euBUbl8agW7EekFwID
+AQABo4H2MIHzMIGwBgNVHREEgagwgaWBD2luZm9AaXplbnBlLmNvbaSBkTCBjjFHMEUGA1UECgw+
+SVpFTlBFIFMuQS4gLSBDSUYgQTAxMzM3MjYwLVJNZXJjLlZpdG9yaWEtR2FzdGVpeiBUMTA1NSBG
+NjIgUzgxQzBBBgNVBAkMOkF2ZGEgZGVsIE1lZGl0ZXJyYW5lbyBFdG9yYmlkZWEgMTQgLSAwMTAx
+MCBWaXRvcmlhLUdhc3RlaXowDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0O
+BBYEFB0cZQ6o8iV7tJHP5LGx5r1VdGwFMA0GCSqGSIb3DQEBCwUAA4ICAQB4pgwWSp9MiDrAyw6l
+Fn2fuUhfGI8NYjb2zRlrrKvV9pF9rnHzP7MOeIWblaQnIUdCSnxIOvVFfLMMjlF4rJUT3sb9fbga
+kEyrkgPH7UIBzg/YsfqikuFgba56awmqxinuaElnMIAkejEWOVt+8Rwu3WwJrfIxwYJOubv5vr8q
+hT/AQKM6WfxZSzwoJNu0FXWuDYi6LnPAvViH5ULy617uHjAimcs30cQhbIHsvm0m5hzkQiCeR7Cs
+g1lwLDXWrzY0tM07+DKo7+N4ifuNRSzanLh+QBxh5z6ikixL8s36mLYp//Pye6kfLqCTVyvehQP5
+aTfLnnhqBbTFMXiJ7HqnheG5ezzevh55hM6fcA5ZwjUukCox2eRFekGkLhObNA5me0mrZJfQRsN5
+nXJQY6aYWwa9SG3YOYNw6DXwBdGqvOPbyALqfP2C2sJbUjWumDqtujWTI6cfSN01RpiyEGjkpTHC
+ClguGYEQyVB1/OpaFs4R1+7vUIgtYf8/QnMFlEPVjjxOAToZpR9GTnfQXeWBIiGH/pR9hNiTrdZo
+Q0iy2+tzJOeRf1SktoA+naM8THLCV8Sg1Mw4J87VBp6iSNnpn86CcDaTmjvfliHjWbcM2pE38P1Z
+WrOZyGlsQyYBNWNgVYkDOnXYukrZVP/u3oDYLdE41V4tC5h9Pmzb/CaIxw==
+-----END CERTIFICATE-----
+
+Chambers of Commerce Root - 2008
+================================
+-----BEGIN CERTIFICATE-----
+MIIHTzCCBTegAwIBAgIJAKPaQn6ksa7aMA0GCSqGSIb3DQEBBQUAMIGuMQswCQYDVQQGEwJFVTFD
+MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
+bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
+QS4xKTAnBgNVBAMTIENoYW1iZXJzIG9mIENvbW1lcmNlIFJvb3QgLSAyMDA4MB4XDTA4MDgwMTEy
+Mjk1MFoXDTM4MDczMTEyMjk1MFowga4xCzAJBgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNl
+ZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNhbWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQF
+EwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENhbWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJl
+cnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDgwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
+AQCvAMtwNyuAWko6bHiUfaN/Gh/2NdW928sNRHI+JrKQUrpjOyhYb6WzbZSm891kDFX29ufyIiKA
+XuFixrYp4YFs8r/lfTJqVKAyGVn+H4vXPWCGhSRv4xGzdz4gljUha7MI2XAuZPeEklPWDrCQiorj
+h40G072QDuKZoRuGDtqaCrsLYVAGUvGef3bsyw/QHg3PmTA9HMRFEFis1tPo1+XqxQEHd9ZR5gN/
+ikilTWh1uem8nk4ZcfUyS5xtYBkL+8ydddy/Js2Pk3g5eXNeJQ7KXOt3EgfLZEFHcpOrUMPrCXZk
+NNI5t3YRCQ12RcSprj1qr7V9ZS+UWBDsXHyvfuK2GNnQm05aSd+pZgvMPMZ4fKecHePOjlO+Bd5g
+D2vlGts/4+EhySnB8esHnFIbAURRPHsl18TlUlRdJQfKFiC4reRB7noI/plvg6aRArBsNlVq5331
+lubKgdaX8ZSD6e2wsWsSaR6s+12pxZjptFtYer49okQ6Y1nUCyXeG0+95QGezdIp1Z8XGQpvvwyQ
+0wlf2eOKNcx5Wk0ZN5K3xMGtr/R5JJqyAQuxr1yW84Ay+1w9mPGgP0revq+ULtlVmhduYJ1jbLhj
+ya6BXBg14JC7vjxPNyK5fuvPnnchpj04gftI2jE9K+OJ9dC1vX7gUMQSibMjmhAxhduub+84Mxh2
+EQIDAQABo4IBbDCCAWgwEgYDVR0TAQH/BAgwBgEB/wIBDDAdBgNVHQ4EFgQU+SSsD7K1+HnA+mCI
+G8TZTQKeFxkwgeMGA1UdIwSB2zCB2IAU+SSsD7K1+HnA+mCIG8TZTQKeFxmhgbSkgbEwga4xCzAJ
+BgNVBAYTAkVVMUMwQQYDVQQHEzpNYWRyaWQgKHNlZSBjdXJyZW50IGFkZHJlc3MgYXQgd3d3LmNh
+bWVyZmlybWEuY29tL2FkZHJlc3MpMRIwEAYDVQQFEwlBODI3NDMyODcxGzAZBgNVBAoTEkFDIENh
+bWVyZmlybWEgUy5BLjEpMCcGA1UEAxMgQ2hhbWJlcnMgb2YgQ29tbWVyY2UgUm9vdCAtIDIwMDiC
+CQCj2kJ+pLGu2jAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUH
+AgEWHGh0dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAJASryI1
+wqM58C7e6bXpeHxIvj99RZJe6dqxGfwWPJ+0W2aeaufDuV2I6A+tzyMP3iU6XsxPpcG1Lawk0lgH
+3qLPaYRgM+gQDROpI9CF5Y57pp49chNyM/WqfcZjHwj0/gF/JM8rLFQJ3uIrbZLGOU8W6jx+ekbU
+RWpGqOt1glanq6B8aBMz9p0w8G8nOSQjKpD9kCk18pPfNKXG9/jvjA9iSnyu0/VU+I22mlaHFoI6
+M6taIgj3grrqLuBHmrS1RaMFO9ncLkVAO+rcf+g769HsJtg1pDDFOqxXnrN2pSB7+R5KBWIBpih1
+YJeSDW4+TTdDDZIVnBgizVGZoCkaPF+KMjNbMMeJL0eYD6MDxvbxrN8y8NmBGuScvfaAFPDRLLmF
+9dijscilIeUcE5fuDr3fKanvNFNb0+RqE4QGtjICxFKuItLcsiFCGtpA8CnJ7AoMXOLQusxI0zcK
+zBIKinmwPQN/aUv0NCB9szTqjktk9T79syNnFQ0EuPAtwQlRPLJsFfClI9eDdOTlLsn+mCdCxqvG
+nrDQWzilm1DefhiYtUU79nm06PcaewaD+9CL2rvHvRirCG88gGtAPxkZumWK5r7VXNM21+9AUiRg
+OGcEMeyP84LG3rlV8zsxkVrctQgVrXYlCg17LofiDKYGvCYQbTed7N14jHyAxfDZd0jQ
+-----END CERTIFICATE-----
+
+Global Chambersign Root - 2008
+==============================
+-----BEGIN CERTIFICATE-----
+MIIHSTCCBTGgAwIBAgIJAMnN0+nVfSPOMA0GCSqGSIb3DQEBBQUAMIGsMQswCQYDVQQGEwJFVTFD
+MEEGA1UEBxM6TWFkcmlkIChzZWUgY3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNv
+bS9hZGRyZXNzKTESMBAGA1UEBRMJQTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMu
+QS4xJzAlBgNVBAMTHkdsb2JhbCBDaGFtYmVyc2lnbiBSb290IC0gMjAwODAeFw0wODA4MDExMjMx
+NDBaFw0zODA3MzExMjMxNDBaMIGsMQswCQYDVQQGEwJFVTFDMEEGA1UEBxM6TWFkcmlkIChzZWUg
+Y3VycmVudCBhZGRyZXNzIGF0IHd3dy5jYW1lcmZpcm1hLmNvbS9hZGRyZXNzKTESMBAGA1UEBRMJ
+QTgyNzQzMjg3MRswGQYDVQQKExJBQyBDYW1lcmZpcm1hIFMuQS4xJzAlBgNVBAMTHkdsb2JhbCBD
+aGFtYmVyc2lnbiBSb290IC0gMjAwODCCAiIwDQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAMDf
+VtPkOpt2RbQT2//BthmLN0EYlVJH6xedKYiONWwGMi5HYvNJBL99RDaxccy9Wglz1dmFRP+RVyXf
+XjaOcNFccUMd2drvXNL7G706tcuto8xEpw2uIRU/uXpbknXYpBI4iRmKt4DS4jJvVpyR1ogQC7N0
+ZJJ0YPP2zxhPYLIj0Mc7zmFLmY/CDNBAspjcDahOo7kKrmCgrUVSY7pmvWjg+b4aqIG7HkF4ddPB
+/gBVsIdU6CeQNR1MM62X/JcumIS/LMmjv9GYERTtY/jKmIhYF5ntRQOXfjyGHoiMvvKRhI9lNNgA
+TH23MRdaKXoKGCQwoze1eqkBfSbW+Q6OWfH9GzO1KTsXO0G2Id3UwD2ln58fQ1DJu7xsepeY7s2M
+H/ucUa6LcL0nn3HAa6x9kGbo1106DbDVwo3VyJ2dwW3Q0L9R5OP4wzg2rtandeavhENdk5IMagfe
+Ox2YItaswTXbo6Al/3K1dh3ebeksZixShNBFks4c5eUzHdwHU1SjqoI7mjcv3N2gZOnm3b2u/GSF
+HTynyQbehP9r6GsaPMWis0L7iwk+XwhSx2LE1AVxv8Rk5Pihg+g+EpuoHtQ2TS9x9o0o9oOpE9Jh
+wZG7SMA0j0GMS0zbaRL/UJScIINZc+18ofLx/d33SdNDWKBWY8o9PeU1VlnpDsogzCtLkykPAgMB
+AAGjggFqMIIBZjASBgNVHRMBAf8ECDAGAQH/AgEMMB0GA1UdDgQWBBS5CcqcHtvTbDprru1U8VuT
+BjUuXjCB4QYDVR0jBIHZMIHWgBS5CcqcHtvTbDprru1U8VuTBjUuXqGBsqSBrzCBrDELMAkGA1UE
+BhMCRVUxQzBBBgNVBAcTOk1hZHJpZCAoc2VlIGN1cnJlbnQgYWRkcmVzcyBhdCB3d3cuY2FtZXJm
+aXJtYS5jb20vYWRkcmVzcykxEjAQBgNVBAUTCUE4Mjc0MzI4NzEbMBkGA1UEChMSQUMgQ2FtZXJm
+aXJtYSBTLkEuMScwJQYDVQQDEx5HbG9iYWwgQ2hhbWJlcnNpZ24gUm9vdCAtIDIwMDiCCQDJzdPp
+1X0jzjAOBgNVHQ8BAf8EBAMCAQYwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEWHGh0
+dHA6Ly9wb2xpY3kuY2FtZXJmaXJtYS5jb20wDQYJKoZIhvcNAQEFBQADggIBAICIf3DekijZBZRG
+/5BXqfEv3xoNa/p8DhxJJHkn2EaqbylZUohwEurdPfWbU1Rv4WCiqAm57OtZfMY18dwY6fFn5a+6
+ReAJ3spED8IXDneRRXozX1+WLGiLwUePmJs9wOzL9dWCkoQ10b42OFZyMVtHLaoXpGNR6woBrX/s
+dZ7LoR/xfxKxueRkf2fWIyr0uDldmOghp+G9PUIadJpwr2hsUF1Jz//7Dl3mLEfXgTpZALVza2Mg
+9jFFCDkO9HB+QHBaP9BrQql0PSgvAm11cpUJjUhjxsYjV5KTXjXBjfkK9yydYhz2rXzdpjEetrHH
+foUm+qRqtdpjMNHvkzeyZi99Bffnt0uYlDXA2TopwZ2yUDMdSqlapskD7+3056huirRXhOukP9Du
+qqqHW2Pok+JrqNS4cnhrG+055F3Lm6qH1U9OAP7Zap88MQ8oAgF9mOinsKJknnn4SPIVqczmyETr
+P3iZ8ntxPjzxmKfFGBI/5rsoM0LpRQp8bfKGeS/Fghl9CYl8slR2iK7ewfPM4W7bMdaTrpmg7yVq
+c5iJWzouE4gev8CSlDQb4ye3ix5vQv/n6TebUB0tovkC7stYWDpxvGjjqsGvHCgfotwjZT+B6q6Z
+09gwzxMNTxXJhLynSC34MCN32EZLeW32jO06f2ARePTpm67VVMB0gNELQp/B
+-----END CERTIFICATE-----
+
+Go Daddy Root Certificate Authority - G2
+========================================
+-----BEGIN CERTIFICATE-----
+MIIDxTCCAq2gAwIBAgIBADANBgkqhkiG9w0BAQsFADCBgzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxGjAYBgNVBAoTEUdvRGFkZHkuY29tLCBJbmMu
+MTEwLwYDVQQDEyhHbyBEYWRkeSBSb290IENlcnRpZmljYXRlIEF1dGhvcml0eSAtIEcyMB4XDTA5
+MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgYMxCzAJBgNVBAYTAlVTMRAwDgYDVQQIEwdBcml6
+b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMRowGAYDVQQKExFHb0RhZGR5LmNvbSwgSW5jLjExMC8G
+A1UEAxMoR28gRGFkZHkgUm9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZI
+hvcNAQEBBQADggEPADCCAQoCggEBAL9xYgjx+lk09xvJGKP3gElY6SKDE6bFIEMBO4Tx5oVJnyfq
+9oQbTqC023CYxzIBsQU+B07u9PpPL1kwIuerGVZr4oAH/PMWdYA5UXvl+TW2dE6pjYIT5LY/qQOD
++qK+ihVqf94Lw7YZFAXK6sOoBJQ7RnwyDfMAZiLIjWltNowRGLfTshxgtDj6AozO091GB94KPutd
+fMh8+7ArU6SSYmlRJQVhGkSBjCypQ5Yj36w6gZoOKcUcqeldHraenjAKOc7xiID7S13MMuyFYkMl
+NAJWJwGRtDtwKj9useiciAF9n9T521NtYJ2/LOdYq7hfRvzOxBsDPAnrSTFcaUaz4EcCAwEAAaNC
+MEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFDqahQcQZyi27/a9
+BUFuIMGU2g/eMA0GCSqGSIb3DQEBCwUAA4IBAQCZ21151fmXWWcDYfF+OwYxdS2hII5PZYe096ac
+vNjpL9DbWu7PdIxztDhC2gV7+AJ1uP2lsdeu9tfeE8tTEH6KRtGX+rcuKxGrkLAngPnon1rpN5+r
+5N9ss4UXnT3ZJE95kTXWXwTrgIOrmgIttRD02JDHBHNA7XIloKmf7J6raBKZV8aPEjoJpL1E/QYV
+N8Gb5DKj7Tjo2GTzLH4U/ALqn83/B2gX2yKQOC16jdFU8WnjXzPKej17CuPKf1855eJ1usV2GDPO
+LPAvTK33sefOT6jEm0pUBsV/fdUID+Ic/n4XuKxe9tQWskMJDE32p2u0mYRlynqI4uJEvlz36hz1
+-----END CERTIFICATE-----
+
+Starfield Root Certificate Authority - G2
+=========================================
+-----BEGIN CERTIFICATE-----
+MIID3TCCAsWgAwIBAgIBADANBgkqhkiG9w0BAQsFADCBjzELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
+b2dpZXMsIEluYy4xMjAwBgNVBAMTKVN0YXJmaWVsZCBSb290IENlcnRpZmljYXRlIEF1dGhvcml0
+eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgY8xCzAJBgNVBAYTAlVTMRAw
+DgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxTdGFyZmllbGQg
+VGVjaG5vbG9naWVzLCBJbmMuMTIwMAYDVQQDEylTdGFyZmllbGQgUm9vdCBDZXJ0aWZpY2F0ZSBB
+dXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAL3twQP89o/8ArFv
+W59I2Z154qK3A2FWGMNHttfKPTUuiUP3oWmb3ooa/RMgnLRJdzIpVv257IzdIvpy3Cdhl+72WoTs
+bhm5iSzchFvVdPtrX8WJpRBSiUZV9Lh1HOZ/5FSuS/hVclcCGfgXcVnrHigHdMWdSL5stPSksPNk
+N3mSwOxGXn/hbVNMYq/NHwtjuzqd+/x5AJhhdM8mgkBj87JyahkNmcrUDnXMN/uLicFZ8WJ/X7Nf
+ZTD4p7dNdloedl40wOiWVpmKs/B/pM293DIxfJHP4F8R+GuqSVzRmZTRouNjWwl2tVZi4Ut0HZbU
+JtQIBFnQmA4O5t78w+wfkPECAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwHQYDVR0OBBYEFHwMMh+n2TB/xH1oo2Kooc6rB1snMA0GCSqGSIb3DQEBCwUAA4IBAQARWfol
+TwNvlJk7mh+ChTnUdgWUXuEok21iXQnCoKjUsHU48TRqneSfioYmUeYs0cYtbpUgSpIB7LiKZ3sx
+4mcujJUDJi5DnUox9g61DLu34jd/IroAow57UvtruzvE03lRTs2Q9GcHGcg8RnoNAX3FWOdt5oUw
+F5okxBDgBPfg8n/Uqgr/Qh037ZTlZFkSIHc40zI+OIF1lnP6aI+xy84fxez6nH7PfrHxBy22/L/K
+pL/QlwVKvOoYKAKQvVR4CSFx09F9HdkWsKlhPdAKACL8x3vLCWRFCztAgfd9fDL1mMpYjn0q7pBZ
+c2T5NnReJaH1ZgUufzkVqSr7UIuOhWn0
+-----END CERTIFICATE-----
+
+Starfield Services Root Certificate Authority - G2
+==================================================
+-----BEGIN CERTIFICATE-----
+MIID7zCCAtegAwIBAgIBADANBgkqhkiG9w0BAQsFADCBmDELMAkGA1UEBhMCVVMxEDAOBgNVBAgT
+B0FyaXpvbmExEzARBgNVBAcTClNjb3R0c2RhbGUxJTAjBgNVBAoTHFN0YXJmaWVsZCBUZWNobm9s
+b2dpZXMsIEluYy4xOzA5BgNVBAMTMlN0YXJmaWVsZCBTZXJ2aWNlcyBSb290IENlcnRpZmljYXRl
+IEF1dGhvcml0eSAtIEcyMB4XDTA5MDkwMTAwMDAwMFoXDTM3MTIzMTIzNTk1OVowgZgxCzAJBgNV
+BAYTAlVTMRAwDgYDVQQIEwdBcml6b25hMRMwEQYDVQQHEwpTY290dHNkYWxlMSUwIwYDVQQKExxT
+dGFyZmllbGQgVGVjaG5vbG9naWVzLCBJbmMuMTswOQYDVQQDEzJTdGFyZmllbGQgU2VydmljZXMg
+Um9vdCBDZXJ0aWZpY2F0ZSBBdXRob3JpdHkgLSBHMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCC
+AQoCggEBANUMOsQq+U7i9b4Zl1+OiFOxHz/Lz58gE20pOsgPfTz3a3Y4Y9k2YKibXlwAgLIvWX/2
+h/klQ4bnaRtSmpDhcePYLQ1Ob/bISdm28xpWriu2dBTrz/sm4xq6HZYuajtYlIlHVv8loJNwU4Pa
+hHQUw2eeBGg6345AWh1KTs9DkTvnVtYAcMtS7nt9rjrnvDH5RfbCYM8TWQIrgMw0R9+53pBlbQLP
+LJGmpufehRhJfGZOozptqbXuNC66DQO4M99H67FrjSXZm86B0UVGMpZwh94CDklDhbZsc7tk6mFB
+rMnUVN+HL8cisibMn1lUaJ/8viovxFUcdUBgF4UCVTmLfwUCAwEAAaNCMEAwDwYDVR0TAQH/BAUw
+AwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFJxfAN+qAdcwKziIorhtSpzyEZGDMA0GCSqG
+SIb3DQEBCwUAA4IBAQBLNqaEd2ndOxmfZyMIbw5hyf2E3F/YNoHN2BtBLZ9g3ccaaNnRbobhiCPP
+E95Dz+I0swSdHynVv/heyNXBve6SbzJ08pGCL72CQnqtKrcgfU28elUSwhXqvfdqlS5sdJ/PHLTy
+xQGjhdByPq1zqwubdQxtRbeOlKyWN7Wg0I8VRw7j6IPdj/3vQQF3zCepYoUz8jcI73HPdwbeyBkd
+iEDPfUYd/x7H4c7/I9vG+o1VTqkC50cRRj70/b17KSa7qWFiNyi2LSr2EIZkyXCn0q23KXB56jza
+YyWf/Wi3MOxw+3WKt21gZ7IeyLnp2KhvAotnDU0mV3HaIPzBSlCNsSi6
+-----END CERTIFICATE-----
+
+AffirmTrust Commercial
+======================
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIId3cGJyapsXwwDQYJKoZIhvcNAQELBQAwRDELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMB4XDTEw
+MDEyOTE0MDYwNloXDTMwMTIzMTE0MDYwNlowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
+bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBDb21tZXJjaWFsMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEA9htPZwcroRX1BiLLHwGy43NFBkRJLLtJJRTWzsO3qyxPxkEylFf6Eqdb
+DuKPHx6GGaeqtS25Xw2Kwq+FNXkyLbscYjfysVtKPcrNcV/pQr6U6Mje+SJIZMblq8Yrba0F8PrV
+C8+a5fBQpIs7R6UjW3p6+DM/uO+Zl+MgwdYoic+U+7lF7eNAFxHUdPALMeIrJmqbTFeurCA+ukV6
+BfO9m2kVrn1OIGPENXY6BwLJN/3HR+7o8XYdcxXyl6S1yHp52UKqK39c/s4mT6NmgTWvRLpUHhww
+MmWd5jyTXlBOeuM61G7MGvv50jeuJCqrVwMiKA1JdX+3KNp1v47j3A55MQIDAQABo0IwQDAdBgNV
+HQ4EFgQUnZPGU4teyq8/nx4P5ZmVvCT2lI8wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQELBQADggEBAFis9AQOzcAN/wr91LoWXym9e2iZWEnStB03TX8nfUYGXUPG
+hi4+c7ImfU+TqbbEKpqrIZcUsd6M06uJFdhrJNTxFq7YpFzUf1GO7RgBsZNjvbz4YYCanrHOQnDi
+qX0GJX0nof5v7LMeJNrjS1UaADs1tDvZ110w/YETifLCBivtZ8SOyUOyXGsViQK8YvxO8rUzqrJv
+0wqiUOP2O+guRMLbZjipM1ZI8W0bM40NjD9gN53Tym1+NH4Nn3J2ixufcv1SNUFFApYvHLKac0kh
+sUlHRUe072o0EclNmsxZt9YCnlpOZbWUrhvfKbAW8b8Angc6F2S1BLUjIZkKlTuXfO8=
+-----END CERTIFICATE-----
+
+AffirmTrust Networking
+======================
+-----BEGIN CERTIFICATE-----
+MIIDTDCCAjSgAwIBAgIIfE8EORzUmS0wDQYJKoZIhvcNAQEFBQAwRDELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMB4XDTEw
+MDEyOTE0MDgyNFoXDTMwMTIzMTE0MDgyNFowRDELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmly
+bVRydXN0MR8wHQYDVQQDDBZBZmZpcm1UcnVzdCBOZXR3b3JraW5nMIIBIjANBgkqhkiG9w0BAQEF
+AAOCAQ8AMIIBCgKCAQEAtITMMxcua5Rsa2FSoOujz3mUTOWUgJnLVWREZY9nZOIG41w3SfYvm4SE
+Hi3yYJ0wTsyEheIszx6e/jarM3c1RNg1lho9Nuh6DtjVR6FqaYvZ/Ls6rnla1fTWcbuakCNrmreI
+dIcMHl+5ni36q1Mr3Lt2PpNMCAiMHqIjHNRqrSK6mQEubWXLviRmVSRLQESxG9fhwoXA3hA/Pe24
+/PHxI1Pcv2WXb9n5QHGNfb2V1M6+oF4nI979ptAmDgAp6zxG8D1gvz9Q0twmQVGeFDdCBKNwV6gb
+h+0t+nvujArjqWaJGctB+d1ENmHP4ndGyH329JKBNv3bNPFyfvMMFr20FQIDAQABo0IwQDAdBgNV
+HQ4EFgQUBx/S55zawm6iQLSwelAQUHTEyL0wDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMC
+AQYwDQYJKoZIhvcNAQEFBQADggEBAIlXshZ6qML91tmbmzTCnLQyFE2npN/svqe++EPbkTfOtDIu
+UFUaNU52Q3Eg75N3ThVwLofDwR1t3Mu1J9QsVtFSUzpE0nPIxBsFZVpikpzuQY0x2+c06lkh1QF6
+12S4ZDnNye2v7UsDSKegmQGA3GWjNq5lWUhPgkvIZfFXHeVZLgo/bNjR9eUJtGxUAArgFU2HdW23
+WJZa3W3SAKD0m0i+wzekujbgfIeFlxoVot4uolu9rxj5kFDNcFn4J2dHy8egBzp90SxdbBk6ZrV9
+/ZFvgrG+CJPbFEfxojfHRZ48x3evZKiT3/Zpg4Jg8klCNO1aAFSFHBY2kgxc+qatv9s=
+-----END CERTIFICATE-----
+
+AffirmTrust Premium
+===================
+-----BEGIN CERTIFICATE-----
+MIIFRjCCAy6gAwIBAgIIbYwURrGmCu4wDQYJKoZIhvcNAQEMBQAwQTELMAkGA1UEBhMCVVMxFDAS
+BgNVBAoMC0FmZmlybVRydXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMB4XDTEwMDEy
+OTE0MTAzNloXDTQwMTIzMTE0MTAzNlowQTELMAkGA1UEBhMCVVMxFDASBgNVBAoMC0FmZmlybVRy
+dXN0MRwwGgYDVQQDDBNBZmZpcm1UcnVzdCBQcmVtaXVtMIICIjANBgkqhkiG9w0BAQEFAAOCAg8A
+MIICCgKCAgEAxBLfqV/+Qd3d9Z+K4/as4Tx4mrzY8H96oDMq3I0gW64tb+eT2TZwamjPjlGjhVtn
+BKAQJG9dKILBl1fYSCkTtuG+kU3fhQxTGJoeJKJPj/CihQvL9Cl/0qRY7iZNyaqoe5rZ+jjeRFcV
+5fiMyNlI4g0WJx0eyIOFJbe6qlVBzAMiSy2RjYvmia9mx+n/K+k8rNrSs8PhaJyJ+HoAVt70VZVs
++7pk3WKL3wt3MutizCaam7uqYoNMtAZ6MMgpv+0GTZe5HMQxK9VfvFMSF5yZVylmd2EhMQcuJUmd
+GPLu8ytxjLW6OQdJd/zvLpKQBY0tL3d770O/Nbua2Plzpyzy0FfuKE4mX4+QaAkvuPjcBukumj5R
+p9EixAqnOEhss/n/fauGV+O61oV4d7pD6kh/9ti+I20ev9E2bFhc8e6kGVQa9QPSdubhjL08s9NI
+S+LI+H+SqHZGnEJlPqQewQcDWkYtuJfzt9WyVSHvutxMAJf7FJUnM7/oQ0dG0giZFmA7mn7S5u04
+6uwBHjxIVkkJx0w3AJ6IDsBz4W9m6XJHMD4Q5QsDyZpCAGzFlH5hxIrff4IaC1nEWTJ3s7xgaVY5
+/bQGeyzWZDbZvUjthB9+pSKPKrhC9IK31FOQeE4tGv2Bb0TXOwF0lkLgAOIua+rF7nKsu7/+6qqo
++Nz2snmKtmcCAwEAAaNCMEAwHQYDVR0OBBYEFJ3AZ6YMItkm9UWrpmVSESfYRaxjMA8GA1UdEwEB
+/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBDAUAA4ICAQCzV00QYk465KzquByv
+MiPIs0laUZx2KI15qldGF9X1Uva3ROgIRL8YhNILgM3FEv0AVQVhh0HctSSePMTYyPtwni94loMg
+Nt58D2kTiKV1NpgIpsbfrM7jWNa3Pt668+s0QNiigfV4Py/VpfzZotReBA4Xrf5B8OWycvpEgjNC
+6C1Y91aMYj+6QrCcDFx+LmUmXFNPALJ4fqENmS2NuB2OosSw/WDQMKSOyARiqcTtNd56l+0OOF6S
+L5Nwpamcb6d9Ex1+xghIsV5n61EIJenmJWtSKZGc0jlzCFfemQa0W50QBuHCAKi4HEoCChTQwUHK
++4w1IX2COPKpVJEZNZOUbWo6xbLQu4mGk+ibyQ86p3q4ofB4Rvr8Ny/lioTz3/4E2aFooC8k4gmV
+BtWVyuEklut89pMFu+1z6S3RdTnX5yTb2E5fQ4+e0BQ5v1VwSJlXMbSc7kqYA5YwH2AG7hsj/oFg
+IxpHYoWlzBk0gG+zrBrjn/B7SK3VAdlntqlyk+otZrWyuOQ9PLLvTIzq6we/qzWaVYa8GKa1qF60
+g2xraUDTn9zxw2lrueFtCfTxqlB2Cnp9ehehVZZCmTEJ3WARjQUwfuaORtGdFNrHF+QFlozEJLUb
+zxQHskD4o55BhrwE0GuWyCqANP2/7waj3VjFhT0+j/6eKeC2uAloGRwYQw==
+-----END CERTIFICATE-----
+
+AffirmTrust Premium ECC
+=======================
+-----BEGIN CERTIFICATE-----
+MIIB/jCCAYWgAwIBAgIIdJclisc/elQwCgYIKoZIzj0EAwMwRTELMAkGA1UEBhMCVVMxFDASBgNV
+BAoMC0FmZmlybVRydXN0MSAwHgYDVQQDDBdBZmZpcm1UcnVzdCBQcmVtaXVtIEVDQzAeFw0xMDAx
+MjkxNDIwMjRaFw00MDEyMzExNDIwMjRaMEUxCzAJBgNVBAYTAlVTMRQwEgYDVQQKDAtBZmZpcm1U
+cnVzdDEgMB4GA1UEAwwXQWZmaXJtVHJ1c3QgUHJlbWl1bSBFQ0MwdjAQBgcqhkjOPQIBBgUrgQQA
+IgNiAAQNMF4bFZ0D0KF5Nbc6PJJ6yhUczWLznCZcBz3lVPqj1swS6vQUX+iOGasvLkjmrBhDeKzQ
+N8O9ss0s5kfiGuZjuD0uL3jET9v0D6RoTFVya5UdThhClXjMNzyR4ptlKymjQjBAMB0GA1UdDgQW
+BBSaryl6wBE1NSZRMADDav5A1a7WPDAPBgNVHRMBAf8EBTADAQH/MA4GA1UdDwEB/wQEAwIBBjAK
+BggqhkjOPQQDAwNnADBkAjAXCfOHiFBar8jAQr9HX/VsaobgxCd05DhT1wV/GzTjxi+zygk8N53X
+57hG8f2h4nECMEJZh0PUUd+60wkyWs6Iflc9nF9Ca/UHLbXwgpP5WW+uZPpY5Yse42O+tYHNbwKM
+eQ==
+-----END CERTIFICATE-----
+
+Certum Trusted Network CA
+=========================
+-----BEGIN CERTIFICATE-----
+MIIDuzCCAqOgAwIBAgIDBETAMA0GCSqGSIb3DQEBBQUAMH4xCzAJBgNVBAYTAlBMMSIwIAYDVQQK
+ExlVbml6ZXRvIFRlY2hub2xvZ2llcyBTLkEuMScwJQYDVQQLEx5DZXJ0dW0gQ2VydGlmaWNhdGlv
+biBBdXRob3JpdHkxIjAgBgNVBAMTGUNlcnR1bSBUcnVzdGVkIE5ldHdvcmsgQ0EwHhcNMDgxMDIy
+MTIwNzM3WhcNMjkxMjMxMTIwNzM3WjB+MQswCQYDVQQGEwJQTDEiMCAGA1UEChMZVW5pemV0byBU
+ZWNobm9sb2dpZXMgUy5BLjEnMCUGA1UECxMeQ2VydHVtIENlcnRpZmljYXRpb24gQXV0aG9yaXR5
+MSIwIAYDVQQDExlDZXJ0dW0gVHJ1c3RlZCBOZXR3b3JrIENBMIIBIjANBgkqhkiG9w0BAQEFAAOC
+AQ8AMIIBCgKCAQEA4/t9o3K6wvDJFIf1awFO4W5AB7ptJ11/91sts1rHUV+rpDKmYYe2bg+G0jAC
+l/jXaVehGDldamR5xgFZrDwxSjh80gTSSyjoIF87B6LMTXPb865Px1bVWqeWifrzq2jUI4ZZJ88J
+J7ysbnKDHDBy3+Ci6dLhdHUZvSqeexVUBBvXQzmtVSjF4hq79MDkrjhJM8x2hZ85RdKknvISjFH4
+fOQtf/WsX+sWn7Et0brMkUJ3TCXJkDhv2/DM+44el1k+1WBO5gUo7Ul5E0u6SNsv+XLTOcr+H9g0
+cvW0QM8xAcPs3hEtF10fuFDRXhmnad4HMyjKUJX5p1TLVIZQRan5SQIDAQABo0IwQDAPBgNVHRMB
+Af8EBTADAQH/MB0GA1UdDgQWBBQIds3LB/8k9sXN7buQvOKEN0Z19zAOBgNVHQ8BAf8EBAMCAQYw
+DQYJKoZIhvcNAQEFBQADggEBAKaorSLOAT2mo/9i0Eidi15ysHhE49wcrwn9I0j6vSrEuVUEtRCj
+jSfeC4Jj0O7eDDd5QVsisrCaQVymcODU0HfLI9MA4GxWL+FpDQ3Zqr8hgVDZBqWo/5U30Kr+4rP1
+mS1FhIrlQgnXdAIv94nYmem8J9RHjboNRhx3zxSkHLmkMcScKHQDNP8zGSal6Q10tz6XxnboJ5aj
+Zt3hrvJBW8qYVoNzcOSGGtIxQbovvi0TWnZvTuhOgQ4/WwMioBK+ZlgRSssDxLQqKi2WF+A5VLxI
+03YnnZotBqbJ7DnSq9ufmgsnAjUpsUCV5/nonFWIGUbWtzT1fs45mtk48VH3Tyw=
+-----END CERTIFICATE-----
+
+Certinomis - Autorité Racine
+=============================
+-----BEGIN CERTIFICATE-----
+MIIFnDCCA4SgAwIBAgIBATANBgkqhkiG9w0BAQUFADBjMQswCQYDVQQGEwJGUjETMBEGA1UEChMK
+Q2VydGlub21pczEXMBUGA1UECxMOMDAwMiA0MzM5OTg5MDMxJjAkBgNVBAMMHUNlcnRpbm9taXMg
+LSBBdXRvcml0w6kgUmFjaW5lMB4XDTA4MDkxNzA4Mjg1OVoXDTI4MDkxNzA4Mjg1OVowYzELMAkG
+A1UEBhMCRlIxEzARBgNVBAoTCkNlcnRpbm9taXMxFzAVBgNVBAsTDjAwMDIgNDMzOTk4OTAzMSYw
+JAYDVQQDDB1DZXJ0aW5vbWlzIC0gQXV0b3JpdMOpIFJhY2luZTCCAiIwDQYJKoZIhvcNAQEBBQAD
+ggIPADCCAgoCggIBAJ2Fn4bT46/HsmtuM+Cet0I0VZ35gb5j2CN2DpdUzZlMGvE5x4jYF1AMnmHa
+wE5V3udauHpOd4cN5bjr+p5eex7Ezyh0x5P1FMYiKAT5kcOrJ3NqDi5N8y4oH3DfVS9O7cdxbwly
+Lu3VMpfQ8Vh30WC8Tl7bmoT2R2FFK/ZQpn9qcSdIhDWerP5pqZ56XjUl+rSnSTV3lqc2W+HN3yNw
+2F1MpQiD8aYkOBOo7C+ooWfHpi2GR+6K/OybDnT0K0kCe5B1jPyZOQE51kqJ5Z52qz6WKDgmi92N
+jMD2AR5vpTESOH2VwnHu7XSu5DaiQ3XV8QCb4uTXzEIDS3h65X27uK4uIJPT5GHfceF2Z5c/tt9q
+c1pkIuVC28+BA5PY9OMQ4HL2AHCs8MF6DwV/zzRpRbWT5BnbUhYjBYkOjUjkJW+zeL9i9Qf6lSTC
+lrLooyPCXQP8w9PlfMl1I9f09bze5N/NgL+RiH2nE7Q5uiy6vdFrzPOlKO1Enn1So2+WLhl+HPNb
+xxaOu2B9d2ZHVIIAEWBsMsGoOBvrbpgT1u449fCfDu/+MYHB0iSVL1N6aaLwD4ZFjliCK0wi1F6g
+530mJ0jfJUaNSih8hp75mxpZuWW/Bd22Ql095gBIgl4g9xGC3srYn+Y3RyYe63j3YcNBZFgCQfna
+4NH4+ej9Uji29YnfAgMBAAGjWzBZMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0G
+A1UdDgQWBBQNjLZh2kS40RR9w759XkjwzspqsDAXBgNVHSAEEDAOMAwGCiqBegFWAgIAAQEwDQYJ
+KoZIhvcNAQEFBQADggIBACQ+YAZ+He86PtvqrxyaLAEL9MW12Ukx9F1BjYkMTv9sov3/4gbIOZ/x
+WqndIlgVqIrTseYyCYIDbNc/CMf4uboAbbnW/FIyXaR/pDGUu7ZMOH8oMDX/nyNTt7buFHAAQCva
+R6s0fl6nVjBhK4tDrP22iCj1a7Y+YEq6QpA0Z43q619FVDsXrIvkxmUP7tCMXWY5zjKn2BCXwH40
+nJ+U8/aGH88bc62UeYdocMMzpXDn2NU4lG9jeeu/Cg4I58UvD0KgKxRA/yHgBcUn4YQRE7rWhh1B
+CxMjidPJC+iKunqjo3M3NYB9Ergzd0A4wPpeMNLytqOx1qKVl4GbUu1pTP+A5FPbVFsDbVRfsbjv
+JL1vnxHDx2TCDyhihWZeGnuyt++uNckZM6i4J9szVb9o4XVIRFb7zdNIu0eJOqxp9YDG5ERQL1TE
+qkPFMTFYvZbF6nVsmnWxTfj3l/+WFvKXTej28xH5On2KOG4Ey+HTRRWqpdEdnV1j6CTmNhTih60b
+WfVEm/vXd3wfAXBioSAaosUaKPQhA+4u2cGA6rnZgtZbdsLLO7XSAPCjDuGtbkD326C00EauFddE
+wk01+dIL8hf2rGbVJLJP0RyZwG71fet0BLj5TXcJ17TPBzAJ8bgAVtkXFhYKK4bfjwEZGuW7gmP/
+vgt2Fl43N+bYdJeimUV5
+-----END CERTIFICATE-----
+
+Root CA Generalitat Valenciana
+==============================
+-----BEGIN CERTIFICATE-----
+MIIGizCCBXOgAwIBAgIEO0XlaDANBgkqhkiG9w0BAQUFADBoMQswCQYDVQQGEwJFUzEfMB0GA1UE
+ChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290
+IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwHhcNMDEwNzA2MTYyMjQ3WhcNMjEwNzAxMTUyMjQ3
+WjBoMQswCQYDVQQGEwJFUzEfMB0GA1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UE
+CxMGUEtJR1ZBMScwJQYDVQQDEx5Sb290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmEwggEiMA0G
+CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDGKqtXETcvIorKA3Qdyu0togu8M1JAJke+WmmmO3I2
+F0zo37i7L3bhQEZ0ZQKQUgi0/6iMweDHiVYQOTPvaLRfX9ptI6GJXiKjSgbwJ/BXufjpTjJ3Cj9B
+ZPPrZe52/lSqfR0grvPXdMIKX/UIKFIIzFVd0g/bmoGlu6GzwZTNVOAydTGRGmKy3nXiz0+J2ZGQ
+D0EbtFpKd71ng+CT516nDOeB0/RSrFOyA8dEJvt55cs0YFAQexvba9dHq198aMpunUEDEO5rmXte
+JajCq+TA81yc477OMUxkHl6AovWDfgzWyoxVjr7gvkkHD6MkQXpYHYTqWBLI4bft75PelAgxAgMB
+AAGjggM7MIIDNzAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAGGFmh0dHA6Ly9vY3NwLnBraS5n
+dmEuZXMwEgYDVR0TAQH/BAgwBgEB/wIBAjCCAjQGA1UdIASCAiswggInMIICIwYKKwYBBAG/VQIB
+ADCCAhMwggHoBggrBgEFBQcCAjCCAdoeggHWAEEAdQB0AG8AcgBpAGQAYQBkACAAZABlACAAQwBl
+AHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAFIAYQDtAHoAIABkAGUAIABsAGEAIABHAGUAbgBlAHIA
+YQBsAGkAdABhAHQAIABWAGEAbABlAG4AYwBpAGEAbgBhAC4ADQAKAEwAYQAgAEQAZQBjAGwAYQBy
+AGEAYwBpAPMAbgAgAGQAZQAgAFAAcgDhAGMAdABpAGMAYQBzACAAZABlACAAQwBlAHIAdABpAGYA
+aQBjAGEAYwBpAPMAbgAgAHEAdQBlACAAcgBpAGcAZQAgAGUAbAAgAGYAdQBuAGMAaQBvAG4AYQBt
+AGkAZQBuAHQAbwAgAGQAZQAgAGwAYQAgAHAAcgBlAHMAZQBuAHQAZQAgAEEAdQB0AG8AcgBpAGQA
+YQBkACAAZABlACAAQwBlAHIAdABpAGYAaQBjAGEAYwBpAPMAbgAgAHMAZQAgAGUAbgBjAHUAZQBu
+AHQAcgBhACAAZQBuACAAbABhACAAZABpAHIAZQBjAGMAaQDzAG4AIAB3AGUAYgAgAGgAdAB0AHAA
+OgAvAC8AdwB3AHcALgBwAGsAaQAuAGcAdgBhAC4AZQBzAC8AYwBwAHMwJQYIKwYBBQUHAgEWGWh0
+dHA6Ly93d3cucGtpLmd2YS5lcy9jcHMwHQYDVR0OBBYEFHs100DSHHgZZu90ECjcPk+yeAT8MIGV
+BgNVHSMEgY0wgYqAFHs100DSHHgZZu90ECjcPk+yeAT8oWykajBoMQswCQYDVQQGEwJFUzEfMB0G
+A1UEChMWR2VuZXJhbGl0YXQgVmFsZW5jaWFuYTEPMA0GA1UECxMGUEtJR1ZBMScwJQYDVQQDEx5S
+b290IENBIEdlbmVyYWxpdGF0IFZhbGVuY2lhbmGCBDtF5WgwDQYJKoZIhvcNAQEFBQADggEBACRh
+TvW1yEICKrNcda3FbcrnlD+laJWIwVTAEGmiEi8YPyVQqHxK6sYJ2fR1xkDar1CdPaUWu20xxsdz
+Ckj+IHLtb8zog2EWRpABlUt9jppSCS/2bxzkoXHPjCpaF3ODR00PNvsETUlR4hTJZGH71BTg9J63
+NI8KJr2XXPR5OkowGcytT6CYirQxlyric21+eLj4iIlPsSKRZEv1UN4D2+XFducTZnV+ZfsBn5OH
+iJ35Rld8TWCvmHMTI6QgkYH60GFmuH3Rr9ZvHmw96RH9qfmCIoaZM3Fa6hlXPZHNqcCjbgcTpsnt
++GijnsNacgmHKNHEc8RzGF9QdRYxn7fofMM=
+-----END CERTIFICATE-----
+
+A-Trust-nQual-03
+================
+-----BEGIN CERTIFICATE-----
+MIIDzzCCAregAwIBAgIDAWweMA0GCSqGSIb3DQEBBQUAMIGNMQswCQYDVQQGEwJBVDFIMEYGA1UE
+Cgw/QS1UcnVzdCBHZXMuIGYuIFNpY2hlcmhlaXRzc3lzdGVtZSBpbSBlbGVrdHIuIERhdGVudmVy
+a2VociBHbWJIMRkwFwYDVQQLDBBBLVRydXN0LW5RdWFsLTAzMRkwFwYDVQQDDBBBLVRydXN0LW5R
+dWFsLTAzMB4XDTA1MDgxNzIyMDAwMFoXDTE1MDgxNzIyMDAwMFowgY0xCzAJBgNVBAYTAkFUMUgw
+RgYDVQQKDD9BLVRydXN0IEdlcy4gZi4gU2ljaGVyaGVpdHNzeXN0ZW1lIGltIGVsZWt0ci4gRGF0
+ZW52ZXJrZWhyIEdtYkgxGTAXBgNVBAsMEEEtVHJ1c3QtblF1YWwtMDMxGTAXBgNVBAMMEEEtVHJ1
+c3QtblF1YWwtMDMwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCtPWFuA/OQO8BBC4SA
+zewqo51ru27CQoT3URThoKgtUaNR8t4j8DRE/5TrzAUjlUC5B3ilJfYKvUWG6Nm9wASOhURh73+n
+yfrBJcyFLGM/BWBzSQXgYHiVEEvc+RFZznF/QJuKqiTfC0Li21a8StKlDJu3Qz7dg9MmEALP6iPE
+SU7l0+m0iKsMrmKS1GWH2WrX9IWf5DMiJaXlyDO6w8dB3F/GaswADm0yqLaHNgBid5seHzTLkDx4
+iHQF63n1k3Flyp3HaxgtPVxO59X4PzF9j4fsCiIvI+n+u33J4PTs63zEsMMtYrWacdaxaujs2e3V
+cuy+VwHOBVWf3tFgiBCzAgMBAAGjNjA0MA8GA1UdEwEB/wQFMAMBAf8wEQYDVR0OBAoECERqlWdV
+eRFPMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQUFAAOCAQEAVdRU0VlIXLOThaq/Yy/kgM40
+ozRiPvbY7meIMQQDbwvUB/tOdQ/TLtPAF8fGKOwGDREkDg6lXb+MshOWcdzUzg4NCmgybLlBMRmr
+sQd7TZjTXLDR8KdCoLXEjq/+8T/0709GAHbrAvv5ndJAlseIOrifEXnzgGWovR/TeIGgUUw3tKZd
+JXDRZslo+S4RFGjxVJgIrCaSD96JntT6s3kr0qN51OyLrIdTaEJMUVF0HhsnLuP1Hyl0Te2v9+GS
+mYHovjrHF1D2t8b8m7CKa9aIA5GPBnc6hQLdmNVDeD/GMBWsm2vLV7eJUYs66MmEDNuxUCAKGkq6
+ahq97BvIxYSazQ==
+-----END CERTIFICATE-----
+
+TWCA Root Certification Authority
+=================================
+-----BEGIN CERTIFICATE-----
+MIIDezCCAmOgAwIBAgIBATANBgkqhkiG9w0BAQUFADBfMQswCQYDVQQGEwJUVzESMBAGA1UECgwJ
+VEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NBIFJvb3QgQ2VydGlmaWNh
+dGlvbiBBdXRob3JpdHkwHhcNMDgwODI4MDcyNDMzWhcNMzAxMjMxMTU1OTU5WjBfMQswCQYDVQQG
+EwJUVzESMBAGA1UECgwJVEFJV0FOLUNBMRAwDgYDVQQLDAdSb290IENBMSowKAYDVQQDDCFUV0NB
+IFJvb3QgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
+AoIBAQCwfnK4pAOU5qfeCTiRShFAh6d8WWQUe7UREN3+v9XAu1bihSX0NXIP+FPQQeFEAcK0HMMx
+QhZHhTMidrIKbw/lJVBPhYa+v5guEGcevhEFhgWQxFnQfHgQsIBct+HHK3XLfJ+utdGdIzdjp9xC
+oi2SBBtQwXu4PhvJVgSLL1KbralW6cH/ralYhzC2gfeXRfwZVzsrb+RH9JlF/h3x+JejiB03HFyP
+4HYlmlD4oFT/RJB2I9IyxsOrBr/8+7/zrX2SYgJbKdM1o5OaQ2RgXbL6Mv87BK9NQGr5x+PvI/1r
+y+UPizgN7gr8/g+YnzAx3WxSZfmLgb4i4RxYA7qRG4kHAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIB
+BjAPBgNVHRMBAf8EBTADAQH/MB0GA1UdDgQWBBRqOFsmjd6LWvJPelSDGRjjCDWmujANBgkqhkiG
+9w0BAQUFAAOCAQEAPNV3PdrfibqHDAhUaiBQkr6wQT25JmSDCi/oQMCXKCeCMErJk/9q56YAf4lC
+mtYR5VPOL8zy2gXE/uJQxDqGfczafhAJO5I1KlOy/usrBdlsXebQ79NqZp4VKIV66IIArB6nCWlW
+QtNoURi+VJq/REG6Sb4gumlc7rh3zc5sH62Dlhh9DrUUOYTxKOkto557HnpyWoOzeW/vtPzQCqVY
+T0bf+215WfKEIlKuD8z7fDvnaspHYcN6+NOSBB+4IIThNlQWx0DeO4pz3N/GCUzf7Nr/1FNCocny
+Yh0igzyXxfkZYiesZSLX0zzG5Y6yU8xJzrww/nsOM5D77dIUkR8Hrw==
+-----END CERTIFICATE-----
+
+Security Communication RootCA2
+==============================
+-----BEGIN CERTIFICATE-----
+MIIDdzCCAl+gAwIBAgIBADANBgkqhkiG9w0BAQsFADBdMQswCQYDVQQGEwJKUDElMCMGA1UEChMc
+U0VDT00gVHJ1c3QgU3lzdGVtcyBDTy4sTFRELjEnMCUGA1UECxMeU2VjdXJpdHkgQ29tbXVuaWNh
+dGlvbiBSb290Q0EyMB4XDTA5MDUyOTA1MDAzOVoXDTI5MDUyOTA1MDAzOVowXTELMAkGA1UEBhMC
+SlAxJTAjBgNVBAoTHFNFQ09NIFRydXN0IFN5c3RlbXMgQ08uLExURC4xJzAlBgNVBAsTHlNlY3Vy
+aXR5IENvbW11bmljYXRpb24gUm9vdENBMjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+ANAVOVKxUrO6xVmCxF1SrjpDZYBLx/KWvNs2l9amZIyoXvDjChz335c9S672XewhtUGrzbl+dp++
++T42NKA7wfYxEUV0kz1XgMX5iZnK5atq1LXaQZAQwdbWQonCv/Q4EpVMVAX3NuRFg3sUZdbcDE3R
+3n4MqzvEFb46VqZab3ZpUql6ucjrappdUtAtCms1FgkQhNBqyjoGADdH5H5XTz+L62e4iKrFvlNV
+spHEfbmwhRkGeC7bYRr6hfVKkaHnFtWOojnflLhwHyg/i/xAXmODPIMqGplrz95Zajv8bxbXH/1K
+EOtOghY6rCcMU/Gt1SSwawNQwS08Ft1ENCcadfsCAwEAAaNCMEAwHQYDVR0OBBYEFAqFqXdlBZh8
+QIH4D5csOPEK7DzPMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEB
+CwUAA4IBAQBMOqNErLlFsceTfsgLCkLfZOoc7llsCLqJX2rKSpWeeo8HxdpFcoJxDjrSzG+ntKEj
+u/Ykn8sX/oymzsLS28yN/HH8AynBbF0zX2S2ZTuJbxh2ePXcokgfGT+Ok+vx+hfuzU7jBBJV1uXk
+3fs+BXziHV7Gp7yXT2g69ekuCkO2r1dcYmh8t/2jioSgrGK+KwmHNPBqAbubKVY8/gA3zyNs8U6q
+tnRGEmyR7jTV7JqR50S+kDFy1UkC9gLl9B/rfNmWVan/7Ir5mUf/NVoCqgTLiluHcSmRvaS0eg29
+mvVXIwAHIRc/SjnRBUkLp7Y3gaVdjKozXoEofKd9J+sAro03
+-----END CERTIFICATE-----
+
+EC-ACC
+======
+-----BEGIN CERTIFICATE-----
+MIIFVjCCBD6gAwIBAgIQ7is969Qh3hSoYqwE893EATANBgkqhkiG9w0BAQUFADCB8zELMAkGA1UE
+BhMCRVMxOzA5BgNVBAoTMkFnZW5jaWEgQ2F0YWxhbmEgZGUgQ2VydGlmaWNhY2lvIChOSUYgUS0w
+ODAxMTc2LUkpMSgwJgYDVQQLEx9TZXJ2ZWlzIFB1YmxpY3MgZGUgQ2VydGlmaWNhY2lvMTUwMwYD
+VQQLEyxWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5ldC92ZXJhcnJlbCAoYykwMzE1MDMGA1UE
+CxMsSmVyYXJxdWlhIEVudGl0YXRzIGRlIENlcnRpZmljYWNpbyBDYXRhbGFuZXMxDzANBgNVBAMT
+BkVDLUFDQzAeFw0wMzAxMDcyMzAwMDBaFw0zMTAxMDcyMjU5NTlaMIHzMQswCQYDVQQGEwJFUzE7
+MDkGA1UEChMyQWdlbmNpYSBDYXRhbGFuYSBkZSBDZXJ0aWZpY2FjaW8gKE5JRiBRLTA4MDExNzYt
+SSkxKDAmBgNVBAsTH1NlcnZlaXMgUHVibGljcyBkZSBDZXJ0aWZpY2FjaW8xNTAzBgNVBAsTLFZl
+Z2V1IGh0dHBzOi8vd3d3LmNhdGNlcnQubmV0L3ZlcmFycmVsIChjKTAzMTUwMwYDVQQLEyxKZXJh
+cnF1aWEgRW50aXRhdHMgZGUgQ2VydGlmaWNhY2lvIENhdGFsYW5lczEPMA0GA1UEAxMGRUMtQUND
+MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsyLHT+KXQpWIR4NA9h0X84NzJB5R85iK
+w5K4/0CQBXCHYMkAqbWUZRkiFRfCQ2xmRJoNBD45b6VLeqpjt4pEndljkYRm4CgPukLjbo73FCeT
+ae6RDqNfDrHrZqJyTxIThmV6PttPB/SnCWDaOkKZx7J/sxaVHMf5NLWUhdWZXqBIoH7nF2W4onW4
+HvPlQn2v7fOKSGRdghST2MDk/7NQcvJ29rNdQlB50JQ+awwAvthrDk4q7D7SzIKiGGUzE3eeml0a
+E9jD2z3Il3rucO2n5nzbcc8tlGLfbdb1OL4/pYUKGbio2Al1QnDE6u/LDsg0qBIimAy4E5S2S+zw
+0JDnJwIDAQABo4HjMIHgMB0GA1UdEQQWMBSBEmVjX2FjY0BjYXRjZXJ0Lm5ldDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUoMOLRKo3pUW/l4Ba0fF4opvpXY0wfwYD
+VR0gBHgwdjB0BgsrBgEEAfV4AQMBCjBlMCwGCCsGAQUFBwIBFiBodHRwczovL3d3dy5jYXRjZXJ0
+Lm5ldC92ZXJhcnJlbDA1BggrBgEFBQcCAjApGidWZWdldSBodHRwczovL3d3dy5jYXRjZXJ0Lm5l
+dC92ZXJhcnJlbCAwDQYJKoZIhvcNAQEFBQADggEBAKBIW4IB9k1IuDlVNZyAelOZ1Vr/sXE7zDkJ
+lF7W2u++AVtd0x7Y/X1PzaBB4DSTv8vihpw3kpBWHNzrKQXlxJ7HNd+KDM3FIUPpqojlNcAZQmNa
+Al6kSBg6hW/cnbw/nZzBh7h6YQjpdwt/cKt63dmXLGQehb+8dJahw3oS7AwaboMMPOhyRp/7SNVe
+l+axofjk70YllJyJ22k4vuxcDlbHZVHlUIiIv0LVKz3l+bqeLrPK9HOSAgu+TGbrIP65y7WZf+a2
+E/rKS03Z7lNGBjvGTq2TWoF+bCpLagVFjPIhpDGQh2xlnJ2lYJU6Un/10asIbvPuW/mIPX64b24D
+5EI=
+-----END CERTIFICATE-----
+
+Hellenic Academic and Research Institutions RootCA 2011
+=======================================================
+-----BEGIN CERTIFICATE-----
+MIIEMTCCAxmgAwIBAgIBADANBgkqhkiG9w0BAQUFADCBlTELMAkGA1UEBhMCR1IxRDBCBgNVBAoT
+O0hlbGxlbmljIEFjYWRlbWljIGFuZCBSZXNlYXJjaCBJbnN0aXR1dGlvbnMgQ2VydC4gQXV0aG9y
+aXR5MUAwPgYDVQQDEzdIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
+IFJvb3RDQSAyMDExMB4XDTExMTIwNjEzNDk1MloXDTMxMTIwMTEzNDk1MlowgZUxCzAJBgNVBAYT
+AkdSMUQwQgYDVQQKEztIZWxsZW5pYyBBY2FkZW1pYyBhbmQgUmVzZWFyY2ggSW5zdGl0dXRpb25z
+IENlcnQuIEF1dGhvcml0eTFAMD4GA1UEAxM3SGVsbGVuaWMgQWNhZGVtaWMgYW5kIFJlc2VhcmNo
+IEluc3RpdHV0aW9ucyBSb290Q0EgMjAxMTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB
+AKlTAOMupvaO+mDYLZU++CwqVE7NuYRhlFhPjz2L5EPzdYmNUeTDN9KKiE15HrcS3UN4SoqS5tdI
+1Q+kOilENbgH9mgdVc04UfCMJDGFr4PJfel3r+0ae50X+bOdOFAPplp5kYCvN66m0zH7tSYJnTxa
+71HFK9+WXesyHgLacEnsbgzImjeN9/E2YEsmLIKe0HjzDQ9jpFEw4fkrJxIH2Oq9GGKYsFk3fb7u
+8yBRQlqD75O6aRXxYp2fmTmCobd0LovUxQt7L/DICto9eQqakxylKHJzkUOap9FNhYS5qXSPFEDH
+3N6sQWRstBmbAmNtJGSPRLIl6s5ddAxjMlyNh+UCAwEAAaOBiTCBhjAPBgNVHRMBAf8EBTADAQH/
+MAsGA1UdDwQEAwIBBjAdBgNVHQ4EFgQUppFC/RNhSiOeCKQp5dgTBCPuQSUwRwYDVR0eBEAwPqA8
+MAWCAy5ncjAFggMuZXUwBoIELmVkdTAGggQub3JnMAWBAy5ncjAFgQMuZXUwBoEELmVkdTAGgQQu
+b3JnMA0GCSqGSIb3DQEBBQUAA4IBAQAf73lB4XtuP7KMhjdCSk4cNx6NZrokgclPEg8hwAOXhiVt
+XdMiKahsog2p6z0GW5k6x8zDmjR/qw7IThzh+uTczQ2+vyT+bOdrwg3IBp5OjWEopmr95fZi6hg8
+TqBTnbI6nOulnJEWtk2C4AwFSKls9cz4y51JtPACpf1wA+2KIaWuE4ZJwzNzvoc7dIsXRSZMFpGD
+/md9zU1jZ/rzAxKWeAaNsWftjj++n08C9bMJL/NMh98qy5V8AcysNnq/onN694/BtZqhFLKPM58N
+7yLcZnuEvUUXBj08yrl3NI/K6s8/MT7jiOOASSXIl7WdmplNsDz4SgCbZN2fOUvRJ9e4
+-----END CERTIFICATE-----
+
+Actalis Authentication Root CA
+==============================
+-----BEGIN CERTIFICATE-----
+MIIFuzCCA6OgAwIBAgIIVwoRl0LE48wwDQYJKoZIhvcNAQELBQAwazELMAkGA1UEBhMCSVQxDjAM
+BgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlzIFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UE
+AwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290IENBMB4XDTExMDkyMjExMjIwMloXDTMwMDky
+MjExMjIwMlowazELMAkGA1UEBhMCSVQxDjAMBgNVBAcMBU1pbGFuMSMwIQYDVQQKDBpBY3RhbGlz
+IFMucC5BLi8wMzM1ODUyMDk2NzEnMCUGA1UEAwweQWN0YWxpcyBBdXRoZW50aWNhdGlvbiBSb290
+IENBMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAp8bEpSmkLO/lGMWwUKNvUTufClrJ
+wkg4CsIcoBh/kbWHuUA/3R1oHwiD1S0eiKD4j1aPbZkCkpAW1V8IbInX4ay8IMKx4INRimlNAJZa
+by/ARH6jDuSRzVju3PvHHkVH3Se5CAGfpiEd9UEtL0z9KK3giq0itFZljoZUj5NDKd45RnijMCO6
+zfB9E1fAXdKDa0hMxKufgFpbOr3JpyI/gCczWw63igxdBzcIy2zSekciRDXFzMwujt0q7bd9Zg1f
+YVEiVRvjRuPjPdA1YprbrxTIW6HMiRvhMCb8oJsfgadHHwTrozmSBp+Z07/T6k9QnBn+locePGX2
+oxgkg4YQ51Q+qDp2JE+BIcXjDwL4k5RHILv+1A7TaLndxHqEguNTVHnd25zS8gebLra8Pu2Fbe8l
+EfKXGkJh90qX6IuxEAf6ZYGyojnP9zz/GPvG8VqLWeICrHuS0E4UT1lF9gxeKF+w6D9Fz8+vm2/7
+hNN3WpVvrJSEnu68wEqPSpP4RCHiMUVhUE4Q2OM1fEwZtN4Fv6MGn8i1zeQf1xcGDXqVdFUNaBr8
+EBtiZJ1t4JWgw5QHVw0U5r0F+7if5t+L4sbnfpb2U8WANFAoWPASUHEXMLrmeGO89LKtmyuy/uE5
+jF66CyCU3nuDuP/jVo23Eek7jPKxwV2dpAtMK9myGPW1n0sCAwEAAaNjMGEwHQYDVR0OBBYEFFLY
+iDrIn3hm7YnzezhwlMkCAjbQMA8GA1UdEwEB/wQFMAMBAf8wHwYDVR0jBBgwFoAUUtiIOsifeGbt
+ifN7OHCUyQICNtAwDgYDVR0PAQH/BAQDAgEGMA0GCSqGSIb3DQEBCwUAA4ICAQALe3KHwGCmSUyI
+WOYdiPcUZEim2FgKDk8TNd81HdTtBjHIgT5q1d07GjLukD0R0i70jsNjLiNmsGe+b7bAEzlgqqI0
+JZN1Ut6nna0Oh4lScWoWPBkdg/iaKWW+9D+a2fDzWochcYBNy+A4mz+7+uAwTc+G02UQGRjRlwKx
+K3JCaKygvU5a2hi/a5iB0P2avl4VSM0RFbnAKVy06Ij3Pjaut2L9HmLecHgQHEhb2rykOLpn7VU+
+Xlff1ANATIGk0k9jpwlCCRT8AKnCgHNPLsBA2RF7SOp6AsDT6ygBJlh0wcBzIm2Tlf05fbsq4/aC
+4yyXX04fkZT6/iyj2HYauE2yOE+b+h1IYHkm4vP9qdCa6HCPSXrW5b0KDtst842/6+OkfcvHlXHo
+2qN8xcL4dJIEG4aspCJTQLas/kx2z/uUMsA1n3Y/buWQbqCmJqK4LL7RK4X9p2jIugErsWx0Hbhz
+lefut8cl8ABMALJ+tguLHPPAUJ4lueAI3jZm/zel0btUZCzJJ7VLkn5l/9Mt4blOvH+kQSGQQXem
+OR/qnuOf0GZvBeyqdn6/axag67XH/JJULysRJyU3eExRarDzzFhdFPFqSBX/wge2sY0PjlxQRrM9
+vwGYT7JZVEc+NHt4bVaTLnPqZih4zR0Uv6CPLy64Lo7yFIrM6bV8+2ydDKXhlg==
+-----END CERTIFICATE-----
+
+Trustis FPS Root CA
+===================
+-----BEGIN CERTIFICATE-----
+MIIDZzCCAk+gAwIBAgIQGx+ttiD5JNM2a/fH8YygWTANBgkqhkiG9w0BAQUFADBFMQswCQYDVQQG
+EwJHQjEYMBYGA1UEChMPVHJ1c3RpcyBMaW1pdGVkMRwwGgYDVQQLExNUcnVzdGlzIEZQUyBSb290
+IENBMB4XDTAzMTIyMzEyMTQwNloXDTI0MDEyMTExMzY1NFowRTELMAkGA1UEBhMCR0IxGDAWBgNV
+BAoTD1RydXN0aXMgTGltaXRlZDEcMBoGA1UECxMTVHJ1c3RpcyBGUFMgUm9vdCBDQTCCASIwDQYJ
+KoZIhvcNAQEBBQADggEPADCCAQoCggEBAMVQe547NdDfxIzNjpvto8A2mfRC6qc+gIMPpqdZh8mQ
+RUN+AOqGeSoDvT03mYlmt+WKVoaTnGhLaASMk5MCPjDSNzoiYYkchU59j9WvezX2fihHiTHcDnlk
+H5nSW7r+f2C/revnPDgpai/lkQtV/+xvWNUtyd5MZnGPDNcE2gfmHhjjvSkCqPoc4Vu5g6hBSLwa
+cY3nYuUtsuvffM/bq1rKMfFMIvMFE/eC+XN5DL7XSxzA0RU8k0Fk0ea+IxciAIleH2ulrG6nS4zt
+o3Lmr2NNL4XSFDWaLk6M6jKYKIahkQlBOrTh4/L68MkKokHdqeMDx4gVOxzUGpTXn2RZEm0CAwEA
+AaNTMFEwDwYDVR0TAQH/BAUwAwEB/zAfBgNVHSMEGDAWgBS6+nEleYtXQSUhhgtx67JkDoshZzAd
+BgNVHQ4EFgQUuvpxJXmLV0ElIYYLceuyZA6LIWcwDQYJKoZIhvcNAQEFBQADggEBAH5Y//01GX2c
+GE+esCu8jowU/yyg2kdbw++BLa8F6nRIW/M+TgfHbcWzk88iNVy2P3UnXwmWzaD+vkAMXBJV+JOC
+yinpXj9WV4s4NvdFGkwozZ5BuO1WTISkQMi4sKUraXAEasP41BIy+Q7DsdwyhEQsb8tGD+pmQQ9P
+8Vilpg0ND2HepZ5dfWWhPBfnqFVO76DH7cZEf1T1o+CP8HxVIo8ptoGj4W1OLBuAZ+ytIJ8MYmHV
+l/9D7S3B2l0pKoU/rGXuhg8FjZBf3+6f9L/uHfuY5H+QK4R4EA5sSVPvFVtlRkpdr7r7OnIdzfYl
+iB6XzCGcKQENZetX2fNXlrtIzYE=
+-----END CERTIFICATE-----
+
+StartCom Certification Authority
+================================
+-----BEGIN CERTIFICATE-----
+MIIHhzCCBW+gAwIBAgIBLTANBgkqhkiG9w0BAQsFADB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
+U3RhcnRDb20gTHRkLjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmlu
+ZzEpMCcGA1UEAxMgU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwHhcNMDYwOTE3MTk0
+NjM3WhcNMzYwOTE3MTk0NjM2WjB9MQswCQYDVQQGEwJJTDEWMBQGA1UEChMNU3RhcnRDb20gTHRk
+LjErMCkGA1UECxMiU2VjdXJlIERpZ2l0YWwgQ2VydGlmaWNhdGUgU2lnbmluZzEpMCcGA1UEAxMg
+U3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAw
+ggIKAoICAQDBiNsJvGxGfHiflXu1M5DycmLWwTYgIiRezul38kMKogZkpMyONvg45iPwbm2xPN1y
+o4UcodM9tDMr0y+v/uqwQVlntsQGfQqedIXWeUyAN3rfOQVSWff0G0ZDpNKFhdLDcfN1YjS6LIp/
+Ho/u7TTQEceWzVI9ujPW3U3eCztKS5/CJi/6tRYccjV3yjxd5srhJosaNnZcAdt0FCX+7bWgiA/d
+eMotHweXMAEtcnn6RtYTKqi5pquDSR3l8u/d5AGOGAqPY1MWhWKpDhk6zLVmpsJrdAfkK+F2PrRt
+2PZE4XNiHzvEvqBTViVsUQn3qqvKv3b9bZvzndu/PWa8DFaqr5hIlTpL36dYUNk4dalb6kMMAv+Z
+6+hsTXBbKWWc3apdzK8BMewM69KN6Oqce+Zu9ydmDBpI125C4z/eIT574Q1w+2OqqGwaVLRcJXrJ
+osmLFqa7LH4XXgVNWG4SHQHuEhANxjJ/GP/89PrNbpHoNkm+Gkhpi8KWTRoSsmkXwQqQ1vp5Iki/
+untp+HDH+no32NgN0nZPV/+Qt+OR0t3vwmC3Zzrd/qqc8NSLf3Iizsafl7b4r4qgEKjZ+xjGtrVc
+UjyJthkqcwEKDwOzEmDyei+B26Nu/yYwl/WL3YlXtq09s68rxbd2AvCl1iuahhQqcvbjM4xdCUsT
+37uMdBNSSwIDAQABo4ICEDCCAgwwDwYDVR0TAQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYD
+VR0OBBYEFE4L7xqkQFulF2mHMMo0aEPQQa7yMB8GA1UdIwQYMBaAFE4L7xqkQFulF2mHMMo0aEPQ
+Qa7yMIIBWgYDVR0gBIIBUTCCAU0wggFJBgsrBgEEAYG1NwEBATCCATgwLgYIKwYBBQUHAgEWImh0
+dHA6Ly93d3cuc3RhcnRzc2wuY29tL3BvbGljeS5wZGYwNAYIKwYBBQUHAgEWKGh0dHA6Ly93d3cu
+c3RhcnRzc2wuY29tL2ludGVybWVkaWF0ZS5wZGYwgc8GCCsGAQUFBwICMIHCMCcWIFN0YXJ0IENv
+bW1lcmNpYWwgKFN0YXJ0Q29tKSBMdGQuMAMCAQEagZZMaW1pdGVkIExpYWJpbGl0eSwgcmVhZCB0
+aGUgc2VjdGlvbiAqTGVnYWwgTGltaXRhdGlvbnMqIG9mIHRoZSBTdGFydENvbSBDZXJ0aWZpY2F0
+aW9uIEF1dGhvcml0eSBQb2xpY3kgYXZhaWxhYmxlIGF0IGh0dHA6Ly93d3cuc3RhcnRzc2wuY29t
+L3BvbGljeS5wZGYwEQYJYIZIAYb4QgEBBAQDAgAHMDgGCWCGSAGG+EIBDQQrFilTdGFydENvbSBG
+cmVlIFNTTCBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTANBgkqhkiG9w0BAQsFAAOCAgEAjo/n3JR5
+fPGFf59Jb2vKXfuM/gTFwWLRfUKKvFO3lANmMD+x5wqnUCBVJX92ehQN6wQOQOY+2IirByeDqXWm
+N3PH/UvSTa0XQMhGvjt/UfzDtgUx3M2FIk5xt/JxXrAaxrqTi3iSSoX4eA+D/i+tLPfkpLst0OcN
+Org+zvZ49q5HJMqjNTbOx8aHmNrs++myziebiMMEofYLWWivydsQD032ZGNcpRJvkrKTlMeIFw6T
+tn5ii5B/q06f/ON1FE8qMt9bDeD1e5MNq6HPh+GlBEXoPBKlCcWw0bdT82AUuoVpaiF8H3VhFyAX
+e2w7QSlc4axa0c2Mm+tgHRns9+Ww2vl5GKVFP0lDV9LdJNUso/2RjSe15esUBppMeyG7Oq0wBhjA
+2MFrLH9ZXF2RsXAiV+uKa0hK1Q8p7MZAwC+ITGgBF3f0JBlPvfrhsiAhS90a2Cl9qrjeVOwhVYBs
+HvUwyKMQ5bLmKhQxw4UtjJixhlpPiVktucf3HMiKf8CdBUrmQk9io20ppB+Fq9vlgcitKj1MXVuE
+JnHEhV5xJMqlG2zYYdMa4FTbzrqpMrUi9nNBCV24F10OD5mQ1kfabwo6YigUZ4LZ8dCAWZvLMdib
+D4x3TrVoivJs9iQOLWxwxXPR3hTQcY+203sC9uO41Alua551hDnmfyWl8kgAwKQB2j8=
+-----END CERTIFICATE-----
+
+StartCom Certification Authority G2
+===================================
+-----BEGIN CERTIFICATE-----
+MIIFYzCCA0ugAwIBAgIBOzANBgkqhkiG9w0BAQsFADBTMQswCQYDVQQGEwJJTDEWMBQGA1UEChMN
+U3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkg
+RzIwHhcNMTAwMTAxMDEwMDAxWhcNMzkxMjMxMjM1OTAxWjBTMQswCQYDVQQGEwJJTDEWMBQGA1UE
+ChMNU3RhcnRDb20gTHRkLjEsMCoGA1UEAxMjU3RhcnRDb20gQ2VydGlmaWNhdGlvbiBBdXRob3Jp
+dHkgRzIwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQC2iTZbB7cgNr2Cu+EWIAOVeq8O
+o1XJJZlKxdBWQYeQTSFgpBSHO839sj60ZwNq7eEPS8CRhXBF4EKe3ikj1AENoBB5uNsDvfOpL9HG
+4A/LnooUCri99lZi8cVytjIl2bLzvWXFDSxu1ZJvGIsAQRSCb0AgJnooD/Uefyf3lLE3PbfHkffi
+Aez9lInhzG7TNtYKGXmu1zSCZf98Qru23QumNK9LYP5/Q0kGi4xDuFby2X8hQxfqp0iVAXV16iul
+Q5XqFYSdCI0mblWbq9zSOdIxHWDirMxWRST1HFSr7obdljKF+ExP6JV2tgXdNiNnvP8V4so75qbs
+O+wmETRIjfaAKxojAuuKHDp2KntWFhxyKrOq42ClAJ8Em+JvHhRYW6Vsi1g8w7pOOlz34ZYrPu8H
+vKTlXcxNnw3h3Kq74W4a7I/htkxNeXJdFzULHdfBR9qWJODQcqhaX2YtENwvKhOuJv4KHBnM0D4L
+nMgJLvlblnpHnOl68wVQdJVznjAJ85eCXuaPOQgeWeU1FEIT/wCc976qUM/iUUjXuG+v+E5+M5iS
+FGI6dWPPe/regjupuznixL0sAA7IF6wT700ljtizkC+p2il9Ha90OrInwMEePnWjFqmveiJdnxMa
+z6eg6+OGCtP95paV1yPIN93EfKo2rJgaErHgTuixO/XWb/Ew1wIDAQABo0IwQDAPBgNVHRMBAf8E
+BTADAQH/MA4GA1UdDwEB/wQEAwIBBjAdBgNVHQ4EFgQUS8W0QGutHLOlHGVuRjaJhwUMDrYwDQYJ
+KoZIhvcNAQELBQADggIBAHNXPyzVlTJ+N9uWkusZXn5T50HsEbZH77Xe7XRcxfGOSeD8bpkTzZ+K
+2s06Ctg6Wgk/XzTQLwPSZh0avZyQN8gMjgdalEVGKua+etqhqaRpEpKwfTbURIfXUfEpY9Z1zRbk
+J4kd+MIySP3bmdCPX1R0zKxnNBFi2QwKN4fRoxdIjtIXHfbX/dtl6/2o1PXWT6RbdejF0mCy2wl+
+JYt7ulKSnj7oxXehPOBKc2thz4bcQ///If4jXSRK9dNtD2IEBVeC2m6kMyV5Sy5UGYvMLD0w6dEG
+/+gyRr61M3Z3qAFdlsHB1b6uJcDJHgoJIIihDsnzb02CVAAgp9KP5DlUFy6NHrgbuxu9mk47EDTc
+nIhT76IxW1hPkWLIwpqazRVdOKnWvvgTtZ8SafJQYqz7Fzf07rh1Z2AQ+4NQ+US1dZxAF7L+/Xld
+blhYXzD8AK6vM8EOTmy6p6ahfzLbOOCxchcKK5HsamMm7YnUeMx0HgX4a/6ManY5Ka5lIxKVCCIc
+l85bBu4M4ru8H0ST9tg4RQUh7eStqxK2A6RCLi3ECToDZ2mEmuFZkIoohdVddLHRDiBYmxOlsGOm
+7XtH/UVVMKTumtTm4ofvmMkyghEpIrwACjFeLQ/Ajulrso8uBtjRkcfGEvRM/TAXw8HaOFvjqerm
+obp573PYtlNXLfbQ4ddI
+-----END CERTIFICATE-----
+
+Buypass Class 2 Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMiBSb290IENBMB4X
+DTEwMTAyNjA4MzgwM1oXDTQwMTAyNjA4MzgwM1owTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
+eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDIgUm9vdCBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBANfHXvfBB9R3+0Mh9PT1aeTuMgHbo4Yf5FkNuud1
+g1Lr6hxhFUi7HQfKjK6w3Jad6sNgkoaCKHOcVgb/S2TwDCo3SbXlzwx87vFKu3MwZfPVL4O2fuPn
+9Z6rYPnT8Z2SdIrkHJasW4DptfQxh6NR/Md+oW+OU3fUl8FVM5I+GC911K2GScuVr1QGbNgGE41b
+/+EmGVnAJLqBcXmQRFBoJJRfuLMR8SlBYaNByyM21cHxMlAQTn/0hpPshNOOvEu/XAFOBz3cFIqU
+CqTqc/sLUegTBxj6DvEr0VQVfTzh97QZQmdiXnfgolXsttlpF9U6r0TtSsWe5HonfOV116rLJeff
+awrbD02TTqigzXsu8lkBarcNuAeBfos4GzjmCleZPe4h6KP1DBbdi+w0jpwqHAAVF41og9JwnxgI
+zRFo1clrUs3ERo/ctfPYV3Me6ZQ5BL/T3jjetFPsaRyifsSP5BtwrfKi+fv3FmRmaZ9JUaLiFRhn
+Bkp/1Wy1TbMz4GHrXb7pmA8y1x1LPC5aAVKRCfLf6o3YBkBjqhHk/sM3nhRSP/TizPJhk9H9Z2vX
+Uq6/aKtAQ6BXNVN48FP4YUIHZMbXb5tMOA1jrGKvNouicwoN9SG9dKpN6nIDSdvHXx1iY8f93ZHs
+M+71bbRuMGjeyNYmsHVee7QHIJihdjK4TWxPAgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFMmAd+BikoL1RpzzuvdMw964o605MA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
+AAOCAgEAU18h9bqwOlI5LJKwbADJ784g7wbylp7ppHR/ehb8t/W2+xUbP6umwHJdELFx7rxP462s
+A20ucS6vxOOto70MEae0/0qyexAQH6dXQbLArvQsWdZHEIjzIVEpMMpghq9Gqx3tOluwlN5E40EI
+osHsHdb9T7bWR9AUC8rmyrV7d35BH16Dx7aMOZawP5aBQW9gkOLo+fsicdl9sz1Gv7SEr5AcD48S
+aq/v7h56rgJKihcrdv6sVIkkLE8/trKnToyokZf7KcZ7XC25y2a2t6hbElGFtQl+Ynhw/qlqYLYd
+DnkM/crqJIByw5c/8nerQyIKx+u2DISCLIBrQYoIwOula9+ZEsuK1V6ADJHgJgg2SMX6OBE1/yWD
+LfJ6v9r9jv6ly0UsH8SIU653DtmadsWOLB2jutXsMq7Aqqz30XpN69QH4kj3Io6wpJ9qzo6ysmD0
+oyLQI+uUWnpp3Q+/QFesa1lQ2aOZ4W7+jQF5JyMV3pKdewlNWudLSDBaGOYKbeaP4NK75t98biGC
+wWg5TbSYWGZizEqQXsP6JwSxeRV0mcy+rSDeJmAc61ZRpqPq5KM/p/9h3PFaTWwyI0PurKju7koS
+CTxdccK+efrCh2gdC/1cacwG0Jp9VJkqyTkaGa9LKkPzY11aWOIv4x3kqdbQCtCev9eBCfHJxyYN
+rJgWVqA=
+-----END CERTIFICATE-----
+
+Buypass Class 3 Root CA
+=======================
+-----BEGIN CERTIFICATE-----
+MIIFWTCCA0GgAwIBAgIBAjANBgkqhkiG9w0BAQsFADBOMQswCQYDVQQGEwJOTzEdMBsGA1UECgwU
+QnV5cGFzcyBBUy05ODMxNjMzMjcxIDAeBgNVBAMMF0J1eXBhc3MgQ2xhc3MgMyBSb290IENBMB4X
+DTEwMTAyNjA4Mjg1OFoXDTQwMTAyNjA4Mjg1OFowTjELMAkGA1UEBhMCTk8xHTAbBgNVBAoMFEJ1
+eXBhc3MgQVMtOTgzMTYzMzI3MSAwHgYDVQQDDBdCdXlwYXNzIENsYXNzIDMgUm9vdCBDQTCCAiIw
+DQYJKoZIhvcNAQEBBQADggIPADCCAgoCggIBAKXaCpUWUOOV8l6ddjEGMnqb8RB2uACatVI2zSRH
+sJ8YZLya9vrVediQYkwiL944PdbgqOkcLNt4EemOaFEVcsfzM4fkoF0LXOBXByow9c3EN3coTRiR
+5r/VUv1xLXA+58bEiuPwKAv0dpihi4dVsjoT/Lc+JzeOIuOoTyrvYLs9tznDDgFHmV0ST9tD+leh
+7fmdvhFHJlsTmKtdFoqwNxxXnUX/iJY2v7vKB3tvh2PX0DJq1l1sDPGzbjniazEuOQAnFN44wOwZ
+ZoYS6J1yFhNkUsepNxz9gjDthBgd9K5c/3ATAOux9TN6S9ZV+AWNS2mw9bMoNlwUxFFzTWsL8TQH
+2xc519woe2v1n/MuwU8XKhDzzMro6/1rqy6any2CbgTUUgGTLT2G/H783+9CHaZr77kgxve9oKeV
+/afmiSTYzIw0bOIjL9kSGiG5VZFvC5F5GQytQIgLcOJ60g7YaEi7ghM5EFjp2CoHxhLbWNvSO1UQ
+RwUVZ2J+GGOmRj8JDlQyXr8NYnon74Do29lLBlo3WiXQCBJ31G8JUJc9yB3D34xFMFbG02SrZvPA
+Xpacw8Tvw3xrizp5f7NJzz3iiZ+gMEuFuZyUJHmPfWupRWgPK9Dx2hzLabjKSWJtyNBjYt1gD1iq
+j6G8BaVmos8bdrKEZLFMOVLAMLrwjEsCsLa3AgMBAAGjQjBAMA8GA1UdEwEB/wQFMAMBAf8wHQYD
+VR0OBBYEFEe4zf/lb+74suwvTg75JbCOPGvDMA4GA1UdDwEB/wQEAwIBBjANBgkqhkiG9w0BAQsF
+AAOCAgEAACAjQTUEkMJAYmDv4jVM1z+s4jSQuKFvdvoWFqRINyzpkMLyPPgKn9iB5btb2iUspKdV
+cSQy9sgL8rxq+JOssgfCX5/bzMiKqr5qb+FJEMwx14C7u8jYog5kV+qi9cKpMRXSIGrs/CIBKM+G
+uIAeqcwRpTzyFrNHnfzSgCHEy9BHcEGhyoMZCCxt8l13nIoUE9Q2HJLw5QY33KbmkJs4j1xrG0aG
+Q0JfPgEHU1RdZX33inOhmlRaHylDFCfChQ+1iHsaO5S3HWCntZznKWlXWpuTekMwGwPXYshApqr8
+ZORK15FTAaggiG6cX0S5y2CBNOxv033aSF/rtJC8LakcC6wc1aJoIIAE1vyxjy+7SjENSoYc6+I2
+KSb12tjE8nVhz36udmNKekBlk4f4HoCMhuWG1o8O/FMsYOgWYRqiPkN7zTlgVGr18okmAWiDSKIz
+6MkEkbIRNBE+6tBDGR8Dk5AM/1E9V/RBbuHLoL7ryWPNbczk+DaqaJ3tvV2XcEQNtg413OEMXbug
+UZTLfhbrES+jkkXITHHZvMmZUldGL1DPvTVp9D0VzgalLA8+9oG6lLvDu79leNKGef9JOxqDDPDe
+eOzI8k1MGt6CKfjBWtrt7uYnXuhF0J0cUahoq0Tj0Itq4/g7u9xN12TyUb7mqqta6THuBrxzvxNi
+Cp/HuZc=
+-----END CERTIFICATE-----
+
+T-TeleSec GlobalRoot Class 3
+============================
+-----BEGIN CERTIFICATE-----
+MIIDwzCCAqugAwIBAgIBATANBgkqhkiG9w0BAQsFADCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoM
+IlQtU3lzdGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBU
+cnVzdCBDZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwHhcNMDgx
+MDAxMTAyOTU2WhcNMzMxMDAxMjM1OTU5WjCBgjELMAkGA1UEBhMCREUxKzApBgNVBAoMIlQtU3lz
+dGVtcyBFbnRlcnByaXNlIFNlcnZpY2VzIEdtYkgxHzAdBgNVBAsMFlQtU3lzdGVtcyBUcnVzdCBD
+ZW50ZXIxJTAjBgNVBAMMHFQtVGVsZVNlYyBHbG9iYWxSb290IENsYXNzIDMwggEiMA0GCSqGSIb3
+DQEBAQUAA4IBDwAwggEKAoIBAQC9dZPwYiJvJK7genasfb3ZJNW4t/zN8ELg63iIVl6bmlQdTQyK
+9tPPcPRStdiTBONGhnFBSivwKixVA9ZIw+A5OO3yXDw/RLyTPWGrTs0NvvAgJ1gORH8EGoel15YU
+NpDQSXuhdfsaa3Ox+M6pCSzyU9XDFES4hqX2iys52qMzVNn6chr3IhUciJFrf2blw2qAsCTz34ZF
+iP0Zf3WHHx+xGwpzJFu5ZeAsVMhg02YXP+HMVDNzkQI6pn97djmiH5a2OK61yJN0HZ65tOVgnS9W
+0eDrXltMEnAMbEQgqxHY9Bn20pxSN+f6tsIxO0rUFJmtxxr1XV/6B7h8DR/Wgx6zAgMBAAGjQjBA
+MA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMB0GA1UdDgQWBBS1A/d2O2GCahKqGFPr
+AyGUv/7OyjANBgkqhkiG9w0BAQsFAAOCAQEAVj3vlNW92nOyWL6ukK2YJ5f+AbGwUgC4TeQbIXQb
+fsDuXmkqJa9c1h3a0nnJ85cp4IaH3gRZD/FZ1GSFS5mvJQQeyUapl96Cshtwn5z2r3Ex3XsFpSzT
+ucpH9sry9uetuUg/vBa3wW306gmv7PO15wWeph6KU1HWk4HMdJP2udqmJQV0eVp+QD6CSyYRMG7h
+P0HHRwA11fXT91Q+gT3aSWqas+8QPebrb9HIIkfLzM8BMZLZGOMivgkeGj5asuRrDFR6fUNOuIml
+e9eiPZaGzPImNC1qkp2aGtAw4l1OBLBfiyB+d8E9lYLRRpo7PHi4b6HQDWSieB4pTpPDpFQUWw==
+-----END CERTIFICATE-----
+
+EE Certification Centre Root CA
+===============================
+-----BEGIN CERTIFICATE-----
+MIIEAzCCAuugAwIBAgIQVID5oHPtPwBMyonY43HmSjANBgkqhkiG9w0BAQUFADB1MQswCQYDVQQG
+EwJFRTEiMCAGA1UECgwZQVMgU2VydGlmaXRzZWVyaW1pc2tlc2t1czEoMCYGA1UEAwwfRUUgQ2Vy
+dGlmaWNhdGlvbiBDZW50cmUgUm9vdCBDQTEYMBYGCSqGSIb3DQEJARYJcGtpQHNrLmVlMCIYDzIw
+MTAxMDMwMTAxMDMwWhgPMjAzMDEyMTcyMzU5NTlaMHUxCzAJBgNVBAYTAkVFMSIwIAYDVQQKDBlB
+UyBTZXJ0aWZpdHNlZXJpbWlza2Vza3VzMSgwJgYDVQQDDB9FRSBDZXJ0aWZpY2F0aW9uIENlbnRy
+ZSBSb290IENBMRgwFgYJKoZIhvcNAQkBFglwa2lAc2suZWUwggEiMA0GCSqGSIb3DQEBAQUAA4IB
+DwAwggEKAoIBAQDIIMDs4MVLqwd4lfNE7vsLDP90jmG7sWLqI9iroWUyeuuOF0+W2Ap7kaJjbMeM
+TC55v6kF/GlclY1i+blw7cNRfdCT5mzrMEvhvH2/UpvObntl8jixwKIy72KyaOBhU8E2lf/slLo2
+rpwcpzIP5Xy0xm90/XsY6KxX7QYgSzIwWFv9zajmofxwvI6Sc9uXp3whrj3B9UiHbCe9nyV0gVWw
+93X2PaRka9ZP585ArQ/dMtO8ihJTmMmJ+xAdTX7Nfh9WDSFwhfYggx/2uh8Ej+p3iDXE/+pOoYtN
+P2MbRMNE1CV2yreN1x5KZmTNXMWcg+HCCIia7E6j8T4cLNlsHaFLAgMBAAGjgYowgYcwDwYDVR0T
+AQH/BAUwAwEB/zAOBgNVHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFBLyWj7qVhy/zQas8fElyalL1BSZ
+MEUGA1UdJQQ+MDwGCCsGAQUFBwMCBggrBgEFBQcDAQYIKwYBBQUHAwMGCCsGAQUFBwMEBggrBgEF
+BQcDCAYIKwYBBQUHAwkwDQYJKoZIhvcNAQEFBQADggEBAHv25MANqhlHt01Xo/6tu7Fq1Q+e2+Rj
+xY6hUFaTlrg4wCQiZrxTFGGVv9DHKpY5P30osxBAIWrEr7BSdxjhlthWXePdNl4dp1BUoMUq5KqM
+lIpPnTX/dqQGE5Gion0ARD9V04I8GtVbvFZMIi5GQ4okQC3zErg7cBqklrkar4dBGmoYDQZPxz5u
+uSlNDUmJEYcyW+ZLBMjkXOZ0c5RdFpgTlf7727FE5TpwrDdr5rMzcijJs1eg9gIWiAYLtqZLICjU
+3j2LrTcFU3T+bsy8QxdxXvnFzBqpYe73dgzzcvRyrc9yAjYHR8/vGVCJYMzpJJUPwssd8m92kMfM
+dcGWxZ0=
+-----END CERTIFICATE-----
diff --git a/sample/res/raw/toy_mono.wav b/sample/res/raw/toy_mono.wav
new file mode 100644
index 000000000..a225ac2cb
Binary files /dev/null and b/sample/res/raw/toy_mono.wav differ
diff --git a/sample/res/values-v11/styles.xml b/sample/res/values-v11/styles.xml
new file mode 100644
index 000000000..3c02242ad
--- /dev/null
+++ b/sample/res/values-v11/styles.xml
@@ -0,0 +1,11 @@
+
+
+
+
+
+
diff --git a/sample/res/values-v14/styles.xml b/sample/res/values-v14/styles.xml
new file mode 100644
index 000000000..a91fd0372
--- /dev/null
+++ b/sample/res/values-v14/styles.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
diff --git a/sample/res/values/strings.xml b/sample/res/values/strings.xml
new file mode 100644
index 000000000..9d39c77ce
--- /dev/null
+++ b/sample/res/values/strings.xml
@@ -0,0 +1,5 @@
+
+
+ Linphone Mini
+
+
diff --git a/sample/res/values/styles.xml b/sample/res/values/styles.xml
new file mode 100644
index 000000000..6ce89c7ba
--- /dev/null
+++ b/sample/res/values/styles.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
diff --git a/sample/src/org/linphone/mini/LinphoneMiniActivity.java b/sample/src/org/linphone/mini/LinphoneMiniActivity.java
new file mode 100644
index 000000000..80f43164b
--- /dev/null
+++ b/sample/src/org/linphone/mini/LinphoneMiniActivity.java
@@ -0,0 +1,53 @@
+package org.linphone.mini;
+/*
+LinphoneMiniActivity.java
+Copyright (C) 2014 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import android.app.Activity;
+import android.os.Bundle;
+
+/**
+ * @author Sylvain Berfini
+ */
+public class LinphoneMiniActivity extends Activity {
+ private LinphoneMiniManager mManager;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ mManager = new LinphoneMiniManager(this);
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ }
+
+ @Override
+ protected void onDestroy() {
+ mManager.destroy();
+
+ super.onDestroy();
+ }
+}
diff --git a/sample/src/org/linphone/mini/LinphoneMiniManager.java b/sample/src/org/linphone/mini/LinphoneMiniManager.java
new file mode 100644
index 000000000..aaf3d5b61
--- /dev/null
+++ b/sample/src/org/linphone/mini/LinphoneMiniManager.java
@@ -0,0 +1,290 @@
+package org.linphone.mini;
+/*
+LinphoneMiniManager.java
+Copyright (C) 2014 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import java.io.File;
+import java.io.IOException;
+import java.util.Timer;
+import java.util.TimerTask;
+
+import org.linphone.core.LinphoneAddress;
+import org.linphone.core.LinphoneCall;
+import org.linphone.core.LinphoneCall.State;
+import org.linphone.core.LinphoneCallStats;
+import org.linphone.core.LinphoneChatMessage;
+import org.linphone.core.LinphoneChatRoom;
+import org.linphone.core.LinphoneContent;
+import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneCore.EcCalibratorStatus;
+import org.linphone.core.LinphoneCore.GlobalState;
+import org.linphone.core.LinphoneCore.RegistrationState;
+import org.linphone.core.LinphoneCore.RemoteProvisioningState;
+import org.linphone.core.LinphoneCoreException;
+import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.core.LinphoneCoreListener;
+import org.linphone.core.LinphoneEvent;
+import org.linphone.core.LinphoneFriend;
+import org.linphone.core.LinphoneInfoMessage;
+import org.linphone.core.LinphoneProxyConfig;
+import org.linphone.core.PublishState;
+import org.linphone.core.SubscriptionState;
+import org.linphone.mediastream.Log;
+import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration;
+import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration.AndroidCamera;
+
+import android.content.Context;
+import android.content.pm.PackageManager.NameNotFoundException;
+
+/**
+ * @author Sylvain Berfini
+ */
+public class LinphoneMiniManager implements LinphoneCoreListener {
+ private static LinphoneMiniManager mInstance;
+ private Context mContext;
+ private LinphoneCore mLinphoneCore;
+ private Timer mTimer;
+
+ public LinphoneMiniManager(Context c) {
+ mContext = c;
+ LinphoneCoreFactory.instance().setDebugMode(true, "Linphone Mini");
+
+ try {
+ String basePath = mContext.getFilesDir().getAbsolutePath();
+ copyAssetsFromPackage(basePath);
+ mLinphoneCore = LinphoneCoreFactory.instance().createLinphoneCore(this, basePath + "/.linphonerc", basePath + "/linphonerc", null, mContext);
+ initLinphoneCoreValues(basePath);
+
+ setUserAgent();
+ setFrontCamAsDefault();
+ startIterate();
+ mInstance = this;
+ mLinphoneCore.setNetworkReachable(true); // Let's assume it's true
+ } catch (LinphoneCoreException e) {
+ } catch (IOException e) {
+ }
+ }
+
+ public static LinphoneMiniManager getInstance() {
+ return mInstance;
+ }
+
+ public void destroy() {
+ try {
+ mTimer.cancel();
+ mLinphoneCore.destroy();
+ }
+ catch (RuntimeException e) {
+ }
+ finally {
+ mLinphoneCore = null;
+ mInstance = null;
+ }
+ }
+
+ private void startIterate() {
+ TimerTask lTask = new TimerTask() {
+ @Override
+ public void run() {
+ mLinphoneCore.iterate();
+ }
+ };
+
+ /*use schedule instead of scheduleAtFixedRate to avoid iterate from being call in burst after cpu wake up*/
+ mTimer = new Timer("LinphoneMini scheduler");
+ mTimer.schedule(lTask, 0, 20);
+ }
+
+ private void setUserAgent() {
+ try {
+ String versionName = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionName;
+ if (versionName == null) {
+ versionName = String.valueOf(mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).versionCode);
+ }
+ mLinphoneCore.setUserAgent("LinphoneMiniAndroid", versionName);
+ } catch (NameNotFoundException e) {
+ }
+ }
+
+ private void setFrontCamAsDefault() {
+ int camId = 0;
+ AndroidCamera[] cameras = AndroidCameraConfiguration.retrieveCameras();
+ for (AndroidCamera androidCamera : cameras) {
+ if (androidCamera.frontFacing)
+ camId = androidCamera.id;
+ }
+ mLinphoneCore.setVideoDevice(camId);
+ }
+
+ private void copyAssetsFromPackage(String basePath) throws IOException {
+ LinphoneMiniUtils.copyIfNotExist(mContext, R.raw.oldphone_mono, basePath + "/oldphone_mono.wav");
+ LinphoneMiniUtils.copyIfNotExist(mContext, R.raw.ringback, basePath + "/ringback.wav");
+ LinphoneMiniUtils.copyIfNotExist(mContext, R.raw.toy_mono, basePath + "/toy_mono.wav");
+ LinphoneMiniUtils.copyIfNotExist(mContext, R.raw.linphonerc_default, basePath + "/.linphonerc");
+ LinphoneMiniUtils.copyFromPackage(mContext, R.raw.linphonerc_factory, new File(basePath + "/linphonerc").getName());
+ LinphoneMiniUtils.copyIfNotExist(mContext, R.raw.lpconfig, basePath + "/lpconfig.xsd");
+ LinphoneMiniUtils.copyIfNotExist(mContext, R.raw.rootca, basePath + "/rootca.pem");
+ }
+
+ private void initLinphoneCoreValues(String basePath) {
+ mLinphoneCore.setContext(mContext);
+ mLinphoneCore.setRing(null);
+ mLinphoneCore.setRootCA(basePath + "/rootca.pem");
+ mLinphoneCore.setPlayFile(basePath + "/toy_mono.wav");
+ mLinphoneCore.setChatDatabasePath(basePath + "/linphone-history.db");
+
+ int availableCores = Runtime.getRuntime().availableProcessors();
+ mLinphoneCore.setCpuCount(availableCores);
+ }
+
+ @Override
+ public void authInfoRequested(LinphoneCore lc, String realm, String username) {
+
+ }
+
+ @Override
+ public void globalState(LinphoneCore lc, GlobalState state, String message) {
+ Log.d("Global state: " + state + "(" + message + ")");
+ }
+
+ @Override
+ public void callState(LinphoneCore lc, LinphoneCall call, State cstate,
+ String message) {
+ Log.d("Call state: " + cstate + "(" + message + ")");
+ }
+
+ @Override
+ public void callStatsUpdated(LinphoneCore lc, LinphoneCall call,
+ LinphoneCallStats stats) {
+
+ }
+
+ @Override
+ public void callEncryptionChanged(LinphoneCore lc, LinphoneCall call,
+ boolean encrypted, String authenticationToken) {
+
+ }
+
+ @Override
+ public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg,
+ RegistrationState cstate, String smessage) {
+ Log.d("Registration state: " + cstate + "(" + smessage + ")");
+ }
+
+ @Override
+ public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf,
+ String url) {
+
+ }
+
+ @Override
+ public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {
+
+ }
+
+ @Override
+ public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,
+ LinphoneAddress from, String message) {
+
+ }
+
+ @Override
+ public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr,
+ LinphoneChatMessage message) {
+ Log.d("Message received from " + cr.getPeerAddress().asString() + " : " + message.getText() + "(" + message.getExternalBodyUrl() + ")");
+ }
+
+ @Override
+ public void isComposingReceived(LinphoneCore lc, LinphoneChatRoom cr) {
+ Log.d("Composing received from " + cr.getPeerAddress().asString());
+ }
+
+ @Override
+ public void dtmfReceived(LinphoneCore lc, LinphoneCall call, int dtmf) {
+
+ }
+
+ @Override
+ public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,
+ int delay_ms, Object data) {
+
+ }
+
+ @Override
+ public void notifyReceived(LinphoneCore lc, LinphoneCall call,
+ LinphoneAddress from, byte[] event) {
+
+ }
+
+ @Override
+ public void transferState(LinphoneCore lc, LinphoneCall call,
+ State new_call_state) {
+
+ }
+
+ @Override
+ public void infoReceived(LinphoneCore lc, LinphoneCall call,
+ LinphoneInfoMessage info) {
+
+ }
+
+ @Override
+ public void subscriptionStateChanged(LinphoneCore lc, LinphoneEvent ev,
+ SubscriptionState state) {
+
+ }
+
+ @Override
+ public void notifyReceived(LinphoneCore lc, LinphoneEvent ev,
+ String eventName, LinphoneContent content) {
+ Log.d("Notify received: " + eventName + " -> " + content.getDataAsString());
+ }
+
+ @Override
+ public void publishStateChanged(LinphoneCore lc, LinphoneEvent ev,
+ PublishState state) {
+
+ }
+
+ @Override
+ public void configuringStatus(LinphoneCore lc,
+ RemoteProvisioningState state, String message) {
+ Log.d("Configuration state: " + state + "(" + message + ")");
+ }
+
+ @Override
+ public void show(LinphoneCore lc) {
+
+ }
+
+ @Override
+ public void displayStatus(LinphoneCore lc, String message) {
+
+ }
+
+ @Override
+ public void displayMessage(LinphoneCore lc, String message) {
+
+ }
+
+ @Override
+ public void displayWarning(LinphoneCore lc, String message) {
+
+ }
+
+}
diff --git a/sample/src/org/linphone/mini/LinphoneMiniUtils.java b/sample/src/org/linphone/mini/LinphoneMiniUtils.java
new file mode 100644
index 000000000..8793e4488
--- /dev/null
+++ b/sample/src/org/linphone/mini/LinphoneMiniUtils.java
@@ -0,0 +1,51 @@
+package org.linphone.mini;
+/*
+LinphoneMiniUtils.java
+Copyright (C) 2014 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+import android.content.Context;
+
+/**
+ * @author Sylvain Berfini
+ */
+public class LinphoneMiniUtils {
+ public static void copyIfNotExist(Context context, int ressourceId, String target) throws IOException {
+ File lFileToCopy = new File(target);
+ if (!lFileToCopy.exists()) {
+ copyFromPackage(context, ressourceId, lFileToCopy.getName());
+ }
+ }
+
+ public static void copyFromPackage(Context context, int ressourceId, String target) throws IOException {
+ FileOutputStream lOutputStream = context.openFileOutput (target, 0);
+ InputStream lInputStream = context.getResources().openRawResource(ressourceId);
+ int readByte;
+ byte[] buff = new byte[8048];
+ while (( readByte = lInputStream.read(buff)) != -1) {
+ lOutputStream.write(buff,0, readByte);
+ }
+ lOutputStream.flush();
+ lOutputStream.close();
+ lInputStream.close();
+ }
+}
diff --git a/sample/submodules b/sample/submodules
new file mode 120000
index 000000000..1bc410d91
--- /dev/null
+++ b/sample/submodules
@@ -0,0 +1 @@
+../submodules
\ No newline at end of file
diff --git a/src/org/linphone/AboutFragment.java b/src/org/linphone/AboutFragment.java
index 7a8130d8a..7a190cfa3 100644
--- a/src/org/linphone/AboutFragment.java
+++ b/src/org/linphone/AboutFragment.java
@@ -18,6 +18,7 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+import org.linphone.core.LinphoneCore;
import org.linphone.mediastream.Log;
import android.content.pm.PackageManager.NameNotFoundException;
@@ -34,15 +35,18 @@ import android.widget.TextView;
*/
public class AboutFragment extends Fragment implements OnClickListener {
private FragmentsAvailable about = FragmentsAvailable.ABOUT_INSTEAD_OF_CHAT;
+ View exitButton = null;
+ View sendLogButton = null;
+ View resetLogButton = null;
+
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if (getArguments() != null && getArguments().getSerializable("About") != null) {
about = (FragmentsAvailable) getArguments().getSerializable("About");
}
-
+
View view = inflater.inflate(R.layout.about, container, false);
-
+
TextView aboutText = (TextView) view.findViewById(R.id.AboutText);
try {
aboutText.setText(String.format(getString(R.string.about_text), getActivity().getPackageManager().getPackageInfo(getActivity().getPackageName(), 0).versionName));
@@ -50,31 +54,58 @@ public class AboutFragment extends Fragment implements OnClickListener {
Log.e(e, "cannot get version name");
}
- View issue = view.findViewById(R.id.exit);
- issue.setOnClickListener(this);
- issue.setVisibility(View.VISIBLE);
-
+ sendLogButton = view.findViewById(R.id.send_log);
+ sendLogButton.setOnClickListener(this);
+ sendLogButton.setVisibility(LinphonePreferences.instance().isDebugEnabled() ? View.VISIBLE : View.GONE);
+
+ resetLogButton = view.findViewById(R.id.reset_log);
+ resetLogButton.setOnClickListener(this);
+ resetLogButton.setVisibility(LinphonePreferences.instance().isDebugEnabled() ? View.VISIBLE : View.GONE);
+
+ exitButton = view.findViewById(R.id.exit);
+ exitButton.setOnClickListener(this);
+ exitButton.setVisibility(View.VISIBLE);
+
return view;
}
-
+
@Override
public void onResume() {
super.onResume();
-
+
if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().selectMenu(about);
+
+ if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) {
+ LinphoneActivity.instance().hideStatusBar();
+ }
}
}
+
@Override
public void onClick(View v) {
if (LinphoneActivity.isInstanciated()) {
-
- if (getResources().getBoolean(R.bool.enable_log_collect)) {
- LinphoneUtils.collectLogs(getString(R.string.app_name), getString(R.string.about_bugreport_email));
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (v == sendLogButton) {
+ //LinphoneUtils.collectLogs(LinphoneActivity.instance(), getString(R.string.about_bugreport_email));
+ if (lc != null) {
+ lc.uploadLogCollection();
+ }
+ } else if (v == resetLogButton) {
+ if (lc != null) {
+ lc.resetLogCollection();
+ }
} else {
LinphoneActivity.instance().exit();
}
}
}
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ }
+
+
}
diff --git a/src/org/linphone/AcceptCallUpdateDialogFragment.java b/src/org/linphone/AcceptCallUpdateDialogFragment.java
new file mode 100644
index 000000000..52d2d1e5c
--- /dev/null
+++ b/src/org/linphone/AcceptCallUpdateDialogFragment.java
@@ -0,0 +1,80 @@
+/*
+AcceptCallUpdateDialogFragment.java
+Copyright (C) 2014 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone;
+
+import org.linphone.mediastream.Log;
+
+import android.annotation.SuppressLint;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.v4.app.DialogFragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.View.OnClickListener;
+import android.widget.Button;
+
+
+
+@SuppressLint("ValidFragment")
+public class AcceptCallUpdateDialogFragment extends DialogFragment {
+
+ public AcceptCallUpdateDialogFragment() {
+ // Empty constructor required for DialogFragment
+ }
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.accept_call_update_dialog, container);
+
+ getDialog().setTitle(R.string.call_update_title);
+
+ Button yes = (Button) view.findViewById(R.id.yes);
+ yes.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (InCallActivity.isInstanciated()) {
+ Log.d("Call Update Accepted");
+ InCallActivity.instance().acceptCallUpdate(true);
+ }
+ dismiss();
+ }
+ });
+
+ Button no = (Button) view.findViewById(R.id.no);
+ no.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (InCallActivity.isInstanciated()) {
+ Log.d("Call Update Denied");
+ InCallActivity.instance().acceptCallUpdate(false);
+ }
+ dismiss();
+ }
+ });
+
+ return view;
+ }
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ super.onCancel(dialog);
+ InCallActivity.instance().acceptCallUpdate(false);
+ }
+}
\ No newline at end of file
diff --git a/src/org/linphone/AccountPreferencesFragment.java b/src/org/linphone/AccountPreferencesFragment.java
index 76c38cc53..bf2ea3bfe 100644
--- a/src/org/linphone/AccountPreferencesFragment.java
+++ b/src/org/linphone/AccountPreferencesFragment.java
@@ -18,12 +18,17 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-import org.linphone.compatibility.Compatibility;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.linphone.LinphonePreferences.AccountBuilder;
+import org.linphone.core.LinphoneCoreException;
import org.linphone.ui.PreferencesListFragment;
-import android.content.SharedPreferences;
import android.os.Bundle;
+import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
+import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.Preference.OnPreferenceChangeListener;
import android.preference.Preference.OnPreferenceClickListener;
@@ -36,10 +41,15 @@ import android.text.InputType;
*/
public class AccountPreferencesFragment extends PreferencesListFragment {
private int n;
- private String key;
+ private boolean isNewAccount=false;
+ private LinphonePreferences mPrefs;
+ private EditTextPreference mProxyPreference;
+ private ListPreference mTransportPreference;
+ private AccountBuilder builder;
public AccountPreferencesFragment() {
super(R.xml.account_preferences);
+ mPrefs = LinphonePreferences.instance();
}
public void onCreate(Bundle savedInstanceState)
@@ -48,146 +58,446 @@ public class AccountPreferencesFragment extends PreferencesListFragment {
PreferenceScreen screen = getPreferenceScreen();
n = getArguments().getInt("Account", 0);
- key = getAccountNumber(n);
- manageAccountPreferencesFields(screen);
+ if(n == mPrefs.getAccountCount()){
+ isNewAccount=true;
+ builder = new AccountBuilder(LinphoneManager.getLc());
+ initAccountPreferencesFields(screen);
+ } else {
+ manageAccountPreferencesFields(screen);
+ }
+
}
- OnPreferenceChangeListener preferenceChangedListener = new OnPreferenceChangeListener() {
+ public static boolean isEditTextEmpty(String s){
+ return s.equals(""); // really empty.
+ }
+
+ OnPreferenceChangeListener usernameChangedListener = new OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if(isEditTextEmpty(newValue.toString())) return false;
+ if (isNewAccount) {
+ builder.setUsername(newValue.toString());
+ } else {
+ mPrefs.setAccountUsername(n, newValue.toString());
+ }
preference.setSummary(newValue.toString());
return true;
}
};
+ OnPreferenceChangeListener useridChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (isNewAccount) {
+ builder.setUserId(newValue.toString());
+ } else {
+ mPrefs.setAccountUserId(n, newValue.toString());
+ }
+ preference.setSummary(newValue.toString());
+ return true;
+ }
+ };
+ OnPreferenceChangeListener passwordChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if(isEditTextEmpty(newValue.toString())) return false;
+ if (isNewAccount) {
+ builder.setPassword(newValue.toString());
+ } else {
+ mPrefs.setAccountPassword(n, newValue.toString());
+ }
+ return true;
+ }
+ };
+ OnPreferenceChangeListener domainChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if(isEditTextEmpty(newValue.toString())) return false;
+ if (isNewAccount) {
+ builder.setDomain(newValue.toString());
+ } else {
+ mPrefs.setAccountDomain(n, newValue.toString());
+ }
+ preference.setSummary(newValue.toString());
+ return true;
+ }
+ };
+ OnPreferenceChangeListener displayNameChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (isNewAccount) {
+ builder.setDisplayName(newValue.toString());
+ } else {
+ mPrefs.setAccountDisplayName(n, newValue.toString());
+ }
+ preference.setSummary(newValue.toString());
+ return true;
+ }
+ };
+ OnPreferenceChangeListener proxyChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String value = newValue.toString();
+ if (isNewAccount) {
+ builder.setProxy(newValue.toString());
+ preference.setSummary(newValue.toString());
+ } else {
+ mPrefs.setAccountProxy(n, value);
+ preference.setSummary(mPrefs.getAccountProxy(n));
+
+ if (mTransportPreference != null) {
+ mTransportPreference.setSummary(mPrefs.getAccountTransportString(n));
+ mTransportPreference.setValue(mPrefs.getAccountTransportKey(n));
+ }
+ }
+ return true;
+ }
+ };
+ OnPreferenceChangeListener outboundProxyChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (isNewAccount) {
+ builder.setOutboundProxyEnabled((Boolean) newValue);
+ } else {
+ mPrefs.setAccountOutboundProxyEnabled(n, (Boolean) newValue);
+ }
+ return true;
+ }
+ };
+ OnPreferenceChangeListener expiresChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if (isNewAccount) {
+ builder.setExpires(newValue.toString());
+ } else {
+ mPrefs.setExpires(n, newValue.toString());
+ }
+ preference.setSummary(newValue.toString());
+ return true;
+ }
+ };
+ OnPreferenceChangeListener prefixChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String value = newValue.toString();
+ preference.setSummary(value);
+ if (isNewAccount) {
+ //TODO acocunt builder ste prefix
+ } else {
+ mPrefs.setPrefix(n, value);
+ }
+ return true;
+ }
+ };
+ OnPreferenceChangeListener avpfChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean value = (Boolean) newValue;
+ if (isNewAccount) {
+ builder.setAvpfEnabled(value);
+ } else {
+ mPrefs.enableAvpf(n, value);
+ }
+ return true;
+ }
+ };
+ OnPreferenceChangeListener avpfRRIntervalChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String value = newValue.toString();
+ try {
+ int intValue = Integer.parseInt(value);
+ if ((intValue < 1) || (intValue > 5)) {
+ return false;
+ }
+ } catch (NumberFormatException nfe) { }
+ if (isNewAccount) {
+ //TODO
+ } else {
+ mPrefs.setAvpfRRInterval(n, value);
+ }
+ preference.setSummary(value);
+ return true;
+ }
+ };
+ OnPreferenceChangeListener escapeChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean value = (Boolean) newValue;
+ if (isNewAccount) {
+ //TODO
+ } else {
+ mPrefs.setReplacePlusByZeroZero(n, value);
+ }
+ return true;
+ }
+ };
+ OnPreferenceChangeListener disableChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean value = (Boolean) newValue;
+ if (isNewAccount) {
+ builder.setEnabled(!value);
+ } else {
+ mPrefs.setAccountEnabled(n, !value);
+ }
+ return true;
+ }
+ };
+ OnPreferenceChangeListener transportChangedListener = new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String key = newValue.toString();
+ if (isNewAccount) {
+ //TODO
+ //builder.setTransport(transport);
+ } else {
+ mPrefs.setAccountTransport(n, key);
+ preference.setSummary(mPrefs.getAccountTransportString(n));
+ preference.setDefaultValue(mPrefs.getAccountTransportKey(n));
+ if (mProxyPreference != null) {
+ String newProxy = mPrefs.getAccountProxy(n);
+ mProxyPreference.setSummary(newProxy);
+ mProxyPreference.setText(newProxy);
+ }
+ }
+ return true;
+ }
+ };
- private void manageAccountPreferencesFields(PreferenceScreen parent) {
- final SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
+ private void initAccountPreferencesFields(PreferenceScreen parent) {
+ boolean isDefaultAccount = mPrefs.getDefaultAccountIndex() == n;
- PreferenceCategory account = (PreferenceCategory) getPreferenceScreen().getPreference(0);
+ PreferenceCategory account = (PreferenceCategory) getPreferenceScreen().findPreference(getString(R.string.pref_sipaccount_key));
EditTextPreference username = (EditTextPreference) account.getPreference(0);
- username.setText(prefs.getString(getString(R.string.pref_username_key) + key, ""));
username.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
- username.setKey(getString(R.string.pref_username_key) + key);
- username.setOnPreferenceChangeListener(preferenceChangedListener);
- username.setSummary(username.getText());
+ username.setOnPreferenceChangeListener(usernameChangedListener);
- EditTextPreference password = (EditTextPreference) account.getPreference(1);
- password.setText(prefs.getString(getString(R.string.pref_passwd_key) + key, ""));
- password.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
- password.setKey(getString(R.string.pref_passwd_key) + key);
+ EditTextPreference userid = (EditTextPreference) account.getPreference(1);
+ userid.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ userid.setOnPreferenceChangeListener(useridChangedListener);
- EditTextPreference domain = (EditTextPreference) account.getPreference(2);
- domain.setText(prefs.getString(getString(R.string.pref_domain_key) + key, ""));
+ EditTextPreference password = (EditTextPreference) account.getPreference(2);
+ password.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ password.setOnPreferenceChangeListener(passwordChangedListener);
+
+ EditTextPreference domain = (EditTextPreference) account.getPreference(3);
domain.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
- domain.setKey(getString(R.string.pref_domain_key) + key);
- domain.setOnPreferenceChangeListener(preferenceChangedListener);
- domain.setSummary(domain.getText());
-
- PreferenceCategory advanced = (PreferenceCategory) getPreferenceScreen().getPreference(1);
- EditTextPreference proxy = (EditTextPreference) advanced.getPreference(0);
- proxy.setText(prefs.getString(getString(R.string.pref_proxy_key) + key, ""));
- proxy.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
- proxy.setKey(getString(R.string.pref_proxy_key) + key);
- proxy.setOnPreferenceChangeListener(preferenceChangedListener);
- proxy.setSummary("".equals(proxy.getText()) || (proxy.getText() == null) ? getString(R.string.pref_help_proxy) : proxy.getText());
+ domain.setOnPreferenceChangeListener(domainChangedListener);
- Preference outboundProxy = advanced.getPreference(1);
- Compatibility.setPreferenceChecked(outboundProxy, prefs.getBoolean(getString(R.string.pref_enable_outbound_proxy_key) + key, false));
- outboundProxy.setKey(getString(R.string.pref_enable_outbound_proxy_key) + key);
-
- final Preference disable = advanced.getPreference(2);
+ EditTextPreference displayName = (EditTextPreference) account.getPreference(4);
+ displayName.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PERSON_NAME);
+ displayName.setOnPreferenceChangeListener(displayNameChangedListener);
+
+ PreferenceCategory advanced = (PreferenceCategory) getPreferenceScreen().findPreference(getString(R.string.pref_advanced_key));
+ mTransportPreference = (ListPreference) advanced.getPreference(0);
+ initializeTransportPreference(mTransportPreference);
+ mTransportPreference.setOnPreferenceChangeListener(transportChangedListener);
+
+ mProxyPreference = (EditTextPreference) advanced.getPreference(1);
+ mProxyPreference.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ mProxyPreference.setOnPreferenceChangeListener(proxyChangedListener);
+
+ CheckBoxPreference outboundProxy = (CheckBoxPreference) advanced.getPreference(2);
+ outboundProxy.setOnPreferenceChangeListener(outboundProxyChangedListener);
+
+ EditTextPreference expires = (EditTextPreference) advanced.getPreference(3);
+ expires.setOnPreferenceChangeListener(expiresChangedListener);
+
+ EditTextPreference prefix = (EditTextPreference) advanced.getPreference(4);
+ prefix.setOnPreferenceChangeListener(prefixChangedListener);
+
+ CheckBoxPreference avpf = (CheckBoxPreference) advanced.getPreference(5);
+ avpf.setOnPreferenceChangeListener(avpfChangedListener);
+
+ EditTextPreference avpfRRInterval = (EditTextPreference) advanced.getPreference(6);
+ avpfRRInterval.setOnPreferenceChangeListener(avpfRRIntervalChangedListener);
+
+ CheckBoxPreference escape = (CheckBoxPreference) advanced.getPreference(7);
+ escape.setOnPreferenceChangeListener(escapeChangedListener);
+
+ PreferenceCategory manage = (PreferenceCategory) getPreferenceScreen().findPreference(getString(R.string.pref_manage_key));
+ final CheckBoxPreference disable = (CheckBoxPreference) manage.getPreference(0);
disable.setEnabled(true);
- Compatibility.setPreferenceChecked(disable, prefs.getBoolean(getString(R.string.pref_disable_account_key) + key, false));
- disable.setKey(getString(R.string.pref_disable_account_key) + key);
-
- final Preference delete = advanced.getPreference(4);
- delete.setEnabled(true);
- delete.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- public boolean onPreferenceClick(Preference preference) {
- int nbAccounts = prefs.getInt(getString(R.string.pref_extra_accounts), 1);
- SharedPreferences.Editor editor = prefs.edit();
-
- for (int i = n; i < nbAccounts - 1; i++) {
- editor.putString(getString(R.string.pref_username_key) + getAccountNumber(i), prefs.getString(getString(R.string.pref_username_key) + getAccountNumber(i+1), null));
- editor.putString(getString(R.string.pref_passwd_key) + getAccountNumber(i), prefs.getString(getString(R.string.pref_passwd_key) + getAccountNumber(i+1), null));
- editor.putString(getString(R.string.pref_domain_key) + getAccountNumber(i), prefs.getString(getString(R.string.pref_domain_key) + getAccountNumber(i+1), null));
- editor.putString(getString(R.string.pref_proxy_key) + getAccountNumber(i), prefs.getString(getString(R.string.pref_proxy_key) + getAccountNumber(i+1), null));
- editor.putBoolean(getString(R.string.pref_enable_outbound_proxy_key) + getAccountNumber(i), prefs.getBoolean(getString(R.string.pref_enable_outbound_proxy_key) + getAccountNumber(i+1), false));
- editor.putBoolean(getString(R.string.pref_disable_account_key) + getAccountNumber(i), prefs.getBoolean(getString(R.string.pref_disable_account_key) + getAccountNumber(i+1), false));
- }
-
- if (n != 0) {
- int lastAccount = nbAccounts - 1;
- editor.putString(getString(R.string.pref_username_key) + getAccountNumber(lastAccount), null);
- editor.putString(getString(R.string.pref_passwd_key) + getAccountNumber(lastAccount), null);
- editor.putString(getString(R.string.pref_domain_key) + getAccountNumber(lastAccount), null);
- editor.putString(getString(R.string.pref_proxy_key) + getAccountNumber(lastAccount), null);
- editor.putBoolean(getString(R.string.pref_enable_outbound_proxy_key) + getAccountNumber(lastAccount), false);
- editor.putBoolean(getString(R.string.pref_disable_account_key) + getAccountNumber(lastAccount), false);
-
- int defaultAccount = prefs.getInt(getString(R.string.pref_default_account_key), 0);
- if (defaultAccount > n) {
- editor.putInt(getString(R.string.pref_default_account_key), defaultAccount - 1);
- }
- editor.putInt(getString(R.string.pref_extra_accounts), nbAccounts - 1);
- } else if (n == 0 && nbAccounts <= 1) {
- editor.putString(getString(R.string.pref_username_key), "");
- editor.putString(getString(R.string.pref_passwd_key), "");
- editor.putString(getString(R.string.pref_domain_key), "");
- } else {
- editor.putInt(getString(R.string.pref_extra_accounts), nbAccounts - 1);
- }
-
- editor.commit();
-
- LinphoneActivity.instance().displaySettings();
-
- return true;
- }
- });
+ disable.setOnPreferenceChangeListener(disableChangedListener);
- Preference mainAccount = advanced.getPreference(3);
- Compatibility.setPreferenceChecked(mainAccount, prefs.getInt(getString(R.string.pref_default_account_key), 0) == n);
- mainAccount.setEnabled(!Compatibility.isPreferenceChecked(mainAccount));
+ CheckBoxPreference mainAccount = (CheckBoxPreference) manage.getPreference(1);
+ mainAccount.setChecked(isDefaultAccount);
+ mainAccount.setEnabled(!mainAccount.isChecked());
mainAccount.setOnPreferenceClickListener(new OnPreferenceClickListener()
{
public boolean onPreferenceClick(Preference preference) {
-
- SharedPreferences.Editor editor = prefs.edit();
- editor.putInt(getString(R.string.pref_default_account_key), n);
- editor.commit();
+ mPrefs.setDefaultAccount(n);
disable.setEnabled(false);
- Compatibility.setPreferenceChecked(disable, false);
+ disable.setChecked(false);
preference.setEnabled(false);
return true;
}
});
+
+ final Preference delete = manage.getPreference(2);
+ delete.setEnabled(true);
+ delete.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ public boolean onPreferenceClick(Preference preference) {
+ mPrefs.deleteAccount(n);
+ LinphoneActivity.instance().displaySettings();
+ return true;
+ }
+ });
}
- private String getAccountNumber(int n) {
- if (n > 0)
- return Integer.toString(n);
- else
- return "";
+ private void manageAccountPreferencesFields(PreferenceScreen parent) {
+ boolean isDefaultAccount = mPrefs.getDefaultAccountIndex() == n;
+
+ PreferenceCategory account = (PreferenceCategory) getPreferenceScreen().findPreference(getString(R.string.pref_sipaccount_key));
+ EditTextPreference username = (EditTextPreference) account.getPreference(0);
+ username.setText(mPrefs.getAccountUsername(n));
+ username.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ username.setOnPreferenceChangeListener(usernameChangedListener);
+ username.setSummary(username.getText());
+
+ EditTextPreference userid = (EditTextPreference) account.getPreference(1);
+ userid.setText(mPrefs.getAccountUserId(n));
+ userid.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ userid.setOnPreferenceChangeListener(useridChangedListener);
+ userid.setSummary(userid.getText());
+
+ EditTextPreference password = (EditTextPreference) account.getPreference(2);
+ password.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
+ password.setText(mPrefs.getAccountPassword(n));
+ password.setOnPreferenceChangeListener(passwordChangedListener);
+
+ EditTextPreference domain = (EditTextPreference) account.getPreference(3);
+ domain.setText(mPrefs.getAccountDomain(n));
+ domain.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ domain.setOnPreferenceChangeListener(domainChangedListener);
+ domain.setSummary(domain.getText());
+
+ EditTextPreference displayName = (EditTextPreference) account.getPreference(4);
+ displayName.setText(mPrefs.getAccountDisplayName(n));
+ displayName.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PERSON_NAME);
+ displayName.setOnPreferenceChangeListener(displayNameChangedListener);
+ displayName.setSummary(displayName.getText());
+
+ PreferenceCategory advanced = (PreferenceCategory) getPreferenceScreen().findPreference(getString(R.string.pref_advanced_key));
+ mTransportPreference = (ListPreference) advanced.getPreference(0);
+ initializeTransportPreference(mTransportPreference);
+ mTransportPreference.setOnPreferenceChangeListener(transportChangedListener);
+ mTransportPreference.setSummary(mPrefs.getAccountTransportString(n));
+
+ mProxyPreference = (EditTextPreference) advanced.getPreference(1);
+ mProxyPreference.setText(mPrefs.getAccountProxy(n));
+ mProxyPreference.getEditText().setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
+ mProxyPreference.setOnPreferenceChangeListener(proxyChangedListener);
+ mProxyPreference.setSummary("".equals(mProxyPreference.getText()) || (mProxyPreference.getText() == null) ? getString(R.string.pref_help_proxy) : mProxyPreference.getText());
+
+ CheckBoxPreference outboundProxy = (CheckBoxPreference) advanced.getPreference(2);
+ outboundProxy.setChecked(mPrefs.isAccountOutboundProxySet(n));
+ outboundProxy.setOnPreferenceChangeListener(outboundProxyChangedListener);
+
+ EditTextPreference expires = (EditTextPreference) advanced.getPreference(3);
+ expires.setText(mPrefs.getExpires(n));
+ expires.setOnPreferenceChangeListener(expiresChangedListener);
+ expires.setSummary(mPrefs.getExpires(n));
+
+ EditTextPreference prefix = (EditTextPreference) advanced.getPreference(4);
+ String prefixValue = mPrefs.getPrefix(n);
+ prefix.setSummary(prefixValue);
+ prefix.setText(prefixValue);
+ prefix.setOnPreferenceChangeListener(prefixChangedListener);
+
+ CheckBoxPreference avpf = (CheckBoxPreference) advanced.getPreference(5);
+ avpf.setChecked(mPrefs.avpfEnabled(n));
+ avpf.setOnPreferenceChangeListener(avpfChangedListener);
+
+ EditTextPreference avpfRRInterval = (EditTextPreference) advanced.getPreference(6);
+ avpfRRInterval.setText(mPrefs.getAvpfRRInterval(n));
+ avpfRRInterval.setOnPreferenceChangeListener(avpfRRIntervalChangedListener);
+ avpfRRInterval.setSummary(mPrefs.getAvpfRRInterval(n));
+
+ CheckBoxPreference escape = (CheckBoxPreference) advanced.getPreference(7);
+ escape.setChecked(mPrefs.getReplacePlusByZeroZero(n));
+ escape.setOnPreferenceChangeListener(escapeChangedListener);
+
+ PreferenceCategory manage = (PreferenceCategory) getPreferenceScreen().findPreference(getString(R.string.pref_manage_key));
+ final CheckBoxPreference disable = (CheckBoxPreference) manage.getPreference(0);
+ disable.setEnabled(true);
+ disable.setChecked(!mPrefs.isAccountEnabled(n));
+ disable.setOnPreferenceChangeListener(disableChangedListener);
+
+ CheckBoxPreference mainAccount = (CheckBoxPreference) manage.getPreference(1);
+ mainAccount.setChecked(isDefaultAccount);
+ mainAccount.setEnabled(!mainAccount.isChecked());
+ mainAccount.setOnPreferenceClickListener(new OnPreferenceClickListener()
+ {
+ public boolean onPreferenceClick(Preference preference) {
+ mPrefs.setDefaultAccount(n);
+ disable.setEnabled(false);
+ disable.setChecked(false);
+ preference.setEnabled(false);
+ return true;
+ }
+ });
+
+ final Preference delete = manage.getPreference(2);
+ delete.setEnabled(true);
+ delete.setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ public boolean onPreferenceClick(Preference preference) {
+ mPrefs.deleteAccount(n);
+ LinphoneActivity.instance().displaySettings();
+ return true;
+ }
+ });
+ }
+
+ private void initializeTransportPreference(ListPreference pref) {
+ List entries = new ArrayList();
+ List values = new ArrayList();
+ entries.add(getString(R.string.pref_transport_udp));
+ values.add(getString(R.string.pref_transport_udp_key));
+ entries.add(getString(R.string.pref_transport_tcp));
+ values.add(getString(R.string.pref_transport_tcp_key));
+
+ if (!getResources().getBoolean(R.bool.disable_all_security_features_for_markets)) {
+ entries.add(getString(R.string.pref_transport_tls));
+ values.add(getString(R.string.pref_transport_tls_key));
+ }
+ setListPreferenceValues(pref, entries, values);
+
+ if (! isNewAccount) {
+ pref.setSummary(mPrefs.getAccountTransportString(n));
+ pref.setDefaultValue(mPrefs.getAccountTransportKey(n));
+ pref.setValueIndex(entries.indexOf(mPrefs.getAccountTransportString(n)));
+ } else {
+
+ pref.setSummary(getString(R.string.pref_transport_udp));
+ pref.setDefaultValue(getString(R.string.pref_transport_udp));
+ pref.setValueIndex(entries.indexOf(getString(R.string.pref_transport_udp)));
+ }
+ }
+
+ private static void setListPreferenceValues(ListPreference pref, List entries, List values) {
+ CharSequence[] contents = new CharSequence[entries.size()];
+ entries.toArray(contents);
+ pref.setEntries(contents);
+ contents = new CharSequence[values.size()];
+ values.toArray(contents);
+ pref.setEntryValues(contents);
}
@Override
public void onPause() {
- super.onPause();
-
- SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
- int n = prefs.getInt(getString(R.string.pref_extra_accounts), 1);
- String keyUsername = getString(R.string.pref_username_key) + getAccountNumber(n-1);
-
- if (prefs.getString(keyUsername, "").equals("")) {
- //If not, we suppress it to not display a blank field
- SharedPreferences.Editor editor = prefs.edit();
- editor.putInt(getString(R.string.pref_extra_accounts), n-1);
- editor.commit();
- }
-
+ super.onPause();
if (LinphoneActivity.isInstanciated()) {
- LinphoneActivity.instance().applyConfigChangesIfNeeded();
+ try {
+ if(isNewAccount){
+ builder.saveNewAccount();
+ }
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+
+ LinphoneManager.getLc().refreshRegisters();
}
}
}
diff --git a/src/org/linphone/BandwidthManager.java b/src/org/linphone/BandwidthManager.java
index 686a4314a..a1b6956a2 100644
--- a/src/org/linphone/BandwidthManager.java
+++ b/src/org/linphone/BandwidthManager.java
@@ -27,7 +27,6 @@ public class BandwidthManager {
public static final int LOW_RESOLUTION = 1;
public static final int LOW_BANDWIDTH = 2;
- private static final int[][] bandwidthes = {{256,256}, {128,128}, {80,80}};
private static BandwidthManager instance;
private int currentProfile = HIGH_RESOLUTION;
@@ -46,34 +45,6 @@ public class BandwidthManager {
// FIXME initially get those values
}
- private boolean userRestriction;
- public boolean isUserRestriction() {return userRestriction;}
- public void setUserRestriction(boolean limit) {
- userRestriction = limit;
- computeNewProfile();
- }
-
-
- private void computeNewProfile() {
- int newProfile = userRestriction ? LOW_RESOLUTION : HIGH_RESOLUTION;
- if (newProfile != currentProfile) {
- currentProfile = newProfile;
- onProfileChanged(currentProfile);
- }
- }
-
- private void onProfileChanged(int newProfile) {
- LinphoneCore lc = LinphoneManager.getLc();
- lc.setUploadBandwidth(bandwidthes[newProfile][0]);
- lc.setDownloadBandwidth(bandwidthes[newProfile][1]);
-
- if (lc.isIncall()) {
- CallManager.getInstance().reinvite();
- } else {
- updateWithProfileSettings(lc, null);
- }
- }
-
public void updateWithProfileSettings(LinphoneCore lc, LinphoneCallParams callParams) {
if (callParams != null) { // in call
diff --git a/src/org/linphone/BluetoothManager.java b/src/org/linphone/BluetoothManager.java
index 3d3d6badf..d4ad16cfe 100644
--- a/src/org/linphone/BluetoothManager.java
+++ b/src/org/linphone/BluetoothManager.java
@@ -17,13 +17,21 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+import java.util.List;
+
+import org.linphone.compatibility.Compatibility;
import org.linphone.mediastream.Log;
import android.annotation.TargetApi;
+import android.bluetooth.BluetoothAdapter;
+import android.bluetooth.BluetoothAssignedNumbers;
import android.bluetooth.BluetoothDevice;
+import android.bluetooth.BluetoothHeadset;
+import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.media.AudioManager;
import android.os.Build;
@@ -32,51 +40,282 @@ import android.os.Build;
*/
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public class BluetoothManager extends BroadcastReceiver {
- @SuppressWarnings("deprecation")
+ public int PLANTRONICS_BUTTON_PRESS = 1;
+ public int PLANTRONICS_BUTTON_LONG_PRESS = 2;
+ public int PLANTRONICS_BUTTON_DOUBLE_PRESS = 5;
+
+ public int PLANTRONICS_BUTTON_CALL = 2;
+ public int PLANTRONICS_BUTTON_MUTE = 3;
+
+ private static BluetoothManager instance;
+
+ private Context mContext;
+ private AudioManager mAudioManager;
+ private BluetoothAdapter mBluetoothAdapter;
+ private BluetoothHeadset mBluetoothHeadset;
+ private BluetoothDevice mBluetoothDevice;
+ private BluetoothProfile.ServiceListener mProfileListener;
+ private boolean isBluetoothConnected;
+ private boolean isScoConnected;
+
+ public static BluetoothManager getInstance() {
+ if (instance == null) {
+ instance = new BluetoothManager();
+ }
+ return instance;
+ }
+
+ public BluetoothManager() {
+ isBluetoothConnected = false;
+ if (!ensureInit()) {
+ Log.w("BluetoothManager tried to init but LinphoneService not ready yet...");
+ }
+ instance = this;
+ }
+
+ public void initBluetooth() {
+ if (!ensureInit()) {
+ Log.w("BluetoothManager tried to init bluetooth but LinphoneService not ready yet...");
+ return;
+ }
+
+ IntentFilter filter = new IntentFilter();
+ filter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "." + BluetoothAssignedNumbers.PLANTRONICS);
+ filter.addAction(Compatibility.getAudioManagerEventForBluetoothConnectionStateChangedEvent());
+ filter.addAction(BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED);
+ filter.addAction(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT);
+ mContext.registerReceiver(this, filter);
+ Log.d("Bluetooth receiver started");
+
+ startBluetooth();
+ }
+
+ private void startBluetooth() {
+ if (isBluetoothConnected) {
+ Log.e("Bluetooth already started");
+ return;
+ }
+
+ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+
+ if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled()) {
+ if (mProfileListener != null) {
+ Log.w("Bluetooth headset profile was already opened, let's close it");
+ mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
+ }
+
+ mProfileListener = new BluetoothProfile.ServiceListener() {
+ public void onServiceConnected(int profile, BluetoothProfile proxy) {
+ if (profile == BluetoothProfile.HEADSET) {
+ Log.d("Bluetooth headset connected");
+ mBluetoothHeadset = (BluetoothHeadset) proxy;
+ isBluetoothConnected = true;
+ }
+ }
+ public void onServiceDisconnected(int profile) {
+ if (profile == BluetoothProfile.HEADSET) {
+ mBluetoothHeadset = null;
+ isBluetoothConnected = false;
+ Log.d("Bluetooth headset disconnected");
+ LinphoneManager.getInstance().routeAudioToReceiver();
+ }
+ }
+ };
+ boolean success = mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEADSET);
+ if (!success) {
+ Log.e("Bluetooth getProfileProxy failed !");
+ }
+ } else {
+ Log.w("Bluetooth interface disabled on device");
+ }
+ }
+
+ private boolean ensureInit() {
+ if (mBluetoothAdapter == null) {
+ mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
+ }
+ if (mContext == null) {
+ if (LinphoneService.isReady()) {
+ mContext = LinphoneService.instance().getApplicationContext();
+ } else {
+ return false;
+ }
+ }
+ if (mContext != null && mAudioManager == null) {
+ mAudioManager = ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE));
+ }
+ return true;
+ }
+
+ public boolean routeAudioToBluetooth() {
+ ensureInit();
+
+ if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled() && mAudioManager != null && mAudioManager.isBluetoothScoAvailableOffCall()) {
+ if (isBluetoothHeadsetAvailable()) {
+ if (mAudioManager != null && !mAudioManager.isBluetoothScoOn()) {
+ Log.d("Bluetooth sco off, let's start it");
+ mAudioManager.setBluetoothScoOn(true);
+ mAudioManager.startBluetoothSco();
+ }
+ } else {
+ return false;
+ }
+
+ // Hack to ensure bluetooth sco is really running
+ boolean ok = isUsingBluetoothAudioRoute();
+ int retries = 0;
+ while (!ok && retries < 5) {
+ retries++;
+
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {}
+
+ if (mAudioManager != null) {
+ mAudioManager.setBluetoothScoOn(true);
+ mAudioManager.startBluetoothSco();
+ }
+
+ ok = isUsingBluetoothAudioRoute();
+ }
+ if (ok) {
+ if (retries > 0) {
+ Log.d("Bluetooth route ok after " + retries + " retries");
+ } else {
+ Log.d("Bluetooth route ok");
+ }
+ } else {
+ Log.d("Bluetooth still not ok...");
+ }
+
+ return ok;
+ }
+
+ return false;
+ }
+
+ public boolean isUsingBluetoothAudioRoute() {
+ return mBluetoothHeadset != null && mBluetoothHeadset.isAudioConnected(mBluetoothDevice) && isScoConnected;
+ }
+
+ public boolean isBluetoothHeadsetAvailable() {
+ ensureInit();
+ if (mBluetoothAdapter != null && mBluetoothAdapter.isEnabled() && mAudioManager != null && mAudioManager.isBluetoothScoAvailableOffCall()) {
+ boolean isHeadsetConnected = false;
+ if (mBluetoothHeadset != null) {
+ List devices = mBluetoothHeadset.getConnectedDevices();
+ mBluetoothDevice = null;
+ for (final BluetoothDevice dev : devices) {
+ if (mBluetoothHeadset.getConnectionState(dev) == BluetoothHeadset.STATE_CONNECTED) {
+ mBluetoothDevice = dev;
+ isHeadsetConnected = true;
+ break;
+ }
+ }
+ Log.d(isHeadsetConnected ? "Headset found, bluetooth audio route available" : "No headset found, bluetooth audio route unavailable");
+ }
+ return isHeadsetConnected;
+ }
+
+ return false;
+ }
+
+ public void disableBluetoothSCO() {
+ if (mAudioManager != null && mAudioManager.isBluetoothScoOn()) {
+ mAudioManager.stopBluetoothSco();
+ mAudioManager.setBluetoothScoOn(false);
+
+ // Hack to ensure bluetooth sco is really stopped
+ int retries = 0;
+ while (isScoConnected && retries < 10) {
+ retries++;
+
+ try {
+ Thread.sleep(200);
+ } catch (InterruptedException e) {}
+
+ mAudioManager.stopBluetoothSco();
+ mAudioManager.setBluetoothScoOn(false);
+ }
+ Log.w("Bluetooth sco disconnected!");
+ }
+ }
+
+ public void stopBluetooth() {
+ Log.w("Stopping bluetooth...");
+ isBluetoothConnected = false;
+
+ disableBluetoothSCO();
+
+ if (mBluetoothAdapter != null && mProfileListener != null && mBluetoothHeadset != null) {
+ mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
+ mProfileListener = null;
+ }
+ mBluetoothDevice = null;
+
+ Log.w("Bluetooth stopped!");
+
+ if (LinphoneManager.isInstanciated()) {
+ LinphoneManager.getInstance().routeAudioToReceiver();
+ }
+ }
+
+ public void destroy() {
+ try {
+ stopBluetooth();
+
+ try {
+ mContext.unregisterReceiver(this);
+ Log.d("Bluetooth receiver stopped");
+ } catch (Exception e) {}
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+
public void onReceive(Context context, Intent intent) {
if (!LinphoneManager.isInstanciated())
return;
String action = intent.getAction();
- LinphoneManager lm = LinphoneManager.getInstance();
-
- if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
- Log.e("Bluetooth Received Event" + " ACTION_ACL_DISCONNECTED" );
-
- if (lm != null) {
- lm.scoDisconnected();
- lm.routeAudioToReceiver();
- }
- }
- else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
- Log.e("Bluetooth Received Event" + " ACTION_ACL_CONNECTED" );
-
- if (lm != null) {
- lm.scoConnected();
- }
- }
- else if (AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED.equals(action)) {
+ if (Compatibility.getAudioManagerEventForBluetoothConnectionStateChangedEvent().equals(action)) {
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 0);
- Log.e("Bluetooth sco state changed : " + state);
- if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
- if (lm != null) {
- lm.scoConnected();
- }
+ if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
+ Log.d("Bluetooth sco state => connected");
+// LinphoneManager.getInstance().audioStateChanged(AudioState.BLUETOOTH);
+ isScoConnected = true;
} else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
- if (lm != null) {
- lm.scoDisconnected();
- lm.routeAudioToReceiver();
- }
+ Log.d("Bluetooth sco state => disconnected");
+// LinphoneManager.getInstance().audioStateChanged(AudioState.SPEAKER);
+ isScoConnected = false;
+ } else {
+ Log.d("Bluetooth sco state => " + state);
}
}
- //Using real value instead of constant because not available before sdk 11
- else if ("android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED".equals(action)) { //BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED
- int currentConnState = intent.getIntExtra("android.bluetooth.adapter.extra.CONNECTION_STATE", //BluetoothAdapter.EXTRA_CONNECTION_STATE
- 0); //BluetoothAdapter.STATE_DISCONNECTED
- Log.e("Bluetooth state changed: " + currentConnState);
- if (lm != null && currentConnState == 2) { //BluetoothAdapter.STATE_CONNECTED
- lm.startBluetooth();
- }
- }
+ else if (BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED.equals(action)) {
+ int state = intent.getIntExtra(BluetoothAdapter.EXTRA_CONNECTION_STATE, BluetoothAdapter.STATE_DISCONNECTED);
+ if (state == 0) {
+ Log.d("Bluetooth state => disconnected");
+ stopBluetooth();
+ } else if (state == 2) {
+ Log.d("Bluetooth state => connected");
+ startBluetooth();
+ } else {
+ Log.d("Bluetooth state => " + state);
+ }
+ }
+ else if (intent.getAction().equals(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)) {
+ String command = intent.getExtras().getString(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD);
+ //int type = intent.getExtras().getInt(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE);
+
+ Object[] args = (Object[]) intent.getExtras().get(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS);
+ String eventName = (String) args[0];
+
+ if (eventName.equals("BUTTON") && args.length >= 3) {
+ Integer buttonID = (Integer) args[1];
+ Integer mode = (Integer) args[2];
+ Log.d("Bluetooth event: " + command + " : " + eventName + ", id = " + buttonID + " (" + mode + ")");
+ }
+ }
}
}
diff --git a/src/org/linphone/BootReceiver.java b/src/org/linphone/BootReceiver.java
index 836e62d12..a911879bb 100644
--- a/src/org/linphone/BootReceiver.java
+++ b/src/org/linphone/BootReceiver.java
@@ -18,17 +18,21 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone;
+import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.core.LpConfig;
+
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
-import android.preference.PreferenceManager;
public class BootReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
- if (PreferenceManager.getDefaultSharedPreferences(context).getBoolean(context.getString(R.string.pref_autostart_key), false)) {
+ String path = context.getFilesDir().getAbsolutePath() + "/.linphonerc";
+ LpConfig lpConfig = LinphoneCoreFactory.instance().createLpConfig(path);
+ if (lpConfig.getBool("app", "auto_start", false)) {
Intent lLinphoneServiceIntent = new Intent(Intent.ACTION_MAIN);
lLinphoneServiceIntent.setClass(context, LinphoneService.class);
context.startService(lLinphoneServiceIntent);;
diff --git a/src/org/linphone/ChatActivity.java b/src/org/linphone/ChatActivity.java
new file mode 100644
index 000000000..5b0884679
--- /dev/null
+++ b/src/org/linphone/ChatActivity.java
@@ -0,0 +1,59 @@
+package org.linphone;
+/*
+ChatActivity.java
+Copyright (C) 2015 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentActivity;
+import android.support.v4.app.FragmentManager;
+
+/**
+ * @author Margaux Clerc
+ */
+public class ChatActivity extends FragmentActivity {
+ private static final String CHAT_FRAGMENT = "chatFragment";
+ private ChatFragment chatFragment;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.chat_activity);
+
+ Bundle extras = new Bundle();
+ extras.putString("SipUri", getIntent().getExtras().getString("SipUri"));
+ extras.putString("DisplayName", getIntent().getExtras().getString("DisplayName"));
+ extras.putString("PictureUri", getIntent().getExtras().getString("PictureUri"));
+ extras.putString("ThumbnailUri", getIntent().getExtras().getString("ThumbnailUri"));
+
+ ChatFragment fragment = new ChatFragment();
+ fragment.setArguments(extras);
+ getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, fragment, "ChatFragment").commit();
+
+ FragmentManager fm = getSupportFragmentManager();
+ chatFragment = (ChatFragment) fm.findFragmentByTag(CHAT_FRAGMENT);
+
+ // If the Fragment is non-null, then it is currently being
+ // retained across a configuration change.
+ if (chatFragment == null) {
+ chatFragment = new ChatFragment();
+ chatFragment.setArguments(extras);
+ fm.beginTransaction().add(R.id.fragmentContainer, chatFragment, CHAT_FRAGMENT).commit();
+ }
+ }
+}
+
diff --git a/src/org/linphone/ChatFragment.java b/src/org/linphone/ChatFragment.java
index 2e30b64c7..d5049aa98 100644
--- a/src/org/linphone/ChatFragment.java
+++ b/src/org/linphone/ChatFragment.java
@@ -1,7 +1,7 @@
package org.linphone;
/*
ChatFragment.java
-Copyright (C) 2012 Belledonne Communications, Grenoble, France
+Copyright (C) 2015 Belledonne Communications, Grenoble, France
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
@@ -17,409 +17,363 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
-import java.io.BufferedInputStream;
+
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
-import java.io.DataOutputStream;
import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.HttpURLConnection;
-import java.net.URL;
-import java.net.URLConnection;
+import android.graphics.Matrix;
import java.util.ArrayList;
-import java.util.HashMap;
import java.util.List;
-import org.apache.http.util.ByteArrayBuffer;
+
import org.linphone.compatibility.Compatibility;
import org.linphone.core.LinphoneAddress;
+import org.linphone.core.LinphoneBuffer;
import org.linphone.core.LinphoneChatMessage;
-import org.linphone.core.LinphoneChatMessage.State;
+import org.linphone.core.LinphoneChatMessage.LinphoneChatMessageListener;
import org.linphone.core.LinphoneChatRoom;
+import org.linphone.core.LinphoneContent;
import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneChatMessage.State;
+import org.linphone.core.LinphoneCoreException;
+import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.core.LinphoneCoreListenerBase;
+import org.linphone.mediastream.Log;
import org.linphone.ui.AvatarWithShadow;
import org.linphone.ui.BubbleChat;
-import org.linphone.ui.LinphoneScrollView;
-import org.linphone.ui.ScrollViewListener;
+
+import android.media.ExifInterface;
+import android.support.v4.content.CursorLoader;
import android.annotation.SuppressLint;
import android.app.Activity;
+import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
+import android.content.res.Configuration;
import android.database.Cursor;
import android.graphics.Bitmap;
-import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
-import android.graphics.Matrix;
import android.graphics.Rect;
-import android.media.ExifInterface;
import android.net.Uri;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
-import android.os.Handler;
import android.os.Parcelable;
-import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.support.v4.app.Fragment;
-import android.support.v4.content.CursorLoader;
import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.view.ContextMenu;
-import android.view.ContextMenu.ContextMenuInfo;
import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
-import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+import android.view.ViewTreeObserver;
+import android.view.WindowManager;
import android.view.inputmethod.InputMethodManager;
+import android.widget.BaseAdapter;
import android.widget.EditText;
import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
-/**
- * @author Sylvain Berfini
- */
-public class ChatFragment extends Fragment implements OnClickListener, LinphoneChatMessage.StateListener {
+public class ChatFragment extends Fragment implements OnClickListener, LinphoneChatMessageListener {
+ private static ChatFragment instance;
+
private static final int ADD_PHOTO = 1337;
private static final int MENU_DELETE_MESSAGE = 0;
- private static final int MENU_SAVE_PICTURE = 1;
- private static final int MENU_PICTURE_SMALL = 2;
- private static final int MENU_PICTURE_MEDIUM = 3;
- private static final int MENU_PICTURE_LARGE = 4;
- private static final int MENU_PICTURE_REAL = 5;
private static final int MENU_COPY_TEXT = 6;
- private static final int COMPRESSOR_QUALITY = 100;
- private static final int SIZE_SMALL = 500;
- private static final int SIZE_MEDIUM = 1000;
- private static final int SIZE_LARGE = 1500;
- private static final int MESSAGES_STEP = 20;
-
+ private static final int MENU_RESEND_MESSAGE = 7;
+ private static final int SIZE_MAX = 2048;
+
private LinphoneChatRoom chatRoom;
- private View view;
private String sipUri;
+ private String displayName;
+ private String pictureUri;
private EditText message;
private ImageView cancelUpload;
- private TextView sendImage, sendMessage, contactName;
+ private LinearLayout topBar;
+ private TextView sendImage, sendMessage, contactName, remoteComposing, back;
private AvatarWithShadow contactPicture;
- private RelativeLayout messagesLayout, uploadLayout, textLayout;
- private LinphoneScrollView messagesScrollView;
- private int previousMessageID;
- private Handler mHandler = new Handler();
- private BubbleChat lastSentMessageBubble;
- private HashMap latestImageMessages;
- private int messagesFilterLimit = 0;
- private List messagesList;
-
+ private RelativeLayout uploadLayout, textLayout;
+ private ListView messagesList;
+
private ProgressBar progressBar;
- private int bytesSent;
- private String uploadServerUri;
- private String fileToUploadPath;
- private Bitmap imageToUpload;
private Uri imageToUploadUri;
- private Thread uploadThread;
private TextWatcher textWatcher;
- private OnGlobalLayoutListener keyboardListener;
+ private ViewTreeObserver.OnGlobalLayoutListener keyboardListener;
+ private ChatMessageAdapter adapter;
+ private LinphoneCoreListenerBase mListener;
+ private ByteArrayOutputStream mDownloadedImageStream;
+ private ByteArrayInputStream mUploadingImageStream;
+ private int mDownloadedImageStreamSize;
+ private LinphoneChatMessage currentMessageInFileTransferUploadState;
+
+ public static boolean isInstanciated() {
+ return instance != null;
+ }
+
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- sipUri = getArguments().getString("SipUri");
- String displayName = getArguments().getString("DisplayName");
- String pictureUri = getArguments().getString("PictureUri");
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ instance = this;
+ View view = inflater.inflate(R.layout.chat, container, false);
- view = inflater.inflate(R.layout.chat, container, false);
-
- contactName = (TextView) view.findViewById(R.id.contactName);
- contactPicture = (AvatarWithShadow) view.findViewById(R.id.contactPicture);
-
- sendMessage = (TextView) view.findViewById(R.id.sendMessage);
- sendMessage.setOnClickListener(this);
-
- message = (EditText) view.findViewById(R.id.message);
- if (!getActivity().getResources().getBoolean(R.bool.allow_chat_multiline)) {
- message.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE);
- message.setMaxLines(1);
- }
-
- uploadLayout = (RelativeLayout) view.findViewById(R.id.uploadLayout);
- textLayout = (RelativeLayout) view.findViewById(R.id.messageLayout);
-
- messagesLayout = (RelativeLayout) view.findViewById(R.id.messages);
- messagesScrollView = (LinphoneScrollView) view.findViewById(R.id.chatScrollView);
- progressBar = (ProgressBar) view.findViewById(R.id.progressbar);
-
- sendImage = (TextView) view.findViewById(R.id.sendPicture);
- if (!getResources().getBoolean(R.bool.disable_chat_send_file)) {
- registerForContextMenu(sendImage);
- sendImage.setOnClickListener(new OnClickListener() {
+ // Retain the fragment across configuration changes
+ setRetainInstance(true);
+
+ //Retrieve parameter from intent
+ sipUri = getArguments().getString("SipUri");
+ displayName = getArguments().getString("DisplayName");
+ pictureUri = getArguments().getString("PictureUri");
+
+ //Initialize UI
+ contactName = (TextView) view.findViewById(R.id.contactName);
+ contactPicture = (AvatarWithShadow) view.findViewById(R.id.contactPicture);
+ messagesList = (ListView) view.findViewById(R.id.chatMessageList);
+ textLayout = (RelativeLayout) view.findViewById(R.id.messageLayout);
+ progressBar = (ProgressBar) view.findViewById(R.id.progressbar);
+ topBar = (LinearLayout) view.findViewById(R.id.topbar);
+
+ sendMessage = (TextView) view.findViewById(R.id.sendMessage);
+ sendMessage.setOnClickListener(this);
+
+ remoteComposing = (TextView) view.findViewById(R.id.remoteComposing);
+ remoteComposing.setVisibility(View.GONE);
+
+ uploadLayout = (RelativeLayout) view.findViewById(R.id.uploadLayout);
+ uploadLayout.setVisibility(View.GONE);
+
+ displayChatHeader(displayName, pictureUri);
+
+ //Manage multiline
+ message = (EditText) view.findViewById(R.id.message);
+ if (!getResources().getBoolean(R.bool.allow_chat_multiline)) {
+ message.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_SHORT_MESSAGE);
+ message.setMaxLines(1);
+ }
+
+ sendImage = (TextView) view.findViewById(R.id.sendPicture);
+ if (!getResources().getBoolean(R.bool.disable_chat_send_file)) {
+ sendImage.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
pickImage();
}
});
- } else {
- sendImage.setEnabled(false);
- }
-
- cancelUpload = (ImageView) view.findViewById(R.id.cancelUpload);
- cancelUpload.setOnClickListener(new OnClickListener() {
+ } else {
+ sendImage.setEnabled(false);
+ }
+
+ back = (TextView) view.findViewById(R.id.back);
+ if (back != null) {
+ back.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ getActivity().finish();
+ }
+ });
+ }
+
+ cancelUpload = (ImageView) view.findViewById(R.id.cancelUpload);
+ cancelUpload.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- uploadThread.interrupt();
- uploadLayout.setVisibility(View.GONE);
- textLayout.setVisibility(View.VISIBLE);
- progressBar.setProgress(0);
+ if (currentMessageInFileTransferUploadState != null) {
+ uploadLayout.setVisibility(View.GONE);
+ textLayout.setVisibility(View.VISIBLE);
+ progressBar.setProgress(0);
+ currentMessageInFileTransferUploadState.cancelFileTransfer();
+ currentMessageInFileTransferUploadState = null;
+ }
}
});
-
- if (savedInstanceState != null) {
- messagesFilterLimit = savedInstanceState.getInt("messagesFilterLimit");
- }
- displayChat(displayName, pictureUri);
-
- LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
if (lc != null) {
- chatRoom = lc.createChatRoom(sipUri);
+ chatRoom = lc.getOrCreateChatRoom(sipUri);
+ //Only works if using liblinphone storage
+ chatRoom.markAsRead();
}
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(LinphoneActivity.instance());
- uploadServerUri = prefs.getString(getString(R.string.pref_image_sharing_server_key), getString(R.string.pref_image_sharing_server_default));
-
- textWatcher = new TextWatcher() {
- public void afterTextChanged(Editable arg0) {
-
+ mListener = new LinphoneCoreListenerBase(){
+ @Override
+ public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) {
+ LinphoneAddress from = cr.getPeerAddress();
+ if (from.asStringUriOnly().equals(sipUri)) {
+ invalidate();
+ }
}
-
- public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
-
+
+ @Override
+ public void isComposingReceived(LinphoneCore lc, LinphoneChatRoom room) {
+ if (chatRoom != null && room != null && chatRoom.getPeerAddress().asStringUriOnly().equals(room.getPeerAddress().asStringUriOnly())) {
+ remoteComposing.setVisibility(chatRoom.isRemoteComposing() ? View.VISIBLE : View.GONE);
+ }
}
+ };
- public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3)
- {
+ textWatcher = new TextWatcher() {
+ public void afterTextChanged(Editable arg0) {}
+
+ public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {}
+
+ public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
if (message.getText().toString().equals("")) {
sendMessage.setEnabled(false);
} else {
+ if (chatRoom != null)
+ chatRoom.compose();
sendMessage.setEnabled(true);
}
}
};
-
- // Force hide keyboard
- if (LinphoneActivity.isInstanciated()) {
- InputMethodManager imm = (InputMethodManager) LinphoneActivity.instance().getSystemService(Context.INPUT_METHOD_SERVICE);
- imm.hideSoftInputFromWindow(view.getWindowToken(),0);
- }
- // Workaround for SGS3 issue
- if (savedInstanceState != null) {
- fileToUploadPath = savedInstanceState.getString("fileToUploadPath");
- imageToUpload = savedInstanceState.getParcelable("imageToUpload");
- }
- if (fileToUploadPath != null || imageToUpload != null) {
- sendImage.post(new Runnable() {
- @Override
- public void run() {
- sendImage.showContextMenu();
- }
- });
- }
+ // Force hide keyboard
+ getActivity().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_ALWAYS_HIDDEN);
return view;
- }
-
- private void refreshMessages() {
- messagesList = LinphoneActivity.instance().getChatMessages(sipUri);
}
-
+
+ public static ChatFragment instance() {
+ return instance;
+ }
+
@Override
public void onSaveInstanceState(Bundle outState) {
- outState.putString("fileToUploadPath", fileToUploadPath);
- outState.putParcelable("imageToUpload", imageToUpload);
- outState.putInt("messagesFilterLimit", messagesFilterLimit);
+ outState.putString("messageDraft", message.getText().toString());
+
super.onSaveInstanceState(outState);
}
-
+
private void addVirtualKeyboardVisiblityListener() {
- keyboardListener = new OnGlobalLayoutListener() {
+ keyboardListener = new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
- Rect visibleArea = new Rect();
- view.getWindowVisibleDisplayFrame(visibleArea);
-
- int heightDiff = view.getRootView().getHeight() - (visibleArea.bottom - visibleArea.top);
- if (heightDiff > 200) {
- showKeyboardVisibleMode();
- } else {
- hideKeyboardVisibleMode();
- }
+ Rect visibleArea = new Rect();
+ getActivity().getWindow().getDecorView().getWindowVisibleDisplayFrame(visibleArea);
+
+ int heightDiff = getActivity().getWindow().getDecorView().getRootView().getHeight() - (visibleArea.bottom - visibleArea.top);
+ if (heightDiff > 200) {
+ showKeyboardVisibleMode();
+ } else {
+ hideKeyboardVisibleMode();
+ }
}
};
- view.getViewTreeObserver().addOnGlobalLayoutListener(keyboardListener);
+ getActivity().getWindow().getDecorView().getViewTreeObserver().addOnGlobalLayoutListener(keyboardListener);
}
-
+
private void removeVirtualKeyboardVisiblityListener() {
- Compatibility.removeGlobalLayoutListener(view.getViewTreeObserver(), keyboardListener);
+ Compatibility.removeGlobalLayoutListener(getActivity().getWindow().getDecorView().getViewTreeObserver(), keyboardListener);
}
-
+
public void showKeyboardVisibleMode() {
- LinphoneActivity.instance().hideMenu(true);
+ boolean isOrientationLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
+ if (isOrientationLandscape && topBar != null) {
+ topBar.setVisibility(View.GONE);
+ }
contactPicture.setVisibility(View.GONE);
//scrollToEnd();
}
-
+
public void hideKeyboardVisibleMode() {
- LinphoneActivity.instance().hideMenu(false);
+ boolean isOrientationLandscape = getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE;
contactPicture.setVisibility(View.VISIBLE);
+ if (isOrientationLandscape && topBar != null) {
+ topBar.setVisibility(View.VISIBLE);
+ }
//scrollToEnd();
}
-
- private void invalidate() {
- refreshMessages();
-
- if (messagesFilterLimit == 0) {
- if (messagesList.size() > MESSAGES_STEP)
- messagesFilterLimit = MESSAGES_STEP;
- else
- messagesFilterLimit = messagesList.size();
- } else {
- if (messagesFilterLimit + MESSAGES_STEP <= messagesList.size())
- messagesFilterLimit += MESSAGES_STEP;
- else
- messagesFilterLimit = messagesList.size();
- }
- invalidate(messagesFilterLimit);
+
+ class ChatMessageAdapter extends BaseAdapter {
+ LinphoneChatMessage[] history;
+ Context context;
+
+ public ChatMessageAdapter(Context context, LinphoneChatMessage[] history) {
+ this.history = history;
+ this.context = context;
+ }
+
+ public void refreshHistory() {
+ this.history = chatRoom.getHistory();
+ }
+
+ @Override
+ public int getCount() {
+ return history.length;
+ }
+
+ @Override
+ public LinphoneChatMessage getItem(int position) {
+ return history[position];
+ }
+
+ @Override
+ public long getItemId(int position) {
+ return history[position].getStorageId();
+ }
+
+ @Override
+ public View getView(int position, View convertView, ViewGroup parent) {
+ LinphoneChatMessage message = history[position];
+
+ BubbleChat bubble = new BubbleChat(context, message, ChatFragment.this);
+ View v = bubble.getView();
+
+ registerForContextMenu(v);
+ RelativeLayout rlayout = new RelativeLayout(context);
+ rlayout.addView(v);
+
+ return rlayout;
+ }
}
-
- private void invalidate(final int limit) {
- messagesLayout.removeAllViews();
-
- mHandler.post(new Runnable() {
- @Override
- public void run() {
-
- previousMessageID = -1;
- ChatStorage chatStorage = LinphoneActivity.instance().getChatStorage();
-
- for (int i = messagesList.size() - limit; i < messagesList.size(); i++) {
- ChatMessage msg = messagesList.get(i);
- if (msg.getMessage() != null) {
- displayMessage(msg.getId(), msg.getMessage(), msg.getTimestamp(), msg.isIncoming(), msg.getStatus(), messagesLayout);
- } else {
- displayImageMessage(msg.getId(), msg.getImage(), msg.getTimestamp(), msg.isIncoming(), msg.getStatus(), messagesLayout, msg.getUrl());
- }
-
- if (!msg.isRead())
- chatStorage.markMessageAsRead(msg.getId());
- }
- LinphoneActivity.instance().updateMissedChatCount();
-
- if (limit < messagesList.size()) {
- messagesScrollView.setScrollViewListener(new ScrollViewListener() {
- @Override
- public void OnScrollToTop(final int previousHeight) {
- invalidate();mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- //Scroll to latest saw message
- if (messagesScrollView != null && messagesLayout != null && messagesLayout.getChildCount() >= MESSAGES_STEP-1)
- messagesScrollView.scrollTo(0, messagesLayout.getChildAt(MESSAGES_STEP-1).getBottom());
- }
- }, 300);
- }
- });
- } else {
- messagesScrollView.setScrollViewListener(null);
- }
+
+ public void dispayMessageList() {
+ adapter = new ChatMessageAdapter(getActivity(), chatRoom.getHistory());
+ messagesList.setAdapter(adapter);
+ adapter.notifyDataSetChanged();
+ }
+
+ private void displayChatHeader(String displayName, String pictureUri) {
+ LinphoneAddress lAddress;
+ try {
+ lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri);
+ Contact contact = ContactsManager.getInstance().findContactWithAddress(getActivity().getContentResolver(), lAddress);
+ if (contact != null) {
+ LinphoneUtils.setImagePictureFromUri(getActivity(), contactPicture.getView(), contact.getPhotoUri(), contact.getThumbnailUri(), R.drawable.unknown_small);
+
+ } else {
+ contactPicture.setImageResource(R.drawable.unknown_small);
}
- });
- }
-
- private void displayChat(String displayName, String pictureUri) {
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+
if (displayName == null && getResources().getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(sipUri)) {
- contactName.setText(LinphoneUtils.getUsernameFromAddress(sipUri));
+ contactName.setText(LinphoneUtils.getUsernameFromAddress(sipUri));
} else if (displayName == null) {
contactName.setText(sipUri);
} else {
contactName.setText(displayName);
}
-
- if (pictureUri != null) {
- LinphoneUtils.setImagePictureFromUri(view.getContext(), contactPicture.getView(), Uri.parse(pictureUri), R.drawable.unknown_small);
- } else {
- contactPicture.setImageResource(R.drawable.unknown_small);
- }
-
- if (messagesFilterLimit == 0)
- invalidate();
- else {
- invalidate(messagesFilterLimit);
- }
-
- scrollToEnd();
- }
-
- private void displayMessage(int id, String message, String time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout) {
- BubbleChat bubble = new BubbleChat(layout.getContext(), id, message, null, time, isIncoming, status, previousMessageID);
- if (!isIncoming) {
- lastSentMessageBubble = bubble;
- }
-
- View v = bubble.getView();
- previousMessageID = id;
- layout.addView(v);
- registerForContextMenu(v);
- }
-
- private void displayImageMessage(final int id, Bitmap image, String time, boolean isIncoming, LinphoneChatMessage.State status, RelativeLayout layout, final String url) {
- BubbleChat bubble = new BubbleChat(layout.getContext(), id, null, image, time, isIncoming, status, previousMessageID);
- if (!isIncoming) {
- lastSentMessageBubble = bubble;
- }
- final View v = bubble.getView();
- bubble.setDownloadImageButtonListener(new OnClickListener() {
- @Override
- public void onClick(View view) {
- new Thread(new Runnable() {
- @Override
- public void run() {
- final Bitmap bm = ChatFragment.downloadImage(url);
- if (bm != null) {
- LinphoneActivity.instance().getChatStorage().saveImage(id, bm);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- ((ImageView)v.findViewById(R.id.image)).setImageBitmap(bm);
- v.findViewById(R.id.image).setVisibility(View.VISIBLE);
- v.findViewById(R.id.download).setVisibility(View.GONE);
- }
- });
- } else {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- LinphoneActivity.instance().displayCustomToast(getString(R.string.download_image_failed), Toast.LENGTH_LONG);
- }
- });
- }
- }
- }).start();
- }
- });
-
- previousMessageID = id;
- layout.addView(v);
- registerForContextMenu(v);
}
public void changeDisplayedChat(String newSipUri, String displayName, String pictureUri) {
+ this.sipUri = newSipUri;
+ this.displayName = displayName;
+ this.pictureUri = pictureUri;
+
if (!message.getText().toString().equals("") && LinphoneActivity.isInstanciated()) {
ChatStorage chatStorage = LinphoneActivity.instance().getChatStorage();
if (chatStorage.getDraft(sipUri) == null) {
@@ -430,558 +384,393 @@ public class ChatFragment extends Fragment implements OnClickListener, LinphoneC
} else if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().getChatStorage().deleteDraft(sipUri);
}
-
- messagesFilterLimit = 0;
- sipUri = newSipUri;
+
if (LinphoneActivity.isInstanciated()) {
String draft = LinphoneActivity.instance().getChatStorage().getDraft(sipUri);
if (draft == null)
draft = "";
message.setText(draft);
}
- displayChat(displayName, pictureUri);
+
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ chatRoom = lc.getOrCreateChatRoom(sipUri);
+ //Only works if using liblinphone storage
+ chatRoom.markAsRead();
+ }
+
+ displayChatHeader(displayName, pictureUri);
+ dispayMessageList();
}
-
+
@Override
- public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
- if (v.getId() == R.id.sendPicture) {
- menu.add(0, MENU_PICTURE_SMALL, 0, getString(R.string.share_picture_size_small));
- menu.add(0, MENU_PICTURE_MEDIUM, 0, getString(R.string.share_picture_size_medium));
- menu.add(0, MENU_PICTURE_LARGE, 0, getString(R.string.share_picture_size_large));
-// Not a good idea, very big pictures cause Out of Memory exceptions, slow display, ...
-// menu.add(0, MENU_PICTURE_REAL, 0, getString(R.string.share_picture_size_real));
- } else {
- menu.add(v.getId(), MENU_DELETE_MESSAGE, 0, getString(R.string.delete));
- ImageView iv = (ImageView) v.findViewById(R.id.image);
- if (iv != null && iv.getVisibility() == View.VISIBLE) {
- menu.add(v.getId(), MENU_SAVE_PICTURE, 0, getString(R.string.save_picture));
- } else {
- menu.add(v.getId(), MENU_COPY_TEXT, 0, getString(R.string.copy_text));
- }
+ public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
+ menu.add(v.getId(), MENU_DELETE_MESSAGE, 0, getString(R.string.delete));
+ menu.add(v.getId(), MENU_COPY_TEXT, 0, getString(R.string.copy_text));
+
+ LinphoneChatMessage msg = getMessageForId(v.getId());
+ if (msg != null && msg.getStatus() == LinphoneChatMessage.State.NotDelivered) {
+ menu.add(v.getId(), MENU_RESEND_MESSAGE, 0, getString(R.string.retry));
}
}
-
+
@Override
public boolean onContextItemSelected(MenuItem item) {
switch (item.getItemId()) {
- case MENU_DELETE_MESSAGE:
- LinphoneActivity.instance().getChatStorage().deleteMessage(item.getGroupId());
- invalidate();
- break;
- case MENU_SAVE_PICTURE:
- saveImage(item.getGroupId());
- break;
- case MENU_COPY_TEXT:
- copyTextMessageToClipboard(item.getGroupId());
- break;
- case MENU_PICTURE_SMALL:
- uploadAndSendImage(fileToUploadPath, imageToUpload, ImageSize.SMALL);
- break;
- case MENU_PICTURE_MEDIUM:
- uploadAndSendImage(fileToUploadPath, imageToUpload, ImageSize.MEDIUM);
- break;
- case MENU_PICTURE_LARGE:
- uploadAndSendImage(fileToUploadPath, imageToUpload, ImageSize.LARGE);
- break;
- case MENU_PICTURE_REAL:
- uploadAndSendImage(fileToUploadPath, imageToUpload, ImageSize.REAL);
- break;
+ case MENU_DELETE_MESSAGE:
+ if (chatRoom != null) {
+ LinphoneChatMessage message = getMessageForId(item.getGroupId());
+ if (message != null) {
+ chatRoom.deleteMessage(message);
+ invalidate();
+ }
+ }
+ break;
+ case MENU_COPY_TEXT:
+ copyTextMessageToClipboard(item.getGroupId());
+ break;
+ case MENU_RESEND_MESSAGE:
+ resendMessage(item.getGroupId());
+ break;
}
return true;
}
-
+
@Override
public void onPause() {
- latestImageMessages = null;
message.removeTextChangedListener(textWatcher);
removeVirtualKeyboardVisiblityListener();
+
LinphoneService.instance().removeMessageNotification();
-
- super.onPause();
-
- if (!message.getText().toString().equals("") && LinphoneActivity.isInstanciated()) {
- ChatStorage chatStorage = LinphoneActivity.instance().getChatStorage();
- if (chatStorage.getDraft(sipUri) == null) {
- chatStorage.saveDraft(sipUri, message.getText().toString());
- } else {
- chatStorage.updateDraft(sipUri, message.getText().toString());
- }
- } else if (LinphoneActivity.isInstanciated()) {
- LinphoneActivity.instance().getChatStorage().deleteDraft(sipUri);
+
+ if (LinphoneActivity.isInstanciated()) {
+ LinphoneActivity.instance().updateChatFragment(null);
}
+
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.removeListener(mListener);
+ }
+
+ onSaveInstanceState(getArguments());
+
+ //Hide keybord
+ InputMethodManager imm = (InputMethodManager)getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
+ imm.hideSoftInputFromWindow(message.getWindowToken(), 0);
+ super.onPause();
}
-
+
@SuppressLint("UseSparseArrays")
@Override
public void onResume() {
- latestImageMessages = new HashMap();
message.addTextChangedListener(textWatcher);
addVirtualKeyboardVisiblityListener();
-
- super.onResume();
+
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.addListener(mListener);
+ }
if (LinphoneActivity.isInstanciated()) {
- LinphoneActivity.instance().selectMenu(FragmentsAvailable.CHAT);
+ if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) {
+ LinphoneActivity.instance().hideStatusBar();
+ }
LinphoneActivity.instance().updateChatFragment(this);
}
-
- if (LinphoneActivity.isInstanciated()) {
- String draft = LinphoneActivity.instance().getChatStorage().getDraft(sipUri);
- message.setText(draft);
- }
+
+ String draft = getArguments().getString("messageDraft");
+ message.setText(draft);
+
+ remoteComposing.setVisibility(chatRoom.isRemoteComposing() ? View.VISIBLE : View.GONE);
+ dispayMessageList();
+
+ super.onResume();
}
@Override
public void onClick(View v) {
sendTextMessage();
}
-
- private void sendTextMessage() {
- LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
- boolean isNetworkReachable = lc == null ? false : lc.isNetworkReachable();
-
- if (chatRoom != null && message != null && message.getText().length() > 0 && isNetworkReachable) {
- String messageToSend = message.getText().toString();
- message.setText("");
- LinphoneChatMessage chatMessage = chatRoom.createLinphoneChatMessage(messageToSend);
- chatRoom.sendMessage(chatMessage, this);
-
- int newId = -1;
- if (LinphoneActivity.isInstanciated()) {
- newId = LinphoneActivity.instance().onMessageSent(sipUri, messageToSend);
- }
-
- displayMessage(newId, messageToSend, String.valueOf(System.currentTimeMillis()), false, State.InProgress, messagesLayout);
- scrollToEnd();
- } else if (!isNetworkReachable && LinphoneActivity.isInstanciated()) {
- LinphoneActivity.instance().displayCustomToast(getString(R.string.error_network_unreachable), Toast.LENGTH_LONG);
- }
+ private void sendTextMessage() {
+ sendTextMessage(message.getText().toString());
+ message.setText("");
}
-
- private void sendImageMessage(String url, Bitmap bitmap) {
+
+ private void sendTextMessage(String messageToSend) {
LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
boolean isNetworkReachable = lc == null ? false : lc.isNetworkReachable();
-
- if (chatRoom != null && url != null && url.length() > 0 && isNetworkReachable) {
- LinphoneChatMessage chatMessage = chatRoom.createLinphoneChatMessage("");
- chatMessage.setExternalBodyUrl(url);
- chatRoom.sendMessage(chatMessage, this);
-
- int newId = -1;
+
+ if (chatRoom != null && messageToSend != null && messageToSend.length() > 0 && isNetworkReachable) {
+ LinphoneChatMessage message = chatRoom.createLinphoneChatMessage(messageToSend);
+ message.setListener(this);
+ chatRoom.sendChatMessage(message);
+
if (LinphoneActivity.isInstanciated()) {
- newId = LinphoneActivity.instance().onMessageSent(sipUri, bitmap, url);
+ LinphoneActivity.instance().onMessageSent(sipUri, messageToSend);
+ }
+
+ invalidate();
+ Log.i("Sent message current status: " + message.getStatus());
+ } else if (!isNetworkReachable && LinphoneActivity.isInstanciated()) {
+ LinphoneActivity.instance().displayCustomToast(getString(R.string.error_network_unreachable), Toast.LENGTH_LONG);
+ }
+ }
+
+ private void sendImageMessage(String path) {
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ boolean isNetworkReachable = lc == null ? false : lc.isNetworkReachable();
+
+ if (chatRoom != null && path != null && path.length() > 0 && isNetworkReachable) {
+ Bitmap bm = BitmapFactory.decodeFile(path);
+ if (bm != null) {
+ FileUploadPrepareTask task = new FileUploadPrepareTask(getActivity(), path);
+ task.execute(bm);
+ } else {
+ Log.e("Error, bitmap factory can't read " + path);
}
- latestImageMessages.put(newId, url);
-
- displayImageMessage(newId, bitmap, String.valueOf(System.currentTimeMillis()), false, State.InProgress, messagesLayout, url);
- scrollToEnd();
} else if (!isNetworkReachable && LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().displayCustomToast(getString(R.string.error_network_unreachable), Toast.LENGTH_LONG);
}
}
- private void scrollToEnd() {
- messagesScrollView.postDelayed(new Runnable() {
- @Override
- public void run() {
- messagesScrollView.fullScroll(View.FOCUS_DOWN);
+ class FileUploadPrepareTask extends AsyncTask {
+ private String path;
+ private ProgressDialog progressDialog;
+
+ public FileUploadPrepareTask(Context context, String fileToUploadPath) {
+ path = fileToUploadPath;
+
+ uploadLayout.setVisibility(View.VISIBLE);
+ textLayout.setVisibility(View.GONE);
+
+ progressDialog = new ProgressDialog(context);
+ progressDialog.setIndeterminate(true);
+ progressDialog.setMessage(getString(R.string.processing_image));
+ progressDialog.show();
+ }
+
+ @Override
+ protected byte[] doInBackground(Bitmap... params) {
+ Bitmap bm = params[0];
+
+ if (bm.getWidth() >= bm.getHeight() && bm.getWidth() > SIZE_MAX) {
+ bm = Bitmap.createScaledBitmap(bm, SIZE_MAX, (SIZE_MAX * bm.getHeight()) / bm.getWidth(), false);
+ } else if (bm.getHeight() >= bm.getWidth() && bm.getHeight() > SIZE_MAX) {
+ bm = Bitmap.createScaledBitmap(bm, (SIZE_MAX * bm.getWidth()) / bm.getHeight(), SIZE_MAX, false);
}
- }, 100);
+
+ // Rotate the bitmap if possible/needed, using EXIF data
+ Log.w(path);
+ try {
+ if (path != null) {
+ ExifInterface exif = new ExifInterface(path);
+ int pictureOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
+ Matrix matrix = new Matrix();
+ if (pictureOrientation == 6) {
+ matrix.postRotate(90);
+ } else if (pictureOrientation == 3) {
+ matrix.postRotate(180);
+ } else if (pictureOrientation == 8) {
+ matrix.postRotate(270);
+ }
+ bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ ByteArrayOutputStream stream = new ByteArrayOutputStream();
+ bm.compress(Bitmap.CompressFormat.PNG, 100, stream);
+ byte[] byteArray = stream.toByteArray();
+ return byteArray;
+ }
+
+ @Override
+ protected void onPostExecute(byte[] result) {
+ if (progressDialog != null && progressDialog.isShowing()) {
+ progressDialog.dismiss();
+ }
+
+ mUploadingImageStream = new ByteArrayInputStream(result);
+
+ LinphoneContent content = LinphoneCoreFactory.instance().createLinphoneContent("image", "jpeg", result, null);
+ String fileName = path.substring(path.lastIndexOf("/") + 1);
+ content.setName(fileName);
+
+ LinphoneChatMessage message = chatRoom.createFileTransferMessage(content);
+ message.setListener(ChatFragment.this);
+ message.setAppData(path);
+
+ chatRoom.sendChatMessage(message);
+ currentMessageInFileTransferUploadState = message;
+ }
}
-
+
+ private LinphoneChatMessage getMessageForId(int id) {
+ for (LinphoneChatMessage message : chatRoom.getHistory()) {
+ if (message.getStorageId() == id) {
+ return message;
+ }
+ }
+
+ return null;
+ }
+
+ private void invalidate() {
+ adapter.refreshHistory();
+ adapter.notifyDataSetChanged();
+ chatRoom.markAsRead();
+ }
+
+ private void resendMessage(int id) {
+ LinphoneChatMessage message = getMessageForId(id);
+ if (message == null)
+ return;
+
+ chatRoom.deleteMessage(getMessageForId(id));
+ invalidate();
+
+ if (message.getText() != null && message.getText().length() > 0) {
+ sendTextMessage(message.getText());
+ } else {
+ sendImageMessage(message.getAppData());
+ }
+ }
+
private void copyTextMessageToClipboard(int id) {
- String msg = LinphoneActivity.instance().getChatStorage().getTextMessageForId(id);
+ String msg = LinphoneActivity.instance().getChatStorage().getTextMessageForId(chatRoom, id);
if (msg != null) {
Compatibility.copyTextToClipboard(getActivity(), msg);
LinphoneActivity.instance().displayCustomToast(getString(R.string.text_copied_to_clipboard), Toast.LENGTH_SHORT);
}
}
- public void onMessageReceived(final int id, LinphoneAddress from, final LinphoneChatMessage message) {
- if (from.asStringUriOnly().equals(sipUri)) {
- if (message.getText() != null) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- displayMessage(id, message.getText(), String.valueOf(message.getTime()), true, null, messagesLayout);
- }
- });
- } else if (message.getExternalBodyUrl() != null) {
- byte[] rawImage = LinphoneActivity.instance().getChatStorage().getRawImageFromMessage(id);
- if (rawImage == null) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- displayImageMessage(id, null, String.valueOf(message.getTime()), true, null, messagesLayout, message.getExternalBodyUrl());
- }
- });
- } else {
- final Bitmap bm = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- displayImageMessage(id, bm, String.valueOf(message.getTime()), true, null, messagesLayout, "");
- }
- });
- }
+ public String getSipUri() {
+ return sipUri;
+ }
+
+ private void pickImage() {
+ List cameraIntents = new ArrayList();
+ Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+ File file = new File(Environment.getExternalStorageDirectory(), getString(R.string.temp_photo_name_with_date).replace("%s", String.valueOf(System.currentTimeMillis())));
+ imageToUploadUri = Uri.fromFile(file);
+ captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageToUploadUri);
+ cameraIntents.add(captureIntent);
+
+ Intent galleryIntent = new Intent();
+ galleryIntent.setType("image/*");
+ galleryIntent.setAction(Intent.ACTION_PICK);
+
+ Intent chooserIntent = Intent.createChooser(galleryIntent, getString(R.string.image_picker_title));
+ chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));
+
+ startActivityForResult(chooserIntent, ADD_PHOTO);
+ }
+
+ public String getRealPathFromURI(Uri contentUri) {
+ String[] proj = {MediaStore.Images.Media.DATA};
+ CursorLoader loader = new CursorLoader(getActivity(), contentUri, proj, null, null, null);
+ Cursor cursor = loader.loadInBackground();
+ if (cursor != null && cursor.moveToFirst()) {
+ int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+ String result = cursor.getString(column_index);
+ cursor.close();
+ return result;
+ }
+ return null;
+ }
+
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (requestCode == ADD_PHOTO && resultCode == Activity.RESULT_OK) {
+ String fileToUploadPath = null;
+
+ if (data != null && data.getData() != null) {
+ fileToUploadPath = getRealPathFromURI(data.getData());
+ } else if (imageToUploadUri != null) {
+ fileToUploadPath = imageToUploadUri.getPath();
}
- scrollToEnd();
+
+ if (fileToUploadPath != null) {
+ sendImageMessage(fileToUploadPath);
+ }
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
}
}
@Override
public void onLinphoneChatMessageStateChanged(LinphoneChatMessage msg, State state) {
- final String finalMessage = msg.getText();
- final String finalImage = msg.getExternalBodyUrl();
- final State finalState = state;
- if (LinphoneActivity.isInstanciated() && state != State.InProgress) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (finalMessage != null && !finalMessage.equals("")) {
- LinphoneActivity.instance().onMessageStateChanged(sipUri, finalMessage, finalState.toInt());
- } else if (finalImage != null && !finalImage.equals("")) {
- if (latestImageMessages != null && latestImageMessages.containsValue(finalImage)) {
- int id = -1;
- for (int key : latestImageMessages.keySet()) {
- String object = latestImageMessages.get(key);
- if (object.equals(finalImage)) {
- id = key;
- break;
- }
- }
- if (id != -1) {
- LinphoneActivity.instance().onImageMessageStateChanged(sipUri, id, finalState.toInt());
- }
- }
- }
- if (lastSentMessageBubble != null) {
- lastSentMessageBubble.updateStatusView(finalState);
- }
- }
- });
- }
- }
-
- public String getSipUri() {
- return sipUri;
- }
-
- private void pickImage() {
- final List cameraIntents = new ArrayList();
- final Intent captureIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
- File file = new File(Environment.getExternalStorageDirectory(), getString(R.string.temp_photo_name));
- imageToUploadUri = Uri.fromFile(file);
- captureIntent.putExtra(MediaStore.EXTRA_OUTPUT, imageToUploadUri);
- cameraIntents.add(captureIntent);
-
- final Intent galleryIntent = new Intent();
- galleryIntent.setType("image/*");
- galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
-
- final Intent chooserIntent = Intent.createChooser(galleryIntent, getString(R.string.image_picker_title));
- chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, cameraIntents.toArray(new Parcelable[]{}));
-
- startActivityForResult(chooserIntent, ADD_PHOTO);
- }
-
- public static Bitmap downloadImage(String stringUrl) {
- URL url;
- Bitmap bm = null;
- try {
- url = new URL(stringUrl);
- URLConnection ucon = url.openConnection();
- InputStream is = ucon.getInputStream();
- BufferedInputStream bis = new BufferedInputStream(is);
-
- ByteArrayBuffer baf = new ByteArrayBuffer(50);
- int current = 0;
- while ((current = bis.read()) != -1) {
- baf.append((byte) current);
- }
-
- byte[] rawImage = baf.toByteArray();
- bm = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
- bis.close();
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- return bm;
- }
-
- private void saveImage(int id) {
- try {
- byte[] rawImage = LinphoneActivity.instance().getChatStorage().getRawImageFromMessage(id);
- Bitmap bm = BitmapFactory.decodeByteArray(rawImage, 0, rawImage.length);
-
- String path = Environment.getExternalStorageDirectory().toString();
- OutputStream fOut = null;
- File file = new File(path, getString(R.string.picture_name_format).replace("%s", String.valueOf(id)));
- fOut = new FileOutputStream(file);
-
- bm.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
- fOut.flush();
- fOut.close();
-
- Toast.makeText(getActivity(), getString(R.string.image_saved), Toast.LENGTH_SHORT).show();
- MediaStore.Images.Media.insertImage(getActivity().getContentResolver(),file.getAbsolutePath(),file.getName(),file.getName());
- } catch (Exception e) {
- Toast.makeText(getActivity(), getString(R.string.image_not_saved), Toast.LENGTH_LONG).show();
- e.printStackTrace();
- }
- }
-
- private long hashBitmap(Bitmap bmp){
- long hash = 31; // Random prime number
- for(int x = 0; x < bmp.getWidth(); x++){
- for (int y = 0; y < bmp.getHeight(); y++){
- hash *= (bmp.getPixel(x,y) + 31);
+ if (LinphoneActivity.isInstanciated() && state != LinphoneChatMessage.State.InProgress) {
+ if (msg != null) {
+ LinphoneActivity.instance().onMessageStateChanged(sipUri, msg.getText(), state.toInt());
}
- }
- return hash;
- }
-
- private String uploadImage(String filePath, Bitmap file, int compressorQuality, final int imageSize) {
- String fileName;
- if (filePath != null) {
- File sourceFile = new File(filePath);
- fileName = sourceFile.getName();
- } else {
- fileName = getString(R.string.temp_photo_name_with_date).replace("%s", String.valueOf(System.currentTimeMillis()));
+ invalidate();
}
- if (getResources().getBoolean(R.bool.hash_images_as_name_before_upload)) {
- fileName = String.valueOf(hashBitmap(file)) + ".jpg";
- }
-
- String response = null;
- HttpURLConnection conn = null;
- try {
- String lineEnd = "\r\n";
- String twoHyphens = "--";
- String boundary = "---------------------------14737809831466499882746641449";
-
- URL url = new URL(uploadServerUri);
- conn = (HttpURLConnection) url.openConnection();
- conn.setDoInput(true);
- conn.setDoOutput(true);
- conn.setUseCaches(false);
- conn.setRequestMethod("POST");
- conn.setRequestProperty("Connection", "Keep-Alive");
- conn.setRequestProperty("ENCTYPE", "multipart/form-data");
- conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
- conn.setRequestProperty("uploaded_file", fileName);
-
- ProgressOutputStream pos = new ProgressOutputStream(conn.getOutputStream());
- pos.setListener(new OutputStreamListener() {
- @Override
- public void onBytesWrite(int count) {
- bytesSent += count;
- progressBar.setProgress(bytesSent * 100 / imageSize);
- }
- });
- DataOutputStream dos = new DataOutputStream(pos);
-
- dos.writeBytes(lineEnd + twoHyphens + boundary + lineEnd);
- dos.writeBytes("Content-Disposition: form-data; name=\"userfile\"; filename=\""+ fileName + "\"" + lineEnd);
- dos.writeBytes("Content-Type: application/octet-stream" + lineEnd);
- dos.writeBytes(lineEnd);
-
- file.compress(CompressFormat.JPEG, compressorQuality, dos);
-
- dos.writeBytes(lineEnd);
- dos.writeBytes(twoHyphens + boundary + twoHyphens + lineEnd);
-
- dos.flush();
- dos.close();
-
- InputStream is = conn.getInputStream();
- ByteArrayOutputStream baos = new ByteArrayOutputStream();
-
- int bytesRead;
- byte[] bytes = new byte[1024];
- while((bytesRead = is.read(bytes)) != -1) {
- baos.write(bytes, 0, bytesRead);
- }
- byte[] bytesReceived = baos.toByteArray();
- baos.close();
- is.close();
-
- response = new String(bytesReceived);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (conn != null) {
- conn.disconnect();
- }
- }
-
- return response;
- }
-
- public String getRealPathFromURI(Uri contentUri) {
- String[] proj = { MediaStore.Images.Media.DATA };
- CursorLoader loader = new CursorLoader(getActivity(), contentUri, proj, null, null, null);
- Cursor cursor = loader.loadInBackground();
- if (cursor != null && cursor.moveToFirst()) {
- int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
- String result = cursor.getString(column_index);
- cursor.close();
- return result;
- }
- return null;
- }
-
- private void showPopupMenuAskingImageSize(final String filePath, final Bitmap image) {
- fileToUploadPath = filePath;
- imageToUpload = image;
- try {
- sendImage.showContextMenu();
- } catch (Exception e) { e.printStackTrace(); };
- }
-
- private void uploadAndSendImage(final String filePath, final Bitmap image, final ImageSize size) {
- uploadLayout.setVisibility(View.VISIBLE);
- textLayout.setVisibility(View.GONE);
-
- uploadThread = new Thread(new Runnable() {
- @Override
- public void run() {
- Bitmap bm = null;
- String url = null;
+ if (state == State.FileTransferDone) {
+ if (mDownloadedImageStream != null) {
+ byte[] bytes = mDownloadedImageStream.toByteArray();
+ Bitmap bm = BitmapFactory.decodeByteArray(bytes, 0, mDownloadedImageStreamSize);
- if (!uploadThread.isInterrupted()) {
- if (filePath != null) {
- bm = BitmapFactory.decodeFile(filePath);
- if (bm != null && size != ImageSize.REAL) {
- int pixelsMax = size == ImageSize.SMALL ? SIZE_SMALL : size == ImageSize.MEDIUM ? SIZE_MEDIUM : SIZE_LARGE;
- if (bm.getWidth() > bm.getHeight() && bm.getWidth() > pixelsMax) {
- bm = Bitmap.createScaledBitmap(bm, pixelsMax, (pixelsMax * bm.getHeight()) / bm.getWidth(), false);
- } else if (bm.getHeight() > bm.getWidth() && bm.getHeight() > pixelsMax) {
- bm = Bitmap.createScaledBitmap(bm, (pixelsMax * bm.getWidth()) / bm.getHeight(), pixelsMax, false);
- }
- }
- } else if (image != null) {
- bm = image;
- }
+ String path = msg.getExternalBodyUrl();
+ String fileName = path.substring(path.lastIndexOf("/") + 1);
+ String url = MediaStore.Images.Media.insertImage(getActivity().getContentResolver(), bm, fileName, null);
+ if (url != null) {
+ msg.setAppData(url);
}
- // Rotate the bitmap if possible/needed, using EXIF data
- try {
- if (filePath != null) {
- ExifInterface exif = new ExifInterface(filePath);
- int pictureOrientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION, 0);
- Matrix matrix = new Matrix();
- if (pictureOrientation == 6) {
- matrix.postRotate(90);
- } else if (pictureOrientation == 3) {
- matrix.postRotate(180);
- } else if (pictureOrientation == 8) {
- matrix.postRotate(270);
- }
- bm = Bitmap.createBitmap(bm, 0, 0, bm.getWidth(), bm.getHeight(), matrix, true);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
-
- ByteArrayOutputStream outStream = new ByteArrayOutputStream();
- if (bm != null) {
- bm.compress(CompressFormat.JPEG, COMPRESSOR_QUALITY, outStream);
- }
-
- if (!uploadThread.isInterrupted() && bm != null) {
- url = uploadImage(filePath, bm, COMPRESSOR_QUALITY, outStream.size());
- File file = new File(Environment.getExternalStorageDirectory(), getString(R.string.temp_photo_name));
- file.delete();
- }
-
- if (!uploadThread.isInterrupted()) {
- final Bitmap fbm = bm;
- final String furl = url;
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- uploadLayout.setVisibility(View.GONE);
- textLayout.setVisibility(View.VISIBLE);
- progressBar.setProgress(0);
- if (furl != null) {
- sendImageMessage(furl, fbm);
- } else {
- Toast.makeText(getActivity(), getString(R.string.error), Toast.LENGTH_LONG).show();
- }
- }
- });
- }
+ mDownloadedImageStream = null;
+ mDownloadedImageStreamSize = 0;
+ } else if (mUploadingImageStream != null) {
+ mUploadingImageStream = null;
}
- });
- uploadThread.start();
+ }
+
+ if (state == State.FileTransferDone || state == State.FileTransferError) {
+ uploadLayout.setVisibility(View.GONE);
+ textLayout.setVisibility(View.VISIBLE);
+ progressBar.setProgress(0);
+ currentMessageInFileTransferUploadState = null;
+ }
+ invalidate();
}
-
+
@Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == ADD_PHOTO && resultCode == Activity.RESULT_OK) {
- if (data != null && data.getExtras() != null && data.getExtras().get("data") != null) {
- Bitmap bm = (Bitmap) data.getExtras().get("data");
- showPopupMenuAskingImageSize(null, bm);
- }
- else if (data != null && data.getData() != null) {
- String filePath = getRealPathFromURI(data.getData());
- showPopupMenuAskingImageSize(filePath, null);
- }
- else if (imageToUploadUri != null) {
- String filePath = imageToUploadUri.getPath();
- showPopupMenuAskingImageSize(filePath, null);
- }
- else {
- File file = new File(Environment.getExternalStorageDirectory(), getString(R.string.temp_photo_name));
- if (file.exists()) {
- imageToUploadUri = Uri.fromFile(file);
- String filePath = imageToUploadUri.getPath();
- showPopupMenuAskingImageSize(filePath, null);
- }
- }
- } else {
- super.onActivityResult(requestCode, resultCode, data);
+ public void onLinphoneChatMessageFileTransferReceived(LinphoneChatMessage msg, LinphoneContent content, LinphoneBuffer buffer) {
+ if (mDownloadedImageStream == null) {
+ mDownloadedImageStream = new ByteArrayOutputStream();
+ mDownloadedImageStreamSize = 0;
}
- }
-
- class ProgressOutputStream extends OutputStream {
- OutputStream outputStream;
- private OutputStreamListener listener;
-
- public ProgressOutputStream(OutputStream stream) {
- outputStream = stream;
- }
-
- public void setListener(OutputStreamListener listener) {
- this.listener = listener;
- }
-
- @Override
- public void write(int oneByte) throws IOException {
- outputStream.write(oneByte);
- }
-
- @Override
- public void write(byte[] buffer, int offset, int count)
- throws IOException {
- listener.onBytesWrite(count);
- outputStream.write(buffer, offset, count);
+
+ if (buffer != null && buffer.getSize() > 0) {
+ try {
+ mDownloadedImageStream.write(buffer.getContent());
+ mDownloadedImageStreamSize += buffer.getSize();
+ } catch (IOException e) {
+ Log.e(e);
+ }
}
}
-
- interface OutputStreamListener {
- public void onBytesWrite(int count);
+
+ @Override
+ public void onLinphoneChatMessageFileTransferSent(LinphoneChatMessage msg, LinphoneContent content, int offset, int size, LinphoneBuffer bufferToFill) {
+ if (mUploadingImageStream != null && size > 0) {
+ byte[] data = new byte[size];
+ int read = mUploadingImageStream.read(data, 0, size);
+ if (read > 0) {
+ bufferToFill.setContent(data);
+ bufferToFill.setSize(read);
+ } else {
+ Log.e("Error, upload task asking for more bytes(" + size + ") than available (" + mUploadingImageStream.available() + ")");
+ }
+ }
}
-
- enum ImageSize {
- SMALL,
- MEDIUM,
- LARGE,
- REAL;
+
+ @Override
+ public void onLinphoneChatMessageFileTransferProgressChanged(LinphoneChatMessage msg, LinphoneContent content, int offset, int total) {
+ progressBar.setProgress(offset * 100 / total);
}
}
diff --git a/src/org/linphone/ChatListFragment.java b/src/org/linphone/ChatListFragment.java
index 4f0a4a224..e6a8b7e8d 100644
--- a/src/org/linphone/ChatListFragment.java
+++ b/src/org/linphone/ChatListFragment.java
@@ -17,13 +17,27 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.OutputStream;
import java.util.List;
import org.linphone.core.LinphoneAddress;
+import org.linphone.core.LinphoneChatMessage;
+import org.linphone.core.LinphoneChatRoom;
+import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.mediastream.Log;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager.NameNotFoundException;
+import android.graphics.Bitmap;
+import android.os.AsyncTask;
import android.os.Bundle;
-import android.os.Handler;
+import android.os.Environment;
+import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.view.ContextMenu;
import android.view.ContextMenu.ContextMenuInfo;
@@ -45,8 +59,6 @@ import android.widget.TextView;
* @author Sylvain Berfini
*/
public class ChatListFragment extends Fragment implements OnClickListener, OnItemClickListener {
- private Handler mHandler = new Handler();
-
private LayoutInflater mInflater;
private List mConversations, mDrafts;
private ListView chatList;
@@ -54,6 +66,7 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
private ImageView clearFastChat;
private EditText fastNewChat;
private boolean isEditMode = false;
+ private boolean useLinphoneStorage;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -91,29 +104,75 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
} else {
noChatHistory.setVisibility(View.GONE);
chatList.setVisibility(View.VISIBLE);
- chatList.setAdapter(new ChatListAdapter());
+ chatList.setAdapter(new ChatListAdapter(useLinphoneStorage));
}
}
public void refresh() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- mConversations = LinphoneActivity.instance().getChatList();
- mDrafts = LinphoneActivity.instance().getDraftChatList();
- mConversations.removeAll(mDrafts);
- hideAndDisplayMessageIfNoChat();
- }
- });
+ mConversations = LinphoneActivity.instance().getChatList();
+ mDrafts = LinphoneActivity.instance().getDraftChatList();
+ mConversations.removeAll(mDrafts);
+ hideAndDisplayMessageIfNoChat();
+ }
+
+ private boolean isVersionUsingNewChatStorage() {
+ try {
+ Context context = LinphoneActivity.instance();
+ return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode >= 2200;
+ } catch (NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ return true;
}
@Override
public void onResume() {
super.onResume();
+ //Check if the is the first time we show the chat view since we use liblinphone chat storage
+ useLinphoneStorage = getResources().getBoolean(R.bool.use_linphone_chat_storage);
+ final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(LinphoneActivity.instance());
+ boolean updateNeeded = prefs.getBoolean(getString(R.string.pref_first_time_linphone_chat_storage), true);
+ updateNeeded = updateNeeded && !isVersionUsingNewChatStorage();
+ if (useLinphoneStorage && updateNeeded) {
+ AsyncTask task = new AsyncTask() {
+ private ProgressDialog pd;
+ @Override
+ protected void onPreExecute() {
+ pd = new ProgressDialog(LinphoneActivity.instance());
+ pd.setTitle(getString(R.string.wait));
+ pd.setMessage(getString(R.string.importing_messages));
+ pd.setCancelable(false);
+ pd.setIndeterminate(true);
+ pd.show();
+ }
+ @Override
+ protected Void doInBackground(Void... arg0) {
+ try {
+ if (importAndroidStoredMessagedIntoLibLinphoneStorage()) {
+ prefs.edit().putBoolean(getString(R.string.pref_first_time_linphone_chat_storage), false).commit();
+ LinphoneActivity.instance().getChatStorage().restartChatStorage();
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+ @Override
+ protected void onPostExecute(Void result) {
+ pd.dismiss();
+ }
+ };
+ task.execute((Void[])null);
+ }
+
if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().selectMenu(FragmentsAvailable.CHATLIST);
LinphoneActivity.instance().updateChatListFragment(this);
+
+ if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) {
+ LinphoneActivity.instance().hideStatusBar();
+ }
}
refresh();
@@ -198,8 +257,64 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
}
}
+ private boolean importAndroidStoredMessagedIntoLibLinphoneStorage() {
+ Log.w("Importing previous messages into new database...");
+ try {
+ ChatStorage db = LinphoneActivity.instance().getChatStorage();
+ List conversations = db.getChatList();
+ for (int j = conversations.size() - 1; j >= 0; j--) {
+ String correspondent = conversations.get(j);
+ LinphoneChatRoom room = LinphoneManager.getLc().getOrCreateChatRoom(correspondent);
+ for (ChatMessage message : db.getMessages(correspondent)) {
+ LinphoneChatMessage msg = room.createLinphoneChatMessage(message.getMessage(), message.getUrl(), message.getStatus(), Long.parseLong(message.getTimestamp()), true, message.isIncoming());
+ if (message.getImage() != null) {
+ String path = saveImageAsFile(message.getId(), message.getImage());
+ if (path != null)
+ msg.setExternalBodyUrl(path);
+ }
+ msg.store();
+ }
+ db.removeDiscussion(correspondent);
+ }
+ return true;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ return false;
+ }
+
+ private String saveImageAsFile(int id, Bitmap bm) {
+ try {
+ String path = Environment.getExternalStorageDirectory().toString();
+ if (!path.endsWith("/"))
+ path += "/";
+ path += "Pictures/";
+ File directory = new File(path);
+ directory.mkdirs();
+
+ String filename = getString(R.string.picture_name_format).replace("%s", String.valueOf(id));
+ File file = new File(path, filename);
+
+ OutputStream fOut = null;
+ fOut = new FileOutputStream(file);
+
+ bm.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
+ fOut.flush();
+ fOut.close();
+
+ return path + filename;
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return null;
+ }
+
class ChatListAdapter extends BaseAdapter {
- ChatListAdapter() {
+ private boolean useNativeAPI;
+
+ ChatListAdapter(boolean useNativeAPI) {
+ this.useNativeAPI = useNativeAPI;
}
public int getCount() {
@@ -234,39 +349,57 @@ public class ChatListFragment extends Fragment implements OnClickListener, OnIte
view.setTag(contact);
int unreadMessagesCount = LinphoneActivity.instance().getChatStorage().getUnreadMessageCount(contact);
- LinphoneAddress address = LinphoneCoreFactory.instance().createLinphoneAddress(contact);
- LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, view.getContext().getContentResolver());
+ LinphoneAddress address;
+ try {
+ address = LinphoneCoreFactory.instance().createLinphoneAddress(contact);
+ } catch (LinphoneCoreException e) {
+ Log.e("Chat view cannot parse address",e);
+ return view;
+ }
+ Contact lContact = ContactsManager.getInstance().findContactWithAddress(getActivity().getContentResolver(), address);
- List messages = LinphoneActivity.instance().getChatMessages(contact);
- if (messages != null && messages.size() > 0) {
- int iterator = messages.size() - 1;
- ChatMessage lastMessage = null;
-
- while (iterator >= 0) {
- lastMessage = messages.get(iterator);
- if (lastMessage.getMessage() == null) {
- iterator--;
- } else {
- iterator = -1;
+ String message = "";
+ if (useNativeAPI) {
+ LinphoneChatRoom chatRoom = LinphoneManager.getLc().getOrCreateChatRoom(contact);
+ LinphoneChatMessage[] history = chatRoom.getHistory(20);
+ if (history != null && history.length > 0) {
+ for (int i = history.length - 1; i >= 0; i--) {
+ LinphoneChatMessage msg = history[i];
+ if (msg.getText() != null && msg.getText().length() > 0 && msg.getFileTransferInformation() == null) {
+ message = msg.getText();
+ break;
+ }
}
}
-
- String message = "";
- message = (lastMessage == null || lastMessage.getMessage() == null) ? "" : lastMessage.getMessage();
- TextView lastMessageView = (TextView) view.findViewById(R.id.lastMessage);
- lastMessageView.setText(message);
+ } else {
+ List messages = LinphoneActivity.instance().getChatMessages(contact);
+ if (messages != null && messages.size() > 0) {
+ int iterator = messages.size() - 1;
+ ChatMessage lastMessage = null;
+
+ while (iterator >= 0) {
+ lastMessage = messages.get(iterator);
+ if (lastMessage.getMessage() == null) {
+ iterator--;
+ } else {
+ iterator = -1;
+ }
+ }
+ message = (lastMessage == null || lastMessage.getMessage() == null) ? "" : lastMessage.getMessage();
+ }
}
+ TextView lastMessageView = (TextView) view.findViewById(R.id.lastMessage);
+ lastMessageView.setText(message);
TextView sipUri = (TextView) view.findViewById(R.id.sipUri);
sipUri.setSelected(true); // For animation
-
- if (getResources().getBoolean(R.bool.only_display_username_if_unknown) && address.getDisplayName() != null && LinphoneUtils.isSipAddress(address.getDisplayName())) {
- address.setDisplayName(LinphoneUtils.getUsernameFromAddress(address.getDisplayName()));
- } else if (getResources().getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(contact)) {
- contact = LinphoneUtils.getUsernameFromAddress(contact);
- }
-
- sipUri.setText(address.getDisplayName() == null ? contact : address.getDisplayName());
+
+ if (getResources().getBoolean(R.bool.only_display_username_if_unknown)) {
+ sipUri.setText(lContact == null ? address.getUserName() : lContact.getName());
+ } else {
+ sipUri.setText(lContact == null ? address.asStringUriOnly() : lContact.getName());
+ }
+
if (isDraft) {
view.findViewById(R.id.draft).setVisibility(View.VISIBLE);
}
diff --git a/src/org/linphone/ChatMessage.java b/src/org/linphone/ChatMessage.java
index eb45e3b4c..b0c59c8cb 100644
--- a/src/org/linphone/ChatMessage.java
+++ b/src/org/linphone/ChatMessage.java
@@ -47,6 +47,17 @@ public class ChatMessage {
this.isRead = read;
}
+ public ChatMessage(int id, String message, Bitmap image, String timestamp, boolean incoming, int status, boolean read) {
+ super();
+ this.id = id;
+ this.message = message;
+ this.timestamp = timestamp;
+ this.incoming = incoming;
+ this.status = status;
+ this.image = image;
+ this.isRead = read;
+ }
+
public int getId() {
return id;
}
@@ -98,4 +109,8 @@ public class ChatMessage {
public void setUrl(String url) {
this.url = url;
}
+
+ public String toString() {
+ return this.id + " : " + this.message + " (" + this.url + ") @ " + this.timestamp + ", read= " + this.isRead + ", incoming= " + this.incoming + ", status = " + this.status;
+ }
}
diff --git a/src/org/linphone/ChatStorage.java b/src/org/linphone/ChatStorage.java
index e8bd64de0..259aa05f9 100644
--- a/src/org/linphone/ChatStorage.java
+++ b/src/org/linphone/ChatStorage.java
@@ -19,17 +19,25 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
import java.io.ByteArrayOutputStream;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
import java.util.List;
import org.linphone.core.LinphoneChatMessage;
+import org.linphone.core.LinphoneChatRoom;
+import org.linphone.mediastream.Log;
import android.content.ContentValues;
import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.pm.PackageManager.NameNotFoundException;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
+import android.graphics.BitmapFactory;
+import android.preference.PreferenceManager;
/**
* @author Sylvain Berfini
@@ -39,22 +47,61 @@ public class ChatStorage {
private static final int OUTGOING = 0;
private static final int READ = 1;
private static final int NOT_READ = 0;
+
+ private static ChatStorage instance;
private Context context;
private SQLiteDatabase db;
+ private boolean useNativeAPI;
private static final String TABLE_NAME = "chat";
private static final String DRAFT_TABLE_NAME = "chat_draft";
- public ChatStorage(Context c) {
+ public synchronized static final ChatStorage getInstance() {
+ if (instance == null)
+ instance = new ChatStorage(LinphoneService.instance().getApplicationContext());
+ return instance;
+ }
+
+ public void restartChatStorage() {
+ if (instance != null)
+ instance.close();
+ instance = new ChatStorage(LinphoneService.instance().getApplicationContext());
+ }
+
+ private boolean isVersionUsingNewChatStorage() {
+ try {
+ return context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionCode >= 2200;
+ } catch (NameNotFoundException e) {
+ e.printStackTrace();
+ }
+ return true;
+ }
+
+ private ChatStorage(Context c) {
context = c;
- ChatHelper chatHelper = new ChatHelper(context);
- db = chatHelper.getWritableDatabase();
+ boolean useLinphoneStorage = c.getResources().getBoolean(R.bool.use_linphone_chat_storage);
+ SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(LinphoneService.instance());
+ boolean updateNeeded = prefs.getBoolean(c.getString(R.string.pref_first_time_linphone_chat_storage), !LinphonePreferences.instance().isFirstLaunch());
+ updateNeeded = updateNeeded && !isVersionUsingNewChatStorage();
+ useNativeAPI = useLinphoneStorage && !updateNeeded;
+ Log.d("Using native API: " + useNativeAPI);
+
+ if (!useNativeAPI) {
+ ChatHelper chatHelper = new ChatHelper(context);
+ db = chatHelper.getWritableDatabase();
+ }
}
-
+
public void close() {
- db.close();
+ if (!useNativeAPI) {
+ db.close();
+ }
}
-
+
public void updateMessageStatus(String to, String message, int status) {
+ if (useNativeAPI) {
+ return;
+ }
+
String[] whereArgs = { String.valueOf(OUTGOING), to, message };
Cursor c = db.query(TABLE_NAME, null, "direction LIKE ? AND remoteContact LIKE ? AND message LIKE ?", whereArgs, null, null, "id DESC");
@@ -67,21 +114,29 @@ public class ChatStorage {
}
}
c.close();
-
+
if (id != null && id.length() > 0) {
int intID = Integer.parseInt(id);
updateMessageStatus(to, intID, status);
}
}
-
+
public void updateMessageStatus(String to, int id, int status) {
+ if (useNativeAPI) {
+ return;
+ }
+
ContentValues values = new ContentValues();
values.put("status", status);
-
+
db.update(TABLE_NAME, values, "id LIKE " + id, null);
}
-
+
public int saveTextMessage(String from, String to, String message, long time) {
+ if (useNativeAPI) {
+ return -1;
+ }
+
ContentValues values = new ContentValues();
if (from.equals("")) {
values.put("localContact", from);
@@ -100,8 +155,12 @@ public class ChatStorage {
values.put("time", time);
return (int) db.insert(TABLE_NAME, null, values);
}
-
+
public int saveImageMessage(String from, String to, Bitmap image, String url, long time) {
+ if (useNativeAPI) {
+ return -1;
+ }
+
ContentValues values = new ContentValues();
if (from.equals("")) {
values.put("localContact", from);
@@ -117,48 +176,73 @@ public class ChatStorage {
values.put("status", LinphoneChatMessage.State.Idle.toInt());
}
values.put("url", url);
-
+
if (image != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(CompressFormat.JPEG, 100, baos);
values.put("image", baos.toByteArray());
}
-
+
values.put("time", time);
return (int) db.insert(TABLE_NAME, null, values);
}
-
+
public void saveImage(int id, Bitmap image) {
+ if (useNativeAPI) {
+ //Handled before this point
+ return;
+ }
+
if (image == null)
return;
-
+
ContentValues values = new ContentValues();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
image.compress(CompressFormat.JPEG, 100, baos);
values.put("image", baos.toByteArray());
-
+
db.update(TABLE_NAME, values, "id LIKE " + id, null);
}
-
+
public int saveDraft(String to, String message) {
+ if (useNativeAPI) {
+ //TODO
+ return -1;
+ }
+
ContentValues values = new ContentValues();
values.put("remoteContact", to);
values.put("message", message);
return (int) db.insert(DRAFT_TABLE_NAME, null, values);
}
-
+
public void updateDraft(String to, String message) {
+ if (useNativeAPI) {
+ //TODO
+ return;
+ }
+
ContentValues values = new ContentValues();
values.put("message", message);
-
+
db.update(DRAFT_TABLE_NAME, values, "remoteContact LIKE \"" + to + "\"", null);
}
-
+
public void deleteDraft(String to) {
+ if (useNativeAPI) {
+ //TODO
+ return;
+ }
+
db.delete(DRAFT_TABLE_NAME, "remoteContact LIKE \"" + to + "\"", null);
}
-
+
public String getDraft(String to) {
+ if (useNativeAPI) {
+ //TODO
+ return "";
+ }
+
Cursor c = db.query(DRAFT_TABLE_NAME, null, "remoteContact LIKE \"" + to + "\"", null, null, null, "id ASC");
String message = null;
@@ -170,121 +254,244 @@ public class ChatStorage {
}
}
c.close();
-
+
return message;
}
-
+
public List getDrafts() {
List drafts = new ArrayList();
- Cursor c = db.query(DRAFT_TABLE_NAME, null, null, null, null, null, "id ASC");
- while (c.moveToNext()) {
- try {
- String to = c.getString(c.getColumnIndex("remoteContact"));
- drafts.add(to);
- } catch (Exception e) {
- e.printStackTrace();
+ if (useNativeAPI) {
+ //TODO
+ } else {
+ Cursor c = db.query(DRAFT_TABLE_NAME, null, null, null, null, null, "id ASC");
+
+ while (c.moveToNext()) {
+ try {
+ String to = c.getString(c.getColumnIndex("remoteContact"));
+ drafts.add(to);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
}
+ c.close();
}
- c.close();
-
+
return drafts;
}
-
+
public List getMessages(String correspondent) {
List chatMessages = new ArrayList();
-
- Cursor c = db.query(TABLE_NAME, null, "remoteContact LIKE \"" + correspondent + "\"", null, null, null, "id ASC");
-
- while (c.moveToNext()) {
- try {
- String message, timestamp, url;
- int id = c.getInt(c.getColumnIndex("id"));
- int direction = c.getInt(c.getColumnIndex("direction"));
- message = c.getString(c.getColumnIndex("message"));
- timestamp = c.getString(c.getColumnIndex("time"));
- int status = c.getInt(c.getColumnIndex("status"));
- byte[] rawImage = c.getBlob(c.getColumnIndex("image"));
- int read = c.getInt(c.getColumnIndex("read"));
- url = c.getString(c.getColumnIndex("url"));
-
- ChatMessage chatMessage = new ChatMessage(id, message, rawImage, timestamp, direction == INCOMING, status, read == READ);
+
+ if (!useNativeAPI) {
+ Cursor c = db.query(TABLE_NAME, null, "remoteContact LIKE \"" + correspondent + "\"", null, null, null, "id ASC");
+
+ while (c.moveToNext()) {
+ try {
+ String message, timestamp, url;
+ int id = c.getInt(c.getColumnIndex("id"));
+ int direction = c.getInt(c.getColumnIndex("direction"));
+ message = c.getString(c.getColumnIndex("message"));
+ timestamp = c.getString(c.getColumnIndex("time"));
+ int status = c.getInt(c.getColumnIndex("status"));
+ byte[] rawImage = c.getBlob(c.getColumnIndex("image"));
+ int read = c.getInt(c.getColumnIndex("read"));
+ url = c.getString(c.getColumnIndex("url"));
+
+ ChatMessage chatMessage = new ChatMessage(id, message, rawImage, timestamp, direction == INCOMING, status, read == READ);
+ chatMessage.setUrl(url);
+ chatMessages.add(chatMessage);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ c.close();
+ } else {
+ LinphoneChatRoom room = LinphoneManager.getLc().getOrCreateChatRoom(correspondent);
+ LinphoneChatMessage[] history = room.getHistory();
+ for (int i = 0; i < history.length; i++) {
+ LinphoneChatMessage message = history[i];
+
+ Bitmap bm = null;
+ String url = message.getExternalBodyUrl();
+ if (url != null && !url.startsWith("http")) {
+ bm = BitmapFactory.decodeFile(url);
+ }
+ ChatMessage chatMessage = new ChatMessage(i+1, message.getText(), bm,
+ String.valueOf(message.getTime()), !message.isOutgoing(),
+ message.getStatus().toInt(), message.isRead());
chatMessage.setUrl(url);
chatMessages.add(chatMessage);
- } catch (Exception e) {
- e.printStackTrace();
}
}
- c.close();
-
+
return chatMessages;
}
- public String getTextMessageForId(int id) {
- Cursor c = db.query(TABLE_NAME, null, "id LIKE " + id, null, null, null, null);
-
+ public String getTextMessageForId(LinphoneChatRoom chatroom, int id) {
String message = null;
- if (c.moveToFirst()) {
- try {
- message = c.getString(c.getColumnIndex("message"));
- } catch (Exception e) {
- e.printStackTrace();
+
+ if (useNativeAPI) {
+ LinphoneChatMessage[] history = chatroom.getHistory();
+ for (LinphoneChatMessage msg : history) {
+ if (msg.getStorageId() == id) {
+ message = msg.getText();
+ break;
+ }
}
+ } else {
+ Cursor c = db.query(TABLE_NAME, null, "id LIKE " + id, null, null, null, null);
+
+ if (c.moveToFirst()) {
+ try {
+ message = c.getString(c.getColumnIndex("message"));
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ c.close();
}
- c.close();
-
+
return message;
}
-
- public void removeDiscussion(String correspondent) {
- db.delete(TABLE_NAME, "remoteContact LIKE \"" + correspondent + "\"", null);
- }
-
- public ArrayList getChatList() {
- ArrayList chatList = new ArrayList();
-
- Cursor c = db.query(TABLE_NAME, null, null, null, "remoteContact", null, "id DESC");
- while (c != null && c.moveToNext()) {
- try {
- String remoteContact = c.getString(c.getColumnIndex("remoteContact"));
- chatList.add(remoteContact);
- } catch (IllegalStateException ise) {
+
+ public LinphoneChatMessage getMessage(LinphoneChatRoom chatroom, int id) {
+ if (useNativeAPI) {
+ LinphoneChatMessage[] history = chatroom.getHistory();
+ for (LinphoneChatMessage msg : history) {
+ if (msg.getStorageId() == id) {
+ return msg;
+ }
}
}
- c.close();
-
+ return null;
+ }
+
+ public void removeDiscussion(String correspondent) {
+ if (useNativeAPI) {
+ LinphoneChatRoom chatroom = LinphoneManager.getLc().getOrCreateChatRoom(correspondent);
+ chatroom.deleteHistory();
+ } else {
+ db.delete(TABLE_NAME, "remoteContact LIKE \"" + correspondent + "\"", null);
+ }
+ }
+
+ public ArrayList getChatList() {
+ ArrayList chatList = new ArrayList();
+
+ if (useNativeAPI) {
+ LinphoneChatRoom[] chats = LinphoneManager.getLc().getChatRooms();
+ List rooms = new ArrayList();
+
+ for (LinphoneChatRoom chatroom : chats) {
+ if (chatroom.getHistory(1).length > 0) {
+ rooms.add(chatroom);
+ }
+ }
+
+ if (rooms.size() > 1) {
+ Collections.sort(rooms, new Comparator() {
+ @Override
+ public int compare(LinphoneChatRoom a, LinphoneChatRoom b) {
+ LinphoneChatMessage[] messagesA = a.getHistory(1);
+ LinphoneChatMessage[] messagesB = b.getHistory(1);
+ long atime = messagesA[0].getTime();
+ long btime = messagesB[0].getTime();
+
+ if (atime > btime)
+ return -1;
+ else if (btime > atime)
+ return 1;
+ else
+ return 0;
+ }
+ });
+ }
+
+ for (LinphoneChatRoom chatroom : rooms) {
+ chatList.add(chatroom.getPeerAddress().asStringUriOnly());
+ }
+ } else {
+ Cursor c = db.query(TABLE_NAME, null, null, null, "remoteContact", null, "id DESC");
+ while (c != null && c.moveToNext()) {
+ try {
+ String remoteContact = c.getString(c.getColumnIndex("remoteContact"));
+ chatList.add(remoteContact);
+ } catch (IllegalStateException ise) {
+ }
+ }
+ c.close();
+ }
+
return chatList;
}
- public void deleteMessage(int id) {
- db.delete(TABLE_NAME, "id LIKE " + id, null);
+ public void deleteMessage(LinphoneChatRoom chatroom, int id) {
+ if (useNativeAPI) {
+ LinphoneChatMessage[] history = chatroom.getHistory();
+ for (LinphoneChatMessage message : history) {
+ if (message.getStorageId() == id) {
+ chatroom.deleteMessage(message);
+ break;
+ }
+ }
+ } else {
+ db.delete(TABLE_NAME, "id LIKE " + id, null);
+ }
}
-
+
public void markMessageAsRead(int id) {
- ContentValues values = new ContentValues();
- values.put("read", READ);
- db.update(TABLE_NAME, values, "id LIKE " + id, null);
+ if (!useNativeAPI) {
+ ContentValues values = new ContentValues();
+ values.put("read", READ);
+ db.update(TABLE_NAME, values, "id LIKE " + id, null);
+ }
}
-
+
+ public void markConversationAsRead(LinphoneChatRoom chatroom) {
+ if (useNativeAPI) {
+ chatroom.markAsRead();
+ }
+ }
+
public int getUnreadMessageCount() {
- Cursor c = db.query(TABLE_NAME, null, "read LIKE " + NOT_READ, null, null, null, null);
- int count = c.getCount();
- c.close();
+ int count;
+ if (!useNativeAPI) {
+ Cursor c = db.query(TABLE_NAME, null, "read LIKE " + NOT_READ, null, null, null, null);
+ count = c.getCount();
+ c.close();
+ } else {
+ count = 0;
+ LinphoneChatRoom[] chats = LinphoneManager.getLc().getChatRooms();
+ for (LinphoneChatRoom chatroom : chats) {
+ count += chatroom.getUnreadMessagesCount();
+ }
+ }
return count;
-
}
public int getUnreadMessageCount(String contact) {
- Cursor c = db.query(TABLE_NAME, null, "remoteContact LIKE \"" + contact + "\" AND read LIKE " + NOT_READ, null, null, null, null);
- int count = c.getCount();
- c.close();
+ int count;
+ if (!useNativeAPI) {
+ Cursor c = db.query(TABLE_NAME, null, "remoteContact LIKE \"" + contact + "\" AND read LIKE " + NOT_READ, null, null, null, null);
+ count = c.getCount();
+ c.close();
+ } else {
+ LinphoneChatRoom chatroom = LinphoneManager.getLc().getOrCreateChatRoom(contact);
+ count = chatroom.getUnreadMessagesCount();
+ }
return count;
}
public byte[] getRawImageFromMessage(int id) {
+ if (useNativeAPI) {
+ //Handled before this point
+ return null;
+ }
+
String[] columns = { "image" };
Cursor c = db.query(TABLE_NAME, columns, "id LIKE " + id + "", null, null, null, null);
-
+
if (c.moveToFirst()) {
byte[] rawImage = c.getBlob(c.getColumnIndex("image"));
c.close();
@@ -296,20 +503,20 @@ public class ChatStorage {
}
class ChatHelper extends SQLiteOpenHelper {
-
+
private static final int DATABASE_VERSION = 15;
private static final String DATABASE_NAME = "linphone-android";
-
+
ChatHelper(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
}
-
+
@Override
public void onCreate(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, localContact TEXT NOT NULL, remoteContact TEXT NOT NULL, direction INTEGER, message TEXT, image BLOB, url TEXT, time NUMERIC, read INTEGER, status INTEGER);");
db.execSQL("CREATE TABLE " + DRAFT_TABLE_NAME + " (id INTEGER PRIMARY KEY AUTOINCREMENT, remoteContact TEXT NOT NULL, message TEXT);");
}
-
+
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
db.execSQL("DROP TABLE IF EXISTS " + TABLE_NAME + ";");
@@ -317,4 +524,4 @@ public class ChatStorage {
onCreate(db);
}
}
-}
\ No newline at end of file
+}
diff --git a/src/org/linphone/Contact.java b/src/org/linphone/Contact.java
index 14d434808..ac9b04c4b 100644
--- a/src/org/linphone/Contact.java
+++ b/src/org/linphone/Contact.java
@@ -22,6 +22,7 @@ import java.util.ArrayList;
import java.util.List;
import org.linphone.compatibility.Compatibility;
+import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneFriend;
import android.content.ContentResolver;
@@ -37,39 +38,43 @@ public class Contact implements Serializable {
private String id;
private String name;
private transient Uri photoUri;
+ private transient Uri thumbnailUri;
private transient Bitmap photo;
- private List numerosOrAddresses;
- private LinphoneFriend friend;
+ private List numbersOrAddresses;
+ private boolean hasFriends;
public Contact(String id, String name) {
super();
this.id = id;
this.name = name;
this.photoUri = null;
+ this.thumbnailUri = null;
+ this.hasFriends = false;
}
- public Contact(String id, String name, Uri photo) {
+ public Contact(String id, String name, Uri photo, Uri thumbnail) {
super();
this.id = id;
this.name = name;
this.photoUri = photo;
+ this.thumbnailUri = thumbnail;
this.photo = null;
+ this.hasFriends = false;
}
- public Contact(String id, String name, Uri photo, Bitmap picture) {
+ public Contact(String id, String name, Uri photo, Uri thumbnail, Bitmap picture) {
super();
this.id = id;
this.name = name;
this.photoUri = photo;
+ this.thumbnailUri = thumbnail;
this.photo = picture;
+ this.hasFriends = false;
}
-
- public void setFriend(LinphoneFriend friend) {
- this.friend = friend;
- }
-
- public LinphoneFriend getFriend() {
- return friend;
+
+
+ public boolean hasFriends() {
+ return hasFriends;
}
public String getID() {
@@ -83,19 +88,32 @@ public class Contact implements Serializable {
public Uri getPhotoUri() {
return photoUri;
}
+
+ public Uri getThumbnailUri() {
+ return thumbnailUri;
+ }
public Bitmap getPhoto() {
return photo;
}
- public List getNumerosOrAddresses() {
- if (numerosOrAddresses == null)
- numerosOrAddresses = new ArrayList();
- return numerosOrAddresses;
+ public List getNumbersOrAddresses() {
+ if (numbersOrAddresses == null)
+ numbersOrAddresses = new ArrayList();
+ return numbersOrAddresses;
}
public void refresh(ContentResolver cr) {
- this.numerosOrAddresses = Compatibility.extractContactNumbersAndAddresses(id, cr);
+ this.numbersOrAddresses = Compatibility.extractContactNumbersAndAddresses(id, cr);
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if(lc != null && lc.getFriendList() != null) {
+ for (LinphoneFriend friend :lc.getFriendList()){
+ if (friend.getRefKey().equals(id)) {
+ hasFriends = true;
+ this.numbersOrAddresses.add(friend.getAddress().asStringUriOnly());
+ }
+ }
+ }
this.name = Compatibility.refreshContactName(cr, id);
}
}
diff --git a/src/org/linphone/ContactFragment.java b/src/org/linphone/ContactFragment.java
index a8d341709..cc07822f8 100644
--- a/src/org/linphone/ContactFragment.java
+++ b/src/org/linphone/ContactFragment.java
@@ -18,13 +18,21 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
import java.io.InputStream;
+import java.util.ArrayList;
import org.linphone.compatibility.Compatibility;
+import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneProxyConfig;
+import org.linphone.mediastream.Log;
import org.linphone.ui.AvatarWithShadow;
+import android.annotation.SuppressLint;
+import android.app.AlertDialog;
+import android.content.ContentProviderOperation;
+import android.content.DialogInterface;
import android.graphics.BitmapFactory;
import android.os.Bundle;
+import android.provider.ContactsContract;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
@@ -39,7 +47,7 @@ import android.widget.TextView;
*/
public class ContactFragment extends Fragment implements OnClickListener {
private Contact contact;
- private TextView editContact;
+ private TextView editContact, deleteContact;
private LayoutInflater inflater;
private View view;
private boolean displayChatAddressOnly = false;
@@ -47,16 +55,33 @@ public class ContactFragment extends Fragment implements OnClickListener {
private OnClickListener dialListener = new OnClickListener() {
@Override
public void onClick(View v) {
- if (LinphoneActivity.isInstanciated())
- LinphoneActivity.instance().setAddresGoToDialerAndCall(v.getTag().toString(), contact.getName(), contact.getPhotoUri());
+ if (LinphoneActivity.isInstanciated()) {
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ LinphoneProxyConfig lpc = lc.getDefaultProxyConfig();
+ String to;
+ if (lpc != null) {
+ String address = v.getTag().toString();
+ if (!address.contains("@")) {
+ to = lpc.normalizePhoneNumber(address);
+ } else {
+ to = v.getTag().toString();
+ }
+ } else {
+ to = v.getTag().toString();
+ }
+ LinphoneActivity.instance().setAddresGoToDialerAndCall(to, contact.getName(), contact.getPhotoUri());
+ }
+ }
}
};
private OnClickListener chatListener = new OnClickListener() {
@Override
public void onClick(View v) {
- if (LinphoneActivity.isInstanciated())
+ if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().displayChat(v.getTag().toString());
+ }
}
};
@@ -73,6 +98,9 @@ public class ContactFragment extends Fragment implements OnClickListener {
editContact = (TextView) view.findViewById(R.id.editContact);
editContact.setOnClickListener(this);
+ deleteContact = (TextView) view.findViewById(R.id.deleteContact);
+ deleteContact.setOnClickListener(this);
+
return view;
}
@@ -82,6 +110,7 @@ public class ContactFragment extends Fragment implements OnClickListener {
displayContact(inflater, view);
}
+ @SuppressLint("InflateParams")
private void displayContact(LayoutInflater inflater, View view) {
AvatarWithShadow contactPicture = (AvatarWithShadow) view.findViewById(R.id.contactPicture);
if (contact.getPhotoUri() != null) {
@@ -92,11 +121,12 @@ public class ContactFragment extends Fragment implements OnClickListener {
}
TextView contactName = (TextView) view.findViewById(R.id.contactName);
- contactName.setText(contact.getName());
+ contactName.setText(contact.getName());
+
TableLayout controls = (TableLayout) view.findViewById(R.id.controls);
controls.removeAllViews();
- for (String numberOrAddress : contact.getNumerosOrAddresses()) {
+ for (String numberOrAddress : contact.getNumbersOrAddresses()) {
View v = inflater.inflate(R.layout.contact_control_row, null);
String displayednumberOrAddress = numberOrAddress;
@@ -115,9 +145,10 @@ public class ContactFragment extends Fragment implements OnClickListener {
v.findViewById(R.id.dial).setVisibility(View.GONE);
}
- v.findViewById(R.id.chat).setOnClickListener(chatListener);
+ v.findViewById(R.id.start_chat).setOnClickListener(chatListener);
LinphoneProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig();
if (lpc != null) {
+ displayednumberOrAddress = lpc.normalizePhoneNumber(displayednumberOrAddress);
if (!displayednumberOrAddress.startsWith("sip:")) {
numberOrAddress = "sip:" + displayednumberOrAddress;
}
@@ -126,9 +157,9 @@ public class ContactFragment extends Fragment implements OnClickListener {
if (!numberOrAddress.contains("@")) {
tag = numberOrAddress + "@" + lpc.getDomain();
}
- v.findViewById(R.id.chat).setTag(tag);
+ v.findViewById(R.id.start_chat).setTag(tag);
} else {
- v.findViewById(R.id.chat).setTag(numberOrAddress);
+ v.findViewById(R.id.start_chat).setTag(numberOrAddress);
}
final String finalNumberOrAddress = numberOrAddress;
@@ -142,7 +173,7 @@ public class ContactFragment extends Fragment implements OnClickListener {
friend.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- if (LinphoneActivity.instance().newFriend(contact, finalNumberOrAddress)) {
+ if (ContactsManager.getInstance().createNewFriend(contact, finalNumberOrAddress)) {
displayContact(ContactFragment.this.inflater, ContactFragment.this.view);
}
}
@@ -152,7 +183,7 @@ public class ContactFragment extends Fragment implements OnClickListener {
friend.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
- if (LinphoneActivity.instance().removeFriend(contact, finalNumberOrAddress)) {
+ if (ContactsManager.getInstance().removeFriend(finalNumberOrAddress)) {
displayContact(ContactFragment.this.inflater, ContactFragment.this.view);
}
}
@@ -161,7 +192,7 @@ public class ContactFragment extends Fragment implements OnClickListener {
}
if (getResources().getBoolean(R.bool.disable_chat)) {
- v.findViewById(R.id.chat).setVisibility(View.GONE);
+ v.findViewById(R.id.start_chat).setVisibility(View.GONE);
}
controls.addView(v);
@@ -171,9 +202,15 @@ public class ContactFragment extends Fragment implements OnClickListener {
@Override
public void onResume() {
super.onResume();
+
if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().selectMenu(FragmentsAvailable.CONTACT);
+
+ if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) {
+ LinphoneActivity.instance().hideStatusBar();
+ }
}
+
contact.refresh(getActivity().getContentResolver());
if (contact.getName() == null || contact.getName().equals("")) {
//Contact has been deleted, return
@@ -188,6 +225,36 @@ public class ContactFragment extends Fragment implements OnClickListener {
if (id == R.id.editContact) {
LinphoneActivity.instance().editContact(contact);
+ } else if (id == R.id.deleteContact) {
+ AlertDialog.Builder alertDialog = new AlertDialog.Builder(getActivity());
+ alertDialog.setMessage(getString(R.string.delete_contact_dialog));
+ alertDialog.setPositiveButton(getString(R.string.button_ok),new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ deleteExistingContact();
+ ContactsManager.getInstance().removeContactFromLists(getActivity().getContentResolver(),contact);
+ LinphoneActivity.instance().displayContacts(false);
+ }
+ });
+ alertDialog.setNegativeButton(getString(R.string.button_cancel),null);
+ alertDialog.show();
}
}
+
+ private void deleteExistingContact() {
+ String select = ContactsContract.Data.CONTACT_ID + " = ?";
+ String[] args = new String[] { contact.getID() };
+
+ ArrayList ops = new ArrayList();
+ ops.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI)
+ .withSelection(select, args)
+ .build()
+ );
+
+ try {
+ getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
+ ContactsManager.getInstance().removeAllFriends(contact);
+ } catch (Exception e) {
+ Log.w(e.getMessage() + ":" + e.getStackTrace());
+ }
+ }
}
diff --git a/src/org/linphone/ContactHelper.java b/src/org/linphone/ContactHelper.java
deleted file mode 100644
index 82817a186..000000000
--- a/src/org/linphone/ContactHelper.java
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
-ContactHelper.java
-Copyright (C) 2011 Belledonne Communications, Grenoble, France
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-package org.linphone;
-
-import org.linphone.core.LinphoneAddress;
-import org.linphone.mediastream.Version;
-
-import android.content.ContentResolver;
-import android.content.ContentUris;
-import android.content.Intent;
-import android.database.Cursor;
-import android.net.Uri;
-import android.provider.ContactsContract.Contacts;
-import android.telephony.PhoneNumberUtils;
-import android.text.TextUtils;
-
-public final class ContactHelper {
- private String username;
- private String domain;
- private ContentResolver resolver;
-
- private Uri foundPhotoUri;
- public Uri getUri() {
- return foundPhotoUri;
- }
-
- private String displayName;
- public String getDisplayName() {
- return displayName;
- }
-
- private LinphoneAddress address;
- public ContactHelper(LinphoneAddress address, ContentResolver resolver) {
- username = address.getUserName();
- domain = address.getDomain();
- this.resolver = resolver;
- this.address = address;
- }
-
- public boolean query() {
- boolean succeeded;
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
- ContactHelperNew helper = new ContactHelperNew();
- succeeded = helper.queryNewContactAPI();
- } else {
- succeeded = queryOldContactAPI();
- }
- if (succeeded && !TextUtils.isEmpty(displayName)) {
- address.setDisplayName(displayName);
- }
- return succeeded;
- }
-
- public static Intent prepareEditContactIntent(int id) {
- Intent intent = new Intent(Intent.ACTION_EDIT, Contacts.CONTENT_URI);
- Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, id);
- intent.setData(contactUri);
-
- return intent;
- }
-
- public static boolean testPhotoUri(Cursor c) {
- if (c == null) return false;
- if (!c.moveToNext()) {
- return false;
- }
- byte[] data = c.getBlob(0);
- if (data == null) {
- // TODO: simplify all this stuff
- // which is here only to check that the
- // photoUri really points to some data.
- // Not retrieving the data now would be better.
- return false;
- }
- return true;
- }
-
- public static boolean testPhotoUriAndCloseCursor(Cursor c) {
- boolean valid = testPhotoUri(c);
- if (c != null) c.close();
- return valid;
- }
-
- public static boolean testPhotoUri(ContentResolver resolver, Uri photoUriToTest, String photoCol) {
- Cursor cursor = resolver.query(photoUriToTest, new String[]{photoCol}, null, null, null);
- return testPhotoUriAndCloseCursor(cursor);
- }
-
- // OLD API
- @SuppressWarnings("deprecation")
- private final boolean queryOldContactAPI() {
- String normalizedNumber = PhoneNumberUtils.getStrippedReversed(username);
- if (TextUtils.isEmpty(normalizedNumber)) {
- // non phone username
- return false;
- }
- String[] projection = {android.provider.Contacts.Phones.PERSON_ID, android.provider.Contacts.Phones.DISPLAY_NAME};
- String selection = android.provider.Contacts.Phones.NUMBER_KEY + "=" + normalizedNumber;
- Cursor c = resolver.query(android.provider.Contacts.Phones.CONTENT_URI, projection, selection, null, null);
- if (c == null) return false;
-
- while (c.moveToNext()) {
- long id = c.getLong(c.getColumnIndex(android.provider.Contacts.Phones.PERSON_ID));
- Uri personUri = ContentUris.withAppendedId(android.provider.Contacts.People.CONTENT_URI, id);
- Uri potentialPictureUri = Uri.withAppendedPath(personUri, android.provider.Contacts.Photos.CONTENT_DIRECTORY);
- boolean valid = testPhotoUri(resolver, potentialPictureUri, android.provider.Contacts.Photos.DATA);
- if (valid) {
- displayName = c.getString(c.getColumnIndex(android.provider.Contacts.Phones.DISPLAY_NAME));
- foundPhotoUri = personUri; // hack (not returning pictureUri as it crashes when reading from it)
- c.close();
- return true;
- }
- }
- c.close();
- return false;
- }
-
- // END OLD API
-
- // START NEW CONTACT API
-
- private class ContactHelperNew {
-
- private final boolean checkPhotosUris(ContentResolver resolver, Cursor c, String idCol, String nameCol) {
- if (c == null) return false;
- while (c.moveToNext()) {
- long id = c.getLong(c.getColumnIndex(idCol));
- Uri contactUri = ContentUris.withAppendedId(android.provider.ContactsContract.Contacts.CONTENT_URI, id);
- Uri photoUri = Uri.withAppendedPath(contactUri, android.provider.ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
- if (photoUri == null) {
- return false;
- }
- String[] projection = {android.provider.ContactsContract.CommonDataKinds.Photo.PHOTO};
- Cursor photoCursor = resolver.query(photoUri, projection, null, null, null);
- String maybeDisplayName = c.getString(c.getColumnIndex(nameCol));
- boolean isPhotoValid = testPhotoUriAndCloseCursor(photoCursor);
- if (isPhotoValid) {
- foundPhotoUri = photoUri;
- displayName = maybeDisplayName;
- return true;
- } else if (maybeDisplayName != null) {
- foundPhotoUri = null;
- displayName = maybeDisplayName;
- return true;
- }
- }
- c.close();
- return false;
- }
-
- private final boolean queryNewContactAPI() {
- String sipUri = username + "@" + domain;
-
- // Try first using sip field
- Uri uri = android.provider.ContactsContract.Data.CONTENT_URI;
- String[] projection = {
- android.provider.ContactsContract.Data.CONTACT_ID,
- android.provider.ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME};
-
- // Then using custom SIP field
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- String selection = new StringBuilder()
- .append(android.provider.ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS)
- .append(" = ? AND ")
- .append(android.provider.ContactsContract.Data.MIMETYPE)
- .append(" = '")
- .append(android.provider.ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
- .append("'")
- .toString();
- Cursor c = resolver.query(uri, projection, selection, new String[] {sipUri}, null);
- boolean valid = checkPhotosUris(resolver, c,
- android.provider.ContactsContract.Data.CONTACT_ID,
- android.provider.ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
- c.close();
- if (valid) return true;
- }
-
- String selection = new StringBuilder()
- .append(android.provider.ContactsContract.CommonDataKinds.Im.DATA).append(" = ? AND ")
- .append(android.provider.ContactsContract.Data.MIMETYPE)
- .append(" = '")
- .append(android.provider.ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
- .append("' AND lower(")
- .append(android.provider.ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL)
- .append(") = 'sip'").toString();
- Cursor c = resolver.query(uri, projection, selection, new String[] {sipUri}, null);
- boolean valid = checkPhotosUris(resolver, c,
- android.provider.ContactsContract.Data.CONTACT_ID,
- android.provider.ContactsContract.CommonDataKinds.Phone.DISPLAY_NAME);
- c.close();
- if (valid) return true;
-
- // Finally using phone number
- String normalizedNumber = PhoneNumberUtils.getStrippedReversed(username);
- if (TextUtils.isEmpty(normalizedNumber)) {
- // non phone username
- return false;
- }
- Uri lookupUri = Uri.withAppendedPath(android.provider.ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(username));
- projection = new String[]{
- android.provider.ContactsContract.PhoneLookup._ID,
- android.provider.ContactsContract.PhoneLookup.NUMBER,
- android.provider.ContactsContract.PhoneLookup.DISPLAY_NAME};
- c = resolver.query(lookupUri, projection, null, null, null);
- while (c != null && c.moveToNext()) {
- long id = c.getLong(c.getColumnIndex(android.provider.ContactsContract.PhoneLookup._ID));
- String enteredNumber = c.getString(c.getColumnIndex(android.provider.ContactsContract.PhoneLookup.NUMBER));
- if (!normalizedNumber.equals(PhoneNumberUtils.getStrippedReversed(enteredNumber))) {
- continue;
- }
-
- Uri contactUri = ContentUris.withAppendedId(android.provider.ContactsContract.Contacts.CONTENT_URI, id);
- Uri photoUri = Uri.withAppendedPath(contactUri, android.provider.ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
-// if (photoUri == null) {
-// continue;
-// }
- String[] photoProj = {android.provider.ContactsContract.CommonDataKinds.Photo.PHOTO};
- Cursor cursor = resolver.query(photoUri, photoProj, null, null, null);
- valid = testPhotoUriAndCloseCursor(cursor);
- displayName = c.getString(c.getColumnIndex(android.provider.ContactsContract.PhoneLookup.DISPLAY_NAME));
- if (valid) {
- foundPhotoUri = photoUri;
- } else {
- foundPhotoUri = null;
- }
- c.close();
- return true;
- }
- c.close();
- return false;
- }
- }
-}
\ No newline at end of file
diff --git a/src/org/linphone/ContactsFragment.java b/src/org/linphone/ContactsFragment.java
index b20d3a6ef..c8e0d4cf2 100644
--- a/src/org/linphone/ContactsFragment.java
+++ b/src/org/linphone/ContactsFragment.java
@@ -21,14 +21,17 @@ import java.util.List;
import org.linphone.compatibility.Compatibility;
import org.linphone.core.LinphoneFriend;
-import org.linphone.core.OnlineStatus;
+import org.linphone.core.PresenceActivityType;
+import org.linphone.mediastream.Log;
+import android.annotation.SuppressLint;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
-import android.os.Handler;
import android.support.v4.app.Fragment;
+import android.text.Editable;
+import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -37,6 +40,7 @@ import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AlphabetIndexer;
import android.widget.BaseAdapter;
+import android.widget.EditText;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
@@ -46,9 +50,8 @@ import android.widget.TextView;
/**
* @author Sylvain Berfini
*/
+@SuppressLint("DefaultLocale")
public class ContactsFragment extends Fragment implements OnClickListener, OnItemClickListener {
- private Handler mHandler = new Handler();
-
private LayoutInflater mInflater;
private ListView contactsList;
private TextView allContacts, linphoneContacts, newContact, noSipContact, noContact;
@@ -57,7 +60,20 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte
private AlphabetIndexer indexer;
private boolean editOnClick = false, editConsumed = false, onlyDisplayChatAddress = false;
private String sipAddressToAdd;
+ private ImageView clearSearchField;
+ private EditText searchField;
+ private Cursor searchCursor;
+
+ private static ContactsFragment instance;
+ static final boolean isInstanciated() {
+ return instance != null;
+ }
+
+ public static final ContactsFragment instance() {
+ return instance;
+ }
+
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
@@ -89,7 +105,30 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte
allContacts.setEnabled(onlyDisplayLinphoneContacts);
linphoneContacts.setEnabled(!allContacts.isEnabled());
+
+ clearSearchField = (ImageView) view.findViewById(R.id.clearSearchField);
+ clearSearchField.setOnClickListener(this);
+
+ searchField = (EditText) view.findViewById(R.id.searchField);
+ searchField.addTextChangedListener(new TextWatcher() {
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count,
+ int after) {
+
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ searchContacts(searchField.getText().toString());
+ }
+ });
+
return view;
}
@@ -99,47 +138,87 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte
if (id == R.id.allContacts) {
onlyDisplayLinphoneContacts = false;
- changeContactsAdapter();
+ if (searchField.getText().toString().length() > 0) {
+ searchContacts();
+ } else {
+ changeContactsAdapter();
+ }
}
else if (id == R.id.linphoneContacts) {
onlyDisplayLinphoneContacts = true;
- changeContactsAdapter();
-
+ if (searchField.getText().toString().length() > 0) {
+ searchContacts();
+ } else {
+ changeContactsAdapter();
+ }
}
else if (id == R.id.newContact) {
editConsumed = true;
LinphoneActivity.instance().addContact(null, sipAddressToAdd);
}
+ else if (id == R.id.clearSearchField) {
+ searchField.setText("");
+ }
+ }
+
+ private void searchContacts() {
+ searchContacts(searchField.getText().toString());
+ }
+
+ private void searchContacts(String search) {
+ if (search == null || search.length() == 0) {
+ changeContactsAdapter();
+ return;
+ }
+ changeContactsToggle();
+
+ if (searchCursor != null) {
+ searchCursor.close();
+ }
+
+ if (onlyDisplayLinphoneContacts) {
+ searchCursor = Compatibility.getSIPContactsCursor(getActivity().getContentResolver(), search, ContactsManager.getInstance().getContactsId());
+ indexer = new AlphabetIndexer(searchCursor, Compatibility.getCursorDisplayNameColumnIndex(searchCursor), " ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ contactsList.setAdapter(new ContactsListAdapter(null, searchCursor));
+ } else {
+ searchCursor = Compatibility.getContactsCursor(getActivity().getContentResolver(), search, ContactsManager.getInstance().getContactsId());
+ indexer = new AlphabetIndexer(searchCursor, Compatibility.getCursorDisplayNameColumnIndex(searchCursor), " ABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ contactsList.setAdapter(new ContactsListAdapter(null, searchCursor));
+ }
}
private void changeContactsAdapter() {
changeContactsToggle();
- Cursor allContactsCursor = LinphoneActivity.instance().getAllContactsCursor();
- Cursor sipContactsCursor = LinphoneActivity.instance().getSIPContactsCursor();
+ if (searchCursor != null) {
+ searchCursor.close();
+ }
+
+ Cursor allContactsCursor = ContactsManager.getInstance().getAllContactsCursor();
+ Cursor sipContactsCursor = ContactsManager.getInstance().getSIPContactsCursor();
noSipContact.setVisibility(View.GONE);
noContact.setVisibility(View.GONE);
contactsList.setVisibility(View.VISIBLE);
if (onlyDisplayLinphoneContacts) {
- if (sipContactsCursor.getCount() == 0) {
+ if (sipContactsCursor != null && sipContactsCursor.getCount() == 0) {
noSipContact.setVisibility(View.VISIBLE);
contactsList.setVisibility(View.GONE);
} else {
indexer = new AlphabetIndexer(sipContactsCursor, Compatibility.getCursorDisplayNameColumnIndex(sipContactsCursor), " ABCDEFGHIJKLMNOPQRSTUVWXYZ");
- contactsList.setAdapter(new ContactsListAdapter(LinphoneActivity.instance().getSIPContacts(), sipContactsCursor));
+ contactsList.setAdapter(new ContactsListAdapter(ContactsManager.getInstance().getSIPContacts(), sipContactsCursor));
}
} else {
- if (allContactsCursor.getCount() == 0) {
+ if (allContactsCursor != null && allContactsCursor.getCount() == 0) {
noContact.setVisibility(View.VISIBLE);
contactsList.setVisibility(View.GONE);
} else {
indexer = new AlphabetIndexer(allContactsCursor, Compatibility.getCursorDisplayNameColumnIndex(allContactsCursor), " ABCDEFGHIJKLMNOPQRSTUVWXYZ");
- contactsList.setAdapter(new ContactsListAdapter(LinphoneActivity.instance().getAllContacts(), allContactsCursor));
+ contactsList.setAdapter(new ContactsListAdapter(ContactsManager.getInstance().getAllContacts(), allContactsCursor));
}
}
- LinphoneActivity.instance().setLinphoneContactsPrefered(onlyDisplayLinphoneContacts);
+ ContactsManager.getInstance().setLinphoneContactsPrefered(onlyDisplayLinphoneContacts);
}
private void changeContactsToggle() {
@@ -166,6 +245,7 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte
@Override
public void onResume() {
+ instance = this;
super.onResume();
if (editConsumed) {
@@ -175,20 +255,32 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte
if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().selectMenu(FragmentsAvailable.CONTACTS);
- onlyDisplayLinphoneContacts = LinphoneActivity.instance().isLinphoneContactsPrefered();
+ onlyDisplayLinphoneContacts = ContactsManager.getInstance().isLinphoneContactsPrefered();
+
+ if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) {
+ LinphoneActivity.instance().hideStatusBar();
+ }
}
invalidate();
}
+ @Override
+ public void onPause() {
+ instance = null;
+ if (searchCursor != null) {
+ searchCursor.close();
+ }
+ super.onPause();
+ }
+
public void invalidate() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- changeContactsAdapter();
- contactsList.setSelectionFromTop(lastKnownPosition, 0);
- }
- });
+ if (searchField != null && searchField.getText().toString().length() > 0) {
+ searchContacts(searchField.getText().toString());
+ } else {
+ changeContactsAdapter();
+ }
+ contactsList.setSelectionFromTop(lastKnownPosition, 0);
}
class ContactsListAdapter extends BaseAdapter implements SectionIndexer {
@@ -201,8 +293,8 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte
contacts = contactsList;
cursor = c;
- margin = LinphoneUtils.pixelsToDpi(getResources(), 10);
- bitmapUnknown = BitmapFactory.decodeResource(getResources(), R.drawable.unknown_small);
+ margin = LinphoneUtils.pixelsToDpi(LinphoneActivity.instance().getResources(), 10);
+ bitmapUnknown = BitmapFactory.decodeResource(LinphoneActivity.instance().getResources(), R.drawable.unknown_small);
}
public int getCount() {
@@ -210,7 +302,7 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte
}
public Object getItem(int position) {
- if (position >= contacts.size()) {
+ if (contacts == null || position >= contacts.size()) {
return Compatibility.getContact(getActivity().getContentResolver(), cursor, position);
} else {
return contacts.get(position);
@@ -258,16 +350,17 @@ public class ContactsFragment extends Fragment implements OnClickListener, OnIte
}
ImageView friendStatus = (ImageView) view.findViewById(R.id.friendStatus);
- LinphoneFriend friend = contact.getFriend();
- if (!LinphoneActivity.instance().isContactPresenceDisabled() && friend != null) {
+ LinphoneFriend[] friends = LinphoneManager.getLc().getFriendList();
+ if (!ContactsManager.getInstance().isContactPresenceDisabled() && friends != null) {
friendStatus.setVisibility(View.VISIBLE);
- if (friend.getStatus() == OnlineStatus.Online) {
+ PresenceActivityType presenceActivity = friends[0].getPresenceModel().getActivity().getType();
+ if (presenceActivity == PresenceActivityType.Online) {
friendStatus.setImageResource(R.drawable.led_connected);
- } else if (friend.getStatus() == OnlineStatus.Busy || friend.getStatus() == OnlineStatus.DoNotDisturb) {
+ } else if (presenceActivity == PresenceActivityType.Busy) {
friendStatus.setImageResource(R.drawable.led_error);
- } else if (friend.getStatus() == OnlineStatus.Away || friend.getStatus() == OnlineStatus.BeRightBack) {
+ } else if (presenceActivity == PresenceActivityType.Away) {
friendStatus.setImageResource(R.drawable.led_inprogress);
- } else if (friend.getStatus() == OnlineStatus.Offline) {
+ } else if (presenceActivity == PresenceActivityType.Offline) {
friendStatus.setImageResource(R.drawable.led_disconnected);
} else {
friendStatus.setImageResource(R.drawable.call_quality_indicator_0);
diff --git a/src/org/linphone/ContactsManager.java b/src/org/linphone/ContactsManager.java
new file mode 100644
index 000000000..6bd632f84
--- /dev/null
+++ b/src/org/linphone/ContactsManager.java
@@ -0,0 +1,626 @@
+package org.linphone;
+/*
+CallManager.java
+Copyright (C) 2015 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import android.accounts.Account;
+import android.accounts.AccountManager;
+import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
+import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
+import android.provider.ContactsContract;
+
+import org.linphone.compatibility.Compatibility;
+import org.linphone.core.LinphoneAddress;
+import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneCoreException;
+import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.core.LinphoneFriend;
+import org.linphone.core.LinphoneProxyConfig;
+import org.linphone.mediastream.Log;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class ContactsManager {
+ private static ContactsManager instance;
+ private List contactList, sipContactList;
+ private Cursor contactCursor, sipContactCursor;
+ private Account mAccount;
+ private boolean preferLinphoneContacts = false, isContactPresenceDisabled = true;
+ private ContentResolver contentResolver;
+ private Context context;
+
+ private ContactsManager() {}
+
+ public static final synchronized ContactsManager getInstance() {
+ if (instance == null) instance = new ContactsManager();
+ return instance;
+ }
+
+ public List getAllContacts() {
+ return contactList;
+ }
+
+ public List getSIPContacts() {
+ return sipContactList;
+ }
+
+ public Cursor getAllContactsCursor() {
+ return contactCursor;
+ }
+
+ public Cursor getSIPContactsCursor() {
+ return sipContactCursor;
+ }
+
+ public void setLinphoneContactsPrefered(boolean isPrefered) {
+ preferLinphoneContacts = isPrefered;
+ }
+
+ public boolean isLinphoneContactsPrefered() {
+ return preferLinphoneContacts;
+ }
+
+ public boolean isContactPresenceDisabled() {
+ return isContactPresenceDisabled;
+ }
+
+ public void initializeContactManager(Context context, ContentResolver contentResolver){
+ this.context = context;
+ this.contentResolver = contentResolver;
+ }
+
+ public void initializeSyncAccount(Context context, ContentResolver contentResolver) {
+ initializeContactManager(context,contentResolver);
+ Account newAccount = new Account(context.getString(R.string.sync_account_name), context.getString(R.string.sync_account_type));
+ AccountManager accountManager = (AccountManager) context.getSystemService(context.ACCOUNT_SERVICE);
+ accountManager.addAccountExplicitly(newAccount, null, null);
+ mAccount = newAccount;
+ }
+
+ public String getDisplayName(String firstName, String lastName) {
+ String displayName = null;
+ if (firstName.length() > 0 && lastName.length() > 0)
+ displayName = firstName + " " + lastName;
+ else if (firstName.length() > 0)
+ displayName = firstName;
+ else if (lastName.length() > 0)
+ displayName = lastName.toString();
+ return displayName;
+ }
+
+ //Contacts
+ public void createNewContact(ArrayList ops, String firstName, String lastName) {
+ int contactID = 0;
+
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
+ .withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
+ .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, null)
+ .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, null)
+ .build()
+ );
+
+ if (getDisplayName(firstName, lastName) != null) {
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, contactID)
+ .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, firstName)
+ .withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, lastName)
+ .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, getDisplayName(firstName, lastName))
+ .build()
+ );
+ }
+ }
+
+ public void updateExistingContact(ArrayList ops, Contact contact, String firstName, String lastName) {
+ if (getDisplayName(firstName, lastName) != null) {
+ String select = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'";
+ String[] args = new String[]{String.valueOf(contact.getID())};
+
+ ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
+ .withSelection(select, args)
+ .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, firstName)
+ .withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, lastName)
+ .build()
+ );
+ }
+ }
+
+//Manage Linphone Friend if we cannot use Sip address
+ public boolean createNewFriend(Contact contact, String sipUri) {
+ if (!sipUri.startsWith("sip:")) {
+ sipUri = "sip:" + sipUri;
+ }
+
+ LinphoneFriend friend = LinphoneCoreFactory.instance().createLinphoneFriend(sipUri);
+ if (friend != null) {
+ friend.edit();
+ friend.enableSubscribes(false);
+ friend.setRefKey(contact.getID());
+ friend.done();
+ try {
+ LinphoneManager.getLcIfManagerNotDestroyedOrNull().addFriend(friend);
+ return true;
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ return false;
+ }
+ } else {
+ return false;
+ }
+ }
+
+ public void updateFriend(String oldSipUri, String newSipUri) {
+ if (!newSipUri.startsWith("sip:")) {
+ newSipUri = "sip:" + newSipUri;
+ }
+
+ if (!oldSipUri.startsWith("sip:")) {
+ oldSipUri = "sip:" + oldSipUri;
+ }
+
+ LinphoneFriend friend = LinphoneManager.getLcIfManagerNotDestroyedOrNull().findFriendByAddress(oldSipUri);
+ if (friend != null) {
+ friend.edit();
+ try {
+ friend.setAddress(LinphoneCoreFactory.instance().createLinphoneAddress(newSipUri));
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+ friend.done();
+ }
+ }
+
+ public boolean removeFriend(String sipUri) {
+ if (!sipUri.startsWith("sip:")) {
+ sipUri = "sip:" + sipUri;
+ }
+
+ LinphoneFriend friend = LinphoneManager.getLcIfManagerNotDestroyedOrNull().findFriendByAddress(sipUri);
+ if (friend != null) {
+ LinphoneManager.getLcIfManagerNotDestroyedOrNull().removeFriend(friend);
+ return true;
+ }
+ return false;
+ }
+
+ public void removeAllFriends(Contact contact) {
+ for (LinphoneFriend friend : LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList()) {
+ if (friend.getRefKey().equals(contact.getID())) {
+ LinphoneManager.getLcIfManagerNotDestroyedOrNull().removeFriend(friend);
+ }
+ }
+ }
+
+ public Contact findContactWithDisplayName(String displayName) {
+ String[] projection = {ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME};
+ String selection = new StringBuilder()
+ .append(ContactsContract.Data.DISPLAY_NAME)
+ .append(" = ?").toString();
+
+ Cursor c = contentResolver.query(ContactsContract.Data.CONTENT_URI, projection, selection,
+ new String[]{displayName}, null);
+ if (c != null) {
+ if (c.moveToFirst()) {
+ Contact contact = Compatibility.getContact(contentResolver, c, c.getPosition());
+ c.close();
+
+ if (contact != null) {
+ return contact;
+ } else {
+ return null;
+ }
+ }
+ c.close();
+ }
+ return null;
+ }
+
+ public Contact getContact(String id, ContentResolver contentResolver){
+ String[] projection = {ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME};
+ String selection = new StringBuilder()
+ .append(ContactsContract.Data.CONTACT_ID)
+ .append(" = ?").toString();
+
+ Cursor c = contentResolver.query(ContactsContract.Data.CONTENT_URI, projection, selection, new String[]{id}, null);
+ if(c!=null){
+ if (c.moveToFirst()) {
+ Contact contact = Compatibility.getContact(contentResolver, c, c.getPosition());
+ c.close();
+
+ if (contact != null) {
+ return contact;
+ } else {
+ return null;
+ }
+ }
+ c.close();
+ }
+ return null;
+ }
+
+ public List getContactsId(){
+ List ids = new ArrayList();
+ if(LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList() == null) return null;
+ for(LinphoneFriend friend : LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList()) {
+ friend.edit();
+ friend.enableSubscribes(false);
+ friend.done();
+ if(!ids.contains(friend.getRefKey())){
+ ids.add(friend.getRefKey());
+ }
+ }
+
+ return ids;
+ }
+//End linphone Friend
+
+ public boolean removeContactTagIsNeeded(Contact contact){
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ LinphoneProxyConfig lpc = lc.createProxyConfig();
+ contact.refresh(contentResolver);
+ for (String address : contact.getNumbersOrAddresses()) {
+ if (!lpc.isPhoneNumber(address)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+ public void removeLinphoneContactTag(Contact contact){
+ ArrayList ops = new ArrayList();
+ String select = ContactsContract.RawContacts._ID + " = ?";
+ String[] args = new String[] { findRawLinphoneContactID(contact.getID()) };
+
+
+ ops.add(ContentProviderOperation.newDelete(ContactsContract.RawContacts.CONTENT_URI)
+ .withSelection(select, args)
+ .build()
+ );
+
+ try {
+ contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+ } catch (Exception e) {
+ Log.w(e.getMessage() + ":" + e.getStackTrace());
+ }
+ }
+
+ private Contact checkPhoneQueryResult(ContentResolver contentResolver, Cursor c, String columnPhone, String columnId, String username) {
+ boolean contactFound = false;
+
+ if (c != null) {
+ while (!contactFound && c.moveToNext()) {
+ String phone = c.getString(c.getColumnIndex(columnPhone));
+ if (phone.equals(username)) {
+ contactFound = true;
+ } else {
+ String normalizedUsername = null;
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ LinphoneProxyConfig lpc = lc.getDefaultProxyConfig();
+ if (lpc != null) {
+ normalizedUsername = lpc.normalizePhoneNumber(phone);
+ }
+ }
+
+ if (normalizedUsername != null && normalizedUsername.equals(username)) {
+ contactFound = true;
+ }
+ }
+
+ if(contactFound){
+ Contact contact = getContact(c.getString(c.getColumnIndex(columnId)), contentResolver);
+ c.close();
+ return contact;
+ }
+ }
+ c.close();
+ }
+ return null;
+ }
+
+ public Contact findContactWithAddress(ContentResolver contentResolver, LinphoneAddress address){
+ String sipUri = address.asStringUriOnly();
+ if (sipUri.startsWith("sip:"))
+ sipUri = sipUri.substring(4);
+
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if(lc != null && lc.getFriendList() != null && LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList().length > 0) {
+ for (LinphoneFriend friend : LinphoneManager.getLcIfManagerNotDestroyedOrNull().getFriendList()) {
+ if (friend.getAddress().equals(address)) {
+ return getContact(friend.getRefKey(), contentResolver);
+ }
+ }
+ }
+
+ //Find Sip address
+ Contact contact;
+ String [] projection = new String[] {ContactsContract.Data.CONTACT_ID, ContactsContract.Data.DISPLAY_NAME};
+ String selection = new StringBuilder()
+ .append(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS)
+ .append(" = ?").toString();
+
+ Cursor cur = contentResolver.query(ContactsContract.Data.CONTENT_URI, projection, selection,
+ new String[]{sipUri}, null);
+ if (cur != null) {
+ if (cur.moveToFirst()) {
+ contact = Compatibility.getContact(contentResolver, cur, cur.getPosition());
+ cur.close();
+
+ if (contact != null) {
+ return contact;
+ }
+ }
+ cur.close();
+ }
+
+ //Find number
+ Uri lookupUri = Uri.withAppendedPath(android.provider.ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(address.getUserName()));
+ projection = new String[] {ContactsContract.PhoneLookup._ID,ContactsContract.PhoneLookup.NUMBER,ContactsContract.PhoneLookup.DISPLAY_NAME };
+ Cursor c = contentResolver.query(lookupUri, projection, null, null, null);
+ contact = checkPhoneQueryResult(contentResolver, c, ContactsContract.PhoneLookup.NUMBER, ContactsContract.PhoneLookup._ID, address.getUserName());
+
+ if (contact != null) {
+ return contact;
+ }
+
+ return null;
+ }
+
+ public void removeContactFromLists(ContentResolver contentResolver, Contact contact) {
+ for (Contact c : contactList) {
+ if (c != null && c.getID().equals(contact.getID())) {
+ contactList.remove(c);
+ contactCursor = Compatibility.getContactsCursor(contentResolver,getContactsId());
+ break;
+ }
+ }
+
+ for (Contact c : sipContactList) {
+ if (c != null && c.getID().equals(contact.getID())) {
+ sipContactList.remove(c);
+ sipContactCursor = Compatibility.getSIPContactsCursor(contentResolver,getContactsId());
+ break;
+ }
+ }
+ }
+
+ public boolean isContactHasAddress(Contact contact, String address){
+ if(contact != null) {
+ contact.refresh(contentResolver);
+ if (contact.getNumbersOrAddresses().contains(address) || contact.getNumbersOrAddresses().contains("sip:"+ address)) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+ return false;
+ }
+
+ public String findRawContactID(ContentResolver cr, String contactID) {
+ Cursor c = cr.query(ContactsContract.RawContacts.CONTENT_URI,
+ new String[]{ContactsContract.RawContacts._ID},
+ ContactsContract.RawContacts.CONTACT_ID + "=?",
+ new String[]{contactID}, null);
+ if (c != null) {
+ String result = null;
+ if (c.moveToFirst()) {
+ result = c.getString(c.getColumnIndex(ContactsContract.RawContacts._ID));
+ }
+
+ c.close();
+ return result;
+ }
+ return null;
+ }
+
+ public String findRawLinphoneContactID(String contactID) {
+ String result = null;
+ String[] projection = { ContactsContract.RawContacts._ID };
+
+ String selection = ContactsContract.RawContacts.CONTACT_ID + "=? AND "
+ + ContactsContract.RawContacts.ACCOUNT_TYPE + "=? ";
+
+ Cursor c = contentResolver.query(ContactsContract.RawContacts.CONTENT_URI, projection,
+ selection, new String[]{contactID, "org.linphone"}, null);
+ if (c != null) {
+ if (c.moveToFirst()) {
+ result = c.getString(c.getColumnIndex(ContactsContract.RawContacts._ID));
+ }
+ }
+ c.close();
+ return result;
+ }
+
+ //Migrate old IM contacts into SIP addresses or linphoneFriends
+ public void migrateContacts() {
+ Cursor oldContacts = Compatibility.getImContactsCursor(contentResolver);
+ ArrayList ops = new ArrayList();
+
+ if(oldContacts != null){
+ for (int i = 0; i < oldContacts.getCount(); i++) {
+ Contact contact = Compatibility.getContact(contentResolver, oldContacts, i);
+ for (String address : Compatibility.extractContactImAddresses(contact.getID(), contentResolver)) {
+ if (LinphoneUtils.isSipAddress(address)) {
+ if (address.startsWith("sip:")) {
+ address = address.substring(4);
+ }
+
+ //Add new sip address
+ Compatibility.addSipAddressToContact(context, ops, address, findRawContactID(contentResolver, contact.getID()));
+ try {
+ contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ ops.clear();
+
+ contact.refresh(contentResolver);
+
+ //If address sip is correctly add, remove the im address
+ if(contact.getNumbersOrAddresses().contains(address)){
+ Compatibility.deleteImAddressFromContact(ops, address, contact.getID());
+ try {
+ contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ ops.clear();
+ } else {
+ //Add linphone friend instead
+ if(createNewFriend(contact, address)) {
+ contact.refresh(contentResolver);
+
+ //Remove IM address
+ Compatibility.deleteImAddressFromContact(ops, address, contact.getID());
+ try {
+ contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+ } catch (Exception e) {
+ e.printStackTrace();
+
+ }
+ }
+ }
+ }
+ ops.clear();
+ }
+ }
+ oldContacts.close();
+ }
+
+ }
+
+ public synchronized void prepareContactsInBackground() {
+ if (contactCursor != null) {
+ contactCursor.close();
+ }
+ if (sipContactCursor != null) {
+ sipContactCursor.close();
+ }
+
+ contactCursor = Compatibility.getContactsCursor(contentResolver, getContactsId());
+ sipContactCursor = Compatibility.getSIPContactsCursor(contentResolver, getContactsId());
+
+ Thread sipContactsHandler = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ if(sipContactCursor != null && sipContactCursor.getCount() > 0) {
+ for (int i = 0; i < sipContactCursor.getCount(); i++) {
+ Contact contact = Compatibility.getContact(contentResolver, sipContactCursor, i);
+ if (contact == null)
+ continue;
+
+ contact.refresh(contentResolver);
+ //Add tag to Linphone contact if it not existed
+ if (LinphoneActivity.isInstanciated() && LinphoneActivity.instance().getResources().getBoolean(R.bool.use_linphone_tag)) {
+ if (!isContactHasLinphoneTag(contact, contentResolver)) {
+ Compatibility.createLinphoneContactTag(context, contentResolver, contact,
+ findRawContactID(contentResolver, String.valueOf(contact.getID())));
+ }
+ }
+
+ sipContactList.add(contact);
+ }
+ }
+ if (contactCursor != null) {
+ for (int i = 0; i < contactCursor.getCount(); i++) {
+ Contact contact = Compatibility.getContact(contentResolver, contactCursor, i);
+ if (contact == null)
+ continue;
+
+ //Remove linphone contact tag if the contact has no sip address
+ if (LinphoneActivity.isInstanciated() && LinphoneActivity.instance().getResources().getBoolean(R.bool.use_linphone_tag)) {
+ if (removeContactTagIsNeeded(contact) && findRawLinphoneContactID(contact.getID()) != null) {
+ removeLinphoneContactTag(contact);
+ }
+ }
+ for (Contact c : sipContactList) {
+ if (c != null && c.getID().equals(contact.getID())) {
+ contact = c;
+ break;
+ }
+ }
+ contactList.add(contact);
+ }
+ }
+ }
+ });
+
+ contactList = new ArrayList();
+ sipContactList = new ArrayList();
+
+ sipContactsHandler.start();
+ }
+
+ public static String queryAddressOrNumber(ContentResolver resolver, Uri contactUri) {
+ // Phone Numbers
+ String[] projection = new String[]{ContactsContract.CommonDataKinds.Phone.NUMBER};
+ Cursor c = resolver.query(contactUri, projection, null, null, null);
+ if (c != null) {
+ while (c.moveToNext()) {
+ int numberIndex = c.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
+ String number = c.getString(numberIndex);
+ c.close();
+ return number;
+ }
+ }
+
+ // SIP addresses
+ projection = new String[] {ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS};
+ c = resolver.query(contactUri, projection, null, null, null);
+ if (c != null) {
+ while (c.moveToNext()) {
+ int numberIndex = c.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
+ String address = c.getString(numberIndex);
+ c.close();
+ return address;
+ }
+ c.close();
+ }
+ return null;
+ }
+
+ boolean isContactHasLinphoneTag(Contact contact, ContentResolver cr) {
+ String select = ContactsContract.Data.CONTACT_ID + " = ?";
+ String[] args = new String[] { contact.getID() };
+
+ String[] projection = new String[] {ContactsContract.Data.MIMETYPE };
+
+ Cursor cursor = cr.query(ContactsContract.Data.CONTENT_URI, projection, select, args, null);
+
+ if (cursor != null) {
+ while (cursor.moveToNext()) {
+ if(cursor.getString(cursor.getColumnIndex(ContactsContract.Data.MIMETYPE)).equals("vnd.android.cursor.item/org.linphone.profile")){
+ cursor.close();
+ return true;
+ }
+ }
+ }
+ cursor.close();
+ return false;
+ }
+
+}
diff --git a/src/org/linphone/DialerFragment.java b/src/org/linphone/DialerFragment.java
index af7c578f7..61319cc6e 100644
--- a/src/org/linphone/DialerFragment.java
+++ b/src/org/linphone/DialerFragment.java
@@ -24,7 +24,6 @@ import org.linphone.ui.AddressText;
import org.linphone.ui.CallButton;
import org.linphone.ui.EraseButton;
-import android.app.Activity;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
@@ -132,20 +131,14 @@ public class DialerFragment extends Fragment {
return instance;
}
- @Override
- public void onAttach(Activity activity) {
- super.onAttach(activity);
- if (LinphoneActivity.isInstanciated()) {
- LinphoneActivity.instance().updateDialerFragment(this);
- }
- }
-
@Override
public void onResume() {
super.onResume();
+
if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().selectMenu(FragmentsAvailable.DIALER);
LinphoneActivity.instance().updateDialerFragment(this);
+ LinphoneActivity.instance().showStatusBar();
}
if (shouldEmptyAddressField) {
@@ -187,6 +180,16 @@ public class DialerFragment extends Fragment {
mAddContact.setEnabled(LinphoneManager.getLc().getCallsNb() > 0 || !mAddress.getText().toString().equals(""));
}
+ public void displayTextInAddressBar(String numberOrSipAddress) {
+ shouldEmptyAddressField = false;
+ mAddress.setText(numberOrSipAddress);
+ }
+
+ public void newOutgoingCall(String numberOrSipAddress) {
+ displayTextInAddressBar(numberOrSipAddress);
+ LinphoneManager.getInstance().newOutgoingCall(mAddress);
+ }
+
public void newOutgoingCall(Intent intent) {
if (intent != null && intent.getData() != null) {
String scheme = intent.getData().getScheme();
@@ -195,8 +198,14 @@ public class DialerFragment extends Fragment {
} else if (scheme.startsWith("call") || scheme.startsWith("sip")) {
mAddress.setText(intent.getData().getSchemeSpecificPart());
} else {
- Log.e("Unknown scheme: ",scheme);
- mAddress.setText(intent.getData().getSchemeSpecificPart());
+ Uri contactUri = intent.getData();
+ String address = ContactsManager.getInstance().queryAddressOrNumber(LinphoneService.instance().getContentResolver(),contactUri);
+ if(address != null) {
+ mAddress.setText(address);
+ } else {
+ Log.e("Unknown scheme: ", scheme);
+ mAddress.setText(intent.getData().getSchemeSpecificPart());
+ }
}
mAddress.clearDisplayedName();
diff --git a/src/org/linphone/EditContactFragment.java b/src/org/linphone/EditContactFragment.java
index a358262d0..ca62beb4f 100644
--- a/src/org/linphone/EditContactFragment.java
+++ b/src/org/linphone/EditContactFragment.java
@@ -3,18 +3,17 @@ package org.linphone;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;
-
import org.linphone.compatibility.Compatibility;
+import org.linphone.core.LinphoneProxyConfig;
import org.linphone.mediastream.Version;
import org.linphone.ui.AvatarWithShadow;
-
+import android.annotation.SuppressLint;
import android.content.ContentProviderOperation;
import android.content.Context;
import android.database.Cursor;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.provider.ContactsContract;
-import android.provider.ContactsContract.RawContacts;
import android.support.v4.app.Fragment;
import android.text.Editable;
import android.text.InputType;
@@ -34,7 +33,6 @@ public class EditContactFragment extends Fragment {
private TextView ok;
private EditText firstName, lastName;
private LayoutInflater inflater;
- private View deleteContact;
private boolean isNewContact = true;
private Contact contact;
@@ -43,7 +41,8 @@ public class EditContactFragment extends Fragment {
private ArrayList ops;
private int firstSipAddressIndex = -1;
private String newSipOrNumberToAdd;
-
+ private ContactsManager contactsManager;
+
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
this.inflater = inflater;
@@ -54,11 +53,17 @@ public class EditContactFragment extends Fragment {
isNewContact = false;
contactID = Integer.parseInt(contact.getID());
contact.refresh(getActivity().getContentResolver());
- }
- if (getArguments().getString("NewSipAdress") != null) {
+ if (getArguments().getString("NewSipAdress") != null) {
+ newSipOrNumberToAdd = getArguments().getString("NewSipAdress");
+ }
+
+ } else if (getArguments().getString("NewSipAdress") != null) {
newSipOrNumberToAdd = getArguments().getString("NewSipAdress");
+ isNewContact = true;
}
}
+
+ contactsManager = ContactsManager.getInstance();
view = inflater.inflate(R.layout.edit_contact, container, false);
@@ -88,9 +93,9 @@ public class EditContactFragment extends Fragment {
return;
}
}
- createNewContact();
+ contactsManager.createNewContact(ops, firstName.getText().toString(), lastName.getText().toString());
} else {
- updateExistingContact();
+ contactsManager.updateExistingContact(ops, contact, firstName.getText().toString(), lastName.getText().toString());
}
for (NewOrUpdatedNumberOrAddress numberOrAddress : numbersAndAddresses) {
@@ -98,13 +103,18 @@ public class EditContactFragment extends Fragment {
}
try {
- getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
- LinphoneActivity.instance().prepareContactsInBackground();
+ getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
+ addLinphoneFriendIfNeeded();
+ removeLinphoneTagIfNeeded();
+ contactsManager.prepareContactsInBackground();
} catch (Exception e) {
e.printStackTrace();
}
-
+
getFragmentManager().popBackStackImmediate();
+
+ if(LinphoneActivity.instance().getResources().getBoolean(R.bool.isTablet))
+ ContactsFragment.instance().invalidate();
}
});
@@ -157,7 +167,7 @@ public class EditContactFragment extends Fragment {
public void afterTextChanged(Editable s) {
}
});
-
+
if (!isNewContact) {
String fn = findContactFirstName(String.valueOf(contactID));
String ln = findContactLastName(String.valueOf(contactID));
@@ -186,35 +196,33 @@ public class EditContactFragment extends Fragment {
return view;
}
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ if (LinphoneActivity.isInstanciated()) {
+ if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) {
+ LinphoneActivity.instance().hideStatusBar();
+ }
+ }
+ }
+
private void initNumbersFields(final TableLayout controls, final Contact contact) {
controls.removeAllViews();
numbersAndAddresses = new ArrayList();
if (contact != null) {
- for (String numberOrAddress : contact.getNumerosOrAddresses()) {
+ for (String numberOrAddress : contact.getNumbersOrAddresses()) {
View view = displayNumberOrAddress(controls, numberOrAddress);
if (view != null)
controls.addView(view);
}
}
if (newSipOrNumberToAdd != null) {
- View view = displayNumberOrAddress(controls, newSipOrNumberToAdd, true);
+ View view = displayNumberOrAddress(controls, newSipOrNumberToAdd);
if (view != null)
controls.addView(view);
}
-
- if (!isNewContact) {
- deleteContact = inflater.inflate(R.layout.contact_delete_button, null);
- deleteContact.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- deleteExistingContact();
- LinphoneActivity.instance().removeContactFromLists(contact);
- LinphoneActivity.instance().displayContacts(false);
- }
- });
- controls.addView(deleteContact, controls.getChildCount());
- }
// Add one for phone numbers, one for SIP address
if (!getResources().getBoolean(R.bool.hide_phone_numbers_in_editor)) {
@@ -231,8 +239,10 @@ public class EditContactFragment extends Fragment {
return displayNumberOrAddress(controls, numberOrAddress, false);
}
+ @SuppressLint("InflateParams")
private View displayNumberOrAddress(final TableLayout controls, String numberOrAddress, boolean forceAddNumber) {
- boolean isSip = numberOrAddress.startsWith("sip:");
+ boolean isSip = LinphoneUtils.isStrictSipAddress(numberOrAddress) || !LinphoneUtils.isNumberAddress(numberOrAddress);
+
if (isSip) {
if (firstSipAddressIndex == -1) {
firstSipAddressIndex = controls.getChildCount();
@@ -250,7 +260,11 @@ public class EditContactFragment extends Fragment {
if (forceAddNumber) {
tempNounoa = new NewOrUpdatedNumberOrAddress(isSip);
} else {
- tempNounoa = new NewOrUpdatedNumberOrAddress(numberOrAddress, isSip);
+ if(isNewContact || newSipOrNumberToAdd != null) {
+ tempNounoa = new NewOrUpdatedNumberOrAddress(isSip, numberOrAddress);
+ } else {
+ tempNounoa = new NewOrUpdatedNumberOrAddress(numberOrAddress, isSip);
+ }
}
final NewOrUpdatedNumberOrAddress nounoa = tempNounoa;
numbersAndAddresses.add(nounoa);
@@ -285,11 +299,13 @@ public class EditContactFragment extends Fragment {
nounoa.delete();
numbersAndAddresses.remove(nounoa);
view.setVisibility(View.GONE);
+
}
});
return view;
}
+ @SuppressLint("InflateParams")
private void addEmptyRowToAllowNewNumberOrAddress(final TableLayout controls, final boolean isSip) {
final View view = inflater.inflate(R.layout.contact_add_row, null);
@@ -348,87 +364,6 @@ public class EditContactFragment extends Fragment {
controls.addView(view);
}
}
- if (deleteContact != null) {
- // Move to the bottom the remove contact button
- controls.removeView(deleteContact);
- controls.addView(deleteContact, controls.getChildCount());
- }
- }
-
- private void createNewContact() {
- contactID = 0;
-
- ops.add(ContentProviderOperation.newInsert(RawContacts.CONTENT_URI)
- .withValue(RawContacts.ACCOUNT_TYPE, null)
- .withValue(RawContacts.ACCOUNT_NAME, null).build());
-
- if (getDisplayName() != null) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, contactID)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, firstName.getText().toString())
- .withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, lastName.getText().toString())
- .build()
- );
- }
- }
-
- private void updateExistingContact() {
- if (getDisplayName() != null) {
- String select = ContactsContract.Data.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE + "'" ;
- String[] args = new String[] { String.valueOf(contactID) };
-
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(select, args)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, firstName.getText().toString())
- .withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, lastName.getText().toString())
- .build()
- );
- }
- }
-
- private void deleteExistingContact() {
- String select = ContactsContract.Data.CONTACT_ID + "=?";
- String[] args = new String[] { String.valueOf(contactID) };
-
- ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
- .withSelection(select, args)
- .build()
- );
-
- try {
- getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- private String getDisplayName() {
- String displayName = null;
- if (firstName.getText().length() > 0 && lastName.getText().length() > 0)
- displayName = firstName.getText().toString() + " " + lastName.getText().toString();
- else if (firstName.getText().length() > 0)
- displayName = firstName.getText().toString();
- else if (lastName.getText().length() > 0)
- displayName = lastName.getText().toString();
- return displayName;
- }
-
- private String findRawContactID(String contactID) {
- Cursor c = getActivity().getContentResolver().query(RawContacts.CONTENT_URI,
- new String[]{RawContacts._ID},
- RawContacts.CONTACT_ID + "=?",
- new String[]{contactID}, null);
- if (c != null) {
- String result = null;
- if (c.moveToFirst()) {
- result = c.getString(c.getColumnIndex(RawContacts._ID));
- }
- c.close();
- return result;
- }
- return null;
}
private String findContactFirstName(String contactID) {
@@ -462,6 +397,43 @@ public class EditContactFragment extends Fragment {
}
return null;
}
+
+ private void addLinphoneFriendIfNeeded(){
+ for (NewOrUpdatedNumberOrAddress numberOrAddress : numbersAndAddresses) {
+ if(numberOrAddress.newNumberOrAddress != null && numberOrAddress.isSipAddress) {
+ if(isNewContact){
+ Contact c = contactsManager.findContactWithDisplayName(ContactsManager.getInstance().getDisplayName(firstName.getText().toString(), lastName.getText().toString()));
+ if (c != null && !contactsManager.isContactHasAddress(c, numberOrAddress.newNumberOrAddress)) {
+ contactsManager.createNewFriend(c, numberOrAddress.newNumberOrAddress);
+ }
+ } else {
+ if (!contactsManager.isContactHasAddress(contact, numberOrAddress.newNumberOrAddress)){
+ if (numberOrAddress.oldNumberOrAddress == null) {
+ contactsManager.createNewFriend(contact, numberOrAddress.newNumberOrAddress);
+ } else {
+ if (contact.hasFriends())
+ contactsManager.updateFriend(numberOrAddress.oldNumberOrAddress, numberOrAddress.newNumberOrAddress);
+ }
+ }
+ }
+ }
+ }
+ }
+
+ private void removeLinphoneTagIfNeeded(){
+ if(!isNewContact) {
+ boolean areAllSipFielsEmpty = true;
+ for (NewOrUpdatedNumberOrAddress nounoa : numbersAndAddresses) {
+ if (!nounoa.isSipAddress && (nounoa.oldNumberOrAddress != null && !nounoa.oldNumberOrAddress.equals("") || nounoa.newNumberOrAddress != null && !nounoa.newNumberOrAddress.equals(""))) {
+ areAllSipFielsEmpty = false;
+ break;
+ }
+ }
+ if (areAllSipFielsEmpty && contactsManager.findRawLinphoneContactID(contact.getID()) != null) {
+ contactsManager.removeLinphoneContactTag(contact);
+ }
+ }
+ }
class NewOrUpdatedNumberOrAddress {
private String oldNumberOrAddress;
@@ -486,6 +458,12 @@ public class EditContactFragment extends Fragment {
isSipAddress = isSip;
}
+ public NewOrUpdatedNumberOrAddress(boolean isSip, String newSip) {
+ oldNumberOrAddress = null;
+ newNumberOrAddress = newSip;
+ isSipAddress = isSip;
+ }
+
public void setNewNumberOrAddress(String newN) {
newNumberOrAddress = newN;
}
@@ -504,44 +482,78 @@ public class EditContactFragment extends Fragment {
}
public void delete() {
- if (isSipAddress) {
- Compatibility.deleteSipAddressFromContact(ops, oldNumberOrAddress, String.valueOf(contactID));
- } else {
- String select = ContactsContract.Data.CONTACT_ID + "=? AND "
- + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "' AND "
- + ContactsContract.CommonDataKinds.Phone.NUMBER + "=?";
- String[] args = new String[] { String.valueOf(contactID), oldNumberOrAddress };
-
- ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
- .withSelection(select, args)
- .build()
- );
+ if(contact != null) {
+ if (isSipAddress) {
+ if (contact.hasFriends()) {
+ ContactsManager.getInstance().removeFriend(oldNumberOrAddress);
+ } else {
+ Compatibility.deleteSipAddressFromContact(ops, oldNumberOrAddress, String.valueOf(contactID));
+ }
+ if (getResources().getBoolean(R.bool.use_linphone_tag)) {
+ Compatibility.deleteLinphoneContactTag(ops, oldNumberOrAddress, contactsManager.findRawLinphoneContactID(String.valueOf(contactID)));
+ }
+ } else {
+ String select = ContactsContract.Data.CONTACT_ID + "=? AND "
+ + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "' AND "
+ + ContactsContract.CommonDataKinds.Phone.NUMBER + "=?";
+ String[] args = new String[]{String.valueOf(contactID), oldNumberOrAddress};
+
+ ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
+ .withSelection(select, args)
+ .build()
+ );
+ }
}
}
private void addNewNumber() {
+ if (newNumberOrAddress == null || newNumberOrAddress.length() == 0) {
+ return;
+ }
+
if (isNewContact) {
if (isSipAddress) {
if (newNumberOrAddress.startsWith("sip:"))
newNumberOrAddress = newNumberOrAddress.substring(4);
+ if(!newNumberOrAddress.contains("@")) {
+ //Use default proxy config domain if it exists
+ LinphoneProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig();
+ if(lpc != null){
+ newNumberOrAddress = newNumberOrAddress + "@" + lpc.getDomain();
+ } else {
+ newNumberOrAddress = newNumberOrAddress + "@" + getResources().getString(R.string.default_domain);
+ }
+ }
Compatibility.addSipAddressToContact(getActivity(), ops, newNumberOrAddress);
} else {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, newNumberOrAddress)
.withValue(ContactsContract.CommonDataKinds.Phone.TYPE, ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM)
- .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, getString(R.string.addressbook_label))
+ .withValue(ContactsContract.CommonDataKinds.Phone.LABEL, getString(R.string.addressbook_label))
.build()
);
}
} else {
- String rawContactId = findRawContactID(String.valueOf(contactID));
-
+ String rawContactId = contactsManager.findRawContactID(getActivity().getContentResolver(),String.valueOf(contactID));
if (isSipAddress) {
if (newNumberOrAddress.startsWith("sip:"))
newNumberOrAddress = newNumberOrAddress.substring(4);
+ if(!newNumberOrAddress.contains("@")) {
+ //Use default proxy config domain if it exists
+ LinphoneProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig();
+ if(lpc != null){
+ newNumberOrAddress = newNumberOrAddress + "@" + lpc.getDomain();
+ } else {
+ newNumberOrAddress = newNumberOrAddress + "@" + getResources().getString(R.string.default_domain);
+ }
+ }
+
Compatibility.addSipAddressToContact(getActivity(), ops, newNumberOrAddress, rawContactId);
+ if (getResources().getBoolean(R.bool.use_linphone_tag)) {
+ Compatibility.addLinphoneContactTag(getActivity(), ops, newNumberOrAddress, contactsManager.findRawLinphoneContactID(String.valueOf(contactID)));
+ }
} else {
ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
.withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId)
@@ -556,10 +568,26 @@ public class EditContactFragment extends Fragment {
}
private void updateNumber() {
+ if (newNumberOrAddress == null || newNumberOrAddress.length() == 0) {
+ return;
+ }
+
if (isSipAddress) {
if (newNumberOrAddress.startsWith("sip:"))
newNumberOrAddress = newNumberOrAddress.substring(4);
+ if(!newNumberOrAddress.contains("@")) {
+ //Use default proxy config domain if it exists
+ LinphoneProxyConfig lpc = LinphoneManager.getLc().getDefaultProxyConfig();
+ if(lpc != null){
+ newNumberOrAddress = newNumberOrAddress + "@" + lpc.getDomain();
+ } else {
+ newNumberOrAddress = newNumberOrAddress + "@" + getResources().getString(R.string.default_domain);
+ }
+ }
Compatibility.updateSipAddressForContact(ops, oldNumberOrAddress, newNumberOrAddress, String.valueOf(contactID));
+ if (getResources().getBoolean(R.bool.use_linphone_tag)) {
+ Compatibility.updateLinphoneContactTag(getActivity(), ops, newNumberOrAddress, oldNumberOrAddress, contactsManager.findRawLinphoneContactID(String.valueOf(contactID)));
+ }
} else {
String select = ContactsContract.Data.CONTACT_ID + "=? AND "
+ ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE + "' AND "
@@ -575,4 +603,4 @@ public class EditContactFragment extends Fragment {
}
}
}
-}
+}
\ No newline at end of file
diff --git a/src/org/linphone/FragmentsAvailable.java b/src/org/linphone/FragmentsAvailable.java
index 1b6fdfa43..700586eac 100644
--- a/src/org/linphone/FragmentsAvailable.java
+++ b/src/org/linphone/FragmentsAvailable.java
@@ -35,10 +35,6 @@ public enum FragmentsAvailable {
SETTINGS,
CHATLIST,
CHAT;
-
- public boolean shouldAddToBackStack() {
- return true;
- }
public boolean shouldAnimate() {
return true;
@@ -68,9 +64,6 @@ public enum FragmentsAvailable {
case CHATLIST:
return DIALER.isRightOf(fragment) || fragment == DIALER;
- case CHAT:
- return CHATLIST.isRightOf(fragment) || fragment == CHATLIST;
-
case ABOUT_INSTEAD_OF_SETTINGS:
case SETTINGS:
return CHATLIST.isRightOf(fragment) || fragment == CHATLIST || fragment == FragmentsAvailable.ABOUT_INSTEAD_OF_CHAT;
@@ -79,6 +72,9 @@ public enum FragmentsAvailable {
case ACCOUNT_SETTINGS:
return SETTINGS.isRightOf(fragment) || fragment == SETTINGS;
+ case CHAT:
+ return CHATLIST.isRightOf(fragment) || fragment == CHATLIST;
+
default:
return false;
}
diff --git a/src/org/linphone/HistoryDetailFragment.java b/src/org/linphone/HistoryDetailFragment.java
index 8c0d42fbc..ceea76b21 100644
--- a/src/org/linphone/HistoryDetailFragment.java
+++ b/src/org/linphone/HistoryDetailFragment.java
@@ -21,7 +21,10 @@ import java.text.SimpleDateFormat;
import java.util.Calendar;
import org.linphone.core.LinphoneAddress;
+import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.mediastream.Log;
+import org.linphone.ui.AvatarWithShadow;
import android.annotation.SuppressLint;
import android.net.Uri;
@@ -40,6 +43,7 @@ import android.widget.TextView;
public class HistoryDetailFragment extends Fragment implements OnClickListener {
private ImageView dialBack, chat, addToContacts;
private View view;
+ private AvatarWithShadow contactPicture;
private TextView contactName, contactAddress, callDirection, time, date;
private String sipUri, displayName, pictureUri;
@@ -66,6 +70,8 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener {
addToContacts = (ImageView) view.findViewById(R.id.addToContacts);
addToContacts.setOnClickListener(this);
+ contactPicture = (AvatarWithShadow) view.findViewById(R.id.contactPicture);
+
contactName = (TextView) view.findViewById(R.id.contactName);
if (displayName == null && getResources().getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(sipUri)) {
displayName = LinphoneUtils.getUsernameFromAddress(sipUri);
@@ -103,13 +109,21 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener {
time.setText(callTime == null ? "" : callTime);
date.setText(timestampToHumanDate(callDate));
-
- LinphoneAddress lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri);
- LinphoneUtils.findUriPictureOfContactAndSetDisplayName(lAddress, view.getContext().getContentResolver());
- String displayName = lAddress.getDisplayName();
- if (displayName != null) {
- view.findViewById(R.id.addContactRow).setVisibility(View.GONE);
+
+ LinphoneAddress lAddress;
+ try {
+ lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri);
+ Contact contact = ContactsManager.getInstance().findContactWithAddress(getActivity().getContentResolver(), lAddress);
+ if (contact != null) {
+ LinphoneUtils.setImagePictureFromUri(view.getContext(), contactPicture.getView(),contact.getPhotoUri(), contact.getThumbnailUri(), R.drawable.unknown_small);
+ view.findViewById(R.id.addContactRow).setVisibility(View.GONE);
+ } else {
+ LinphoneUtils.setImagePictureFromUri(view.getContext(), contactPicture.getView(),null, null ,R.drawable.unknown_small);
+ }
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
}
+
}
public void changeDisplayedHistory(String sipUri, String displayName, String pictureUri, String status, String callTime, String callDate) {
@@ -126,8 +140,13 @@ public class HistoryDetailFragment extends Fragment implements OnClickListener {
@Override
public void onResume() {
super.onResume();
+
if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().selectMenu(FragmentsAvailable.HISTORY_DETAIL);
+
+ if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) {
+ LinphoneActivity.instance().hideStatusBar();
+ }
}
}
diff --git a/src/org/linphone/HistoryFragment.java b/src/org/linphone/HistoryFragment.java
index 5acf9f3b2..3a3b87ddc 100644
--- a/src/org/linphone/HistoryFragment.java
+++ b/src/org/linphone/HistoryFragment.java
@@ -30,7 +30,6 @@ import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
-import android.os.Handler;
import android.support.v4.app.Fragment;
import android.util.SparseArray;
import android.view.ContextMenu;
@@ -53,7 +52,6 @@ import android.widget.TextView;
* @author Sylvain Berfini
*/
public class HistoryFragment extends Fragment implements OnClickListener, OnChildClickListener, OnGroupClickListener {
- private Handler mHandler = new Handler();
private ExpandableListView historyList;
private LayoutInflater mInflater;
private TextView allCalls, missedCalls, edit, ok, deleteAll, noCallHistory, noMissedCallHistory;
@@ -115,8 +113,14 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnChil
@Override
public void onResume() {
super.onResume();
- if (LinphoneActivity.isInstanciated())
+
+ if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().selectMenu(FragmentsAvailable.HISTORY);
+
+ if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) {
+ LinphoneActivity.instance().hideStatusBar();
+ }
+ }
initLogsLists(Arrays.asList(LinphoneManager.getLc().getCallLogs()));
if (!hideHistoryListAndDisplayMessageIfEmpty()) {
@@ -158,16 +162,11 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnChil
}
private void expandAllGroups() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- for (int groupToExpand = 0; groupToExpand < historyList.getExpandableListAdapter().getGroupCount(); groupToExpand++) {
- if (!historyList.isGroupExpanded(groupToExpand)) {
- historyList.expandGroup(groupToExpand);
- }
- }
+ for (int groupToExpand = 0; groupToExpand < historyList.getExpandableListAdapter().getGroupCount(); groupToExpand++) {
+ if (!historyList.isGroupExpanded(groupToExpand)) {
+ historyList.expandGroup(groupToExpand);
}
- });
+ }
}
private String getCorrespondentDisplayName(LinphoneCallLog log) {
@@ -179,15 +178,16 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnChil
address = log.getTo();
}
- LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, getActivity().getContentResolver());
- displayName = address.getDisplayName();
+ Contact contact = ContactsManager.getInstance().findContactWithAddress(getActivity().getContentResolver(), address);
String sipUri = address.asStringUriOnly();
- if (displayName == null) {
+ if (contact == null) {
if (getResources().getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(sipUri)) {
- displayName = LinphoneUtils.getUsernameFromAddress(sipUri);
+ displayName = address.getUserName();
} else {
displayName = sipUri;
}
+ } else {
+ displayName = contact.getName();
}
return displayName;
@@ -390,8 +390,7 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnChil
address = log.getTo();
callDirection.setImageBitmap(outgoingCall);
}
-
- LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, view.getContext().getContentResolver());
+
String sipUri = address.asStringUriOnly();
dateAndTime.setText(log.getStartDate() + " " + log.getCallDuration());
view.setTag(sipUri);
@@ -456,8 +455,7 @@ public class HistoryFragment extends Fragment implements OnClickListener, OnChil
} else {
address = log.getTo();
}
-
- LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, view.getContext().getContentResolver());
+
String displayName = getCorrespondentDisplayName(log);
String sipUri = address.asStringUriOnly();
contact.setText(displayName + " (" + getChildrenCount(groupPosition) + ")");
diff --git a/src/org/linphone/HistorySimpleFragment.java b/src/org/linphone/HistorySimpleFragment.java
index 0dc71b752..aa5abdeff 100644
--- a/src/org/linphone/HistorySimpleFragment.java
+++ b/src/org/linphone/HistorySimpleFragment.java
@@ -130,8 +130,14 @@ public class HistorySimpleFragment extends Fragment implements OnClickListener,
@Override
public void onResume() {
super.onResume();
- if (LinphoneActivity.isInstanciated())
+
+ if (LinphoneActivity.isInstanciated()) {
LinphoneActivity.instance().selectMenu(FragmentsAvailable.HISTORY);
+
+ if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) {
+ LinphoneActivity.instance().hideStatusBar();
+ }
+ }
mLogs = Arrays.asList(LinphoneManager.getLc().getCallLogs());
if (!hideHistoryListAndDisplayMessageIfEmpty()) {
@@ -385,22 +391,25 @@ public class HistorySimpleFragment extends Fragment implements OnClickListener,
address = log.getTo();
callDirection.setImageBitmap(outgoingCall);
}
-
- LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, view.getContext().getContentResolver());
- String displayName = address.getDisplayName();
- String sipUri = address.asStringUriOnly();
+
+ Contact c = ContactsManager.getInstance().findContactWithAddress(getActivity().getContentResolver(), address);
+ String displayName = null;
+ final String sipUri = address.asStringUriOnly();
+ if(c != null){
+ displayName = c.getName();
+ }
if (displayName == null) {
if (getResources().getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(sipUri)) {
- contact.setText(LinphoneUtils.getUsernameFromAddress(sipUri));
+ contact.setText(address.getUserName());
} else {
contact.setText(sipUri);
}
} else {
if (getResources().getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(address.getDisplayName())) {
- contact.setText(LinphoneUtils.getUsernameFromAddress(address.getDisplayName()));
- } else {
contact.setText(displayName);
+ } else {
+ contact.setText(sipUri);
}
}
view.setTag(sipUri);
@@ -415,7 +424,7 @@ public class HistorySimpleFragment extends Fragment implements OnClickListener,
@Override
public void onClick(View v) {
if (LinphoneActivity.isInstanciated()) {
- LinphoneActivity.instance().displayHistoryDetail(address.asStringUriOnly(), log);
+ LinphoneActivity.instance().displayHistoryDetail(sipUri, log);
}
}
});
diff --git a/src/org/linphone/InCallActivity.java b/src/org/linphone/InCallActivity.java
index af06903fe..032209db5 100644
--- a/src/org/linphone/InCallActivity.java
+++ b/src/org/linphone/InCallActivity.java
@@ -20,8 +20,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import java.util.Arrays;
import java.util.List;
-import org.linphone.LinphoneSimpleListener.LinphoneOnCallEncryptionChangedListener;
-import org.linphone.LinphoneSimpleListener.LinphoneOnCallStateChangedListener;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCall.State;
@@ -29,15 +27,16 @@ import org.linphone.core.LinphoneCallParams;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.core.LinphoneCoreListenerBase;
+import org.linphone.core.LinphonePlayer;
import org.linphone.mediastream.Log;
+import org.linphone.mediastream.Version;
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration;
import org.linphone.ui.AvatarWithShadow;
import org.linphone.ui.Numpad;
-import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.net.Uri;
@@ -45,8 +44,6 @@ import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.Handler;
import android.os.SystemClock;
-import android.preference.PreferenceManager;
-import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
@@ -62,10 +59,10 @@ import android.view.animation.Animation;
import android.view.animation.Animation.AnimationListener;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
-import android.widget.Button;
import android.widget.Chronometer;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.ProgressBar;
import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.Toast;
@@ -73,39 +70,37 @@ import android.widget.Toast;
/**
* @author Sylvain Berfini
*/
-public class InCallActivity extends FragmentActivity implements
- LinphoneOnCallStateChangedListener,
- LinphoneOnCallEncryptionChangedListener,
- OnClickListener {
+public class InCallActivity extends FragmentActivity implements OnClickListener {
private final static int SECONDS_BEFORE_HIDING_CONTROLS = 3000;
private final static int SECONDS_BEFORE_DENYING_CALL_UPDATE = 30000;
private static InCallActivity instance;
-
- private Handler mHandler = new Handler();
- private Handler mControlsHandler = new Handler();
+
+ private Handler mControlsHandler = new Handler();
private Runnable mControls;
- private ImageView pause, hangUp, dialer, switchCamera, conference;
- private TextView video, micro, speaker, options, addCall, transfer;
+ private ImageView switchCamera;
+ private TextView pause, hangUp, dialer, video, micro, speaker, options, addCall, transfer, conference;
private TextView audioRoute, routeSpeaker, routeReceiver, routeBluetooth;
private LinearLayout routeLayout;
+ private ProgressBar videoProgress;
private StatusFragment status;
private AudioCallFragment audioCallFragment;
private VideoCallFragment videoCallFragment;
- private boolean isSpeakerEnabled = false, isMicMuted = false, isVideoEnabled, isTransferAllowed, isAnimationDisabled;
+ private boolean isSpeakerEnabled = false, isMicMuted = false, isTransferAllowed, isAnimationDisabled;
private ViewGroup mControlsLayout;
private Numpad numpad;
private int cameraNumber;
private Animation slideOutLeftToRight, slideInRightToLeft, slideInBottomToTop, slideInTopToBottom, slideOutBottomToTop, slideOutTopToBottom;
private CountDownTimer timer;
- private AcceptCallUpdateDialog callUpdateDialog;
private boolean isVideoCallPaused = false;
+ AcceptCallUpdateDialogFragment callUpdateDialog;
private TableLayout callsList;
private LayoutInflater inflater;
private ViewGroup container;
private boolean isConferenceRunning = false;
private boolean showCallListInVideo = false;
+ private LinphoneCoreListenerBase mListener;
public static InCallActivity instance() {
return instance;
@@ -123,22 +118,126 @@ public class InCallActivity extends FragmentActivity implements
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
setContentView(R.layout.incall);
- isVideoEnabled = getIntent().getExtras() != null && getIntent().getExtras().getBoolean("VideoEnabled");
isTransferAllowed = getApplicationContext().getResources().getBoolean(R.bool.allow_transfers);
showCallListInVideo = getApplicationContext().getResources().getBoolean(R.bool.show_current_calls_above_video);
-
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- isAnimationDisabled = getApplicationContext().getResources().getBoolean(R.bool.disable_animations) || !prefs.getBoolean(getString(R.string.pref_animation_enable_key), false);
+ isSpeakerEnabled = LinphoneManager.getLcIfManagerNotDestroyedOrNull().isSpeakerEnabled();
+
+ if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
+ if(!BluetoothManager.getInstance().isBluetoothHeadsetAvailable()) {
+ BluetoothManager.getInstance().initBluetooth();
+ } else {
+ isSpeakerEnabled = false;
+ }
+ }
+
+ isAnimationDisabled = getApplicationContext().getResources().getBoolean(R.bool.disable_animations) || !LinphonePreferences.instance().areAnimationsEnabled();
cameraNumber = AndroidCameraConfiguration.retrieveCameras().length;
+ mListener = new LinphoneCoreListenerBase(){
+ @Override
+ public void callState(LinphoneCore lc, final LinphoneCall call, LinphoneCall.State state, String message) {
+ if (LinphoneManager.getLc().getCallsNb() == 0) {
+ finish();
+ return;
+ }
+
+ if (state == State.IncomingReceived) {
+ startIncomingCallActivity();
+ return;
+ }
+
+ if (state == State.Paused || state == State.PausedByRemote || state == State.Pausing) {
+ video.setEnabled(false);
+ if(isVideoEnabled(call)){
+ showAudioView();
+ }
+ }
+
+ if (state == State.Resuming) {
+ if(LinphonePreferences.instance().isVideoEnabled()){
+ status.refreshStatusItems(call, isVideoEnabled(call));
+ if(call.getCurrentParamsCopy().getVideoEnabled()){
+ showVideoView();
+ }
+ }
+ }
+
+ if (state == State.StreamsRunning) {
+ switchVideo(isVideoEnabled(call));
+
+ //Check media in progress
+ if(LinphonePreferences.instance().isVideoEnabled() && !call.mediaInProgress()){
+ video.setEnabled(true);
+ }
+
+ LinphoneManager.getLc().enableSpeaker(isSpeakerEnabled);
+
+ isMicMuted = LinphoneManager.getLc().isMicMuted();
+ enableAndRefreshInCallActions();
+
+ if (status != null) {
+ videoProgress.setVisibility(View.GONE);
+ status.refreshStatusItems(call, isVideoEnabled(call));
+ }
+ }
+
+ refreshInCallActions();
+
+ refreshCallList(getResources());
+
+ if (state == State.CallUpdatedByRemote) {
+ // If the correspondent proposes video while audio call
+ boolean videoEnabled = LinphonePreferences.instance().isVideoEnabled();
+ if (!videoEnabled) {
+ acceptCallUpdate(false);
+ return;
+ }
+
+ boolean remoteVideo = call.getRemoteParams().getVideoEnabled();
+ boolean localVideo = call.getCurrentParamsCopy().getVideoEnabled();
+ boolean autoAcceptCameraPolicy = LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests();
+ if (remoteVideo && !localVideo && !autoAcceptCameraPolicy && !LinphoneManager.getLc().isInConference()) {
+ showAcceptCallUpdateDialog();
+
+ timer = new CountDownTimer(SECONDS_BEFORE_DENYING_CALL_UPDATE, 1000) {
+ public void onTick(long millisUntilFinished) { }
+ public void onFinish() {
+ if (callUpdateDialog != null)
+ callUpdateDialog.dismiss();
+ acceptCallUpdate(false);
+ }
+ }.start();
+ }
+// else if (remoteVideo && !LinphoneManager.getLc().isInConference() && autoAcceptCameraPolicy) {
+// mHandler.post(new Runnable() {
+// @Override
+// public void run() {
+// acceptCallUpdate(true);
+// }
+// });
+// }
+ }
+
+ transfer.setEnabled(LinphoneManager.getLc().getCurrentCall() != null);
+ }
+
+ @Override
+ public void callEncryptionChanged(LinphoneCore lc, final LinphoneCall call, boolean encrypted, String authenticationToken) {
+ if (status != null) {
+ status.refreshStatusItems(call, call.getCurrentParamsCopy().getVideoEnabled());
+ }
+ }
+
+ };
+
if (findViewById(R.id.fragmentContainer) != null) {
+
initUI();
if (LinphoneManager.getLc().getCallsNb() > 0) {
LinphoneCall call = LinphoneManager.getLc().getCalls()[0];
if (LinphoneUtils.isCallEstablished(call)) {
- isVideoEnabled = call.getCurrentParamsCopy().getVideoEnabled() && !call.getRemoteParams().isLowBandwidthEnabled();
enableAndRefreshInCallActions();
}
}
@@ -153,9 +252,10 @@ public class InCallActivity extends FragmentActivity implements
}
Fragment callFragment;
- if (isVideoEnabled) {
+ if (isVideoEnabled(LinphoneManager.getLc().getCurrentCall())) {
callFragment = new VideoCallFragment();
videoCallFragment = (VideoCallFragment) callFragment;
+ isSpeakerEnabled = true;
if (cameraNumber > 1) {
switchCamera.setVisibility(View.VISIBLE);
@@ -165,26 +265,44 @@ public class InCallActivity extends FragmentActivity implements
audioCallFragment = (AudioCallFragment) callFragment;
switchCamera.setVisibility(View.INVISIBLE);
}
+
+ if(BluetoothManager.getInstance().isBluetoothHeadsetAvailable()){
+ BluetoothManager.getInstance().routeAudioToBluetooth();
+ }
+
callFragment.setArguments(getIntent().getExtras());
getSupportFragmentManager().beginTransaction().add(R.id.fragmentContainer, callFragment).commitAllowingStateLoss();
+
}
}
+ private boolean isVideoEnabled(LinphoneCall call) {
+ if(call != null){
+ return call.getCurrentParamsCopy().getVideoEnabled();
+ }
+ return false;
+ }
+
@Override
protected void onSaveInstanceState(Bundle outState) {
- outState.putBoolean("Speaker", isSpeakerEnabled);
- outState.putBoolean("Mic", isMicMuted);
+ outState.putBoolean("Speaker", LinphoneManager.getLc().isSpeakerEnabled());
+ outState.putBoolean("Mic", LinphoneManager.getLc().isMicMuted());
outState.putBoolean("VideoCallPaused", isVideoCallPaused);
super.onSaveInstanceState(outState);
}
+ private boolean isTablet() {
+ return getResources().getBoolean(R.bool.isTablet);
+ }
+
private void initUI() {
inflater = LayoutInflater.from(this);
container = (ViewGroup) findViewById(R.id.topLayout);
callsList = (TableLayout) findViewById(R.id.calls);
if (!showCallListInVideo) {
callsList.setVisibility(View.GONE);
+
}
video = (TextView) findViewById(R.id.video);
@@ -195,6 +313,9 @@ public class InCallActivity extends FragmentActivity implements
// micro.setEnabled(false);
speaker = (TextView) findViewById(R.id.speaker);
speaker.setOnClickListener(this);
+ if(isTablet()){
+ speaker.setEnabled(false);
+ }
// speaker.setEnabled(false);
addCall = (TextView) findViewById(R.id.addCall);
addCall.setOnClickListener(this);
@@ -205,17 +326,20 @@ public class InCallActivity extends FragmentActivity implements
options = (TextView) findViewById(R.id.options);
options.setOnClickListener(this);
options.setEnabled(false);
- pause = (ImageView) findViewById(R.id.pause);
+ pause = (TextView) findViewById(R.id.pause);
pause.setOnClickListener(this);
pause.setEnabled(false);
- hangUp = (ImageView) findViewById(R.id.hangUp);
+ hangUp = (TextView) findViewById(R.id.hangUp);
hangUp.setOnClickListener(this);
- conference = (ImageView) findViewById(R.id.conference);
+ conference = (TextView) findViewById(R.id.conference);
conference.setOnClickListener(this);
- dialer = (ImageView) findViewById(R.id.dialer);
+ dialer = (TextView) findViewById(R.id.dialer);
dialer.setOnClickListener(this);
dialer.setEnabled(false);
numpad = (Numpad) findViewById(R.id.numpad);
+ videoProgress = (ProgressBar) findViewById(R.id.videoInProgress);
+ videoProgress.setVisibility(View.GONE);
+
try {
routeLayout = (LinearLayout) findViewById(R.id.routesLayout);
@@ -248,8 +372,8 @@ public class InCallActivity extends FragmentActivity implements
slideOutBottomToTop = AnimationUtils.loadAnimation(this, R.anim.slide_out_bottom_to_top);
slideOutTopToBottom = AnimationUtils.loadAnimation(this, R.anim.slide_out_top_to_bottom);
}
-
- if (LinphoneManager.getInstance().isBluetoothScoConnected) {
+
+ if (BluetoothManager.getInstance().isBluetoothHeadsetAvailable()) {
try {
if (routeLayout != null)
routeLayout.setVisibility(View.VISIBLE);
@@ -264,115 +388,98 @@ public class InCallActivity extends FragmentActivity implements
speaker.setVisibility(View.VISIBLE);
} catch (NullPointerException npe) { Log.e("Bluetooth: Audio routes menu disabled on tablets for now (3)"); }
}
+
+ LinphoneManager.getInstance().changeStatusToOnThePhone();
}
private void refreshInCallActions() {
- if (mHandler == null) {
- mHandler = new Handler();
+ if (!LinphonePreferences.instance().isVideoEnabled()) {
+ video.setEnabled(false);
+ } else {
+ if (isVideoEnabled(LinphoneManager.getLc().getCurrentCall())) {
+ video.setBackgroundResource(R.drawable.video_on);
+ } else {
+ video.setBackgroundResource(R.drawable.video_off);
+ }
}
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (!isVideoActivatedInSettings()) {
- video.setEnabled(false);
+
+ try {
+ if (isSpeakerEnabled) {
+ speaker.setBackgroundResource(R.drawable.speaker_on);
+ routeSpeaker.setBackgroundResource(R.drawable.route_speaker_on);
+ routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
+ routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
+ } else {
+ speaker.setBackgroundResource(R.drawable.speaker_off);
+ routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off);
+ if (BluetoothManager.getInstance().isUsingBluetoothAudioRoute()) {
+ routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
+ routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_on);
} else {
- if (isVideoEnabled) {
- video.setBackgroundResource(R.drawable.video_on);
- } else {
- video.setBackgroundResource(R.drawable.video_off);
- }
- }
-
- try {
- if (isSpeakerEnabled) {
- speaker.setBackgroundResource(R.drawable.speaker_on);
- routeSpeaker.setBackgroundResource(R.drawable.route_speaker_on);
- routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
- routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
- } else {
- speaker.setBackgroundResource(R.drawable.speaker_off);
- routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off);
- if (LinphoneManager.getInstance().isUsingBluetoothAudioRoute) {
- routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
- routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_on);
- } else {
- routeReceiver.setBackgroundResource(R.drawable.route_receiver_on);
- routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
- }
- }
- } catch (NullPointerException npe) {
- Log.e("Bluetooth: Audio routes menu disabled on tablets for now (4)");
- }
-
- if (isMicMuted) {
- micro.setBackgroundResource(R.drawable.micro_off);
- } else {
- micro.setBackgroundResource(R.drawable.micro_on);
- }
-
- if (LinphoneManager.getLc().getCallsNb() > 1) {
- conference.setVisibility(View.VISIBLE);
- pause.setVisibility(View.GONE);
- } else {
- conference.setVisibility(View.GONE);
- pause.setVisibility(View.VISIBLE);
-
- List pausedCalls = LinphoneUtils.getCallsInState(LinphoneManager.getLc(), Arrays.asList(State.Paused));
- if (pausedCalls.size() == 1) {
- pause.setImageResource(R.drawable.pause_on);
- } else {
- pause.setImageResource(R.drawable.pause_off);
- }
+ routeReceiver.setBackgroundResource(R.drawable.route_receiver_on);
+ routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_off);
}
}
- });
+ } catch (NullPointerException npe) {
+ Log.e("Bluetooth: Audio routes menu disabled on tablets for now (4)");
+ }
+
+ if (isMicMuted) {
+ micro.setBackgroundResource(R.drawable.micro_off);
+ } else {
+ micro.setBackgroundResource(R.drawable.micro_on);
+ }
+
+ if (LinphoneManager.getLc().getCallsNb() > 1) {
+ conference.setVisibility(View.VISIBLE);
+ pause.setVisibility(View.GONE);
+ } else {
+ conference.setVisibility(View.GONE);
+ pause.setVisibility(View.VISIBLE);
+
+ List pausedCalls = LinphoneUtils.getCallsInState(LinphoneManager.getLc(), Arrays.asList(State.Paused));
+ if (pausedCalls.size() == 1) {
+ pause.setBackgroundResource(R.drawable.pause_on);
+ } else {
+ pause.setBackgroundResource(R.drawable.pause_off);
+ }
+ }
}
private void enableAndRefreshInCallActions() {
- if (mHandler == null) {
- mHandler = new Handler();
- }
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- addCall.setEnabled(LinphoneManager.getLc().getCallsNb() < LinphoneManager.getLc().getMaxCalls());
- transfer.setEnabled(getResources().getBoolean(R.bool.allow_transfers));
- options.setEnabled(!getResources().getBoolean(R.bool.disable_options_in_call) && (addCall.isEnabled() || transfer.isEnabled()));
-
- video.setEnabled(true);
- micro.setEnabled(true);
- speaker.setEnabled(true);
- transfer.setEnabled(true);
- pause.setEnabled(true);
- dialer.setEnabled(true);
- conference.setEnabled(true);
+ addCall.setEnabled(LinphoneManager.getLc().getCallsNb() < LinphoneManager.getLc().getMaxCalls());
+ transfer.setEnabled(getResources().getBoolean(R.bool.allow_transfers));
+ options.setEnabled(!getResources().getBoolean(R.bool.disable_options_in_call) && (addCall.isEnabled() || transfer.isEnabled()));
- refreshInCallActions();
- }
- });
+ if(LinphoneManager.getLc().getCurrentCall() != null && LinphonePreferences.instance().isVideoEnabled() && !LinphoneManager.getLc().getCurrentCall().mediaInProgress()) {
+ video.setEnabled(true);
+ }
+ micro.setEnabled(true);
+ if(!isTablet()){
+ speaker.setEnabled(true);
+ }
+ transfer.setEnabled(true);
+ pause.setEnabled(true);
+ dialer.setEnabled(true);
+ conference.setEnabled(true);
+
+ refreshInCallActions();
}
public void updateStatusFragment(StatusFragment statusFragment) {
status = statusFragment;
}
-
- private boolean isVideoActivatedInSettings() {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- boolean settingsVideoEnabled = prefs.getBoolean(getString(R.string.pref_video_enable_key), false);
- return settingsVideoEnabled;
- }
@Override
public void onClick(View v) {
int id = v.getId();
- if (isVideoEnabled) {
+ if (isVideoEnabled(LinphoneManager.getLc().getCurrentCall())) {
displayVideoCallControlsIfHidden();
}
-
- if (id == R.id.video) {
- isVideoEnabled = !isVideoEnabled;
- switchVideo(isVideoEnabled, true);
+
+ if (id == R.id.video) {
+ enabledOrDisabledVideo(isVideoEnabled(LinphoneManager.getLc().getCurrentCall()));
}
else if (id == R.id.micro) {
toggleMicro();
@@ -410,11 +517,12 @@ public class InCallActivity extends FragmentActivity implements
hideOrDisplayAudioRoutes();
}
else if (id == R.id.routeBluetooth) {
- LinphoneManager.getInstance().routeAudioToBluetooth();
- isSpeakerEnabled = false;
- routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_on);
- routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
- routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off);
+ if (BluetoothManager.getInstance().routeAudioToBluetooth()) {
+ isSpeakerEnabled = false;
+ routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_on);
+ routeReceiver.setBackgroundResource(R.drawable.route_receiver_off);
+ routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off);
+ }
hideOrDisplayAudioRoutes();
}
else if (id == R.id.routeReceiver) {
@@ -443,67 +551,82 @@ public class InCallActivity extends FragmentActivity implements
}
}
- public void displayCustomToast(final String message, final int duration) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- LayoutInflater inflater = getLayoutInflater();
- View layout = inflater.inflate(R.layout.toast, (ViewGroup) findViewById(R.id.toastRoot));
-
- TextView toastText = (TextView) layout.findViewById(R.id.toastMessage);
- toastText.setText(message);
-
- final Toast toast = new Toast(getApplicationContext());
- toast.setGravity(Gravity.CENTER, 0, 0);
- toast.setDuration(duration);
- toast.setView(layout);
- toast.show();
- }
- });
- }
-
- private void switchVideo(final boolean displayVideo, final boolean isInitiator) {
- final LinphoneCall call = LinphoneManager.getLc().getCalls()[0];
+ private void enabledOrDisabledVideo(final boolean isVideoEnabled) {
+ final LinphoneCall call = LinphoneManager.getLc().getCurrentCall();
if (call == null) {
return;
}
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (!displayVideo) {
- if (isInitiator) {
- LinphoneCallParams params = call.getCurrentParamsCopy();
- params.setVideoEnabled(false);
- LinphoneManager.getLc().updateCall(call, params);
- }
- showAudioView();
- } else {
- if (!call.getRemoteParams().isLowBandwidthEnabled()) {
- LinphoneManager.getInstance().addVideo();
- showVideoView();
- } else {
- displayCustomToast(getString(R.string.error_low_bandwidth), Toast.LENGTH_LONG);
- }
- }
+ if (isVideoEnabled) {
+ video.setEnabled(true);
+ LinphoneCallParams params = call.getCurrentParamsCopy();
+ params.setVideoEnabled(false);
+ LinphoneManager.getLc().updateCall(call, params);
+ } else {
+ video.setEnabled(false);
+ videoProgress.setVisibility(View.VISIBLE);
+ if (!call.getRemoteParams().isLowBandwidthEnabled()) {
+ LinphoneManager.getInstance().addVideo();
+ } else {
+ displayCustomToast(getString(R.string.error_low_bandwidth), Toast.LENGTH_LONG);
}
- });
+ }
+ }
+
+ public void displayCustomToast(final String message, final int duration) {
+ LayoutInflater inflater = getLayoutInflater();
+ View layout = inflater.inflate(R.layout.toast, (ViewGroup) findViewById(R.id.toastRoot));
+
+ TextView toastText = (TextView) layout.findViewById(R.id.toastMessage);
+ toastText.setText(message);
+
+ final Toast toast = new Toast(getApplicationContext());
+ toast.setGravity(Gravity.CENTER, 0, 0);
+ toast.setDuration(duration);
+ toast.setView(layout);
+ toast.show();
+ }
+
+ private void switchVideo(final boolean displayVideo) {
+ final LinphoneCall call = LinphoneManager.getLc().getCurrentCall();
+ if (call == null) {
+ return;
+ }
+
+ //Check if the call is not terminated
+ if(call.getState() == State.CallEnd || call.getState() == State.CallReleased) return;
+
+ if (!displayVideo) {
+ showAudioView();
+ } else {
+ if (!call.getRemoteParams().isLowBandwidthEnabled()) {
+ LinphoneManager.getInstance().addVideo();
+ if (videoCallFragment == null || !videoCallFragment.isVisible())
+ showVideoView();
+ } else {
+ displayCustomToast(getString(R.string.error_low_bandwidth), Toast.LENGTH_LONG);
+ }
+ }
}
private void showAudioView() {
video.setBackgroundResource(R.drawable.video_on);
-
LinphoneManager.startProximitySensorForActivity(InCallActivity.this);
replaceFragmentVideoByAudio();
setCallControlsVisibleAndRemoveCallbacks();
}
private void showVideoView() {
- isSpeakerEnabled = true;
- LinphoneManager.getInstance().routeAudioToSpeaker();
- speaker.setBackgroundResource(R.drawable.speaker_on);
+ if (!BluetoothManager.getInstance().isBluetoothHeadsetAvailable()) {
+ Log.w("Bluetooth not available, using speaker");
+ LinphoneManager.getInstance().routeAudioToSpeaker();
+ isSpeakerEnabled = true;
+ speaker.setBackgroundResource(R.drawable.speaker_on);
+ }
video.setBackgroundResource(R.drawable.video_off);
-
+ video.setEnabled(true);
+ videoProgress.setVisibility(View.INVISIBLE);
+
LinphoneManager.stopProximitySensorForActivity(InCallActivity.this);
replaceFragmentAudioByVideo();
displayVideoCallControlsIfHidden();
@@ -553,15 +676,18 @@ public class InCallActivity extends FragmentActivity implements
speaker.setBackgroundResource(R.drawable.speaker_on);
LinphoneManager.getLc().enableSpeaker(isSpeakerEnabled);
} else {
+ Log.d("Toggle speaker off, routing back to earpiece");
LinphoneManager.getInstance().routeAudioToReceiver();
speaker.setBackgroundResource(R.drawable.speaker_off);
}
}
private void pauseOrResumeCall() {
- LinphoneCore lc = LinphoneManager.getLc();
- LinphoneCall call = lc.getCurrentCall();
- pauseOrResumeCall(call);
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null && lc.getCallsNb() >= 1) {
+ LinphoneCall call = lc.getCalls()[0];
+ pauseOrResumeCall(call);
+ }
}
public void pauseOrResumeCall(LinphoneCall call) {
@@ -574,31 +700,20 @@ public class InCallActivity extends FragmentActivity implements
}
} else {
lc.pauseCall(call);
- if (isVideoEnabled) {
+ if (isVideoEnabled(LinphoneManager.getLc().getCurrentCall())) {
isVideoCallPaused = true;
showAudioView();
}
- pause.setImageResource(R.drawable.pause_on);
+ pause.setBackgroundResource(R.drawable.pause_on);
}
- } else {
- List pausedCalls = LinphoneUtils.getCallsInState(lc, Arrays.asList(State.Paused));
- if (pausedCalls.size() == 1) {
- LinphoneCall callToResume = pausedCalls.get(0);
- if ((call != null && callToResume.equals(call)) || call == null) {
- lc.resumeCall(callToResume);
- if (isVideoCallPaused) {
- isVideoCallPaused = false;
- showVideoView();
- }
- pause.setImageResource(R.drawable.pause_off);
- }
- } else if (call != null) {
+ } else if (call != null) {
+ if (call.getState() == State.Paused) {
lc.resumeCall(call);
if (isVideoCallPaused) {
isVideoCallPaused = false;
showVideoView();
}
- pause.setImageResource(R.drawable.pause_off);
+ pause.setBackgroundResource(R.drawable.pause_off);
}
}
}
@@ -675,7 +790,7 @@ public class InCallActivity extends FragmentActivity implements
}
mControls = null;
- if (isVideoEnabled && mControlsHandler != null) {
+ if (isVideoEnabled(LinphoneManager.getLc().getCurrentCall()) && mControlsHandler != null) {
mControlsHandler.postDelayed(mControls = new Runnable() {
public void run() {
hideNumpad();
@@ -740,7 +855,7 @@ public class InCallActivity extends FragmentActivity implements
return;
}
- dialer.setImageResource(R.drawable.dialer_alt);
+ dialer.setBackgroundResource(R.drawable.dialer_alt);
if (isAnimationDisabled) {
numpad.setVisibility(View.GONE);
} else {
@@ -774,7 +889,7 @@ public class InCallActivity extends FragmentActivity implements
if (numpad.getVisibility() == View.VISIBLE) {
hideNumpad();
} else {
- dialer.setImageResource(R.drawable.dialer_alt_back);
+ dialer.setBackgroundResource(R.drawable.dialer_alt_back);
if (isAnimationDisabled) {
numpad.setVisibility(View.VISIBLE);
} else {
@@ -949,11 +1064,11 @@ public class InCallActivity extends FragmentActivity implements
private void hideOrDisplayAudioRoutes()
{
if (routeSpeaker.getVisibility() == View.VISIBLE) {
- routeSpeaker.setVisibility(View.INVISIBLE);
- routeBluetooth.setVisibility(View.INVISIBLE);
- routeReceiver.setVisibility(View.INVISIBLE);
+ routeSpeaker.setVisibility(View.GONE);
+ routeBluetooth.setVisibility(View.GONE);
+ routeReceiver.setVisibility(View.GONE);
audioRoute.setSelected(false);
- } else {
+ } else {
routeSpeaker.setVisibility(View.VISIBLE);
routeBluetooth.setVisibility(View.VISIBLE);
routeReceiver.setVisibility(View.VISIBLE);
@@ -1012,14 +1127,10 @@ public class InCallActivity extends FragmentActivity implements
finish();
}
- private void acceptCallUpdate(boolean accept) {
+ public void acceptCallUpdate(boolean accept) {
if (timer != null) {
timer.cancel();
}
-
- if (callUpdateDialog != null) {
- callUpdateDialog.dismissAllowingStateLoss();
- }
LinphoneCall call = LinphoneManager.getLc().getCurrentCall();
if (call == null) {
@@ -1043,113 +1154,19 @@ public class InCallActivity extends FragmentActivity implements
startActivity(new Intent(this, IncomingCallActivity.class));
}
- @Override
- public void onCallStateChanged(final LinphoneCall call, State state, String message) {
- if (LinphoneManager.getLc().getCallsNb() == 0) {
- finish();
- return;
- }
-
- if (state == State.IncomingReceived) {
- startIncomingCallActivity();
- return;
- }
-
- if (state == State.StreamsRunning) {
- boolean isVideoEnabledInCall = call.getCurrentParamsCopy().getVideoEnabled();
- if (isVideoEnabledInCall != isVideoEnabled) {
- isVideoEnabled = isVideoEnabledInCall;
- switchVideo(isVideoEnabled, false);
- }
-
- LinphoneManager.getLc().enableSpeaker(isSpeakerEnabled);
-
- isMicMuted = LinphoneManager.getLc().isMicMuted();
- enableAndRefreshInCallActions();
-
- if (status != null) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- status.refreshStatusItems(call, isVideoEnabled);
- }
- });
- }
- }
- refreshInCallActions();
-
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- refreshCallList(getResources());
- }
- });
-
- if (state == State.CallUpdatedByRemote) {
- // If the correspondent proposes video while audio call
- boolean isVideoEnabled = LinphoneManager.getInstance().isVideoEnabled();
- if (!isVideoEnabled) {
- acceptCallUpdate(false);
- return;
- }
-
- boolean remoteVideo = call.getRemoteParams().getVideoEnabled();
- boolean localVideo = call.getCurrentParamsCopy().getVideoEnabled();
- boolean autoAcceptCameraPolicy = LinphoneManager.getInstance().isAutoAcceptCamera();
- if (remoteVideo && !localVideo && !autoAcceptCameraPolicy && !LinphoneManager.getLc().isInConference()) {
- mHandler.post(new Runnable() {
- public void run() {
- showAcceptCallUpdateDialog();
-
- timer = new CountDownTimer(SECONDS_BEFORE_DENYING_CALL_UPDATE, 1000) {
- public void onTick(long millisUntilFinished) { }
- public void onFinish() {
- acceptCallUpdate(false);
- }
- }.start();
- }
- });
- }
-// else if (remoteVideo && !LinphoneManager.getLc().isInConference() && autoAcceptCameraPolicy) {
-// mHandler.post(new Runnable() {
-// @Override
-// public void run() {
-// acceptCallUpdate(true);
-// }
-// });
-// }
- }
-
- mHandler.post(new Runnable() {
- public void run() {
- transfer.setEnabled(LinphoneManager.getLc().getCurrentCall() != null);
- }
- });
- }
+
private void showAcceptCallUpdateDialog() {
FragmentManager fm = getSupportFragmentManager();
- callUpdateDialog = new AcceptCallUpdateDialog();
+ callUpdateDialog = new AcceptCallUpdateDialogFragment();
callUpdateDialog.show(fm, "Accept Call Update Dialog");
}
- @Override
- public void onCallEncryptionChanged(final LinphoneCall call, boolean encrypted, String authenticationToken) {
- if (status != null) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- status.refreshStatusItems(call, call.getCurrentParamsCopy().getVideoEnabled());
- }
- });
- }
- }
-
@Override
protected void onResume() {
instance = this;
- if (isVideoEnabled) {
+ if (isVideoEnabled(LinphoneManager.getLc().getCurrentCall())) {
displayVideoCallControlsIfHidden();
} else {
LinphoneManager.startProximitySensorForActivity(this);
@@ -1158,34 +1175,76 @@ public class InCallActivity extends FragmentActivity implements
super.onResume();
- LinphoneManager.addListener(this);
-
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.addListener(mListener);
+ }
+
refreshCallList(getResources());
+
+ handleViewIntent();
+ }
+
+ private void handleViewIntent() {
+ Intent intent = getIntent();
+ if(intent != null && intent.getAction() == "android.intent.action.VIEW") {
+ LinphoneCall call = LinphoneManager.getLc().getCurrentCall();
+ if(call != null && isVideoEnabled(call)) {
+ LinphonePlayer player = call.getPlayer();
+ String path = intent.getData().getPath();
+ Log.i("Openning " + path);
+ int openRes = player.open(path, new LinphonePlayer.Listener() {
+
+ @Override
+ public void endOfFile(LinphonePlayer player) {
+ player.close();
+ }
+ });
+ if(openRes == -1) {
+ String message = "Could not open " + path;
+ Log.e(message);
+ Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
+ return;
+ }
+ Log.i("Start playing");
+ if(player.start() == -1) {
+ player.close();
+ String message = "Could not start playing " + path;
+ Log.e(message);
+ Toast.makeText(getApplicationContext(), message, Toast.LENGTH_SHORT).show();
+ }
+ }
+ }
}
@Override
protected void onPause() {
- super.onPause();
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.removeListener(mListener);
+ }
+ super.onPause();
+
if (mControlsHandler != null && mControls != null) {
mControlsHandler.removeCallbacks(mControls);
}
mControls = null;
- if (!isVideoEnabled) {
+ if (!isVideoEnabled(LinphoneManager.getLc().getCurrentCall())) {
LinphoneManager.stopProximitySensorForActivity(this);
}
- LinphoneManager.removeListener(this);
}
@Override
protected void onDestroy() {
+ LinphoneManager.getInstance().changeStatusToOnline();
+
if (mControlsHandler != null && mControls != null) {
mControlsHandler.removeCallbacks(mControls);
}
mControls = null;
mControlsHandler = null;
- mHandler = null;
unbindDrawables(findViewById(R.id.topLayout));
instance = null;
@@ -1223,41 +1282,6 @@ public class InCallActivity extends FragmentActivity implements
videoCallFragment = fragment;
}
- @SuppressLint("ValidFragment")
- class AcceptCallUpdateDialog extends DialogFragment {
-
- public AcceptCallUpdateDialog() {
- // Empty constructor required for DialogFragment
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.accept_call_update_dialog, container);
-
- getDialog().setTitle(R.string.call_update_title);
-
- Button yes = (Button) view.findViewById(R.id.yes);
- yes.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Log.d("Call Update Accepted");
- acceptCallUpdate(true);
- }
- });
-
- Button no = (Button) view.findViewById(R.id.no);
- no.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- Log.d("Call Update Denied");
- acceptCallUpdate(false);
- }
- });
-
- return view;
- }
- }
-
private void displayConferenceHeader() {
LinearLayout conferenceHeader = (LinearLayout) inflater.inflate(R.layout.conference_header, container, false);
@@ -1274,10 +1298,17 @@ public class InCallActivity extends FragmentActivity implements
private void displayCall(Resources resources, LinphoneCall call, int index) {
String sipUri = call.getRemoteAddress().asStringUriOnly();
- LinphoneAddress lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri);
+ LinphoneAddress lAddress;
+ try {
+ lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri);
+ } catch (LinphoneCoreException e) {
+ Log.e("Incall activity cannot parse remote address",e);
+ lAddress= LinphoneCoreFactory.instance().createLinphoneAddress("uknown","unknown","unkonown");
+ }
// Control Row
LinearLayout callView = (LinearLayout) inflater.inflate(R.layout.active_call_control_row, container, false);
+ callView.setId(index+1);
setContactName(callView, lAddress, sipUri, resources);
displayCallStatusIconAndReturnCallPaused(callView, call);
setRowBackground(callView, index);
@@ -1286,8 +1317,12 @@ public class InCallActivity extends FragmentActivity implements
// Image Row
LinearLayout imageView = (LinearLayout) inflater.inflate(R.layout.active_call_image_row, container, false);
- Uri pictureUri = LinphoneUtils.findUriPictureOfContactAndSetDisplayName(lAddress, imageView.getContext().getContentResolver());
- displayOrHideContactPicture(imageView, pictureUri, false);
+ Contact contact = ContactsManager.getInstance().findContactWithAddress(imageView.getContext().getContentResolver(), lAddress);
+ if(contact != null) {
+ displayOrHideContactPicture(imageView, contact.getPhotoUri(), contact.getThumbnailUri(), false);
+ } else {
+ displayOrHideContactPicture(imageView, null, null, false);
+ }
callsList.addView(imageView);
callView.setTag(imageView);
@@ -1308,18 +1343,16 @@ public class InCallActivity extends FragmentActivity implements
private void setContactName(LinearLayout callView, LinphoneAddress lAddress, String sipUri, Resources resources) {
TextView contact = (TextView) callView.findViewById(R.id.contactNameOrNumber);
-
- LinphoneUtils.findUriPictureOfContactAndSetDisplayName(lAddress, callView.getContext().getContentResolver());
- String displayName = lAddress.getDisplayName();
- if (displayName == null) {
+ Contact lContact = ContactsManager.getInstance().findContactWithAddress(callView.getContext().getContentResolver(), lAddress);
+ if (lContact == null) {
if (resources.getBoolean(R.bool.only_display_username_if_unknown) && LinphoneUtils.isSipAddress(sipUri)) {
- contact.setText(LinphoneUtils.getUsernameFromAddress(sipUri));
+ contact.setText(lAddress.getUserName());
} else {
contact.setText(sipUri);
}
} else {
- contact.setText(displayName);
+ contact.setText(lContact.getName());
}
}
@@ -1351,10 +1384,10 @@ public class InCallActivity extends FragmentActivity implements
return isCallPaused || isInConference;
}
- private void displayOrHideContactPicture(LinearLayout callView, Uri pictureUri, boolean hide) {
+ private void displayOrHideContactPicture(LinearLayout callView, Uri pictureUri, Uri thumbnailUri, boolean hide) {
AvatarWithShadow contactPicture = (AvatarWithShadow) callView.findViewById(R.id.contactPicture);
if (pictureUri != null) {
- LinphoneUtils.setImagePictureFromUri(callView.getContext(), contactPicture.getView(), Uri.parse(pictureUri.toString()), R.drawable.unknown_small);
+ LinphoneUtils.setImagePictureFromUri(callView.getContext(), contactPicture.getView(), Uri.parse(pictureUri.toString()), thumbnailUri, R.drawable.unknown_small);
}
callView.setVisibility(hide ? View.GONE : View.VISIBLE);
}
@@ -1405,10 +1438,15 @@ public class InCallActivity extends FragmentActivity implements
index++;
}
for (LinphoneCall call : LinphoneManager.getLc().getCalls()) {
- displayCall(resources, call, index);
+ displayCall(resources, call, index);
index++;
}
+ if(LinphoneManager.getLc().getCurrentCall() == null){
+ showAudioView();
+ video.setEnabled(false);
+ }
+
callsList.invalidate();
}
}
diff --git a/src/org/linphone/IncomingCallActivity.java b/src/org/linphone/IncomingCallActivity.java
index 362e05fc1..713c009d0 100644
--- a/src/org/linphone/IncomingCallActivity.java
+++ b/src/org/linphone/IncomingCallActivity.java
@@ -20,11 +20,12 @@ package org.linphone;
import java.util.List;
-import org.linphone.LinphoneSimpleListener.LinphoneOnCallStateChangedListener;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCallParams;
+import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneCoreListenerBase;
import org.linphone.mediastream.Log;
import org.linphone.ui.AvatarWithShadow;
import org.linphone.ui.LinphoneSliders;
@@ -44,7 +45,7 @@ import android.widget.Toast;
*
* @author Guillaume Beraudo
*/
-public class IncomingCallActivity extends Activity implements LinphoneOnCallStateChangedListener, LinphoneSliderTriggered {
+public class IncomingCallActivity extends Activity implements LinphoneSliderTriggered {
private static IncomingCallActivity instance;
@@ -53,6 +54,7 @@ public class IncomingCallActivity extends Activity implements LinphoneOnCallStat
private AvatarWithShadow mPictureView;
private LinphoneCall mCall;
private LinphoneSliders mIncomingCallWidget;
+ private LinphoneCoreListenerBase mListener;
public static IncomingCallActivity instance() {
return instance;
@@ -78,6 +80,19 @@ public class IncomingCallActivity extends Activity implements LinphoneOnCallStat
// "Dial-to-answer" widget for incoming calls.
mIncomingCallWidget = (LinphoneSliders) findViewById(R.id.sliding_widget);
mIncomingCallWidget.setOnTriggerListener(this);
+
+ mListener = new LinphoneCoreListenerBase(){
+ @Override
+ public void callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State state, String message) {
+ if (call == mCall && State.CallEnd == state) {
+ finish();
+ }
+ if (state == State.StreamsRunning) {
+ // The following should not be needed except some devices need it (e.g. Galaxy S).
+ LinphoneManager.getLc().enableSpeaker(LinphoneManager.getLc().isSpeakerEnabled());
+ }
+ }
+ };
super.onCreate(savedInstanceState);
instance = this;
@@ -87,7 +102,10 @@ public class IncomingCallActivity extends Activity implements LinphoneOnCallStat
protected void onResume() {
super.onResume();
instance = this;
- LinphoneManager.addListener(this);
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.addListener(mListener);
+ }
// Only one call ringing at a time is allowed
if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) {
@@ -106,11 +124,12 @@ public class IncomingCallActivity extends Activity implements LinphoneOnCallStat
}
LinphoneAddress address = mCall.getRemoteAddress();
// May be greatly sped up using a drawable cache
- Uri uri = LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, getContentResolver());
- LinphoneUtils.setImagePictureFromUri(this, mPictureView.getView(), uri, R.drawable.unknown_small);
+ Contact contact = ContactsManager.getInstance().findContactWithAddress(getContentResolver(), address);
+ LinphoneUtils.setImagePictureFromUri(this, mPictureView.getView(), contact != null ? contact.getPhotoUri() : null,
+ contact != null ? contact.getThumbnailUri() : null, R.drawable.unknown_small);
// To be done after findUriPictureOfContactAndSetDisplayName called
- mNameView.setText(address.getDisplayName());
+ mNameView.setText(contact != null ? contact.getName() : "");
if (getResources().getBoolean(R.bool.only_display_username_if_unknown)) {
mNumberView.setText(address.getUserName());
} else {
@@ -120,8 +139,11 @@ public class IncomingCallActivity extends Activity implements LinphoneOnCallStat
@Override
protected void onPause() {
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.removeListener(mListener);
+ }
super.onPause();
- LinphoneManager.removeListener(this);
}
@Override
@@ -139,16 +161,7 @@ public class IncomingCallActivity extends Activity implements LinphoneOnCallStat
return super.onKeyDown(keyCode, event);
}
- @Override
- public void onCallStateChanged(LinphoneCall call, State state, String msg) {
- if (call == mCall && State.CallEnd == state) {
- finish();
- }
- if (state == State.StreamsRunning) {
- // The following should not be needed except some devices need it (e.g. Galaxy S).
- LinphoneManager.getLc().enableSpeaker(LinphoneManager.getLc().isSpeakerEnabled());
- }
- }
+
private void decline() {
LinphoneManager.getLc().terminateCall(mCall);
@@ -156,13 +169,8 @@ public class IncomingCallActivity extends Activity implements LinphoneOnCallStat
private void answer() {
LinphoneCallParams params = LinphoneManager.getLc().createDefaultCallParameters();
- if (mCall != null && mCall.getRemoteParams() != null && mCall.getRemoteParams().getVideoEnabled() && LinphoneManager.isInstanciated() && LinphoneManager.getInstance().isAutoAcceptCamera()) {
- params.setVideoEnabled(true);
- } else {
- params.setVideoEnabled(false);
- }
- boolean isLowBandwidthConnection = !LinphoneUtils.isHightBandwidthConnection(this);
+ boolean isLowBandwidthConnection = !LinphoneUtils.isHighBandwidthConnection(this);
if (isLowBandwidthConnection) {
params.enableLowBandwidth(true);
Log.d("Low bandwidth enabled in call params");
@@ -176,7 +184,7 @@ public class IncomingCallActivity extends Activity implements LinphoneOnCallStat
return;
}
final LinphoneCallParams remoteParams = mCall.getRemoteParams();
- if (remoteParams != null && remoteParams.getVideoEnabled() && LinphoneManager.getInstance().isAutoAcceptCamera()) {
+ if (remoteParams != null && remoteParams.getVideoEnabled() && LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests()) {
LinphoneActivity.instance().startVideoActivity(mCall);
} else {
LinphoneActivity.instance().startIncallActivity(mCall);
diff --git a/src/org/linphone/KeepAliveHandler.java b/src/org/linphone/KeepAliveHandler.java
new file mode 100644
index 000000000..5f674893d
--- /dev/null
+++ b/src/org/linphone/KeepAliveHandler.java
@@ -0,0 +1,46 @@
+package org.linphone;
+/*
+KeepAliveHandler.java
+Copyright (C) 2013 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import org.linphone.mediastream.Log;
+
+import android.content.BroadcastReceiver;
+import android.content.Context;
+import android.content.Intent;
+
+public class KeepAliveHandler extends BroadcastReceiver {
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ Log.i("Keep alive handler invoked");
+ if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) {
+ //first refresh registers
+ LinphoneManager.getLc().refreshRegisters();
+ //make sure iterate will have enough time, device will not sleep until exit from this method
+ try {
+ Thread.sleep(2000);
+ } catch (InterruptedException e) {
+ Log.e("Cannot sleep for 2s", e);
+ }
+
+ }
+
+ }
+
+}
diff --git a/src/org/linphone/KeepAliveReceiver.java b/src/org/linphone/KeepAliveReceiver.java
index ed5c9b980..321953df1 100644
--- a/src/org/linphone/KeepAliveReceiver.java
+++ b/src/org/linphone/KeepAliveReceiver.java
@@ -25,7 +25,9 @@ import android.content.Context;
import android.content.Intent;
-
+/*
+ * Purpose of this receiver is to disable keep alives when screen is off
+ * */
public class KeepAliveReceiver extends BroadcastReceiver {
@Override
diff --git a/src/org/linphone/LinphoneActivity.java b/src/org/linphone/LinphoneActivity.java
index 27943b98d..c505e7792 100644
--- a/src/org/linphone/LinphoneActivity.java
+++ b/src/org/linphone/LinphoneActivity.java
@@ -27,41 +27,38 @@ import java.util.Collection;
import java.util.List;
import org.linphone.LinphoneManager.AddressType;
-import org.linphone.LinphoneManager.LinphoneConfigException;
-import org.linphone.LinphoneSimpleListener.LinphoneOnCallStateChangedListener;
-import org.linphone.LinphoneSimpleListener.LinphoneOnMessageReceivedListener;
-import org.linphone.LinphoneSimpleListener.LinphoneOnRegistrationStateChangedListener;
import org.linphone.compatibility.Compatibility;
import org.linphone.core.CallDirection;
import org.linphone.core.LinphoneAddress;
+import org.linphone.core.LinphoneAuthInfo;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCallLog;
import org.linphone.core.LinphoneCallLog.CallStatus;
import org.linphone.core.LinphoneChatMessage;
+import org.linphone.core.LinphoneChatRoom;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.RegistrationState;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
-import org.linphone.core.LinphoneFriend;
-import org.linphone.core.OnlineStatus;
+import org.linphone.core.LinphoneCoreListenerBase;
+import org.linphone.core.LinphoneProxyConfig;
import org.linphone.mediastream.Log;
+import org.linphone.setup.RemoteProvisioningLoginActivity;
import org.linphone.setup.SetupActivity;
import org.linphone.ui.AddressText;
import android.annotation.SuppressLint;
import android.app.Activity;
+import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
-import android.database.Cursor;
+import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
-import android.os.Handler;
-import android.preference.PreferenceManager;
-import android.support.v4.app.DialogFragment;
+import android.provider.ContactsContract;
import android.support.v4.app.Fragment;
import android.support.v4.app.Fragment.SavedState;
import android.support.v4.app.FragmentActivity;
@@ -71,13 +68,13 @@ import android.view.Gravity;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.OrientationEventListener;
+import android.view.Surface;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.view.animation.AnimationUtils;
import android.widget.AdapterView;
-import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.RelativeLayout;
@@ -87,14 +84,13 @@ import android.widget.Toast;
/**
* @author Sylvain Berfini
*/
-public class LinphoneActivity extends FragmentActivity implements
- OnClickListener, ContactPicked, LinphoneOnCallStateChangedListener,
- LinphoneOnMessageReceivedListener,
- LinphoneOnRegistrationStateChangedListener {
+public class LinphoneActivity extends FragmentActivity implements OnClickListener, ContactPicked {
public static final String PREF_FIRST_LAUNCH = "pref_first_launch";
private static final int SETTINGS_ACTIVITY = 123;
private static final int FIRST_LOGIN_ACTIVITY = 101;
- private static final int callActivity = 19;
+ private static final int REMOTE_PROVISIONING_LOGIN_ACTIVITY = 102;
+ private static final int CALL_ACTIVITY = 19;
+ private static final int CHAT_ACTIVITY = 21;
private static LinphoneActivity instance;
@@ -104,13 +100,13 @@ public class LinphoneActivity extends FragmentActivity implements
private LinearLayout menu, mark;
private RelativeLayout contacts, history, settings, chat, aboutChat, aboutSettings;
private FragmentsAvailable currentFragment, nextFragment;
- private Fragment dialerFragment, messageListenerFragment, messageListFragment, friendStatusListenerFragment;
+ private List fragmentsHistory;
+ private Fragment dialerFragment, messageListFragment, friendStatusListenerFragment;
+ private ChatFragment chatFragment;
private SavedState dialerSavedState;
- private boolean preferLinphoneContacts = false, isAnimationDisabled = false, isContactPresenceDisabled = true;
- private Handler mHandler = new Handler();
- private List contactList, sipContactList;
- private Cursor contactCursor, sipContactCursor;
+ private boolean isAnimationDisabled = false, preferLinphoneContacts = false;
private OrientationEventListener mOrientationHelper;
+ private LinphoneCoreListenerBase mListener;
static final boolean isInstanciated() {
return instance != null;
@@ -128,8 +124,10 @@ public class LinphoneActivity extends FragmentActivity implements
if (isTablet() && getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
+ } else if (!isTablet() && getRequestedOrientation() != ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) {
+ setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}
-
+
if (!LinphoneManager.isInstanciated()) {
Log.e("No service running: avoid crash by starting the launcher", this.getClass().getName());
// super.onCreate called earlier
@@ -139,20 +137,37 @@ public class LinphoneActivity extends FragmentActivity implements
}
boolean useFirstLoginActivity = getResources().getBoolean(R.bool.display_account_wizard_at_first_start);
- SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(this);
- if (useFirstLoginActivity && !pref.getBoolean(getString(R.string.first_launch_suceeded_once_key), false)) {
- if (pref.getInt(getString(R.string.pref_extra_accounts), -1) > -1) {
- pref.edit().putBoolean(getString(R.string.first_launch_suceeded_once_key), true);
+ if (LinphonePreferences.instance().isProvisioningLoginViewEnabled()) {
+ Intent wizard = new Intent();
+ wizard.setClass(this, RemoteProvisioningLoginActivity.class);
+ wizard.putExtra("Domain", LinphoneManager.getInstance().wizardLoginViewDomain);
+ startActivityForResult(wizard, REMOTE_PROVISIONING_LOGIN_ACTIVITY);
+ } else if (useFirstLoginActivity && LinphonePreferences.instance().isFirstLaunch()) {
+ if (LinphonePreferences.instance().getAccountCount() > 0) {
+ LinphonePreferences.instance().firstLaunchSuccessful();
} else {
startActivityForResult(new Intent().setClass(this, SetupActivity.class), FIRST_LOGIN_ACTIVITY);
}
}
+ if (getResources().getBoolean(R.bool.use_linphone_tag)) {
+ ContactsManager.getInstance().initializeSyncAccount(getApplicationContext(), getContentResolver());
+ } else {
+ ContactsManager.getInstance().initializeContactManager(getApplicationContext(), getContentResolver());
+ }
+
+ if(!LinphonePreferences.instance().isContactsMigrationDone()){
+ ContactsManager.getInstance().migrateContacts();
+ LinphonePreferences.instance().contactsMigrationDone();
+ }
+
setContentView(R.layout.main);
instance = this;
+ fragmentsHistory = new ArrayList();
initButtons();
currentFragment = nextFragment = FragmentsAvailable.DIALER;
+ fragmentsHistory.add(currentFragment);
if (savedInstanceState == null) {
if (findViewById(R.id.fragmentContainer) != null) {
dialerFragment = new DialerFragment();
@@ -162,15 +177,81 @@ public class LinphoneActivity extends FragmentActivity implements
}
}
+ mListener = new LinphoneCoreListenerBase(){
+ @Override
+ public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) {
+ if(!displayChatMessageNotification(message.getFrom().asStringUriOnly())) {
+ cr.markAsRead();
+ }
+ displayMissedChats(getChatStorage().getUnreadMessageCount());
+ if (messageListFragment != null && messageListFragment.isVisible()) {
+ ((ChatListFragment) messageListFragment).refresh();
+ }
+ }
+
+ @Override
+ public void registrationState(LinphoneCore lc, LinphoneProxyConfig proxy, LinphoneCore.RegistrationState state, String smessage) {
+ if (state.equals(RegistrationState.RegistrationCleared)) {
+ if (lc != null) {
+ LinphoneAuthInfo authInfo = lc.findAuthInfo(proxy.getIdentity(), proxy.getRealm(), proxy.getDomain());
+ if (authInfo != null)
+ lc.removeAuthInfo(authInfo);
+ }
+ }
+ }
+
+ @Override
+ public void callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State state, String message) {
+ if (state == State.IncomingReceived) {
+ startActivity(new Intent(LinphoneActivity.instance(), IncomingCallActivity.class));
+ } else if (state == State.OutgoingInit) {
+ if (call.getCurrentParamsCopy().getVideoEnabled()) {
+ startVideoActivity(call);
+ } else {
+ startIncallActivity(call);
+ }
+ } else if (state == State.CallEnd || state == State.Error || state == State.CallReleased) {
+ // Convert LinphoneCore message for internalization
+ if (message != null && message.equals("Call declined.")) {
+ displayCustomToast(getString(R.string.error_call_declined), Toast.LENGTH_LONG);
+ } else if (message != null && message.equals("Not Found")) {
+ displayCustomToast(getString(R.string.error_user_not_found), Toast.LENGTH_LONG);
+ } else if (message != null && message.equals("Unsupported media type")) {
+ displayCustomToast(getString(R.string.error_incompatible_media), Toast.LENGTH_LONG);
+ } else if (message != null && state == State.Error) {
+ displayCustomToast(getString(R.string.error_unknown) + " - " + message, Toast.LENGTH_LONG);
+ }
+ resetClassicMenuLayoutAndGoBackToCallIfStillRunning();
+ }
+
+ int missedCalls = LinphoneManager.getLc().getMissedCallsCount();
+ displayMissedCalls(missedCalls);
+ }
+ };
+
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.addListener(mListener);
+ }
+
int missedCalls = LinphoneManager.getLc().getMissedCallsCount();
displayMissedCalls(missedCalls);
- int rotation = Compatibility.getRotation(getWindowManager().getDefaultDisplay());
- // Inverse landscape rotation to initiate linphoneCore correctly
- if (rotation == 270)
+ int rotation = getWindowManager().getDefaultDisplay().getRotation();
+ switch (rotation) {
+ case Surface.ROTATION_0:
+ rotation = 0;
+ break;
+ case Surface.ROTATION_90:
rotation = 90;
- else if (rotation == 90)
+ break;
+ case Surface.ROTATION_180:
+ rotation = 180;
+ break;
+ case Surface.ROTATION_270:
rotation = 270;
+ break;
+ }
LinphoneManager.getLc().setDeviceRotation(rotation);
mAlwaysChangingPhoneAngle = rotation;
@@ -178,6 +259,7 @@ public class LinphoneActivity extends FragmentActivity implements
updateAnimationsState();
}
+
private void initButtons() {
menu = (LinearLayout) findViewById(R.id.menu);
mark = (LinearLayout) findViewById(R.id.mark);
@@ -212,25 +294,25 @@ public class LinphoneActivity extends FragmentActivity implements
missedCalls = (TextView) findViewById(R.id.missedCalls);
missedChats = (TextView) findViewById(R.id.missedChats);
}
-
+
private boolean isTablet() {
return getResources().getBoolean(R.bool.isTablet);
}
- private void hideStatusBar() {
+ public void hideStatusBar() {
if (isTablet()) {
return;
}
-
+
findViewById(R.id.status).setVisibility(View.GONE);
findViewById(R.id.fragmentContainer).setPadding(0, 0, 0, 0);
}
- private void showStatusBar() {
+ public void showStatusBar() {
if (isTablet()) {
return;
}
-
+
if (statusFragment != null && !statusFragment.isVisible()) {
// Hack to ensure statusFragment is visible after coming back to
// dialer from chat
@@ -244,7 +326,6 @@ public class LinphoneActivity extends FragmentActivity implements
changeCurrentFragment(newFragmentType, extras, false);
}
- @SuppressWarnings("incomplete-switch")
private void changeCurrentFragment(FragmentsAvailable newFragmentType, Bundle extras, boolean withoutAnimation) {
if (newFragmentType == currentFragment && newFragmentType != FragmentsAvailable.CHAT) {
return;
@@ -272,8 +353,17 @@ public class LinphoneActivity extends FragmentActivity implements
newFragment = new HistoryDetailFragment();
break;
case CONTACTS:
- newFragment = new ContactsFragment();
- friendStatusListenerFragment = newFragment;
+ if (getResources().getBoolean(R.bool.use_android_native_contact_edit_interface)) {
+ Intent i = new Intent();
+ i.setComponent(new ComponentName("com.android.contacts", "com.android.contacts.DialtactsContactsEntryActivity"));
+ i.setAction("android.intent.action.MAIN");
+ i.addCategory("android.intent.category.LAUNCHER");
+ i.addCategory("android.intent.category.DEFAULT");
+ startActivity(i);
+ } else {
+ newFragment = new ContactsFragment();
+ friendStatusListenerFragment = newFragment;
+ }
break;
case CONTACT:
newFragment = new ContactFragment();
@@ -289,7 +379,7 @@ public class LinphoneActivity extends FragmentActivity implements
dialerFragment = newFragment;
break;
case SETTINGS:
- newFragment = new PreferencesFragment();
+ newFragment = new SettingsFragment();
break;
case ACCOUNT_SETTINGS:
newFragment = new AccountPreferencesFragment();
@@ -299,14 +389,15 @@ public class LinphoneActivity extends FragmentActivity implements
case ABOUT_INSTEAD_OF_SETTINGS:
newFragment = new AboutFragment();
break;
- case CHAT:
- newFragment = new ChatFragment();
- messageListenerFragment = newFragment;
- break;
case CHATLIST:
newFragment = new ChatListFragment();
messageListFragment = new Fragment();
break;
+ case CHAT:
+ newFragment = new ChatFragment();
+ break;
+ default:
+ break;
}
if (newFragment != null) {
@@ -320,27 +411,14 @@ public class LinphoneActivity extends FragmentActivity implements
}
private void updateAnimationsState() {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- isAnimationDisabled = getResources().getBoolean(R.bool.disable_animations) || !prefs.getBoolean(getString(R.string.pref_animation_enable_key), false);
- isContactPresenceDisabled = !getResources().getBoolean(R.bool.enable_linphone_friends);
+ isAnimationDisabled = getResources().getBoolean(R.bool.disable_animations) || !LinphonePreferences.instance().areAnimationsEnabled();
}
public boolean isAnimationDisabled() {
return isAnimationDisabled;
}
- public boolean isContactPresenceDisabled() {
- return isContactPresenceDisabled;
- }
-
private void changeFragment(Fragment newFragment, FragmentsAvailable newFragmentType, boolean withoutAnimation) {
- if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) {
- if (newFragmentType == FragmentsAvailable.DIALER) {
- showStatusBar();
- } else {
- hideStatusBar();
- }
- }
if (statusFragment != null) {
statusFragment.closeStatusBar();
}
@@ -360,13 +438,15 @@ public class LinphoneActivity extends FragmentActivity implements
R.anim.slide_out_right_to_left);
}
}
- try {
- getSupportFragmentManager().popBackStackImmediate(newFragmentType.toString(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
- } catch (java.lang.IllegalStateException e) {
+ if (newFragmentType != FragmentsAvailable.DIALER
+ || newFragmentType != FragmentsAvailable.ABOUT_INSTEAD_OF_CHAT
+ || newFragmentType != FragmentsAvailable.ABOUT_INSTEAD_OF_SETTINGS
+ || newFragmentType != FragmentsAvailable.CONTACTS
+ || newFragmentType != FragmentsAvailable.CHATLIST
+ || newFragmentType != FragmentsAvailable.HISTORY) {
+ transaction.addToBackStack(newFragmentType.toString());
}
-
- transaction.addToBackStack(newFragmentType.toString());
transaction.replace(R.id.fragmentContainer, newFragment, newFragmentType.toString());
transaction.commitAllowingStateLoss();
getSupportFragmentManager().executePendingTransactions();
@@ -391,21 +471,21 @@ public class LinphoneActivity extends FragmentActivity implements
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
if (newFragmentType.shouldAddItselfToTheRightOf(currentFragment)) {
ll.setVisibility(View.VISIBLE);
-
+
transaction.addToBackStack(newFragmentType.toString());
transaction.replace(R.id.fragmentContainer2, newFragment);
} else {
- if (newFragmentType == FragmentsAvailable.DIALER
- || newFragmentType == FragmentsAvailable.ABOUT
- || newFragmentType == FragmentsAvailable.ABOUT_INSTEAD_OF_CHAT
+ if (newFragmentType == FragmentsAvailable.DIALER
+ || newFragmentType == FragmentsAvailable.ABOUT
+ || newFragmentType == FragmentsAvailable.ABOUT_INSTEAD_OF_CHAT
|| newFragmentType == FragmentsAvailable.ABOUT_INSTEAD_OF_SETTINGS
- || newFragmentType == FragmentsAvailable.SETTINGS
+ || newFragmentType == FragmentsAvailable.SETTINGS
|| newFragmentType == FragmentsAvailable.ACCOUNT_SETTINGS) {
ll.setVisibility(View.GONE);
} else {
ll.setVisibility(View.INVISIBLE);
}
-
+
if (!withoutAnimation && !isAnimationDisabled && currentFragment.shouldAnimate()) {
if (newFragmentType.isRightOf(currentFragment)) {
transaction.setCustomAnimations(R.anim.slide_in_right_to_left, R.anim.slide_out_right_to_left, R.anim.slide_in_left_to_right, R.anim.slide_out_left_to_right);
@@ -413,28 +493,41 @@ public class LinphoneActivity extends FragmentActivity implements
transaction.setCustomAnimations(R.anim.slide_in_left_to_right, R.anim.slide_out_left_to_right, R.anim.slide_in_right_to_left, R.anim.slide_out_right_to_left);
}
}
-
- try {
- getSupportFragmentManager().popBackStackImmediate(newFragmentType.toString(), FragmentManager.POP_BACK_STACK_INCLUSIVE);
- } catch (java.lang.IllegalStateException e) {
-
- }
-
- transaction.addToBackStack(newFragmentType.toString());
+
transaction.replace(R.id.fragmentContainer, newFragment);
}
transaction.commitAllowingStateLoss();
getSupportFragmentManager().executePendingTransactions();
-
+
currentFragment = newFragmentType;
+ if (newFragmentType == FragmentsAvailable.DIALER
+ || newFragmentType == FragmentsAvailable.ABOUT_INSTEAD_OF_CHAT
+ || newFragmentType == FragmentsAvailable.ABOUT_INSTEAD_OF_SETTINGS
+ || newFragmentType == FragmentsAvailable.SETTINGS
+ || newFragmentType == FragmentsAvailable.CONTACTS
+ || newFragmentType == FragmentsAvailable.CHATLIST
+ || newFragmentType == FragmentsAvailable.HISTORY) {
+ try {
+ getSupportFragmentManager().popBackStackImmediate(null, FragmentManager.POP_BACK_STACK_INCLUSIVE);
+ } catch (java.lang.IllegalStateException e) {
+
+ }
+ }
+ fragmentsHistory.add(currentFragment);
}
public void displayHistoryDetail(String sipUri, LinphoneCallLog log) {
- LinphoneAddress lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri);
- Uri uri = LinphoneUtils.findUriPictureOfContactAndSetDisplayName(lAddress, getContentResolver());
+ LinphoneAddress lAddress;
+ try {
+ lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri);
+ } catch (LinphoneCoreException e) {
+ Log.e("Cannot display history details",e);
+ return;
+ }
+ Contact c = ContactsManager.getInstance().findContactWithAddress(getContentResolver(), lAddress);
- String displayName = lAddress.getDisplayName();
- String pictureUri = uri == null ? null : uri.toString();
+ String displayName = c != null ? c.getName() : null;
+ String pictureUri = c != null && c.getPhotoUri() != null ? c.getPhotoUri().toString() : null;
String status;
if (log.getDirection() == CallDirection.Outgoing) {
@@ -510,6 +603,16 @@ public class LinphoneActivity extends FragmentActivity implements
public void displayAbout() {
changeCurrentFragment(FragmentsAvailable.ABOUT, null);
+ settings.setSelected(true);
+ }
+
+ public boolean displayChatMessageNotification(String address){
+ if(chatFragment != null) {
+ if(chatFragment.getSipUri().equals(address)){
+ return false;
+ }
+ }
+ return true;
}
public void displayChat(String sipUri) {
@@ -517,29 +620,58 @@ public class LinphoneActivity extends FragmentActivity implements
return;
}
- LinphoneAddress lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri);
- Uri uri = LinphoneUtils.findUriPictureOfContactAndSetDisplayName(lAddress, getContentResolver());
- String displayName = lAddress.getDisplayName();
- String pictureUri = uri == null ? null : uri.toString();
+ LinphoneAddress lAddress;
+ try {
+ lAddress = LinphoneCoreFactory.instance().createLinphoneAddress(sipUri);
+ } catch (LinphoneCoreException e) {
+ Log.e("Cannot display chat",e);
+ return;
+ }
+ Contact contact = ContactsManager.getInstance().findContactWithAddress(getContentResolver(), lAddress);
+ String displayName = contact != null ? contact.getName() : null;
- if (currentFragment == FragmentsAvailable.CHATLIST || currentFragment == FragmentsAvailable.CHAT) {
- Fragment fragment2 = getSupportFragmentManager().findFragmentById(R.id.fragmentContainer2);
- if (fragment2 != null && fragment2.isVisible() && currentFragment == FragmentsAvailable.CHAT) {
- ChatFragment chatFragment = (ChatFragment) fragment2;
- chatFragment.changeDisplayedChat(sipUri, displayName, pictureUri);
- } else {
- Bundle extras = new Bundle();
- extras.putString("SipUri", sipUri);
- if (lAddress.getDisplayName() != null) {
- extras.putString("DisplayName", displayName);
- extras.putString("PictureUri", pictureUri);
+ String pictureUri = null;
+ String thumbnailUri = null;
+ if(contact != null && contact.getPhotoUri() != null){
+ pictureUri = contact.getPhotoUri().toString();
+ thumbnailUri = contact.getThumbnailUri().toString();
+ }
+
+ if (isTablet()){
+ if (currentFragment == FragmentsAvailable.CHATLIST || currentFragment == FragmentsAvailable.CHAT){
+ Fragment fragment2 = getSupportFragmentManager().findFragmentById(R.id.fragmentContainer2);
+ if (fragment2 != null && fragment2.isVisible() && currentFragment == FragmentsAvailable.CHAT) {
+ ChatFragment chatFragment = (ChatFragment) fragment2;
+ chatFragment.changeDisplayedChat(sipUri, displayName, pictureUri);
+ } else {
+ Bundle extras = new Bundle();
+ extras.putString("SipUri", sipUri);
+ if (contact != null) {
+ extras.putString("DisplayName", displayName);
+ extras.putString("PictureUri", pictureUri);
+ extras.putString("ThumbnailUri", thumbnailUri);
+ }
+ changeCurrentFragment(FragmentsAvailable.CHAT, extras);
}
- changeCurrentFragment(FragmentsAvailable.CHAT, extras);
+ } else {
+ changeCurrentFragment(FragmentsAvailable.CHATLIST, null);
+ displayChat(sipUri);
+ }
+ if (messageListFragment != null && messageListFragment.isVisible()) {
+ ((ChatListFragment) messageListFragment).refresh();
}
} else {
- changeCurrentFragment(FragmentsAvailable.CHATLIST, null);
- displayChat(sipUri);
+ Intent intent = new Intent(this, ChatActivity.class);
+ intent.putExtra("SipUri", sipUri);
+ if (contact != null) {
+ intent.putExtra("DisplayName", contact.getName());
+ intent.putExtra("PictureUri", pictureUri);
+ intent.putExtra("ThumbnailUri", thumbnailUri);
+ }
+ startOrientationSensor();
+ startActivityForResult(intent, CHAT_ACTIVITY);
}
+
LinphoneService.instance().resetMessageNotifCount();
LinphoneService.instance().removeMessageNotification();
displayMissedChats(getChatStorage().getUnreadMessageCount());
@@ -618,8 +750,8 @@ public class LinphoneActivity extends FragmentActivity implements
case ABOUT_INSTEAD_OF_SETTINGS:
aboutSettings.setSelected(true);
break;
- case CHAT:
case CHATLIST:
+ case CHAT:
chat.setSelected(true);
break;
}
@@ -632,9 +764,7 @@ public class LinphoneActivity extends FragmentActivity implements
}
public void updateChatFragment(ChatFragment fragment) {
- messageListenerFragment = fragment;
- // Hack to maintain soft input flags
- getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE | WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
+ chatFragment = fragment;
}
public void updateChatListFragment(ChatListFragment fragment) {
@@ -648,11 +778,6 @@ public class LinphoneActivity extends FragmentActivity implements
public void updateStatusFragment(StatusFragment fragment) {
statusFragment = fragment;
-
- LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
- if (lc != null && lc.getDefaultProxyConfig() != null) {
- statusFragment.registrationStateChanged(LinphoneManager.getLc().getDefaultProxyConfig().getState());
- }
}
public void displaySettings() {
@@ -662,32 +787,10 @@ public class LinphoneActivity extends FragmentActivity implements
public void applyConfigChangesIfNeeded() {
if (nextFragment != FragmentsAvailable.SETTINGS && nextFragment != FragmentsAvailable.ACCOUNT_SETTINGS) {
- reloadConfig();
updateAnimationsState();
}
}
- private void reloadConfig() {
- LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
-
- if (lc != null && (lc.isInComingInvitePending() || lc.isIncall())) {
- Log.w("Call in progress => settings not applied");
- return;
- }
-
- try {
- LinphoneManager.getInstance().initFromConf();
- lc.setVideoPolicy(LinphoneManager.getInstance().isAutoInitiateVideoCalls(), LinphoneManager.getInstance().isAutoAcceptCamera());
- } catch (LinphoneException e) {
- if (!(e instanceof LinphoneConfigException)) {
- Log.e(e, "Cannot update config");
- return;
- }
-
- LinphoneActivity.instance().showPreferenceErrorDialog(e.getMessage());
- }
- }
-
public void displayAccountSettings(int accountNumber) {
Bundle bundle = new Bundle();
bundle.putInt("Account", accountNumber);
@@ -719,19 +822,7 @@ public class LinphoneActivity extends FragmentActivity implements
getChatStorage().deleteDraft(sipUri);
}
- @Override
- public void onMessageReceived(LinphoneAddress from, LinphoneChatMessage message, int id) {
- ChatFragment chatFragment = ((ChatFragment) messageListenerFragment);
- if (messageListenerFragment != null && messageListenerFragment.isVisible() && chatFragment.getSipUri().equals(from.asStringUriOnly())) {
- chatFragment.onMessageReceived(id, from, message);
- getChatStorage().markMessageAsRead(id);
- } else if (LinphoneService.isReady()) {
- displayMissedChats(getChatStorage().getUnreadMessageCount());
- if (messageListFragment != null && messageListFragment.isVisible()) {
- ((ChatListFragment) messageListFragment).refresh();
- }
- }
- }
+
public void updateMissedChatCount() {
displayMissedChats(getChatStorage().getUnreadMessageCount());
@@ -739,6 +830,10 @@ public class LinphoneActivity extends FragmentActivity implements
public int onMessageSent(String to, String message) {
getChatStorage().deleteDraft(to);
+ if (messageListFragment != null && messageListFragment.isVisible()) {
+ ((ChatListFragment) messageListFragment).refresh();
+ }
+
return getChatStorage().saveTextMessage("", to, message, System.currentTimeMillis());
}
@@ -755,101 +850,49 @@ public class LinphoneActivity extends FragmentActivity implements
getChatStorage().updateMessageStatus(to, id, newState);
}
- @Override
- public void onRegistrationStateChanged(RegistrationState state) {
- if (statusFragment != null) {
- LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
- if (lc != null && lc.getDefaultProxyConfig() != null)
- statusFragment.registrationStateChanged(lc.getDefaultProxyConfig().getState());
- else
- statusFragment.registrationStateChanged(RegistrationState.RegistrationNone);
- }
- }
-
private void displayMissedCalls(final int missedCallsCount) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (missedCallsCount > 0) {
- missedCalls.setText(missedCallsCount + "");
- missedCalls.setVisibility(View.VISIBLE);
- if (!isAnimationDisabled) {
- missedCalls.startAnimation(AnimationUtils.loadAnimation(LinphoneActivity.this, R.anim.bounce));
- }
- } else {
- missedCalls.clearAnimation();
- missedCalls.setVisibility(View.GONE);
- }
+ if (missedCallsCount > 0) {
+ missedCalls.setText(missedCallsCount + "");
+ missedCalls.setVisibility(View.VISIBLE);
+ if (!isAnimationDisabled) {
+ missedCalls.startAnimation(AnimationUtils.loadAnimation(LinphoneActivity.this, R.anim.bounce));
}
- });
+ } else {
+ missedCalls.clearAnimation();
+ missedCalls.setVisibility(View.GONE);
+ }
}
private void displayMissedChats(final int missedChatCount) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (missedChatCount > 0) {
- missedChats.setText(missedChatCount + "");
- if (missedChatCount > 99) {
- missedChats.setTextSize(12);
- } else {
- missedChats.setTextSize(20);
- }
- missedChats.setVisibility(View.VISIBLE);
- if (!isAnimationDisabled) {
- missedChats.startAnimation(AnimationUtils.loadAnimation(LinphoneActivity.this, R.anim.bounce));
- }
- } else {
- missedChats.clearAnimation();
- missedChats.setVisibility(View.GONE);
- }
- }
- });
- }
-
- @Override
- public void onCallStateChanged(LinphoneCall call, State state, String message) {
- if (state == State.IncomingReceived) {
- startActivity(new Intent(this, IncomingCallActivity.class));
- } else if (state == State.OutgoingInit) {
- if (call.getCurrentParamsCopy().getVideoEnabled()) {
- startVideoActivity(call);
+ if (missedChatCount > 0) {
+ missedChats.setText(missedChatCount + "");
+ if (missedChatCount > 99) {
+ missedChats.setTextSize(12);
} else {
- startIncallActivity(call);
+ missedChats.setTextSize(20);
}
- } else if (state == State.CallEnd || state == State.Error || state == State.CallReleased) {
- // Convert LinphoneCore message for internalization
- if (message != null && message.equals("Call declined.")) {
- displayCustomToast(getString(R.string.error_call_declined), Toast.LENGTH_LONG);
- } else if (message != null && message.equals("User not found.")) {
- displayCustomToast(getString(R.string.error_user_not_found), Toast.LENGTH_LONG);
- } else if (message != null && message.equals("Incompatible media parameters.")) {
- displayCustomToast(getString(R.string.error_incompatible_media), Toast.LENGTH_LONG);
+ missedChats.setVisibility(View.VISIBLE);
+ if (!isAnimationDisabled) {
+ missedChats.startAnimation(AnimationUtils.loadAnimation(LinphoneActivity.this, R.anim.bounce));
}
- resetClassicMenuLayoutAndGoBackToCallIfStillRunning();
+ } else {
+ missedChats.clearAnimation();
+ missedChats.setVisibility(View.GONE);
}
-
- int missedCalls = LinphoneManager.getLc().getMissedCallsCount();
- displayMissedCalls(missedCalls);
}
public void displayCustomToast(final String message, final int duration) {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- LayoutInflater inflater = getLayoutInflater();
- View layout = inflater.inflate(R.layout.toast, (ViewGroup) findViewById(R.id.toastRoot));
+ LayoutInflater inflater = getLayoutInflater();
+ View layout = inflater.inflate(R.layout.toast, (ViewGroup) findViewById(R.id.toastRoot));
- TextView toastText = (TextView) layout.findViewById(R.id.toastMessage);
- toastText.setText(message);
+ TextView toastText = (TextView) layout.findViewById(R.id.toastMessage);
+ toastText.setText(message);
- final Toast toast = new Toast(getApplicationContext());
- toast.setGravity(Gravity.CENTER, 0, 0);
- toast.setDuration(duration);
- toast.setView(layout);
- toast.show();
- }
- });
+ final Toast toast = new Toast(getApplicationContext());
+ toast.setGravity(Gravity.CENTER, 0, 0);
+ toast.setDuration(duration);
+ toast.setView(layout);
+ toast.show();
}
@Override
@@ -859,13 +902,11 @@ public class LinphoneActivity extends FragmentActivity implements
// extras.putString("DisplayName", name);
// extras.putString("Photo", photo == null ? null : photo.toString());
// changeCurrentFragment(FragmentsAvailable.DIALER, extras);
-
+
AddressType address = new AddressText(this, null);
address.setDisplayedName(name);
address.setText(number);
- if (LinphoneManager.getLc().getCallsNb() == 0) {
- LinphoneManager.getInstance().newOutgoingCall(address);
- }
+ LinphoneManager.getInstance().newOutgoingCall(address);
}
public void setAddressAndGoToDialer(String number) {
@@ -883,14 +924,30 @@ public class LinphoneActivity extends FragmentActivity implements
Intent intent = new Intent(this, InCallActivity.class);
intent.putExtra("VideoEnabled", true);
startOrientationSensor();
- startActivityForResult(intent, callActivity);
+ startActivityForResult(intent, CALL_ACTIVITY);
}
public void startIncallActivity(LinphoneCall currentCall) {
Intent intent = new Intent(this, InCallActivity.class);
intent.putExtra("VideoEnabled", false);
startOrientationSensor();
- startActivityForResult(intent, callActivity);
+ startActivityForResult(intent, CALL_ACTIVITY);
+ }
+
+ public void sendLogs(Context context, String info){
+ final String appName = context.getString(R.string.app_name);
+
+ Intent i = new Intent(Intent.ACTION_SEND);
+ i.putExtra(Intent.EXTRA_EMAIL, new String[]{ context.getString(R.string.about_bugreport_email) });
+ i.putExtra(Intent.EXTRA_SUBJECT, appName + " Logs");
+ i.putExtra(Intent.EXTRA_TEXT, info);
+ i.setType("application/zip");
+
+ try {
+ startActivity(Intent.createChooser(i, "Send mail..."));
+ } catch (android.content.ActivityNotFoundException ex) {
+ Log.e(ex);
+ }
}
/**
@@ -904,7 +961,6 @@ public class LinphoneActivity extends FragmentActivity implements
}
private int mAlwaysChangingPhoneAngle = -1;
- private AcceptNewFriendDialog acceptNewFriendDialog;
private class LocalOrientationEventListener extends OrientationEventListener {
public LocalOrientationEventListener(Context context) {
@@ -943,198 +999,6 @@ public class LinphoneActivity extends FragmentActivity implements
}
}
- public void showPreferenceErrorDialog(String message) {
-
- }
-
- public List getAllContacts() {
- return contactList;
- }
-
- public List getSIPContacts() {
- return sipContactList;
- }
-
- public Cursor getAllContactsCursor() {
- return contactCursor;
- }
-
- public Cursor getSIPContactsCursor() {
- return sipContactCursor;
- }
-
- public void setLinphoneContactsPrefered(boolean isPrefered) {
- preferLinphoneContacts = isPrefered;
- }
-
- public boolean isLinphoneContactsPrefered() {
- return preferLinphoneContacts;
- }
-
- private void refreshStatus(OnlineStatus status) {
- if (LinphoneManager.isInstanciated()) {
- LinphoneManager.getLcIfManagerNotDestroyedOrNull().setPresenceInfo(0, "", status);
- }
- }
-
- public void onNewSubscriptionRequestReceived(LinphoneFriend friend,
- String sipUri) {
- if (isContactPresenceDisabled) {
- return;
- }
-
- sipUri = sipUri.replace("<", "").replace(">", "");
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
- if (prefs.getBoolean(getString(R.string.pref_auto_accept_friends_key), false)) {
- Contact contact = findContactWithSipAddress(sipUri);
- if (contact != null) {
- friend.enableSubscribes(true);
- try {
- LinphoneManager.getLc().addFriend(friend);
- contact.setFriend(friend);
- } catch (LinphoneCoreException e) {
- e.printStackTrace();
- }
- }
- } else {
- Contact contact = findContactWithSipAddress(sipUri);
- if (contact != null) {
- FragmentManager fm = getSupportFragmentManager();
- acceptNewFriendDialog = new AcceptNewFriendDialog(contact, sipUri);
- acceptNewFriendDialog.show(fm, "New Friend Request Dialog");
- }
- }
- }
-
- private Contact findContactWithSipAddress(String sipUri) {
- if (!sipUri.startsWith("sip:")) {
- sipUri = "sip:" + sipUri;
- }
-
- for (Contact contact : sipContactList) {
- for (String addr : contact.getNumerosOrAddresses()) {
- if (addr.equals(sipUri)) {
- return contact;
- }
- }
- }
- return null;
- }
-
- public void onNotifyPresenceReceived(LinphoneFriend friend) {
- if (!isContactPresenceDisabled && currentFragment == FragmentsAvailable.CONTACTS && friendStatusListenerFragment != null) {
- ((ContactsFragment) friendStatusListenerFragment).invalidate();
- }
- }
-
- public boolean newFriend(Contact contact, String sipUri) {
- LinphoneFriend friend = LinphoneCoreFactory.instance().createLinphoneFriend(sipUri);
- friend.enableSubscribes(true);
- friend.setIncSubscribePolicy(LinphoneFriend.SubscribePolicy.SPAccept);
- try {
- LinphoneManager.getLc().addFriend(friend);
- contact.setFriend(friend);
- return true;
- } catch (LinphoneCoreException e) {
- e.printStackTrace();
- }
- return false;
- }
-
- private void acceptNewFriend(Contact contact, String sipUri, boolean accepted) {
- acceptNewFriendDialog.dismissAllowingStateLoss();
- if (accepted) {
- newFriend(contact, sipUri);
- }
- }
-
- public boolean removeFriend(Contact contact, String sipUri) {
- LinphoneFriend friend = LinphoneManager.getLc().findFriendByAddress(sipUri);
- if (friend != null) {
- friend.enableSubscribes(false);
- LinphoneManager.getLc().removeFriend(friend);
- contact.setFriend(null);
- return true;
- }
- return false;
- }
-
- private void searchFriendAndAddToContact(Contact contact) {
- if (contact == null || contact.getNumerosOrAddresses() == null) {
- return;
- }
-
- for (String sipUri : contact.getNumerosOrAddresses()) {
- if (LinphoneUtils.isSipAddress(sipUri)) {
- LinphoneFriend friend = LinphoneManager.getLc().findFriendByAddress(sipUri);
- if (friend != null) {
- friend.enableSubscribes(true);
- friend.setIncSubscribePolicy(LinphoneFriend.SubscribePolicy.SPAccept);
- contact.setFriend(friend);
- break;
- }
- }
- }
- }
-
- public void removeContactFromLists(Contact contact) {
- if (contactList.contains(contact)) {
- contactList.remove(contact);
- contactCursor = Compatibility.getContactsCursor(getContentResolver());
- }
- if (sipContactList.contains(contact)) {
- sipContactList.remove(contact);
- sipContactCursor = Compatibility.getSIPContactsCursor(getContentResolver());
- }
- }
-
- public synchronized void prepareContactsInBackground() {
- if (contactCursor != null) {
- contactCursor.close();
- }
- if (sipContactCursor != null) {
- sipContactCursor.close();
- }
-
- contactCursor = Compatibility.getContactsCursor(getContentResolver());
- sipContactCursor = Compatibility.getSIPContactsCursor(getContentResolver());
-
- Thread sipContactsHandler = new Thread(new Runnable() {
- @Override
- public void run() {
- for (int i = 0; i < sipContactCursor.getCount(); i++) {
- Contact contact = Compatibility.getContact(getContentResolver(), sipContactCursor, i);
- if (contact == null)
- continue;
-
- contact.refresh(getContentResolver());
- if (!isContactPresenceDisabled) {
- searchFriendAndAddToContact(contact);
- }
- sipContactList.add(contact);
- }
- for (int i = 0; i < contactCursor.getCount(); i++) {
- Contact contact = Compatibility.getContact(getContentResolver(), contactCursor, i);
- if (contact == null)
- continue;
-
- for (Contact c : sipContactList) {
- if (c != null && c.getID().equals(contact.getID())) {
- contact = c;
- break;
- }
- }
- contactList.add(contact);
- }
- }
- });
-
- contactList = new ArrayList();
- sipContactList = new ArrayList();
-
- sipContactsHandler.start();
- }
-
private void initInCallMenuLayout(boolean callTransfer) {
selectMenu(FragmentsAvailable.DIALER);
if (dialerFragment != null) {
@@ -1143,25 +1007,20 @@ public class LinphoneActivity extends FragmentActivity implements
}
public void resetClassicMenuLayoutAndGoBackToCallIfStillRunning() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- if (dialerFragment != null) {
- ((DialerFragment) dialerFragment).resetLayout(false);
- }
+ if (dialerFragment != null) {
+ ((DialerFragment) dialerFragment).resetLayout(false);
+ }
- if (LinphoneManager.isInstanciated() && LinphoneManager.getLc().getCallsNb() > 0) {
- LinphoneCall call = LinphoneManager.getLc().getCalls()[0];
- if (call.getState() == LinphoneCall.State.IncomingReceived) {
- startActivity(new Intent(LinphoneActivity.this, IncomingCallActivity.class));
- } else if (call.getCurrentParamsCopy().getVideoEnabled()) {
- startVideoActivity(call);
- } else {
- startIncallActivity(call);
- }
- }
+ if (LinphoneManager.isInstanciated() && LinphoneManager.getLc().getCallsNb() > 0) {
+ LinphoneCall call = LinphoneManager.getLc().getCalls()[0];
+ if (call.getState() == LinphoneCall.State.IncomingReceived) {
+ startActivity(new Intent(LinphoneActivity.this, IncomingCallActivity.class));
+ } else if (call.getCurrentParamsCopy().getVideoEnabled()) {
+ startVideoActivity(call);
+ } else {
+ startIncallActivity(call);
}
- });
+ }
}
public FragmentsAvailable getCurrentFragment() {
@@ -1169,12 +1028,9 @@ public class LinphoneActivity extends FragmentActivity implements
}
public ChatStorage getChatStorage() {
- if (LinphoneManager.getInstance().chatStorage == null) {
- return new ChatStorage(this);
- }
- return LinphoneManager.getInstance().chatStorage;
+ return ChatStorage.getInstance();
}
-
+
public void addContact(String displayName, String sipUri)
{
if (getResources().getBoolean(R.bool.use_android_native_contact_edit_interface)) {
@@ -1186,7 +1042,7 @@ public class LinphoneActivity extends FragmentActivity implements
changeCurrentFragment(FragmentsAvailable.EDIT_CONTACT, extras);
}
}
-
+
public void editContact(Contact contact)
{
if (getResources().getBoolean(R.bool.use_android_native_contact_edit_interface)) {
@@ -1197,8 +1053,9 @@ public class LinphoneActivity extends FragmentActivity implements
extras.putSerializable("Contact", contact);
changeCurrentFragment(FragmentsAvailable.EDIT_CONTACT, extras);
}
+
}
-
+
public void editContact(Contact contact, String sipAddress)
{
if (getResources().getBoolean(R.bool.use_android_native_contact_edit_interface)) {
@@ -1213,7 +1070,6 @@ public class LinphoneActivity extends FragmentActivity implements
}
public void exit() {
- refreshStatus(OnlineStatus.Offline);
finish();
stopService(new Intent(ACTION_MAIN).setClass(this, LinphoneService.class));
}
@@ -1228,7 +1084,8 @@ public class LinphoneActivity extends FragmentActivity implements
changeCurrentFragment(newFragment, null, true);
selectMenu(newFragment);
}
- } else if (requestCode == callActivity) {
+ } else if (resultCode == Activity.RESULT_FIRST_USER && requestCode == CALL_ACTIVITY) {
+ getIntent().putExtra("PreviousActivity", CALL_ACTIVITY);
boolean callTransfer = data == null ? false : data.getBooleanExtra("Transfer", false);
if (LinphoneManager.getLc().getCallsNb() > 0) {
initInCallMenuLayout(callTransfer);
@@ -1240,50 +1097,58 @@ public class LinphoneActivity extends FragmentActivity implements
}
}
+ @Override
+ protected void onPause() {
+ getIntent().putExtra("PreviousActivity", 0);
+ super.onPause();
+ }
+
@Override
protected void onResume() {
super.onResume();
-
+
if (!LinphoneService.isReady()) {
startService(new Intent(ACTION_MAIN).setClass(this, LinphoneService.class));
}
- // Remove to avoid duplication of the listeners
- LinphoneManager.removeListener(this);
- LinphoneManager.addListener(this);
-
- prepareContactsInBackground();
+ ContactsManager.getInstance().prepareContactsInBackground();
updateMissedChatCount();
-
+
displayMissedCalls(LinphoneManager.getLc().getMissedCallsCount());
- if (LinphoneManager.getLc().getCalls().length > 0) {
- LinphoneCall call = LinphoneManager.getLc().getCalls()[0];
- LinphoneCall.State callState = call.getState();
- if (callState == State.IncomingReceived) {
- startActivity(new Intent(this, IncomingCallActivity.class));
- }
+ LinphoneManager.getInstance().changeStatusToOnline();
+
+ if(getIntent().getIntExtra("PreviousActivity", 0) != CALL_ACTIVITY){
+ if (LinphoneManager.getLc().getCalls().length > 0) {
+ LinphoneCall call = LinphoneManager.getLc().getCalls()[0];
+ LinphoneCall.State callState = call.getState();
+ if (callState == State.IncomingReceived) {
+ startActivity(new Intent(this, IncomingCallActivity.class));
+ } else {
+
+ if (call.getCurrentParamsCopy().getVideoEnabled()) {
+ startVideoActivity(call);
+ } else {
+ startIncallActivity(call);
+ }
+ }
+ }
}
-
- refreshStatus(OnlineStatus.Online);
- }
-
- @Override
- protected void onPause() {
- super.onPause();
- refreshStatus(OnlineStatus.Away);
}
@Override
protected void onDestroy() {
- LinphoneManager.removeListener(this);
-
if (mOrientationHelper != null) {
mOrientationHelper.disable();
mOrientationHelper = null;
}
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.removeListener(mListener);
+ }
+
instance = null;
super.onDestroy();
@@ -1323,13 +1188,21 @@ public class LinphoneActivity extends FragmentActivity implements
}
} else {
if (dialerFragment != null) {
- ((DialerFragment) dialerFragment).newOutgoingCall(intent);
+ if (extras != null && extras.containsKey("SipUriOrNumber")) {
+ if (getResources().getBoolean(R.bool.automatically_start_intercepted_outgoing_gsm_call)) {
+ ((DialerFragment) dialerFragment).newOutgoingCall(extras.getString("SipUriOrNumber"));
+ } else {
+ ((DialerFragment) dialerFragment).displayTextInAddressBar(extras.getString("SipUriOrNumber"));
+ }
+ } else {
+ ((DialerFragment) dialerFragment).newOutgoingCall(intent);
+ }
}
if (LinphoneManager.getLc().getCalls().length > 0) {
LinphoneCall calls[] = LinphoneManager.getLc().getCalls();
if (calls.length > 0) {
LinphoneCall call = calls[0];
-
+
if (call != null && call.getState() != LinphoneCall.State.IncomingReceived) {
if (call.getCurrentParamsCopy().getVideoEnabled()) {
startVideoActivity(call);
@@ -1338,7 +1211,7 @@ public class LinphoneActivity extends FragmentActivity implements
}
}
}
-
+
// If a call is ringing, start incomingcallactivity
Collection incoming = new ArrayList();
incoming.add(LinphoneCall.State.IncomingReceived);
@@ -1355,8 +1228,13 @@ public class LinphoneActivity extends FragmentActivity implements
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
- if (currentFragment == FragmentsAvailable.DIALER) {
- boolean isBackgroundModeActive = PreferenceManager.getDefaultSharedPreferences(this).getBoolean(getString(R.string.pref_background_mode_key), getResources().getBoolean(R.bool.pref_background_mode_default));
+ if (currentFragment == FragmentsAvailable.DIALER
+ || currentFragment == FragmentsAvailable.CONTACTS
+ || currentFragment == FragmentsAvailable.HISTORY
+ || currentFragment == FragmentsAvailable.CHATLIST
+ || currentFragment == FragmentsAvailable.ABOUT_INSTEAD_OF_CHAT
+ || currentFragment == FragmentsAvailable.ABOUT_INSTEAD_OF_SETTINGS) {
+ boolean isBackgroundModeActive = LinphonePreferences.instance().isBackgroundModeEnabled();
if (!isBackgroundModeActive) {
stopService(new Intent(Intent.ACTION_MAIN).setClass(this, LinphoneService.class));
finish();
@@ -1364,23 +1242,8 @@ public class LinphoneActivity extends FragmentActivity implements
return true;
}
} else {
- if (!isTablet()) {
- int backStackEntryCount = getSupportFragmentManager().getBackStackEntryCount();
- if (backStackEntryCount <= 1) {
- showStatusBar();
- }
-
+ if (isTablet()) {
if (currentFragment == FragmentsAvailable.SETTINGS) {
- showStatusBar();
- reloadConfig();
- updateAnimationsState();
- } else if (currentFragment == FragmentsAvailable.CHATLIST) {
- //Hack to ensure display the status bar on some devices
- showStatusBar();
- }
- } else {
- if (currentFragment == FragmentsAvailable.SETTINGS) {
- reloadConfig();
updateAnimationsState();
}
}
@@ -1392,45 +1255,9 @@ public class LinphoneActivity extends FragmentActivity implements
}
return super.onKeyDown(keyCode, event);
}
-
- @SuppressLint("ValidFragment")
- class AcceptNewFriendDialog extends DialogFragment {
- private Contact contact;
- private String sipUri;
-
- public AcceptNewFriendDialog(Contact c, String a) {
- contact = c;
- sipUri = a;
- }
-
- @Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.new_friend_request_dialog, container);
-
- getDialog().setTitle(R.string.linphone_friend_new_request_title);
-
- Button yes = (Button) view.findViewById(R.id.yes);
- yes.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- acceptNewFriend(contact, sipUri, true);
- }
- });
-
- Button no = (Button) view.findViewById(R.id.no);
- no.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- acceptNewFriend(contact, sipUri, false);
- }
- });
-
- return view;
- }
- }
}
interface ContactPicked {
void setAddresGoToDialerAndCall(String number, String name, Uri photo);
void goToDialer();
-}
\ No newline at end of file
+}
diff --git a/src/org/linphone/LinphoneLauncherActivity.java b/src/org/linphone/LinphoneLauncherActivity.java
index 2e295ab68..7ac7a70c2 100644
--- a/src/org/linphone/LinphoneLauncherActivity.java
+++ b/src/org/linphone/LinphoneLauncherActivity.java
@@ -20,8 +20,8 @@ package org.linphone;
import static android.content.Intent.ACTION_MAIN;
-import org.linphone.compatibility.Compatibility;
import org.linphone.mediastream.Log;
+import org.linphone.setup.RemoteProvisioningActivity;
import org.linphone.tutorials.TutorialLauncherActivity;
import android.app.Activity;
@@ -58,11 +58,6 @@ public class LinphoneLauncherActivity extends Activity {
setContentView(R.layout.launcher);
mHandler = new Handler();
-
-
- if (getResources().getBoolean(R.bool.enable_push_id)) {
- Compatibility.initPushNotificationService(this);
- }
if (LinphoneService.isReady()) {
onServiceReady();
@@ -78,6 +73,8 @@ public class LinphoneLauncherActivity extends Activity {
final Class extends Activity> classToStart;
if (getResources().getBoolean(R.bool.show_tutorials_instead_of_app)) {
classToStart = TutorialLauncherActivity.class;
+ } else if (getResources().getBoolean(R.bool.display_sms_remote_provisioning_activity) && LinphonePreferences.instance().isFirstRemoteProvisioning()) {
+ classToStart = RemoteProvisioningActivity.class;
} else {
classToStart = LinphoneActivity.class;
}
diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java
index 393b659db..028b13fcc 100644
--- a/src/org/linphone/LinphoneManager.java
+++ b/src/org/linphone/LinphoneManager.java
@@ -21,60 +21,49 @@ package org.linphone;
import static android.media.AudioManager.MODE_RINGTONE;
import static android.media.AudioManager.STREAM_RING;
import static android.media.AudioManager.STREAM_VOICE_CALL;
-import static org.linphone.R.string.pref_codec_amr_key;
-import static org.linphone.R.string.pref_codec_amrwb_key;
-import static org.linphone.R.string.pref_codec_ilbc_key;
-import static org.linphone.R.string.pref_codec_speex16_key;
-import static org.linphone.R.string.pref_codec_speex32_key;
-import static org.linphone.R.string.pref_video_enable_key;
-import static org.linphone.core.LinphoneCall.State.CallEnd;
-import static org.linphone.core.LinphoneCall.State.Error;
-import static org.linphone.core.LinphoneCall.State.CallReleased;
-import static org.linphone.core.LinphoneCall.State.IncomingReceived;
import java.io.File;
+import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.util.ArrayList;
+import java.nio.ByteBuffer;
import java.util.HashSet;
-import java.util.List;
import java.util.Set;
import java.util.Timer;
import java.util.TimerTask;
-import org.linphone.LinphoneSimpleListener.ConnectivityChangedListener;
-import org.linphone.LinphoneSimpleListener.LinphoneOnAudioChangedListener;
-import org.linphone.LinphoneSimpleListener.LinphoneOnAudioChangedListener.AudioState;
-import org.linphone.LinphoneSimpleListener.LinphoneOnDTMFReceivedListener;
-import org.linphone.LinphoneSimpleListener.LinphoneOnMessageReceivedListener;
-import org.linphone.LinphoneSimpleListener.LinphoneServiceListener;
import org.linphone.compatibility.Compatibility;
import org.linphone.core.CallDirection;
import org.linphone.core.LinphoneAddress;
-import org.linphone.core.LinphoneAuthInfo;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCallParams;
import org.linphone.core.LinphoneCallStats;
import org.linphone.core.LinphoneChatMessage;
import org.linphone.core.LinphoneChatRoom;
+import org.linphone.core.LinphoneContent;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
-import org.linphone.core.LinphoneCore.FirewallPolicy;
import org.linphone.core.LinphoneCore.GlobalState;
-import org.linphone.core.LinphoneCore.MediaEncryption;
+import org.linphone.core.LinphoneCore.LogCollectionUploadState;
import org.linphone.core.LinphoneCore.RegistrationState;
-import org.linphone.core.LinphoneCore.Transports;
+import org.linphone.core.LinphoneCore.RemoteProvisioningState;
import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
import org.linphone.core.LinphoneCoreListener;
+import org.linphone.core.LinphoneEvent;
import org.linphone.core.LinphoneFriend;
+import org.linphone.core.LinphoneInfoMessage;
import org.linphone.core.LinphoneProxyConfig;
import org.linphone.core.PayloadType;
+import org.linphone.core.PresenceActivityType;
+import org.linphone.core.PresenceModel;
+import org.linphone.core.PublishState;
+import org.linphone.core.SubscriptionState;
+import org.linphone.core.TunnelConfig;
import org.linphone.mediastream.Log;
import org.linphone.mediastream.Version;
-import org.linphone.mediastream.video.capture.AndroidVideoApi5JniWrapper;
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration;
import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration.AndroidCamera;
import org.linphone.mediastream.video.capture.hwconf.Hacks;
@@ -82,17 +71,11 @@ import org.linphone.mediastream.video.capture.hwconf.Hacks;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.Activity;
-import android.bluetooth.BluetoothAdapter;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
-import android.bluetooth.BluetoothProfile;
import android.content.BroadcastReceiver;
import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.SharedPreferences;
-import android.content.SharedPreferences.Editor;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.Resources;
import android.hardware.Sensor;
@@ -103,11 +86,12 @@ import android.media.AudioManager;
import android.media.MediaPlayer;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
+import android.net.Uri;
import android.os.Build;
+import android.os.Handler;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Vibrator;
-import android.preference.PreferenceManager;
import android.provider.Settings;
import android.provider.Settings.SettingNotFoundException;
import android.telephony.TelephonyManager;
@@ -118,17 +102,17 @@ import android.view.WindowManager;
import android.widget.Toast;
/**
- *
+ *
* Manager of the low level LibLinphone stuff.
* Including:
* - Starting C liblinphone
* - Reacting to C liblinphone state changes
* - Calling Linphone android service listener methods
* - Interacting from Android GUI/service with low level SIP stuff/
- *
- *
+ *
+ *
* Add Service Listener to react to Linphone state changes.
- *
+ *
* @author Guillaume Beraudo
*
*/
@@ -138,103 +122,70 @@ public class LinphoneManager implements LinphoneCoreListener {
private Context mServiceContext;
private AudioManager mAudioManager;
private PowerManager mPowerManager;
- private ConnectivityManager mConnectivityManager;
- private SharedPreferences mPref;
private Resources mR;
+ private LinphonePreferences mPrefs;
private LinphoneCore mLc;
- private static Transports initialTransports;
- private static LinphonePreferenceManager sLPref;
private String lastLcStatusMessage;
private String basePath;
private static boolean sExited;
- private String contactParams;
private boolean mAudioFocused;
- private boolean isNetworkReachable;
-
+ private int mLastNetworkType=-1;
+ private ConnectivityManager mConnectivityManager;
+ private Handler mHandler = new Handler();
private WakeLock mIncallWakeLock;
-
- private BluetoothAdapter mBluetoothAdapter;
- private BluetoothHeadset mBluetoothHeadset;
- private BluetoothProfile.ServiceListener mProfileListener;
- private BroadcastReceiver bluetoothReiceiver = new BluetoothManager();
- public boolean isBluetoothScoConnected;
- public boolean isUsingBluetoothAudioRoute;
- private boolean mBluetoothStarted;
-
- public ChatStorage chatStorage;
- private static List simpleListeners = new ArrayList();
- public static void addListener(LinphoneSimpleListener listener) {
- if (!simpleListeners.contains(listener)) {
- simpleListeners.add(listener);
- }
- }
- public static void removeListener(LinphoneSimpleListener listener) {
- simpleListeners.remove(listener);
- }
+ public String wizardLoginViewDomain = null;
- protected LinphoneManager(final Context c, LinphoneServiceListener listener) {
- sExited=false;
+ protected LinphoneManager(final Context c) {
+ sExited = false;
mServiceContext = c;
- mListenerDispatcher = new ListenerDispatcher(listener);
basePath = c.getFilesDir().getAbsolutePath();
mLPConfigXsd = basePath + "/lpconfig.xsd";
- mLinphoneInitialConfigFile = basePath + "/linphonerc";
+ mLinphoneFactoryConfigFile = basePath + "/linphonerc";
mLinphoneConfigFile = basePath + "/.linphonerc";
mLinphoneRootCaFile = basePath + "/rootca.pem";
- mRingSoundFile = basePath + "/oldphone_mono.wav";
+ mRingSoundFile = basePath + "/oldphone_mono.wav";
mRingbackSoundFile = basePath + "/ringback.wav";
mPauseSoundFile = basePath + "/toy_mono.wav";
+ mChatDatabaseFile = basePath + "/linphone-history.db";
+ mErrorToneFile = basePath + "/error.wav";
- sLPref = LinphonePreferenceManager.getInstance(c);
+ mPrefs = LinphonePreferences.instance();
mAudioManager = ((AudioManager) c.getSystemService(Context.AUDIO_SERVICE));
mVibrator = (Vibrator) c.getSystemService(Context.VIBRATOR_SERVICE);
- mPref = PreferenceManager.getDefaultSharedPreferences(c);
mPowerManager = (PowerManager) c.getSystemService(Context.POWER_SERVICE);
mConnectivityManager = (ConnectivityManager) c.getSystemService(Context.CONNECTIVITY_SERVICE);
mR = c.getResources();
-
- chatStorage = new ChatStorage(mServiceContext);
}
private static final int LINPHONE_VOLUME_STREAM = STREAM_VOICE_CALL;
private static final int dbStep = 4;
/** Called when the activity is first created. */
private final String mLPConfigXsd;
- private final String mLinphoneInitialConfigFile;
+ private final String mLinphoneFactoryConfigFile;
private final String mLinphoneRootCaFile;
- private final String mLinphoneConfigFile;
- private final String mRingSoundFile;
+ public final String mLinphoneConfigFile;
+ private final String mRingSoundFile;
private final String mRingbackSoundFile;
private final String mPauseSoundFile;
+ private final String mChatDatabaseFile;
+ private final String mErrorToneFile;
- private Timer mTimer = new Timer("Linphone scheduler");
+ private Timer mTimer;
private BroadcastReceiver mKeepAliveReceiver = new KeepAliveReceiver();
private void routeAudioToSpeakerHelper(boolean speakerOn) {
- isUsingBluetoothAudioRoute = false;
- if (mAudioManager != null && mBluetoothStarted) {
- //Compatibility.setAudioManagerInCallMode(mAudioManager);
- mAudioManager.stopBluetoothSco();
- mAudioManager.setBluetoothScoOn(false);
- mBluetoothStarted=false;
- }
-
- if (!speakerOn) {
- mLc.enableSpeaker(false);
- } else {
- mLc.enableSpeaker(true);
- }
-
- for (LinphoneOnAudioChangedListener listener : getSimpleListeners(LinphoneOnAudioChangedListener.class)) {
- listener.onAudioStateChanged(speakerOn ? AudioState.SPEAKER : AudioState.EARPIECE);
- }
+ Log.w("Routing audio to " + (speakerOn ? "speaker" : "earpiece") + ", disabling bluetooth audio route");
+ BluetoothManager.getInstance().disableBluetoothSCO();
+
+ mLc.enableSpeaker(speakerOn);
}
+
public void routeAudioToSpeaker() {
routeAudioToSpeakerHelper(true);
}
-
+
public String getUserAgent() throws NameNotFoundException {
StringBuilder userAgent = new StringBuilder();
userAgent.append("LinphoneAndroid/" + mServiceContext.getPackageManager().getPackageInfo(mServiceContext.getPackageName(),0).versionCode);
@@ -245,124 +196,61 @@ public class LinphoneManager implements LinphoneCoreListener {
return userAgent.toString();
}
- /**
- *
- */
public void routeAudioToReceiver() {
routeAudioToSpeakerHelper(false);
}
-
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- @SuppressWarnings("deprecation")
- public void startBluetooth() {
- mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- if (mBluetoothAdapter.isEnabled()) {
- if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
- mProfileListener = new BluetoothProfile.ServiceListener() {
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- public void onServiceConnected(int profile, BluetoothProfile proxy) {
- if (profile == BluetoothProfile.HEADSET) {
- mBluetoothHeadset = (BluetoothHeadset) proxy;
- isBluetoothScoConnected = true;
- Log.d("Bluetooth headset connected");
- }
- }
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- public void onServiceDisconnected(int profile) {
- if (profile == BluetoothProfile.HEADSET) {
- mBluetoothHeadset = null;
- isBluetoothScoConnected = false;
- Log.d("Bluetooth headset disconnected");
- routeAudioToReceiver();
- }
- }
- };
- mBluetoothAdapter.getProfileProxy(mServiceContext, mProfileListener, BluetoothProfile.HEADSET);
- } else {
- try {
- mServiceContext.unregisterReceiver(bluetoothReiceiver);
- } catch (Exception e) {}
-
- Intent currentValue = mServiceContext.registerReceiver(bluetoothReiceiver, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED));
- int state = currentValue == null ? 0 : currentValue.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 0);
- if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
- isBluetoothScoConnected = true;
- }
- }
- } else {
- isBluetoothScoConnected = false;
- scoDisconnected();
- routeAudioToReceiver();
- }
- }
-
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
- public boolean routeAudioToBluetooth() {
- BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
- if (bluetoothAdapter.isEnabled() && mAudioManager.isBluetoothScoAvailableOffCall()) {
- mAudioManager.setBluetoothScoOn(true);
- mAudioManager.startBluetoothSco();
- mBluetoothStarted=true;
-
- if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
- isUsingBluetoothAudioRoute = false;
- if (mBluetoothHeadset != null) {
- List devices = mBluetoothHeadset.getConnectedDevices();
- for (final BluetoothDevice dev : devices) {
- isUsingBluetoothAudioRoute |= mBluetoothHeadset.getConnectionState(dev) == BluetoothHeadset.STATE_CONNECTED;
- }
- }
-
- if (!isUsingBluetoothAudioRoute) {
- Log.d("No bluetooth device available");
- scoDisconnected();
- } else {
- //Why is this for:
- //mAudioManager.setMode(AudioManager.MODE_IN_CALL);
- for (LinphoneOnAudioChangedListener listener : getSimpleListeners(LinphoneOnAudioChangedListener.class)) {
- listener.onAudioStateChanged(AudioState.SPEAKER);
- }
- }
- }
- return isUsingBluetoothAudioRoute;
- }
-
- return false;
- }
-
- public void scoConnected() {
- Log.i("Bluetooth sco connected!");
- isBluetoothScoConnected = true;
- }
-
- public void scoDisconnected() {
- Log.w("Bluetooth sco disconnected!");
- isUsingBluetoothAudioRoute = false;
- isBluetoothScoConnected = false;
- if (mAudioManager != null) {
- //why is this for ?
- //mAudioManager.setMode(AudioManager.MODE_NORMAL);
- mAudioManager.stopBluetoothSco();
- mAudioManager.setBluetoothScoOn(false);
- }
- }
- public synchronized static final LinphoneManager createAndStart(
- Context c, LinphoneServiceListener listener) {
+ public synchronized static final LinphoneManager createAndStart(Context c) {
if (instance != null)
throw new RuntimeException("Linphone Manager is already initialized");
-
- instance = new LinphoneManager(c, listener);
+
+ instance = new LinphoneManager(c);
instance.startLibLinphone(c);
TelephonyManager tm = (TelephonyManager) c.getSystemService(Context.TELEPHONY_SERVICE);
boolean gsmIdle = tm.getCallState() == TelephonyManager.CALL_STATE_IDLE;
setGsmIdle(gsmIdle);
-
- if (Version.isVideoCapable())
- AndroidVideoApi5JniWrapper.setAndroidSdkVersion(Version.sdk());
+
return instance;
}
+ private boolean isPresenceModelActivitySet() {
+ LinphoneCore lc = getLcIfManagerNotDestroyedOrNull();
+ if (isInstanciated() && lc != null) {
+ return lc.getPresenceModel() != null && lc.getPresenceModel().getActivity() != null;
+ }
+ return false;
+ }
+
+ public void changeStatusToOnline() {
+ LinphoneCore lc = getLcIfManagerNotDestroyedOrNull();
+ if (isInstanciated() && lc != null && isPresenceModelActivitySet() && lc.getPresenceModel().getActivity().getType() != PresenceActivityType.Online) {
+ lc.getPresenceModel().getActivity().setType(PresenceActivityType.Online);
+ } else if (isInstanciated() && lc != null && !isPresenceModelActivitySet()) {
+ PresenceModel model = LinphoneCoreFactory.instance().createPresenceModel(PresenceActivityType.Online, null);
+ lc.setPresenceModel(model);
+ }
+ }
+
+ public void changeStatusToOnThePhone() {
+ LinphoneCore lc = getLcIfManagerNotDestroyedOrNull();
+ if (isInstanciated() && isPresenceModelActivitySet() && lc.getPresenceModel().getActivity().getType() != PresenceActivityType.OnThePhone) {
+ lc.getPresenceModel().getActivity().setType(PresenceActivityType.OnThePhone);
+ } else if (isInstanciated() && !isPresenceModelActivitySet()) {
+ PresenceModel model = LinphoneCoreFactory.instance().createPresenceModel(PresenceActivityType.OnThePhone, null);
+ lc.setPresenceModel(model);
+ }
+ }
+
+ public void changeStatusToOffline() {
+ LinphoneCore lc = getLcIfManagerNotDestroyedOrNull();
+ if (isInstanciated() && isPresenceModelActivitySet() && lc.getPresenceModel().getActivity().getType() != PresenceActivityType.Offline) {
+ lc.getPresenceModel().getActivity().setType(PresenceActivityType.Offline);
+ } else if (isInstanciated() && !isPresenceModelActivitySet()) {
+ PresenceModel model = LinphoneCoreFactory.instance().createPresenceModel(PresenceActivityType.Offline, null);
+ lc.setPresenceModel(model);
+ }
+ }
+
public static synchronized final LinphoneManager getInstance() {
if (instance != null) return instance;
@@ -373,18 +261,21 @@ public class LinphoneManager implements LinphoneCoreListener {
throw new RuntimeException("Linphone Manager should be created before accessed");
}
-
+
public static synchronized final LinphoneCore getLc() {
return getInstance().mLc;
}
-
+
public String getLPConfigXsdPath() {
return mLPConfigXsd;
}
public void newOutgoingCall(AddressType address) {
String to = address.getText().toString();
+ newOutgoingCall(to, address.getDisplayedName());
+ }
+ public void newOutgoingCall(String to, String displayName) {
// if (mLc.isIncall()) {
// listenerDispatcher.tryingNewOutgoingCallButAlreadyInCall();
// return;
@@ -398,31 +289,27 @@ public class LinphoneManager implements LinphoneCoreListener {
LinphoneProxyConfig lpc = mLc.getDefaultProxyConfig();
if (mR.getBoolean(R.bool.forbid_self_call) && lpc!=null && lAddress.asStringUriOnly().equals(lpc.getIdentity())) {
- mListenerDispatcher.tryingNewOutgoingCallButWrongDestinationAddress();
return;
}
} catch (LinphoneCoreException e) {
- mListenerDispatcher.tryingNewOutgoingCallButWrongDestinationAddress();
return;
}
- lAddress.setDisplayName(address.getDisplayedName());
+ lAddress.setDisplayName(displayName);
+
+ boolean isLowBandwidthConnection = !LinphoneUtils.isHighBandwidthConnection(LinphoneService.instance().getApplicationContext());
- boolean isLowBandwidthConnection = !LinphoneUtils.isHightBandwidthConnection(LinphoneService.instance().getApplicationContext());
-
if (mLc.isNetworkReachable()) {
try {
if (Version.isVideoCapable()) {
- boolean prefVideoEnable = isVideoEnabled();
- int key = R.string.pref_video_initiate_call_with_video_key;
- boolean prefInitiateWithVideo = getPrefBoolean(key, false);
+ boolean prefVideoEnable = mPrefs.isVideoEnabled();
+ boolean prefInitiateWithVideo = mPrefs.shouldInitiateVideoCall();
CallManager.getInstance().inviteAddress(lAddress, prefVideoEnable && prefInitiateWithVideo, isLowBandwidthConnection);
} else {
CallManager.getInstance().inviteAddress(lAddress, false, isLowBandwidthConnection);
}
-
-
+
+
} catch (LinphoneCoreException e) {
- mListenerDispatcher.tryingNewOutgoingCallButCannotGetCallParameters();
return;
}
} else if (LinphoneActivity.isInstanciated()) {
@@ -431,10 +318,10 @@ public class LinphoneManager implements LinphoneCoreListener {
Log.e("Error: " + getString(R.string.error_network_unreachable));
}
}
-
+
private void resetCameraFromPreferences() {
- boolean useFrontCam = getPrefBoolean(R.string.pref_video_use_front_camera_key, mR.getBoolean(R.bool.pref_video_use_front_camera_default));
-
+ boolean useFrontCam = mPrefs.useFrontCam();
+
int camId = 0;
AndroidCamera[] cameras = AndroidCameraConfiguration.retrieveCameras();
for (AndroidCamera androidCamera : cameras) {
@@ -444,7 +331,7 @@ public class LinphoneManager implements LinphoneCoreListener {
LinphoneManager.getLc().setVideoDevice(camId);
}
-
+
public static interface AddressType {
void setText(CharSequence s);
CharSequence getText();
@@ -459,7 +346,7 @@ public class LinphoneManager implements LinphoneCoreListener {
public void onAlreadyInCall();
}
- public boolean toggleEnableCamera() {
+ public boolean toggleEnableCamera() {
if (mLc.isIncall()) {
boolean enabled = !mLc.getCurrentCall().cameraEnabled();
enableCamera(mLc.getCurrentCall(), enabled);
@@ -467,6 +354,7 @@ public class LinphoneManager implements LinphoneCoreListener {
}
return false;
}
+
public void enableCamera(LinphoneCall call, boolean enable) {
if (call != null) {
call.enableCamera(enable);
@@ -498,6 +386,18 @@ public class LinphoneManager implements LinphoneCoreListener {
}
}
+ public void initTunnelFromConf() {
+ if (!mLc.isTunnelAvailable())
+ return;
+
+ NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
+ mLc.tunnelCleanServers();
+ TunnelConfig config = mPrefs.getTunnelConfig();
+ if (config.getHost() != null) {
+ mLc.tunnelAddServer(config);
+ manageTunnelServer(info);
+ }
+ }
private boolean isTunnelNeeded(NetworkInfo info) {
if (info == null) {
@@ -505,7 +405,7 @@ public class LinphoneManager implements LinphoneCoreListener {
return false;
}
- String pref = getPrefString(R.string.pref_tunnel_mode_key, R.string.default_tunnel_mode_entry_value);
+ String pref = mPrefs.getTunnelMode();
if (getString(R.string.tunnel_mode_entry_value_always).equals(pref)) {
return true;
@@ -520,20 +420,20 @@ public class LinphoneManager implements LinphoneCoreListener {
return false;
}
- public void manageTunnelServer(NetworkInfo info) {
+ private void manageTunnelServer(NetworkInfo info) {
if (mLc == null) return;
if (!mLc.isTunnelAvailable()) return;
Log.i("Managing tunnel");
if (isTunnelNeeded(info)) {
Log.i("Tunnel need to be activated");
- mLc.tunnelEnable(true);
+ mLc.tunnelSetMode(LinphoneCore.TunnelMode.enable);
} else {
Log.i("Tunnel should not be used");
- String pref = getPrefString(R.string.pref_tunnel_mode_key, R.string.default_tunnel_mode_entry_value);
- mLc.tunnelEnable(false);
+ String pref = mPrefs.getTunnelMode();
+ mLc.tunnelSetMode(LinphoneCore.TunnelMode.disable);
if (getString(R.string.tunnel_mode_entry_value_auto).equals(pref)) {
- mLc.tunnelAutoDetect();
+ mLc.tunnelSetMode(LinphoneCore.TunnelMode.auto);
}
}
}
@@ -542,83 +442,130 @@ public class LinphoneManager implements LinphoneCoreListener {
try {
copyAssetsFromPackage();
//traces alway start with traces enable to not missed first initialization
-
- boolean isDebugLogEnabled = !(mR.getBoolean(R.bool.disable_every_log)) && getPrefBoolean(R.string.pref_debug_key, mR.getBoolean(R.bool.pref_debug_default));
+ boolean isDebugLogEnabled = !(mR.getBoolean(R.bool.disable_every_log));
LinphoneCoreFactory.instance().setDebugMode(isDebugLogEnabled, getString(R.string.app_name));
-
- // Try to get remote provisioning
- String remote_provisioning = (getPrefString(R.string.pref_remote_provisioning_key, mR.getString(R.string.pref_remote_provisioning_default)));
- if(remote_provisioning != null && remote_provisioning.length() > 0 && RemoteProvisioning.isAvailable()) {
- RemoteProvisioning.download(remote_provisioning, mLinphoneConfigFile);
- }
-
- mLc = LinphoneCoreFactory.instance().createLinphoneCore(this, mLinphoneConfigFile, mLinphoneInitialConfigFile, null);
- mLc.getConfig().setInt("sip", "store_auth_info", 0);
- mLc.setContext(c);
+ LinphoneCoreFactory.instance().enableLogCollection(isDebugLogEnabled);
+
+ mLc = LinphoneCoreFactory.instance().createLinphoneCore(this, mLinphoneConfigFile, mLinphoneFactoryConfigFile, null, c);
+
try {
- String versionName = c.getPackageManager().getPackageInfo(c.getPackageName(), 0).versionName;
- if (versionName == null) {
- versionName = String.valueOf(c.getPackageManager().getPackageInfo(c.getPackageName(), 0).versionCode);
- }
- mLc.setUserAgent("LinphoneAndroid", versionName);
- } catch (NameNotFoundException e) {
- Log.e(e, "cannot get version name");
+ initLiblinphone();
+ } catch (LinphoneCoreException e) {
+ Log.e(e);
}
- mLc.enableIpv6(getPrefBoolean(R.string.pref_ipv6_key, false));
- mLc.setZrtpSecretsCache(basePath + "/zrtp_secrets");
-
- mLc.setRing(null);
- mLc.setRootCA(mLinphoneRootCaFile);
- mLc.setPlayFile(mPauseSoundFile);
-
- int availableCores = Runtime.getRuntime().availableProcessors();
- Log.w("MediaStreamer : " + availableCores + " cores detected and configured");
- mLc.setCpuCount(availableCores);
-
- try {
- initFromConf();
- } catch (LinphoneException e) {
- Log.w("no config ready yet");
- }
-
TimerTask lTask = new TimerTask() {
@Override
public void run() {
- mLc.iterate();
+ UIThreadDispatcher.dispatch(new Runnable() {
+ @Override
+ public void run() {
+ if (mLc != null) {
+ mLc.iterate();
+ }
+ }
+ });
}
};
/*use schedule instead of scheduleAtFixedRate to avoid iterate from being call in burst after cpu wake up*/
- mTimer.schedule(lTask, 0, 20);
-
- IntentFilter lFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
- lFilter.addAction(Intent.ACTION_SCREEN_OFF);
- mServiceContext.registerReceiver(mKeepAliveReceiver, lFilter);
-
- startBluetooth();
- resetCameraFromPreferences();
+ mTimer = new Timer("Linphone scheduler");
+ mTimer.schedule(lTask, 0, 20);
}
catch (Exception e) {
+ e.printStackTrace();
Log.e(e, "Cannot start linphone");
}
}
- private void copyAssetsFromPackage() throws IOException {
- copyIfNotExist(R.raw.oldphone_mono,mRingSoundFile);
- copyIfNotExist(R.raw.ringback,mRingbackSoundFile);
- copyIfNotExist(R.raw.toy_mono,mPauseSoundFile);
- copyFromPackage(R.raw.linphonerc, new File(mLinphoneInitialConfigFile).getName());
- copyIfNotExist(R.raw.lpconfig, new File(mLPConfigXsd).getName());
- copyIfNotExist(R.raw.rootca, new File(mLinphoneRootCaFile).getName());
+ private synchronized void initLiblinphone() throws LinphoneCoreException {
+ boolean isDebugLogEnabled = !(mR.getBoolean(R.bool.disable_every_log)) && mPrefs.isDebugEnabled();
+ LinphoneCoreFactory.instance().setDebugMode(isDebugLogEnabled, getString(R.string.app_name));
+ LinphoneCoreFactory.instance().enableLogCollection(isDebugLogEnabled);
+
+ PreferencesMigrator prefMigrator = new PreferencesMigrator(mServiceContext);
+ prefMigrator.migrateRemoteProvisioningUriIfNeeded();
+ prefMigrator.migrateSharingServerUrlIfNeeded();
+
+ if (prefMigrator.isMigrationNeeded()) {
+ prefMigrator.doMigration();
+ }
+
+ // Some devices could be using software AEC before
+ // This will disable it in favor of hardware AEC if available
+ if (prefMigrator.isEchoMigratioNeeded()) {
+ Log.d("Echo canceller configuration need to be updated");
+ prefMigrator.doEchoMigration();
+ mPrefs.echoConfigurationUpdated();
+ }
+
+ mLc.setContext(mServiceContext);
+ mLc.setZrtpSecretsCache(basePath + "/zrtp_secrets");
+
+ try {
+ String versionName = mServiceContext.getPackageManager().getPackageInfo(mServiceContext.getPackageName(), 0).versionName;
+ if (versionName == null) {
+ versionName = String.valueOf(mServiceContext.getPackageManager().getPackageInfo(mServiceContext.getPackageName(), 0).versionCode);
+ }
+ mLc.setUserAgent("LinphoneAndroid", versionName);
+ } catch (NameNotFoundException e) {
+ Log.e(e, "cannot get version name");
+ }
+
+ if (mR.getBoolean(R.bool.use_linphonecore_ringing)) {
+ disableRinging();
+ } else {
+ mLc.setRing(null);
+ }
+ mLc.setRootCA(mLinphoneRootCaFile);
+ mLc.setPlayFile(mPauseSoundFile);
+ mLc.setChatDatabasePath(mChatDatabaseFile);
+ //mLc.setCallErrorTone(Reason.NotFound, mErrorToneFile);
+
+ int availableCores = Runtime.getRuntime().availableProcessors();
+ Log.w("MediaStreamer : " + availableCores + " cores detected and configured");
+ mLc.setCpuCount(availableCores);
+
+ int migrationResult = getLc().migrateToMultiTransport();
+ Log.d("Migration to multi transport result = " + migrationResult);
+
+ if (mServiceContext.getResources().getBoolean(R.bool.enable_push_id)) {
+ Compatibility.initPushNotificationService(mServiceContext);
+ }
+
+ IntentFilter lFilter = new IntentFilter(Intent.ACTION_SCREEN_ON);
+ lFilter.addAction(Intent.ACTION_SCREEN_OFF);
+ mServiceContext.registerReceiver(mKeepAliveReceiver, lFilter);
+
+ updateNetworkReachability();
+
+ if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
+ BluetoothManager.getInstance().initBluetooth();
+ }
+ resetCameraFromPreferences();
+
+ mLc.setFileTransferServer(LinphonePreferences.instance().getSharingPictureServerUrl());
}
- private void copyIfNotExist(int ressourceId,String target) throws IOException {
+
+ private void copyAssetsFromPackage() throws IOException {
+ copyIfNotExist(R.raw.oldphone_mono, mRingSoundFile);
+ copyIfNotExist(R.raw.ringback, mRingbackSoundFile);
+ copyIfNotExist(R.raw.toy_mono, mPauseSoundFile);
+ copyIfNotExist(R.raw.incoming_chat, mErrorToneFile);
+ copyIfNotExist(R.raw.linphonerc_default, mLinphoneConfigFile);
+ copyFromPackage(R.raw.linphonerc_factory, new File(mLinphoneFactoryConfigFile).getName());
+ copyIfNotExist(R.raw.lpconfig, mLPConfigXsd);
+ copyIfNotExist(R.raw.rootca, mLinphoneRootCaFile);
+ }
+
+ public void copyIfNotExist(int ressourceId, String target) throws IOException {
File lFileToCopy = new File(target);
- if (!lFileToCopy.exists()) {
- copyFromPackage(ressourceId,lFileToCopy.getName());
+ if (!lFileToCopy.exists()) {
+ copyFromPackage(ressourceId,lFileToCopy.getName());
}
}
- private void copyFromPackage(int ressourceId,String target) throws IOException{
- FileOutputStream lOutputStream = mServiceContext.openFileOutput (target, 0);
+
+ public void copyFromPackage(int ressourceId, String target) throws IOException{
+ FileOutputStream lOutputStream = mServiceContext.openFileOutput (target, 0);
InputStream lInputStream = mR.openRawResource(ressourceId);
int readByte;
byte[] buff = new byte[8048];
@@ -636,7 +583,7 @@ public class LinphoneManager implements LinphoneCoreListener {
}
return false;
}
-
+
public boolean detectAudioCodec(String mime){
for (PayloadType audioCodec : mLc.getAudioCodecs()) {
if (mime.equals(audioCodec.getMime())) return true;
@@ -644,376 +591,49 @@ public class LinphoneManager implements LinphoneCoreListener {
return false;
}
- void initMediaEncryption(){
- String pref = getPrefString(R.string.pref_media_encryption_key, R.string.pref_media_encryption_key_none);
- MediaEncryption me=MediaEncryption.None;
- if (pref.equals(getString(R.string.pref_media_encryption_key_srtp)))
- me = MediaEncryption.SRTP;
- else if (pref.equals(getString(R.string.pref_media_encryption_key_zrtp)))
- me = MediaEncryption.ZRTP;
- Log.i("Media encryption set to " + pref);
- mLc.setMediaEncryption(me);
- }
-
- private void initFromConfTunnel(){
- if (!mLc.isTunnelAvailable())
- return;
-
- NetworkInfo info = mConnectivityManager.getActiveNetworkInfo();
- mLc.tunnelCleanServers();
- String host = getString(R.string.tunnel_host);
- if (host == null || host.length() == 0)
- host = mPref.getString(getString(R.string.pref_tunnel_host_key), "");
- int port = Integer.parseInt(getPrefString(R.string.pref_tunnel_port_key, "443"));
- mLc.tunnelAddServerAndMirror(host, port, 12345,500);
- manageTunnelServer(info);
- }
-
- public void initAccounts() throws LinphoneCoreException {
- mLc.clearAuthInfos();
- mLc.clearProxyConfigs();
-
- for (int i = 0; i < getPrefExtraAccountsNumber(); i++) {
- String key = i == 0 ? "" : String.valueOf(i);
- if (!getPrefBoolean(getString(R.string.pref_disable_account_key) + key, false)) {
- initAccount(key, i == getPrefInt(R.string.pref_default_account_key, 0));
- }
- }
-
- LinphoneProxyConfig lDefaultProxyConfig = mLc.getDefaultProxyConfig();
- if (lDefaultProxyConfig != null) {
- //prefix
- String lPrefix = getPrefString(R.string.pref_prefix_key, null);
- if (lPrefix != null) {
- lDefaultProxyConfig.setDialPrefix(lPrefix);
- }
- //escape +
- lDefaultProxyConfig.setDialEscapePlus(getPrefBoolean(R.string.pref_escape_plus_key, false));
- } else if (LinphoneService.isReady()) {
- LinphoneService.instance().onRegistrationStateChanged(RegistrationState.RegistrationNone, null);
- }
- }
-
- private void initAccount(String key, boolean defaultAccount) throws LinphoneCoreException {
- String username = getPrefString(getString(R.string.pref_username_key) + key, null);
- String password = getPrefString(getString(R.string.pref_passwd_key) + key, null);
- String domain = getPrefString(getString(R.string.pref_domain_key) + key, null);
- if (username != null && username.length() > 0 && password != null) {
- LinphoneAuthInfo lAuthInfo = LinphoneCoreFactory.instance().createAuthInfo(username, password, null);
- mLc.addAuthInfo(lAuthInfo);
-
- if (domain != null && domain.length() > 0) {
- String identity = "sip:" + username +"@" + domain;
- String proxy = getPrefString(getString(R.string.pref_proxy_key) + key, null);
- if (proxy == null || proxy.length() == 0) {
- proxy = "sip:" + domain;
- }
- if (!proxy.startsWith("sip:")) {
- proxy = "sip:" + proxy;
- }
-
- LinphoneProxyConfig proxycon = LinphoneCoreFactory.instance().createProxyConfig(identity, proxy, null, true);
- String defaultExpire = getString(R.string.pref_expire_default);
- proxycon.setExpires(tryToParseIntValue(getPrefString(R.string.pref_expire_key, defaultExpire), defaultExpire));
-
- // Add parameters for push notifications
- if (mR.getBoolean(R.bool.enable_push_id)) {
- String regId = getPrefString(R.string.push_reg_id_key, null);
- String appId = getString(R.string.push_sender_id);
- if (regId != null && getPrefBoolean(R.string.pref_push_notification_key, mR.getBoolean(R.bool.pref_push_notification_default))) {
- String contactInfos = "app-id=" + appId + ";pn-type=google;pn-tok=" + regId + ";pn-msg-str=IM_MSG;pn-call-str=IC_MSG;pn-call-snd=ring.caf;pn-msg-snd=msg.caf";
- proxycon.setContactParameters(contactInfos);
- }
- } else if (contactParams != null) {
- proxycon.setContactParameters(contactParams);
- }
- mLc.addProxyConfig(proxycon);
-
- //outbound proxy
- if (getPrefBoolean(getString(R.string.pref_enable_outbound_proxy_key) + key, false)) {
- proxycon.setRoute(proxy);
- } else {
- proxycon.setRoute(null);
- }
- proxycon.done();
-
- if (defaultAccount) {
- mLc.setDefaultProxyConfig(proxycon);
- }
- }
- }
- }
-
- private void readAndSetAudioAndVideoPorts() throws NumberFormatException {
- int aPortStart, aPortEnd, vPortStart, vPortEnd;
- int defaultAudioPort, defaultVideoPort;
- defaultAudioPort = Integer.parseInt(getString(R.string.default_audio_port));
- defaultVideoPort = Integer.parseInt(getString(R.string.default_video_port));
- aPortStart = aPortEnd = defaultAudioPort;
- vPortStart = vPortEnd = defaultVideoPort;
-
- String audioPort = getPrefString(R.string.pref_audio_port_key, String.valueOf(aPortStart));
- String videoPort = getPrefString(R.string.pref_video_port_key, String.valueOf(vPortStart));
-
- if (audioPort.contains("-")) {
- // Port range
- aPortStart = Integer.parseInt(audioPort.split("-")[0]);
- aPortEnd = Integer.parseInt(audioPort.split("-")[1]);
- } else {
- try {
- aPortStart = aPortEnd = Integer.parseInt(audioPort);
- } catch (NumberFormatException nfe) {
- aPortStart = aPortEnd = defaultAudioPort;
- }
- }
-
- if (videoPort.contains("-")) {
- // Port range
- vPortStart = Integer.parseInt(videoPort.split("-")[0]);
- vPortEnd = Integer.parseInt(videoPort.split("-")[1]);
- } else {
- try {
- vPortStart = vPortEnd = Integer.parseInt(videoPort);
- } catch (NumberFormatException nfe) {
- vPortStart = vPortEnd = defaultVideoPort;
- }
- }
-
- if (aPortStart >= aPortEnd) {
- mLc.setAudioPort(aPortStart);
- } else {
- mLc.setAudioPortRange(aPortStart, aPortEnd);
- }
-
- if (vPortStart >= vPortEnd) {
- mLc.setVideoPort(vPortStart);
- } else {
- mLc.setVideoPortRange(vPortStart, vPortEnd);
- }
- }
-
- private int tryToParseIntValue(String valueToParse, String defaultValue) {
- return tryToParseIntValue(valueToParse, Integer.parseInt(defaultValue));
- }
-
- private int tryToParseIntValue(String valueToParse, int defaultValue) {
- try {
- int returned = Integer.parseInt(valueToParse);
- return returned;
- } catch (NumberFormatException nfe) {
-
- }
- return defaultValue;
- }
-
- public void setContactParams(String params) {
- contactParams = params;
- }
-
- public void initFromConf() throws LinphoneConfigException {
- boolean isDebugLogEnabled = !(mR.getBoolean(R.bool.disable_every_log)) && getPrefBoolean(R.string.pref_debug_key, mR.getBoolean(R.bool.pref_debug_default));
- LinphoneCoreFactory.instance().setDebugMode(isDebugLogEnabled, getString(R.string.app_name));
- initFromConfTunnel();
-
- if (initialTransports == null)
- initialTransports = mLc.getSignalingTransportPorts();
-
- setSignalingTransportsFromConfiguration(initialTransports);
- initMediaEncryption();
-
- mLc.setVideoPolicy(isAutoInitiateVideoCalls(), isAutoAcceptCamera());
-
- readAndSetAudioAndVideoPorts();
-
- String defaultIncomingCallTimeout = getString(R.string.pref_incoming_call_timeout_default);
- int incomingCallTimeout = tryToParseIntValue(getPrefString(R.string.pref_incoming_call_timeout_key, defaultIncomingCallTimeout), defaultIncomingCallTimeout);
- mLc.setIncomingTimeout(incomingCallTimeout);
-
- try {
- // Configure audio codecs
-// enableDisableAudioCodec("speex", 32000, 1, R.string.pref_codec_speex32_key);
- enableDisableAudioCodec("speex", 32000, 1, false);
- enableDisableAudioCodec("speex", 16000, 1, R.string.pref_codec_speex16_key);
- enableDisableAudioCodec("speex", 8000, 1, R.string.pref_codec_speex8_key);
- enableDisableAudioCodec("iLBC", 8000, 1, R.string.pref_codec_ilbc_key);
- enableDisableAudioCodec("GSM", 8000, 1, R.string.pref_codec_gsm_key);
- enableDisableAudioCodec("G722", 8000, 1, R.string.pref_codec_g722_key);
- enableDisableAudioCodec("G729", 8000, 1, R.string.pref_codec_g729_key);
- enableDisableAudioCodec("PCMU", 8000, 1, R.string.pref_codec_pcmu_key);
- enableDisableAudioCodec("PCMA", 8000, 1, R.string.pref_codec_pcma_key);
- enableDisableAudioCodec("AMR", 8000, 1, R.string.pref_codec_amr_key);
- enableDisableAudioCodec("AMR-WB", 16000, 1, R.string.pref_codec_amrwb_key);
- //enableDisableAudioCodec("SILK", 24000, 1, R.string.pref_codec_silk24_key);
- enableDisableAudioCodec("SILK", 24000, 1, false);
- enableDisableAudioCodec("SILK", 16000, 1, R.string.pref_codec_silk16_key);
- //enableDisableAudioCodec("SILK", 12000, 1, R.string.pref_codec_silk12_key);
- enableDisableAudioCodec("SILK", 12000, 1, false);
- enableDisableAudioCodec("SILK", 8000, 1, R.string.pref_codec_silk8_key);
-
- // Configure video codecs
- for (PayloadType videoCodec : mLc.getVideoCodecs()) {
- enableDisableVideoCodecs(videoCodec);
- }
-
- boolean useEC = getPrefBoolean(R.string.pref_echo_cancellation_key, mR.getBoolean(R.bool.pref_echo_canceller_default));
- mLc.enableEchoCancellation(useEC);
- } catch (LinphoneCoreException e) {
- throw new LinphoneConfigException(getString(R.string.wrong_settings),e);
- }
- boolean isVideoEnabled = isVideoEnabled();
- mLc.enableVideo(isVideoEnabled, isVideoEnabled);
-
- //stun server
- String lStun = getPrefString(R.string.pref_stun_server_key, getString(R.string.default_stun));
- boolean useICE = getPrefBoolean(R.string.pref_ice_enable_key, mR.getBoolean(R.bool.pref_ice_enabled_default));
- //boolean useUpnp = getPrefBoolean(R.string.pref_upnp_enable_key, mR.getBoolean(R.bool.pref_upnp_enabled_default));
-
- mLc.setStunServer(lStun);
- if (lStun!=null && lStun.length()>0) {
- mLc.setFirewallPolicy(useICE ? FirewallPolicy.UseIce : FirewallPolicy.UseStun);
- } else {
- mLc.setFirewallPolicy(FirewallPolicy.NoFirewall);
- }
-
- mLc.setUseRfc2833ForDtmfs(getPrefBoolean(R.string.pref_rfc2833_dtmf_key, mR.getBoolean(R.bool.pref_rfc2833_dtmf_default)));
- mLc.setUseSipInfoForDtmfs(getPrefBoolean(R.string.pref_sipinfo_dtmf_key, mR.getBoolean(R.bool.pref_sipinfo_dtmf_default)));
-
- String displayName = getPrefString(R.string.pref_display_name_key, getString(R.string.pref_display_name_default));
- String username = getPrefString(R.string.pref_user_name_key, getString(R.string.pref_user_name_default));
- mLc.setPrimaryContact(displayName, username);
-
- //accounts
- try {
- initAccounts();
-
- //init network state
- updateNetworkReachability();
- } catch (LinphoneCoreException e) {
- throw new LinphoneConfigException(getString(R.string.wrong_settings),e);
- }
- }
-
public void updateNetworkReachability() {
ConnectivityManager cm = (ConnectivityManager) mServiceContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo eventInfo = cm.getActiveNetworkInfo();
if (eventInfo == null || eventInfo.getState() == NetworkInfo.State.DISCONNECTED) {
Log.i("No connectivity: setting network unreachable");
- if (isNetworkReachable) {
- isNetworkReachable = false;
- mLc.setNetworkReachable(isNetworkReachable);
- }
+ mLc.setNetworkReachable(false);
} else if (eventInfo.getState() == NetworkInfo.State.CONNECTED){
manageTunnelServer(eventInfo);
- SharedPreferences pref = PreferenceManager.getDefaultSharedPreferences(mServiceContext);
- boolean wifiOnly = pref.getBoolean(getString(R.string.pref_wifi_only_key), mR.getBoolean(R.bool.pref_wifi_only_default));
- if ((eventInfo.getTypeName().equals("WIFI")) || (!eventInfo.getTypeName().equals("WIFI") && !wifiOnly)) {
- if (!isNetworkReachable) {
- isNetworkReachable = true;
- mLc.setNetworkReachable(isNetworkReachable);
- Log.i(eventInfo.getTypeName()," connected: setting network reachable (network = " + eventInfo.getTypeName() + ")");
+
+ boolean wifiOnly = LinphonePreferences.instance().isWifiOnlyEnabled();
+ if (wifiOnly){
+ if (eventInfo.getType()==ConnectivityManager.TYPE_WIFI)
+ mLc.setNetworkReachable(true);
+ else {
+ Log.i("Wifi-only mode, setting network not reachable");
+ mLc.setNetworkReachable(false);
}
- } else {
- if (isNetworkReachable) {
- isNetworkReachable = false;
- mLc.setNetworkReachable(isNetworkReachable);
- Log.i(eventInfo.getTypeName()," connected: wifi only activated, setting network unreachable (network = " + eventInfo.getTypeName() + ")");
+ }else{
+ int curtype=eventInfo.getType();
+
+ if (curtype!=mLastNetworkType){
+ //if kind of network has changed, we need to notify network_reachable(false) to make sure all current connections are destroyed.
+ //they will be re-created during setNetworkReachable(true).
+ Log.i("Connectivity has changed.");
+ mLc.setNetworkReachable(false);
}
+ mLc.setNetworkReachable(true);
+ mLastNetworkType=curtype;
}
}
}
-
- private void setSignalingTransportsFromConfiguration(Transports t) {
- Transports ports = new Transports(t);
- boolean useRandomPort = getPrefBoolean(R.string.pref_transport_use_random_ports_key, mR.getBoolean(R.bool.pref_transport_use_random_ports_default));
- int lPreviousPort = tryToParseIntValue(getPrefString(R.string.pref_sip_port_key, getString(R.string.pref_sip_port_default)), 5060);
- if (lPreviousPort>0xFFFF || useRandomPort) {
- lPreviousPort=(int)(Math.random() * (0xFFFF - 1024)) + 1024;
- Log.w("Using random port " + lPreviousPort);
- }
-
- String transport = getPrefString(R.string.pref_transport_key, getString(R.string.pref_transport_udp_key));
- if (transport.equals(getString(R.string.pref_transport_tcp_key)))
- {
- ports.udp = 0;
- ports.tls = 0;
- ports.tcp = lPreviousPort;
- } else if (transport.equals(getString(R.string.pref_transport_udp_key)))
- {
- ports.tcp = 0;
- ports.tls = 0;
- ports.udp = lPreviousPort;
- } else if (transport.equals(getString(R.string.pref_transport_tls_key)))
- {
- ports.udp = 0;
- ports.tcp = 0;
- ports.tls = lPreviousPort;
- }
- mLc.setSignalingTransportPorts(ports);
- }
-
- private void enableDisableAudioCodec(String codec, int rate, int channels, int key) throws LinphoneCoreException {
- PayloadType pt = mLc.findPayloadType(codec, rate, channels);
- if (pt !=null) {
- boolean enable= getPrefBoolean(key,false);
- mLc.enablePayloadType(pt, enable);
- }
- }
- private void enableDisableAudioCodec(String codec, int rate, int channels, boolean enable) throws LinphoneCoreException {
- PayloadType pt = mLc.findPayloadType(codec, rate, channels);
- if (pt !=null) {
- mLc.enablePayloadType(pt, enable);
- }
- }
-
- private void enableDisableVideoCodecs(PayloadType videoCodec) throws LinphoneCoreException {
- String mime = videoCodec.getMime();
- int key;
- int defaultValueKey;
-
- if ("MP4V-ES".equals(mime)) {
- key = R.string.pref_video_codec_mpeg4_key;
- defaultValueKey = R.bool.pref_video_codec_mpeg4_default;
- } else if ("H264".equals(mime)) {
- key = R.string.pref_video_codec_h264_key;
- defaultValueKey = R.bool.pref_video_codec_h264_default;
- } else if ("H263-1998".equals(mime)) {
- key = R.string.pref_video_codec_h263_key;
- defaultValueKey = R.bool.pref_video_codec_h263_default;
- } else if ("VP8".equals(mime)) {
- key = R.string.pref_video_codec_vp8_key;
- defaultValueKey = R.bool.pref_video_codec_vp8_default;
- } else {
- Log.e("Unhandled video codec ", mime);
- mLc.enablePayloadType(videoCodec, false);
- return;
- }
-
- boolean enable = getPrefBoolean(key, mR.getBoolean(defaultValueKey));
- mLc.enablePayloadType(videoCodec, enable);
- }
-
- @TargetApi(Build.VERSION_CODES.HONEYCOMB)
+ @TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void doDestroy() {
- if (chatStorage != null) {
- chatStorage.close();
- chatStorage = null;
- }
+ if (LinphoneService.isReady()) // indeed, no need to crash
+ ChatStorage.getInstance().close();
- try {
- mServiceContext.unregisterReceiver(bluetoothReiceiver);
- } catch (Exception e) {}
-
- try {
- if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30))
- mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset);
- } catch (Exception e) {}
-
+ BluetoothManager.getInstance().destroy();
try {
mTimer.cancel();
mLc.destroy();
- }
+ }
catch (RuntimeException e) {
e.printStackTrace();
}
@@ -1026,35 +646,14 @@ public class LinphoneManager implements LinphoneCoreListener {
public static synchronized void destroy() {
if (instance == null) return;
- sExited=true;
+ getInstance().changeStatusToOffline();
+ sExited = true;
instance.doDestroy();
}
private String getString(int key) {
return mR.getString(key);
}
- private boolean getPrefBoolean(int key, boolean value) {
- return mPref.getBoolean(mR.getString(key), value);
- }
- private boolean getPrefBoolean(String key, boolean value) {
- return mPref.getBoolean(key, value);
- }
- private String getPrefString(int key, String value) {
- return mPref.getString(mR.getString(key), value);
- }
- private int getPrefInt(int key, int value) {
- return mPref.getInt(mR.getString(key), value);
- }
- private String getPrefString(int key, int value) {
- return mPref.getString(mR.getString(key), mR.getString(value));
- }
- private String getPrefString(String key, String value) {
- return mPref.getString(key, value);
- }
- private int getPrefExtraAccountsNumber() {
- return mPref.getInt(getString(R.string.pref_extra_accounts), 1);
- }
-
/* Simple implementation as Android way seems very complicate:
For example: with wifi and mobile actives; when pulling mobile down:
@@ -1065,47 +664,30 @@ public class LinphoneManager implements LinphoneCoreListener {
I/Linphone( 8397): WIFI connected: setting network reachable
*/
public void connectivityChanged(ConnectivityManager cm, boolean noConnectivity) {
- NetworkInfo eventInfo = cm.getActiveNetworkInfo();
updateNetworkReachability();
-
- if (connectivityListener != null) {
- connectivityListener.onConnectivityChanged(mServiceContext, eventInfo, cm);
- }
- }
-
- private ConnectivityChangedListener connectivityListener;
- public void addConnectivityChangedListener(ConnectivityChangedListener l) {
- connectivityListener = l;
}
public interface EcCalibrationListener {
void onEcCalibrationStatus(EcCalibratorStatus status, int delayMs);
}
- private ListenerDispatcher mListenerDispatcher;
private LinphoneCall ringingCall;
private MediaPlayer mRingerPlayer;
private Vibrator mVibrator;
public void displayWarning(LinphoneCore lc, String message) {}
- public void authInfoRequested(LinphoneCore lc, String realm, String username) {}
+ public void authInfoRequested(LinphoneCore lc, String realm, String username, String domain) {}
public void byeReceived(LinphoneCore lc, String from) {}
public void displayMessage(LinphoneCore lc, String message) {}
public void show(LinphoneCore lc) {}
-
+
public void newSubscriptionRequest(LinphoneCore lc, LinphoneFriend lf, String url) {
- for (LinphoneSimpleListener listener : getSimpleListeners(LinphoneActivity.class)) {
- ((LinphoneActivity) listener).onNewSubscriptionRequestReceived(lf, url);
- }
}
-
+
public void notifyPresenceReceived(LinphoneCore lc, LinphoneFriend lf) {
- for (LinphoneSimpleListener listener : getSimpleListeners(LinphoneActivity.class)) {
- ((LinphoneActivity) listener).onNotifyPresenceReceived(lf);
- }
}
-
+
public void textReceived(LinphoneCore lc, LinphoneChatRoom cr,
LinphoneAddress from, String message) {
//deprecated
@@ -1114,66 +696,57 @@ public class LinphoneManager implements LinphoneCoreListener {
@Override
public void dtmfReceived(LinphoneCore lc, LinphoneCall call, int dtmf) {
Log.d("DTMF received: " + dtmf);
- if (dtmfReceivedListener != null)
- dtmfReceivedListener.onDTMFReceived(call, dtmf);
}
-
- private LinphoneOnDTMFReceivedListener dtmfReceivedListener;
- public void setOnDTMFReceivedListener(LinphoneOnDTMFReceivedListener listener) {
- dtmfReceivedListener = listener;
- }
-
+
@Override
public void messageReceived(LinphoneCore lc, LinphoneChatRoom cr, LinphoneChatMessage message) {
if (mServiceContext.getResources().getBoolean(R.bool.disable_chat)) {
return;
}
-
+
LinphoneAddress from = message.getFrom();
String textMessage = message.getText();
String url = message.getExternalBodyUrl();
- String notificationText = null;
- int id = -1;
if (textMessage != null && textMessage.length() > 0) {
- id = chatStorage.saveTextMessage(from.asStringUriOnly(), "", textMessage, message.getTime());
- notificationText = textMessage;
+ ChatStorage.getInstance().saveTextMessage(from.asStringUriOnly(), "", textMessage, message.getTime());
} else if (url != null && url.length() > 0) {
- //Bitmap bm = ChatFragment.downloadImage(url);
- id = chatStorage.saveImageMessage(from.asStringUriOnly(), "", null, message.getExternalBodyUrl(), message.getTime());
- notificationText = url;
+ ChatStorage.getInstance().saveImageMessage(from.asStringUriOnly(), "", null, message.getExternalBodyUrl(), message.getTime());
}
-
- try {
- LinphoneUtils.findUriPictureOfContactAndSetDisplayName(from, mServiceContext.getContentResolver());
- //LinphoneService.instance().displayMessageNotification(from.asStringUriOnly(), from.getDisplayName(), notificationText);
- } catch (Exception e) { }
- for (LinphoneSimpleListener listener : getSimpleListeners(LinphoneOnMessageReceivedListener.class)) {
- ((LinphoneOnMessageReceivedListener) listener).onMessageReceived(from, message, id);
+ try {
+ Contact contact = ContactsManager.getInstance().findContactWithAddress(mServiceContext.getContentResolver(), from);
+ if (!mServiceContext.getResources().getBoolean(R.bool.disable_chat__message_notification)) {
+ if (LinphoneActivity.isInstanciated() && !LinphoneActivity.instance().displayChatMessageNotification(from.asStringUriOnly())) {
+ return;
+ } else {
+ if (contact != null) {
+ LinphoneService.instance().displayMessageNotification(from.asStringUriOnly(), contact.getName(), textMessage);
+ } else {
+ LinphoneService.instance().displayMessageNotification(from.asStringUriOnly(), from.getUserName(), textMessage);
+ }
+ }
+ }
+ } catch (Exception e) {
+ Log.e(e);
}
}
public String getLastLcStatusMessage() {
return lastLcStatusMessage;
}
+
public void displayStatus(final LinphoneCore lc, final String message) {
Log.i(message);
lastLcStatusMessage=message;
- mListenerDispatcher.onDisplayStatus(message);
}
-
- public void globalState(final LinphoneCore lc, final LinphoneCore.GlobalState state, final String message) {
- Log.i("new state [",state,"]");
- mListenerDispatcher.onGlobalStateChanged(state, message);
+ public void globalState(final LinphoneCore lc, final GlobalState state, final String message) {
+ Log.i("New global state [",state,"]");
}
-
-
- public void registrationState(final LinphoneCore lc, final LinphoneProxyConfig cfg,final LinphoneCore.RegistrationState state,final String message) {
- Log.i("new state ["+state+"]");
- mListenerDispatcher.onRegistrationStateChanged(state, message);
+ public void registrationState(final LinphoneCore lc, final LinphoneProxyConfig proxy,final RegistrationState state,final String message) {
+ Log.i("New registration state ["+state+"]");
}
private int savedMaxCallWhileGsmIncall;
@@ -1187,7 +760,7 @@ public class LinphoneManager implements LinphoneCoreListener {
}
private synchronized void allowSIPCalls() {
if (savedMaxCallWhileGsmIncall == 0) {
- Log.w("SIP calls are already allowed as no GSM call knowned to be running");
+ Log.w("SIP calls are already allowed as no GSM call known to be running");
return;
}
mLc.setMaxCalls(savedMaxCallWhileGsmIncall);
@@ -1202,7 +775,7 @@ public class LinphoneManager implements LinphoneCoreListener {
mThis.preventSIPCalls();
}
}
-
+
public Context getContext() {
try {
if (LinphoneActivity.isInstanciated())
@@ -1211,7 +784,9 @@ public class LinphoneManager implements LinphoneCoreListener {
return InCallActivity.instance();
else if (IncomingCallActivity.isInstanciated())
return IncomingCallActivity.instance();
- else
+ else if (mServiceContext != null)
+ return mServiceContext;
+ else if (LinphoneService.isReady())
return LinphoneService.instance().getApplicationContext();
} catch (Exception e) {
e.printStackTrace();
@@ -1221,58 +796,74 @@ public class LinphoneManager implements LinphoneCoreListener {
@SuppressLint("Wakelock")
public void callState(final LinphoneCore lc,final LinphoneCall call, final State state, final String message) {
- Log.i("new state [",state,"]");
- if (state == IncomingReceived && !call.equals(lc.getCurrentCall())) {
+ Log.i("New call state [",state,"]");
+ if (state == State.IncomingReceived && !call.equals(lc.getCurrentCall())) {
if (call.getReplacedCall()!=null){
// attended transfer
// it will be accepted automatically.
return;
- }
+ }
}
-
- if (state == IncomingReceived || (state == State.CallIncomingEarlyMedia && mR.getBoolean(R.bool.allow_ringing_while_early_media))) {
+
+ if (state == State.IncomingReceived && mR.getBoolean(R.bool.auto_answer_calls)) {
+ try {
+ mLc.acceptCall(call);
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+ }
+ else if (state == State.IncomingReceived || (state == State.CallIncomingEarlyMedia && mR.getBoolean(R.bool.allow_ringing_while_early_media))) {
// Brighten screen for at least 10 seconds
if (mLc.getCallsNb() == 1) {
+ BluetoothManager.getInstance().disableBluetoothSCO(); // Just in case
+
ringingCall = call;
startRinging();
// otherwise there is the beep
}
- } else if (call == ringingCall && isRinging) {
+ } else if (call == ringingCall && isRinging) {
//previous state was ringing, so stop ringing
stopRinging();
}
-
- if (state == LinphoneCall.State.Connected) {
+
+ if (state == State.Connected) {
if (mLc.getCallsNb() == 1) {
requestAudioFocus();
Compatibility.setAudioManagerInCallMode(mAudioManager);
}
-
- if (Hacks.needSoftvolume() || sLPref.useSoftvolume()) {
+
+ if (Hacks.needSoftvolume()) {
+ Log.w("Using soft volume audio hack");
adjustVolume(0); // Synchronize
}
}
- if (state == CallEnd || state == Error) {
+ if (state == State.OutgoingEarlyMedia) {
+ Compatibility.setAudioManagerInCallMode(mAudioManager);
+ }
+
+ if (state == State.CallReleased || state == State.Error) {
if (mLc.getCallsNb() == 0) {
if (mAudioFocused){
- int res=mAudioManager.abandonAudioFocus(null);
+ int res = mAudioManager.abandonAudioFocus(null);
Log.d("Audio focus released a bit later: " + (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED ? "Granted" : "Denied"));
- mAudioFocused=false;
+ mAudioFocused = false;
}
-
+
Context activity = getContext();
if (activity != null) {
TelephonyManager tm = (TelephonyManager) activity.getSystemService(Context.TELEPHONY_SERVICE);
if (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
Log.d("---AudioManager: back to MODE_NORMAL");
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ Log.d("All call terminated, routing back to earpiece");
+ routeAudioToReceiver();
}
}
}
}
- if (state == CallEnd) {
+ if (state == State.CallEnd) {
if (mLc.getCallsNb() == 0) {
if (mIncallWakeLock != null && mIncallWakeLock.isHeld()) {
mIncallWakeLock.release();
@@ -1282,7 +873,19 @@ public class LinphoneManager implements LinphoneCoreListener {
}
}
}
+
if (state == State.StreamsRunning) {
+ if (BluetoothManager.getInstance().isBluetoothHeadsetAvailable()) {
+ BluetoothManager.getInstance().routeAudioToBluetooth();
+ // Hack to ensure the bluetooth route is really used
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ BluetoothManager.getInstance().routeAudioToBluetooth();
+ }
+ }, 500);
+ }
+
if (mIncallWakeLock == null) {
mIncallWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "incall");
}
@@ -1293,68 +896,54 @@ public class LinphoneManager implements LinphoneCoreListener {
Log.i("New call active while incall (CPU only) wake lock already active");
}
}
- mListenerDispatcher.onCallStateChanged(call, state, message);
}
public void callStatsUpdated(final LinphoneCore lc, final LinphoneCall call, final LinphoneCallStats stats) {}
public void callEncryptionChanged(LinphoneCore lc, LinphoneCall call,
boolean encrypted, String authenticationToken) {
- mListenerDispatcher.onCallEncryptionChanged(call, encrypted, authenticationToken);
}
- public void ecCalibrationStatus(final LinphoneCore lc,final EcCalibratorStatus status, final int delayMs,
- final Object data) {
- EcCalibrationListener listener = (EcCalibrationListener) data;
- listener.onEcCalibrationStatus(status, delayMs);
- }
-
-
-
- public void startEcCalibration(EcCalibrationListener l) throws LinphoneCoreException {
+ public void startEcCalibration(LinphoneCoreListener l) throws LinphoneCoreException {
+ routeAudioToSpeaker();
int oldVolume = mAudioManager.getStreamVolume(STREAM_VOICE_CALL);
int maxVolume = mAudioManager.getStreamMaxVolume(STREAM_VOICE_CALL);
mAudioManager.setStreamVolume(STREAM_VOICE_CALL, maxVolume, 0);
-
mLc.startEchoCalibration(l);
mAudioManager.setStreamVolume(STREAM_VOICE_CALL, oldVolume, 0);
}
-
-
-
-
-
-
-
-
private boolean isRinging;
private boolean disableRinging = false;
-
+
public void disableRinging() {
disableRinging = true;
}
-
+
private void requestAudioFocus(){
if (!mAudioFocused){
- int res=mAudioManager.requestAudioFocus(null, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT );
+ int res = mAudioManager.requestAudioFocus(null, AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT );
Log.d("Audio focus requested: " + (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED ? "Granted" : "Denied"));
- if (res==AudioManager.AUDIOFOCUS_REQUEST_GRANTED) mAudioFocused=true;
+ if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) mAudioFocused=true;
}
}
-
+
private synchronized void startRinging() {
- if (disableRinging ) {
+ if (disableRinging) {
+ routeAudioToSpeaker();
return;
}
+ if (mR.getBoolean(R.bool.allow_ringing_while_early_media)) {
+ routeAudioToSpeaker(); // Need to be able to ear the ringtone during the early media
+ }
if (Hacks.needGalaxySAudioHack()) {
mAudioManager.setMode(MODE_RINGTONE);
}
-
+
try {
- if ((mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE || mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL) && mVibrator !=null) {
+ if ((mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE || mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL) && mVibrator != null) {
long[] patern = {0,1000,1000};
mVibrator.vibrate(patern, 1);
}
@@ -1362,7 +951,20 @@ public class LinphoneManager implements LinphoneCoreListener {
requestAudioFocus();
mRingerPlayer = new MediaPlayer();
mRingerPlayer.setAudioStreamType(STREAM_RING);
- mListenerDispatcher.onRingerPlayerCreated(mRingerPlayer);
+
+ String ringtone = LinphonePreferences.instance().getRingtone(android.provider.Settings.System.DEFAULT_RINGTONE_URI.toString());
+ try {
+ if (ringtone.startsWith("content://")) {
+ mRingerPlayer.setDataSource(mServiceContext, Uri.parse(ringtone));
+ } else {
+ FileInputStream fis = new FileInputStream(ringtone);
+ mRingerPlayer.setDataSource(fis.getFD());
+ fis.close();
+ }
+ } catch (IOException e) {
+ Log.e(e, "Cannot set ringtone");
+ }
+
mRingerPlayer.prepare();
mRingerPlayer.setLooping(true);
mRingerPlayer.start();
@@ -1376,24 +978,32 @@ public class LinphoneManager implements LinphoneCoreListener {
}
private synchronized void stopRinging() {
- if (mRingerPlayer !=null) {
+ if (mRingerPlayer != null) {
mRingerPlayer.stop();
mRingerPlayer.release();
- mRingerPlayer=null;
+ mRingerPlayer = null;
}
- if (mVibrator!=null) {
+ if (mVibrator != null) {
mVibrator.cancel();
}
-
+
if (Hacks.needGalaxySAudioHack())
mAudioManager.setMode(AudioManager.MODE_NORMAL);
-
+
isRinging = false;
// You may need to call galaxys audio hack after this method
- routeAudioToReceiver();
+ if (!BluetoothManager.getInstance().isBluetoothHeadsetAvailable()) {
+ if (mServiceContext.getResources().getBoolean(R.bool.isTablet)) {
+ Log.d("Stopped ringing, routing back to speaker");
+ routeAudioToSpeaker();
+ } else {
+ Log.d("Stopped ringing, routing back to earpiece");
+ routeAudioToReceiver();
+ }
+ }
}
-
+
public static String extractADisplayName(Resources r, LinphoneAddress address) {
if (address == null) return r.getString(R.string.unknown_incoming_call_name);
@@ -1406,7 +1016,7 @@ public class LinphoneManager implements LinphoneCoreListener {
String rms = address.toString();
if (rms != null && rms.length() > 1)
return rms;
-
+
return r.getString(R.string.unknown_incoming_call_name);
}
}
@@ -1415,65 +1025,16 @@ public class LinphoneManager implements LinphoneCoreListener {
return CallManager.getInstance().reinviteWithVideo();
}
- public boolean isVideoEnabled() {
- return getPrefBoolean(R.string.pref_video_enable_key, false);
- }
-
- public boolean isAutoAcceptCamera() {
- return isVideoEnabled() && getPrefBoolean(R.string.pref_video_automatically_accept_video_key, false);
- }
-
- public boolean isAutoInitiateVideoCalls() {
- return isVideoEnabled() && getPrefBoolean(R.string.pref_video_initiate_call_with_video_key, false);
- }
-
- // Called on first launch only
- public void initializePayloads() {
- Log.i("Initializing supported payloads");
- Editor e = mPref.edit();
- boolean fastCpu = Version.hasFastCpu();
-
- e.putBoolean(getString(R.string.pref_codec_gsm_key), true);
- e.putBoolean(getString(R.string.pref_codec_pcma_key), true);
- e.putBoolean(getString(R.string.pref_codec_pcmu_key), true);
- e.putBoolean(getString(R.string.pref_codec_speex8_key), true);
- e.putBoolean(getString(R.string.pref_codec_g722_key), false);
- e.putBoolean(getString(pref_codec_speex16_key), fastCpu);
- e.putBoolean(getString(pref_codec_speex32_key), fastCpu);
-
- boolean ilbc = LinphoneService.isReady() && LinphoneManager.getLc()
- .findPayloadType("iLBC", 8000, 1)!=null;
- e.putBoolean(getString(pref_codec_ilbc_key), ilbc);
-
- boolean amr = LinphoneService.isReady() && LinphoneManager.getLc()
- .findPayloadType("AMR", 8000, 1)!=null;
- e.putBoolean(getString(pref_codec_amr_key), amr);
-
- boolean amrwb = LinphoneService.isReady() && LinphoneManager.getLc()
- .findPayloadType("AMR-WB", 16000, 1)!=null;
- e.putBoolean(getString(pref_codec_amrwb_key), amrwb);
-
- boolean g729 = LinphoneService.isReady() && LinphoneManager.getLc()
- .findPayloadType("G729", 8000, 1)!=null;
- e.putBoolean(getString(R.string.pref_codec_g729_key), g729);
-
- if (Version.sdkStrictlyBelow(5) || !Version.hasNeon() || !Hacks.hasCamera()) {
- e.putBoolean(getString(pref_video_enable_key), false);
- }
-
- e.commit();
- }
-
/**
- *
- * @return false if already in video call.
+ *
+ * @return false if already in video call.
*/
public boolean addVideo() {
LinphoneCall call = mLc.getCurrentCall();
enableCamera(call, true);
return reinviteWithVideo();
}
-
+
public boolean acceptCallIfIncomingPending() throws LinphoneCoreException {
if (mLc.isInComingInvitePending()) {
mLc.acceptCall(mLc.getCurrentCall());
@@ -1481,7 +1042,7 @@ public class LinphoneManager implements LinphoneCoreListener {
}
return false;
}
-
+
public boolean acceptCall(LinphoneCall call) {
try {
mLc.acceptCall(call);
@@ -1507,7 +1068,7 @@ public class LinphoneManager implements LinphoneCoreListener {
}
public void adjustVolume(int i) {
- if (Build.VERSION.SDK_INT<15) {
+ if (Build.VERSION.SDK_INT < 15) {
int oldVolume = mAudioManager.getStreamVolume(LINPHONE_VOLUME_STREAM);
int maxVolume = mAudioManager.getStreamMaxVolume(LINPHONE_VOLUME_STREAM);
@@ -1518,7 +1079,7 @@ public class LinphoneManager implements LinphoneCoreListener {
mLc.setPlaybackGain((nextVolume - maxVolume)* dbStep);
} else
// starting from ICS, volume must be adjusted by the application, at least for STREAM_VOICE_CALL volume stream
- mAudioManager.adjustStreamVolume(LINPHONE_VOLUME_STREAM, i<0?AudioManager.ADJUST_LOWER:AudioManager.ADJUST_RAISE, 0);
+ mAudioManager.adjustStreamVolume(LINPHONE_VOLUME_STREAM, i < 0 ? AudioManager.ADJUST_LOWER : AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
}
public static Boolean isProximitySensorNearby(final SensorEvent event) {
@@ -1579,7 +1140,7 @@ public class LinphoneManager implements LinphoneCoreListener {
Log.i("proximity sensor already active for " + activity.getLocalClassName());
return;
}
-
+
if (sProximityDependentActivities.isEmpty()) {
SensorManager sm = (SensorManager) activity.getSystemService(Context.SENSOR_SERVICE);
Sensor s = sm.getDefaultSensor(Sensor.TYPE_PROXIMITY);
@@ -1606,98 +1167,19 @@ public class LinphoneManager implements LinphoneCoreListener {
public static synchronized LinphoneCore getLcIfManagerNotDestroyedOrNull() {
- if (sExited) {
+ if (sExited || instance == null) {
// Can occur if the UI thread play a posted event but in the meantime the LinphoneManager was destroyed
// Ex: stop call and quickly terminate application.
- Log.w("Trying to get linphone core while LinphoneManager already destroyed");
+ Log.w("Trying to get linphone core while LinphoneManager already destroyed or not created");
return null;
}
return getLc();
}
- @SuppressWarnings("unchecked")
- private List getSimpleListeners(Class clazz) {
- List list = new ArrayList();
- for (LinphoneSimpleListener l : simpleListeners) {
- if (clazz.isInstance(l)) list.add((T) l);
- }
- return list;
- }
-
- private class ListenerDispatcher implements LinphoneServiceListener {
- private LinphoneServiceListener serviceListener;
-
- public ListenerDispatcher(LinphoneServiceListener listener) {
- this.serviceListener = listener;
- }
-
- public void onCallEncryptionChanged(LinphoneCall call,
- boolean encrypted, String authenticationToken) {
- if (serviceListener != null) {
- serviceListener.onCallEncryptionChanged(call, encrypted, authenticationToken);
- }
- for (LinphoneOnCallEncryptionChangedListener l : getSimpleListeners(LinphoneOnCallEncryptionChangedListener.class)) {
- l.onCallEncryptionChanged(call, encrypted, authenticationToken);
- }
- }
-
- public void onCallStateChanged(LinphoneCall call, State state, String message) {
- if (state == State.OutgoingInit || state == State.IncomingReceived) {
- boolean sendCamera = mLc.getConferenceSize() == 0;
- enableCamera(call, sendCamera);
- }
-
- Context activity = getContext();
- if (activity != null) {
- TelephonyManager tm = (TelephonyManager) activity.getSystemService(Context.TELEPHONY_SERVICE);
- if (state == State.CallEnd && mLc.getCallsNb() == 0 && tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
- routeAudioToReceiver();
- }
- }
-
- if (serviceListener != null) serviceListener.onCallStateChanged(call, state, message);
- for (LinphoneOnCallStateChangedListener l : getSimpleListeners(LinphoneOnCallStateChangedListener.class)) {
- l.onCallStateChanged(call, state, message);
- }
- }
-
- public void onDisplayStatus(String message) {
- if (serviceListener != null) serviceListener.onDisplayStatus(message);
- }
-
- public void onGlobalStateChanged(GlobalState state, String message) {
- if (serviceListener != null) serviceListener.onGlobalStateChanged( state, message);
- }
-
- public void onRegistrationStateChanged(RegistrationState state,
- String message) {
- if (serviceListener != null) serviceListener.onRegistrationStateChanged(state, message);
- for (LinphoneOnRegistrationStateChangedListener listener : getSimpleListeners(LinphoneOnRegistrationStateChangedListener.class)) {
- listener.onRegistrationStateChanged(state);
- }
- }
-
- public void onRingerPlayerCreated(MediaPlayer mRingerPlayer) {
- if (serviceListener != null) serviceListener.onRingerPlayerCreated(mRingerPlayer);
- }
-
- public void tryingNewOutgoingCallButAlreadyInCall() {
- if (serviceListener != null) serviceListener.tryingNewOutgoingCallButAlreadyInCall();
- }
-
- public void tryingNewOutgoingCallButCannotGetCallParameters() {
- if (serviceListener != null) serviceListener.tryingNewOutgoingCallButCannotGetCallParameters();
- }
-
- public void tryingNewOutgoingCallButWrongDestinationAddress() {
- if (serviceListener != null) serviceListener.tryingNewOutgoingCallButWrongDestinationAddress();
- }
- }
-
public static final boolean isInstanciated() {
return instance != null;
}
-
+
public synchronized LinphoneCall getPendingIncomingCall() {
LinphoneCall currentCall = mLc.getCurrentCall();
if (currentCall == null) return null;
@@ -1709,9 +1191,9 @@ public class LinphoneManager implements LinphoneCoreListener {
return incomingPending ? currentCall : null;
}
-
-
-
+
+
+
@SuppressWarnings("serial")
public static class LinphoneConfigException extends LinphoneException {
@@ -1736,4 +1218,94 @@ public class LinphoneManager implements LinphoneCoreListener {
public void notifyReceived(LinphoneCore lc, LinphoneCall call,
LinphoneAddress from, byte[] event) {
}
+ @Override
+ public void transferState(LinphoneCore lc, LinphoneCall call,
+ State new_call_state) {
+
+ }
+ @Override
+ public void infoReceived(LinphoneCore lc, LinphoneCall call, LinphoneInfoMessage info) {
+ Log.d("Info message received from "+call.getRemoteAddress().asString());
+ LinphoneContent ct=info.getContent();
+ if (ct!=null){
+ Log.d("Info received with body with mime type "+ct.getType()+"/"+ct.getSubtype()+" and data ["+ct.getDataAsString()+"]");
+ }
+ }
+ @Override
+ public void subscriptionStateChanged(LinphoneCore lc, LinphoneEvent ev,
+ SubscriptionState state) {
+ Log.d("Subscription state changed to "+state+" event name is "+ev.getEventName());
+ }
+
+ @Override
+ public void notifyReceived(LinphoneCore lc, LinphoneEvent ev,
+ String eventName, LinphoneContent content) {
+ Log.d("Notify received for event "+eventName);
+ if (content!=null) Log.d("with content "+content.getType()+"/"+content.getSubtype()+" data:"+content.getDataAsString());
+ }
+ @Override
+ public void publishStateChanged(LinphoneCore lc, LinphoneEvent ev,
+ PublishState state) {
+ Log.d("Publish state changed to " + state + " for event name " + ev.getEventName());
+ }
+
+ @Override
+ public void isComposingReceived(LinphoneCore lc, LinphoneChatRoom cr) {
+ Log.d("Composing received for chatroom " + cr.getPeerAddress().asStringUriOnly());
+ }
+
+ @Override
+ public void configuringStatus(LinphoneCore lc,
+ RemoteProvisioningState state, String message) {
+ Log.d("Remote provisioning status = " + state.toString() + " (" + message + ")");
+
+ if (state == RemoteProvisioningState.ConfiguringSuccessful) {
+ if (LinphonePreferences.instance().isProvisioningLoginViewEnabled()) {
+ LinphoneProxyConfig proxyConfig = lc.createProxyConfig();
+ try {
+ LinphoneAddress addr = LinphoneCoreFactory.instance().createLinphoneAddress(proxyConfig.getIdentity());
+ wizardLoginViewDomain = addr.getDomain();
+ } catch (LinphoneCoreException e) {
+ wizardLoginViewDomain = null;
+ }
+ }
+ }
+ }
+ @Override
+ public void fileTransferProgressIndication(LinphoneCore lc,
+ LinphoneChatMessage message, LinphoneContent content, int progress) {
+
+ }
+ @Override
+ public void fileTransferRecv(LinphoneCore lc, LinphoneChatMessage message,
+ LinphoneContent content, byte[] buffer, int size) {
+
+ }
+ @Override
+ public int fileTransferSend(LinphoneCore lc, LinphoneChatMessage message,
+ LinphoneContent content, ByteBuffer buffer, int size) {
+ return 0;
+ }
+
+ @Override
+ public void uploadProgressIndication(LinphoneCore linphoneCore, int offset, int total) {
+ if(total > 0)
+ Log.d("Log upload progress: currently uploaded = " + offset + " , total = " + total + ", % = " + String.valueOf((offset * 100) / total));
+ }
+
+ @Override
+ public void uploadStateChanged(LinphoneCore linphoneCore, LogCollectionUploadState state, String info) {
+ Log.d("Log upload state: " + state.toString() + ", info = " + info);
+
+ if (state == LogCollectionUploadState.LogCollectionUploadStateDelivered) {
+ LinphoneActivity.instance().sendLogs(LinphoneService.instance().getApplicationContext(),info);
+ }
+ }
+
+ @Override
+ public void ecCalibrationStatus(LinphoneCore lc, EcCalibratorStatus status,
+ int delay_ms, Object data) {
+ // TODO Auto-generated method stub
+
+ }
}
diff --git a/src/org/linphone/LinphonePreferenceManager.java b/src/org/linphone/LinphonePreferenceManager.java
deleted file mode 100644
index a9906fa44..000000000
--- a/src/org/linphone/LinphonePreferenceManager.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
-PreferenceManager.java
-Copyright (C) 2011 Belledonne Communications, Grenoble, France
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- */
-package org.linphone;
-
-import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-
-public class LinphonePreferenceManager {
-
- private static LinphonePreferenceManager instance;
- private Context c;
- private SharedPreferences p;
-
- public LinphonePreferenceManager(Context context) {
- c = context.getApplicationContext();
- p = PreferenceManager.getDefaultSharedPreferences(c);
- }
-
- private String getString(int key) {
- return c.getString(key);
- }
-
- public boolean useSoftvolume() {
- return p.getBoolean(
- getString(R.string.pref_audio_soft_volume_key), false);
- }
-
- public boolean useAudioRoutingAPIHack() {
- return p.getBoolean(
- getString(R.string.pref_audio_hacks_use_routing_api_key), false);
- }
-
- public boolean useGalaxySHack() {
- return p.getBoolean(
- getString(R.string.pref_audio_hacks_use_galaxys_hack_key), false);
- }
-
- public int useSpecificAudioModeHack() {
- return Integer.parseInt(p.getString(getString(R.string.pref_audio_use_specific_mode_key), "0"));
- }
-
- public static final synchronized LinphonePreferenceManager getInstance(Context c) {
- if (instance == null) {
- instance = new LinphonePreferenceManager(c.getApplicationContext());
- }
- return instance;
- }
-
-}
diff --git a/src/org/linphone/LinphonePreferences.java b/src/org/linphone/LinphonePreferences.java
new file mode 100644
index 000000000..2d45d9c73
--- /dev/null
+++ b/src/org/linphone/LinphonePreferences.java
@@ -0,0 +1,1202 @@
+package org.linphone;
+
+/*
+LinphonePreferences.java
+Copyright (C) 2013 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import org.linphone.core.LinphoneAddress;
+import org.linphone.core.LinphoneAddress.TransportType;
+import org.linphone.core.LinphoneAuthInfo;
+import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneCore.AdaptiveRateAlgorithm;
+import org.linphone.core.LinphoneCore.FirewallPolicy;
+import org.linphone.core.LinphoneCore.MediaEncryption;
+import org.linphone.core.LinphoneCore.Transports;
+import org.linphone.core.LinphoneCoreException;
+import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.core.LinphoneProxyConfig;
+import org.linphone.core.LpConfig;
+import org.linphone.core.TunnelConfig;
+import org.linphone.mediastream.Log;
+
+import android.content.Context;
+
+/**
+ * @author Sylvain Berfini
+ */
+public class LinphonePreferences {
+ private static final int LINPHONE_CORE_RANDOM_PORT = -1;
+ private static LinphonePreferences instance;
+ private Context mContext;
+
+ public static final synchronized LinphonePreferences instance() {
+ if (instance == null) {
+ instance = new LinphonePreferences();
+ }
+ return instance;
+ }
+
+ private LinphonePreferences() {
+
+ }
+
+ public void setContext(Context c) {
+ mContext = c;
+ }
+
+ private String getString(int key) {
+ if (mContext == null && LinphoneManager.isInstanciated()) {
+ mContext = LinphoneManager.getInstance().getContext();
+ }
+
+ return mContext.getString(key);
+ }
+
+ private LinphoneCore getLc() {
+ if (!LinphoneManager.isInstanciated())
+ return null;
+
+ return LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ }
+
+ public LpConfig getConfig() {
+ LinphoneCore lc = getLc();
+ if (lc != null) {
+ return lc.getConfig();
+ }
+
+ if (!LinphoneManager.isInstanciated()) {
+ Log.w("LinphoneManager not instanciated yet...");
+ return LinphoneCoreFactory.instance().createLpConfig(mContext.getFilesDir().getAbsolutePath() + "/.linphonerc");
+ }
+
+ return LinphoneCoreFactory.instance().createLpConfig(LinphoneManager.getInstance().mLinphoneConfigFile);
+ }
+
+ public void removePreviousVersionAuthInfoRemoval() {
+ getConfig().setBool("sip", "store_auth_info", true);
+ }
+
+ // App settings
+ public boolean isFirstLaunch() {
+ return getConfig().getBool("app", "first_launch", true);
+ }
+
+ public void firstLaunchSuccessful() {
+ getConfig().setBool("app", "first_launch", false);
+ }
+
+ public String getRingtone(String defaultRingtone) {
+ String ringtone = getConfig().getString("app", "ringtone", defaultRingtone);
+ if (ringtone == null || ringtone.length() == 0)
+ ringtone = defaultRingtone;
+ return ringtone;
+ }
+
+ public void setRingtone(String ringtonePath) {
+ getConfig().setString("app", "ringtone", ringtonePath);
+
+ }
+
+ public boolean shouldAutomaticallyAcceptFriendsRequests() {
+ return false; //TODO
+ }
+ // End of app settings
+
+ // Accounts settings
+ private LinphoneProxyConfig getProxyConfig(int n) {
+ LinphoneProxyConfig[] prxCfgs = getLc().getProxyConfigList();
+ if (n < 0 || n >= prxCfgs.length)
+ return null;
+ return prxCfgs[n];
+ }
+
+ private LinphoneAuthInfo getAuthInfo(int n) {
+ LinphoneProxyConfig prxCfg = getProxyConfig(n);
+ try {
+ LinphoneAddress addr = LinphoneCoreFactory.instance().createLinphoneAddress(prxCfg.getIdentity());
+ LinphoneAuthInfo authInfo = getLc().findAuthInfo(addr.getUserName(), null, addr.getDomain());
+ return authInfo;
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ /**
+ * Removes a authInfo from the core and returns a copy of it.
+ * Useful to edit a authInfo (you should call saveAuthInfo after the modifications to save them).
+ */
+ private LinphoneAuthInfo getClonedAuthInfo(int n) {
+ LinphoneAuthInfo authInfo = getAuthInfo(n);
+ if (authInfo == null)
+ return null;
+
+ LinphoneAuthInfo cloneAuthInfo = authInfo.clone();
+ getLc().removeAuthInfo(authInfo);
+ return cloneAuthInfo;
+ }
+
+ /**
+ * Saves a authInfo into the core.
+ * Useful to save the changes made to a cloned authInfo.
+ */
+ private void saveAuthInfo(LinphoneAuthInfo authInfo) {
+ getLc().addAuthInfo(authInfo);
+ }
+
+ public static class AccountBuilder {
+ private LinphoneCore lc;
+ private String tempUsername;
+ private String tempDisplayName;
+ private String tempUserId;
+ private String tempPassword;
+ private String tempDomain;
+ private String tempProxy;
+ private String tempRealm;
+ private boolean tempOutboundProxy;
+ private String tempContactsParams;
+ private String tempExpire;
+ private TransportType tempTransport;
+ private boolean tempAvpfEnabled = false;
+ private int tempAvpfRRInterval = 0;
+ private String tempQualityReportingCollector;
+ private boolean tempQualityReportingEnabled = false;
+ private int tempQualityReportingInterval = 0;
+ private boolean tempEnabled = true;
+ private boolean tempNoDefault = false;
+
+
+ public AccountBuilder(LinphoneCore lc) {
+ this.lc = lc;
+ }
+
+ public AccountBuilder setTransport(TransportType transport) {
+ tempTransport = transport;
+ return this;
+ }
+
+ public AccountBuilder setUsername(String username) {
+ tempUsername = username;
+ return this;
+ }
+
+ public AccountBuilder setDisplayName(String displayName) {
+ tempDisplayName = displayName;
+ return this;
+ }
+
+ public AccountBuilder setPassword(String password) {
+ tempPassword = password;
+ return this;
+ }
+
+ public AccountBuilder setDomain(String domain) {
+ tempDomain = domain;
+ return this;
+ }
+
+ public AccountBuilder setProxy(String proxy) {
+ tempProxy = proxy;
+ return this;
+ }
+
+ public AccountBuilder setOutboundProxyEnabled(boolean enabled) {
+ tempOutboundProxy = enabled;
+ return this;
+ }
+
+ public AccountBuilder setContactParameters(String contactParams) {
+ tempContactsParams = contactParams;
+ return this;
+ }
+
+ public AccountBuilder setExpires(String expire) {
+ tempExpire = expire;
+ return this;
+ }
+
+ public AccountBuilder setUserId(String userId) {
+ tempUserId = userId;
+ return this;
+ }
+
+ public AccountBuilder setAvpfEnabled(boolean enable) {
+ tempAvpfEnabled = enable;
+ return this;
+ }
+
+ public AccountBuilder setAvpfRRInterval(int interval) {
+ tempAvpfRRInterval = interval;
+ return this;
+ }
+
+ public AccountBuilder setRealm(String realm) {
+ tempRealm = realm;
+ return this;
+ }
+
+ public AccountBuilder setQualityReportingCollector(String collector) {
+ tempQualityReportingCollector = collector;
+ return this;
+ }
+
+ public AccountBuilder setQualityReportingEnabled(boolean enable) {
+ tempQualityReportingEnabled = enable;
+ return this;
+ }
+
+ public AccountBuilder setQualityReportingInterval(int interval) {
+ tempQualityReportingInterval = interval;
+ return this;
+ }
+
+ public AccountBuilder setEnabled(boolean enable) {
+ tempEnabled = enable;
+ return this;
+ }
+
+ public AccountBuilder setNoDefault(boolean yesno) {
+ tempNoDefault = yesno;
+ return this;
+ }
+
+ /**
+ * Creates a new account
+ * @throws LinphoneCoreException
+ */
+ public void saveNewAccount() throws LinphoneCoreException {
+
+ if (tempUsername == null || tempUsername.length() < 1 || tempDomain == null || tempDomain.length() < 1) {
+ Log.w("Skipping account save: username or domain not provided");
+ return;
+ }
+
+ String identity = "sip:" + tempUsername + "@" + tempDomain;
+ String proxy = "sip:";
+ if (tempProxy == null) {
+ proxy += tempDomain;
+ } else {
+ if (!tempProxy.startsWith("sip:") && !tempProxy.startsWith("= 0 && accountIndex < prxCfgs.length)
+ getLc().setDefaultProxyConfig(prxCfgs[accountIndex]);
+ }
+
+ public int getDefaultAccountIndex() {
+ LinphoneProxyConfig defaultPrxCfg = getLc().getDefaultProxyConfig();
+ if (defaultPrxCfg == null)
+ return -1;
+
+ LinphoneProxyConfig[] prxCfgs = getLc().getProxyConfigList();
+ for (int i = 0; i < prxCfgs.length; i++) {
+ if (defaultPrxCfg.getIdentity().equals(prxCfgs[i].getIdentity())) {
+ return i;
+ }
+ }
+ return -1;
+ }
+
+ public int getAccountCount() {
+ if (getLc() == null || getLc().getProxyConfigList() == null)
+ return 0;
+
+ return getLc().getProxyConfigList().length;
+ }
+
+ public void setAccountEnabled(int n, boolean enabled) {
+ LinphoneProxyConfig prxCfg = getProxyConfig(n);
+ prxCfg.edit();
+ prxCfg.enableRegister(enabled);
+ prxCfg.done();
+
+ // If default proxy config is disabled, try to set another one as default proxy
+ if (!enabled && getLc().getDefaultProxyConfig().getIdentity().equals(prxCfg.getIdentity())) {
+ int count = getLc().getProxyConfigList().length;
+ if (count > 1) {
+ for (int i = 0; i < count; i++) {
+ if (isAccountEnabled(i)) {
+ getLc().setDefaultProxyConfig(getProxyConfig(i));
+ break;
+ }
+ }
+ }
+ }
+ }
+
+ public boolean isAccountEnabled(int n) {
+ return getProxyConfig(n).registerEnabled();
+ }
+
+ public void resetDefaultProxyConfig(){
+ int count = getLc().getProxyConfigList().length;
+ for (int i = 0; i < count; i++) {
+ if (isAccountEnabled(i)) {
+ getLc().setDefaultProxyConfig(getProxyConfig(i));
+ break;
+ }
+ }
+
+ if(getLc().getDefaultProxyConfig() == null){
+ getLc().setDefaultProxyConfig(getProxyConfig(0));
+ }
+ }
+
+ public void deleteAccount(int n) {
+ final LinphoneProxyConfig proxyCfg = getProxyConfig(n);
+
+ if (proxyCfg != null)
+ getLc().removeProxyConfig(proxyCfg);
+ if (getLc().getProxyConfigList().length != 0) {
+ resetDefaultProxyConfig();
+ getLc().refreshRegisters();
+ }
+ }
+ // End of accounts settings
+
+ // Audio settings
+ public void setEchoCancellation(boolean enable) {
+ getLc().enableEchoCancellation(enable);
+ }
+
+ public boolean isEchoCancellationEnabled() {
+ return getLc().isEchoCancellationEnabled();
+ }
+
+ public int getEchoCalibration() {
+ return getConfig().getInt("sound", "ec_delay", -1);
+ }
+
+ public boolean isEchoConfigurationUpdated() {
+ return getConfig().getBool("app", "ec_updated", false);
+ }
+
+ public void echoConfigurationUpdated() {
+ getConfig().setBool("app", "ec_updated", true);
+ }
+ // End of audio settings
+
+ // Video settings
+ public boolean useFrontCam() {
+ return getConfig().getBool("app", "front_camera_default", true);
+ }
+
+ public void setFrontCamAsDefault(boolean frontcam) {
+ getConfig().setBool("app", "front_camera_default", frontcam);
+ }
+
+ public boolean isVideoEnabled() {
+ return getLc().isVideoSupported() && getLc().isVideoEnabled();
+ }
+
+ public void enableVideo(boolean enable) {
+ getLc().enableVideo(enable, enable);
+ }
+
+ public boolean shouldInitiateVideoCall() {
+ return getLc().getVideoAutoInitiatePolicy();
+ }
+
+ public void setInitiateVideoCall(boolean initiate) {
+ getLc().setVideoPolicy(initiate, shouldAutomaticallyAcceptVideoRequests());
+ }
+
+ public boolean shouldAutomaticallyAcceptVideoRequests() {
+ return getLc().getVideoAutoAcceptPolicy();
+ }
+
+ public void setAutomaticallyAcceptVideoRequests(boolean accept) {
+ getLc().setVideoPolicy(shouldInitiateVideoCall(), accept);
+ }
+
+ public String getVideoPreset() {
+ String preset = getLc().getVideoPreset();
+ if (preset == null) preset = "default";
+ return preset;
+ }
+
+ public void setVideoPreset(String preset) {
+ if (preset.equals("default")) preset = null;
+ getLc().setVideoPreset(preset);
+ preset = getVideoPreset();
+ if (!preset.equals("custom")) {
+ getLc().setPreferredFramerate(0);
+ }
+ setPreferredVideoSize(getPreferredVideoSize()); // Apply the bandwidth limit
+ }
+
+ public String getPreferredVideoSize() {
+ //LinphoneCore can only return video size (width and height), not the name
+ return getConfig().getString("video", "size", "qvga");
+ }
+
+ public void setPreferredVideoSize(String preferredVideoSize) {
+ getLc().setPreferredVideoSizeByName(preferredVideoSize);
+ String preset = getVideoPreset();
+ if (!preset.equals("custom")) {
+ int bandwidth = 512;
+ if (preferredVideoSize.equals("720p")) {
+ bandwidth = 1024 + 128;
+ } else if (preferredVideoSize.equals("vga")) {
+ bandwidth = 660;
+ } else if (preferredVideoSize.equals("qvga")) {
+ bandwidth = 380;
+ } else if (preferredVideoSize.equals("qcif")) {
+ bandwidth = 256;
+ }
+ setBandwidthLimit(bandwidth);
+ }
+ }
+
+ public int getPreferredVideoFps() {
+ return (int)getLc().getPreferredFramerate();
+ }
+
+ public void setPreferredVideoFps(int fps) {
+ getLc().setPreferredFramerate(fps);
+ }
+
+ public int getBandwidthLimit() {
+ return getLc().getDownloadBandwidth();
+ }
+
+ public void setBandwidthLimit(int bandwidth) {
+ getLc().setUploadBandwidth(bandwidth);
+ getLc().setDownloadBandwidth(bandwidth);
+ }
+ // End of video settings
+
+ // Call settings
+ public boolean useRfc2833Dtmfs() {
+ return getLc().getUseRfc2833ForDtmfs();
+ }
+
+ public void sendDtmfsAsRfc2833(boolean use) {
+ getLc().setUseRfc2833ForDtmfs(use);
+ }
+
+ public boolean useSipInfoDtmfs() {
+ return getLc().getUseSipInfoForDtmfs();
+ }
+
+ public void sendDTMFsAsSipInfo(boolean use) {
+ getLc().setUseSipInfoForDtmfs(use);
+ }
+
+ public String getVoiceMailUri() {
+ return getConfig().getString("app", "voice_mail", null);
+ }
+
+ public void setVoiceMailUri(String uri) {
+ getConfig().setString("app", "voice_mail", uri);
+ }
+ // End of call settings
+
+ // Network settings
+ public void setWifiOnlyEnabled(Boolean enable) {
+ getConfig().setBool("app", "wifi_only", enable);
+ }
+
+ public boolean isWifiOnlyEnabled() {
+ return getConfig().getBool("app", "wifi_only", false);
+ }
+
+ public String getStunServer() {
+ return getLc().getStunServer();
+ }
+
+ public void setStunServer(String stun) {
+ getLc().setStunServer(stun);
+ }
+
+ public void setIceEnabled(boolean enabled) {
+ if (enabled) {
+ getLc().setFirewallPolicy(FirewallPolicy.UseIce);
+ } else {
+ String stun = getStunServer();
+ if (stun != null && stun.length() > 0) {
+ getLc().setFirewallPolicy(FirewallPolicy.UseStun);
+ } else {
+ getLc().setFirewallPolicy(FirewallPolicy.NoFirewall);
+ }
+ }
+ }
+
+ public void setUpnpEnabled(boolean enabled) {
+ if (enabled) {
+ if (isIceEnabled()) {
+ Log.e("Cannot have both ice and upnp enabled, disabling upnp");
+ } else {
+ getLc().setFirewallPolicy(FirewallPolicy.UseUpnp);
+ }
+ }
+ else {
+ String stun = getStunServer();
+ if (stun != null && stun.length() > 0) {
+ getLc().setFirewallPolicy(FirewallPolicy.UseStun);
+ } else {
+ getLc().setFirewallPolicy(FirewallPolicy.NoFirewall);
+ }
+ }
+ }
+
+ public void useRandomPort(boolean enabled) {
+ useRandomPort(enabled, true);
+ }
+
+ public void useRandomPort(boolean enabled, boolean apply) {
+ getConfig().setBool("app", "random_port", enabled);
+ if (apply) {
+ if (enabled) {
+ setSipPort(LINPHONE_CORE_RANDOM_PORT);
+ } else {
+ setSipPort(5060);
+ }
+ }
+ }
+
+ public boolean isUsingRandomPort() {
+ return getConfig().getBool("app", "random_port", true);
+ }
+
+ public String getSipPort() {
+ Transports transports = getLc().getSignalingTransportPorts();
+ int port;
+ if (transports.udp > 0)
+ port = transports.udp;
+ else
+ port = transports.tcp;
+ return String.valueOf(port);
+ }
+
+ public void setSipPort(int port) {
+ Transports transports = getLc().getSignalingTransportPorts();
+ transports.udp = port;
+ transports.tcp = port;
+ transports.tls = LINPHONE_CORE_RANDOM_PORT;
+ getLc().setSignalingTransportPorts(transports);
+ }
+
+ public boolean isUpnpEnabled() {
+ return getLc().upnpAvailable() && getLc().getFirewallPolicy() == FirewallPolicy.UseUpnp;
+ }
+
+ public boolean isIceEnabled() {
+ return getLc().getFirewallPolicy() == FirewallPolicy.UseIce;
+ }
+
+ public MediaEncryption getMediaEncryption() {
+ return getLc().getMediaEncryption();
+ }
+
+ public void setMediaEncryption(MediaEncryption menc) {
+ if (menc == null)
+ return;
+
+ getLc().setMediaEncryption(menc);
+ }
+
+ public void setPushNotificationEnabled(boolean enable) {
+ getConfig().setBool("app", "push_notification", enable);
+
+ if (enable) {
+ // Add push infos to exisiting proxy configs
+ String regId = getPushNotificationRegistrationID();
+ String appId = getString(R.string.push_sender_id);
+ if (regId != null && getLc().getProxyConfigList().length > 0) {
+ for (LinphoneProxyConfig lpc : getLc().getProxyConfigList()) {
+ String contactInfos = "app-id=" + appId + ";pn-type=google;pn-tok=" + regId;
+ lpc.edit();
+ lpc.setContactUriParameters(contactInfos);
+ lpc.done();
+ Log.d("Push notif infos added to proxy config");
+ }
+ getLc().refreshRegisters();
+ }
+ } else {
+ if (getLc().getProxyConfigList().length > 0) {
+ for (LinphoneProxyConfig lpc : getLc().getProxyConfigList()) {
+ lpc.edit();
+ lpc.setContactUriParameters(null);
+ lpc.done();
+ Log.d("Push notif infos removed from proxy config");
+ }
+ getLc().refreshRegisters();
+ }
+ }
+ }
+
+ public boolean isPushNotificationEnabled() {
+ return getConfig().getBool("app", "push_notification", false);
+ }
+
+ public void setPushNotificationRegistrationID(String regId) {
+ getConfig().setString("app", "push_notification_regid", regId);
+ }
+
+ public String getPushNotificationRegistrationID() {
+ return getConfig().getString("app", "push_notification_regid", null);
+ }
+
+ public void useIpv6(Boolean enable) {
+ getLc().enableIpv6(enable);
+ }
+
+ public boolean isUsingIpv6() {
+ return getLc().isIpv6Enabled();
+ }
+ // End of network settings
+
+ // Advanced settings
+ public void setDebugEnabled(boolean enabled) {
+ getConfig().setBool("app", "debug", enabled);
+ LinphoneCoreFactory.instance().enableLogCollection(enabled);
+ LinphoneCoreFactory.instance().setDebugMode(enabled, getString(R.string.app_name));
+ }
+
+ public boolean isDebugEnabled() {
+ return getConfig().getBool("app", "debug", false);
+ }
+
+ public void setBackgroundModeEnabled(boolean enabled) {
+ getConfig().setBool("app", "background_mode", enabled);
+ }
+
+ public boolean isBackgroundModeEnabled() {
+ return getConfig().getBool("app", "background_mode", true);
+ }
+
+ public void setAnimationsEnabled(boolean enabled) {
+ getConfig().setBool("app", "animations", enabled);
+ }
+
+ public boolean areAnimationsEnabled() {
+ return getConfig().getBool("app", "animations", false);
+ }
+
+ public boolean isAutoStartEnabled() {
+ return getConfig().getBool("app", "auto_start", false);
+ }
+
+ public void setAutoStart(boolean autoStartEnabled) {
+ getConfig().setBool("app", "auto_start", autoStartEnabled);
+ }
+
+ public String getSharingPictureServerUrl() {
+ return getConfig().getString("app", "sharing_server", null);
+ }
+
+ public void setSharingPictureServerUrl(String url) {
+ getConfig().setString("app", "sharing_server", url);
+ }
+
+ public void setRemoteProvisioningUrl(String url) {
+ if (url != null && url.length() == 0) {
+ url = null;
+ }
+
+ LpConfig config = getConfig();
+ config.setString("misc", "config-uri", url);
+ config.sync();
+ }
+
+ public String getRemoteProvisioningUrl() {
+ return getConfig().getString("misc", "config-uri", null);
+ }
+
+ public void setDefaultDisplayName(String displayName) {
+ getLc().setPrimaryContact(displayName, getDefaultUsername());
+ }
+
+ public String getDefaultDisplayName() {
+ return getLc().getPrimaryContactDisplayName();
+ }
+
+ public void setDefaultUsername(String username) {
+ getLc().setPrimaryContact(getDefaultDisplayName(), username);
+ }
+
+ public String getDefaultUsername() {
+ return getLc().getPrimaryContactUsername();
+ }
+ // End of advanced settings
+
+ // Tunnel settings
+ private TunnelConfig tunnelConfig = null;
+
+ public TunnelConfig getTunnelConfig() {
+ if(getLc().isTunnelAvailable()) {
+ if(tunnelConfig == null) {
+ TunnelConfig servers[] = getLc().tunnelGetServers();
+ if(servers.length > 0) {
+ tunnelConfig = servers[0];
+ } else {
+ tunnelConfig = new TunnelConfig();
+ tunnelConfig.setDelay(500);
+ }
+ }
+ return tunnelConfig;
+ } else {
+ return null;
+ }
+ }
+
+ public String getTunnelHost() {
+ TunnelConfig config = getTunnelConfig();
+ if(config != null) {
+ return config.getHost();
+ } else {
+ return null;
+ }
+ }
+
+ public void setTunnelHost(String host) {
+ TunnelConfig config = getTunnelConfig();
+ if(config != null) {
+ config.setHost(host);
+ LinphoneManager.getInstance().initTunnelFromConf();
+ }
+ }
+
+ public int getTunnelPort() {
+ TunnelConfig config = getTunnelConfig();
+ if(config != null) {
+ return config.getPort();
+ } else {
+ return -1;
+ }
+ }
+
+ public void setTunnelPort(int port) {
+ TunnelConfig config = getTunnelConfig();
+ if(config != null) {
+ config.setPort(port);
+ LinphoneManager.getInstance().initTunnelFromConf();
+ }
+ }
+
+ public String getTunnelMode() {
+ return getConfig().getString("app", "tunnel", null);
+ }
+
+ public void setTunnelMode(String mode) {
+ getConfig().setString("app", "tunnel", mode);
+ LinphoneManager.getInstance().initTunnelFromConf();
+ }
+ // End of tunnel settings
+
+ public boolean isProvisioningLoginViewEnabled() {
+ return getConfig().getBool("app", "show_login_view", false);
+ }
+
+ public void disableProvisioningLoginView() {
+ if (isProvisioningLoginViewEnabled()) { // Only do it if it was previously enabled
+ getConfig().setBool("app", "show_login_view", false);
+ } else {
+ Log.w("Remote provisioning login view wasn't enabled, ignoring");
+ }
+ }
+
+ public void firstRemoteProvisioningSuccessful() {
+ getConfig().setBool("app", "first_remote_provisioning", false);
+ }
+
+ public boolean isFirstRemoteProvisioning() {
+ return getConfig().getBool("app", "first_remote_provisioning", true);
+ }
+
+ public boolean isAdaptiveRateControlEnabled() {
+ return getLc().isAdaptiveRateControlEnabled();
+ }
+
+ public void enableAdaptiveRateControl(boolean enabled) {
+ getLc().enableAdaptiveRateControl(enabled);
+ }
+
+ public AdaptiveRateAlgorithm getAdaptiveRateAlgorithm() {
+ return getLc().getAdaptiveRateAlgorithm();
+ }
+
+ public void setAdaptiveRateAlgorithm(AdaptiveRateAlgorithm alg) {
+ getLc().setAdaptiveRateAlgorithm(alg);
+ }
+
+ public int getCodecBitrateLimit() {
+ return getConfig().getInt("audio", "codec_bitrate_limit", 36);
+ }
+
+ public void setCodecBitrateLimit(int bitrate) {
+ getConfig().setInt("audio", "codec_bitrate_limit", bitrate);
+ }
+
+ public void contactsMigrationDone(){
+ getConfig().setBool("app", "contacts_migration_done",true);
+ }
+
+ public boolean isContactsMigrationDone(){
+ return getConfig().getBool("app", "contacts_migration_done",false);
+ }
+
+ public String getDebugPopupAddress(){
+ return getConfig().getString("app", "debug_popup_magic", null);
+ }
+
+ public void enableDebugLogs(Boolean debugMode){
+ getConfig().setBool("app", "debug_logs_enabled", debugMode);
+ }
+
+ public Boolean isDebugLogsEnabled(){
+ return getConfig().getBool("app", "debug_logs_enabled", false);
+ }
+}
diff --git a/src/org/linphone/LinphoneService.java b/src/org/linphone/LinphoneService.java
index e1a151f44..2b5ec9c7b 100644
--- a/src/org/linphone/LinphoneService.java
+++ b/src/org/linphone/LinphoneService.java
@@ -18,13 +18,9 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
package org.linphone;
-import java.io.FileInputStream;
-import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
-import org.linphone.LinphoneManager.NewOutgoingCallUiListener;
-import org.linphone.LinphoneSimpleListener.LinphoneServiceListener;
import org.linphone.compatibility.Compatibility;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
@@ -33,32 +29,32 @@ import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.GlobalState;
import org.linphone.core.LinphoneCore.RegistrationState;
import org.linphone.core.LinphoneCoreException;
-import org.linphone.core.LinphoneCoreFactoryImpl;
+import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.core.LinphoneCoreListenerBase;
import org.linphone.core.LinphoneProxyConfig;
-import org.linphone.core.OnlineStatus;
import org.linphone.mediastream.Log;
import org.linphone.mediastream.Version;
+import android.annotation.TargetApi;
import android.app.Activity;
+import android.app.AlarmManager;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager.NameNotFoundException;
+import android.database.ContentObserver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
-import android.media.MediaPlayer;
import android.net.Uri;
-import android.net.wifi.WifiManager;
-import android.net.wifi.WifiManager.WifiLock;
import android.os.Build;
import android.os.Handler;
import android.os.IBinder;
-import android.preference.PreferenceManager;
+import android.os.SystemClock;
+import android.provider.ContactsContract;
import android.provider.MediaStore;
/**
@@ -75,20 +71,25 @@ import android.provider.MediaStore;
* @author Guillaume Beraudo
*
*/
-public final class LinphoneService extends Service implements LinphoneServiceListener {
+public final class LinphoneService extends Service {
/* Listener needs to be implemented in the Service as it calls
* setLatestEventInfo and startActivity() which needs a context.
*/
-
- public Handler mHandler = new Handler();
+ public static final String START_LINPHONE_LOGS = " ==== Phone information dump ====";
+ public static final int IC_LEVEL_ORANGE=0;
+ /*private static final int IC_LEVEL_GREEN=1;
+ private static final int IC_LEVEL_RED=2;*/
+ public static final int IC_LEVEL_OFFLINE=3;
+
private static LinphoneService instance;
-
-// private boolean mTestDelayElapsed; // add a timer for testing
- private boolean mTestDelayElapsed = true; // no timer
- private WifiManager mWifiManager ;
- private WifiLock mWifiLock ;
+
+ private final static int NOTIF_ID=1;
+ private final static int INCALL_NOTIF_ID=2;
+ private final static int MESSAGE_NOTIF_ID=3;
+ private final static int CUSTOM_NOTIF_ID=4;
+
public static boolean isReady() {
- return instance!=null && instance.mTestDelayElapsed;
+ return instance != null && instance.mTestDelayElapsed;
}
/**
@@ -100,11 +101,11 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
throw new RuntimeException("LinphoneService not instantiated yet");
}
-
- private final static int NOTIF_ID=1;
- private final static int INCALL_NOTIF_ID=2;
- private final static int MESSAGE_NOTIF_ID=3;
- private final static int CUSTOM_NOTIF_ID=4;
+ public Handler mHandler = new Handler();
+
+// private boolean mTestDelayElapsed; // add a timer for testing
+ private boolean mTestDelayElapsed = true; // no timer
+ private NotificationManager mNM;
private Notification mNotif;
private Notification mIncallNotif;
@@ -112,15 +113,12 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
private Notification mCustomNotif;
private int mMsgNotifCount;
private PendingIntent mNotifContentIntent;
+ private PendingIntent mkeepAlivePendingIntent;
private String mNotificationTitle;
+ private boolean mDisableRegistrationStatus;
+ private LinphoneCoreListenerBase mListener;
+ public static int notifcationsPriority = (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41) ? Notification.PRIORITY_DEFAULT : 0);
-
- private static final int IC_LEVEL_ORANGE=0;
- /*private static final int IC_LEVEL_GREEN=1;
- private static final int IC_LEVEL_RED=2;*/
- private static final int IC_LEVEL_OFFLINE=3;
-
-
public int getMessageNotifCount() {
return mMsgNotifCount;
}
@@ -134,14 +132,12 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
super.onCreate();
// In case restart after a crash. Main in LinphoneActivity
- LinphonePreferenceManager.getInstance(this);
-
- // Set default preferences
- PreferenceManager.setDefaultValues(this, R.xml.preferences, true);
+ mNotificationTitle = getString(R.string.service_name);
+ // Needed in order for the two next calls to succeed, libraries must have been loaded first
+ LinphoneCoreFactory.instance().setLogCollectionPath(getFilesDir().getAbsolutePath());
+ LinphoneCoreFactory.instance().enableLogCollection(!(getResources().getBoolean(R.bool.disable_every_log)));
- mNotificationTitle = getString(R.string.app_name);
-
// Dump some debugging information to the logs
Log.i(START_LINPHONE_LOGS);
dumpDeviceInformation();
@@ -149,26 +145,87 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
mNM = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
mNM.cancel(INCALL_NOTIF_ID); // in case of crash the icon is not removed
-
- mNotif = new Notification();
- mNotif.icon = R.drawable.status_level;
- mNotif.when = System.currentTimeMillis();
- mNotif.iconLevel=IC_LEVEL_ORANGE;
- mNotif.flags |= Notification.FLAG_ONGOING_EVENT;
Intent notifIntent = new Intent(this, incomingReceivedActivity);
notifIntent.putExtra("Notification", true);
mNotifContentIntent = PendingIntent.getActivity(this, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
-
- Compatibility.setNotificationLatestEventInfo(mNotif, this, mNotificationTitle, "", mNotifContentIntent);
- LinphoneManager.createAndStart(this, this);
- mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE);
- mWifiLock = mWifiManager.createWifiLock(WifiManager.WIFI_MODE_FULL_HIGH_PERF, this.getPackageName()+"-wifi-call-lock");
- mWifiLock.setReferenceCounted(false);
+ Bitmap bm = null;
+ try {
+ bm = BitmapFactory.decodeResource(getResources(), R.drawable.logo_linphone_57x57);
+ } catch (Exception e) {
+ }
+ mNotif = Compatibility.createNotification(this, mNotificationTitle, "", R.drawable.status_level, IC_LEVEL_OFFLINE, bm, mNotifContentIntent, true,notifcationsPriority);
+
+ LinphoneManager.createAndStart(LinphoneService.this);
+
instance = this; // instance is ready once linphone manager has been created
-
+ LinphoneManager.getLc().addListener(mListener = new LinphoneCoreListenerBase(){
+ @Override
+ public void callState(LinphoneCore lc, LinphoneCall call, LinphoneCall.State state, String message) {
+ if (instance == null) {
+ Log.i("Service not ready, discarding call state change to ",state.toString());
+ return;
+ }
+
+ if (state == LinphoneCall.State.IncomingReceived) {
+ onIncomingReceived();
+ }
+
+ if (state == State.CallUpdatedByRemote) {
+ // If the correspondent proposes video while audio call
+ boolean remoteVideo = call.getRemoteParams().getVideoEnabled();
+ boolean localVideo = call.getCurrentParamsCopy().getVideoEnabled();
+ boolean autoAcceptCameraPolicy = LinphonePreferences.instance().shouldAutomaticallyAcceptVideoRequests();
+ if (remoteVideo && !localVideo && !autoAcceptCameraPolicy && !LinphoneManager.getLc().isInConference()) {
+ try {
+ LinphoneManager.getLc().deferCallUpdate(call);
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+ }
+ }
+
+ if (state == State.StreamsRunning) {
+ // Workaround bug current call seems to be updated after state changed to streams running
+ if (getResources().getBoolean(R.bool.enable_call_notification))
+ refreshIncallIcon(call);
+ } else {
+ if (getResources().getBoolean(R.bool.enable_call_notification))
+ refreshIncallIcon(LinphoneManager.getLc().getCurrentCall());
+ }
+ }
+
+ @Override
+ public void globalState(LinphoneCore lc,LinphoneCore.GlobalState state, String message) {
+ if (state == GlobalState.GlobalOn) {
+ sendNotification(IC_LEVEL_OFFLINE, R.string.notification_started);
+ }
+ }
+
+ @Override
+ public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg, LinphoneCore.RegistrationState state, String smessage) {
+// if (instance == null) {
+// Log.i("Service not ready, discarding registration state change to ",state.toString());
+// return;
+// }
+ if (!mDisableRegistrationStatus) {
+ if (state == RegistrationState.RegistrationOk && LinphoneManager.getLc().getDefaultProxyConfig() != null && LinphoneManager.getLc().getDefaultProxyConfig().isRegistered()) {
+ sendNotification(IC_LEVEL_ORANGE, R.string.notification_registered);
+ }
+
+ if ((state == RegistrationState.RegistrationFailed || state == RegistrationState.RegistrationCleared) && (LinphoneManager.getLc().getDefaultProxyConfig() == null || !LinphoneManager.getLc().getDefaultProxyConfig().isRegistered())) {
+ sendNotification(IC_LEVEL_OFFLINE, R.string.notification_register_failure);
+ }
+
+ if (state == RegistrationState.RegistrationNone) {
+ sendNotification(IC_LEVEL_OFFLINE, R.string.notification_started);
+ }
+ }
+ }
+ });
+
// Retrieve methods to publish notification and keep Android
// from killing us and keep the audio quality high.
if (Version.sdkStrictlyBelow(Version.API05_ECLAIR_20)) {
@@ -182,10 +239,12 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
mStartForeground = getClass().getMethod("startForeground", mStartFgSign);
mStopForeground = getClass().getMethod("stopForeground", mStopFgSign);
} catch (NoSuchMethodException e) {
- Log.e(e, "Couldn't find startGoreground or stopForeground");
+ Log.e(e, "Couldn't find startForeground or stopForeground");
}
}
+ this.getContentResolver().registerContentObserver(ContactsContract.Contacts.CONTENT_URI, true, mObserver);
+
startForegroundCompat(NOTIF_ID, mNotif);
if (!mTestDelayElapsed) {
@@ -197,9 +256,25 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
}, 5000);
}
- LinphoneManager.getLc().setPresenceInfo(0, "", OnlineStatus.Online);
+ //make sure the application will at least wakes up every 10 mn
+ Intent intent = new Intent(this, KeepAliveHandler.class);
+ mkeepAlivePendingIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
+ ((AlarmManager) this.getSystemService(Context.ALARM_SERVICE)).setRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP
+ , SystemClock.elapsedRealtime()+600000
+ , 600000
+ , mkeepAlivePendingIntent);
}
+ private ContentObserver mObserver = new ContentObserver(new Handler()) {
+
+ @Override
+ public void onChange(boolean selfChange) {
+ super.onChange(selfChange);
+ }
+
+ };
+
+
private enum IncallIconState {INCALL, PAUSE, VIDEO, IDLE}
private IncallIconState mCurrentIncallIconState = IncallIconState.IDLE;
private synchronized void setIncallIcon(IncallIconState state) {
@@ -237,10 +312,11 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
String userName = call.getRemoteAddress().getUserName();
String domain = call.getRemoteAddress().getDomain();
String displayName = call.getRemoteAddress().getDisplayName();
- LinphoneAddress address = LinphoneCoreFactoryImpl.instance().createLinphoneAddress("sip:" + userName + "@" + domain);
+ LinphoneAddress address = LinphoneCoreFactory.instance().createLinphoneAddress(userName,domain,null);
address.setDisplayName(displayName);
- Uri pictureUri = LinphoneUtils.findUriPictureOfContactAndSetDisplayName(address, getContentResolver());
+ Contact contact = ContactsManager.getInstance().findContactWithAddress(getContentResolver(), address);
+ Uri pictureUri = contact != null ? contact.getPhotoUri() : null;
Bitmap bm = null;
try {
bm = MediaStore.Images.Media.getBitmap(getContentResolver(), pictureUri);
@@ -271,23 +347,25 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
}
}
+ @Deprecated
public void addNotification(Intent onClickIntent, int iconResourceID, String title, String message) {
+ addCustomNotification(onClickIntent, iconResourceID, title, message, true);
+ }
+
+ public void addCustomNotification(Intent onClickIntent, int iconResourceID, String title, String message, boolean isOngoingEvent) {
PendingIntent notifContentIntent = PendingIntent.getActivity(this, 0, onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
- if (mCustomNotif == null) {
- mCustomNotif = new Notification();
+ Bitmap bm = null;
+ try {
+ bm = BitmapFactory.decodeResource(getResources(), R.drawable.logo_linphone_57x57);
+ } catch (Exception e) {
}
-
- mCustomNotif.icon = iconResourceID;
- mCustomNotif.iconLevel = 0;
- mCustomNotif.when = System.currentTimeMillis();
- mCustomNotif.flags &= Notification.FLAG_ONGOING_EVENT;
+ mCustomNotif = Compatibility.createNotification(this, title, message, iconResourceID, 0, bm, notifContentIntent, isOngoingEvent,notifcationsPriority);
mCustomNotif.defaults |= Notification.DEFAULT_VIBRATE;
mCustomNotif.defaults |= Notification.DEFAULT_SOUND;
mCustomNotif.defaults |= Notification.DEFAULT_LIGHTS;
- Compatibility.setNotificationLatestEventInfo(mCustomNotif, this, title, message, notifContentIntent);
notifyWrapper(CUSTOM_NOTIF_ID, mCustomNotif);
}
@@ -313,11 +391,23 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
mMsgNotifCount++;
}
- Uri pictureUri = LinphoneUtils.findUriPictureOfContactAndSetDisplayName(LinphoneCoreFactoryImpl.instance().createLinphoneAddress(fromSipUri), getContentResolver());
- Bitmap bm = null;
+ Uri pictureUri = null;
try {
- bm = MediaStore.Images.Media.getBitmap(getContentResolver(), pictureUri);
- } catch (Exception e) {
+ Contact contact = ContactsManager.getInstance().findContactWithAddress(getContentResolver(), LinphoneCoreFactory.instance().createLinphoneAddress(fromSipUri));
+ if (contact != null)
+ pictureUri = contact.getPhotoUri();
+ } catch (LinphoneCoreException e1) {
+ Log.e("Cannot parse from address ", e1);
+ }
+
+ Bitmap bm = null;
+ if (pictureUri != null) {
+ try {
+ bm = MediaStore.Images.Media.getBitmap(getContentResolver(), pictureUri);
+ } catch (Exception e) {
+ bm = BitmapFactory.decodeResource(getResources(), R.drawable.unknown_small);
+ }
+ } else {
bm = BitmapFactory.decodeResource(getResources(), R.drawable.unknown_small);
}
mMsgNotif = Compatibility.createMessageNotification(getApplicationContext(), mMsgNotifCount, fromName, message, bm, notifContentIntent);
@@ -335,7 +425,6 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
int.class, Notification.class};
private static final Class>[] mStopFgSign = new Class[] {boolean.class};
- private NotificationManager mNM;
private Method mSetForeground;
private Method mStartForeground;
private Method mStopForeground;
@@ -399,23 +488,19 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
invokeMethod(mSetForeground, mSetForegroundArgs);
}
}
-
-
-
-
- public static final String START_LINPHONE_LOGS = " ==== Phone information dump ====";
+
+ @SuppressWarnings("deprecation")
private void dumpDeviceInformation() {
StringBuilder sb = new StringBuilder();
sb.append("DEVICE=").append(Build.DEVICE).append("\n");
sb.append("MODEL=").append(Build.MODEL).append("\n");
//MANUFACTURER doesn't exist in android 1.5.
//sb.append("MANUFACTURER=").append(Build.MANUFACTURER).append("\n");
- sb.append("SDK=").append(Build.VERSION.SDK_INT);
+ sb.append("SDK=").append(Build.VERSION.SDK_INT).append("\n");
+ sb.append("EABI=").append(Version.getCpuAbis().get(0)).append("\n");
Log.i(sb.toString());
}
-
-
private void dumpInstalledLinphoneInformation() {
PackageInfo info = null;
try {
@@ -428,10 +513,12 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
Log.i("Linphone version is unknown");
}
}
+
+ public void disableNotificationsAutomaticRegistrationStatusContent() {
+ mDisableRegistrationStatus = true;
+ }
- private synchronized void sendNotification(int level, int textId) {
- mNotif.iconLevel = level;
- mNotif.when=System.currentTimeMillis();
+ public synchronized void sendNotification(int level, int textId) {
String text = getString(textId);
if (text.contains("%s") && LinphoneManager.getLc() != null) {
// Test for null lc is to avoid a NPE when Android mess up badly with the String resources.
@@ -439,8 +526,13 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
String id = lpc != null ? lpc.getIdentity() : "";
text = String.format(text, id);
}
-
- Compatibility.setNotificationLatestEventInfo(mNotif, this, mNotificationTitle, text, mNotifContentIntent);
+
+ Bitmap bm = null;
+ try {
+ bm = BitmapFactory.decodeResource(getResources(), R.drawable.logo_linphone_57x57);
+ } catch (Exception e) {
+ }
+ mNotif = Compatibility.createNotification(this, mNotificationTitle, text, R.drawable.status_level, level, bm, mNotifContentIntent, true,notifcationsPriority);
notifyWrapper(NOTIF_ID, mNotif);
}
@@ -451,7 +543,7 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
* stop linphone as soon as it is started. Transport configured with TLS.
*/
private synchronized void notifyWrapper(int id, Notification notification) {
- if (instance != null) {
+ if (instance != null && notification != null) {
mNM.notify(id, notification);
} else {
Log.i("Service not ready, discarding notification");
@@ -462,10 +554,25 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
public IBinder onBind(Intent intent) {
return null;
}
+
+ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
+ @Override
+ public void onTaskRemoved(Intent rootIntent) {
+ if (getResources().getBoolean(R.bool.kill_service_with_task_manager)) {
+ Log.d("Task removed, stop service");
+ LinphoneManager.getLc().setNetworkReachable(false);
+ stopSelf();
+ }
+ super.onTaskRemoved(rootIntent);
+ }
@Override
public synchronized void onDestroy() {
- LinphoneManager.getLc().setPresenceInfo(0, "", OnlineStatus.Offline);
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.removeListener(mListener);
+ }
+
instance = null;
LinphoneManager.destroy();
@@ -473,64 +580,12 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
stopForegroundCompat(NOTIF_ID);
mNM.cancel(INCALL_NOTIF_ID);
mNM.cancel(MESSAGE_NOTIF_ID);
- mWifiLock.release();
+
+ ((AlarmManager) this.getSystemService(Context.ALARM_SERVICE)).cancel(mkeepAlivePendingIntent);
+ getContentResolver().unregisterContentObserver(mObserver);
super.onDestroy();
}
- private static final LinphoneGuiListener guiListener() {
- return null;
- }
-
- public void onDisplayStatus(final String message) {
- mHandler.post(new Runnable() {
- public void run() {
- if (guiListener() != null) guiListener().onDisplayStatus(message);
- }
- });
- }
-
- public void onGlobalStateChanged(final GlobalState state, final String message) {
- if (state == GlobalState.GlobalOn) {
- sendNotification(IC_LEVEL_OFFLINE, R.string.notification_started);
-
- // Slightly delay the propagation of the state change.
- // This is to let the linphonecore finish to be created
- // in the java part.
- mHandler.postDelayed(new Runnable() {
- public void run() {
- if (guiListener() != null)
- guiListener().onGlobalStateChangedToOn(message);
- }
- }, 50);
- }
- }
-
- public void onRegistrationStateChanged(final RegistrationState state,
- final String message) {
-// if (instance == null) {
-// Log.i("Service not ready, discarding registration state change to ",state.toString());
-// return;
-// }
- if (state == RegistrationState.RegistrationOk && LinphoneManager.getLc().getDefaultProxyConfig() != null && LinphoneManager.getLc().getDefaultProxyConfig().isRegistered()) {
- sendNotification(IC_LEVEL_ORANGE, R.string.notification_registered);
- }
-
- if ((state == RegistrationState.RegistrationFailed || state == RegistrationState.RegistrationCleared) && (LinphoneManager.getLc().getDefaultProxyConfig() == null || !LinphoneManager.getLc().getDefaultProxyConfig().isRegistered())) {
- sendNotification(IC_LEVEL_OFFLINE, R.string.notification_register_failure);
- }
- if (state == RegistrationState.RegistrationNone) {
- sendNotification(IC_LEVEL_OFFLINE, R.string.notification_started);
- }
-
- mHandler.post(new Runnable() {
- public void run() {
- if (LinphoneActivity.isInstanciated()) {
- LinphoneActivity.instance().onRegistrationStateChanged(state);
- }
- }
- });
- }
-
public void setActivityToLaunchOnIncomingReceived(Class extends Activity> activity) {
incomingReceivedActivity = activity;
resetIntentLaunchedOnNotificationClick();
@@ -539,7 +594,11 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
private void resetIntentLaunchedOnNotificationClick() {
Intent notifIntent = new Intent(this, incomingReceivedActivity);
mNotifContentIntent = PendingIntent.getActivity(this, 0, notifIntent, PendingIntent.FLAG_UPDATE_CURRENT);
- Compatibility.setNotificationLatestEventInfo(mNotif, this, mNotificationTitle, "", mNotifContentIntent);
+
+ if (mNotif != null) {
+ mNotif.contentIntent = mNotifContentIntent;
+ }
+ notifyWrapper(NOTIF_ID, mNotif);
}
protected void onIncomingReceived() {
@@ -549,111 +608,18 @@ public final class LinphoneService extends Service implements LinphoneServiceLis
.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
}
- public void onCallStateChanged(final LinphoneCall call, final State state, final String message) {
- if (instance == null) {
- Log.i("Service not ready, discarding call state change to ",state.toString());
- return;
- }
-
- if (state == LinphoneCall.State.IncomingReceived) {
- onIncomingReceived();
- }
-
- if (state == State.CallUpdatedByRemote) {
- // If the correspondent proposes video while audio call
- boolean remoteVideo = call.getRemoteParams().getVideoEnabled();
- boolean localVideo = call.getCurrentParamsCopy().getVideoEnabled();
- boolean autoAcceptCameraPolicy = LinphoneManager.getInstance().isAutoAcceptCamera();
- if (remoteVideo && !localVideo && !autoAcceptCameraPolicy && !LinphoneManager.getLc().isInConference()) {
- try {
- LinphoneManager.getLc().deferCallUpdate(call);
- } catch (LinphoneCoreException e) {
- e.printStackTrace();
- }
- }
- }
-
- if (state == State.StreamsRunning) {
- // Workaround bug current call seems to be updated after state changed to streams running
- if (getResources().getBoolean(R.bool.enable_call_notification))
- refreshIncallIcon(call);
- mWifiLock.acquire();
- } else {
- if (getResources().getBoolean(R.bool.enable_call_notification))
- refreshIncallIcon(LinphoneManager.getLc().getCurrentCall());
- }
- if ((state == State.CallEnd || state == State.Error) && LinphoneManager.getLc().getCallsNb() < 1) {
- mWifiLock.release();
- }
-
- mHandler.post(new Runnable() {
- public void run() {
- if (guiListener() != null)
- guiListener().onCallStateChanged(call, state, message);
- }
- });
- }
-
-
-
- public interface LinphoneGuiListener extends NewOutgoingCallUiListener {
- void onDisplayStatus(String message);
- void onGlobalStateChangedToOn(String message);
- void onCallStateChanged(LinphoneCall call, State state, String message);
- }
-
- public void changeRingtone(String ringtone) {
- SharedPreferences.Editor editor = PreferenceManager.getDefaultSharedPreferences(this).edit();
- editor.putString(getString(R.string.pref_audio_ringtone), ringtone);
- editor.commit();
- }
-
- public void onRingerPlayerCreated(MediaPlayer mRingerPlayer) {
- String uriString = PreferenceManager.getDefaultSharedPreferences(this).getString(getString(R.string.pref_audio_ringtone),
- android.provider.Settings.System.DEFAULT_RINGTONE_URI.toString());
- try {
- if (uriString.startsWith("content://")) {
- mRingerPlayer.setDataSource(this, Uri.parse(uriString));
- } else {
- FileInputStream fis = new FileInputStream(uriString);
- mRingerPlayer.setDataSource(fis.getFD());
- fis.close();
- }
- } catch (IOException e) {
- Log.e(e, "Cannot set ringtone");
- }
- }
public void tryingNewOutgoingCallButAlreadyInCall() {
- mHandler.post(new Runnable() {
- public void run() {
- if (guiListener() != null)
- guiListener().onAlreadyInCall();
- }
- });
}
public void tryingNewOutgoingCallButCannotGetCallParameters() {
- mHandler.post(new Runnable() {
- public void run() {
- if (guiListener() != null)
- guiListener().onCannotGetCallParameters();
- }
- });
}
public void tryingNewOutgoingCallButWrongDestinationAddress() {
- mHandler.post(new Runnable() {
- public void run() {
- if (guiListener() != null)
- guiListener().onWrongDestinationAddress();
- }
- });
}
public void onCallEncryptionChanged(final LinphoneCall call, final boolean encrypted,
final String authenticationToken) {
- // IncallActivity registers itself to this event and handle it.
}
}
diff --git a/src/org/linphone/LinphoneSimpleListener.java b/src/org/linphone/LinphoneSimpleListener.java
deleted file mode 100644
index 7864a20ba..000000000
--- a/src/org/linphone/LinphoneSimpleListener.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
-LinphoneServiceListener.java
-Copyright (C) 2011 Belledonne Communications, Grenoble, France
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-package org.linphone;
-
-import org.linphone.core.LinphoneAddress;
-import org.linphone.core.LinphoneCall;
-import org.linphone.core.LinphoneCall.State;
-import org.linphone.core.LinphoneChatMessage;
-import org.linphone.core.LinphoneCore.GlobalState;
-import org.linphone.core.LinphoneCore.RegistrationState;
-
-import android.content.Context;
-import android.media.MediaPlayer;
-import android.net.ConnectivityManager;
-import android.net.NetworkInfo;
-
-public interface LinphoneSimpleListener {
-
- public static interface LinphoneServiceListener extends
- LinphoneOnGlobalStateChangedListener,
- LinphoneOnCallStateChangedListener,
- LinphoneOnCallEncryptionChangedListener
- {
- void tryingNewOutgoingCallButCannotGetCallParameters();
- void tryingNewOutgoingCallButWrongDestinationAddress();
- void tryingNewOutgoingCallButAlreadyInCall();
- void onRegistrationStateChanged(RegistrationState state, String message);
- void onRingerPlayerCreated(MediaPlayer mRingerPlayer);
- void onDisplayStatus(String message);
- }
-
-
- public static interface LinphoneOnCallEncryptionChangedListener extends LinphoneSimpleListener {
- void onCallEncryptionChanged(LinphoneCall call, boolean encrypted, String authenticationToken);
- }
-
- public static interface LinphoneOnGlobalStateChangedListener extends LinphoneSimpleListener {
- void onGlobalStateChanged(GlobalState state, String message);
- }
-
- public static interface LinphoneOnCallStateChangedListener extends LinphoneSimpleListener {
- void onCallStateChanged(LinphoneCall call, State state, String message);
- }
-
- public static interface LinphoneOnAudioChangedListener extends LinphoneSimpleListener {
- public enum AudioState {EARPIECE, SPEAKER, BLUETOOTH}
- void onAudioStateChanged(AudioState state);
- }
-
- public static interface LinphoneOnMessageReceivedListener extends LinphoneSimpleListener {
- void onMessageReceived(LinphoneAddress from, LinphoneChatMessage message, int id);
- }
-
- public static interface LinphoneOnRegistrationStateChangedListener extends LinphoneSimpleListener {
- void onRegistrationStateChanged(RegistrationState state);
- }
-
- public static interface ConnectivityChangedListener extends LinphoneSimpleListener {
- void onConnectivityChanged(Context context, NetworkInfo eventInfo, ConnectivityManager cm);
- }
-
- public static interface LinphoneOnDTMFReceivedListener extends LinphoneSimpleListener {
- void onDTMFReceived(LinphoneCall call, int dtmf);
- }
-}
diff --git a/src/org/linphone/LinphoneUtils.java b/src/org/linphone/LinphoneUtils.java
index 321285430..d98711c1e 100644
--- a/src/org/linphone/LinphoneUtils.java
+++ b/src/org/linphone/LinphoneUtils.java
@@ -21,7 +21,9 @@ package org.linphone;
import static android.view.View.GONE;
import static android.view.View.VISIBLE;
+import java.io.BufferedOutputStream;
import java.io.BufferedReader;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
@@ -31,12 +33,16 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipOutputStream;
import org.linphone.core.LinphoneAddress;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCall.State;
import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneCoreException;
import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.core.LinphoneProxyConfig;
import org.linphone.mediastream.Log;
import org.linphone.mediastream.Version;
import org.linphone.mediastream.video.capture.hwconf.Hacks;
@@ -52,6 +58,7 @@ import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.os.Build;
+import android.provider.MediaStore;
import android.telephony.TelephonyManager;
import android.util.TypedValue;
import android.view.KeyEvent;
@@ -68,25 +75,37 @@ public final class LinphoneUtils {
private LinphoneUtils(){}
- private static boolean preventVolumeBarToDisplay = false;
//private static final String sipAddressRegExp = "^(sip:)?(\\+)?[a-z0-9]+([_\\.-][a-z0-9]+)*@([a-z0-9]+([\\.-][a-z0-9]+)*)+\\.[a-z]{2,}(:[0-9]{2,5})?$";
//private static final String strictSipAddressRegExp = "^sip:(\\+)?[a-z0-9]+([_\\.-][a-z0-9]+)*@([a-z0-9]+([\\.-][a-z0-9]+)*)+\\.[a-z]{2,}$";
public static boolean isSipAddress(String numberOrAddress) {
- return LinphoneCoreFactory.instance().createLinphoneAddress(numberOrAddress) != null;
+ try {
+ LinphoneCoreFactory.instance().createLinphoneAddress(numberOrAddress);
+ return true;
+ } catch (LinphoneCoreException e) {
+ return false;
+ }
+ }
+
+ public static boolean isNumberAddress(String numberOrAddress) {
+ LinphoneProxyConfig proxy = LinphoneManager.getLc().createProxyConfig();
+ if(proxy.normalizePhoneNumber(numberOrAddress) != null){
+ return true;
+ }
+ return false;
}
public static boolean isStrictSipAddress(String numberOrAddress) {
return isSipAddress(numberOrAddress) && numberOrAddress.startsWith("sip:");
}
-
+
public static String getUsernameFromAddress(String address) {
if (address.contains("sip:"))
address = address.replace("sip:", "");
-
+
if (address.contains("@"))
address = address.split("@")[0];
-
+
return address;
}
@@ -115,24 +134,13 @@ public final class LinphoneUtils {
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
LinphoneManager.getInstance().adjustVolume(-1);
}
- return preventVolumeBarToDisplay;
+ return true;
}
- /**
- * @param contact sip uri
- * @return url/uri of the resource
- */
-// public static Uri findUriPictureOfContactAndSetDisplayName(LinphoneAddress address, ContentResolver resolver) {
-// return Compatibility.findUriPictureOfContactAndSetDisplayName(address, resolver);
-// }
-
- public static Uri findUriPictureOfContactAndSetDisplayName(LinphoneAddress address, ContentResolver resolver) {
- ContactHelper helper = new ContactHelper(address, resolver);
- helper.query();
- return helper.getUri();
- }
+
+
public static Bitmap downloadBitmap(Uri uri) {
URL url;
InputStream is = null;
@@ -151,7 +159,7 @@ public final class LinphoneUtils {
}
- public static void setImagePictureFromUri(Context c, ImageView view, Uri uri, int notFoundResource) {
+ public static void setImagePictureFromUri(Context c, ImageView view, Uri uri, Uri tUri, int notFoundResource) {
if (uri == null) {
view.setImageResource(notFoundResource);
return;
@@ -162,7 +170,17 @@ public final class LinphoneUtils {
view.setImageBitmap(bm);
} else {
if (Version.sdkAboveOrEqual(Version.API06_ECLAIR_201)) {
- view.setImageURI(uri);
+ Bitmap bm = null;
+ try {
+ bm = MediaStore.Images.Media.getBitmap(c.getContentResolver(),uri);
+ } catch (IOException e) {
+ if(tUri != null){
+ view.setImageURI(tUri);
+ }
+ }
+ if(bm != null) {
+ view.setImageBitmap(bm);
+ }
} else {
@SuppressWarnings("deprecation")
Bitmap bitmap = android.provider.Contacts.People.loadContactPhoto(c, uri, notFoundResource, null);
@@ -278,54 +296,23 @@ public final class LinphoneUtils {
state == LinphoneCall.State.Pausing;
}
- public static boolean isHightBandwidthConnection(Context context){
+ public static boolean isHighBandwidthConnection(Context context){
ConnectivityManager cm = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo info = cm.getActiveNetworkInfo();
return (info != null && info.isConnected() && isConnectionFast(info.getType(),info.getSubtype()));
}
private static boolean isConnectionFast(int type, int subType){
- if (type == ConnectivityManager.TYPE_WIFI) {
- return true;
- } else if (type == ConnectivityManager.TYPE_MOBILE) {
+ if (type == ConnectivityManager.TYPE_MOBILE) {
switch (subType) {
- case TelephonyManager.NETWORK_TYPE_1xRTT:
- return false; // ~ 50-100 kbps
- case TelephonyManager.NETWORK_TYPE_CDMA:
- return false; // ~ 14-64 kbps
- case TelephonyManager.NETWORK_TYPE_EDGE:
- return false; // ~ 50-100 kbps
- case TelephonyManager.NETWORK_TYPE_GPRS:
- return false; // ~ 100 kbps
- case TelephonyManager.NETWORK_TYPE_EVDO_0:
- return false; // ~25 kbps
- case TelephonyManager.NETWORK_TYPE_LTE:
- return true; // ~ 400-1000 kbps
- case TelephonyManager.NETWORK_TYPE_EVDO_A:
- return true; // ~ 600-1400 kbps
- case TelephonyManager.NETWORK_TYPE_HSDPA:
- return true; // ~ 2-14 Mbps
- case TelephonyManager.NETWORK_TYPE_HSPA:
- return true; // ~ 700-1700 kbps
- case TelephonyManager.NETWORK_TYPE_HSUPA:
- return true; // ~ 1-23 Mbps
- case TelephonyManager.NETWORK_TYPE_UMTS:
- return true; // ~ 400-7000 kbps
- case TelephonyManager.NETWORK_TYPE_EHRPD:
- return true; // ~ 1-2 Mbps
- case TelephonyManager.NETWORK_TYPE_EVDO_B:
- return true; // ~ 5 Mbps
- case TelephonyManager.NETWORK_TYPE_HSPAP:
- return true; // ~ 10-20 Mbps
- case TelephonyManager.NETWORK_TYPE_IDEN:
- return true; // ~ 10+ Mbps
- case TelephonyManager.NETWORK_TYPE_UNKNOWN:
- default:
- return false;
+ case TelephonyManager.NETWORK_TYPE_EDGE:
+ case TelephonyManager.NETWORK_TYPE_GPRS:
+ case TelephonyManager.NETWORK_TYPE_IDEN:
+ return false;
}
- } else {
- return false;
- }
+ }
+ //in doubt, assume connection is good.
+ return true;
}
public static void clearLogs() {
@@ -335,8 +322,29 @@ public final class LinphoneUtils {
e.printStackTrace();
}
}
-
- public static void collectLogs(String logTag, String email) {
+
+ public static boolean zipLogs(StringBuilder sb, String toZipFile){
+ boolean success = false;
+ try {
+ FileOutputStream zip = new FileOutputStream(toZipFile);
+
+ ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(zip));
+ ZipEntry entry = new ZipEntry("logs.txt");
+ out.putNextEntry(entry);
+
+ out.write(sb.toString().getBytes());
+
+ out.close();
+ success = true;
+
+ } catch (Exception e){
+ Log.e("Exception when trying to zip the logs: " + e.getMessage());
+ }
+
+ return success;
+ }
+
+ public static void collectLogs(Context context, String email) {
BufferedReader br = null;
Process p = null;
StringBuilder sb = new StringBuilder();
@@ -350,16 +358,26 @@ public final class LinphoneUtils {
sb.append(line);
sb.append("\r\n");
}
-
- Intent i = new Intent(Intent.ACTION_SEND);
- i.setType("message/rfc822");
- i.putExtra(Intent.EXTRA_EMAIL, new String[]{email});
- i.putExtra(Intent.EXTRA_SUBJECT, "Linphone Logs");
- i.putExtra(Intent.EXTRA_TEXT, sb.toString());
- try {
- LinphoneActivity.instance().startActivity(Intent.createChooser(i, "Send mail..."));
- } catch (android.content.ActivityNotFoundException ex) {
- }
+ String zipFilePath = context.getExternalFilesDir(null).getAbsolutePath() + "/logs.zip";
+ Log.i("Saving logs to " + zipFilePath);
+
+ if( zipLogs(sb, zipFilePath) ) {
+ final String appName = (context != null) ? context.getString(R.string.app_name) : "Linphone(?)";
+
+ Uri zipURI = Uri.parse("file://" + zipFilePath);
+ Intent i = new Intent(Intent.ACTION_SEND);
+ i.putExtra(Intent.EXTRA_EMAIL, new String[]{email});
+ i.putExtra(Intent.EXTRA_SUBJECT, appName + " Logs");
+ i.putExtra(Intent.EXTRA_TEXT, appName + " logs");
+ i.setType("application/zip");
+ i.putExtra(Intent.EXTRA_STREAM, zipURI);
+ try {
+ context.startActivity(Intent.createChooser(i, "Send mail..."));
+ } catch (android.content.ActivityNotFoundException ex) {
+
+ }
+ }
+
} catch (IOException e) {
e.printStackTrace();
}
diff --git a/src/org/linphone/PreferencesFragment.java b/src/org/linphone/PreferencesFragment.java
deleted file mode 100644
index d2ad9f4f9..000000000
--- a/src/org/linphone/PreferencesFragment.java
+++ /dev/null
@@ -1,531 +0,0 @@
-package org.linphone;
-/*
-PreferencesFragment.java
-Copyright (C) 2012 Belledonne Communications, Grenoble, France
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-*/
-import static org.linphone.R.string.ec_calibrating;
-import static org.linphone.R.string.pref_codec_amr_key;
-import static org.linphone.R.string.pref_codec_amrwb_key;
-import static org.linphone.R.string.pref_codec_ilbc_key;
-import static org.linphone.R.string.pref_codec_speex16_key;
-import static org.linphone.R.string.pref_echo_cancellation_key;
-import static org.linphone.R.string.pref_echo_canceller_calibration_key;
-import static org.linphone.R.string.pref_media_encryption_key;
-import static org.linphone.R.string.pref_transport_key;
-import static org.linphone.R.string.pref_video_enable_key;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.linphone.LinphoneManager.EcCalibrationListener;
-import org.linphone.compatibility.Compatibility;
-import org.linphone.core.LinphoneCore;
-import org.linphone.core.LinphoneCore.EcCalibratorStatus;
-import org.linphone.core.LinphoneCore.MediaEncryption;
-import org.linphone.core.LinphoneCoreException;
-import org.linphone.core.LinphoneProxyConfig;
-import org.linphone.mediastream.Log;
-import org.linphone.mediastream.Version;
-import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration;
-import org.linphone.mediastream.video.capture.hwconf.Hacks;
-import org.linphone.setup.SetupActivity;
-import org.linphone.ui.LedPreference;
-import org.linphone.ui.PreferencesListFragment;
-
-import android.app.Activity;
-import android.content.Context;
-import android.content.Intent;
-import android.content.SharedPreferences;
-import android.os.Bundle;
-import android.os.Handler;
-import android.preference.CheckBoxPreference;
-import android.preference.EditTextPreference;
-import android.preference.ListPreference;
-import android.preference.Preference;
-import android.preference.Preference.OnPreferenceChangeListener;
-import android.preference.Preference.OnPreferenceClickListener;
-import android.preference.PreferenceCategory;
-
-public class PreferencesFragment extends PreferencesListFragment implements EcCalibrationListener {
- private Handler mHandler = new Handler();
- private Context mContext;
- private Preference ecCalibratePref;
- private CheckBoxPreference ecPref;
- private ListPreference mencPref;
- private int nbAccounts = 1;
- private PreferenceCategory accounts;
-
- private static final int WIZARD_INTENT = 1;
-
- public PreferencesFragment() {
- super(R.xml.preferences);
- }
-
- @Override
- public void onCreate(Bundle bundle) {
- super.onCreate(bundle);
- mContext = getActivity();
-
- if (getResources().getBoolean(R.bool.hide_accounts)) {
- // Hide category
- PreferenceCategory accounts = (PreferenceCategory) findPreference(getString(R.string.pref_sipaccounts_key));
- accounts.removeAll();
- accounts.setLayoutResource(R.layout.hidden);
- }
-
- if (getResources().getBoolean(R.bool.hide_wizard) || getResources().getBoolean(R.bool.replace_wizard_with_old_interface)) {
- Preference wizard = findPreference(getString(R.string.setup_key));
- if (getResources().getBoolean(R.bool.replace_wizard_with_old_interface)) {
- createAddAccountButton();
- } else {
- wizard.setLayoutResource(R.layout.hidden);
- }
- } else {
- addWizardPreferenceButton();
- }
-
- if (getResources().getBoolean(R.bool.disable_animations)) {
- uncheckDisableAndHideCheckbox(R.string.pref_animation_enable_key);
- }
-
- if (!getResources().getBoolean(R.bool.enable_linphone_friends)) {
- PreferenceCategory friends = (PreferenceCategory) findPreference(getString(R.string.pref_linphone_friend_key));
- friends.removeAll();
- friends.setLayoutResource(R.layout.hidden);
- }
-
- EditTextPreference imageSharingServer = (EditTextPreference) findPreference(getString(R.string.pref_image_sharing_server_key));
- if (getResources().getBoolean(R.bool.disable_chat)) {
- imageSharingServer.setLayoutResource(R.layout.hidden);
- }
-
- if (!getResources().getBoolean(R.bool.enable_push_id)) {
- findPreference(getString(R.string.pref_push_notification_key)).setLayoutResource(R.layout.hidden);
- }
-
- initializeTransportPreferences();
-
- ecCalibratePref = findPreference(pref_echo_canceller_calibration_key);
- ecCalibratePref.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- public boolean onPreferenceClick(Preference preference) {
- startEcCalibration();
- return false;
- }
- });
- ecPref = (CheckBoxPreference) findPreference(pref_echo_cancellation_key);
- mencPref = (ListPreference) findPreference(pref_media_encryption_key);
-
- boolean fastCpu = Version.hasFastCpu();
- if (fastCpu) {
- detectAudioCodec(pref_codec_ilbc_key, "iLBC", 8000, 1, false);
- findPreference(pref_codec_speex16_key).setEnabled(true);
- //findPreference(pref_codec_speex32_key)).setEnabled(enableIlbc);
- }
-
- initializeMediaEncryptionPreferences();
-
- detectAudioCodec(pref_codec_amr_key,"AMR", 8000, 1, false);
- detectAudioCodec(pref_codec_amrwb_key,"AMR-WB", 16000, 1, false);
- //detectAudioCodec(R.string.pref_codec_silk8_key,"SILK",8000, 1, true);
- //detectAudioCodec(R.string.pref_codec_silk12_key,"SILK",12000, 1, true);
- detectAudioCodec(R.string.pref_codec_silk16_key,"SILK",16000, 1, true);
- //detectAudioCodec(R.string.pref_codec_silk24_key,"SILK",24000, 1, true);
- detectAudioCodec(R.string.pref_codec_g729_key,"G729",8000, 1, true);
-
- // No video
- if (!Version.isVideoCapable()) {
- uncheckAndDisableCheckbox(pref_video_enable_key);
- } else {
- if (!AndroidCameraConfiguration.hasFrontCamera()) {
- uncheckDisableAndHideCheckbox(R.string.pref_video_use_front_camera_key);
- }
- }
-
- if (prefs().getBoolean(LinphoneActivity.PREF_FIRST_LAUNCH,true)) {
- doOnFirstLaunch();
- }
- if (Hacks.hasBuiltInEchoCanceller()) {
- uncheckDisableAndHideCheckbox(R.string.pref_echo_cancellation_key);
- findPreference(R.string.pref_echo_canceller_calibration_key).setLayoutResource(R.layout.hidden);
- }
-
- if (getResources().getBoolean(R.bool.disable_all_patented_codecs_for_markets)) {
- Preference prefH264 = findPreference(R.string.pref_video_codec_h264_key);
- prefH264.setEnabled(false);
- prefH264.setSummary(R.string.pref_video_codec_h264_unavailable);
-
- Preference prefMPEG4 = findPreference(R.string.pref_video_codec_mpeg4_key);
- prefMPEG4.setEnabled(false);
- prefMPEG4.setSummary(R.string.pref_video_codec_mpeg4_unavailable);
- } else {
- detectVideoCodec(R.string.pref_video_codec_h264_key, "H264");
- if (!Version.hasNeon())
- {
- // Android without neon doesn't support H264
- Log.w("No NEON available, disabling H264");
- findPreference(R.string.pref_video_codec_h264_key).setEnabled(false);
- findPreference(R.string.pref_video_codec_h264_key).setDefaultValue(false);
- }
- }
-
- if (Hacks.needSoftvolume()) {
- Log.w("Using Audio Hack");
- checkAndDisableCheckbox(R.string.pref_audio_hacks_use_galaxys_hack_key);
- }
-
- if (!LinphoneManager.getLc().isTunnelAvailable()) {
- hidePreferenceCategory(R.string.pref_tunnel_key);
- }
-
- if (getResources().getBoolean(R.bool.hide_camera_settings)) {
- PreferenceCategory videoSettings = (PreferenceCategory) findPreference(getString(R.string.pref_video_key));
- videoSettings.removeAll();
- videoSettings.setLayoutResource(R.layout.hidden);
-
- Preference enableVideo = findPreference(R.string.pref_video_enable_key);
- enableVideo.setLayoutResource(R.layout.hidden);
- }
-
- if (getResources().getBoolean(R.bool.display_about_in_settings)) {
- findPreference(getString(R.string.menu_about_key)).setOnPreferenceClickListener(new OnPreferenceClickListener() {
- @Override
- public boolean onPreferenceClick(Preference preference) {
- if (LinphoneActivity.isInstanciated()) {
- LinphoneActivity.instance().displayAbout();
- return true;
- }
- return false;
- }
- });
- } else {
- findPreference(getString(R.string.menu_about_key)).setLayoutResource(R.layout.hidden);
- }
-
- final CheckBoxPreference useRandomPort = (CheckBoxPreference) findPreference(R.string.pref_transport_use_random_ports_key);
- final Preference sipPort = findPreference(R.string.pref_sip_port_key);
- sipPort.setEnabled(!useRandomPort.isChecked());
- useRandomPort.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- boolean isChecked = (Boolean) newValue;
- sipPort.setEnabled(!isChecked);
- return true;
- }
- });
-
- CheckBoxPreference wifiOnly = (CheckBoxPreference) findPreference(R.string.pref_wifi_only_key);
- wifiOnly.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
- @Override
- public boolean onPreferenceChange(Preference preference, Object newValue) {
- LinphoneManager.getInstance().updateNetworkReachability();
- return true;
- }
- });
-
- if (getResources().getBoolean(R.bool.disable_every_log)) {
- uncheckDisableAndHideCheckbox(R.string.pref_debug_key);
- }
- }
-
- private void createAddAccountButton() {
- Preference addAccount = findPreference(getString(R.string.setup_key));
- addAccount.setTitle(getString(R.string.pref_add_account));
- addAccount.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- public boolean onPreferenceClick(Preference preference) {
- SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
- nbAccounts = prefs.getInt(getString(R.string.pref_extra_accounts), 0);
- prefs.edit().putInt(getString(R.string.pref_extra_accounts), nbAccounts+1).commit();
-
- addExtraAccountPreferencesButton(accounts, nbAccounts, true);
- LinphoneActivity.instance().displayAccountSettings(nbAccounts);
- nbAccounts++;
- return true;
- }
- });
- }
-
- private void hidePreferenceCategory(int key) {
- PreferenceCategory p = (PreferenceCategory) findPreference(key);
- p.removeAll();
- p.setLayoutResource(R.layout.hidden);
- }
-
- private void doOnFirstLaunch() {
- prefs().edit().putBoolean(LinphoneActivity.PREF_FIRST_LAUNCH, false).commit();
- }
-
- private synchronized void startEcCalibration() {
- try {
- LinphoneManager.getInstance().startEcCalibration(this);
-
- ecCalibratePref.setSummary(ec_calibrating);
- ecCalibratePref.getEditor().putBoolean(getString(pref_echo_canceller_calibration_key), false).commit();
- } catch (LinphoneCoreException e) {
- Log.w(e, "Cannot calibrate EC");
- }
- }
-
- public void onEcCalibrationStatus(final EcCalibratorStatus status, final int delayMs) {
- mHandler.post(new Runnable() {
- public void run() {
- if (status == EcCalibratorStatus.DoneNoEcho) {
- ecCalibratePref.setSummary(R.string.no_echo);
- ecPref.setChecked(false);
- } else if (status == EcCalibratorStatus.Done) {
- ecCalibratePref.setSummary(String.format(getString(R.string.ec_calibrated), delayMs));
- ecPref.setChecked(true);
- } else if (status == EcCalibratorStatus.Failed) {
- ecCalibratePref.setSummary(R.string.failed);
- ecPref.setChecked(true);
- }
- }
- });
- }
-
- private void uncheckDisableAndHideCheckbox(int key) {
- manageCheckbox(key, false, false, true);
- }
-
- private void uncheckAndDisableCheckbox(int key) {
- manageCheckbox(key, false, false, false);
- }
-
- private void checkAndDisableCheckbox(int key) {
- manageCheckbox(key, true, false, false);
- }
-
- private void manageCheckbox(int key, boolean value, boolean enabled, boolean hidden) {
- Preference box = findPreference(key);
- box.setEnabled(enabled);
- Compatibility.setPreferenceChecked(box, value);
- writeBoolean(key, value);
- if (hidden) box.setLayoutResource(R.layout.hidden);
- }
-
- private void writeBoolean(int key, boolean value) {
- prefs().edit().putBoolean(getString(key), value).commit();
- }
-
- private SharedPreferences prefs() {
- return getPreferenceManager().getSharedPreferences();
- }
-
- private void detectAudioCodec(int id, String mime, int rate, int channels, boolean hide) {
- Log.w("Payload type for codec " + mime + " = " + LinphoneManager.getLc().findPayloadType(mime, rate, channels));
- boolean enable = LinphoneService.isReady() && LinphoneManager.getLc().findPayloadType(mime, rate, channels)!=null;
- Preference cb = findPreference(id);
- cb.setEnabled(enable);
- if (hide && !enable) {
- cb.setLayoutResource(R.layout.hidden);
- }
- }
-
- private void detectVideoCodec(int id, String mime) {
- findPreference(id).setEnabled(LinphoneManager.getInstance().detectVideoCodec(mime));
- }
-
- private void createDynamicAccountsPreferences() {
- accounts = (PreferenceCategory) findPreference(getString(R.string.pref_sipaccounts_key));
- accounts.removeAll();
-
- // Get already configured extra accounts
- SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
- nbAccounts = prefs.getInt(getString(R.string.pref_extra_accounts), 0);
- for (int i = 0; i < nbAccounts; i++) {
- // For each, add menus to configure it
- addExtraAccountPreferencesButton(accounts, i, false);
- }
- }
-
- public int getNbAccountsExtra() {
- return nbAccounts;
- }
-
- private void addExtraAccountPreferencesButton(PreferenceCategory parent, final int n, boolean isNewAccount) {
- SharedPreferences prefs = getPreferenceManager().getSharedPreferences();
- if (isNewAccount) {
- SharedPreferences.Editor editor = prefs.edit();
- editor.putInt(getString(R.string.pref_extra_accounts), n+1);
- editor.commit();
- }
-
- final LedPreference me = new LedPreference(mContext);
- String keyUsername = getString(R.string.pref_username_key);
- String keyDomain = getString(R.string.pref_domain_key);
- if (n > 0) {
- keyUsername += n + "";
- keyDomain += n + "";
- }
-
- String username = prefs.getString(keyUsername, "");
- String domain = prefs.getString(keyDomain, "");
- if (username == null) {
- me.setTitle(getString(R.string.pref_sipaccount));
- } else {
- me.setTitle(username + "@" + domain);
- }
-
- me.setOnPreferenceClickListener(new OnPreferenceClickListener()
- {
- public boolean onPreferenceClick(Preference preference) {
- LinphoneActivity.instance().displayAccountSettings(n);
- return false;
- }
- });
-
- updateAccountLed(me, username, domain);
- parent.addPreference(me);
- }
-
- private void updateAccountLed(final LedPreference me, final String username, final String domain) {
- if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) {
- for (LinphoneProxyConfig lpc : LinphoneManager.getLc().getProxyConfigList()) {
- if (lpc.getIdentity().contains(username) && lpc.getIdentity().contains(domain)) {
- if (lpc.getState() == LinphoneCore.RegistrationState.RegistrationOk) {
- me.setLed(R.drawable.led_connected);
- } else if (lpc.getState() == LinphoneCore.RegistrationState.RegistrationFailed) {
- me.setLed(R.drawable.led_error);
- } else if (lpc.getState() == LinphoneCore.RegistrationState.RegistrationProgress) {
- me.setLed(R.drawable.led_inprogress);
- mHandler.postDelayed(new Runnable() {
- @Override
- public void run() {
- updateAccountLed(me, username, domain);
- }
- }, 1500);
- } else {
- me.setLed(R.drawable.led_disconnected);
- }
- break;
- }
- }
- }
- }
-
- private void addWizardPreferenceButton() {
- Preference wizard = findPreference(getString(R.string.setup_key));
- wizard.setOnPreferenceClickListener(new OnPreferenceClickListener() {
- public boolean onPreferenceClick(Preference preference) {
- Intent intent = new Intent(mContext, SetupActivity.class);
- startActivityForResult(intent, WIZARD_INTENT);
- return true;
- }
- });
- }
-
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if (requestCode == WIZARD_INTENT && resultCode == Activity.RESULT_OK) {
- if (LinphoneActivity.isInstanciated()) {
- LinphoneActivity.instance().goToDialer();
- }
- }
- }
-
- private void initializeMediaEncryptionPreferences() {
- LinphoneCore lc = null;
- try {
- lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
- } catch (Exception e) {}
-
- List mencEntries=new ArrayList();
- List mencEntryValues=new ArrayList();
- mencEntries.add(getString(R.string.media_encryption_none));
- mencEntryValues.add(getString(R.string.pref_media_encryption_key_none));
-
- if (lc == null || getResources().getBoolean(R.bool.disable_all_security_features_for_markets)) {
- CharSequence[] contents=new CharSequence[mencEntries.size()];
- mencEntries.toArray(contents);
- mencPref.setEntries(contents);
- contents=new CharSequence[mencEntryValues.size()];
- mencEntryValues.toArray(contents);
- mencPref.setEntryValues(contents);
- mencPref.setDefaultValue(getString(R.string.media_encryption_none));
- return;
- }
-
- boolean hasZrtp = lc.mediaEncryptionSupported(MediaEncryption.ZRTP);
- boolean hasSrtp = lc.mediaEncryptionSupported(MediaEncryption.SRTP);
- if (!hasSrtp && !hasZrtp){
- mencPref.setEnabled(false);
- }else{
- if (hasSrtp){
- mencEntries.add(getString(R.string.media_encryption_srtp));
- mencEntryValues.add(getString(R.string.pref_media_encryption_key_srtp));
- }
- if (hasZrtp){
- mencEntries.add(getString(R.string.media_encryption_zrtp));
- mencEntryValues.add(getString(R.string.pref_media_encryption_key_zrtp));
- }
- CharSequence[] contents=new CharSequence[mencEntries.size()];
- mencEntries.toArray(contents);
- mencPref.setEntries(contents);
- contents=new CharSequence[mencEntryValues.size()];
- mencEntryValues.toArray(contents);
- mencPref.setEntryValues(contents);
- mencPref.setDefaultValue(getString(R.string.media_encryption_none));
- //mencPref.setValueIndex(mencPref.findIndexOfValue(getString(R.string.media_encryption_none)));
- }
- }
-
- private void initializeTransportPreferences() {
- List mencEntries=new ArrayList();
- List mencEntryValues=new ArrayList();
- mencEntries.add(getString(R.string.pref_transport_udp));
- mencEntryValues.add(getString(R.string.pref_transport_udp_key));
- mencEntries.add(getString(R.string.pref_transport_tcp));
- mencEntryValues.add(getString(R.string.pref_transport_tcp_key));
-
- if (!getResources().getBoolean(R.bool.disable_all_security_features_for_markets)) {
- mencEntries.add(getString(R.string.pref_transport_tls));
- mencEntryValues.add(getString(R.string.pref_transport_tls_key));
- }
-
- ListPreference transport = (ListPreference) findPreference(pref_transport_key);
-
- CharSequence[] contents=new CharSequence[mencEntries.size()];
- mencEntries.toArray(contents);
- transport.setEntries(contents);
- contents=new CharSequence[mencEntryValues.size()];
- mencEntryValues.toArray(contents);
- transport.setEntryValues(contents);
- }
-
- private Preference findPreference(int key) {
- return getPreferenceManager().findPreference(getString(key));
- }
-
- @Override
- public void onPause() {
- super.onPause();
-
- if (LinphoneActivity.isInstanciated()) {
- LinphoneActivity.instance().applyConfigChangesIfNeeded();
- }
- }
-
- @Override
- public void onResume() {
- super.onResume();
-
- if (LinphoneActivity.isInstanciated()) {
- LinphoneActivity.instance().selectMenu(FragmentsAvailable.SETTINGS);
- }
-
- createDynamicAccountsPreferences();
- }
-}
diff --git a/src/org/linphone/PreferencesMigrator.java b/src/org/linphone/PreferencesMigrator.java
new file mode 100644
index 000000000..f6cae93c4
--- /dev/null
+++ b/src/org/linphone/PreferencesMigrator.java
@@ -0,0 +1,191 @@
+package org.linphone;
+
+/*
+PreferencesMigrator.java
+Copyright (C) 2013 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import org.linphone.LinphonePreferences.AccountBuilder;
+import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneCoreException;
+
+import android.content.Context;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.content.res.Resources;
+
+import android.preference.PreferenceManager;
+
+/**
+ * @author Sylvain Berfini
+ */
+public class PreferencesMigrator {
+ private LinphonePreferences mNewPrefs;
+ private SharedPreferences mOldPrefs;
+ private Resources mResources;
+
+ public PreferencesMigrator(Context context) {
+ mNewPrefs = LinphonePreferences.instance();
+ mResources = context.getResources();
+ mOldPrefs = PreferenceManager.getDefaultSharedPreferences(context);
+ }
+
+ public boolean isEchoMigratioNeeded() {
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc == null) {
+ return false;
+ }
+
+ if (mNewPrefs.isEchoConfigurationUpdated()) {
+ return false;
+ }
+
+ return (!lc.needsEchoCalibration() && mNewPrefs.isEchoCancellationEnabled());
+ }
+
+ public void doEchoMigration() {
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc == null) {
+ return;
+ }
+
+ if (!lc.needsEchoCalibration()) {
+ mNewPrefs.setEchoCancellation(false);
+ }
+ }
+
+ public boolean isMigrationNeeded() {
+ int accountNumber = mOldPrefs.getInt(getString(R.string.pref_extra_accounts), -1);
+ return accountNumber != -1;
+ }
+
+ public void doMigration() {
+ mNewPrefs.firstLaunchSuccessful(); // If migration is needed, it is safe to assume Linphone has already been started once.
+ mNewPrefs.removePreviousVersionAuthInfoRemoval(); // Remove flag in linphonerc asking core not to store auths infos
+
+ mNewPrefs.setFrontCamAsDefault(getPrefBoolean(R.string.pref_video_use_front_camera_key, true));
+ mNewPrefs.setWifiOnlyEnabled(getPrefBoolean(R.string.pref_wifi_only_key, false));
+ mNewPrefs.useRandomPort(getPrefBoolean(R.string.pref_transport_use_random_ports_key, true), false);
+ mNewPrefs.setPushNotificationEnabled(getPrefBoolean(R.string.pref_push_notification_key, false));
+ mNewPrefs.setPushNotificationRegistrationID(getPrefString(R.string.push_reg_id_key, null));
+ mNewPrefs.setDebugEnabled(getPrefBoolean(R.string.pref_debug_key, false));
+ mNewPrefs.setBackgroundModeEnabled(getPrefBoolean(R.string.pref_background_mode_key, true));
+ mNewPrefs.setAnimationsEnabled(getPrefBoolean(R.string.pref_animation_enable_key, false));
+ mNewPrefs.setAutoStart(getPrefBoolean(R.string.pref_autostart_key, false));
+ mNewPrefs.setSharingPictureServerUrl(getPrefString(R.string.pref_image_sharing_server_key, null));
+ mNewPrefs.setRemoteProvisioningUrl(getPrefString(R.string.pref_remote_provisioning_key, null));
+
+ doAccountsMigration();
+ deleteAllOldPreferences();
+ }
+
+ public void migrateRemoteProvisioningUriIfNeeded() {
+ String oldUri = mNewPrefs.getConfig().getString("app", "remote_provisioning", null);
+ String currentUri = mNewPrefs.getRemoteProvisioningUrl();
+ if (oldUri != null && oldUri.length() > 0 && currentUri == null) {
+ mNewPrefs.setRemoteProvisioningUrl(oldUri);
+ mNewPrefs.getConfig().setString("app", "remote_provisioning", null);
+ mNewPrefs.getConfig().sync();
+ }
+ }
+
+ public void migrateSharingServerUrlIfNeeded() {
+ String currentUrl = mNewPrefs.getConfig().getString("app", "sharing_server", null);
+ if (currentUrl == null || currentUrl.equals("https://www.linphone.org:444/upload.php")) {
+ mNewPrefs.setSharingPictureServerUrl("https://www.linphone.org:444/lft.php");
+ mNewPrefs.getConfig().sync();
+ }
+ }
+
+ private void doAccountsMigration() {
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ lc.clearAuthInfos();
+ lc.clearProxyConfigs();
+
+ for (int i = 0; i < mOldPrefs.getInt(getString(R.string.pref_extra_accounts), 1); i++) {
+ doAccountMigration(i, i == getPrefInt(R.string.pref_default_account_key, 0));
+ }
+ }
+
+ private void doAccountMigration(int index, boolean isDefaultAccount) {
+ String key = index == 0 ? "" : String.valueOf(index);
+
+ String username = getPrefString(getString(R.string.pref_username_key) + key, null);
+ String userid = getPrefString(getString(R.string.pref_auth_userid_key) + key, null);
+ String password = getPrefString(getString(R.string.pref_passwd_key) + key, null);
+ String domain = getPrefString(getString(R.string.pref_domain_key) + key, null);
+ if (username != null && username.length() > 0 && password != null) {
+ String proxy = getPrefString(getString(R.string.pref_proxy_key) + key, null);
+ String expire = getPrefString(R.string.pref_expire_key, null);
+
+ AccountBuilder builder = new AccountBuilder(LinphoneManager.getLc())
+ .setUsername(username)
+ .setUserId(userid)
+ .setDomain(domain)
+ .setPassword(password)
+ .setProxy(proxy)
+ .setExpires(expire);
+
+ if (getPrefBoolean(getString(R.string.pref_enable_outbound_proxy_key) + key, false)) {
+ builder.setOutboundProxyEnabled(true);
+ }
+ if (mResources.getBoolean(R.bool.enable_push_id)) {
+ String regId = mNewPrefs.getPushNotificationRegistrationID();
+ String appId = getString(R.string.push_sender_id);
+ if (regId != null && mNewPrefs.isPushNotificationEnabled()) {
+ String contactInfos = "app-id=" + appId + ";pn-type=google;pn-tok=" + regId;
+ builder.setContactParameters(contactInfos);
+ }
+ }
+
+ try {
+ builder.saveNewAccount();
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+
+ if (isDefaultAccount) {
+ mNewPrefs.setDefaultAccount(index);
+ }
+ }
+ }
+
+ private void deleteAllOldPreferences() {
+ Editor editor = mOldPrefs.edit();
+ editor.clear();
+ editor.commit();
+ }
+
+ private String getString(int key) {
+ return mResources.getString(key);
+ }
+ private boolean getPrefBoolean(int key, boolean defaultValue) {
+ return mOldPrefs.getBoolean(mResources.getString(key), defaultValue);
+ }
+ private boolean getPrefBoolean(String key, boolean defaultValue) {
+ return mOldPrefs.getBoolean(key, defaultValue);
+ }
+ private String getPrefString(int key, String defaultValue) {
+ return mOldPrefs.getString(mResources.getString(key), defaultValue);
+ }
+ private int getPrefInt(int key, int defaultValue) {
+ return mOldPrefs.getInt(mResources.getString(key), defaultValue);
+ }
+ private String getPrefString(String key, String defaultValue) {
+ return mOldPrefs.getString(key, defaultValue);
+ }
+}
diff --git a/src/org/linphone/RemoteProvisioning.java b/src/org/linphone/RemoteProvisioning.java
deleted file mode 100644
index e654e391c..000000000
--- a/src/org/linphone/RemoteProvisioning.java
+++ /dev/null
@@ -1,123 +0,0 @@
-package org.linphone;
-
-import java.io.BufferedInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.MalformedURLException;
-import java.net.URL;
-import java.net.URLConnection;
-
-import org.linphone.core.LinphoneCoreFactory;
-import org.linphone.core.LpConfig;
-import org.linphone.mediastream.Log;
-import org.linphone.tools.Xml2Lpc;
-
-
-
-public class RemoteProvisioning {
- static private class RemoteProvisioningThread extends Thread {
- String mRPAddress;
- String mSchema;
- String mLocalLP;
- boolean value;
-
- public RemoteProvisioningThread(final String RPAddress, final String LocalLP, final String schema) {
- this.mRPAddress = RPAddress;
- this.mLocalLP = LocalLP;
- this.mSchema = schema;
- }
-
- public void run() {
- try {
- value = false;
- Log.i("Download remote provisioning file from " + mRPAddress);
- URL url = new URL(mRPAddress);
- URLConnection ucon = url.openConnection();
- InputStream is = ucon.getInputStream();
- BufferedInputStream bis = new BufferedInputStream(is);
- byte[] contents = new byte[1024];
-
- int bytesRead = 0;
- ByteArrayOutputStream fileContents = new ByteArrayOutputStream();
- while( (bytesRead = bis.read(contents)) != -1) {
- fileContents.write(contents, 0, bytesRead);
- }
-
- String strFileContents = fileContents.toString();
- Log.i("Download Success");
- Log.i(strFileContents);
-
- // Initialize converter
- LpConfig lp = LinphoneCoreFactory.instance().createLpConfig(mLocalLP);
- Xml2Lpc x2l = new Xml2Lpc();
- if(x2l.setXmlString(strFileContents) != 0) {
- Log.e("Error during remote provisioning file parsing");
- return;
- }
-
- // Check if needed
- if(mSchema != null) {
- if(x2l.setXsdFile(mSchema) != 0) {
- Log.e("Error during schema file parsing");
- }
- if(x2l.validate() != 0) {
- Log.e("Can't validate the schema of remote provisioning file");
- return;
- }
- }
-
- // Convert
- if(x2l.convert(lp) != 0) {
- Log.e("Can't convert remote provisioning file to LinphoneConfig");
- return;
- } else {
- lp.sync();
- }
- value = true;
- Log.i("Remote provisioning ok");
- } catch (MalformedURLException e) {
- Log.e("Invalid remote provisioning url: " + e.getLocalizedMessage());
- } catch (IOException e) {
- Log.e(e);
- } finally {
- synchronized(this) {
- this.notify();
- }
- }
- }
- };
-
- static boolean download(String address, String lpfile, boolean check) {
- try {
- String schema = null;
- if(check) {
- schema = LinphoneManager.getInstance().getLPConfigXsdPath();
- }
- RemoteProvisioningThread thread = new RemoteProvisioningThread(address, lpfile, schema);
- synchronized(thread) {
- thread.start();
- thread.wait();
- }
- return thread.value;
- } catch (InterruptedException e) {
- Log.e(e);
- }
- return false;
- }
-
- static boolean download(String address, String lpfile) {
- return download(address, lpfile, true);
- }
-
- static boolean isAvailable() {
- if(Xml2Lpc.isAvailable()) {
- Log.i("RemoteProvisioning is available");
- return true;
- } else {
- Log.i("RemoteProvisioning is NOT available");
- return false;
- }
- }
-
-}
diff --git a/src/org/linphone/SettingsFragment.java b/src/org/linphone/SettingsFragment.java
new file mode 100644
index 000000000..0c93276ff
--- /dev/null
+++ b/src/org/linphone/SettingsFragment.java
@@ -0,0 +1,1067 @@
+package org.linphone;
+
+/*
+SettingsFragment.java
+Copyright (C) 2013 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.linphone.core.LinphoneAddress;
+import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneCore.AdaptiveRateAlgorithm;
+import org.linphone.core.LinphoneCore.EcCalibratorStatus;
+import org.linphone.core.LinphoneCore.MediaEncryption;
+import org.linphone.core.LinphoneCoreException;
+import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.core.LinphoneCoreListenerBase;
+import org.linphone.core.LinphoneProxyConfig;
+import org.linphone.core.PayloadType;
+import org.linphone.mediastream.Log;
+import org.linphone.mediastream.Version;
+import org.linphone.mediastream.video.capture.hwconf.AndroidCameraConfiguration;
+import org.linphone.setup.SetupActivity;
+import org.linphone.ui.LedPreference;
+import org.linphone.ui.PreferencesListFragment;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.os.Handler;
+import android.preference.CheckBoxPreference;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.Preference.OnPreferenceClickListener;
+import android.preference.PreferenceCategory;
+import android.preference.PreferenceScreen;
+import android.widget.EditText;
+
+/**
+ * @author Sylvain Berfini
+ */
+public class SettingsFragment extends PreferencesListFragment {
+ private static final int WIZARD_INTENT = 1;
+ private LinphonePreferences mPrefs;
+ private Handler mHandler = new Handler();
+ private LinphoneCoreListenerBase mListener;
+
+ public SettingsFragment() {
+ super(R.xml.preferences);
+ mPrefs = LinphonePreferences.instance();
+ }
+
+ @Override
+ public void onCreate(Bundle bundle) {
+ super.onCreate(bundle);
+
+ // Init the settings page interface
+ initSettings();
+ setListeners();
+ hideSettings();
+
+ mListener = new LinphoneCoreListenerBase(){
+ @Override
+ public void ecCalibrationStatus(LinphoneCore lc, final EcCalibratorStatus status, final int delayMs, Object data) {
+ LinphoneManager.getInstance().routeAudioToReceiver();
+
+ CheckBoxPreference echoCancellation = (CheckBoxPreference) findPreference(getString(R.string.pref_echo_cancellation_key));
+ Preference echoCancellerCalibration = findPreference(getString(R.string.pref_echo_canceller_calibration_key));
+
+ if (status == EcCalibratorStatus.DoneNoEcho) {
+ echoCancellerCalibration.setSummary(R.string.no_echo);
+ echoCancellation.setChecked(false);
+ LinphonePreferences.instance().setEchoCancellation(false);
+ } else if (status == EcCalibratorStatus.Done) {
+ echoCancellerCalibration.setSummary(String.format(getString(R.string.ec_calibrated), delayMs));
+ echoCancellation.setChecked(true);
+ LinphonePreferences.instance().setEchoCancellation(true);
+ } else if (status == EcCalibratorStatus.Failed) {
+ echoCancellerCalibration.setSummary(R.string.failed);
+ echoCancellation.setChecked(true);
+ LinphonePreferences.instance().setEchoCancellation(true);
+ }
+ }
+ };
+ }
+
+ // Inits the values or the listener on some settings
+ private void initSettings() {
+ //Init accounts on Resume instead of on Create to update the account list when coming back from wizard
+
+ initTunnelSettings();
+ initAudioSettings();
+ initVideoSettings();
+ initCallSettings();
+ initNetworkSettings();
+ initAdvancedSettings();
+
+ // Add action on About button
+ findPreference(getString(R.string.menu_about_key)).setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ if (LinphoneActivity.isInstanciated()) {
+ LinphoneActivity.instance().displayAbout();
+ return true;
+ }
+ return false;
+ }
+ });
+ findPreference(getString(R.string.setup_key)).setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ Intent intent = new Intent(LinphoneService.instance(), SetupActivity.class);
+ startActivityForResult(intent, WIZARD_INTENT);
+ return true;
+ }
+ });
+ findPreference(getString(R.string.pref_add_account_key)).setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ int nbAccounts = mPrefs.getAccountCount();
+ LinphoneActivity.instance().displayAccountSettings(nbAccounts);
+ return true;
+ }
+ });
+ }
+
+ // Sets listener for each preference to update the matching value in linphonecore
+ private void setListeners() {
+ setTunnelPreferencesListener();
+ setAudioPreferencesListener();
+ setVideoPreferencesListener();
+ setCallPreferencesListener();
+ setNetworkPreferencesListener();
+ setAdvancedPreferencesListener();
+ }
+
+ // Read the values set in resources and hides the settings accordingly
+ private void hideSettings() {
+ if (!getResources().getBoolean(R.bool.display_about_in_settings)) {
+ hidePreference(R.string.menu_about_key);
+ }
+
+ if (getResources().getBoolean(R.bool.hide_accounts)) {
+ emptyAndHidePreference(R.string.pref_sipaccounts_key);
+ }
+
+ if (getResources().getBoolean(R.bool.hide_wizard)){
+ hidePreference(R.string.setup_key);
+ }
+
+ if(!getResources().getBoolean(R.bool.replace_wizard_with_old_interface)){
+ hidePreference(R.string.pref_add_account_key);
+ }
+
+ if (getResources().getBoolean(R.bool.disable_animations)) {
+ uncheckAndHidePreference(R.string.pref_animation_enable_key);
+ }
+
+ if (!getResources().getBoolean(R.bool.enable_linphone_friends)) {
+ emptyAndHidePreference(R.string.pref_linphone_friend_key);
+ }
+
+ if (getResources().getBoolean(R.bool.disable_chat)) {
+ findPreference(getString(R.string.pref_image_sharing_server_key)).setLayoutResource(R.layout.hidden);
+ }
+
+ if (!getResources().getBoolean(R.bool.enable_push_id)) {
+ hidePreference(R.string.pref_push_notification_key);
+ }
+
+ if (!Version.isVideoCapable() || !LinphoneManager.getLcIfManagerNotDestroyedOrNull().isVideoSupported()) {
+ uncheckAndHidePreference(R.string.pref_video_enable_key);
+ } else {
+ if (!AndroidCameraConfiguration.hasFrontCamera()) {
+ uncheckAndHidePreference(R.string.pref_video_use_front_camera_key);
+ }
+ }
+
+ if (!LinphoneManager.getLc().isTunnelAvailable()) {
+ emptyAndHidePreference(R.string.pref_tunnel_key);
+ }
+
+ if (getResources().getBoolean(R.bool.hide_camera_settings)) {
+ emptyAndHidePreference(R.string.pref_video_key);
+ hidePreference(R.string.pref_video_enable_key);
+ }
+
+ if (getResources().getBoolean(R.bool.disable_every_log)) {
+ uncheckAndHidePreference(R.string.pref_debug_key);
+ }
+
+ if (!LinphoneManager.getLc().upnpAvailable()) {
+ uncheckAndHidePreference(R.string.pref_upnp_enable_key);
+ }
+ }
+
+ private void uncheckAndHidePreference(int preferenceKey) {
+ Preference preference = findPreference(getString(preferenceKey));
+ if (!(preference instanceof CheckBoxPreference))
+ return;
+
+ CheckBoxPreference checkBoxPreference = (CheckBoxPreference) preference;
+ checkBoxPreference.setChecked(false);
+ hidePreference(checkBoxPreference);
+ }
+
+ private void emptyAndHidePreference(int preferenceKey) {
+ Preference preference = findPreference(getString(preferenceKey));
+ if (preference instanceof PreferenceCategory)
+ emptyAndHidePreferenceCategory(preferenceKey);
+ else if (preference instanceof PreferenceScreen)
+ emptyAndHidePreferenceScreen(preferenceKey);
+ }
+
+ private void emptyAndHidePreferenceCategory(int preferenceKey) {
+ Preference preference = findPreference(getString(preferenceKey));
+ if (!(preference instanceof PreferenceCategory))
+ return;
+
+ PreferenceCategory preferenceCategory = (PreferenceCategory) preference;
+ preferenceCategory.removeAll();
+ hidePreference(preferenceCategory);
+ }
+
+ private void emptyAndHidePreferenceScreen(int preferenceKey) {
+ Preference preference = findPreference(getString(preferenceKey));
+ if (!(preference instanceof PreferenceScreen))
+ return;
+
+ PreferenceScreen preferenceScreen = (PreferenceScreen) preference;
+ preferenceScreen.removeAll();
+ hidePreference(preferenceScreen);
+ }
+
+ private void hidePreference(int preferenceKey) {
+ hidePreference(findPreference(getString(preferenceKey)));
+ }
+
+ private void hidePreference(Preference preference) {
+ preference.setLayoutResource(R.layout.hidden);
+ }
+
+ private void setPreferenceDefaultValueAndSummary(int pref, String value) {
+ if(value != null) {
+ EditTextPreference etPref = (EditTextPreference) findPreference(getString(pref));
+ etPref.setText(value);
+ etPref.setSummary(value);
+ }
+ }
+
+ private void initTunnelSettings() {
+ setPreferenceDefaultValueAndSummary(R.string.pref_tunnel_host_key, mPrefs.getTunnelHost());
+ setPreferenceDefaultValueAndSummary(R.string.pref_tunnel_port_key, String.valueOf(mPrefs.getTunnelPort()));
+ ListPreference tunnelModePref = (ListPreference) findPreference(getString(R.string.pref_tunnel_mode_key));
+ String tunnelMode = mPrefs.getTunnelMode();
+ tunnelModePref.setSummary(tunnelMode);
+ tunnelModePref.setValue(tunnelMode);
+ }
+
+ private void setTunnelPreferencesListener() {
+ findPreference(getString(R.string.pref_tunnel_host_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String host = newValue.toString();
+ mPrefs.setTunnelHost(host);
+ preference.setSummary(host);
+ return true;
+ }
+ });
+ findPreference(getString(R.string.pref_tunnel_port_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ try {
+ int port = Integer.parseInt(newValue.toString());
+ mPrefs.setTunnelPort(port);
+ preference.setSummary(String.valueOf(port));
+ return true;
+ } catch (NumberFormatException nfe) {
+ return false;
+ }
+ }
+ });
+ findPreference(getString(R.string.pref_tunnel_mode_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String mode = newValue.toString();
+ mPrefs.setTunnelMode(mode);
+ preference.setSummary(mode);
+ return true;
+ }
+ });
+ }
+
+ private void initAccounts() {
+ PreferenceCategory accounts = (PreferenceCategory) findPreference(getString(R.string.pref_sipaccounts_key));
+ accounts.removeAll();
+
+ // Get already configured extra accounts
+ int defaultAccountID = mPrefs.getDefaultAccountIndex();
+ int nbAccounts = mPrefs.getAccountCount();
+ for (int i = 0; i < nbAccounts; i++) {
+ final int accountId = i;
+ // For each, add menus to configure it
+ String username = mPrefs.getAccountUsername(accountId);
+ String domain = mPrefs.getAccountDomain(accountId);
+ LedPreference account = new LedPreference(getActivity());
+
+ if (username == null) {
+ account.setTitle(getString(R.string.pref_sipaccount));
+ } else {
+ account.setTitle(username + "@" + domain);
+ }
+
+ if (defaultAccountID == i) {
+ account.setSummary(R.string.default_account_flag);
+ }
+
+ account.setOnPreferenceClickListener(new OnPreferenceClickListener()
+ {
+ public boolean onPreferenceClick(Preference preference) {
+ LinphoneActivity.instance().displayAccountSettings(accountId);
+ return false;
+ }
+ });
+ updateAccountLed(account, username, domain, mPrefs.isAccountEnabled(i));
+ accounts.addPreference(account);
+ }
+ }
+
+ private void updateAccountLed(final LedPreference me, final String username, final String domain, boolean enabled) {
+ if (!enabled) {
+ me.setLed(R.drawable.led_disconnected);
+ return;
+ }
+
+ if (LinphoneManager.getLcIfManagerNotDestroyedOrNull() != null) {
+ for (LinphoneProxyConfig lpc : LinphoneManager.getLc().getProxyConfigList()) {
+ LinphoneAddress addr = null;
+ try {
+ addr = LinphoneCoreFactory.instance().createLinphoneAddress(lpc.getIdentity());
+ } catch (LinphoneCoreException e) {
+ me.setLed(R.drawable.led_disconnected);
+ return;
+ }
+ if (addr.getUserName().equals(username) && addr.getDomain().equals(domain)) {
+ if (lpc.getState() == LinphoneCore.RegistrationState.RegistrationOk) {
+ me.setLed(R.drawable.led_connected);
+ } else if (lpc.getState() == LinphoneCore.RegistrationState.RegistrationFailed) {
+ me.setLed(R.drawable.led_error);
+ } else if (lpc.getState() == LinphoneCore.RegistrationState.RegistrationProgress) {
+ me.setLed(R.drawable.led_inprogress);
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ updateAccountLed(me, username, domain, true);
+ }
+ }, 500);
+ } else {
+ me.setLed(R.drawable.led_disconnected);
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ private void initMediaEncryptionPreference(ListPreference pref) {
+ List entries = new ArrayList();
+ List values = new ArrayList();
+ entries.add(getString(R.string.media_encryption_none));
+ values.add(getString(R.string.pref_media_encryption_key_none));
+
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc == null || getResources().getBoolean(R.bool.disable_all_security_features_for_markets)) {
+ setListPreferenceValues(pref, entries, values);
+ return;
+ }
+
+ boolean hasZrtp = lc.mediaEncryptionSupported(MediaEncryption.ZRTP);
+ boolean hasSrtp = lc.mediaEncryptionSupported(MediaEncryption.SRTP);
+ boolean hasDtls = lc.mediaEncryptionSupported(MediaEncryption.DTLS);
+
+ if (!hasSrtp && !hasZrtp && !hasDtls) {
+ pref.setEnabled(false);
+ } else {
+ if (hasSrtp){
+ entries.add(getString(R.string.media_encryption_srtp));
+ values.add(getString(R.string.pref_media_encryption_key_srtp));
+ }
+ if (hasZrtp){
+ entries.add(getString(R.string.media_encryption_zrtp));
+ values.add(getString(R.string.pref_media_encryption_key_zrtp));
+ }
+ if (hasDtls){
+ entries.add(getString(R.string.media_encryption_dtls));
+ values.add(getString(R.string.pref_media_encryption_key_dtls));
+
+ }
+ setListPreferenceValues(pref, entries, values);
+ }
+
+ MediaEncryption value = mPrefs.getMediaEncryption();
+ pref.setSummary(value.toString());
+
+ String key = getString(R.string.pref_media_encryption_key_none);
+ if (value.toString().equals(getString(R.string.media_encryption_srtp)))
+ key = getString(R.string.pref_media_encryption_key_srtp);
+ else if (value.toString().equals(getString(R.string.media_encryption_zrtp)))
+ key = getString(R.string.pref_media_encryption_key_zrtp);
+ else if (value.toString().equals(getString(R.string.media_encryption_dtls)))
+ key = getString(R.string.pref_media_encryption_key_dtls);
+ pref.setValue(key);
+ }
+
+ private void initializeVideoPresetPreferences(ListPreference pref) {
+ List entries = new ArrayList();
+ List values = new ArrayList();
+ entries.add("default");
+ values.add("default");
+ entries.add("high-fps");
+ values.add("high-fps");
+ entries.add("custom");
+ values.add("custom");
+ setListPreferenceValues(pref, entries, values);
+ String value = mPrefs.getVideoPreset();
+ pref.setSummary(value);
+ pref.setValue(value);
+ }
+
+ private void initializePreferredVideoSizePreferences(ListPreference pref) {
+ List entries = new ArrayList();
+ List values = new ArrayList();
+ for (String name : LinphoneManager.getLc().getSupportedVideoSizes()) {
+ entries.add(name);
+ values.add(name);
+ }
+
+ setListPreferenceValues(pref, entries, values);
+
+ String value = mPrefs.getPreferredVideoSize();
+ pref.setSummary(value);
+ pref.setValue(value);
+ }
+
+ private void initializePreferredVideoFpsPreferences(ListPreference pref) {
+ List entries = new ArrayList();
+ List values = new ArrayList();
+ entries.add("none");
+ values.add("0");
+ for (int i = 5; i <= 30; i += 5) {
+ String str = Integer.toString(i);
+ entries.add(str);
+ values.add(str);
+ }
+ setListPreferenceValues(pref, entries, values);
+ String value = Integer.toString(mPrefs.getPreferredVideoFps());
+ if (value.equals("0")) {
+ value = "none";
+ }
+ pref.setSummary(value);
+ pref.setValue(value);
+ }
+
+ private static void setListPreferenceValues(ListPreference pref, List entries, List values) {
+ CharSequence[] contents = new CharSequence[entries.size()];
+ entries.toArray(contents);
+ pref.setEntries(contents);
+ contents = new CharSequence[values.size()];
+ values.toArray(contents);
+ pref.setEntryValues(contents);
+ }
+
+ private void initAudioSettings() {
+ PreferenceCategory codecs = (PreferenceCategory) findPreference(getString(R.string.pref_codecs_key));
+ codecs.removeAll();
+
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ for (final PayloadType pt : lc.getAudioCodecs()) {
+ CheckBoxPreference codec = new CheckBoxPreference(getActivity());
+ codec.setTitle(pt.getMime());
+ /* Special case */
+ if (pt.getMime().equals("mpeg4-generic")) {
+ if (android.os.Build.VERSION.SDK_INT < 16) {
+ /* Make sure AAC is disabled */
+ try {
+ lc.enablePayloadType(pt, false);
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+ continue;
+ } else {
+ codec.setTitle("AAC-ELD");
+ }
+ }
+
+ codec.setSummary(pt.getRate() + " Hz");
+ codec.setChecked(lc.isPayloadTypeEnabled(pt));
+
+ codec.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean enable = (Boolean) newValue;
+ try {
+ LinphoneManager.getLcIfManagerNotDestroyedOrNull().enablePayloadType(pt, enable);
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+ return true;
+ }
+ });
+
+ codecs.addPreference(codec);
+ }
+
+ CheckBoxPreference echoCancellation = (CheckBoxPreference) findPreference(getString(R.string.pref_echo_cancellation_key));
+ echoCancellation.setChecked(mPrefs.isEchoCancellationEnabled());
+
+ if (mPrefs.isEchoCancellationEnabled()) {
+ Preference echoCalibration = findPreference(getString(R.string.pref_echo_canceller_calibration_key));
+ echoCalibration.setSummary(String.format(getString(R.string.ec_calibrated), mPrefs.getEchoCalibration()));
+ }
+
+ CheckBoxPreference adaptiveRateControl = (CheckBoxPreference) findPreference(getString(R.string.pref_adaptive_rate_control_key));
+ adaptiveRateControl.setChecked(mPrefs.isAdaptiveRateControlEnabled());
+
+ ListPreference adaptiveRateAlgorithm = (ListPreference) findPreference(getString(R.string.pref_adaptive_rate_algorithm_key));
+ adaptiveRateAlgorithm.setSummary(String.valueOf(mPrefs.getAdaptiveRateAlgorithm()));
+ adaptiveRateAlgorithm.setValue(String.valueOf(mPrefs.getAdaptiveRateAlgorithm()));
+
+ ListPreference bitrateLimit = (ListPreference) findPreference(getString(R.string.pref_codec_bitrate_limit_key));
+ bitrateLimit.setSummary(String.valueOf(mPrefs.getCodecBitrateLimit()));
+ bitrateLimit.setValue(String.valueOf(mPrefs.getCodecBitrateLimit()));
+ }
+
+ private void setAudioPreferencesListener() {
+ findPreference(getString(R.string.pref_echo_cancellation_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean enabled = (Boolean) newValue;
+ mPrefs.setEchoCancellation(enabled);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_adaptive_rate_control_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean enabled = (Boolean) newValue;
+ mPrefs.enableAdaptiveRateControl(enabled);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_adaptive_rate_algorithm_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mPrefs.setAdaptiveRateAlgorithm(AdaptiveRateAlgorithm.fromString((String) newValue));
+ preference.setSummary(String.valueOf(mPrefs.getAdaptiveRateAlgorithm()));
+ return true;
+ }
+ });
+
+
+ findPreference(getString(R.string.pref_codec_bitrate_limit_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mPrefs.setCodecBitrateLimit(Integer.parseInt(newValue.toString()));
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ int bitrate = Integer.parseInt(newValue.toString());
+
+ for (final PayloadType pt : lc.getAudioCodecs()) {
+ if (lc.payloadTypeIsVbr(pt)) {
+ lc.setPayloadTypeBitrate(pt, bitrate);
+ }
+ }
+
+ preference.setSummary(String.valueOf(mPrefs.getCodecBitrateLimit()));
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_echo_canceller_calibration_key)).setOnPreferenceClickListener(new OnPreferenceClickListener() {
+ @Override
+ public boolean onPreferenceClick(Preference preference) {
+ synchronized (SettingsFragment.this) {
+ try {
+ LinphoneManager.getInstance().startEcCalibration(mListener);
+ preference.setSummary(R.string.ec_calibrating);
+ } catch (LinphoneCoreException e) {
+ Log.w(e, "Cannot calibrate EC");
+ }
+ }
+ return true;
+ }
+ });
+ }
+
+ private void initVideoSettings() {
+ initializeVideoPresetPreferences((ListPreference) findPreference(getString(R.string.pref_video_preset_key)));
+ initializePreferredVideoSizePreferences((ListPreference) findPreference(getString(R.string.pref_preferred_video_size_key)));
+ initializePreferredVideoFpsPreferences((ListPreference) findPreference(getString(R.string.pref_preferred_video_fps_key)));
+ EditTextPreference bandwidth = (EditTextPreference) findPreference(getString(R.string.pref_bandwidth_limit_key));
+ bandwidth.setText(Integer.toString(mPrefs.getBandwidthLimit()));
+ bandwidth.setSummary(bandwidth.getText());
+ updateVideoPreferencesAccordingToPreset();
+
+ PreferenceCategory codecs = (PreferenceCategory) findPreference(getString(R.string.pref_video_codecs_key));
+ codecs.removeAll();
+
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ for (final PayloadType pt : lc.getVideoCodecs()) {
+ CheckBoxPreference codec = new CheckBoxPreference(getActivity());
+ codec.setTitle(pt.getMime());
+
+ if (!pt.getMime().equals("VP8")) {
+ if (getResources().getBoolean(R.bool.disable_all_patented_codecs_for_markets)) {
+ continue;
+ } else {
+ if (!Version.hasFastCpuWithAsmOptim() && pt.getMime().equals("H264"))
+ {
+ // Android without neon doesn't support H264
+ Log.w("CPU does not have asm optimisations available, disabling H264");
+ continue;
+ }
+ }
+ }
+ codec.setChecked(lc.isPayloadTypeEnabled(pt));
+
+ codec.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean enable = (Boolean) newValue;
+ try {
+ LinphoneManager.getLcIfManagerNotDestroyedOrNull().enablePayloadType(pt, enable);
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+ return true;
+ }
+ });
+
+ codecs.addPreference(codec);
+ }
+
+ ((CheckBoxPreference) findPreference(getString(R.string.pref_video_enable_key))).setChecked(mPrefs.isVideoEnabled());
+ ((CheckBoxPreference) findPreference(getString(R.string.pref_video_use_front_camera_key))).setChecked(mPrefs.useFrontCam());
+ ((CheckBoxPreference) findPreference(getString(R.string.pref_video_initiate_call_with_video_key))).setChecked(mPrefs.shouldInitiateVideoCall());
+ //((CheckBoxPreference) findPreference(getString(R.string.pref_video_automatically_share_my_video_key))).setChecked(mPrefs.shouldAutomaticallyShareMyVideo());
+ ((CheckBoxPreference) findPreference(getString(R.string.pref_video_automatically_accept_video_key))).setChecked(mPrefs.shouldAutomaticallyAcceptVideoRequests());
+ }
+
+ private void updateVideoPreferencesAccordingToPreset() {
+ if (mPrefs.getVideoPreset().equals("custom")) {
+ findPreference(getString(R.string.pref_preferred_video_fps_key)).setEnabled(true);
+ findPreference(getString(R.string.pref_bandwidth_limit_key)).setEnabled(true);
+ } else {
+ findPreference(getString(R.string.pref_preferred_video_fps_key)).setEnabled(false);
+ findPreference(getString(R.string.pref_bandwidth_limit_key)).setEnabled(false);
+ }
+ ((ListPreference) findPreference(getString(R.string.pref_video_preset_key))).setSummary(mPrefs.getVideoPreset());
+ int fps = mPrefs.getPreferredVideoFps();
+ String fpsStr = Integer.toString(fps);
+ if (fpsStr.equals("0")) {
+ fpsStr = "none";
+ }
+ ((ListPreference) findPreference(getString(R.string.pref_preferred_video_fps_key))).setSummary(fpsStr);
+ ((EditTextPreference) findPreference(getString(R.string.pref_bandwidth_limit_key))).setSummary(Integer.toString(mPrefs.getBandwidthLimit()));
+ }
+
+ private void setVideoPreferencesListener() {
+ findPreference(getString(R.string.pref_video_enable_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean enable = (Boolean) newValue;
+ mPrefs.enableVideo(enable);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_video_use_front_camera_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean enable = (Boolean) newValue;
+ mPrefs.setFrontCamAsDefault(enable);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_video_initiate_call_with_video_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean enable = (Boolean) newValue;
+ mPrefs.setInitiateVideoCall(enable);
+ return true;
+ }
+ });
+
+ /*
+ findPreference(getString(R.string.pref_video_automatically_share_my_video_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean enable = (Boolean) newValue;
+ mPrefs.setAutomaticallyShareMyVideo(enable);
+ return true;
+ }
+ });
+ */
+
+ findPreference(getString(R.string.pref_video_automatically_accept_video_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean enable = (Boolean) newValue;
+ mPrefs.setAutomaticallyAcceptVideoRequests(enable);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_video_preset_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mPrefs.setVideoPreset(newValue.toString());
+ preference.setSummary(mPrefs.getVideoPreset());
+ updateVideoPreferencesAccordingToPreset();
+ return true;
+ }
+ });
+ findPreference(getString(R.string.pref_preferred_video_size_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mPrefs.setPreferredVideoSize(newValue.toString());
+ preference.setSummary(mPrefs.getPreferredVideoSize());
+ updateVideoPreferencesAccordingToPreset();
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_preferred_video_fps_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mPrefs.setPreferredVideoFps(Integer.parseInt(newValue.toString()));
+ updateVideoPreferencesAccordingToPreset();
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_bandwidth_limit_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mPrefs.setBandwidthLimit(Integer.parseInt(newValue.toString()));
+ preference.setSummary(newValue.toString());
+ return true;
+ }
+ });
+ }
+
+ private void initCallSettings() {
+ CheckBoxPreference rfc2833 = (CheckBoxPreference) findPreference(getString(R.string.pref_rfc2833_dtmf_key));
+ CheckBoxPreference sipInfo = (CheckBoxPreference) findPreference(getString(R.string.pref_sipinfo_dtmf_key));
+
+ if (mPrefs.useRfc2833Dtmfs()) {
+ rfc2833.setChecked(true);
+ sipInfo.setChecked(false);
+ sipInfo.setEnabled(false);
+ } else if (mPrefs.useSipInfoDtmfs()) {
+ sipInfo.setChecked(true);
+ rfc2833.setChecked(false);
+ rfc2833.setEnabled(false);
+ }
+
+ setPreferenceDefaultValueAndSummary(R.string.pref_voice_mail_key, mPrefs.getVoiceMailUri());
+ }
+
+ private void setCallPreferencesListener() {
+ findPreference(getString(R.string.pref_rfc2833_dtmf_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean use = (Boolean) newValue;
+ CheckBoxPreference sipInfo = (CheckBoxPreference) findPreference(getString(R.string.pref_sipinfo_dtmf_key));
+ sipInfo.setEnabled(!use);
+ sipInfo.setChecked(false);
+ mPrefs.sendDtmfsAsRfc2833(use);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_voice_mail_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ EditTextPreference voiceMail = (EditTextPreference) findPreference(getString(R.string.pref_voice_mail_key));
+ voiceMail.setSummary(newValue.toString());
+ voiceMail.setText(newValue.toString());
+ mPrefs.setVoiceMailUri(newValue.toString());
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_sipinfo_dtmf_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean use = (Boolean) newValue;
+ CheckBoxPreference rfc2833 = (CheckBoxPreference) findPreference(getString(R.string.pref_rfc2833_dtmf_key));
+ rfc2833.setEnabled(!use);
+ rfc2833.setChecked(false);
+ mPrefs.sendDTMFsAsSipInfo(use);
+ return true;
+ }
+ });
+ }
+
+ private void initNetworkSettings() {
+ initMediaEncryptionPreference((ListPreference) findPreference(getString(R.string.pref_media_encryption_key)));
+
+ ((CheckBoxPreference) findPreference(getString(R.string.pref_wifi_only_key))).setChecked(mPrefs.isWifiOnlyEnabled());
+
+ // Disable UPnP if ICE si enabled, or disable ICE if UPnP is enabled
+ CheckBoxPreference ice = (CheckBoxPreference) findPreference(getString(R.string.pref_ice_enable_key));
+ CheckBoxPreference upnp = (CheckBoxPreference) findPreference(getString(R.string.pref_upnp_enable_key));
+ ice.setChecked(mPrefs.isIceEnabled());
+ if (mPrefs.isIceEnabled()) {
+ upnp.setEnabled(false);
+ } else {
+ upnp.setChecked(mPrefs.isUpnpEnabled());
+ if (mPrefs.isUpnpEnabled()) {
+ ice.setEnabled(false);
+ }
+ }
+
+ CheckBoxPreference randomPort = (CheckBoxPreference) findPreference(getString(R.string.pref_transport_use_random_ports_key));
+ randomPort.setChecked(mPrefs.isUsingRandomPort());
+
+ // Disable sip port choice if port is random
+ EditTextPreference sipPort = (EditTextPreference) findPreference(getString(R.string.pref_sip_port_key));
+ sipPort.setEnabled(!randomPort.isChecked());
+ sipPort.setSummary(mPrefs.getSipPort());
+ sipPort.setText(mPrefs.getSipPort());
+
+ EditTextPreference stun = (EditTextPreference) findPreference(getString(R.string.pref_stun_server_key));
+ stun.setSummary(mPrefs.getStunServer());
+ stun.setText(mPrefs.getStunServer());
+
+ ((CheckBoxPreference) findPreference(getString(R.string.pref_push_notification_key))).setChecked(mPrefs.isPushNotificationEnabled());
+ ((CheckBoxPreference) findPreference(getString(R.string.pref_ipv6_key))).setChecked(mPrefs.isUsingIpv6());
+ }
+
+ private void setNetworkPreferencesListener() {
+ findPreference(getString(R.string.pref_wifi_only_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mPrefs.setWifiOnlyEnabled((Boolean) newValue);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_stun_server_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mPrefs.setStunServer(newValue.toString());
+ preference.setSummary(newValue.toString());
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_ice_enable_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ CheckBoxPreference upnp = (CheckBoxPreference) findPreference(getString(R.string.pref_upnp_enable_key));
+ boolean value = (Boolean) newValue;
+ upnp.setChecked(false);
+ upnp.setEnabled(!value);
+ mPrefs.setIceEnabled((Boolean) newValue);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_upnp_enable_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ CheckBoxPreference ice = (CheckBoxPreference) findPreference(getString(R.string.pref_ice_enable_key));
+ boolean value = (Boolean) newValue;
+ ice.setChecked(false);
+ ice.setEnabled(!value);
+ mPrefs.setUpnpEnabled(value);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_transport_use_random_ports_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean randomPort = (Boolean) newValue;
+ mPrefs.useRandomPort((Boolean) newValue);
+ findPreference(getString(R.string.pref_sip_port_key)).setEnabled(!randomPort);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_sip_port_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ int port = -1;
+ try {
+ port = Integer.parseInt(newValue.toString());
+ } catch (NumberFormatException nfe) { }
+
+ mPrefs.setSipPort(port);
+ preference.setSummary(newValue.toString());
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_media_encryption_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String value = newValue.toString();
+ MediaEncryption menc = MediaEncryption.None;
+ if (value.equals(getString(R.string.pref_media_encryption_key_srtp)))
+ menc = MediaEncryption.SRTP;
+ else if (value.equals(getString(R.string.pref_media_encryption_key_zrtp)))
+ menc = MediaEncryption.ZRTP;
+ else if (value.equals(getString(R.string.pref_media_encryption_key_dtls)))
+ menc = MediaEncryption.DTLS;
+ mPrefs.setMediaEncryption(menc);
+
+ preference.setSummary(mPrefs.getMediaEncryption().toString());
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_push_notification_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mPrefs.setPushNotificationEnabled((Boolean) newValue);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_ipv6_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ mPrefs.useIpv6((Boolean) newValue);
+ return true;
+ }
+ });
+ }
+
+ private void initAdvancedSettings() {
+ ((CheckBoxPreference)findPreference(getString(R.string.pref_debug_key))).setChecked(mPrefs.isDebugEnabled());
+ ((CheckBoxPreference)findPreference(getString(R.string.pref_background_mode_key))).setChecked(mPrefs.isBackgroundModeEnabled());
+ ((CheckBoxPreference)findPreference(getString(R.string.pref_animation_enable_key))).setChecked(mPrefs.areAnimationsEnabled());
+ ((CheckBoxPreference)findPreference(getString(R.string.pref_autostart_key))).setChecked(mPrefs.isAutoStartEnabled());
+ setPreferenceDefaultValueAndSummary(R.string.pref_image_sharing_server_key, mPrefs.getSharingPictureServerUrl());
+ setPreferenceDefaultValueAndSummary(R.string.pref_remote_provisioning_key, mPrefs.getRemoteProvisioningUrl());
+ setPreferenceDefaultValueAndSummary(R.string.pref_display_name_key, mPrefs.getDefaultDisplayName());
+ setPreferenceDefaultValueAndSummary(R.string.pref_user_name_key, mPrefs.getDefaultUsername());
+ }
+
+ private void setAdvancedPreferencesListener() {
+ findPreference(getString(R.string.pref_debug_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean value = (Boolean) newValue;
+ mPrefs.setDebugEnabled(value);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_background_mode_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean value = (Boolean) newValue;
+ mPrefs.setBackgroundModeEnabled(value);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_animation_enable_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean value = (Boolean) newValue;
+ mPrefs.setAnimationsEnabled(value);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_autostart_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ boolean value = (Boolean) newValue;
+ mPrefs.setAutoStart(value);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_image_sharing_server_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String value = (String) newValue;
+ mPrefs.setSharingPictureServerUrl(value);
+ preference.setSummary(value);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_remote_provisioning_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String value = (String) newValue;
+ mPrefs.setRemoteProvisioningUrl(value);
+ preference.setSummary(value);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_display_name_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String value = (String) newValue;
+ mPrefs.setDefaultDisplayName(value);
+ preference.setSummary(value);
+ return true;
+ }
+ });
+
+ findPreference(getString(R.string.pref_user_name_key)).setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String value = (String) newValue;
+ if(value.equals("")) return false;
+
+ mPrefs.setDefaultUsername(value);
+ preference.setSummary(value);
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+
+ initAccounts();
+
+ if (LinphoneActivity.isInstanciated()) {
+ LinphoneActivity.instance().selectMenu(FragmentsAvailable.SETTINGS);
+
+ if (getResources().getBoolean(R.bool.show_statusbar_only_on_dialer)) {
+ LinphoneActivity.instance().hideStatusBar();
+ }
+ }
+ }
+}
diff --git a/src/org/linphone/StatusFragment.java b/src/org/linphone/StatusFragment.java
index 0309ce5df..e6f997b2c 100644
--- a/src/org/linphone/StatusFragment.java
+++ b/src/org/linphone/StatusFragment.java
@@ -25,23 +25,25 @@ import java.util.TimerTask;
import org.linphone.core.LinphoneCall;
import org.linphone.core.LinphoneCallParams;
import org.linphone.core.LinphoneCallStats;
+import org.linphone.core.LinphoneContent;
import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.MediaEncryption;
import org.linphone.core.LinphoneCore.RegistrationState;
+import org.linphone.core.LinphoneCoreListenerBase;
+import org.linphone.core.LinphoneEvent;
import org.linphone.core.LinphoneProxyConfig;
import org.linphone.core.PayloadType;
+import org.linphone.mediastream.Log;
import org.linphone.ui.SlidingDrawer;
import org.linphone.ui.SlidingDrawer.OnDrawerOpenListener;
import android.app.Activity;
+import android.app.AlertDialog;
import android.content.Context;
-import android.content.SharedPreferences;
+import android.content.DialogInterface;
import android.os.Bundle;
-import android.os.CountDownTimer;
import android.os.Handler;
-import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
-import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
@@ -52,7 +54,6 @@ import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TableLayout;
import android.widget.TextView;
-import android.widget.Toast;
/**
* @author Sylvain Berfini
@@ -60,7 +61,7 @@ import android.widget.Toast;
public class StatusFragment extends Fragment {
private Handler mHandler = new Handler();
private Handler refreshHandler = new Handler();
- private TextView statusText;
+ private TextView statusText, exit, voicemailCount;
private ImageView statusLed, callQuality, encryption, background;
private ListView sliderContentAccounts;
private TableLayout callStats;
@@ -68,12 +69,9 @@ public class StatusFragment extends Fragment {
// private LinearLayout allAccountsLed;
private Runnable mCallQualityUpdater;
private boolean isInCall, isAttached = false;
-
- private Toast zrtpToast;
- private CountDownTimer zrtpHack;
- private boolean hideZrtpToast = false;
private Timer mTimer;
private TimerTask mTask;
+ private LinphoneCoreListenerBase mListener;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -98,8 +96,81 @@ public class StatusFragment extends Fragment {
sliderContentAccounts = (ListView) view.findViewById(R.id.accounts);
+ voicemailCount = (TextView) view.findViewById(R.id.voicemailCount);
+
+ exit = (TextView) view.findViewById(R.id.exit);
+ exit.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ if (LinphoneActivity.isInstanciated()) {
+ LinphoneActivity.instance().exit();
+ }
+ }
+ });
+ if (getResources().getBoolean(R.bool.exit_button_on_dialer))
+ exit.setVisibility(View.VISIBLE);
+
// We create it once to not delay the first display
populateSliderContent();
+
+ mListener = new LinphoneCoreListenerBase(){
+ @Override
+ public void registrationState(final LinphoneCore lc, final LinphoneProxyConfig proxy, final LinphoneCore.RegistrationState state, String smessage) {
+ if (!isAttached || !LinphoneService.isReady()) {
+ return;
+ }
+ if (lc.getDefaultProxyConfig().equals(proxy)) {
+ statusLed.setImageResource(getStatusIconResource(state, true));
+ statusText.setText(getStatusIconText(state));
+ }
+
+ try {
+ if (getResources().getBoolean(R.bool.lock_statusbar)) {
+ statusText.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ lc.refreshRegisters();
+ }
+ });
+ }
+// setMiniLedsForEachAccount();
+ populateSliderContent();
+ sliderContentAccounts.invalidate();
+ } catch (IllegalStateException ise) {}
+ }
+
+ @Override
+ public void notifyReceived(LinphoneCore lc, LinphoneEvent ev, String eventName, LinphoneContent content) {
+
+ if(!content.getType().equals("application")) return;
+ if(!content.getSubtype().equals("simple-message-summary")) return;
+
+ if (content.getData() == null) return;
+
+ int unreadCount = -1;
+ String data = content.getDataAsString();
+ String[] voiceMail = data.split("voice-message: ");
+ final String[] intToParse = voiceMail[1].split("/",0);
+
+ unreadCount = Integer.parseInt(intToParse[0]);
+ if (unreadCount > 0) {
+ voicemailCount.setText(unreadCount + " " + getResources().getString(R.string.voicemail_unread));
+ voicemailCount.setVisibility(View.VISIBLE);
+ } else {
+ voicemailCount.setVisibility(View.GONE);
+ }
+ }
+
+ };
+
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.addListener(mListener);
+ LinphoneProxyConfig lpc = lc.getDefaultProxyConfig();
+ if (lpc != null) {
+ mListener.registrationState(lc, lpc, lpc.getState(), null);
+ }
+ }
return view;
}
@@ -156,12 +227,14 @@ public class StatusFragment extends Fragment {
if (LinphoneManager.isInstanciated() && LinphoneManager.getLc() != null) {
sliderContentAccounts.setVisibility(View.GONE);
callStats.setVisibility(View.GONE);
+ voicemailCount.setVisibility(View.GONE);
if (isInCall && isAttached && getResources().getBoolean(R.bool.display_call_stats)) {
callStats.setVisibility(View.VISIBLE);
LinphoneCall call = LinphoneManager.getLc().getCurrentCall();
initCallStatsRefresher(call, callStats);
} else if (!isInCall) {
+ voicemailCount.setVisibility(View.VISIBLE);
sliderContentAccounts.setVisibility(View.VISIBLE);
AccountsListAdapter adapter = new AccountsListAdapter();
sliderContentAccounts.setAdapter(adapter);
@@ -169,35 +242,6 @@ public class StatusFragment extends Fragment {
}
}
- public void registrationStateChanged(final RegistrationState state) {
- if (!isAttached || !LinphoneService.isReady()) {
- return;
- }
-
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- statusLed.setImageResource(getStatusIconResource(state, true));
- statusText.setText(getStatusIconText(state));
- try {
- if (getResources().getBoolean(R.bool.lock_statusbar)) {
- statusText.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (LinphoneManager.isInstanciated()) {
- LinphoneManager.getLc().refreshRegisters();
- }
- }
- });
- }
- // setMiniLedsForEachAccount();
- populateSliderContent();
- sliderContentAccounts.invalidate();
- } catch (IllegalStateException ise) {}
- }
- });
- }
-
// private void setMiniLedsForEachAccount() {
// if (allAccountsLed == null)
// return;
@@ -217,7 +261,8 @@ public class StatusFragment extends Fragment {
private int getStatusIconResource(LinphoneCore.RegistrationState state, boolean isDefaultAccount) {
try {
- boolean defaultAccountConnected = (isDefaultAccount && LinphoneManager.getLcIfManagerNotDestroyedOrNull().getDefaultProxyConfig().isRegistered()) || !isDefaultAccount;
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ boolean defaultAccountConnected = (isDefaultAccount && lc != null && lc.getDefaultProxyConfig() != null && lc.getDefaultProxyConfig().isRegistered()) || !isDefaultAccount;
if (state == RegistrationState.RegistrationOk && defaultAccountConnected) {
return R.drawable.led_connected;
} else if (state == RegistrationState.RegistrationProgress) {
@@ -236,8 +281,10 @@ public class StatusFragment extends Fragment {
private String getStatusIconText(LinphoneCore.RegistrationState state) {
Context context = getActivity();
- if (!isAttached)
+ if (!isAttached && LinphoneActivity.isInstanciated())
context = LinphoneActivity.instance();
+ else if (!isAttached && LinphoneService.isReady())
+ context = LinphoneService.instance();
try {
if (state == RegistrationState.RegistrationOk && LinphoneManager.getLcIfManagerNotDestroyedOrNull().getDefaultProxyConfig().isRegistered()) {
@@ -309,8 +356,8 @@ public class StatusFragment extends Fragment {
@Override
public void onResume() {
super.onResume();
- LinphoneCore lc = LinphoneManager.getLc();
-
+
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
LinphoneCall call = lc.getCurrentCall();
if (isInCall && (call != null || lc.getConferenceSize() > 1 || lc.getCallsNb() > 0)) {
if (call != null) {
@@ -320,6 +367,7 @@ public class StatusFragment extends Fragment {
statusText.setVisibility(View.GONE);
encryption.setVisibility(View.VISIBLE);
+ exit.setVisibility(View.GONE);
// We are obviously connected
statusLed.setImageResource(R.drawable.led_connected);
@@ -328,6 +376,8 @@ public class StatusFragment extends Fragment {
statusText.setVisibility(View.VISIBLE);
background.setVisibility(View.VISIBLE);
encryption.setVisibility(View.GONE);
+ if (getResources().getBoolean(R.bool.exit_button_on_dialer))
+ exit.setVisibility(View.VISIBLE);
if (drawer != null && getResources().getBoolean(R.bool.lock_statusbar)) {
drawer.lock();
@@ -341,18 +391,25 @@ public class StatusFragment extends Fragment {
public void onPause() {
super.onPause();
- if (zrtpToast != null) {
- hideZRTPDialog();
- }
-
if (mCallQualityUpdater != null) {
refreshHandler.removeCallbacks(mCallQualityUpdater);
mCallQualityUpdater = null;
}
}
+ @Override
+ public void onDestroy() {
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.removeListener(mListener);
+ }
+
+ super.onDestroy();
+ }
+
public void refreshStatusItems(final LinphoneCall call, boolean isVideoEnabled) {
if (call != null) {
+ voicemailCount.setVisibility(View.GONE);
MediaEncryption mediaEncryption = call.getCurrentParamsCopy().getMediaEncryption();
if (isVideoEnabled) {
@@ -361,7 +418,7 @@ public class StatusFragment extends Fragment {
background.setVisibility(View.VISIBLE);
}
- if (mediaEncryption == MediaEncryption.SRTP || (mediaEncryption == MediaEncryption.ZRTP && call.isAuthenticationTokenVerified())) {
+ if (mediaEncryption == MediaEncryption.SRTP || (mediaEncryption == MediaEncryption.ZRTP && call.isAuthenticationTokenVerified()) || mediaEncryption == MediaEncryption.DTLS) {
encryption.setImageResource(R.drawable.security_ok);
} else if (mediaEncryption == MediaEncryption.ZRTP && !call.isAuthenticationTokenVerified()) {
encryption.setImageResource(R.drawable.security_pending);
@@ -382,80 +439,33 @@ public class StatusFragment extends Fragment {
}
}
- private void hideZRTPDialog() {
- hideZrtpToast = true;
-
- if (zrtpToast != null) {
- zrtpToast.cancel();
- }
- if (zrtpHack != null) {
- zrtpHack.cancel();
- }
- }
-
private void showZRTPDialog(final LinphoneCall call) {
- boolean authVerified = call.isAuthenticationTokenVerified();
- String format = getString(authVerified ? R.string.reset_sas_fmt : R.string.verify_sas_fmt);
-
- LayoutInflater inflater = LayoutInflater.from(getActivity());
- View layout = inflater.inflate(R.layout.zrtp_dialog, (ViewGroup) getActivity().findViewById(R.id.toastRoot));
-
- TextView toastText = (TextView) layout.findViewById(R.id.toastMessage);
- toastText.setText(String.format(format, call.getAuthenticationToken()));
-
- zrtpToast = new Toast(getActivity());
- zrtpToast.setGravity(Gravity.TOP | Gravity.RIGHT, 0, LinphoneUtils.pixelsToDpi(getResources(), 40));
- zrtpToast.setDuration(Toast.LENGTH_LONG);
-
- ImageView ok = (ImageView) layout.findViewById(R.id.toastOK);
- ok.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (call != null) {
- call.setAuthenticationTokenVerified(true);
- }
- if (encryption != null) {
- encryption.setImageResource(R.drawable.security_ok);
- }
- hideZRTPDialog();
- }
- });
-
- ImageView notOk = (ImageView) layout.findViewById(R.id.toastNotOK);
- notOk.setOnClickListener(new OnClickListener() {
- @Override
- public void onClick(View v) {
- if (call != null) {
- call.setAuthenticationTokenVerified(false);
- }
- if (encryption != null) {
- encryption.setImageResource(R.drawable.security_pending);
- }
- hideZRTPDialog();
- }
- });
-
- zrtpHack = new CountDownTimer(3000, 1000)
- {
- public void onTick(long millisUntilFinished)
- {
- if (!hideZrtpToast) {
- zrtpToast.show();
- }
- }
- public void onFinish() {
- if (!hideZrtpToast) {
- zrtpToast.show();
- zrtpHack.start();
- }
- }
-
- };
-
- zrtpToast.setView(layout);
- hideZrtpToast = false;
- zrtpToast.show();
- zrtpHack.start();
+ if (getActivity() == null) {
+ Log.w("Can't display ZRTP popup, no Activity");
+ return;
+ }
+ new AlertDialog.Builder(getActivity())
+ .setTitle(call.getAuthenticationToken())
+ .setMessage(getString(R.string.zrtp_help))
+ .setPositiveButton(R.string.zrtp_accept, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ call.setAuthenticationTokenVerified(true);
+ if (encryption != null) {
+ encryption.setImageResource(R.drawable.security_ok);
+ }
+ }
+ })
+ .setNegativeButton(R.string.zrtp_deny, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ if (call != null) {
+ call.setAuthenticationTokenVerified(false);
+ if (encryption != null) {
+ encryption.setImageResource(R.drawable.security_pending);
+ }
+ }
+ }
+ })
+ .show();
}
private void initCallStatsRefresher(final LinphoneCall call, final View view) {
@@ -477,7 +487,10 @@ public class StatusFragment extends Fragment {
final TextView dl = (TextView) view.findViewById(R.id.downloadBandwith);
final TextView ul = (TextView) view.findViewById(R.id.uploadBandwith);
final TextView ice = (TextView) view.findViewById(R.id.ice);
- if (codec == null || dl == null || ul == null || ice == null) {
+ final TextView videoResolution = (TextView) view.findViewById(R.id.video_resolution);
+ final View videoResolutionLayout = view.findViewById(R.id.video_resolution_layout);
+
+ if (codec == null || dl == null || ul == null || ice == null || videoResolution == null || videoResolutionLayout == null) {
mTimer.cancel();
return;
}
@@ -500,6 +513,9 @@ public class StatusFragment extends Fragment {
dl.setText(String.valueOf((int) videoStats.getDownloadBandwidth()) + " / " + (int) audioStats.getDownloadBandwidth() + " kbits/s");
ul.setText(String.valueOf((int) videoStats.getUploadBandwidth()) + " / " + (int) audioStats.getUploadBandwidth() + " kbits/s");
ice.setText(videoStats.getIceState().toString());
+
+ videoResolutionLayout.setVisibility(View.VISIBLE);
+ videoResolution.setText("\u2191 " + params.getSentVideoSize().toDisplayableString() + " / \u2193 " + params.getReceivedVideoSize().toDisplayableString());
}
} else {
final LinphoneCallStats audioStats = call.getAudioStats();
@@ -512,6 +528,8 @@ public class StatusFragment extends Fragment {
dl.setText(String.valueOf((int) audioStats.getDownloadBandwidth()) + " kbits/s");
ul.setText(String.valueOf((int) audioStats.getUploadBandwidth()) + " kbits/s");
ice.setText(audioStats.getIceState().toString());
+
+ videoResolutionLayout.setVisibility(View.GONE);
}
}
}
@@ -519,17 +537,13 @@ public class StatusFragment extends Fragment {
});
}
};
- mTimer.scheduleAtFixedRate(mTask, 0, 1500);
+ mTimer.scheduleAtFixedRate(mTask, 0, 1000);
}
class AccountsListAdapter extends BaseAdapter {
- private SharedPreferences prefs;
private List checkboxes;
AccountsListAdapter() {
- if (LinphoneActivity.isInstanciated()) {
- prefs = PreferenceManager.getDefaultSharedPreferences(LinphoneActivity.instance());
- }
checkboxes = new ArrayList();
}
@@ -539,23 +553,16 @@ public class StatusFragment extends Fragment {
public void onClick(View v) {
CheckBox checkBox = (CheckBox) v;
if (checkBox.isChecked()) {
- SharedPreferences.Editor editor = prefs.edit();
String tag = (String) checkBox.getTag();
String sipAddress = tag.split(":")[0];
int accountPosition = Integer.parseInt(tag.split(":")[1]);
- int nbAccounts = prefs.getInt(getString(R.string.pref_extra_accounts), 0);
+ int nbAccounts = LinphonePreferences.instance().getAccountCount();
int accountIndex = 0;
for (int i = 0; i < nbAccounts; i++)
{
- String keyUsername = getString(R.string.pref_username_key);
- String keyDomain = getString(R.string.pref_domain_key);
- if (i > 0) {
- keyUsername += i + "";
- keyDomain += i + "";
- }
- String username = prefs.getString(keyUsername, "");
- String domain = prefs.getString(keyDomain, "");
+ String username = LinphonePreferences.instance().getAccountUsername(i);
+ String domain = LinphonePreferences.instance().getAccountDomain(i);
String identity = username + "@" + domain;
if (identity.equals(sipAddress)) {
accountIndex = i;
@@ -563,8 +570,7 @@ public class StatusFragment extends Fragment {
}
}
- editor.putInt(getString(R.string.pref_default_account_key), accountIndex);
- editor.commit();
+ LinphonePreferences.instance().setDefaultAccount(accountIndex);
for (CheckBox cb : checkboxes) {
cb.setChecked(false);
@@ -628,34 +634,30 @@ public class StatusFragment extends Fragment {
isDefault.setChecked(false);
isDefault.setEnabled(true);
- if (prefs != null) {
- int nbAccounts = prefs.getInt(getString(R.string.pref_extra_accounts), 0);
- int accountIndex = 0;
- for (int i = 0; i < nbAccounts; i++)
- {
- String keyUsername = getString(R.string.pref_username_key);
- String keyDomain = getString(R.string.pref_domain_key);
- if (i > 0) {
- keyUsername += i + "";
- keyDomain += i + "";
- }
- String username = prefs.getString(keyUsername, "");
- String domain = prefs.getString(keyDomain, "");
- String id = username + "@" + domain;
- if (id.equals(sipAddress)) {
- accountIndex = i;
- break;
- }
+ int nbAccounts = LinphonePreferences.instance().getAccountCount();
+ int accountIndex = 0;
+ for (int i = 0; i < nbAccounts; i++)
+ {
+ String username = LinphonePreferences.instance().getAccountUsername(i);
+ String domain = LinphonePreferences.instance().getAccountDomain(i);
+ String id = username + "@" + domain;
+ if (id.equals(sipAddress)) {
+ accountIndex = i;
+ break;
}
- if (prefs.getInt(getString(R.string.pref_default_account_key), 0) == accountIndex) {
+ }
+
+ // Force led if account is disabled
+ if (!LinphonePreferences.instance().isAccountEnabled(accountIndex)) {
+ status.setImageResource(getStatusIconResource(RegistrationState.RegistrationNone, false));
+ } else {
+ if (LinphonePreferences.instance().getDefaultAccountIndex() == accountIndex) {
isDefault.setChecked(true);
isDefault.setEnabled(false);
status.setImageResource(getStatusIconResource(lpc.getState(), true));
} else {
status.setImageResource(getStatusIconResource(lpc.getState(), false));
}
- } else {
- status.setImageResource(getStatusIconResource(lpc.getState(), false));
}
isDefault.setOnClickListener(defaultListener);
@@ -663,4 +665,5 @@ public class StatusFragment extends Fragment {
return view;
}
}
+
}
diff --git a/src/org/linphone/UIThreadDispatcher.java b/src/org/linphone/UIThreadDispatcher.java
new file mode 100644
index 000000000..d2b419bdf
--- /dev/null
+++ b/src/org/linphone/UIThreadDispatcher.java
@@ -0,0 +1,30 @@
+/*
+UIThreadDispatcher.java
+Copyright (C) 2014 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+package org.linphone;
+
+import android.os.Handler;
+import android.os.Looper;
+
+public class UIThreadDispatcher {
+ private static Handler mHandler = new Handler(Looper.getMainLooper());
+
+ public static void dispatch(Runnable r) {
+ mHandler.post(r);
+ }
+}
diff --git a/src/org/linphone/VideoCallFragment.java b/src/org/linphone/VideoCallFragment.java
index cb32628b5..51744e887 100644
--- a/src/org/linphone/VideoCallFragment.java
+++ b/src/org/linphone/VideoCallFragment.java
@@ -66,8 +66,7 @@ public class VideoCallFragment extends Fragment implements OnGestureListener, On
fixZOrder(mVideoView, mCaptureView);
- androidVideoWindowImpl = new AndroidVideoWindowImpl(mVideoView, mCaptureView);
- androidVideoWindowImpl.setListener(new AndroidVideoWindowImpl.VideoWindowListener() {
+ androidVideoWindowImpl = new AndroidVideoWindowImpl(mVideoView, mCaptureView, new AndroidVideoWindowImpl.VideoWindowListener() {
public void onVideoRenderingSurfaceReady(AndroidVideoWindowImpl vw, SurfaceView surface) {
LinphoneManager.getLc().setVideoWindow(vw);
mVideoView = surface;
@@ -90,7 +89,6 @@ public class VideoCallFragment extends Fragment implements OnGestureListener, On
LinphoneManager.getLc().setPreviewWindow(null);
}
});
- androidVideoWindowImpl.init();
mVideoView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
diff --git a/src/org/linphone/compatibility/ApiEightPlus.java b/src/org/linphone/compatibility/ApiEightPlus.java
index fb9cc1f63..c9e47a198 100644
--- a/src/org/linphone/compatibility/ApiEightPlus.java
+++ b/src/org/linphone/compatibility/ApiEightPlus.java
@@ -1,15 +1,12 @@
package org.linphone.compatibility;
+import org.linphone.LinphonePreferences;
import org.linphone.R;
import org.linphone.mediastream.Log;
import android.annotation.TargetApi;
import android.content.Context;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
-import android.view.Display;
-
-import com.google.android.gcm.GCMRegistrar;
+import android.media.AudioManager;
/*
ApiEightPlus.java
@@ -27,44 +24,47 @@ GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/**
* @author Sylvain Berfini
*/
+
@TargetApi(8)
public class ApiEightPlus {
- public static int getRotation(Display display) {
- return display.getRotation();
- }
+ public static void initPushNotificationService(Context context) {
+ try {
+ Class> GCMRegistrar = Class.forName("com.google.android.gcm.GCMRegistrar");
+ // Starting the push notification service
+ GCMRegistrar.getMethod("checkDevice", Context.class).invoke(null, context);
+ try {
+ GCMRegistrar.getMethod("checkManifest", Context.class).invoke(null, context);
+ } catch (IllegalStateException e){
+ Log.e("Push notification: No receiver found",e);
+ }
+ final String regId = (String)GCMRegistrar.getMethod("getRegistrationId", Context.class).invoke(null, context);
+ String newPushSenderID = context.getString(R.string.push_sender_id);
+ String currentPushSenderID = LinphonePreferences.instance().getPushNotificationRegistrationID();
+ if (regId.equals("") || currentPushSenderID == null || !currentPushSenderID.equals(newPushSenderID)) {
+ GCMRegistrar.getMethod("register", Context.class, String[].class).invoke(null, context, new String[]{newPushSenderID});
- public static void initPushNotificationService(Context context) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
+ Log.d("Push Notification: storing current sender id = " + newPushSenderID);
+ LinphonePreferences.instance().setPushNotificationRegistrationID(newPushSenderID);
+ } else {
+ Log.d("Push Notification: already registered with id = " + regId);
+ LinphonePreferences.instance().setPushNotificationRegistrationID(regId);
+ }
+ } catch (java.lang.UnsupportedOperationException e) {
+ Log.i("Push Notification: not activated");
+ } catch (Exception e1) {
+ //assume the jar is not provided
+ Log.i("Push Notification: assuming GCM jar is not provided.");
+ }
+ }
- try {
- // Starting the push notification service
- GCMRegistrar.checkDevice(context);
- GCMRegistrar.checkManifest(context);
- final String regId = GCMRegistrar.getRegistrationId(context);
- String newPushSenderID = context.getString(R.string.push_sender_id);
- String currentPushSenderID = prefs.getString(context.getString(R.string.push_sender_id_key), null);
- if (regId.equals("") || currentPushSenderID == null || !currentPushSenderID.equals(newPushSenderID)) {
- GCMRegistrar.register(context, newPushSenderID);
-
- Log.d("Push Notification : storing current sender id = " + newPushSenderID);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString(context.getString(R.string.push_sender_id_key), newPushSenderID);
-
- editor.commit();
- } else {
- Log.d("Push Notification : already registered with id = " + regId);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString(context.getString(R.string.push_reg_id_key), regId);
- editor.commit();
- }
- } catch (java.lang.UnsupportedOperationException e) {
- Log.i("Push Notification not activated");
- }
- }
-}
+ @SuppressWarnings("deprecation")
+ public static String getAudioManagerEventForBluetoothConnectionStateChangedEvent() {
+ return AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED;
+ }
+}
\ No newline at end of file
diff --git a/src/org/linphone/compatibility/ApiElevenPlus.java b/src/org/linphone/compatibility/ApiElevenPlus.java
index 66e70f516..cce5c9795 100644
--- a/src/org/linphone/compatibility/ApiElevenPlus.java
+++ b/src/org/linphone/compatibility/ApiElevenPlus.java
@@ -1,15 +1,26 @@
package org.linphone.compatibility;
+import java.util.ArrayList;
+
import org.linphone.R;
+import org.linphone.mediastream.Log;
import android.annotation.TargetApi;
import android.app.Notification;
import android.app.PendingIntent;
import android.content.ClipData;
import android.content.ClipboardManager;
+import android.content.ContentUris;
+import android.content.ContentValues;
import android.content.Context;
+import android.content.Intent;
import android.graphics.Bitmap;
import android.media.AudioManager;
+import android.net.Uri;
+import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds.SipAddress;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.Intents.Insert;
/*
ApiElevenPlus.java
@@ -41,15 +52,16 @@ public class ApiElevenPlus {
PendingIntent intent) {
String title;
if (msgCount == 1) {
- title = "Unread message from %s".replace("%s", msgSender);
+ title = msgSender;
} else {
- title = "%i unread messages"
+ title = context.getString(R.string.unread_messages)
.replace("%i", String.valueOf(msgCount));
}
Notification notif = new Notification.Builder(context)
.setContentTitle(title)
.setContentText(msg)
+ .setContentIntent(intent)
.setSmallIcon(R.drawable.chat_icon_over)
.setAutoCancel(true)
.setDefaults(
@@ -58,7 +70,6 @@ public class ApiElevenPlus {
| Notification.DEFAULT_VIBRATE)
.setWhen(System.currentTimeMillis())
.setLargeIcon(contactIcon).getNotification();
- notif.contentIntent = intent;
return notif;
}
@@ -71,17 +82,41 @@ public class ApiElevenPlus {
Notification notif = new Notification.Builder(context).setContentTitle(contactName)
.setContentText(msg).setSmallIcon(iconID)
.setAutoCancel(false)
+ .setContentIntent(intent)
.setWhen(System.currentTimeMillis())
.setLargeIcon(contactIcon).getNotification();
- notif.contentIntent = intent;
-
+ notif.flags |= Notification.FLAG_ONGOING_EVENT;
+
return notif;
}
-
+
@SuppressWarnings("deprecation")
- public static void setNotificationLatestEventInfo(Notification notif,
- Context context, String title, String content, PendingIntent intent) {
- notif.setLatestEventInfo(context, title, content, intent);
+ public static Notification createNotification(Context context, String title, String message, int icon, int level, Bitmap largeIcon, PendingIntent intent, boolean isOngoingEvent) {
+ Notification notif;
+
+ if (largeIcon != null) {
+ notif = new Notification.Builder(context)
+ .setContentTitle(title)
+ .setContentText(message)
+ .setSmallIcon(icon, level)
+ .setLargeIcon(largeIcon)
+ .setContentIntent(intent)
+ .setWhen(System.currentTimeMillis())
+ .getNotification();
+ } else {
+ notif = new Notification.Builder(context)
+ .setContentTitle(title)
+ .setContentText(message)
+ .setSmallIcon(icon, level)
+ .setContentIntent(intent)
+ .setWhen(System.currentTimeMillis())
+ .getNotification();
+ }
+ if (isOngoingEvent) {
+ notif.flags |= Notification.FLAG_ONGOING_EVENT;
+ }
+
+ return notif;
}
public static void copyTextToClipboard(Context context, String msg) {
@@ -91,6 +126,58 @@ public class ApiElevenPlus {
}
public static void setAudioManagerInCallMode(AudioManager manager) {
+ if (manager.getMode() == AudioManager.MODE_IN_COMMUNICATION) {
+ Log.w("---AudioManager: already in MODE_IN_COMMUNICATION, skipping...");
+ return;
+ }
+ Log.d("---AudioManager: set mode to MODE_IN_COMMUNICATION");
manager.setMode(AudioManager.MODE_IN_COMMUNICATION);
}
+
+ public static Intent prepareAddContactIntent(String displayName, String sipUri) {
+ Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
+ intent.putExtra(ContactsContract.Intents.Insert.NAME, displayName);
+
+ if (sipUri != null && sipUri.startsWith("sip:")) {
+ sipUri = sipUri.substring(4);
+ }
+
+ ArrayList data = new ArrayList();
+ ContentValues sipAddressRow = new ContentValues();
+ sipAddressRow.put(Contacts.Data.MIMETYPE, SipAddress.CONTENT_ITEM_TYPE);
+ sipAddressRow.put(SipAddress.SIP_ADDRESS, sipUri);
+ data.add(sipAddressRow);
+ intent.putParcelableArrayListExtra(Insert.DATA, data);
+
+ return intent;
+ }
+
+ public static Intent prepareEditContactIntentWithSipAddress(int id, String sipUri) {
+ Intent intent = new Intent(Intent.ACTION_EDIT, Contacts.CONTENT_URI);
+ Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, id);
+ intent.setData(contactUri);
+
+ ArrayList data = new ArrayList();
+ ContentValues sipAddressRow = new ContentValues();
+ sipAddressRow.put(Contacts.Data.MIMETYPE, SipAddress.CONTENT_ITEM_TYPE);
+ sipAddressRow.put(SipAddress.SIP_ADDRESS, sipUri);
+ data.add(sipAddressRow);
+ intent.putParcelableArrayListExtra(Insert.DATA, data);
+
+ return intent;
+ }
+
+ @SuppressWarnings("deprecation")
+ public static Notification createSimpleNotification(Context context, String title, String text, PendingIntent intent) {
+ Notification notif = new Notification.Builder(context)
+ .setContentTitle(title)
+ .setContentText(text)
+ .setContentIntent(intent)
+ .setSmallIcon(R.drawable.logo_linphone_57x57)
+ .setAutoCancel(true)
+ .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
+ .setWhen(System.currentTimeMillis()).getNotification();
+
+ return notif;
+ }
}
diff --git a/src/org/linphone/compatibility/ApiFivePlus.java b/src/org/linphone/compatibility/ApiFivePlus.java
index 7809702ca..b0c66f825 100644
--- a/src/org/linphone/compatibility/ApiFivePlus.java
+++ b/src/org/linphone/compatibility/ApiFivePlus.java
@@ -9,7 +9,6 @@ import java.util.Set;
import org.linphone.Contact;
import org.linphone.R;
import org.linphone.core.LinphoneAddress;
-import org.linphone.mediastream.Version;
import android.annotation.TargetApi;
import android.app.Activity;
@@ -18,7 +17,6 @@ import android.app.PendingIntent;
import android.content.ContentProviderOperation;
import android.content.ContentResolver;
import android.content.ContentUris;
-import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
@@ -32,12 +30,10 @@ import android.preference.Preference;
import android.provider.ContactsContract;
import android.provider.ContactsContract.CommonDataKinds;
import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.SipAddress;
import android.provider.ContactsContract.Contacts;
import android.provider.ContactsContract.Data;
-import android.provider.ContactsContract.Intents.Insert;
import android.text.ClipboardManager;
-import android.view.Display;
+import android.text.TextUtils;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
@@ -73,22 +69,9 @@ public class ApiFivePlus {
Intent intent = new Intent(Intent.ACTION_INSERT, Contacts.CONTENT_URI);
intent.putExtra(ContactsContract.Intents.Insert.NAME, displayName);
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- if (sipUri != null && sipUri.startsWith("sip:")) {
- sipUri = sipUri.substring(4);
- }
-
- ArrayList data = new ArrayList();
- ContentValues sipAddressRow = new ContentValues();
- sipAddressRow.put(Contacts.Data.MIMETYPE, SipAddress.CONTENT_ITEM_TYPE);
- sipAddressRow.put(SipAddress.SIP_ADDRESS, sipUri);
- data.add(sipAddressRow);
- intent.putParcelableArrayListExtra(Insert.DATA, data);
- } else {
- // VoIP field not available, we store the address in the IM field
- intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, sipUri);
- intent.putExtra(ContactsContract.Intents.Insert.IM_PROTOCOL, "sip");
- }
+ // VoIP field not available, we store the address in the IM field
+ intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, sipUri);
+ intent.putExtra(ContactsContract.Intents.Insert.IM_PROTOCOL, "sip");
return intent;
}
@@ -106,24 +89,13 @@ public class ApiFivePlus {
Uri contactUri = ContentUris.withAppendedId(Contacts.CONTENT_URI, id);
intent.setData(contactUri);
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- ArrayList data = new ArrayList();
- ContentValues sipAddressRow = new ContentValues();
- sipAddressRow.put(Contacts.Data.MIMETYPE, SipAddress.CONTENT_ITEM_TYPE);
- sipAddressRow.put(SipAddress.SIP_ADDRESS, sipUri);
- data.add(sipAddressRow);
- data.add(sipAddressRow);
- intent.putParcelableArrayListExtra(Insert.DATA, data);
- } else {
- // VoIP field not available, we store the address in the IM field
- intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, sipUri);
- intent.putExtra(ContactsContract.Intents.Insert.IM_PROTOCOL, "sip");
- }
+ // VoIP field not available, we store the address in the IM field
+ intent.putExtra(ContactsContract.Intents.Insert.IM_HANDLE, sipUri);
+ intent.putExtra(ContactsContract.Intents.Insert.IM_PROTOCOL, "sip");
return intent;
}
- @SuppressWarnings("resource")
public static List extractContactNumbersAndAddresses(String id, ContentResolver cr) {
List list = new ArrayList();
@@ -140,95 +112,71 @@ public class ApiFivePlus {
c.close();
}
- // SIP addresses
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- String selection = new StringBuilder()
- .append(Data.CONTACT_ID)
- .append(" = ? AND ")
- .append(Data.MIMETYPE)
- .append(" = '")
- .append(ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
- .append("'")
- .toString();
- projection = new String[] {ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS};
- c = cr.query(uri, projection, selection, new String[]{id}, null);
- if (c != null) {
- int nbId = c.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
- while (c.moveToNext()) {
- list.add("sip:" + c.getString(nbId));
- }
- c.close();
- }
- } else {
- String selection = new StringBuilder()
- .append(Data.CONTACT_ID).append(" = ? AND ")
- .append(Data.MIMETYPE).append(" = '")
- .append(ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
- .append("' AND lower(")
- .append(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL)
- .append(") = 'sip'")
- .toString();
- c = cr.query(uri, projection, selection, new String[]{id}, null);
- if (c != null) {
- int nbId = c.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA);
- while (c.moveToNext()) {
- list.add("sip:" + c.getString(nbId));
- }
- c.close();
+ // IM addresses
+ String selection = new StringBuilder()
+ .append(Data.CONTACT_ID).append(" = ? AND ")
+ .append(Data.MIMETYPE).append(" = '")
+ .append(ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
+ .append("' AND lower(")
+ .append(ContactsContract.CommonDataKinds.Im.CUSTOM_PROTOCOL)
+ .append(") = 'sip'")
+ .toString();
+ c = cr.query(uri, projection, selection, new String[]{id}, null);
+ if (c != null) {
+ int nbId = c.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA);
+ while (c.moveToNext()) {
+ list.add("sip:" + c.getString(nbId));
}
+ c.close();
}
return list;
}
- public static Cursor getContactsCursor(ContentResolver cr) {
+ public static Cursor getContactsCursor(ContentResolver cr, List ids) {
String req = Data.MIMETYPE + " = '" + CommonDataKinds.Phone.CONTENT_ITEM_TYPE
- + "' AND " + CommonDataKinds.Phone.NUMBER + " IS NOT NULL";
-
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- req += " OR (" + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
- + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL)";
- } else {
- req += " OR (" + Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.Im.CONTENT_ITEM_TYPE
- + "' AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip')";
- }
+ + "' AND " + CommonDataKinds.Phone.NUMBER + " IS NOT NULL";
+
+ req += " OR (" + Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.Im.CONTENT_ITEM_TYPE
+ + "' AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip')";
+
+ if(ids != null){
+ String s = TextUtils.join(",", ids);
+ req += " OR (" + Data.CONTACT_ID + " IN (" + s + "))";
+ }
+
+ return getGeneralContactCursor(cr, req, true);
+ }
+
+ public static Cursor getSIPContactsCursor(ContentResolver cr, List ids) {
+ String req = null;
+ req = Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.Im.CONTENT_ITEM_TYPE
+ + "' AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip'";
+
+ if(ids != null){
+ String s = TextUtils.join(",", ids);
+ req += " OR (" + Data.CONTACT_ID + " IN (" + s + "))";
+ }
return getGeneralContactCursor(cr, req, true);
}
- public static Cursor getSIPContactsCursor(ContentResolver cr) {
- String req = null;
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- req = Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
- + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL";
- } else {
- req = Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.Im.CONTENT_ITEM_TYPE
- + "' AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip'";
- }
-
- return getGeneralContactCursor(cr, req, true);
- }
-
private static Cursor getSIPContactCursor(ContentResolver cr, String id) {
String req = null;
- if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
- req = Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
- + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " LIKE '" + id + "'";
- } else {
- req = Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.Im.CONTENT_ITEM_TYPE
- + " AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip' AND "
- + android.provider.ContactsContract.CommonDataKinds.Im.DATA + " LIKE '" + id + "'";
- }
-
+ req = Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.Im.CONTENT_ITEM_TYPE
+ + " AND lower(" + CommonDataKinds.Im.CUSTOM_PROTOCOL + ") = 'sip' AND "
+ + android.provider.ContactsContract.CommonDataKinds.Im.DATA + " LIKE '" + id + "'";
+
return getGeneralContactCursor(cr, req, false);
}
- private static Cursor getGeneralContactCursor(ContentResolver cr, String select, boolean shouldGroupBy) {
-
+ public static Cursor getGeneralContactCursor(ContentResolver cr, String select, boolean shouldGroupBy) {
String[] projection = new String[] { Data.CONTACT_ID, Data.DISPLAY_NAME };
-
- String query = Data.DISPLAY_NAME + " IS NOT NULL AND (" + select + ")";
- Cursor cursor = cr.query(Data.CONTENT_URI, projection, query, null, Data.DISPLAY_NAME + " COLLATE NOCASE ASC");
+ String query;
+
+ query = Data.DISPLAY_NAME + " IS NOT NULL AND (" + select + ")";
+
+ Cursor cursor = cr.query(Data.CONTENT_URI, projection, query, null, " lower(" + Data.DISPLAY_NAME + ") COLLATE UNICODE ASC");
if (!shouldGroupBy || cursor == null) {
return cursor;
@@ -261,29 +209,34 @@ public class ApiFivePlus {
public static Contact getContact(ContentResolver cr, Cursor cursor, int position) {
try {
- cursor.moveToFirst();
- boolean success = cursor.move(position);
- if (!success)
+ if(cursor != null) {
+ cursor.moveToFirst();
+ boolean success = cursor.move(position);
+ if (!success)
+ return null;
+
+ String id = cursor.getString(cursor.getColumnIndex(Data.CONTACT_ID));
+ String name = getContactDisplayName(cursor);
+ Uri thumbnail = getContactPictureUri(id);
+ Uri photo = getContactPhotoUri(id);
+ InputStream input = getContactPictureInputStream(cr, id);
+
+ Contact contact;
+ if (input == null) {
+ contact = new Contact(id, name);
+ } else {
+ Bitmap bm = null;
+ try {
+ bm = BitmapFactory.decodeStream(input);
+ } catch (OutOfMemoryError oome) {
+ }
+ contact = new Contact(id, name, photo, thumbnail, bm);
+ }
+
+ return contact;
+ } else {
return null;
-
- String id = cursor.getString(cursor.getColumnIndex(Data.CONTACT_ID));
- String name = getContactDisplayName(cursor);
- Uri photo = getContactPictureUri(id);
- InputStream input = getContactPictureInputStream(cr, id);
-
- Contact contact;
- if (input == null) {
- contact = new Contact(id, name);
- }
- else {
- Bitmap bm = null;
- try {
- bm = BitmapFactory.decodeStream(input);
- } catch (OutOfMemoryError oome) {}
- contact = new Contact(id, name, photo, bm);
- }
-
- return contact;
+ }
} catch (Exception e) {
}
@@ -291,7 +244,7 @@ public class ApiFivePlus {
}
public static InputStream getContactPictureInputStream(ContentResolver cr, String id) {
- Uri person = getContactPictureUri(id);
+ Uri person = ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(id));
return Contacts.openContactPhotoInputStream(cr, person);
}
@@ -300,7 +253,13 @@ public class ApiFivePlus {
}
private static Uri getContactPictureUri(String id) {
- return ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(id));
+ Uri person = ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(id));
+ return Uri.withAppendedPath(person, Contacts.Photo.CONTENT_DIRECTORY);
+ }
+
+ private static Uri getContactPhotoUri(String id) {
+ Uri person = ContentUris.withAppendedId(Contacts.CONTENT_URI, Long.parseLong(id));
+ return Uri.withAppendedPath(person, Contacts.Photo.DISPLAY_PHOTO);
}
public static Uri findUriPictureOfContactAndSetDisplayName(LinphoneAddress address, ContentResolver cr) {
@@ -309,14 +268,15 @@ public class ApiFivePlus {
String sipUri = username + "@" + domain;
Cursor cursor = getSIPContactCursor(cr, sipUri);
- Contact contact = getContact(cr, cursor, 0);
- if (contact != null && contact.getNumerosOrAddresses().contains(sipUri)) {
- address.setDisplayName(contact.getName());
+ if(cursor != null) {
+ Contact contact = getContact(cr, cursor, 0);
+ if (contact != null && contact.getNumbersOrAddresses().contains(sipUri)) {
+ address.setDisplayName(contact.getName());
+ cursor.close();
+ return contact.getPhotoUri();
+ }
cursor.close();
- return contact.getPhotoUri();
}
-
- cursor.close();
return null;
}
@@ -327,15 +287,9 @@ public class ApiFivePlus {
cursor.close();
return contactDisplayName;
}
-
- cursor.close();
return null;
}
- public static int getRotation(Display display) {
- return display.getOrientation();
- }
-
public static Notification createMessageNotification(Context context, String title, String msg, PendingIntent intent) {
Notification notif = new Notification();
notif.icon = R.drawable.chat_icon_over;
@@ -365,10 +319,6 @@ public class ApiFivePlus {
return notif;
}
- public static void setNotificationLatestEventInfo(Notification notif, Context context, String title, String content, PendingIntent intent) {
- notif.setLatestEventInfo(context, title, content, intent);
- }
-
public static void setPreferenceChecked(Preference preference, boolean checked) {
((CheckBoxPreference) preference).setChecked(checked);
}
@@ -435,6 +385,36 @@ public class ApiFivePlus {
}
public static void setAudioManagerInCallMode(AudioManager manager) {
- manager.setMode(AudioManager.MODE_IN_CALL);
+ /* Do not use MODE_IN_CALL, because it is reserved to GSM. This is causing conflicts on audio system resulting in silenced audio.*/
+ //manager.setMode(AudioManager.MODE_IN_CALL);
+ }
+
+ public static Notification createNotification(Context context, String title, String message, int icon, int level, PendingIntent intent, boolean isOngoingEvent) {
+ Notification notif = new Notification();
+ notif.icon = icon;
+ notif.iconLevel = level;
+ notif.when = System.currentTimeMillis();
+ if (isOngoingEvent) {
+ notif.flags |= Notification.FLAG_ONGOING_EVENT;
+ }
+ notif.setLatestEventInfo(context, title, message, intent);
+
+ return notif;
+ }
+
+ public static Notification createSimpleNotification(Context context, String title, String text, PendingIntent intent) {
+ Notification notif = new Notification();
+ notif.icon = R.drawable.logo_linphone_57x57;
+ notif.iconLevel = 0;
+ notif.when = System.currentTimeMillis();
+ notif.flags &= Notification.FLAG_ONGOING_EVENT;
+
+ notif.defaults |= Notification.DEFAULT_VIBRATE;
+ notif.defaults |= Notification.DEFAULT_SOUND;
+ notif.defaults |= Notification.DEFAULT_LIGHTS;
+
+ notif.setLatestEventInfo(context, title, text, intent);
+
+ return notif;
}
}
diff --git a/src/org/linphone/compatibility/ApiFourteenPlus.java b/src/org/linphone/compatibility/ApiFourteenPlus.java
index 1c65fc8f2..f12d678b6 100644
--- a/src/org/linphone/compatibility/ApiFourteenPlus.java
+++ b/src/org/linphone/compatibility/ApiFourteenPlus.java
@@ -2,6 +2,7 @@ package org.linphone.compatibility;
import android.annotation.TargetApi;
import android.app.Activity;
+import android.media.AudioManager;
import android.preference.Preference;
import android.preference.TwoStatePreference;
import android.view.View;
@@ -45,4 +46,8 @@ public class ApiFourteenPlus {
public static void showNavigationBar(Activity activity) {
activity.getWindow().getDecorView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
+
+ public static String getAudioManagerEventForBluetoothConnectionStateChangedEvent() {
+ return AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED;
+ }
}
diff --git a/src/org/linphone/compatibility/ApiNinePlus.java b/src/org/linphone/compatibility/ApiNinePlus.java
index 1d462a313..1a586b42a 100644
--- a/src/org/linphone/compatibility/ApiNinePlus.java
+++ b/src/org/linphone/compatibility/ApiNinePlus.java
@@ -1,13 +1,25 @@
package org.linphone.compatibility;
import java.util.ArrayList;
+import java.util.List;
+import org.linphone.Contact;
+import org.linphone.LinphoneUtils;
import org.linphone.R;
+import org.linphone.core.LinphoneAddress;
import android.annotation.TargetApi;
import android.content.ContentProviderOperation;
+import android.content.ContentResolver;
import android.content.Context;
+import android.database.Cursor;
+import android.net.Uri;
import android.provider.ContactsContract;
+import android.provider.ContactsContract.CommonDataKinds;
+import android.provider.ContactsContract.Contacts;
+import android.provider.ContactsContract.CommonDataKinds.Phone;
+import android.provider.ContactsContract.Data;
+import android.text.TextUtils;
/*
ApiNinePlus.java
@@ -32,52 +44,238 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
@TargetApi(9)
public class ApiNinePlus {
-
+
public static void addSipAddressToContact(Context context, ArrayList ops, String sipAddress) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, sipAddress)
- .withValue(ContactsContract.CommonDataKinds.SipAddress.TYPE, ContactsContract.CommonDataKinds.SipAddress.TYPE_CUSTOM)
- .withValue(ContactsContract.CommonDataKinds.SipAddress.LABEL, context.getString(R.string.addressbook_label))
- .build()
- );
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+ .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.SipAddress.DATA, sipAddress)
+ .withValue(CommonDataKinds.SipAddress.TYPE, CommonDataKinds.SipAddress.TYPE_CUSTOM)
+ .withValue(CommonDataKinds.SipAddress.LABEL, context.getString(R.string.addressbook_label))
+ .build()
+ );
}
public static void addSipAddressToContact(Context context, ArrayList ops, String sipAddress, String rawContactID) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, sipAddress)
- .withValue(ContactsContract.CommonDataKinds.SipAddress.TYPE, ContactsContract.CommonDataKinds.SipAddress.TYPE_CUSTOM)
- .withValue(ContactsContract.CommonDataKinds.SipAddress.LABEL, context.getString(R.string.addressbook_label))
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactID)
+ .withValue(ContactsContract.Data.MIMETYPE, CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.SipAddress.DATA, sipAddress)
+ .withValue(CommonDataKinds.SipAddress.TYPE, CommonDataKinds.SipAddress.TYPE_CUSTOM)
+ .withValue(CommonDataKinds.SipAddress.LABEL, context.getString(R.string.addressbook_label))
.build()
);
}
public static void updateSipAddressForContact(ArrayList ops, String oldSipAddress, String newSipAddress, String contactID) {
- String select = ContactsContract.Data.CONTACT_ID + "=? AND "
- + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' AND "
- + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + "=?";
- String[] args = new String[] { String.valueOf(contactID), oldSipAddress };
+ String select = ContactsContract.Data.CONTACT_ID + "=? AND "
+ + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' AND "
+ + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + "=?";
+ String[] args = new String[] { String.valueOf(contactID), oldSipAddress };
ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(select, args)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, newSipAddress)
+ .withSelection(select, args)
+ .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS, newSipAddress)
.build()
);
}
public static void deleteSipAddressFromContact(ArrayList ops, String oldSipAddress, String contactID) {
- String select = ContactsContract.Data.CONTACT_ID + "=? AND "
- + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' AND "
- + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + "=?";
- String[] args = new String[] { String.valueOf(contactID), oldSipAddress };
+ String select = ContactsContract.Data.CONTACT_ID + "=? AND "
+ + ContactsContract.Data.MIMETYPE + "='" + ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE + "' AND "
+ + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + "=? ";
+ String[] args = new String[] { String.valueOf(contactID), oldSipAddress };
ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
.withSelection(select, args)
.build()
);
}
+
+ public static List extractContactNumbersAndAddresses(String id, ContentResolver cr) {
+ List list = new ArrayList();
+
+ Uri uri = Data.CONTENT_URI;
+ String[] projection;
+
+ // Phone Numbers
+ Cursor c = cr.query(Phone.CONTENT_URI, new String[] { Phone.NUMBER }, Phone.CONTACT_ID + " = " + id, null, null);
+ if (c != null) {
+ while (c.moveToNext()) {
+ String number = c.getString(c.getColumnIndex(Phone.NUMBER));
+ list.add(number);
+ }
+ c.close();
+ }
+
+ // SIP addresses
+ String selection2 = new StringBuilder()
+ .append(Data.CONTACT_ID)
+ .append(" = ? AND ")
+ .append(Data.MIMETYPE)
+ .append(" = '")
+ .append(ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE)
+ .append("'")
+ .toString();
+ projection = new String[] {ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS};
+ c = cr.query(uri, projection, selection2, new String[]{id}, null);
+ if (c != null) {
+ int nbid = c.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
+ while (c.moveToNext()) {
+ list.add("sip:" + c.getString(nbid));
+ }
+ c.close();
+ }
+
+ return list;
+ }
+
+ public static Cursor getContactsCursor(ContentResolver cr, String search, List ids) {
+ String req;
+ if(ids != null && ids.size() > 0) {
+ req = "(" + Data.MIMETYPE + " = '" + CommonDataKinds.Phone.CONTENT_ITEM_TYPE
+ + "' AND " + CommonDataKinds.Phone.NUMBER + " IS NOT NULL "
+ + " OR (" + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
+ + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL)"
+ + " OR (" + Data.CONTACT_ID + " IN (" + TextUtils.join(" , ", ids) + ")))";
+ } else {
+ req = "(" + Data.MIMETYPE + " = '" + CommonDataKinds.Phone.CONTENT_ITEM_TYPE
+ + "' AND " + CommonDataKinds.Phone.NUMBER + " IS NOT NULL "
+ + " OR (" + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
+ + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL))";
+ }
+
+ if (search != null) {
+ req += " AND " + Data.DISPLAY_NAME + " LIKE '%" + search + "%'";
+ }
+
+ return ApiFivePlus.getGeneralContactCursor(cr, req, true);
+ }
+
+ public static Cursor getSIPContactsCursor(ContentResolver cr, String search, List ids) {
+
+ String req = "(" + Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
+ + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " IS NOT NULL) ";
+
+ if(ids != null && ids.size() > 0) {
+ req += " OR (" + Data.CONTACT_ID + " IN (" + TextUtils.join(" , ", ids) + "))";
+ }
+
+ if (search != null) {
+ req += " AND " + Data.DISPLAY_NAME + " LIKE '%" + search + "%'";
+ }
+
+ return ApiFivePlus.getGeneralContactCursor(cr, req, true);
+ }
+
+ private static Cursor getSIPContactCursor(ContentResolver cr, String id) {
+ String req = null;
+ req = Contacts.Data.MIMETYPE + " = '" + CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE
+ + "' AND " + ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + " LIKE '" + id + "'";
+
+ return ApiFivePlus.getGeneralContactCursor(cr, req, false);
+ }
+
+ public static Uri findUriPictureOfContactAndSetDisplayName(LinphoneAddress address, ContentResolver cr) {
+ String username = address.getUserName();
+ String domain = address.getDomain();
+ String sipUri = username + "@" + domain;
+
+ Cursor cursor = getSIPContactCursor(cr, sipUri);
+ Contact contact = ApiFivePlus.getContact(cr, cursor, 0);
+ if (contact != null && contact.getNumbersOrAddresses().contains(sipUri)) {
+ address.setDisplayName(contact.getName());
+ cursor.close();
+ return contact.getPhotoUri();
+ }
+
+ cursor.close();
+ return null;
+ }
+
+ //Linphone Contacts Tag
+ public static void addLinphoneContactTag(Context context, ArrayList ops, String newAddress, String rawContactId){
+ if(rawContactId != null) {
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValue(ContactsContract.Data.RAW_CONTACT_ID, rawContactId)
+ .withValue(ContactsContract.Data.MIMETYPE, context.getString(R.string.sync_mimetype))
+ .withValue(ContactsContract.Data.DATA1, newAddress)
+ .withValue(ContactsContract.Data.DATA2, context.getString(R.string.app_name))
+ .withValue(ContactsContract.Data.DATA3, newAddress)
+ .build()
+ );
+ }
+ }
+ public static void updateLinphoneContactTag(Context context, ArrayList ops, String newAddress, String oldAddress, String rawContactId){
+ if(rawContactId != null) {
+ ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
+ .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " + ContactsContract.Data.DATA1 + "=? ", new String[]{rawContactId, oldAddress})
+ .withValue(ContactsContract.Data.DATA1, newAddress)
+ .withValue(ContactsContract.Data.DATA2, context.getString(R.string.app_name))
+ .withValue(ContactsContract.Data.DATA3, newAddress)
+ .build());
+ }
+ }
+
+ public static void deleteLinphoneContactTag(ArrayList ops , String oldAddress, String rawContactId){
+ if(rawContactId != null) {
+ String select = ContactsContract.Data.RAW_CONTACT_ID + "=? AND "
+ + ContactsContract.Data.DATA1 + "= ?";
+ String[] args = new String[]{rawContactId, oldAddress};
+
+ ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
+ .withSelection(select, args)
+ .build());
+ }
+ }
+
+ public static void createLinphoneContactTag(Context context, ContentResolver contentResolver, Contact contact, String rawContactId){
+ ArrayList ops = new ArrayList();
+
+ if (contact != null) {
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
+ .withValue(ContactsContract.RawContacts.AGGREGATION_MODE, ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
+ .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, context.getString(R.string.sync_account_type))
+ .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, context.getString(R.string.sync_account_name))
+ .build()
+ );
+
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+ .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
+ .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, contact.getName())
+ .build()
+ );
+
+ List numbersOrAddresses = contact.getNumbersOrAddresses();
+ for (String numberOrAddress : numbersOrAddresses) {
+ if (LinphoneUtils.isSipAddress(numberOrAddress)) {
+ if (numberOrAddress.startsWith("sip:")){
+ numberOrAddress = numberOrAddress.substring(4);
+ }
+
+ ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
+ .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
+ .withValue(ContactsContract.Data.MIMETYPE, context.getString(R.string.sync_mimetype))
+ .withValue(ContactsContract.Data.DATA1, numberOrAddress)
+ .withValue(ContactsContract.Data.DATA2, context.getString(R.string.app_name))
+ .withValue(ContactsContract.Data.DATA3, numberOrAddress)
+ .build()
+ );
+ }
+ }
+
+ ops.add(ContentProviderOperation.newUpdate(ContactsContract.AggregationExceptions.CONTENT_URI)
+ .withValue(ContactsContract.AggregationExceptions.TYPE, ContactsContract.AggregationExceptions.TYPE_KEEP_TOGETHER)
+ .withValue(ContactsContract.AggregationExceptions.RAW_CONTACT_ID1, rawContactId)
+ .withValueBackReference(ContactsContract.AggregationExceptions.RAW_CONTACT_ID2, 0).build());
+
+ try {
+ contentResolver.applyBatch(ContactsContract.AUTHORITY, ops);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ }
}
diff --git a/src/org/linphone/compatibility/ApiSixteenPlus.java b/src/org/linphone/compatibility/ApiSixteenPlus.java
index ec83e5928..dba56077c 100644
--- a/src/org/linphone/compatibility/ApiSixteenPlus.java
+++ b/src/org/linphone/compatibility/ApiSixteenPlus.java
@@ -36,30 +36,27 @@ public class ApiSixteenPlus {
public static Notification createMessageNotification(Context context,
int msgCount, String msgSender, String msg, Bitmap contactIcon,
PendingIntent intent) {
- String title, summary;
+ String title;
if (msgCount == 1) {
- title = "Unread message from %s".replace("%s", msgSender);
- summary = "";
+ title = msgSender;
} else {
- title = "%i unread messages"
+ title = context.getString(R.string.unread_messages)
.replace("%i", String.valueOf(msgCount));
- summary = "";
}
- Notification notif = new Notification.BigPictureStyle(
- new Notification.Builder(context)
+ Notification notif = new Notification.Builder(context)
.setContentTitle(title)
.setContentText(msg)
.setSmallIcon(R.drawable.chat_icon_over)
.setAutoCancel(true)
+ .setContentIntent(intent)
.setDefaults(
Notification.DEFAULT_LIGHTS
| Notification.DEFAULT_SOUND
| Notification.DEFAULT_VIBRATE)
.setWhen(System.currentTimeMillis())
- .setLargeIcon(contactIcon)).setSummaryText(summary)
+ .setLargeIcon(contactIcon)
.build();
- notif.contentIntent = intent;
return notif;
}
@@ -68,18 +65,62 @@ public class ApiSixteenPlus {
String title, String msg, int iconID, Bitmap contactIcon,
String contactName, PendingIntent intent) {
- Notification notif = new Notification.BigPictureStyle(
- new Notification.Builder(context).setContentTitle(contactName)
+ Notification notif = new Notification.Builder(context).setContentTitle(contactName)
.setContentText(msg).setSmallIcon(iconID)
.setAutoCancel(false)
+ .setContentIntent(intent)
.setWhen(System.currentTimeMillis())
- .setLargeIcon(contactIcon)).build();
- notif.contentIntent = intent;
-
+ .setLargeIcon(contactIcon).build();
+ notif.flags |= Notification.FLAG_ONGOING_EVENT;
+
+ return notif;
+ }
+
+ public static Notification createNotification(Context context, String title, String message, int icon, int level, Bitmap largeIcon, PendingIntent intent, boolean isOngoingEvent,int priority) {
+ Notification notif;
+
+ if (largeIcon != null) {
+ notif = new Notification.Builder(context)
+ .setContentTitle(title)
+ .setContentText(message)
+ .setSmallIcon(icon, level)
+ .setLargeIcon(largeIcon)
+ .setContentIntent(intent)
+ .setWhen(System.currentTimeMillis())
+ .setPriority(priority)
+ .build();
+ } else {
+ notif = new Notification.Builder(context)
+ .setContentTitle(title)
+ .setContentText(message)
+ .setSmallIcon(icon, level)
+ .setContentIntent(intent)
+ .setWhen(System.currentTimeMillis())
+ .setPriority(priority)
+ .build();
+ }
+ if (isOngoingEvent) {
+ notif.flags |= Notification.FLAG_ONGOING_EVENT;
+ }
+
return notif;
}
public static void removeGlobalLayoutListener(ViewTreeObserver viewTreeObserver, OnGlobalLayoutListener keyboardListener) {
viewTreeObserver.removeOnGlobalLayoutListener(keyboardListener);
}
+
+ public static Notification createSimpleNotification(Context context, String title, String text, PendingIntent intent) {
+ Notification notif = new Notification.Builder(context)
+ .setContentTitle(title)
+ .setContentText(text)
+ .setSmallIcon(R.drawable.logo_linphone_57x57)
+ .setAutoCancel(true)
+ .setContentIntent(intent)
+ .setDefaults(Notification.DEFAULT_LIGHTS | Notification.DEFAULT_SOUND | Notification.DEFAULT_VIBRATE)
+ .setWhen(System.currentTimeMillis())
+ .build();
+
+ return notif;
+ }
}
diff --git a/src/org/linphone/compatibility/ApiTwentyOnePlus.java b/src/org/linphone/compatibility/ApiTwentyOnePlus.java
new file mode 100644
index 000000000..c47fe007b
--- /dev/null
+++ b/src/org/linphone/compatibility/ApiTwentyOnePlus.java
@@ -0,0 +1,129 @@
+package org.linphone.compatibility;
+
+import org.linphone.R;
+
+import android.annotation.TargetApi;
+import android.app.Notification;
+import android.app.PendingIntent;
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.support.v4.app.NotificationCompat;
+import android.view.ViewTreeObserver;
+import android.view.ViewTreeObserver.OnGlobalLayoutListener;
+/*
+ApiTwentyOnePlus.java
+Copyright (C) 2012 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+/**
+ * @author Sylvain Berfini
+ */
+@TargetApi(21)
+public class ApiTwentyOnePlus {
+
+ public static Notification createMessageNotification(Context context,
+ int msgCount, String msgSender, String msg, Bitmap contactIcon,
+ PendingIntent intent) {
+ String title;
+ if (msgCount == 1) {
+ title = msgSender;
+ } else {
+ title = context.getString(R.string.unread_messages).replace("%i", String.valueOf(msgCount));
+ }
+
+ Notification notif = new NotificationCompat.Builder(context)
+ .setContentTitle(title)
+ .setContentText(msg)
+ .setSmallIcon(R.drawable.chat_icon_over)
+ .setAutoCancel(true)
+ .setContentIntent(intent)
+ .setDefaults(Notification.DEFAULT_ALL)
+ .setLargeIcon(contactIcon)
+ .setCategory(Notification.CATEGORY_MESSAGE)
+ .setVisibility(Notification.VISIBILITY_PRIVATE)
+ .setPriority(Notification.PRIORITY_HIGH)
+ .build();
+
+ return notif;
+ }
+
+ public static Notification createInCallNotification(Context context,
+ String title, String msg, int iconID, Bitmap contactIcon,
+ String contactName, PendingIntent intent) {
+
+ Notification notif = new NotificationCompat.Builder(context).setContentTitle(contactName)
+ .setContentText(msg)
+ .setSmallIcon(iconID)
+ .setAutoCancel(false)
+ .setContentIntent(intent)
+ .setLargeIcon(contactIcon)
+ .setCategory(Notification.CATEGORY_CALL)
+ .setVisibility(Notification.VISIBILITY_PUBLIC)
+ .setPriority(Notification.PRIORITY_HIGH)
+ .build();
+
+ return notif;
+ }
+
+ public static Notification createNotification(Context context, String title, String message, int icon, int level, Bitmap largeIcon, PendingIntent intent, boolean isOngoingEvent,int priority) {
+ Notification notif;
+
+ if (largeIcon != null) {
+ notif = new NotificationCompat.Builder(context)
+ .setContentTitle(title)
+ .setContentText(message)
+ .setSmallIcon(icon, level)
+ .setLargeIcon(largeIcon)
+ .setContentIntent(intent)
+ .setCategory(Notification.CATEGORY_SERVICE)
+ .setVisibility(Notification.VISIBILITY_SECRET)
+ .setPriority(priority)
+ .build();
+ } else {
+ notif = new NotificationCompat.Builder(context)
+ .setContentTitle(title)
+ .setContentText(message)
+ .setSmallIcon(icon, level)
+ .setContentIntent(intent)
+ .setCategory(Notification.CATEGORY_SERVICE)
+ .setVisibility(Notification.VISIBILITY_SECRET)
+ .setPriority(priority)
+ .build();
+ }
+
+ return notif;
+ }
+
+ public static void removeGlobalLayoutListener(ViewTreeObserver viewTreeObserver, OnGlobalLayoutListener keyboardListener) {
+ viewTreeObserver.removeOnGlobalLayoutListener(keyboardListener);
+ }
+
+ public static Notification createSimpleNotification(Context context, String title, String text, PendingIntent intent) {
+ Notification notif = new NotificationCompat.Builder(context)
+ .setContentTitle(title)
+ .setContentText(text)
+ .setSmallIcon(R.drawable.logo_linphone_57x57)
+ .setAutoCancel(true)
+ .setContentIntent(intent)
+ .setDefaults(Notification.DEFAULT_ALL)
+ .setCategory(Notification.CATEGORY_MESSAGE)
+ .setVisibility(Notification.VISIBILITY_PRIVATE)
+ .setPriority(Notification.PRIORITY_HIGH)
+ .build();
+
+ return notif;
+ }
+}
diff --git a/src/org/linphone/compatibility/Compatibility.java b/src/org/linphone/compatibility/Compatibility.java
index 45cf16173..2e8bd3afb 100644
--- a/src/org/linphone/compatibility/Compatibility.java
+++ b/src/org/linphone/compatibility/Compatibility.java
@@ -37,7 +37,6 @@ import android.graphics.Bitmap;
import android.media.AudioManager;
import android.net.Uri;
import android.preference.Preference;
-import android.view.Display;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
/**
@@ -51,10 +50,11 @@ public class Compatibility {
}
public static Intent prepareAddContactIntent(String displayName, String sipUri) {
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
+ if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
+ return ApiElevenPlus.prepareAddContactIntent(displayName, sipUri);
+ } else {
return ApiFivePlus.prepareAddContactIntent(displayName, sipUri);
}
- return null;
}
public static Intent prepareEditContactIntent(int id) {
@@ -65,31 +65,63 @@ public class Compatibility {
}
public static Intent prepareEditContactIntentWithSipAddress(int id, String sipAddress) {
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
- return ApiFivePlus.prepareEditContactIntentWithSipAddress(id, sipAddress);
+ if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
+ return ApiElevenPlus.prepareEditContactIntentWithSipAddress(id, sipAddress);
+ } else {
+ return ApiFivePlus.prepareEditContactIntent(id);
}
- return null;
}
public static List extractContactNumbersAndAddresses(String id, ContentResolver cr) {
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ return ApiNinePlus.extractContactNumbersAndAddresses(id, cr);
+ } else {
return ApiFivePlus.extractContactNumbersAndAddresses(id, cr);
}
- return null;
+ }
+
+ public static List extractContactImAddresses(String id, ContentResolver cr) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ return ApiFivePlus.extractContactNumbersAndAddresses(id, cr);
+ } else {
+ return null;
+ }
}
- public static Cursor getContactsCursor(ContentResolver cr) {
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
- return ApiFivePlus.getContactsCursor(cr);
+ public static Cursor getContactsCursor(ContentResolver cr, List contactsId) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ return ApiNinePlus.getContactsCursor(cr, null, contactsId);
+ } else {
+ return ApiFivePlus.getContactsCursor(cr, contactsId);
}
- return null;
}
- public static Cursor getSIPContactsCursor(ContentResolver cr) {
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
- return ApiFivePlus.getSIPContactsCursor(cr);
+ public static Cursor getContactsCursor(ContentResolver cr, String search, List contactsId) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ return ApiNinePlus.getContactsCursor(cr, search, contactsId);
+ } else {
+ return ApiFivePlus.getContactsCursor(cr, contactsId);
}
- return null;
+ }
+
+ public static Cursor getSIPContactsCursor(ContentResolver cr, List contactsId) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ return ApiNinePlus.getSIPContactsCursor(cr, null, contactsId);
+ } else {
+ return ApiFivePlus.getSIPContactsCursor(cr, contactsId);
+ }
+ }
+
+ public static Cursor getSIPContactsCursor(ContentResolver cr, String search, List contactsId) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ return ApiNinePlus.getSIPContactsCursor(cr, search, contactsId);
+ } else {
+ return ApiFivePlus.getSIPContactsCursor(cr, contactsId);
+ }
+ }
+
+ public static Cursor getImContactsCursor(ContentResolver cr) {
+ return ApiFivePlus.getSIPContactsCursor(cr,null);
}
public static int getCursorDisplayNameColumnIndex(Cursor cursor) {
@@ -114,10 +146,26 @@ public class Compatibility {
}
public static Uri findUriPictureOfContactAndSetDisplayName(LinphoneAddress address, ContentResolver cr) {
- if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ return ApiNinePlus.findUriPictureOfContactAndSetDisplayName(address, cr);
+ } else {
return ApiFivePlus.findUriPictureOfContactAndSetDisplayName(address, cr);
}
- return null;
+ }
+
+ public static Notification createSimpleNotification(Context context, String title, String text, PendingIntent intent) {
+ Notification notif = null;
+
+ if (Version.sdkAboveOrEqual(Version.API21_LOLLIPOP_50)) {
+ return ApiTwentyOnePlus.createSimpleNotification(context, title, text, intent);
+ } else if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
+ notif = ApiSixteenPlus.createSimpleNotification(context, title, text, intent);
+ } else if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
+ notif = ApiElevenPlus.createSimpleNotification(context, title, text, intent);
+ } else {
+ notif = ApiFivePlus.createSimpleNotification(context, title, text, intent);
+ }
+ return notif;
}
public static Notification createMessageNotification(Context context, int msgCount, String msgSender, String msg, Bitmap contactIcon, PendingIntent intent) {
@@ -129,7 +177,9 @@ public class Compatibility {
title = "%i unread messages".replace("%i", String.valueOf(msgCount));
}
- if (Version.sdkAboveOrEqual(16)) {
+ if (Version.sdkAboveOrEqual(Version.API21_LOLLIPOP_50)) {
+ return ApiTwentyOnePlus.createMessageNotification(context, msgCount, msgSender, msg, contactIcon, intent);
+ } else if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
notif = ApiSixteenPlus.createMessageNotification(context, msgCount, msgSender, msg, contactIcon, intent);
} else if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
notif = ApiElevenPlus.createMessageNotification(context, msgCount, msgSender, msg, contactIcon, intent);
@@ -142,7 +192,9 @@ public class Compatibility {
public static Notification createInCallNotification(Context context, String title, String msg, int iconID, Bitmap contactIcon, String contactName, PendingIntent intent) {
Notification notif = null;
- if (Version.sdkAboveOrEqual(16)) {
+ if (Version.sdkAboveOrEqual(Version.API21_LOLLIPOP_50)) {
+ return ApiTwentyOnePlus.createInCallNotification(context, title, msg, iconID, contactIcon, contactName, intent);
+ } else if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
notif = ApiSixteenPlus.createInCallNotification(context, title, msg, iconID, contactIcon, contactName, intent);
} else if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
notif = ApiElevenPlus.createInCallNotification(context, title, msg, iconID, contactIcon, contactName, intent);
@@ -152,6 +204,18 @@ public class Compatibility {
return notif;
}
+ public static Notification createNotification(Context context, String title, String message, int icon, int iconLevel, Bitmap largeIcon, PendingIntent intent, boolean isOngoingEvent,int priority) {
+ if (Version.sdkAboveOrEqual(Version.API21_LOLLIPOP_50)) {
+ return ApiTwentyOnePlus.createNotification(context, title, message, icon, iconLevel, largeIcon, intent, isOngoingEvent,priority);
+ } else if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
+ return ApiSixteenPlus.createNotification(context, title, message, icon, iconLevel, largeIcon, intent, isOngoingEvent,priority);
+ } else if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
+ return ApiElevenPlus.createNotification(context, title, message, icon, iconLevel, largeIcon, intent, isOngoingEvent);
+ } else {
+ return ApiFivePlus.createNotification(context, title, message, icon, iconLevel, intent, isOngoingEvent);
+ }
+ }
+
public static String refreshContactName(ContentResolver cr, String id) {
if (Version.sdkAboveOrEqual(Version.API05_ECLAIR_20)) {
return ApiFivePlus.refreshContactName(cr, id);
@@ -159,22 +223,6 @@ public class Compatibility {
return null;
}
- public static int getRotation(Display display) {
- if (Version.sdkStrictlyBelow(Version.API08_FROYO_22)) {
- return ApiFivePlus.getRotation(display);
- } else {
- return ApiEightPlus.getRotation(display);
- }
- }
-
- public static void setNotificationLatestEventInfo(Notification notif, Context context, String title, String content, PendingIntent intent) {
- if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
- ApiElevenPlus.setNotificationLatestEventInfo(notif, context, title, content, intent);
- } else {
- ApiFivePlus.setNotificationLatestEventInfo(notif, context, title, content, intent);
- }
- }
-
public static CompatibilityScaleGestureDetector getScaleGestureDetector(Context context, CompatibilityScaleGestureListener listener) {
if (Version.sdkAboveOrEqual(Version.API08_FROYO_22)) {
CompatibilityScaleGestureDetector csgd = new CompatibilityScaleGestureDetector(context);
@@ -246,7 +294,36 @@ public class Compatibility {
ApiFivePlus.deleteSipAddressFromContact(ops, oldSipAddress, contactID);
}
}
-
+
+ public static void deleteImAddressFromContact(ArrayList ops, String oldSipAddress, String contactID) {
+ ApiFivePlus.deleteSipAddressFromContact(ops, oldSipAddress, contactID);
+ }
+
+ //Linphone Contacts Tag
+ public static void addLinphoneContactTag(Context context, ArrayList ops, String newSipAddress, String rawContactId) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ ApiNinePlus.addLinphoneContactTag(context, ops, newSipAddress, rawContactId);
+ }
+ }
+
+ public static void updateLinphoneContactTag(Context context, ArrayList ops, String newSipAddress, String oldSipAddress, String rawContactId) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ ApiNinePlus.updateLinphoneContactTag(context, ops, newSipAddress, oldSipAddress, rawContactId);
+ }
+ }
+
+ public static void deleteLinphoneContactTag(ArrayList ops, String oldSipAddress, String rawContactId) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ ApiNinePlus.deleteLinphoneContactTag(ops, oldSipAddress, rawContactId);
+ }
+ }
+
+ public static void createLinphoneContactTag(Context context, ContentResolver contentResolver, Contact contact, String rawContactId) {
+ if (Version.sdkAboveOrEqual(Version.API09_GINGERBREAD_23)) {
+ ApiNinePlus.createLinphoneContactTag(context, contentResolver, contact, rawContactId);
+ }
+ }
+ //End of Linphone Contact Tag
public static void removeGlobalLayoutListener(ViewTreeObserver viewTreeObserver, OnGlobalLayoutListener keyboardListener) {
if (Version.sdkAboveOrEqual(Version.API16_JELLY_BEAN_41)) {
@@ -277,4 +354,12 @@ public class Compatibility {
ApiFivePlus.setAudioManagerInCallMode(manager);
}
}
+
+ public static String getAudioManagerEventForBluetoothConnectionStateChangedEvent() {
+ if (Version.sdkAboveOrEqual(Version.API14_ICE_CREAM_SANDWICH_40)) {
+ return ApiFourteenPlus.getAudioManagerEventForBluetoothConnectionStateChangedEvent();
+ } else {
+ return ApiEightPlus.getAudioManagerEventForBluetoothConnectionStateChangedEvent();
+ }
+ }
}
diff --git a/src/org/linphone/gcm/GCMService.java b/src/org/linphone/gcm/GCMService.java
index 5ca6d11be..59906ef77 100644
--- a/src/org/linphone/gcm/GCMService.java
+++ b/src/org/linphone/gcm/GCMService.java
@@ -18,15 +18,17 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+import static android.content.Intent.ACTION_MAIN;
+
import org.linphone.LinphoneManager;
+import org.linphone.LinphonePreferences;
+import org.linphone.LinphoneService;
import org.linphone.R;
-import org.linphone.core.LinphoneCoreException;
+import org.linphone.UIThreadDispatcher;
import org.linphone.mediastream.Log;
import android.content.Context;
import android.content.Intent;
-import android.content.SharedPreferences;
-import android.preference.PreferenceManager;
import com.google.android.gcm.GCMBaseIntentService;
@@ -48,36 +50,32 @@ public class GCMService extends GCMBaseIntentService {
@Override
protected void onMessage(Context context, Intent intent) {
Log.d("Push notification received");
- if (LinphoneManager.isInstanciated()) {
- LinphoneManager.getLc().setNetworkReachable(false);
- LinphoneManager.getLc().setNetworkReachable(true);
+ if (!LinphoneService.isReady()) {
+ startService(new Intent(ACTION_MAIN).setClass(this, LinphoneService.class));
+ } else if (LinphoneManager.isInstanciated() && LinphoneManager.getLc().getCallsNb() == 0) {
+ UIThreadDispatcher.dispatch(new Runnable(){
+ @Override
+ public void run() {
+ if (LinphoneManager.isInstanciated() && LinphoneManager.getLc().getCallsNb() == 0){
+ LinphoneManager.getLc().setNetworkReachable(false);
+ LinphoneManager.getLc().setNetworkReachable(true);
+ }
+ }
+ });
+
}
}
@Override
protected void onRegistered(Context context, String regId) {
Log.d("Registered push notification : " + regId);
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString(context.getString(R.string.push_reg_id_key), regId);
- editor.commit();
-
- if (LinphoneManager.isInstanciated()) {
- try {
- LinphoneManager.getInstance().initAccounts();
- } catch (LinphoneCoreException e) {
- e.printStackTrace();
- }
- }
+ LinphonePreferences.instance().setPushNotificationRegistrationID(regId);
}
@Override
protected void onUnregistered(Context context, String regId) {
Log.w("Unregistered push notification : " + regId);
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
- SharedPreferences.Editor editor = prefs.edit();
- editor.putString(context.getString(R.string.push_reg_id_key), null);
- editor.commit();
+ LinphonePreferences.instance().setPushNotificationRegistrationID(null);
}
protected String[] getSenderIds(Context context) {
diff --git a/src/org/linphone/setup/EchoCancellerCalibrationFragment.java b/src/org/linphone/setup/EchoCancellerCalibrationFragment.java
index 50cccb09e..a347a5f3e 100644
--- a/src/org/linphone/setup/EchoCancellerCalibrationFragment.java
+++ b/src/org/linphone/setup/EchoCancellerCalibrationFragment.java
@@ -22,19 +22,17 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
import java.net.URL;
import org.linphone.LinphoneManager;
-import org.linphone.LinphoneManager.EcCalibrationListener;
-import org.linphone.LinphoneService;
+import org.linphone.LinphonePreferences;
import org.linphone.R;
import org.linphone.core.LinphoneCore.EcCalibratorStatus;
+import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCoreException;
+import org.linphone.core.LinphoneCoreListenerBase;
import org.linphone.mediastream.Log;
-import android.content.Context;
-import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
-import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
@@ -47,43 +45,43 @@ import de.timroes.axmlrpc.XMLRPCServerException;
/**
* @author Ghislain MARY
*/
-public class EchoCancellerCalibrationFragment extends Fragment implements EcCalibrationListener {
+public class EchoCancellerCalibrationFragment extends Fragment {
private Handler mHandler = new Handler();
private boolean mSendEcCalibrationResult = false;
+ private LinphoneCoreListenerBase mListener;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.setup_ec_calibration, container, false);
+
+ mListener = new LinphoneCoreListenerBase(){
+ @Override
+ public void ecCalibrationStatus(LinphoneCore lc,LinphoneCore.EcCalibratorStatus status, int delay_ms, Object data) {
+ LinphoneManager.getInstance().routeAudioToReceiver();
+
+ if (status == EcCalibratorStatus.DoneNoEcho) {
+ LinphonePreferences.instance().setEchoCancellation(false);
+ } else if ((status == EcCalibratorStatus.Done) || (status == EcCalibratorStatus.Failed)) {
+ LinphonePreferences.instance().setEchoCancellation(true);
+ }
+ if (mSendEcCalibrationResult) {
+ sendEcCalibrationResult(status, delay_ms);
+ } else {
+ SetupActivity.instance().isEchoCalibrationFinished();
+ }
+ }
+ };
try {
- LinphoneManager.getInstance().startEcCalibration(this);
+ LinphoneManager.getInstance().startEcCalibration(mListener);
} catch (LinphoneCoreException e) {
Log.e(e, "Unable to calibrate EC");
}
-
return view;
}
- @Override
- public void onEcCalibrationStatus(EcCalibratorStatus status, int delayMs) {
- SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(SetupActivity.instance());
- SharedPreferences.Editor editor = prefs.edit();
-
- Context context = SetupActivity.instance() == null ? LinphoneService.instance().getApplicationContext() : SetupActivity.instance();
-
- if (status == EcCalibratorStatus.DoneNoEcho) {
- editor.putBoolean(context.getString(R.string.pref_echo_cancellation_key), false);
- } else if ((status == EcCalibratorStatus.Done) || (status == EcCalibratorStatus.Failed)) {
- editor.putBoolean(context.getString(R.string.pref_echo_cancellation_key), true);
- }
- editor.commit();
- if (mSendEcCalibrationResult) {
- sendEcCalibrationResult(status, delayMs);
- } else {
- SetupActivity.instance().isEchoCalibrationFinished();
- }
- }
+
public void enableEcCalibrationResultSending(boolean enabled) {
mSendEcCalibrationResult = enabled;
diff --git a/src/org/linphone/setup/MenuFragment.java b/src/org/linphone/setup/MenuFragment.java
index c5242ee3b..5eebba12c 100644
--- a/src/org/linphone/setup/MenuFragment.java
+++ b/src/org/linphone/setup/MenuFragment.java
@@ -30,7 +30,7 @@ import android.widget.ImageView;
* @author Sylvain Berfini
*/
public class MenuFragment extends Fragment implements OnClickListener {
- private ImageView createAccount, logLinphoneAccount, logGenericAccount;
+ private ImageView createAccount, logLinphoneAccount, logGenericAccount, remoteProvisioning;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
@@ -54,6 +54,13 @@ public class MenuFragment extends Fragment implements OnClickListener {
logGenericAccount.setOnClickListener(this);
}
+ remoteProvisioning = (ImageView) view.findViewById(R.id.setup_remote_provisioning);
+ if (getResources().getBoolean(R.bool.hide_remote_provisioning_in_wizard)) {
+ view.findViewById(R.id.setup_remote_provisioning_layout).setVisibility(View.GONE);
+ } else {
+ remoteProvisioning.setOnClickListener(this);
+ }
+
return view;
}
@@ -67,6 +74,8 @@ public class MenuFragment extends Fragment implements OnClickListener {
SetupActivity.instance().displayLoginLinphone();
} else if (id == R.id.setup_create_account) {
SetupActivity.instance().displayWizard();
+ } else if (id == R.id.setup_remote_provisioning) {
+ SetupActivity.instance().displayRemoteProvisioning();
}
}
}
diff --git a/src/org/linphone/setup/RemoteProvisioningActivity.java b/src/org/linphone/setup/RemoteProvisioningActivity.java
new file mode 100644
index 000000000..9a22a05b2
--- /dev/null
+++ b/src/org/linphone/setup/RemoteProvisioningActivity.java
@@ -0,0 +1,204 @@
+package org.linphone.setup;
+/*
+RemoteProvisioningActivity.java
+Copyright (C) 2014 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import static android.content.Intent.ACTION_MAIN;
+
+import java.io.UnsupportedEncodingException;
+import java.net.URLDecoder;
+
+import org.linphone.LinphoneActivity;
+import org.linphone.LinphoneLauncherActivity;
+import org.linphone.LinphoneManager;
+import org.linphone.LinphonePreferences;
+import org.linphone.LinphoneService;
+import org.linphone.R;
+import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneCore.RemoteProvisioningState;
+import org.linphone.core.LinphoneCoreListenerBase;
+import org.linphone.mediastream.Log;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.View;
+import android.widget.ProgressBar;
+import android.widget.Toast;
+
+/**
+ * @author Sylvain Berfini
+ */
+public class RemoteProvisioningActivity extends Activity {
+ private Handler mHandler = new Handler();
+ private String configUriParam = null;
+ private ProgressBar spinner;
+ private LinphoneCoreListenerBase mListener;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.remote_provisioning);
+ spinner = (ProgressBar) findViewById(R.id.spinner);
+
+ mListener = new LinphoneCoreListenerBase(){
+ @Override
+ public void configuringStatus(LinphoneCore lc, final RemoteProvisioningState state, String message) {
+ if (spinner != null) spinner.setVisibility(View.GONE);
+ if (state == RemoteProvisioningState.ConfiguringSuccessful) {
+ goToLinphoneActivity();
+ } else if (state == RemoteProvisioningState.ConfiguringFailed) {
+ Toast.makeText(RemoteProvisioningActivity.this, R.string.remote_provisioning_failure, Toast.LENGTH_LONG).show();
+ }
+ }
+ };
+ }
+
+ @Override
+ protected void onResume() {
+ super.onResume();
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.addListener(mListener);
+ }
+ LinphonePreferences.instance().setContext(this);
+
+ checkIntentForConfigUri(getIntent());
+ }
+
+ @Override
+ protected void onPause() {
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.removeListener(mListener);
+ }
+ super.onPause();
+ }
+
+ @Override
+ protected void onNewIntent(Intent intent) {
+ super.onNewIntent(intent);
+ checkIntentForConfigUri(intent);
+ }
+
+ private void checkIntentForConfigUri(final Intent intent) {
+ new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ Uri openUri = intent.getData();
+ if (openUri != null) {
+ // We expect something like linphone-config://http://linphone.org/config.xml
+ configUriParam = openUri.getEncodedSchemeSpecificPart().substring(2); // Removes the linphone-config://
+ try {
+ configUriParam = URLDecoder.decode(configUriParam, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ Log.e(e);
+ }
+ Log.d("Using config uri: " + configUriParam);
+ }
+
+ if (configUriParam == null) {
+ if (!LinphonePreferences.instance().isFirstRemoteProvisioning()) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ goToLinphoneActivity();
+ }
+ });
+ } else if (!getResources().getBoolean(R.bool.forbid_app_usage_until_remote_provisioning_completed)) {
+ // Show this view for a few seconds then go to the dialer
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ goToLinphoneActivity();
+ }
+ }, 1500);
+ } // else we do nothing if there is no config uri parameter and if user not allowed to leave this screen
+ } else {
+ if (getResources().getBoolean(R.bool.display_confirmation_popup_after_first_configuration)
+ && !LinphonePreferences.instance().isFirstRemoteProvisioning()) {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ displayDialogConfirmation();
+ }
+ });
+ } else {
+ mHandler.post(new Runnable() {
+ @Override
+ public void run() {
+ setRemoteProvisioningAddressAndRestart(configUriParam);
+ }
+ });
+ }
+ }
+ }
+ }).start();
+ }
+
+ private void displayDialogConfirmation() {
+ new AlertDialog.Builder(RemoteProvisioningActivity.this)
+ .setTitle(getString(R.string.remote_provisioning_again_title))
+ .setMessage(getString(R.string.remote_provisioning_again_message))
+ .setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ setRemoteProvisioningAddressAndRestart(configUriParam);
+ }
+ })
+ .setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ goToLinphoneActivity();
+ }
+ })
+ .show();
+ }
+
+ private void setRemoteProvisioningAddressAndRestart(String configUri) {
+ if (spinner != null) spinner.setVisibility(View.VISIBLE);
+
+ LinphonePreferences.instance().setContext(this); // Needed, else the next call will crash
+ LinphonePreferences.instance().setRemoteProvisioningUrl(configUri);
+ LinphonePreferences.instance().firstRemoteProvisioningSuccessful();
+
+ mHandler.postDelayed(new Runnable() {
+ @Override
+ public void run() {
+ LinphoneManager.destroy();
+ stopService(new Intent(ACTION_MAIN).setClass(RemoteProvisioningActivity.this, LinphoneService.class));
+ Intent intent = new Intent();
+ intent.setClass(RemoteProvisioningActivity.this, LinphoneLauncherActivity.class);
+ startActivity(intent);
+ }
+ }, 1000);
+ }
+
+ private void goToLinphoneActivity() {
+ if (LinphoneService.isReady()) {
+ LinphoneService.instance().setActivityToLaunchOnIncomingReceived(LinphoneActivity.class);
+ //finish(); // To prevent the user to come back to this page using back button
+ startActivity(new Intent().setClass(this, LinphoneActivity.class));
+ } else {
+ finish();
+ }
+ }
+}
diff --git a/src/org/linphone/setup/RemoteProvisioningFragment.java b/src/org/linphone/setup/RemoteProvisioningFragment.java
new file mode 100644
index 000000000..4780d6a42
--- /dev/null
+++ b/src/org/linphone/setup/RemoteProvisioningFragment.java
@@ -0,0 +1,50 @@
+package org.linphone.setup;
+
+import org.linphone.LinphoneActivity;
+import org.linphone.LinphoneLauncherActivity;
+import org.linphone.LinphonePreferences;
+import org.linphone.R;
+
+import android.content.Intent;
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.widget.EditText;
+import android.widget.ImageView;
+
+public class RemoteProvisioningFragment extends Fragment implements OnClickListener {
+ private EditText remoteProvisioningUrl;
+ private ImageView apply;
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container,
+ Bundle savedInstanceState) {
+ View view = inflater.inflate(R.layout.setup_remote_provisioning, container, false);
+
+ remoteProvisioningUrl = (EditText) view.findViewById(R.id.setup_remote_provisioning_url);
+ apply = (ImageView) view.findViewById(R.id.setup_apply);
+ apply.setOnClickListener(this);
+
+ return view;
+ }
+
+ @Override
+ public void onClick(View v) {
+ int id = v.getId();
+
+ if (id == R.id.setup_apply) {
+ String url = remoteProvisioningUrl.getText().toString();
+ LinphonePreferences.instance().setRemoteProvisioningUrl(url);
+
+ // Restart Linphone
+ Intent intent = new Intent();
+ intent.setClass(getActivity(), LinphoneLauncherActivity.class);
+ getActivity().finish();
+ LinphoneActivity.instance().exit();
+ startActivity(intent);
+ }
+ }
+}
diff --git a/src/org/linphone/setup/RemoteProvisioningLoginActivity.java b/src/org/linphone/setup/RemoteProvisioningLoginActivity.java
new file mode 100644
index 000000000..6b358d7b1
--- /dev/null
+++ b/src/org/linphone/setup/RemoteProvisioningLoginActivity.java
@@ -0,0 +1,117 @@
+package org.linphone.setup;
+/*
+RemoteProvisioningLoginActivity.java
+Copyright (C) 2014 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import org.linphone.LinphoneManager;
+import org.linphone.LinphonePreferences;
+import org.linphone.R;
+import org.linphone.core.LinphoneAuthInfo;
+import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneCoreException;
+import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.core.LinphoneProxyConfig;
+
+import android.app.Activity;
+import android.os.Bundle;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.widget.EditText;
+import android.widget.RelativeLayout;
+import android.widget.Toast;
+
+/**
+ * @author Sylvain Berfini
+ */
+public class RemoteProvisioningLoginActivity extends Activity implements OnClickListener {
+ private EditText login, password, domain;
+ private RelativeLayout next, cancel;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.setup_remote_provisioning_login);
+
+ login = (EditText) findViewById(R.id.setup_username);
+ password = (EditText) findViewById(R.id.setup_password);
+ domain = (EditText) findViewById(R.id.setup_domain);
+
+ next = (RelativeLayout) findViewById(R.id.setup_next);
+ next.setOnClickListener(this);
+ cancel = (RelativeLayout) findViewById(R.id.setup_cancel);
+ cancel.setOnClickListener(this);
+
+ String defaultDomain = getIntent().getStringExtra("Domain");
+ if (defaultDomain != null) {
+ domain.setText(defaultDomain);
+ domain.setEnabled(false);
+ }
+ }
+
+ private void cancelWizard(boolean bypassCheck) {
+ if (bypassCheck || getResources().getBoolean(R.bool.allow_cancel_remote_provisioning_login_activity)) {
+ LinphonePreferences.instance().disableProvisioningLoginView();
+ setResult(bypassCheck ? Activity.RESULT_OK : Activity.RESULT_CANCELED);
+ finish();
+ }
+ }
+
+ private boolean storeAccount(String username, String password, String domain) {
+ LinphoneCore lc = LinphoneManager.getLc();
+
+ String identity = "sip:" + username + "@" + domain;
+ LinphoneProxyConfig prxCfg = lc.createProxyConfig();
+ try {
+ prxCfg.setIdentity(identity);
+ lc.addProxyConfig(prxCfg);
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ return false;
+ }
+
+ LinphoneAuthInfo authInfo = LinphoneCoreFactory.instance().createAuthInfo(username, null, password, null, null, domain);
+ lc.addAuthInfo(authInfo);
+
+ if (LinphonePreferences.instance().getAccountCount() == 1)
+ lc.setDefaultProxyConfig(prxCfg);
+
+ return true;
+ }
+
+ @Override
+ public void onClick(View v) {
+ int id = v.getId();
+
+ if (id == R.id.setup_next) {
+ if (login.getText() == null || login.length() == 0 || password.getText() == null || password.length() == 0 || domain.getText() == null || domain.length() == 0) {
+ Toast.makeText(this, getString(R.string.first_launch_no_login_password), Toast.LENGTH_LONG).show();
+ return;
+ }
+
+ storeAccount(login.getText().toString(), password.getText().toString(), domain.getText().toString());
+ cancelWizard(true);
+ } else if (id == R.id.setup_cancel) {
+ cancelWizard(false);
+ }
+ }
+
+ @Override
+ public void onBackPressed() {
+ cancelWizard(false);
+ }
+}
diff --git a/src/org/linphone/setup/SetupActivity.java b/src/org/linphone/setup/SetupActivity.java
index cfb8644f9..bba6e8292 100644
--- a/src/org/linphone/setup/SetupActivity.java
+++ b/src/org/linphone/setup/SetupActivity.java
@@ -18,18 +18,22 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
import org.linphone.LinphoneManager;
-import org.linphone.LinphoneSimpleListener.LinphoneOnRegistrationStateChangedListener;
+import org.linphone.LinphonePreferences;
+import org.linphone.LinphonePreferences.AccountBuilder;
import org.linphone.R;
+import org.linphone.core.LinphoneAddress;
+import org.linphone.core.LinphoneAddress.TransportType;
+import org.linphone.core.LinphoneCore;
import org.linphone.core.LinphoneCore.RegistrationState;
-import org.linphone.mediastream.Log;
+import org.linphone.core.LinphoneCoreException;
+import org.linphone.core.LinphoneCoreFactory;
+import org.linphone.core.LinphoneCoreListenerBase;
+import org.linphone.core.LinphoneProxyConfig;
import android.app.Activity;
import android.content.Context;
-import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.os.Bundle;
-import android.os.Handler;
-import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTransaction;
@@ -46,11 +50,12 @@ public class SetupActivity extends FragmentActivity implements OnClickListener {
private static SetupActivity instance;
private RelativeLayout back, next, cancel;
private SetupFragmentsEnum currentFragment;
- private SharedPreferences mPref;
private SetupFragmentsEnum firstFragment;
private Fragment fragment;
+ private LinphonePreferences mPrefs;
private boolean accountCreated = false;
- private Handler mHandler = new Handler();
+ private LinphoneCoreListenerBase mListener;
+ private LinphoneAddress address;
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -69,13 +74,50 @@ public class SetupActivity extends FragmentActivity implements OnClickListener {
currentFragment = (SetupFragmentsEnum) savedInstanceState.getSerializable("CurrentFragment");
}
}
-
- mPref = PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
+ mPrefs = LinphonePreferences.instance();
initUI();
+
+ mListener = new LinphoneCoreListenerBase(){
+ @Override
+ public void registrationState(LinphoneCore lc, LinphoneProxyConfig cfg, LinphoneCore.RegistrationState state, String smessage) {
+ if(accountCreated){
+ if(address != null && address.asString().equals(cfg.getIdentity()) ) {
+ if (state == RegistrationState.RegistrationOk) {
+ if (LinphoneManager.getLc().getDefaultProxyConfig() != null) {
+ launchEchoCancellerCalibration(true);
+ }
+ } else if (state == RegistrationState.RegistrationFailed) {
+ Toast.makeText(SetupActivity.this, getString(R.string.first_launch_bad_login_password), Toast.LENGTH_LONG).show();
+ }
+ }
+ }
+ }
+ };
+
instance = this;
};
+ @Override
+ protected void onResume() {
+ super.onResume();
+
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.addListener(mListener);
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.removeListener(mListener);
+ }
+
+ super.onPause();
+ }
+
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putSerializable("CurrentFragment", currentFragment);
@@ -109,9 +151,11 @@ public class SetupActivity extends FragmentActivity implements OnClickListener {
int id = v.getId();
if (id == R.id.setup_cancel) {
+ LinphonePreferences.instance().firstLaunchSuccessful();
if (getResources().getBoolean(R.bool.setup_cancel_move_to_back)) {
moveTaskToBack(true);
} else {
+ setResult(Activity.RESULT_CANCELED);
finish();
}
} else if (id == R.id.setup_next) {
@@ -138,9 +182,11 @@ public class SetupActivity extends FragmentActivity implements OnClickListener {
@Override
public void onBackPressed() {
if (currentFragment == firstFragment) {
+ LinphonePreferences.instance().firstLaunchSuccessful();
if (getResources().getBoolean(R.bool.setup_cancel_move_to_back)) {
moveTaskToBack(true);
} else {
+ setResult(Activity.RESULT_CANCELED);
finish();
}
}
@@ -151,7 +197,10 @@ public class SetupActivity extends FragmentActivity implements OnClickListener {
next.setVisibility(View.VISIBLE);
back.setVisibility(View.GONE);
- } else if (currentFragment == SetupFragmentsEnum.GENERIC_LOGIN || currentFragment == SetupFragmentsEnum.LINPHONE_LOGIN || currentFragment == SetupFragmentsEnum.WIZARD) {
+ } else if (currentFragment == SetupFragmentsEnum.GENERIC_LOGIN
+ || currentFragment == SetupFragmentsEnum.LINPHONE_LOGIN
+ || currentFragment == SetupFragmentsEnum.WIZARD
+ || currentFragment == SetupFragmentsEnum.REMOTE_PROVISIONING) {
MenuFragment fragment = new MenuFragment();
changeFragment(fragment);
currentFragment = SetupFragmentsEnum.MENU;
@@ -161,7 +210,9 @@ public class SetupActivity extends FragmentActivity implements OnClickListener {
}
private void launchEchoCancellerCalibration(boolean sendEcCalibrationResult) {
- if (LinphoneManager.getLc().needsEchoCalibration() && !mPref.getBoolean(getString(R.string.first_launch_suceeded_once_key), false)) {
+ boolean needsEchoCalibration = LinphoneManager.getLc().needsEchoCalibration();
+ if (needsEchoCalibration && mPrefs.isFirstLaunch()) {
+ mPrefs.setAccountEnabled(mPrefs.getAccountCount() - 1, false); //We'll enable it after the echo calibration
EchoCancellerCalibrationFragment fragment = new EchoCancellerCalibrationFragment();
fragment.enableEcCalibrationResultSending(sendEcCalibrationResult);
changeFragment(fragment);
@@ -171,6 +222,9 @@ public class SetupActivity extends FragmentActivity implements OnClickListener {
next.setEnabled(false);
cancel.setEnabled(false);
} else {
+ if (mPrefs.isFirstLaunch()) {
+ mPrefs.setEchoCancellation(LinphoneManager.getLc().needsEchoCanceler());
+ }
success();
}
}
@@ -182,60 +236,14 @@ public class SetupActivity extends FragmentActivity implements OnClickListener {
}
saveCreatedAccount(username, password, domain);
- LinphoneManager.getInstance().initializePayloads();
-
- try {
- LinphoneManager.getInstance().initFromConf();
- } catch (Throwable e) {
- Log.e(e, "Error while initializing from config in first login activity");
- Toast.makeText(this, getString(R.string.error), Toast.LENGTH_LONG).show();
- }
if (LinphoneManager.getLc().getDefaultProxyConfig() != null) {
launchEchoCancellerCalibration(sendEcCalibrationResult);
}
}
-
- private LinphoneOnRegistrationStateChangedListener registrationListener = new LinphoneOnRegistrationStateChangedListener() {
- public void onRegistrationStateChanged(RegistrationState state) {
- if (state == RegistrationState.RegistrationOk) {
- LinphoneManager.removeListener(registrationListener);
-
- if (LinphoneManager.getLc().getDefaultProxyConfig() != null) {
- mHandler .post(new Runnable () {
- public void run() {
- launchEchoCancellerCalibration(true);
- }
- });
- }
- } else if (state == RegistrationState.RegistrationFailed) {
- LinphoneManager.removeListener(registrationListener);
- deleteCreatedAccount();
- mHandler.post(new Runnable () {
- public void run() {
- Toast.makeText(SetupActivity.this, getString(R.string.first_launch_bad_login_password), Toast.LENGTH_LONG).show();
- }
- });
- }
- }
- };
public void checkAccount(String username, String password, String domain) {
- LinphoneManager.removeListener(registrationListener);
- LinphoneManager.addListener(registrationListener);
-
saveCreatedAccount(username, password, domain);
- LinphoneManager.getInstance().initializePayloads();
-
- try {
- LinphoneManager.getInstance().initFromConf();
- } catch (Throwable e) {
- LinphoneManager.removeListener(registrationListener);
- deleteCreatedAccount();
-
- Log.e(e, "Error while initializing from config in first login activity");
- Toast.makeText(this, getString(R.string.error), Toast.LENGTH_LONG).show();
- }
}
public void linphoneLogIn(String username, String password, boolean validate) {
@@ -250,22 +258,6 @@ public class SetupActivity extends FragmentActivity implements OnClickListener {
logIn(username, password, domain, false);
}
- private void writePreference(int key, String value) {
- mPref.edit().putString(getString(key), value).commit();
- }
-
- private void writePreference(String key, String value) {
- mPref.edit().putString(key, value).commit();
- }
-
- private void writePreference(int key, int value) {
- mPref.edit().putInt(getString(key), value).commit();
- }
-
- private void writePreference(int key, boolean value) {
- mPref.edit().putBoolean(getString(key), value).commit();
- }
-
private void display(SetupFragmentsEnum fragment) {
switch (fragment) {
case WELCOME:
@@ -302,57 +294,84 @@ public class SetupActivity extends FragmentActivity implements OnClickListener {
changeFragment(fragment);
currentFragment = SetupFragmentsEnum.WIZARD;
}
-
- public void deleteCreatedAccount() {
- if (!accountCreated)
- return;
-
- writePreference(R.string.pref_extra_accounts, 0);
- accountCreated = false;
+
+ public void displayRemoteProvisioning() {
+ fragment = new RemoteProvisioningFragment();
+ changeFragment(fragment);
+ currentFragment = SetupFragmentsEnum.REMOTE_PROVISIONING;
}
public void saveCreatedAccount(String username, String password, String domain) {
if (accountCreated)
return;
+
+ if(username.startsWith("sip:")) {
+ username = username.substring(4);
+ }
+
+ if(domain.startsWith("sip:")) {
+ domain = domain.substring(4);
+ }
+
+ String identity = "sip:" + username + "@" + domain;
+ try {
+ address = LinphoneCoreFactory.instance().createLinphoneAddress(identity);
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
+ }
+ boolean isMainAccountLinphoneDotOrg = domain.equals(getString(R.string.default_domain));
+ boolean useLinphoneDotOrgCustomPorts = getResources().getBoolean(R.bool.use_linphone_server_ports);
+ AccountBuilder builder = new AccountBuilder(LinphoneManager.getLc())
+ .setUsername(username)
+ .setDomain(domain)
+ .setPassword(password);
- int newAccountId = mPref.getInt(getString(R.string.pref_extra_accounts), 0);
- if (newAccountId == -1)
- newAccountId = 0;
- writePreference(R.string.pref_extra_accounts, newAccountId+1);
-
- if (newAccountId == 0) {
- writePreference(R.string.pref_username_key, username);
- writePreference(R.string.pref_passwd_key, password);
- writePreference(R.string.pref_domain_key, domain);
-
- boolean isMainAccountLinphoneDotOrg = domain.equals(getString(R.string.default_domain));
- if (isMainAccountLinphoneDotOrg) {
- if (getResources().getBoolean(R.bool.disable_all_security_features_for_markets)) {
- writePreference(R.string.pref_proxy_key, domain + ":5228");
- writePreference(R.string.pref_transport_key, getString(R.string.pref_transport_tcp_key));
- }
- else {
- writePreference(R.string.pref_proxy_key, domain + ":5223");
- writePreference(R.string.pref_transport_key, getString(R.string.pref_transport_tls_key));
- }
-
- writePreference(R.string.pref_expire_key, "604800"); // 3600*24*7
- writePreference(R.string.pref_enable_outbound_proxy_key, true);
- writePreference(R.string.pref_stun_server_key, getString(R.string.default_stun));
- writePreference(R.string.pref_ice_enable_key, true);
- writePreference(R.string.pref_push_notification_key, true);
+ if (isMainAccountLinphoneDotOrg && useLinphoneDotOrgCustomPorts) {
+ if (getResources().getBoolean(R.bool.disable_all_security_features_for_markets)) {
+ builder.setProxy(domain + ":5228")
+ .setTransport(TransportType.LinphoneTransportTcp);
}
+ else {
+ builder.setProxy(domain + ":5223")
+ .setTransport(TransportType.LinphoneTransportTls);
+ }
+
+ builder.setExpires("604800")
+ .setOutboundProxyEnabled(true)
+ .setAvpfEnabled(true)
+ .setAvpfRRInterval(3)
+ .setQualityReportingCollector("sip:voip-metrics@sip.linphone.org")
+ .setQualityReportingEnabled(true)
+ .setQualityReportingInterval(180)
+ .setRealm("sip.linphone.org");
+
+
+ mPrefs.setStunServer(getString(R.string.default_stun));
+ mPrefs.setIceEnabled(true);
} else {
- writePreference(getString(R.string.pref_username_key) + newAccountId, username);
- writePreference(getString(R.string.pref_passwd_key) + newAccountId, password);
- writePreference(getString(R.string.pref_domain_key) + newAccountId, domain);
+ String forcedProxy = getResources().getString(R.string.setup_forced_proxy);
+ if (!TextUtils.isEmpty(forcedProxy)) {
+ builder.setProxy(forcedProxy)
+ .setOutboundProxyEnabled(true)
+ .setAvpfRRInterval(5);
+ }
}
- String forcedProxy=getResources().getString(R.string.setup_forced_proxy);
- if (!TextUtils.isEmpty(forcedProxy)) {
- writePreference(R.string.pref_enable_outbound_proxy_key, true);
- writePreference(R.string.pref_proxy_key, forcedProxy);
+
+ if (getResources().getBoolean(R.bool.enable_push_id)) {
+ String regId = mPrefs.getPushNotificationRegistrationID();
+ String appId = getString(R.string.push_sender_id);
+ if (regId != null && mPrefs.isPushNotificationEnabled()) {
+ String contactInfos = "app-id=" + appId + ";pn-type=google;pn-tok=" + regId;
+ builder.setContactParameters(contactInfos);
+ }
+ }
+
+ try {
+ builder.saveNewAccount();
+ accountCreated = true;
+ } catch (LinphoneCoreException e) {
+ e.printStackTrace();
}
- accountCreated = true;
}
public void displayWizardConfirm(String username) {
@@ -370,27 +389,19 @@ public class SetupActivity extends FragmentActivity implements OnClickListener {
back.setVisibility(View.GONE);
}
- public void isAccountVerified() {
+ public void isAccountVerified(String username) {
Toast.makeText(this, getString(R.string.setup_account_validated), Toast.LENGTH_LONG).show();
-
- LinphoneManager.getInstance().initializePayloads();
-
- try {
- LinphoneManager.getInstance().initFromConf();
- } catch (Throwable e) {
- Log.e(e, "Error while initializing from config in first login activity");
- Toast.makeText(this, getString(R.string.error), Toast.LENGTH_LONG).show();
- }
-
+ LinphoneManager.getLcIfManagerNotDestroyedOrNull().refreshRegisters();
launchEchoCancellerCalibration(true);
}
public void isEchoCalibrationFinished() {
+ mPrefs.setAccountEnabled(mPrefs.getAccountCount() - 1, true);
success();
}
public void success() {
- writePreference(R.string.first_launch_suceeded_once_key, true);
+ mPrefs.firstLaunchSuccessful();
setResult(Activity.RESULT_OK);
finish();
}
diff --git a/src/org/linphone/setup/SetupFragmentsEnum.java b/src/org/linphone/setup/SetupFragmentsEnum.java
index 91b8c2feb..9ef733bac 100644
--- a/src/org/linphone/setup/SetupFragmentsEnum.java
+++ b/src/org/linphone/setup/SetupFragmentsEnum.java
@@ -27,5 +27,6 @@ public enum SetupFragmentsEnum {
WIZARD_CONFIRM,
LINPHONE_LOGIN,
GENERIC_LOGIN,
+ REMOTE_PROVISIONING,
ECHO_CANCELLER_CALIBRATION;
}
diff --git a/src/org/linphone/setup/WizardConfirmFragment.java b/src/org/linphone/setup/WizardConfirmFragment.java
index 0575afc83..0fbcbb482 100644
--- a/src/org/linphone/setup/WizardConfirmFragment.java
+++ b/src/org/linphone/setup/WizardConfirmFragment.java
@@ -59,7 +59,7 @@ public class WizardConfirmFragment extends Fragment {
return view;
}
- private void isAccountVerified(String username) {
+ private void isAccountVerified(final String username) {
final Runnable runNotReachable = new Runnable() {
public void run() {
Toast.makeText(getActivity(), getString(R.string.wizard_server_unavailable), Toast.LENGTH_LONG).show();
@@ -78,7 +78,7 @@ public class WizardConfirmFragment extends Fragment {
Runnable runOk = new Runnable() {
public void run() {
- SetupActivity.instance().isAccountVerified();
+ SetupActivity.instance().isAccountVerified(username);
}
};
diff --git a/src/org/linphone/setup/WizardFragment.java b/src/org/linphone/setup/WizardFragment.java
index 15c8ee055..d9b642d16 100644
--- a/src/org/linphone/setup/WizardFragment.java
+++ b/src/org/linphone/setup/WizardFragment.java
@@ -18,19 +18,25 @@ along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
import java.net.URL;
+import java.util.Locale;
import java.util.regex.Pattern;
import org.linphone.LinphoneManager;
import org.linphone.LinphoneService;
import org.linphone.R;
+import org.linphone.core.LinphoneProxyConfig;
import android.accounts.Account;
import android.accounts.AccountManager;
+import android.app.AlertDialog;
import android.content.Context;
+import android.content.DialogInterface;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.app.Fragment;
import android.text.Editable;
+import android.text.InputFilter;
+import android.text.Spanned;
import android.text.TextWatcher;
import android.util.Patterns;
import android.view.LayoutInflater;
@@ -57,15 +63,47 @@ public class WizardFragment extends Fragment {
private boolean confirmPasswordOk = false;
private ImageView createAccount;
private TextView errorMessage;
+ private char[] acceptedChars = new char[]{ 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z',
+ 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
+ '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '.', '_', '-' };
+ private char[] acceptedCharsForPhoneNumbers = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '-', '+' };
+ private String inputFilterCharacters;
+
+ private String getUsername() {
+ String username = this.username.getText().toString();
+ if (getResources().getBoolean(R.bool.allow_only_phone_numbers_in_wizard)) {
+ LinphoneProxyConfig lpc = LinphoneManager.getLc().createProxyConfig();
+ username = lpc.normalizePhoneNumber(username);
+ }
+ return username.toLowerCase(Locale.getDefault());
+ }
@Override
- public View onCreateView(LayoutInflater inflater, ViewGroup container,
- Bundle savedInstanceState) {
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.setup_wizard, container, false);
username = (EditText) view.findViewById(R.id.setup_username);
ImageView usernameOkIV = (ImageView) view.findViewById(R.id.setup_username_ok);
addXMLRPCUsernameHandler(username, usernameOkIV);
+
+ inputFilterCharacters = new String(acceptedChars);
+ if (getResources().getBoolean(R.bool.allow_only_phone_numbers_in_wizard)) {
+ inputFilterCharacters = new String(acceptedCharsForPhoneNumbers);
+ }
+ InputFilter filter = new InputFilter(){
+ @Override
+ public CharSequence filter(CharSequence source, int start, int end, Spanned dest, int dstart, int dend) {
+ if (end > start) {
+ for (int index = start; index < end; index++) {
+ if (!inputFilterCharacters.contains(String.valueOf(source.charAt(index)))) {
+ return "";
+ }
+ }
+ }
+ return null;
+ }
+ };
+ username.setFilters(new InputFilter[] { filter });
password = (EditText) view.findViewById(R.id.setup_password);
passwordConfirm = (EditText) view.findViewById(R.id.setup_password_confirm);
@@ -86,7 +124,19 @@ public class WizardFragment extends Fragment {
createAccount.setEnabled(false);
createAccount.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
- createAccount(username.getText().toString(), password.getText().toString(), email.getText().toString(), false);
+ AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
+ builder.setPositiveButton(R.string.button_ok, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ createAccount(getUsername(), password.getText().toString(), email.getText().toString(), false);
+ }
+ });
+ builder.setNegativeButton(R.string.button_cancel, new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int id) {
+ }
+ });
+ builder.setMessage(getString(R.string.setup_confirm_username).replace("%s", getUsername()));
+ AlertDialog dialog = builder.create();
+ dialog.show();
}
});
@@ -106,7 +156,12 @@ public class WizardFragment extends Fragment {
}
private boolean isUsernameCorrect(String username) {
- return username.matches("^[a-zA-Z]+[a-zA-Z0-9.\\-_]{2,}$");
+ if (getResources().getBoolean(R.bool.allow_only_phone_numbers_in_wizard)) {
+ LinphoneProxyConfig lpc = LinphoneManager.getLc().createProxyConfig();
+ return lpc.isPhoneNumber(username);
+ } else {
+ return username.matches("^[a-zA-Z]+[a-zA-Z0-9.\\-_]{2,}$");
+ }
}
private void isUsernameRegistred(String username, final ImageView icon) {
@@ -229,22 +284,24 @@ public class WizardFragment extends Fragment {
private void addXMLRPCUsernameHandler(final EditText field, final ImageView icon) {
field.addTextChangedListener(new TextWatcher() {
- public void afterTextChanged(Editable arg0) {
+ public void afterTextChanged(Editable s) {
}
- public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
- public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3)
- {
+ public void onTextChanged(CharSequence s, int start, int count, int after) {
usernameOk = false;
- if (isUsernameCorrect(field.getText().toString()))
- {
- isUsernameRegistred(field.getText().toString(), icon);
- }
- else {
+ String username = field.getText().toString().toLowerCase(Locale.getDefault());
+ if (isUsernameCorrect(username)) {
+ if (getResources().getBoolean(R.bool.allow_only_phone_numbers_in_wizard)) {
+ LinphoneProxyConfig lpc = LinphoneManager.getLc().createProxyConfig();
+ username = lpc.normalizePhoneNumber(username);
+ }
+ isUsernameRegistred(username, icon);
+ } else {
errorMessage.setText(R.string.wizard_username_incorrect);
icon.setImageResource(R.drawable.wizard_notok);
}
@@ -254,15 +311,15 @@ public class WizardFragment extends Fragment {
private void addXMLRPCEmailHandler(final EditText field, final ImageView icon) {
field.addTextChangedListener(new TextWatcher() {
- public void afterTextChanged(Editable arg0) {
+ public void afterTextChanged(Editable s) {
}
- public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
- public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3)
+ public void onTextChanged(CharSequence s, int start, int count, int after)
{
emailOk = false;
if (isEmailCorrect(field.getText().toString())) {
@@ -281,15 +338,15 @@ public class WizardFragment extends Fragment {
private void addXMLRPCPasswordHandler(final EditText field1, final ImageView icon) {
TextWatcher passwordListener = new TextWatcher() {
- public void afterTextChanged(Editable arg0) {
+ public void afterTextChanged(Editable s) {
}
- public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
- public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3)
+ public void onTextChanged(CharSequence s, int start, int count, int after)
{
passwordOk = false;
if (isPasswordCorrect(field1.getText().toString())) {
@@ -310,15 +367,15 @@ public class WizardFragment extends Fragment {
private void addXMLRPCConfirmPasswordHandler(final EditText field1, final EditText field2, final ImageView icon) {
TextWatcher passwordListener = new TextWatcher() {
- public void afterTextChanged(Editable arg0) {
+ public void afterTextChanged(Editable s) {
}
- public void beforeTextChanged(CharSequence arg0, int arg1, int arg2, int arg3) {
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
- public void onTextChanged(CharSequence arg0, int arg1, int arg2, int arg3)
+ public void onTextChanged(CharSequence s, int start, int count, int after)
{
confirmPasswordOk = false;
if (field1.getText().toString().equals(field2.getText().toString())) {
diff --git a/src/org/linphone/sync/AuthenticationService.java b/src/org/linphone/sync/AuthenticationService.java
new file mode 100644
index 000000000..aec317e82
--- /dev/null
+++ b/src/org/linphone/sync/AuthenticationService.java
@@ -0,0 +1,39 @@
+package org.linphone.sync;
+
+/*
+AuthenticationService.java
+Copyright (C) 2015 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class AuthenticationService extends Service {
+
+ private Authenticator mAuthenticator;
+ @Override
+ public void onCreate() {
+ mAuthenticator = new Authenticator(this);
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return mAuthenticator.getIBinder();
+ }
+}
\ No newline at end of file
diff --git a/src/org/linphone/sync/Authenticator.java b/src/org/linphone/sync/Authenticator.java
new file mode 100644
index 000000000..30f3e8065
--- /dev/null
+++ b/src/org/linphone/sync/Authenticator.java
@@ -0,0 +1,85 @@
+package org.linphone.sync;
+
+/*
+Authenticator.java
+Copyright (C) 2015 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import android.accounts.AbstractAccountAuthenticator;
+import android.accounts.*;
+import android.content.Context;
+import android.os.Bundle;
+
+public class Authenticator extends AbstractAccountAuthenticator {
+
+ public Authenticator(Context context) {
+ super(context);
+ }
+
+ @Override
+ public Bundle editProperties(
+ AccountAuthenticatorResponse r, String s) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Bundle addAccount(
+ AccountAuthenticatorResponse r,
+ String s,
+ String s2,
+ String[] strings,
+ Bundle bundle) throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle confirmCredentials(
+ AccountAuthenticatorResponse r,
+ Account account,
+ Bundle bundle) throws NetworkErrorException {
+ return null;
+ }
+
+ @Override
+ public Bundle getAuthToken(
+ AccountAuthenticatorResponse r,
+ Account account,
+ String s,
+ Bundle bundle) throws NetworkErrorException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public String getAuthTokenLabel(String s) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Bundle updateCredentials(
+ AccountAuthenticatorResponse r,
+ Account account,
+ String s, Bundle bundle) throws NetworkErrorException {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public Bundle hasFeatures(
+ AccountAuthenticatorResponse r,
+ Account account, String[] strings) throws NetworkErrorException {
+ throw new UnsupportedOperationException();
+ }
+}
\ No newline at end of file
diff --git a/src/org/linphone/sync/SyncAdapter.java b/src/org/linphone/sync/SyncAdapter.java
new file mode 100755
index 000000000..620adc861
--- /dev/null
+++ b/src/org/linphone/sync/SyncAdapter.java
@@ -0,0 +1,40 @@
+package org.linphone.sync;
+
+/*
+SyncAdapter.java
+Copyright (C) 2015 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+import android.accounts.Account;
+import android.content.AbstractThreadedSyncAdapter;
+import android.content.ContentProviderClient;
+import android.content.Context;
+import android.content.SyncResult;
+import android.os.Bundle;
+
+public class SyncAdapter extends AbstractThreadedSyncAdapter {
+
+ public SyncAdapter(Context context, boolean autoInitialize) {
+ super(context, autoInitialize);
+ }
+
+ @Override
+ public void onPerformSync(Account account, Bundle extras, String authority,
+ ContentProviderClient provider, SyncResult syncResult) {
+ }
+}
+
diff --git a/src/org/linphone/sync/SyncService.java b/src/org/linphone/sync/SyncService.java
new file mode 100755
index 000000000..fc9ee6638
--- /dev/null
+++ b/src/org/linphone/sync/SyncService.java
@@ -0,0 +1,45 @@
+package org.linphone.sync;
+
+/*
+SyncService.java
+Copyright (C) 2015 Belledonne Communications, Grenoble, France
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+*/
+
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.IBinder;
+
+public class SyncService extends Service {
+ private static SyncAdapter sSyncAdapter = null;
+ private static final Object sSyncAdapterLock = new Object();
+
+ @Override
+ public void onCreate() {
+
+ synchronized (sSyncAdapterLock) {
+ if (sSyncAdapter == null) {
+ sSyncAdapter = new SyncAdapter(getApplicationContext(), true);
+ }
+ }
+ }
+
+ @Override
+ public IBinder onBind(Intent intent) {
+ return sSyncAdapter.getSyncAdapterBinder();
+ }
+}
diff --git a/src/org/linphone/ui/AddressText.java b/src/org/linphone/ui/AddressText.java
index f0fef5bd6..3b6677578 100644
--- a/src/org/linphone/ui/AddressText.java
+++ b/src/org/linphone/ui/AddressText.java
@@ -56,7 +56,7 @@ public class AddressText extends EditText implements AddressType {
}
public void clearDisplayedName() {
- displayedName = "";
+ displayedName = null;
}
public String getDisplayedName() {
diff --git a/src/org/linphone/ui/BubbleChat.java b/src/org/linphone/ui/BubbleChat.java
index 7df7792f7..7ff74ef65 100644
--- a/src/org/linphone/ui/BubbleChat.java
+++ b/src/org/linphone/ui/BubbleChat.java
@@ -17,19 +17,32 @@ You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.lang.ref.WeakReference;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.HashMap;
import java.util.Map.Entry;
-import org.linphone.LinphoneUtils;
import org.linphone.R;
import org.linphone.core.LinphoneChatMessage;
+import org.linphone.core.LinphoneChatMessage.State;
+import org.linphone.core.LinphoneContent;
+import org.linphone.mediastream.Log;
import android.annotation.SuppressLint;
import android.content.Context;
+import android.content.Intent;
+import android.content.res.Resources;
import android.graphics.Bitmap;
-import android.graphics.Color;
+import android.graphics.BitmapFactory;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
+import android.media.ThumbnailUtils;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.provider.MediaStore;
import android.text.Html;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
@@ -42,6 +55,7 @@ import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.LinearLayout;
+import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.RelativeLayout.LayoutParams;
import android.widget.TextView;
@@ -85,115 +99,126 @@ public class BubbleChat {
private RelativeLayout view;
private ImageView statusView;
- private Button download;
+ private LinphoneChatMessage nativeMessage;
+ private LinphoneChatMessage.LinphoneChatMessageListener fileTransferListener;
+ private Context mContext;
+ private static final int SIZE_MAX = 512;
- public BubbleChat(Context context, int id, String message, Bitmap image, String time, boolean isIncoming, LinphoneChatMessage.State status, int previousID) {
- view = new RelativeLayout(context);
+ @SuppressLint("InflateParams")
+ public BubbleChat(final Context context, LinphoneChatMessage message, LinphoneChatMessage.LinphoneChatMessageListener listener) {
+ if (message == null) {
+ return;
+ }
+ nativeMessage = message;
+ fileTransferListener = listener;
+ mContext = context;
- LayoutParams layoutParams = new LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
+ view = new RelativeLayout(context);
+ LayoutParams layoutParams = new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
- if (isIncoming) {
- layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
- view.setBackgroundResource(R.drawable.chat_bubble_incoming);
- }
- else {
+ if (message.isOutgoing()) {
layoutParams.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
view.setBackgroundResource(R.drawable.chat_bubble_outgoing);
}
-
- if (previousID != -1) {
- layoutParams.addRule(RelativeLayout.BELOW, previousID);
+ else {
+ layoutParams.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
+ view.setBackgroundResource(R.drawable.chat_bubble_incoming);
}
- view.setId(id);
- layoutParams.setMargins(0, LinphoneUtils.pixelsToDpi(context.getResources(), 10), 0, 0);
- view.setLayoutParams(layoutParams);
+ layoutParams.setMargins(10, 0, 10, 0);
- Spanned text = null;
- if (message != null) {
- if (context.getResources().getBoolean(R.bool.emoticons_in_messages)) {
- text = getSmiledText(context, getTextWithHttpLinks(message));
- } else {
- text = getTextWithHttpLinks(message);
- }
- }
+ view.setId(message.getStorageId());
+ view.setLayoutParams(layoutParams);
- if (context.getResources().getBoolean(R.bool.display_messages_time_and_status)) {
- LinearLayout layout;
- if (context.getResources().getBoolean(R.bool.display_time_aside)) {
- if (isIncoming) {
- layout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.chat_bubble_alt_incoming, null);
- } else {
- layout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.chat_bubble_alt_outgoing, null);
- }
+ LinearLayout layout;
+ if (context.getResources().getBoolean(R.bool.display_time_aside)) {
+ if (message.isOutgoing()) {
+ layout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.chat_bubble_alt_outgoing, null);
} else {
- if (isIncoming) {
- layout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.chat_bubble_incoming, null);
- } else {
- layout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.chat_bubble_outgoing, null);
- }
+ layout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.chat_bubble_alt_incoming, null);
}
-
- TextView msgView = (TextView) layout.findViewById(R.id.message);
- if (message != null && msgView != null) {
- msgView.setText(text);
- msgView.setMovementMethod(LinkMovementMethod.getInstance());
- } else if (msgView != null) {
- msgView.setVisibility(View.GONE);
- }
-
- ImageView imageView = (ImageView) layout.findViewById(R.id.image);
- if (image != null && imageView != null) {
- imageView.setImageBitmap(image);
- } else if (imageView != null) {
- imageView.setVisibility(View.GONE);
- }
-
- download = (Button) layout.findViewById(R.id.download);
- if (download != null && image == null && message == null) {
- download.setVisibility(View.VISIBLE);
- }
-
- TextView timeView = (TextView) layout.findViewById(R.id.time);
- timeView.setText(timestampToHumanDate(context, time));
-
- statusView = (ImageView) layout.findViewById(R.id.status);
- if (statusView != null) {
- if (status == LinphoneChatMessage.State.Delivered) {
- statusView.setImageResource(R.drawable.chat_message_delivered);
- } else if (status == LinphoneChatMessage.State.NotDelivered) {
- statusView.setImageResource(R.drawable.chat_message_not_delivered);
- } else {
- statusView.setImageResource(R.drawable.chat_message_inprogress);
- }
- }
-
- view.addView(layout);
} else {
- TextView messageView = new TextView(context);
- messageView.setId(id);
- messageView.setTextColor(Color.BLACK);
- messageView.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));
- messageView.setText(text);
- messageView.setLinksClickable(true);
- messageView.setMovementMethod(LinkMovementMethod.getInstance());
-
- view.addView(messageView);
+ if (message.isOutgoing()) {
+ layout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.chat_bubble_outgoing, null);
+ } else {
+ layout = (LinearLayout) LayoutInflater.from(context).inflate(R.layout.chat_bubble_incoming, null);
+ }
}
+
+ String externalBodyUrl = message.getExternalBodyUrl();
+ LinphoneContent fileTransferContent = message.getFileTransferInformation();
+ if (externalBodyUrl != null || fileTransferContent != null) {
+ Button download = (Button) layout.findViewById(R.id.download);
+ ImageView imageView = (ImageView) layout.findViewById(R.id.image);
+
+ String appData = message.getAppData();
+ if (appData == null) {
+ download.setVisibility(View.VISIBLE);
+ download.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ v.setEnabled(false);
+ ProgressBar spinner = (ProgressBar) view.findViewById(R.id.spinner);
+ spinner.setVisibility(View.VISIBLE);
+ v.setVisibility(View.GONE);
+
+ nativeMessage.setListener(fileTransferListener);
+ nativeMessage.downloadFile();
+ }
+ });
+ } else {
+ imageView.setVisibility(View.VISIBLE);
+ loadBitmap(appData, imageView);
+ }
+ } else {
+ TextView msgView = (TextView) layout.findViewById(R.id.message);
+ if (msgView != null) {
+ Spanned text = null;
+ String msg = message.getText();
+ if (msg != null) {
+ if (context.getResources().getBoolean(R.bool.emoticons_in_messages)) {
+ text = getSmiledText(context, getTextWithHttpLinks(msg));
+ } else {
+ text = getTextWithHttpLinks(msg);
+ }
+ msgView.setText(text);
+ msgView.setMovementMethod(LinkMovementMethod.getInstance());
+ msgView.setVisibility(View.VISIBLE);
+ }
+ }
+ }
+
+ TextView timeView = (TextView) layout.findViewById(R.id.time);
+ timeView.setText(timestampToHumanDate(context, message.getTime()));
+
+ LinphoneChatMessage.State status = message.getStatus();
+ statusView = (ImageView) layout.findViewById(R.id.status);
+ if (statusView != null) {
+ if (status == LinphoneChatMessage.State.Delivered) {
+ statusView.setImageResource(R.drawable.chat_message_delivered);
+ } else if (status == LinphoneChatMessage.State.NotDelivered) {
+ statusView.setImageResource(R.drawable.chat_message_not_delivered);
+ } else {
+ statusView.setImageResource(R.drawable.chat_message_inprogress);
+ }
+ }
+
+ view.addView(layout);
}
- public void updateStatusView(LinphoneChatMessage.State status) {
+ public void updateStatusView() {
if (statusView == null) {
return;
}
- if (status == LinphoneChatMessage.State.Delivered) {
+ if (nativeMessage.getStatus() == LinphoneChatMessage.State.Delivered) {
statusView.setImageResource(R.drawable.chat_message_delivered);
- } else if (status == LinphoneChatMessage.State.NotDelivered) {
+ } else if (nativeMessage.getStatus() == LinphoneChatMessage.State.NotDelivered) {
statusView.setImageResource(R.drawable.chat_message_not_delivered);
} else {
statusView.setImageResource(R.drawable.chat_message_inprogress);
}
+
view.invalidate();
}
@@ -201,10 +226,10 @@ public class BubbleChat {
return view;
}
- private String timestampToHumanDate(Context context, String timestamp) {
+ private String timestampToHumanDate(Context context, long timestamp) {
try {
Calendar cal = Calendar.getInstance();
- cal.setTimeInMillis(Long.parseLong(timestamp));
+ cal.setTimeInMillis(timestamp);
SimpleDateFormat dateFormat;
if (isToday(cal)) {
@@ -215,7 +240,7 @@ public class BubbleChat {
return dateFormat.format(cal.getTime());
} catch (NumberFormatException nfe) {
- return timestamp;
+ return String.valueOf(timestamp);
}
}
@@ -233,27 +258,30 @@ public class BubbleChat {
cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));
}
- public static Spannable getSmiledText(Context context, Spanned text) {
- SpannableStringBuilder builder = new SpannableStringBuilder(text);
- int index;
+ public static Spannable getSmiledText(Context context, Spanned spanned) {
+ SpannableStringBuilder builder = new SpannableStringBuilder(spanned);
+ String text = spanned.toString();
- for (index = 0; index < builder.length(); index++) {
- for (Entry entry : emoticons.entrySet()) {
- int length = entry.getKey().length();
- if (index + length > builder.length())
- continue;
- if (builder.subSequence(index, index + length).toString().equals(entry.getKey())) {
- builder.setSpan(new ImageSpan(context, entry.getValue()), index, index + length,
- Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- index += length - 1;
- break;
- }
- }
+ for (Entry entry : emoticons.entrySet()) {
+ String key = entry.getKey();
+ int indexOf = text.indexOf(key);
+ while (indexOf >= 0) {
+ int end = indexOf + key.length();
+ builder.setSpan(new ImageSpan(context, entry.getValue()), indexOf, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ indexOf = text.indexOf(key, end);
+ }
}
+
return builder;
}
public static Spanned getTextWithHttpLinks(String text) {
+ if (text.contains("<")) {
+ text = text.replace("<", "<");
+ }
+ if (text.contains(">")) {
+ text = text.replace(">", ">");
+ }
if (text.contains("http://")) {
int indexHttp = text.indexOf("http://");
int indexFinHttp = text.indexOf(" ", indexHttp) == -1 ? text.length() : text.indexOf(" ", indexHttp);
@@ -271,10 +299,137 @@ public class BubbleChat {
return Html.fromHtml(text);
}
+
+ public String getTextMessage() {
+ return nativeMessage.getText();
+ }
- public void setDownloadImageButtonListener(OnClickListener onClickListener) {
- if (download != null) {
- download.setOnClickListener(onClickListener);
+ public State getStatus() {
+ return nativeMessage.getStatus();
+ }
+
+ public LinphoneChatMessage getNativeMessageObject() {
+ return nativeMessage;
+ }
+
+ public int getId() {
+ return nativeMessage.getStorageId();
+ }
+
+ public void loadBitmap(String path, ImageView imageView) {
+ if (cancelPotentialWork(path, imageView)) {
+ BitmapWorkerTask task = new BitmapWorkerTask(imageView);
+ Bitmap defaultBitmap = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.chat_photo_default);
+ final AsyncBitmap asyncBitmap = new AsyncBitmap(mContext.getResources(), defaultBitmap, task);
+ imageView.setImageDrawable(asyncBitmap);
+ task.execute(path);
}
+ }
+
+ private class BitmapWorkerTask extends AsyncTask {
+ private final WeakReference imageViewReference;
+ public String path;
+
+ public BitmapWorkerTask(ImageView imageView) {
+ path = null;
+ // Use a WeakReference to ensure the ImageView can be garbage collected
+ imageViewReference = new WeakReference(imageView);
+ }
+
+ // Decode image in background.
+ @Override
+ protected Bitmap doInBackground(String... params) {
+ path = params[0];
+ Bitmap bm = null;
+
+ if (path.startsWith("content")) {
+ try {
+ bm = MediaStore.Images.Media.getBitmap(mContext.getContentResolver(), Uri.parse(path));
+ } catch (FileNotFoundException e) {
+ Log.e(e);
+ } catch (IOException e) {
+ Log.e(e);
+ }
+ } else {
+ bm = BitmapFactory.decodeFile(path);
+ path = "file://" + path;
+ }
+
+ if (bm != null) {
+ if (bm.getWidth() >= bm.getHeight() && bm.getWidth() > SIZE_MAX) {
+ bm = ThumbnailUtils.extractThumbnail(bm, SIZE_MAX, (SIZE_MAX * bm.getHeight()) / bm.getWidth());
+ } else if (bm.getHeight() >= bm.getWidth() && bm.getHeight() > SIZE_MAX) {
+ bm = ThumbnailUtils.extractThumbnail(bm, (SIZE_MAX * bm.getWidth()) / bm.getHeight(), SIZE_MAX);
+ }
+ }
+ return bm;
+ }
+
+ // Once complete, see if ImageView is still around and set bitmap.
+ @Override
+ protected void onPostExecute(Bitmap bitmap) {
+ if (isCancelled()) {
+ bitmap = null;
+ }
+
+ if (imageViewReference != null && bitmap != null) {
+ final ImageView imageView = imageViewReference.get();
+ final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
+ if (this == bitmapWorkerTask && imageView != null) {
+ imageView.setImageBitmap(bitmap);
+ imageView.setTag(path);
+ imageView.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ Intent intent = new Intent(Intent.ACTION_VIEW);
+ intent.setDataAndType(Uri.parse((String)v.getTag()), "image/*");
+ mContext.startActivity(intent);
+ }
+ });
+ }
+ }
+ }
+ }
+
+ static class AsyncBitmap extends BitmapDrawable {
+ private final WeakReference bitmapWorkerTaskReference;
+
+ public AsyncBitmap(Resources res, Bitmap bitmap, BitmapWorkerTask bitmapWorkerTask) {
+ super(res, bitmap);
+ bitmapWorkerTaskReference = new WeakReference(bitmapWorkerTask);
+ }
+
+ public BitmapWorkerTask getBitmapWorkerTask() {
+ return bitmapWorkerTaskReference.get();
+ }
+ }
+
+ public static boolean cancelPotentialWork(String path, ImageView imageView) {
+ final BitmapWorkerTask bitmapWorkerTask = getBitmapWorkerTask(imageView);
+
+ if (bitmapWorkerTask != null) {
+ final String bitmapData = bitmapWorkerTask.path;
+ // If bitmapData is not yet set or it differs from the new data
+ if (bitmapData == null || bitmapData != path) {
+ // Cancel previous task
+ bitmapWorkerTask.cancel(true);
+ } else {
+ // The same work is already in progress
+ return false;
+ }
+ }
+ // No task associated with the ImageView, or an existing task was cancelled
+ return true;
+ }
+
+ private static BitmapWorkerTask getBitmapWorkerTask(ImageView imageView) {
+ if (imageView != null) {
+ final Drawable drawable = imageView.getDrawable();
+ if (drawable instanceof AsyncBitmap) {
+ final AsyncBitmap asyncDrawable = (AsyncBitmap) drawable;
+ return asyncDrawable.getBitmapWorkerTask();
+ }
+ }
+ return null;
}
}
diff --git a/src/org/linphone/ui/Digit.java b/src/org/linphone/ui/Digit.java
index 623dd1db9..528d6eebb 100644
--- a/src/org/linphone/ui/Digit.java
+++ b/src/org/linphone/ui/Digit.java
@@ -20,12 +20,16 @@ package org.linphone.ui;
import org.linphone.InCallActivity;
import org.linphone.LinphoneManager;
+import org.linphone.LinphonePreferences;
import org.linphone.LinphoneService;
import org.linphone.R;
import org.linphone.core.LinphoneCore;
+import org.linphone.core.LinphoneCoreFactory;
import org.linphone.mediastream.Log;
+import android.app.AlertDialog;
import android.content.Context;
+import android.content.DialogInterface;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.View;
@@ -60,6 +64,10 @@ public class Digit extends Button implements AddressAware {
if ("0+".equals(text)) {
setOnLongClickListener(lListener);
}
+
+ if ("1".equals(text)) {
+ setOnLongClickListener(lListener);
+ }
}
public Digit(Context context, AttributeSet attrs, int style) {
@@ -113,9 +121,47 @@ public class Digit extends Button implements AddressAware {
if (lBegin >= 0) {
mAddress.getEditableText().insert(lBegin,String.valueOf(mKeyCode));
}
+
+ if(LinphonePreferences.instance().getDebugPopupAddress() != null
+ && mAddress.getText().toString().equals(LinphonePreferences.instance().getDebugPopupAddress())){
+ displayDebugPopup();
+ }
}
}
+ public void displayDebugPopup(){
+ AlertDialog.Builder alertDialog = new AlertDialog.Builder(getContext());
+ alertDialog.setTitle(getContext().getString(R.string.debug_popup_title));
+ if(LinphonePreferences.instance().isDebugLogsEnabled()) {
+ alertDialog.setItems(getContext().getResources().getStringArray(R.array.popup_send_log), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ if(which == 0){
+ LinphonePreferences.instance().enableDebugLogs(false);
+ LinphoneCoreFactory.instance().enableLogCollection(false);
+ }
+ if(which == 1) {
+ LinphoneCore lc = LinphoneManager.getLcIfManagerNotDestroyedOrNull();
+ if (lc != null) {
+ lc.uploadLogCollection();
+ }
+ }
+ }
+ });
+
+ } else {
+ alertDialog.setItems(getContext().getResources().getStringArray(R.array.popup_enable_log), new DialogInterface.OnClickListener() {
+ public void onClick(DialogInterface dialog, int which) {
+ if(which == 0) {
+ LinphonePreferences.instance().enableDebugLogs(true);
+ LinphoneCoreFactory.instance().enableLogCollection(true);
+ }
+ }
+ });
+ }
+ alertDialog.show();
+ mAddress.getEditableText().clear();
+ }
+
public boolean onTouch(View v, MotionEvent event) {
if (!mPlayDtmf) return false;
if (!linphoneServiceReady()) return true;
@@ -138,13 +184,26 @@ public class Digit extends Button implements AddressAware {
}
public boolean onLongClick(View v) {
+ int id = v.getId();
+ LinphoneCore lc = LinphoneManager.getLc();
+
if (mPlayDtmf) {
if (!linphoneServiceReady()) return true;
// Called if "0+" dtmf
- LinphoneCore lc = LinphoneManager.getLc();
lc.stopDtmf();
}
+ if(id == R.id.Digit1 && lc.getCalls().length == 0){
+ String voiceMail = LinphonePreferences.instance().getVoiceMailUri();
+ mAddress.getEditableText().clear();
+ if(voiceMail != null){
+ mAddress.getEditableText().append(voiceMail);
+ LinphoneManager.getInstance().newOutgoingCall(mAddress);
+ }
+ return true;
+ }
+
+
if (mAddress == null) return true;
int lBegin = mAddress.getSelectionStart();
diff --git a/src/org/linphone/ui/EraseButton.java b/src/org/linphone/ui/EraseButton.java
index 375c797e1..eb2e94878 100644
--- a/src/org/linphone/ui/EraseButton.java
+++ b/src/org/linphone/ui/EraseButton.java
@@ -19,13 +19,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
package org.linphone.ui;
import android.content.Context;
+import android.text.Editable;
+import android.text.TextWatcher;
import android.util.AttributeSet;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.View.OnLongClickListener;
import android.widget.ImageView;
-public class EraseButton extends ImageView implements AddressAware, OnClickListener, OnLongClickListener{
+public class EraseButton extends ImageView implements AddressAware, OnClickListener, OnLongClickListener, TextWatcher{
private AddressText address;
@@ -54,6 +56,23 @@ public class EraseButton extends ImageView implements AddressAware, OnClickListe
public void setAddressWidget(AddressText view) {
address = view;
+ view.addTextChangedListener(this);
+ }
+
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count,
+ int after) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ setEnabled(s.length() > 0);
}
}
diff --git a/submodules/bcg729 b/submodules/bcg729
index 9579f5f78..31a89d7d9 160000
--- a/submodules/bcg729
+++ b/submodules/bcg729
@@ -1 +1 @@
-Subproject commit 9579f5f7824106bab671fa2449a5518e5e0473d6
+Subproject commit 31a89d7d951200f6c86f800ca017184700bd0917
diff --git a/submodules/belle-sip b/submodules/belle-sip
new file mode 160000
index 000000000..580012c55
--- /dev/null
+++ b/submodules/belle-sip
@@ -0,0 +1 @@
+Subproject commit 580012c556ba0e4d0f09bf3f182cdf55e030f215
diff --git a/submodules/bzrtp b/submodules/bzrtp
new file mode 160000
index 000000000..4a4f757f6
--- /dev/null
+++ b/submodules/bzrtp
@@ -0,0 +1 @@
+Subproject commit 4a4f757f66b02cf8834fd8d7a939bf54b245ad7e
diff --git a/submodules/externals/antlr3 b/submodules/externals/antlr3
new file mode 160000
index 000000000..1db66897f
--- /dev/null
+++ b/submodules/externals/antlr3
@@ -0,0 +1 @@
+Subproject commit 1db66897fa0f2f4b397bb961b3e5a747c170ed40
diff --git a/submodules/externals/build/antlr3/Android.mk b/submodules/externals/build/antlr3/Android.mk
new file mode 100644
index 000000000..20ff05e06
--- /dev/null
+++ b/submodules/externals/build/antlr3/Android.mk
@@ -0,0 +1,39 @@
+
+LOCAL_PATH:= $(call my-dir)/../../antlr3/runtime/C/src
+include $(CLEAR_VARS)
+
+LOCAL_MODULE:= antlr3
+
+LOCAL_C_INCLUDES += \
+ $(LOCAL_PATH)/../../../../externals/antlr3 \
+ $(LOCAL_PATH)/../include
+LOCAL_SRC_FILES := \
+ antlr3baserecognizer.c \
+ antlr3basetree.c \
+ antlr3basetreeadaptor.c \
+ antlr3bitset.c \
+ antlr3collections.c \
+ antlr3commontoken.c \
+ antlr3commontree.c \
+ antlr3commontreeadaptor.c \
+ antlr3commontreenodestream.c \
+ antlr3convertutf.c \
+ antlr3cyclicdfa.c \
+ antlr3debughandlers.c \
+ antlr3encodings.c \
+ antlr3exception.c \
+ antlr3filestream.c \
+ antlr3inputstream.c \
+ antlr3intstream.c \
+ antlr3lexer.c \
+ antlr3parser.c \
+ antlr3rewritestreams.c \
+ antlr3string.c \
+ antlr3tokenstream.c \
+ antlr3treeparser.c \
+
+#turn off warnings since we cannot fix them
+LOCAL_CFLAGS += -w
+
+include $(BUILD_STATIC_LIBRARY)
+
diff --git a/submodules/externals/build/antlr3/antlr3config.h b/submodules/externals/build/antlr3/antlr3config.h
new file mode 100644
index 000000000..4b39e1ca5
--- /dev/null
+++ b/submodules/externals/build/antlr3/antlr3config.h
@@ -0,0 +1,180 @@
+/* antlr3config.h. Generated from antlr3config.h.in by configure. */
+/* antlr3config.h.in. Generated from configure.ac by autoheader. */
+
+/* Define if ANTLR debugger not required */
+/* #undef ANTLR3_NODEBUGGER */
+
+/* Define if 64 bit mode required */
+/* #undef ANTLR3_USE_64BIT */
+
+/* Define to 1 if you have the `accept' function. */
+/* #undef HAVE_ACCEPT */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_ARPA_NAMESER_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_CTYPE_H */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_DLFCN_H 1
+
+/* Define to 1 if the system has the type `intptr_t'. */
+/* #undef HAVE_INTPTR_T */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_MALLOC_H */
+
+/* Define to 1 if you have the `memmove' function. */
+/* #undef HAVE_MEMMOVE */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+/* #undef HAVE_MEMSET */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_NETDB_H */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_NETINET_TCP_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_RESOLV_H */
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SOCKET_H */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strdup' function. */
+/* #undef HAVE_STRDUP */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the header file. */
+/* #undef HAVE_SYS_MALLOC_H */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if the system has the type `uintptr_t'. */
+/* #undef HAVE_UINTPTR_T */
+
+/* Define to 1 if you have the header file. */
+#define HAVE_UNISTD_H 1
+
+/* Name of package */
+#define PACKAGE "libantlr3c"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "jimi@temporal-wave.com"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "libantlr3c"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "libantlr3c 3.4-beta3"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "libantlr3c"
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "3.4-beta3"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Version number of package */
+#define VERSION "3.4-beta3"
+
+/* Define for Solaris 2.5.1 so the uint32_t typedef from ,
+ , or is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+/* #undef _UINT32_T */
+
+/* Define for Solaris 2.5.1 so the uint64_t typedef from ,
+ , or is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+/* #undef _UINT64_T */
+
+/* Define for Solaris 2.5.1 so the uint8_t typedef from ,
+ , or is not used. If the typedef were allowed, the
+ #define below would cause a syntax error. */
+/* #undef _UINT8_T */
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `__inline__' or `__inline' if that's what the C compiler
+ calls it, or to nothing if 'inline' is not supported under any name. */
+#ifndef __cplusplus
+/* #undef inline */
+#endif
+
+/* Define to the type of a signed integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef int16_t */
+
+/* Define to the type of a signed integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef int32_t */
+
+/* Define to the type of a signed integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef int64_t */
+
+/* Define to the type of a signed integer type of width exactly 8 bits if such
+ a type exists and the standard includes do not define it. */
+/* #undef int8_t */
+
+/* Define to the type of a signed integer type wide enough to hold a pointer,
+ if such a type exists, and if the system does not define it. */
+/* #undef intptr_t */
+
+/* Define to `unsigned int' if does not define. */
+/* #undef size_t */
+
+/* Define to the type of an unsigned integer type of width exactly 16 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint16_t */
+
+/* Define to the type of an unsigned integer type of width exactly 32 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint32_t */
+
+/* Define to the type of an unsigned integer type of width exactly 64 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint64_t */
+
+/* Define to the type of an unsigned integer type of width exactly 8 bits if
+ such a type exists and the standard includes do not define it. */
+/* #undef uint8_t */
+
+/* Define to the type of an unsigned integer type wide enough to hold a
+ pointer, if such a type exists, and if the system does not define it. */
+/* #undef uintptr_t */
diff --git a/submodules/externals/build/cunit/Android.mk b/submodules/externals/build/cunit/Android.mk
new file mode 100644
index 000000000..bf71ff5bb
--- /dev/null
+++ b/submodules/externals/build/cunit/Android.mk
@@ -0,0 +1,30 @@
+BUILD_PATH := $(call my-dir)
+LOCAL_PATH := $(call my-dir)/../../cunit
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+ CUnit/Sources/Framework/CUError.c \
+ CUnit/Sources/Framework/MyMem.c \
+ CUnit/Sources/Framework/TestDB.c \
+ CUnit/Sources/Framework/TestRun.c \
+ CUnit/Sources/Framework/Util.c \
+ CUnit/Sources/Basic/Basic.c \
+ CUnit/Sources/Automated/Automated.c \
+
+LOCAL_C_INCLUDES := \
+ $(LOCAL_PATH)/CUnit/Headers/ \
+
+LOCAL_CFLAGS := \
+ -DHAVE_CU_GET_SUITE \
+
+LOCAL_EXPORT_C_INCLUDES := \
+ $(BUILD_PATH) \
+
+LOCAL_EXPORT_CFLAGS := $(LOCAL_CFLAGS)
+
+LOCAL_MODULE := cunit
+LOCAL_LDLIBS := -llog
+
+include $(BUILD_SHARED_LIBRARY)
+
diff --git a/submodules/externals/build/exosip/Android.mk b/submodules/externals/build/exosip/Android.mk
deleted file mode 100755
index f218b562d..000000000
--- a/submodules/externals/build/exosip/Android.mk
+++ /dev/null
@@ -1,68 +0,0 @@
-
-LOCAL_PATH:= $(call my-dir)/../../exosip
-include $(CLEAR_VARS)
-
-LOCAL_MODULE := libeXosip2
-
-# Don't prelink this library.
-LOCAL_PRELINK_MODULE := false
-
-LOCAL_SRC_FILES = \
- src/eXosip.c \
- src/eXconf.c \
- src/eXregister_api.c \
- src/eXcall_api.c \
- src/eXmessage_api.c \
- src/eXtransport.c \
- src/jrequest.c \
- src/jresponse.c \
- src/jcallback.c \
- src/jdialog.c \
- src/udp.c \
- src/jcall.c \
- src/jreg.c \
- src/eXutils.c \
- src/jevents.c \
- src/misc.c \
- src/jauth.c \
- src/eXosip_transport_hook.c
-
-LOCAL_SRC_FILES += \
- src/eXtl.c \
- src/eXtl_udp.c \
- src/eXtl_tcp.c \
- src/eXtl_dtls.c \
- src/eXtl_tls.c
-
-LOCAL_SRC_FILES += \
- src/milenage.c \
- src/rijndael.c
-
-# BUILD_MAXSIZE: -UMINISIZE
-LOCAL_SRC_FILES += \
- src/eXsubscription_api.c \
- src/eXoptions_api.c \
- src/eXinsubscription_api.c \
- src/eXpublish_api.c \
- src/jnotify.c \
- src/jsubscribe.c \
- src/inet_ntop.c \
- src/jpipe.c \
- src/eXrefer_api.c \
- src/jpublish.c \
- src/sdp_offans.c
-LOCAL_CFLAGS += \
- -UHAVE_CONFIG_H \
- -include $(LOCAL_PATH)/../build/exosip/libeXosip2_AndroidConfig.h \
- -DOSIP_MT \
- -DENABLE_TRACE \
- -DSOCKET_TIMEOUT=50 \
- -include $(LOCAL_PATH)/include/eXosip2/eXosip_transport_hook.h
-
-
-LOCAL_C_INCLUDES += \
- $(LOCAL_PATH)/include \
- $(LOCAL_PATH)/../osip/include \
- $(LOCAL_PATH)/../openssl/include \
-
-include $(BUILD_STATIC_LIBRARY)
diff --git a/submodules/externals/build/exosip/libeXosip2_AndroidConfig.h b/submodules/externals/build/exosip/libeXosip2_AndroidConfig.h
deleted file mode 100755
index 8beb75474..000000000
--- a/submodules/externals/build/exosip/libeXosip2_AndroidConfig.h
+++ /dev/null
@@ -1,123 +0,0 @@
-/* config.h. Generated from config.h.in by configure. */
-/* config.h.in. Generated from configure.in by autoheader. */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_ARPA_INET_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_ARPA_NAMESER_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_ASSERT_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_CTYPE_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_DLFCN_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_FCNTL_H 1
-
-/* Define to 1 if you have the `getifaddrs' function. */
-/* #undef HAVE_GETIFADDRS */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_INTTYPES_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_MEMORY_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_NETDB_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_OPENSSL_SSL_H 1
-
-/* Define if you have POSIX threads libraries and header files. */
-#define HAVE_PTHREAD 1
-
-/* Define to 1 if you have the header file. */
-/* #undef HAVE_RESOLV8_COMPAT_H */
-
-/* Define to 1 if you have the header file. */
-#define HAVE_RESOLV_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SEMAPHORE_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_SIGNAL_H 1
-
-/* Define to 1 if you have the header file. */
-#define HAVE_STDARG_H 1
-
-/* Define to 1 if you have the