Merge branch 'siacs/master' into development

This commit is contained in:
Christian S 2016-01-13 17:48:30 +01:00
commit 4c2dc70828
43 changed files with 902 additions and 588 deletions

View file

@ -1,6 +1,12 @@
###Changelog
####Versin 1.8.4
####Version 1.9.0
* Per conference notification settings
* Let user decide whether to compress pictures
* Support for XEP-0368
* Ask user to exclude Conversations from battery optimizations
####Version 1.8.4
* prompt to trust own OMEMO devices
* fixed rotation issues in avatar publication
* invite non-contact JIDs to conferences

View file

@ -2,6 +2,7 @@
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:osb="http://www.openswatchbook.org/uri/2009/osb"
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
@ -10,29 +11,122 @@
xmlns:xlink="http://www.w3.org/1999/xlink"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
width="512"
height="512"
id="svg2"
width="57mm"
height="57mm"
viewBox="0 0 201.96849 201.96849"
id="svg4211"
version="1.1"
inkscape:version="0.48.5 r10040"
sodipodi:docname="conversations_baloon.svg"
inkscape:export-filename="/home/diesys/diesys/grafica/conversation/conversation_bubble.png"
inkscape:export-xdpi="100"
inkscape:export-ydpi="100">
inkscape:version="0.91 r13725"
sodipodi:docname="conversations_baloon.svg">
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
showguides="false"
inkscape:zoom="2.2196812"
inkscape:cx="39.109276"
inkscape:cy="132.27753"
inkscape:window-width="1600"
inkscape:window-height="836"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
inkscape:current-layer="layer8" />
<defs
id="defs4">
id="defs4213">
<linearGradient
inkscape:collect="always"
id="linearGradient3874">
osb:paint="solid"
id="linearGradient5393">
<stop
style="stop-color:#00a000;stop-opacity:1;"
id="stop5395"
offset="0"
id="stop3876" />
<stop
style="stop-color:#00a000;stop-opacity:0;"
offset="1"
id="stop3878" />
style="stop-color:#ffffff;stop-opacity:1;" />
</linearGradient>
<clipPath
id="clipPath4831"
clipPathUnits="userSpaceOnUse">
<circle
style="display:inline;opacity:1;fill:#a00e00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle4833"
cx="883.16943"
cy="677.19611"
r="229.80969" />
</clipPath>
<clipPath
id="clipPath4859"
clipPathUnits="userSpaceOnUse">
<circle
style="display:inline;opacity:1;fill:#a00e00;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle4861"
cx="883.16943"
cy="677.19611"
r="229.80969" />
</clipPath>
<clipPath
id="clipPath5624"
clipPathUnits="userSpaceOnUse">
<g
style="display:inline"
id="g5626"
transform="matrix(0.3835576,0,0,0.3835576,-250.60108,-156.11014)">
<path
sodipodi:nodetypes="ccsssc"
inkscape:connector-curvature="0"
id="path5628"
d="m 1120.8042,772.36056 -118.0025,103.66316 118.5792,46.01918 c 8.4859,3.29325 19.6524,7.94481 27.2622,0.71376 7.3868,-7.01907 5.6502,-14.13839 3.0935,-24.54095 z"
style="display:inline;fill:#4caf50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<circle
transform="matrix(1.0878566,0,0,1.0878566,-57.401992,-79.686482)"
clip-path="url(#clipPath4859)"
r="229.80969"
cy="677.19611"
cx="883.16943"
id="circle5630"
style="display:inline;opacity:1;fill:#4caf50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath10653">
<g
style="display:inline"
id="g10655"
transform="matrix(0.3835576,0,0,0.3835576,-250.60108,-156.11015)"
inkscape:export-xdpi="100"
inkscape:export-ydpi="100">
<path
sodipodi:nodetypes="ccsssc"
inkscape:connector-curvature="0"
id="path10657"
d="m 1120.8042,772.36056 -118.0025,103.66316 118.5792,46.01918 c 8.4859,3.29325 19.6524,7.94481 27.2622,0.71376 7.3868,-7.01907 5.6502,-14.13839 3.0935,-24.54095 z"
style="display:inline;fill:#4caf50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
<circle
transform="matrix(1.0878566,0,0,1.0878566,-57.401992,-79.686482)"
clip-path="url(#clipPath4859)"
r="229.80969"
cy="677.19611"
cx="883.16943"
id="circle10659"
style="display:inline;opacity:1;fill:#4caf50;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</g>
</clipPath>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3913"
id="radialGradient3883"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.68662089,-0.30388739,0.24146012,0.54605188,-300.74233,-264.46964)"
cx="262.33273"
cy="945.23846"
fx="262.33273"
fy="945.23846"
r="185.49754" />
<linearGradient
inkscape:collect="always"
id="linearGradient3913">
@ -45,263 +139,128 @@
offset="1"
id="stop3917" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient3818">
<stop
style="stop-color:#669900;stop-opacity:1"
offset="0"
id="stop3820" />
<stop
style="stop-color:#99cc00;stop-opacity:1"
offset="1"
id="stop3822" />
</linearGradient>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3818"
id="radialGradient3824"
cx="212.07048"
cy="1045.9178"
fx="212.07048"
fy="1045.9178"
r="238.57143"
gradientTransform="matrix(1.9491621,-0.90817722,0.65829208,1.4128498,-879.63121,-248.98648)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3913"
id="radialGradient3919"
cx="362.98563"
cy="379.77524"
fx="362.98563"
fy="379.77524"
r="139.95312"
gradientTransform="matrix(1.3800477,1.0445431,-1.3325077,1.7605059,339.09383,-577.83938)"
gradientUnits="userSpaceOnUse" />
<linearGradient
gradientUnits="userSpaceOnUse"
y2="-155.75885"
x2="114.59022"
y1="35.545681"
x1="114.55434"
id="linearGradient3794"
xlink:href="#linearGradient3788"
inkscape:collect="always" />
<linearGradient
id="linearGradient3788">
<stop
id="stop3790"
offset="0"
style="stop-color:#1eed00;stop-opacity:1;" />
<stop
id="stop3792"
offset="1"
style="stop-color:#abff28;stop-opacity:1;" />
</linearGradient>
<linearGradient
id="linearGradient3821">
<stop
style="stop-color:#ff283d;stop-opacity:1;"
offset="0"
id="stop3823" />
<stop
style="stop-color:#ff28ae;stop-opacity:1;"
offset="1"
id="stop3825" />
</linearGradient>
<linearGradient
id="linearGradient4543">
<stop
style="stop-color:#2e45bf;stop-opacity:1;"
offset="0"
id="stop4545" />
<stop
style="stop-color:#28a7ff;stop-opacity:1;"
offset="1"
id="stop4547" />
</linearGradient>
<linearGradient
inkscape:collect="always"
id="linearGradient4098">
<stop
style="stop-color:#ffffff;stop-opacity:1;"
offset="0"
id="stop4100" />
<stop
style="stop-color:#e6e6e6;stop-opacity:1"
offset="1"
id="stop4102" />
</linearGradient>
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4098"
id="linearGradient3833"
x1="273.81851"
y1="764.74677"
x2="304.14023"
y2="936.47272"
gradientUnits="userSpaceOnUse" />
<linearGradient
inkscape:collect="always"
xlink:href="#linearGradient4098"
id="linearGradient3853"
gradientUnits="userSpaceOnUse"
x1="273.81851"
y1="764.74677"
x2="304.14023"
y2="936.47272" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3818"
id="radialGradient3863"
cx="262.33273"
cy="945.23846"
fx="262.33273"
fy="945.23846"
r="185.49754"
gradientTransform="matrix(1.2253203,-0.54206726,0.43090148,0.97403458,-466.4135,170.11831)"
gradientUnits="userSpaceOnUse" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3818"
id="radialGradient3866"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.2253203,-0.54206726,0.43090148,0.97403458,-466.4135,170.11831)"
cx="262.33273"
cy="945.23846"
fx="262.33273"
fy="945.23846"
r="185.49754" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3913"
id="radialGradient3873"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.3800477,1.0445431,-1.3325077,1.7605059,339.09383,-577.83938)"
cx="321.75275"
cy="386.38751"
fx="321.75275"
fy="386.38751"
r="139.95312" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3818"
id="radialGradient3880"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.2253203,-0.54206726,0.43090148,0.97403458,-466.4135,-370.24387)"
cx="262.33273"
cy="945.23846"
fx="262.33273"
fy="945.23846"
r="185.49754" />
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3913"
id="radialGradient3883"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(1.4430075,-0.63865195,0.50745433,1.1475866,-594.40824,44.803037)"
cx="262.33273"
cy="945.23846"
fx="262.33273"
fy="945.23846"
r="185.49754" />
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath5315">
<g
inkscape:export-ydpi="100"
inkscape:export-xdpi="100"
transform="matrix(0.3835576,0,0,0.3835576,-246.60108,-156.11013)"
id="g5317"
style="display:inline;fill:#00a000;fill-opacity:1">
<path
style="display:inline;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
d="m 1120.8042,772.36056 -118.0025,103.66316 118.5792,46.01918 c 8.4859,3.29325 19.6524,7.94481 27.2622,0.71376 7.3868,-7.01907 5.6502,-14.13839 3.0935,-24.54095 z"
id="path5319"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsssc" />
<circle
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
id="circle5321"
cx="883.16943"
cy="677.19611"
r="229.80969"
clip-path="url(#clipPath4859)"
transform="matrix(1.0878566,0,0,1.0878566,-57.401992,-79.686482)" />
</g>
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6882">
<path
inkscape:connector-curvature="0"
id="path6884"
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6886">
<path
inkscape:connector-curvature="0"
id="path6888"
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6890">
<path
inkscape:connector-curvature="0"
id="path6892"
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6894">
<path
inkscape:connector-curvature="0"
id="path6896"
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6898">
<path
inkscape:connector-curvature="0"
id="path6900"
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6902">
<path
inkscape:connector-curvature="0"
id="path6904"
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6906">
<path
inkscape:connector-curvature="0"
id="path6908"
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</clipPath>
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath6910">
<path
inkscape:connector-curvature="0"
id="path6912"
d="M 99.88867,-2.3837657e-4 A 95.889392,95.889392 0 0 0 4,95.888436 95.889392,95.889392 0 0 0 99.88867,191.77906 95.889392,95.889392 0 0 0 142.59375,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.7793,95.888466 95.889392,95.889392 0 0 0 99.88867,-2.0837657e-4 Z"
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</clipPath>
<filter
inkscape:collect="always"
id="filter3895">
style="color-interpolation-filters:sRGB"
id="filter5640"
x="-0.012227737"
width="1.0244555"
y="-0.011780591"
height="1.0235612">
<feGaussianBlur
inkscape:collect="always"
stdDeviation="2.0013623"
id="feGaussianBlur3897" />
stdDeviation="0.9782166"
id="feGaussianBlur5642" />
</filter>
<radialGradient
inkscape:collect="always"
xlink:href="#linearGradient3874"
id="radialGradient3881"
cx="150.35715"
cy="236.28571"
fx="150.35715"
fy="236.28571"
r="26.887305"
gradientTransform="matrix(1,0,0,0.98671703,0,3.1385771)"
gradientUnits="userSpaceOnUse" />
<clipPath
clipPathUnits="userSpaceOnUse"
id="clipPath5745">
<path
inkscape:connector-curvature="0"
id="path5747"
d="M 99.908581,-2.3831968e-4 A 95.889392,95.889392 0 0 0 4.0199102,95.888436 95.889392,95.889392 0 0 0 99.908581,191.77906 95.889392,95.889392 0 0 0 142.61366,181.70093 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 L 183.8285,142.24002 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 195.79921,95.888466 95.889392,95.889392 0 0 0 99.908581,-2.0831968e-4 Z"
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
</clipPath>
</defs>
<sodipodi:namedview
id="base"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageopacity="0.0"
inkscape:pageshadow="2"
inkscape:zoom="1.4142136"
inkscape:cx="385.13513"
inkscape:cy="237.84331"
inkscape:document-units="px"
inkscape:current-layer="layer4"
showgrid="false"
inkscape:window-width="2560"
inkscape:window-height="1020"
inkscape:window-x="0"
inkscape:window-y="27"
inkscape:window-maximized="1"
showguides="true"
inkscape:guide-bbox="true"
inkscape:snap-to-guides="true"
inkscape:snap-grids="false"
inkscape:object-paths="true"
inkscape:object-nodes="false"
inkscape:snap-nodes="false">
<sodipodi:guide
orientation="1,0"
position="0,534.28571"
id="guide3004" />
<sodipodi:guide
orientation="0,1"
position="394.28571,511.42857"
id="guide3006" />
<sodipodi:guide
orientation="1,0"
position="511.42857,320"
id="guide3008" />
<sodipodi:guide
orientation="0,1"
position="401.42857,0"
id="guide3010" />
<sodipodi:guide
orientation="1,0"
position="17.142857,258.57143"
id="guide3012" />
<sodipodi:guide
orientation="0,1"
position="327.14286,494.28571"
id="guide3014" />
<sodipodi:guide
orientation="0,1"
position="324.28571,17.142857"
id="guide3016" />
<sodipodi:guide
orientation="1,0"
position="494.28571,237.14286"
id="guide3018" />
<sodipodi:guide
orientation="1,0"
position="255.71429,302.85714"
id="guide3022" />
<sodipodi:guide
orientation="1,0"
position="660,-315"
id="guide3904" />
<sodipodi:guide
orientation="0,1"
position="554.28571,475.71429"
id="guide3931" />
<sodipodi:guide
orientation="0,1"
position="581.42857,244.28571"
id="guide3933" />
</sodipodi:namedview>
<metadata
id="metadata7">
id="metadata4216">
<rdf:RDF>
<cc:Work
rdf:about="">
@ -313,78 +272,156 @@
</rdf:RDF>
</metadata>
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(0,-540.36218)"
id="layer9"
inkscape:label="shaddow"
transform="translate(-4,2.6816164)"
style="display:inline">
<path
d="m 253.34375,605.78125 c -107.90463,0 -195.9375,85.86121 -195.9375,191.84375 0,105.98253 88.02779,191.90625 195.9375,191.90625 33.55862,0 59.4324,-6.89467 88.96875,-17.625 l 93.8125,37.81255 A 12.359798,12.359798 0 0 0 452.75,995.28125 L 427.34375,892.59375 C 443.67389,863.93074 449.25,831.2919 449.25,797.625 449.25,691.64506 361.24842,605.78125 253.34375,605.78125 z"
id="path3885"
style="opacity:0.6;fill:#000000;fill-opacity:1;stroke:none;filter:url(#filter3895)"
inkscape:original="M 253.34375 618.125 C 151.96941 618.125 69.75 698.4746 69.75 797.625 C 69.75 896.77539 151.96941 977.1875 253.34375 977.1875 C 287.00054 977.1875 311.5728 970.27778 342.65625 958.71875 L 440.75 998.25 L 414.1875 890.8125 C 431.0772 863.65332 436.90625 831.73711 436.90625 797.625 C 436.90625 698.4746 354.71813 618.125 253.34375 618.125 z "
inkscape:radius="12.358562"
sodipodi:type="inkscape:offset"
transform="matrix(1.1776575,0,0,1.1781783,-45.132882,-150.91395)" />
inkscape:connector-curvature="0"
id="path6914"
d="M 104.88867,0.06226191 A 95.889392,95.889392 0 0 0 8.9999996,95.950936 95.889392,95.889392 0 0 0 104.88867,191.84156 95.889392,95.889392 0 0 0 147.59375,181.76343 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 l -11.34766,-46.16797 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 200.7793,95.950966 95.889392,95.889392 0 0 0 104.88867,0.06229191 Z"
style="display:inline;opacity:0.4;fill:#000000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;filter:url(#filter5640)" />
</g>
<g
style="display:inline"
inkscape:label="bubble"
id="layer4"
inkscape:groupmode="layer"
transform="translate(-4,2.6816348)">
<path
sodipodi:type="inkscape:offset"
inkscape:radius="12.358562"
inkscape:original="M 253.34375 618.125 C 151.96941 618.125 69.75 698.4746 69.75 797.625 C 69.75 896.77539 151.96941 977.1875 253.34375 977.1875 C 287.00054 977.1875 311.5728 970.27778 342.65625 958.71875 L 440.75 998.25 L 414.1875 890.8125 C 431.0772 863.65332 436.90625 831.73711 436.90625 797.625 C 436.90625 698.4746 354.71813 618.125 253.34375 618.125 z "
style="fill:#00a000;fill-opacity:1;stroke:none"
id="path3868"
d="m 253.34375,605.78125 c -107.90463,0 -195.9375,85.86121 -195.9375,191.84375 0,105.98253 88.02779,191.90625 195.9375,191.90625 33.55862,0 59.4324,-6.89467 88.96875,-17.625 l 93.8125,37.81255 A 12.359798,12.359798 0 0 0 452.75,995.28125 L 427.34375,892.59375 C 443.67389,863.93074 449.25,831.2919 449.25,797.625 449.25,691.64506 361.24842,605.78125 253.34375,605.78125 z"
transform="matrix(1.1776575,0,0,1.1781783,-45.132882,-155.6267)" />
<path
style="opacity:0.19211821;fill:url(#radialGradient3883);fill-opacity:1;stroke:none"
d="m 442.08605,700.89397 c -129.66422,0 -234.75863,103.19621 -234.75863,230.48113 0,26.84957 4.6841,52.62718 13.28548,76.5811 10.65333,1.4828 21.54531,2.2461 32.60637,2.2461 39.52053,0 69.99101,-8.1231 104.7747,-20.7651 l 110.479,44.5494 a 14.555607,14.562048 0 0 0 19.57853,-17.0097 L 458.13167,895.99293 c 19.23127,-33.77016 25.79804,-72.22452 25.79804,-111.89014 0,-28.84573 -5.53074,-56.41202 -15.60395,-81.77294 -8.61503,-0.94041 -17.37147,-1.43588 -26.23971,-1.43588 z"
id="path3878"
style="display:inline;opacity:1;fill:#00a000;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:4;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
d="M 104.88867,-1.9377566 A 95.889392,95.889392 0 0 0 8.9999996,93.950918 95.889392,95.889392 0 0 0 104.88867,189.84154 95.889392,95.889392 0 0 0 147.59375,179.76341 l 0.12695,0.0137 40.79297,15.83204 c 3.25479,1.26313 7.53628,3.04697 10.45508,0.27343 2.83326,-2.69222 2.16811,-5.42213 1.1875,-9.41211 L 188.80859,140.3025 a 95.889392,95.889392 0 0 1 -0.002,0.002 l 0,-0.008 0.002,0.006 A 95.889392,95.889392 0 0 0 200.7793,93.950948 95.889392,95.889392 0 0 0 104.88867,-1.9377266 Z"
id="circle6661"
inkscape:connector-curvature="0" />
<path
sodipodi:nodetypes="ccsssscc"
inkscape:connector-curvature="0"
id="path3845"
d="M 478.64112,1025.218 447.36049,898.60749 c 19.89028,-31.99834 26.74288,-69.57172 26.74288,-109.76189 0,-116.81686 -96.79943,-211.48385 -216.18374,-211.48385 -119.38425,0 -216.183656,94.66699 -216.183656,211.48385 0,116.81685 96.799406,211.5536 216.183656,211.5536 39.63617,0 68.58847,-8.14219 105.19417,-21.76075 z"
style="opacity:0;fill:none;stroke:#000000;stroke-width:23.55835724;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:94.23343197, 94.23343197;stroke-dashoffset:0" />
<path
inkscape:connector-curvature="0"
id="path3855"
d="m 253.18246,561.05889 c -5.38379,-0.002 -10.7413,0.0871 -12.77023,0.22089 -16.80965,1.10727 -29.68729,3.05317 -44.38296,6.77453 -5.64799,1.43026 -9.96811,2.69833 -15.19914,4.41816 -3.34052,1.09828 -8.41764,2.85364 -8.68521,3.01909 -0.082,0.0507 3.32705,9.32907 7.98597,21.79631 0.0466,0.12496 0.17057,0.13832 0.33123,0.0736 1.11322,-0.44815 6.45699,-2.29745 8.94283,-3.09273 21.39718,-6.84518 43.95735,-10.19531 66.31683,-9.86723 3.14874,0.0461 7.13319,0.15915 8.83245,0.25775 1.69921,0.0987 3.12161,0.15378 3.16493,0.11037 0.0685,-0.0684 1.53237,-23.21444 1.47209,-23.26905 -0.0122,-0.0117 -1.41064,-0.10943 -3.12817,-0.22089 -2.0869,-0.13546 -7.49683,-0.21852 -12.88062,-0.22088 z m 110.81021,28.16581 c -0.10125,0.10911 -11.15095,20.28455 -11.15095,20.36043 0,0.0184 0.50701,0.31641 1.14084,0.66267 8.38104,4.57856 17.56037,10.63803 25.90897,17.04889 3.23527,2.48434 6.34578,5.02146 9.23674,7.54561 4.2123,3.67784 8.41256,7.68117 12.42754,11.81905 6.38417,6.5796 12.29989,13.4994 17.05071,19.99177 0.65274,0.89212 0.79099,1.01157 1.03047,0.84681 1.13402,-0.7802 18.39736,-13.76959 18.40089,-13.84358 0.005,-0.1 -3.33561,-4.52525 -4.74744,-6.29593 -5.64395,-7.07831 -10.59769,-12.59166 -17.26005,-19.25582 -8.26499,-8.26722 -16.14264,-15.121 -25.02569,-21.71453 -2.5667,-1.90515 -5.21733,-3.78858 -7.9855,-5.6781 -6.60132,-4.50598 -18.71149,-11.82683 -19.02653,-11.48727 z m -274.762206,39.94759 -2.428914,2.57732 c -21.579098,22.69359 -38.068397,49.23025 -48.467963,78.05431 -0.50904,1.41091 -0.957247,2.67589 -0.993643,2.83498 -0.04781,0.20904 2.956962,1.31003 10.78292,3.93954 5.956638,2.00143 10.92488,3.63791 11.040538,3.64502 0.115645,0.007 0.916879,-1.94564 1.803285,-4.34458 9.098432,-24.62317 23.187184,-47.25662 41.659643,-66.93523 l 3.05453,-3.27681 -8.206806,-8.24726 z m 388.222146,115.167 -9.89972,1.91451 c -5.44839,1.06994 -10.56998,2.07187 -11.40857,2.20908 -1.04711,0.17137 -1.54564,0.35016 -1.54564,0.55228 0,0.16187 0.23325,1.63204 0.51522,3.2768 2.70275,15.76547 3.28356,34.63258 1.69287,55.26394 -0.7281,9.44363 -2.34823,21.04449 -3.90099,28.01857 -0.23345,1.0486 -0.37949,1.97667 -0.33118,2.02499 0.0483,0.0483 5.12585,1.1561 11.29809,2.46683 6.17232,1.31067 11.30751,2.37915 11.3718,2.39315 0.0641,0.014 0.45734,-1.73307 0.88322,-3.90272 3.35867,-17.11028 4.82653,-33.18977 4.85786,-53.27572 0.0219,-14.08945 -0.79161,-24.35571 -2.87056,-36.96537 z m -427.268845,64.06345 -0.772838,0.11039 c -0.421858,0.0612 -5.59823,0.67716 -11.482161,1.36226 -5.883927,0.68512 -10.759171,1.30169 -10.819725,1.36228 -0.141991,0.142 0.252313,2.91986 1.140854,8.32086 4.869392,29.59836 15.038358,56.25732 31.539139,82.61977 0.450701,0.72005 0.931445,1.27763 1.06725,1.25182 0.361709,-0.0685 19.423106,-12.2036 19.431349,-12.3709 0.0036,-0.0779 -0.796734,-1.40341 -1.766487,-2.94542 -4.266677,-6.78447 -9.935035,-17.45299 -13.064635,-24.5945 -7.52905,-17.18062 -12.488823,-34.71382 -15.051936,-53.27567 z M 462.40066,926.44149 c -0.46898,0.009 -22.08567,5.38002 -22.2283,5.52269 -0.098,0.0981 22.04129,90.06142 22.37549,91.01382 0.40286,1.1482 3.73284,10.5298 13.56323,8.9156 10.95786,-2.3434 9.8458,-14.6677 8.99628,-14.4751 -0.11284,0.025 -5.02627,-20.61508 -11.18774,-45.58033 -8.79763,-35.64656 -11.26829,-45.40142 -11.51896,-45.39668 z M 143.91794,953.1714 c -0.40943,0.0131 -1.21588,1.3276 -6.29312,9.64634 -3.31435,5.43031 -6.03549,9.92123 -6.03549,9.9777 0,0.13674 3.42858,2.19027 7.06593,4.27089 22.35182,12.78549 47.08561,21.82095 72.42596,26.43487 3.59043,0.654 5.67261,1.0064 11.04051,1.804 0.69401,0.1031 1.36954,0.2073 1.50889,0.2212 0.31484,0.031 0.24386,0.6279 1.87691,-11.45018 0.75094,-5.5542 1.40492,-10.43428 1.47207,-10.86126 0.11781,-0.74877 0.0863,-0.77677 -0.58887,-0.88362 -0.38487,-0.0607 -2.68651,-0.4127 -5.11543,-0.77322 -22.30454,-3.3101 -45.25895,-10.90321 -65.32317,-21.57538 -3.55401,-1.89038 -10.16752,-5.64292 -11.85018,-6.73769 -0.0531,-0.0345 -0.12551,-0.0755 -0.18401,-0.0737 z m 214.22322,9.09404 c -1.98095,0.13013 -4.60205,1.01767 -10.4517,3.12954 -11.29964,4.0795 -24.13159,8.26507 -29.91986,9.75681 -0.83741,0.21582 -1.5445,0.50692 -1.54566,0.62592 -0.002,0.21503 5.72469,22.22722 5.81468,22.34847 0.0552,0.075 6.34708,-1.70267 10.2677,-2.90858 5.09669,-1.5677 13.67295,-4.44246 19.79936,-6.62722 l 6.07232,-2.17225 22.30187,8.98356 c 18.14341,7.31671 22.30098,8.95081 22.41231,8.68881 0.9061,-2.1322 8.61707,-21.32757 8.57483,-21.35419 -0.38803,-0.24492 -49.13929,-19.77601 -49.90327,-19.99221 -1.25781,-0.35596 -2.23399,-0.55669 -3.42258,-0.47866 z"
style="opacity:0.5;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:5.88958931;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
sodipodi:nodetypes="ccssccssscccccccssssscccsssscccscsssccccccssssssssssccccscssccsscccsscsscsssssccsccsscsscsccscccccssc" />
<text
xml:space="preserve"
style="font-style:normal;font-weight:normal;font-size:125px;line-height:1000%;font-family:Sans;letter-spacing:-10.89000034px;word-spacing:5px;fill:#000000;fill-opacity:1;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
x="85.862968"
y="-55.271603"
id="text6634"
sodipodi:linespacing="1000%"><tspan
sodipodi:role="line"
id="tspan6636"
x="85.862968"
y="-55.271603" /></text>
</g>
<g
inkscape:groupmode="layer"
id="layer4"
inkscape:label="Dots">
id="layer8"
inkscape:label="dotted line"
style="display:inline"
transform="translate(-4,2.6816164)">
<path
sodipodi:type="arc"
style="opacity:0.928;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="path3047"
sodipodi:cx="173.57143"
sodipodi:cy="241.28571"
sodipodi:rx="26.428572"
sodipodi:ry="20"
d="m 200,241.28571 a 26.428572,20 0 1 1 -52.85715,0 26.428572,20 0 1 1 52.85715,0 z"
transform="matrix(0.94594594,0,0,1.25,-18.332045,-54.607132)" />
style="opacity:1;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
clip-path="url(#clipPath6910)"
d="m 145.16406,11.183594 -5.13232,9.649402 c -0.77924,1.465076 -0.65974,2.41396 0.66876,3.18097 9.66686,5.488467 18.12303,12.874168 24.86104,21.711122 1.05534,1.616079 2.08054,1.713076 3.67763,0.571565 L 178.04883,40 C 169.45271,27.990203 158.19857,18.128379 145.16406,11.183594 Z"
id="path7364"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csccscc"
transform="translate(4.9999996,-1.9374999)" />
<path
sodipodi:type="arc"
style="opacity:0.928;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="path3047-1"
sodipodi:cx="173.57143"
sodipodi:cy="241.28571"
sodipodi:rx="26.428572"
sodipodi:ry="20"
d="m 200,241.28571 a 26.428572,20 0 1 1 -52.85715,0 26.428572,20 0 1 1 52.85715,0 z"
transform="matrix(0.94594594,0,0,1.25,91.38502,-54.607132)" />
style="opacity:1;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
clip-path="url(#clipPath6906)"
d="m 193.80469,75.615234 -9.62713,2.062751 c -2.66266,0.570512 -3.40763,1.172953 -2.90593,3.917433 0.85823,4.714633 1.30424,9.497137 1.33189,14.293254 -0.028,5.578758 -0.62194,11.137108 -1.77093,16.589918 -0.86591,3.23162 0.13682,3.77092 3.16149,4.58138 l 8.98639,2.30136 c 1.98177,-7.66828 3.00584,-15.55255 3.04883,-23.472658 -0.0187,-6.817681 -0.76446,-13.613926 -2.22461,-20.273438 z"
id="path7366"
inkscape:connector-curvature="0"
sodipodi:nodetypes="csccccccc"
transform="translate(4.9999996,-1.9374999)" />
<path
sodipodi:type="arc"
style="opacity:0.928;fill:#ffffff;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="path3047-1-8"
sodipodi:cx="173.57143"
sodipodi:cy="241.28571"
sodipodi:rx="26.428572"
sodipodi:ry="20"
d="m 200,241.28571 a 26.428572,20 0 1 1 -52.85715,0 26.428572,20 0 1 1 52.85715,0 z"
transform="matrix(0.94594594,0,0,1.25,201.38502,-54.607132)" />
style="opacity:1;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
clip-path="url(#clipPath6902)"
d="m 14.264281,102.76512 -10.2076406,0.87943 c 1.2093798,14.83154 5.8540346,29.17808 13.5664056,41.90429 l 8.544301,-5.23239 c 2.394983,-1.46665 1.895406,-3.37834 0.986202,-5.04513 -5.118253,-9.40257 -8.359018,-19.71635 -9.536202,-30.36553 0,-2.09418 -1.881577,-2.26744 -3.353066,-2.14067 z"
id="path7372"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sccsccs"
transform="translate(4.9999996,-1.9374999)" />
<path
style="opacity:1;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
clip-path="url(#clipPath6898)"
d="m 51.504371,166.60235 -5.82273,8.50898 c 12.710503,8.71282 27.333669,14.23394 42.630859,16.0957 l 1.220329,-9.90843 c 0.355066,-2.88295 -1.085712,-3.52946 -3.332252,-3.90256 -10.402329,-1.73697 -20.373956,-5.45322 -29.373754,-10.94516 -1.647505,-1.06744 -3.639993,-2.30718 -5.322452,0.15147 z"
id="path7370"
inkscape:connector-curvature="0"
sodipodi:nodetypes="sccsccs"
transform="translate(4.9999996,-1.9374999)" />
<path
style="opacity:1;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
clip-path="url(#clipPath6894)"
d="M 32.208984,27.683594 C 21.779177,38.079001 13.883707,50.736882 9.1347656,64.675781 L 19.33617,68.090365 c 1.658147,0.55501 2.832564,-0.120955 3.374272,-1.591979 3.777598,-10.021698 9.470788,-19.210103 16.759132,-27.052307 1.561136,-1.561136 1.567283,-2.960058 0.447507,-4.076606 z"
id="path7374"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsccsc"
transform="translate(4.9999996,-1.9374999)" />
<path
style="opacity:1;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
clip-path="url(#clipPath6890)"
d="M 99.888672,-0.25 C 87.701045,-0.2239408 75.630114,2.1252837 64.322266,6.671875 l 3.530435,8.74898 c 1.063314,2.635062 1.616754,3.526314 4.973913,2.352259 8.692057,-3.031338 17.839027,-4.588849 27.062058,-4.599286 5.555828,0 6.486278,0.350026 6.780788,-3.4460223 l 0.74851,-9.64772758 C 104.9135,-0.12857239 102.40179,-0.23868346 99.888672,-0.25 Z"
id="path7376"
inkscape:connector-curvature="0"
sodipodi:nodetypes="ccsccscc"
transform="translate(4.9999996,-1.9374999)" />
<path
style="display:inline;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
clip-path="url(#clipPath6886)"
d="m 138.72416,168.48439 c -4.17634,2.25458 -8.55959,4.09055 -13.0504,5.63418 -1.00363,0.34498 -1.20742,1.18222 -0.8682,2.27372 l 3.44056,11.0706 c 4.92985,-1.53124 9.72799,-3.45808 14.34766,-5.76172 l 0.12695,0.0137 14.0293,5.44532 4.12174,-10.20577 c 0.7548,-1.86894 -0.0184,-2.7016 -1.59462,-3.31324 l -14.72114,-5.71251 c -1.86679,-0.7244 -3.68834,-0.60144 -5.83185,0.55572 z"
id="path5005"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssccccsssc"
transform="translate(4.9999996,-1.9374999)" />
<path
style="display:inline;fill:#80d080;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
clip-path="url(#clipPath6882)"
d="m 186.53125,152.80469 -10.6386,2.70888 c -0.78879,0.20085 -1.67397,1.02386 -1.35494,2.33801 l 9.75918,40.15428 c 8.56713,5.97538 15.30408,3.06731 11.01563,-9.47266 z"
id="path5071"
inkscape:connector-curvature="0"
sodipodi:nodetypes="cssccc"
transform="translate(4.9999996,-1.9374999)" />
</g>
<g
style="display:inline"
inkscape:label="dots"
id="layer2"
inkscape:groupmode="layer"
transform="translate(-4,2.6816348)">
<g
inkscape:export-ydpi="100"
inkscape:export-xdpi="100"
style="fill:#f5f5f5;fill-opacity:1"
transform="matrix(0.3835576,0,0,0.3835576,-248.17635,-138.86977)"
id="g5126">
<circle
r="27.299093"
style="opacity:1;fill:#f5f5f5;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="path3047-4"
cx="799.11273"
cy="609.86285" />
<circle
r="27.299093"
style="opacity:1;fill:#f5f5f5;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="path3047-1-2"
cx="918.91962"
cy="609.86285" />
<circle
r="27.299093"
style="opacity:1;fill:#f5f5f5;fill-opacity:1;fill-rule:evenodd;stroke:none"
id="path3047-1-8-6"
cx="1039.0352"
cy="609.86285" />
</g>
</g>
<g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="light"
style="display:inline"
transform="translate(-4,2.6816164)">
<path
style="display:inline;opacity:0.19211821;fill:url(#radialGradient3883);fill-opacity:1;stroke:none"
d="m 192.44891,47.715674 c -61.69765,0 -111.704333,49.103472 -111.704333,109.668976 0,12.77573 2.228815,25.0414 6.321575,36.4393 5.069139,0.70557 10.251828,1.06876 15.514978,1.06876 18.80489,0 30.91434,7.28449 47.46533,1.26909 l 54.00234,6.06606 c 5.24363,2.11897 11.63381,1.37954 10.27166,-4.11162 l -14.23663,-57.56735 c 9.15073,-16.06873 12.27539,-34.36633 12.27539,-53.240271 0,-13.72556 -2.63167,-26.842322 -7.42478,-38.909717 -4.09925,-0.447474 -8.2658,-0.683228 -12.48553,-0.683228 z"
id="path3878"
inkscape:connector-curvature="0"
clip-path="url(#clipPath5745)"
transform="translate(4.9800894,-1.9374999)"
sodipodi:nodetypes="sscsccccscs" />
</g>
</svg>

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 25 KiB

View file

@ -57,8 +57,8 @@ android {
minSdkVersion 14
targetSdkVersion 23
versionCode 116
versionName "1.9.0-beta"
versionCode 118
versionName "1.9.0-beta.3"
project.ext.set(archivesBaseName, archivesBaseName + "-" + versionName);
}

View file

@ -13,6 +13,7 @@
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<uses-permission android:name="android.permission.VIBRATE"/>
<uses-permission android:name="android.permission.NFC"/>
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS"/>
<uses-permission
android:name="android.permission.READ_PHONE_STATE"

View file

@ -577,6 +577,7 @@ public class DatabaseBackend extends SQLiteOpenHelper {
public void writeRoster(final Roster roster) {
final Account account = roster.getAccount();
final SQLiteDatabase db = this.getWritableDatabase();
db.beginTransaction();
for (Contact contact : roster.getContacts()) {
if (contact.getOption(Contact.Options.IN_ROSTER)) {
db.insert(Contact.TABLENAME, null, contact.getContentValues());
@ -586,6 +587,8 @@ public class DatabaseBackend extends SQLiteOpenHelper {
db.delete(Contact.TABLENAME, where, whereArgs);
}
}
db.setTransactionSuccessful();
db.endTransaction();
account.setRosterVersion(roster.getVersion());
updateAccount(account);
}

View file

@ -1,6 +1,5 @@
package eu.siacs.conversations.ui;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.ActionBar;
import android.app.AlertDialog;
@ -18,6 +17,7 @@ import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.provider.MediaStore;
import android.provider.Settings;
import android.support.v4.widget.SlidingPaneLayout;
import android.support.v4.widget.SlidingPaneLayout.PanelSlideListener;
import android.util.Log;
@ -38,6 +38,8 @@ import android.widget.Toast;
import net.java.otr4j.session.SessionStatus;
import org.openintents.openpgp.util.OpenPgpApi;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
@ -66,7 +68,6 @@ import eu.siacs.conversations.xmpp.OnUpdateBlocklist;
import eu.siacs.conversations.xmpp.chatstate.ChatState;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
import org.openintents.openpgp.util.OpenPgpApi;
public class ConversationActivity extends XmppActivity
implements OnAccountUpdate, OnConversationUpdate, OnRosterUpdate, OnUpdateBlocklist, XmppConnectionService.OnShowErrorToast {
@ -207,7 +208,7 @@ public class ConversationActivity extends XmppActivity
@Override
public void onItemClick(AdapterView<?> arg0, View clickedView,
int position, long arg3) {
int position, long arg3) {
if (getSelectedConversation() != conversationList.get(position)) {
setSelectedConversation(conversationList.get(position));
ConversationActivity.this.mConversationFragment.reInit(getSelectedConversation());
@ -296,7 +297,7 @@ public class ConversationActivity extends XmppActivity
SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView;
mSlidingPaneLayout.setParallaxDistance(150);
mSlidingPaneLayout
.setShadowResource(R.drawable.es_slidingpane_shadow);
.setShadowResource(R.drawable.es_slidingpane_shadow);
mSlidingPaneLayout.setSliderFadeColor(0);
mSlidingPaneLayout.setPanelSlideListener(new PanelSlideListener() {
@ -307,7 +308,7 @@ public class ConversationActivity extends XmppActivity
hideKeyboard();
if (xmppConnectionServiceBound) {
xmppConnectionService.getNotificationService()
.setOpenConversation(null);
.setOpenConversation(null);
}
closeContextMenu();
}
@ -504,7 +505,7 @@ public class ConversationActivity extends XmppActivity
case ATTACHMENT_CHOICE_CHOOSE_IMAGE:
intent.setAction(Intent.ACTION_GET_CONTENT);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE,true);
intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);
}
intent.setType("image/*");
chooser = true;
@ -571,16 +572,16 @@ public class ConversationActivity extends XmppActivity
}
switch (attachmentChoice) {
case ATTACHMENT_CHOICE_LOCATION:
getPreferences().edit().putString("recently_used_quick_action","location").apply();
getPreferences().edit().putString("recently_used_quick_action", "location").apply();
break;
case ATTACHMENT_CHOICE_RECORD_VOICE:
getPreferences().edit().putString("recently_used_quick_action","voice").apply();
getPreferences().edit().putString("recently_used_quick_action", "voice").apply();
break;
case ATTACHMENT_CHOICE_TAKE_PHOTO:
getPreferences().edit().putString("recently_used_quick_action","photo").apply();
getPreferences().edit().putString("recently_used_quick_action", "photo").apply();
break;
case ATTACHMENT_CHOICE_CHOOSE_IMAGE:
getPreferences().edit().putString("recently_used_quick_action","picture").apply();
getPreferences().edit().putString("recently_used_quick_action", "picture").apply();
break;
}
final Conversation conversation = getSelectedConversation();
@ -620,19 +621,19 @@ public class ConversationActivity extends XmppActivity
selectPresenceToAttachFile(attachmentChoice, encryption);
} else {
final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
.findFragmentByTag("conversation");
.findFragmentByTag("conversation");
if (fragment != null) {
fragment.showNoPGPKeyDialog(false,
new OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
int which) {
conversation
.setNextEncryption(Message.ENCRYPTION_NONE);
.setNextEncryption(Message.ENCRYPTION_NONE);
xmppConnectionService.databaseBackend
.updateConversation(conversation);
selectPresenceToAttachFile(attachmentChoice,Message.ENCRYPTION_NONE);
.updateConversation(conversation);
selectPresenceToAttachFile(attachmentChoice, Message.ENCRYPTION_NONE);
}
});
}
@ -647,19 +648,6 @@ public class ConversationActivity extends XmppActivity
}
}
public boolean hasStoragePermission(int attachmentChoice) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, attachmentChoice);
return false;
} else {
return true;
}
} else {
return true;
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (grantResults.length > 0)
@ -672,8 +660,8 @@ public class ConversationActivity extends XmppActivity
attachFile(requestCode);
}
} else {
Toast.makeText(this,R.string.no_storage_permission,Toast.LENGTH_SHORT).show();
}
Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show();
}
}
public void startDownloadable(Message message) {
@ -684,14 +672,14 @@ public class ConversationActivity extends XmppActivity
Transferable transferable = message.getTransferable();
if (transferable != null) {
if (!transferable.start()) {
Toast.makeText(this, R.string.not_connected_try_again,Toast.LENGTH_SHORT).show();
Toast.makeText(this, R.string.not_connected_try_again, Toast.LENGTH_SHORT).show();
}
} else if (message.treatAsDownloadable() != Message.Decision.NEVER) {
xmppConnectionService.getHttpConnectionManager().createNewDownloadConnection(message, true);
}
}
@Override
@Override
public boolean onOptionsItemSelected(final MenuItem item) {
if (item.getItemId() == android.R.id.home) {
showConversationsOverview();
@ -762,9 +750,9 @@ public class ConversationActivity extends XmppActivity
this.mConversationFragment.reInit(getSelectedConversation());
} else {
setSelectedConversation(null);
if (mRedirected.compareAndSet(false,true)) {
if (mRedirected.compareAndSet(false, true)) {
Intent intent = new Intent(this, StartConversationActivity.class);
intent.putExtra("init",true);
intent.putExtra("init", true);
startActivity(intent);
finish();
}
@ -779,7 +767,7 @@ public class ConversationActivity extends XmppActivity
View dialogView = getLayoutInflater().inflate(
R.layout.dialog_clear_history, null);
final CheckBox endConversationCheckBox = (CheckBox) dialogView
.findViewById(R.id.end_conversation_checkbox);
.findViewById(R.id.end_conversation_checkbox);
builder.setView(dialogView);
builder.setNegativeButton(getString(R.string.cancel), null);
builder.setPositiveButton(getString(R.string.delete_messages),
@ -881,7 +869,7 @@ public class ConversationActivity extends XmppActivity
}
PopupMenu popup = new PopupMenu(this, menuItemView);
final ConversationFragment fragment = (ConversationFragment) getFragmentManager()
.findFragmentByTag("conversation");
.findFragmentByTag("conversation");
if (fragment != null) {
popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
@ -902,7 +890,7 @@ public class ConversationActivity extends XmppActivity
conversation.setNextEncryption(Message.ENCRYPTION_PGP);
item.setChecked(true);
} else {
announcePgp(conversation.getAccount(),conversation);
announcePgp(conversation.getAccount(), conversation);
}
} else {
showInstallPgpDialog();
@ -1008,7 +996,7 @@ public class ConversationActivity extends XmppActivity
int rotation = getWindowManager().getDefaultDisplay().getRotation();
final int upKey;
final int downKey;
switch(rotation) {
switch (rotation) {
case Surface.ROTATION_90:
upKey = KeyEvent.KEYCODE_DPAD_LEFT;
downKey = KeyEvent.KEYCODE_DPAD_RIGHT;
@ -1032,7 +1020,7 @@ public class ConversationActivity extends XmppActivity
} else if (modifier && key == downKey) {
if (isConversationsOverviewHideable() && !isConversationsOverviewVisable()) {
showConversationsOverview();
}
}
return selectDownConversation();
} else if (modifier && key == upKey) {
if (isConversationsOverviewHideable() && !isConversationsOverviewVisable()) {
@ -1169,11 +1157,11 @@ public class ConversationActivity extends XmppActivity
public void onSaveInstanceState(final Bundle savedInstanceState) {
Conversation conversation = getSelectedConversation();
if (conversation != null) {
savedInstanceState.putString(STATE_OPEN_CONVERSATION,conversation.getUuid());
savedInstanceState.putString(STATE_OPEN_CONVERSATION, conversation.getUuid());
} else {
savedInstanceState.remove(STATE_OPEN_CONVERSATION);
}
savedInstanceState.putBoolean(STATE_PANEL_OPEN,isConversationsOverviewVisable());
savedInstanceState.putBoolean(STATE_PANEL_OPEN, isConversationsOverviewVisable());
if (this.mPendingImageUris.size() >= 1) {
savedInstanceState.putString(STATE_PENDING_URI, this.mPendingImageUris.get(0).toString());
} else {
@ -1200,7 +1188,7 @@ public class ConversationActivity extends XmppActivity
}
if (xmppConnectionService.getAccounts().size() == 0) {
if (mRedirected.compareAndSet(false,true)) {
if (mRedirected.compareAndSet(false, true)) {
if (Config.X509_VERIFICATION) {
startActivity(new Intent(this, ManageAccountActivity.class));
} else {
@ -1209,9 +1197,9 @@ public class ConversationActivity extends XmppActivity
finish();
}
} else if (conversationList.size() <= 0) {
if (mRedirected.compareAndSet(false,true)) {
if (mRedirected.compareAndSet(false, true)) {
Intent intent = new Intent(this, StartConversationActivity.class);
intent.putExtra("init",true);
intent.putExtra("init", true);
startActivity(intent);
finish();
}
@ -1243,7 +1231,7 @@ public class ConversationActivity extends XmppActivity
this.onActivityResult(mPostponedActivityResult.first, RESULT_OK, mPostponedActivityResult.second);
}
if(!forbidProcessingPendings) {
if (!forbidProcessingPendings) {
for (Iterator<Uri> i = mPendingImageUris.iterator(); i.hasNext(); i.remove()) {
Uri foo = i.next();
attachImageToConversation(getSelectedConversation(), foo);
@ -1260,7 +1248,9 @@ public class ConversationActivity extends XmppActivity
}
forbidProcessingPendings = false;
ExceptionHelper.checkForCrash(this, this.xmppConnectionService);
if (!ExceptionHelper.checkForCrash(this, this.xmppConnectionService)) {
openBatteryOptimizationDialogIfNeeded();
}
setIntent(new Intent());
}
@ -1269,14 +1259,14 @@ public class ConversationActivity extends XmppActivity
final String downloadUuid = intent.getStringExtra(MESSAGE);
final String text = intent.getStringExtra(TEXT);
final String nick = intent.getStringExtra(NICK);
final boolean pm = intent.getBooleanExtra(PRIVATE_MESSAGE,false);
final boolean pm = intent.getBooleanExtra(PRIVATE_MESSAGE, false);
if (selectConversationByUuid(uuid)) {
this.mConversationFragment.reInit(getSelectedConversation());
if (nick != null) {
if (pm) {
Jid jid = getSelectedConversation().getJid();
try {
Jid next = Jid.fromParts(jid.getLocalpart(),jid.getDomainpart(),nick);
Jid next = Jid.fromParts(jid.getLocalpart(), jid.getDomainpart(), nick);
this.mConversationFragment.privateMessageWith(next);
} catch (final InvalidJidException ignored) {
//do nothing
@ -1326,7 +1316,7 @@ public class ConversationActivity extends XmppActivity
Uri uri = intent.getData();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2 && uri == null) {
ClipData clipData = intent.getClipData();
for(int i = 0; i < clipData.getItemCount(); ++i) {
for (int i = 0; i < clipData.getItemCount(); ++i) {
uris.add(clipData.getItemAt(i).getUri());
}
} else {
@ -1336,8 +1326,7 @@ public class ConversationActivity extends XmppActivity
}
@Override
protected void onActivityResult(int requestCode, int resultCode,
final Intent data) {
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
if (requestCode == REQUEST_DECRYPT_PGP) {
@ -1365,15 +1354,15 @@ public class ConversationActivity extends XmppActivity
mPendingImageUris.clear();
mPendingImageUris.addAll(extractUriFromIntent(data));
if (xmppConnectionServiceBound) {
for(Iterator<Uri> i = mPendingImageUris.iterator(); i.hasNext(); i.remove()) {
attachImageToConversation(getSelectedConversation(),i.next());
for (Iterator<Uri> i = mPendingImageUris.iterator(); i.hasNext(); i.remove()) {
attachImageToConversation(getSelectedConversation(), i.next());
}
}
} else if (requestCode == ATTACHMENT_CHOICE_CHOOSE_FILE || requestCode == ATTACHMENT_CHOICE_RECORD_VOICE) {
mPendingFileUris.clear();
mPendingFileUris.addAll(extractUriFromIntent(data));
if (xmppConnectionServiceBound) {
for(Iterator<Uri> i = mPendingFileUris.iterator(); i.hasNext(); i.remove()) {
for (Iterator<Uri> i = mPendingFileUris.iterator(); i.hasNext(); i.remove()) {
attachFileToConversation(getSelectedConversation(), i.next());
}
}
@ -1391,9 +1380,9 @@ public class ConversationActivity extends XmppActivity
mPendingImageUris.clear();
}
} else if (requestCode == ATTACHMENT_CHOICE_LOCATION) {
double latitude = data.getDoubleExtra("latitude",0);
double longitude = data.getDoubleExtra("longitude",0);
this.mPendingGeoUri = Uri.parse("geo:"+String.valueOf(latitude)+","+String.valueOf(longitude));
double latitude = data.getDoubleExtra("latitude", 0);
double longitude = data.getDoubleExtra("longitude", 0);
this.mPendingGeoUri = Uri.parse("geo:" + String.valueOf(latitude) + "," + String.valueOf(longitude));
if (xmppConnectionServiceBound) {
attachLocationToConversation(getSelectedConversation(), mPendingGeoUri);
this.mPendingGeoUri = null;
@ -1408,6 +1397,39 @@ public class ConversationActivity extends XmppActivity
if (requestCode == ConversationActivity.REQUEST_DECRYPT_PGP) {
mConversationFragment.onActivityResult(requestCode, resultCode, data);
}
if (requestCode == REQUEST_BATTERY_OP) {
setNeverAskForBatteryOptimizationsAgain();
}
}
}
private void setNeverAskForBatteryOptimizationsAgain() {
getPreferences().edit().putBoolean("show_battery_optimization", false).commit();
}
private void openBatteryOptimizationDialogIfNeeded() {
if (showBatteryOptimizationWarning() && getPreferences().getBoolean("show_battery_optimizationF", true)) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle(R.string.battery_optimizations_enabled);
builder.setMessage(R.string.battery_optimizations_enabled_dialog);
builder.setPositiveButton(R.string.next, new OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
Uri uri = Uri.parse("package:" + getPackageName());
intent.setData(uri);
startActivityForResult(intent, REQUEST_BATTERY_OP);
}
});
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
setNeverAskForBatteryOptimizationsAgain();
}
});
}
builder.create().show();
}
}

View file

@ -5,9 +5,10 @@ import android.app.AlertDialog.Builder;
import android.app.PendingIntent;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.net.Uri;
import android.os.Bundle;
import android.provider.Settings;
import android.security.KeyChain;
import android.security.KeyChainAliasCallback;
import android.text.Editable;
@ -52,16 +53,17 @@ import eu.siacs.conversations.xmpp.pep.Avatar;
public class EditAccountActivity extends XmppActivity implements OnAccountUpdate,
OnKeyStatusUpdated, OnCaptchaRequested, KeyChainAliasCallback, XmppConnectionService.OnShowErrorToast {
private LinearLayout mMainLayout;
private AutoCompleteTextView mAccountJid;
private EditText mPassword;
private EditText mPasswordConfirm;
private CheckBox mRegisterNew;
private Button mCancelButton;
private Button mSaveButton;
private Button mDisableBatterOptimizations;
private TableLayout mMoreTable;
private LinearLayout mStats;
private RelativeLayout mBatteryOptimizations;
private TextView mServerInfoSm;
private TextView mServerInfoRosterVersion;
private TextView mServerInfoCarbons;
@ -311,6 +313,14 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
});
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_BATTERY_OP) {
updateAccountInformation(mAccount == null);
}
}
protected void updateSaveButton() {
if (accountInfoEdited() && !mInitMode) {
this.mSaveButton.setText(R.string.save);
@ -372,7 +382,6 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_edit_account);
this.mMainLayout = (LinearLayout) findViewById(R.id.account_main_layout);
this.mAccountJid = (AutoCompleteTextView) findViewById(R.id.account_jid);
this.mAccountJid.addTextChangedListener(this.mTextWatcher);
this.mAccountJidLabel = (TextView) findViewById(R.id.account_jid_label);
@ -387,6 +396,17 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
this.mAvatar.setOnClickListener(this.mAvatarClickListener);
this.mRegisterNew = (CheckBox) findViewById(R.id.account_register_new);
this.mStats = (LinearLayout) findViewById(R.id.stats);
this.mBatteryOptimizations = (RelativeLayout) findViewById(R.id.battery_optimization);
this.mDisableBatterOptimizations = (Button) findViewById(R.id.batt_op_disable);
this.mDisableBatterOptimizations.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS);
Uri uri = Uri.parse("package:"+getPackageName());
intent.setData(uri);
startActivityForResult(intent,REQUEST_BATTERY_OP);
}
});
this.mSessionEst = (TextView) findViewById(R.id.session_est);
this.mServerInfoRosterVersion = (TextView) findViewById(R.id.server_info_roster_version);
this.mServerInfoCarbons = (TextView) findViewById(R.id.server_info_carbons);
@ -595,6 +615,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
}
if (this.mAccount.isOnlineAndConnected() && !this.mFetchingAvatar) {
this.mStats.setVisibility(View.VISIBLE);
this.mBatteryOptimizations.setVisibility(showBatteryOptimizationWarning() ? View.VISIBLE : View.GONE);
this.mSessionEst.setText(UIHelper.readableTimeDifferenceFull(this, this.mAccount.getXmppConnection()
.getLastSessionEstablished()));
Features features = this.mAccount.getXmppConnection().getFeatures();

View file

@ -3,6 +3,7 @@ package eu.siacs.conversations.ui;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
@ -137,16 +138,35 @@ public class PublishProfilePictureActivity extends XmppActivity {
@Override
public void onClick(View v) {
Intent attachFileIntent = new Intent();
attachFileIntent.setType("image/*");
attachFileIntent.setAction(Intent.ACTION_GET_CONTENT);
Intent chooser = Intent.createChooser(attachFileIntent, getString(R.string.attach_file));
startActivityForResult(chooser, REQUEST_CHOOSE_FILE);
if (hasStoragePermission(REQUEST_CHOOSE_FILE)) {
chooseAvatar();
}
}
});
this.defaultUri = PhoneHelper.getSefliUri(getApplicationContext());
}
private void chooseAvatar() {
Intent attachFileIntent = new Intent();
attachFileIntent.setType("image/*");
attachFileIntent.setAction(Intent.ACTION_GET_CONTENT);
Intent chooser = Intent.createChooser(attachFileIntent, getString(R.string.attach_file));
startActivityForResult(chooser, REQUEST_CHOOSE_FILE);
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
if (grantResults.length > 0)
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (requestCode == REQUEST_CHOOSE_FILE) {
chooseAvatar();
}
} else {
Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show();
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, final Intent data) {
super.onActivityResult(requestCode, resultCode, data);

View file

@ -42,6 +42,8 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
private Button mSaveButton;
private Button mCancelButton;
private AxolotlService.FetchStatus lastFetchReport = AxolotlService.FetchStatus.SUCCESS;
private final Map<String, Boolean> ownKeysToTrust = new HashMap<>();
private final Map<String, Boolean> foreignKeysToTrust = new HashMap<>();
@ -160,7 +162,11 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
} else {
if (!hasForeignKeys && hasNoOtherTrustedKeys()) {
keyErrorMessageCard.setVisibility(View.VISIBLE);
keyErrorMessage.setText(R.string.error_no_keys_to_trust);
if (lastFetchReport == AxolotlService.FetchStatus.ERROR) {
keyErrorMessage.setText(R.string.error_no_keys_to_trust_server_error);
} else {
keyErrorMessage.setText(R.string.error_no_keys_to_trust);
}
ownKeys.removeAllViews(); ownKeysCard.setVisibility(View.GONE);
foreignKeys.removeAllViews(); foreignKeysCard.setVisibility(View.GONE);
}
@ -216,6 +222,7 @@ public class TrustKeysActivity extends XmppActivity implements OnKeyStatusUpdate
@Override
public void onKeyStatusUpdated(final AxolotlService.FetchStatus report) {
if (report != null) {
lastFetchReport = report;
runOnUiThread(new Runnable() {
@Override
public void run() {

View file

@ -1,5 +1,6 @@
package eu.siacs.conversations.ui;
import android.Manifest;
import android.annotation.SuppressLint;
import android.annotation.TargetApi;
import android.app.ActionBar;
@ -35,6 +36,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.SystemClock;
import android.preference.PreferenceManager;
import android.text.InputType;
@ -91,6 +93,7 @@ public abstract class XmppActivity extends Activity {
protected static final int REQUEST_ANNOUNCE_PGP = 0x0101;
protected static final int REQUEST_INVITE_TO_CONVERSATION = 0x0102;
protected static final int REQUEST_CHOOSE_PGP_ID = 0x0103;
protected static final int REQUEST_BATTERY_OP = 0x13849ff;
public XmppConnectionService xmppConnectionService;
public boolean xmppConnectionServiceBound = false;
@ -375,6 +378,15 @@ public abstract class XmppActivity extends Activity {
}
}
protected boolean showBatteryOptimizationWarning() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
PowerManager pm = (PowerManager) getSystemService(POWER_SERVICE);
return !pm.isIgnoringBatteryOptimizations(getPackageName());
} else {
return false;
}
}
protected boolean usingEnterKey() {
return getPreferences().getBoolean("display_enter_key", false);
}
@ -785,6 +797,19 @@ public abstract class XmppActivity extends Activity {
builder.create().show();
}
public boolean hasStoragePermission(int requestCode) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (checkSelfPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
requestPermissions(new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, requestCode);
return false;
} else {
return true;
}
} else {
return true;
}
}
public void selectPresence(final Conversation conversation,
final OnPresenceSelected listener) {
final Contact contact = conversation.getContact();

View file

@ -19,6 +19,7 @@ import java.util.Collections;
import java.util.List;
import java.util.Random;
import java.util.TreeMap;
import java.util.Map;
import java.util.regex.Pattern;
import de.measite.minidns.Client;
@ -57,7 +58,7 @@ public class DNSHelper {
if (!b.containsKey("values")) {
Log.d(Config.LOGTAG,"all dns queries failed. provide fallback A record");
ArrayList<Parcelable> values = new ArrayList<>();
values.add(createNamePortBundle(host,5222));
values.add(createNamePortBundle(host, 5222, false));
b.putParcelableArrayList("values",values);
}
return b;
@ -96,57 +97,73 @@ public class DNSHelper {
return servers;
}
private static class TlsSrv {
private final SRV srv;
private final boolean tls;
public TlsSrv(SRV srv, boolean tls) {
this.srv = srv;
this.tls = tls;
}
}
private static void fillSrvMaps(final String qname, final InetAddress dnsServer, final Map<Integer, List<TlsSrv>> priorities, final Map<String, List<String>> ips4, final Map<String, List<String>> ips6, final boolean tls) throws IOException {
final DNSMessage message = client.query(qname, TYPE.SRV, CLASS.IN, dnsServer.getHostAddress());
for (Record[] rrset : new Record[][] { message.getAnswers(), message.getAdditionalResourceRecords() }) {
for (Record rr : rrset) {
Data d = rr.getPayload();
if (d instanceof SRV && NameUtil.idnEquals(qname, rr.getName())) {
SRV srv = (SRV) d;
if (!priorities.containsKey(srv.getPriority())) {
priorities.put(srv.getPriority(),new ArrayList<TlsSrv>());
}
priorities.get(srv.getPriority()).add(new TlsSrv(srv, tls));
}
if (d instanceof A) {
A a = (A) d;
if (!ips4.containsKey(rr.getName())) {
ips4.put(rr.getName(), new ArrayList<String>());
}
ips4.get(rr.getName()).add(a.toString());
}
if (d instanceof AAAA) {
AAAA aaaa = (AAAA) d;
if (!ips6.containsKey(rr.getName())) {
ips6.put(rr.getName(), new ArrayList<String>());
}
ips6.get(rr.getName()).add("[" + aaaa.toString() + "]");
}
}
}
}
public static Bundle queryDNS(String host, InetAddress dnsServer) {
Bundle bundle = new Bundle();
try {
client.setTimeout(Config.PING_TIMEOUT * 1000);
String qname = "_xmpp-client._tcp." + host;
final String qname = "_xmpp-client._tcp." + host;
final String tlsQname = "_xmpps-client._tcp." + host;
Log.d(Config.LOGTAG, "using dns server: " + dnsServer.getHostAddress() + " to look up " + host);
DNSMessage message = client.query(qname, TYPE.SRV, CLASS.IN, dnsServer.getHostAddress());
TreeMap<Integer, ArrayList<SRV>> priorities = new TreeMap<>();
TreeMap<String, ArrayList<String>> ips4 = new TreeMap<>();
TreeMap<String, ArrayList<String>> ips6 = new TreeMap<>();
final Map<Integer, List<TlsSrv>> priorities = new TreeMap<>();
final Map<String, List<String>> ips4 = new TreeMap<>();
final Map<String, List<String>> ips6 = new TreeMap<>();
for (Record[] rrset : new Record[][] { message.getAnswers(), message.getAdditionalResourceRecords() }) {
for (Record rr : rrset) {
Data d = rr.getPayload();
if (d instanceof SRV && NameUtil.idnEquals(qname, rr.getName())) {
SRV srv = (SRV) d;
if (!priorities.containsKey(srv.getPriority())) {
priorities.put(srv.getPriority(),new ArrayList<SRV>());
}
priorities.get(srv.getPriority()).add(srv);
}
if (d instanceof A) {
A a = (A) d;
if (!ips4.containsKey(rr.getName())) {
ips4.put(rr.getName(), new ArrayList<String>());
}
ips4.get(rr.getName()).add(a.toString());
}
if (d instanceof AAAA) {
AAAA aaaa = (AAAA) d;
if (!ips6.containsKey(rr.getName())) {
ips6.put(rr.getName(), new ArrayList<String>());
}
ips6.get(rr.getName()).add("[" + aaaa.toString() + "]");
}
}
}
fillSrvMaps(qname, dnsServer, priorities, ips4, ips6, false);
fillSrvMaps(tlsQname, dnsServer, priorities, ips4, ips6, true);
ArrayList<SRV> result = new ArrayList<>();
for (ArrayList<SRV> s : priorities.values()) {
final List<TlsSrv> result = new ArrayList<>();
for (final List<TlsSrv> s : priorities.values()) {
result.addAll(s);
}
ArrayList<Bundle> values = new ArrayList<>();
final ArrayList<Bundle> values = new ArrayList<>();
if (result.size() == 0) {
DNSMessage response;
try {
response = client.query(host, TYPE.A, CLASS.IN, dnsServer.getHostAddress());
for (int i = 0; i < response.getAnswers().length; ++i) {
values.add(createNamePortBundle(host, 5222, response.getAnswers()[i].getPayload()));
values.add(createNamePortBundle(host, 5222, response.getAnswers()[i].getPayload(), false));
}
} catch (SocketTimeoutException e) {
Log.d(Config.LOGTAG,"ignoring timeout exception when querying A record on "+dnsServer.getHostAddress());
@ -154,37 +171,38 @@ public class DNSHelper {
try {
response = client.query(host, TYPE.AAAA, CLASS.IN, dnsServer.getHostAddress());
for (int i = 0; i < response.getAnswers().length; ++i) {
values.add(createNamePortBundle(host, 5222, response.getAnswers()[i].getPayload()));
values.add(createNamePortBundle(host, 5222, response.getAnswers()[i].getPayload(), false));
}
} catch (SocketTimeoutException e) {
Log.d(Config.LOGTAG,"ignoring timeout exception when querying AAAA record on "+dnsServer.getHostAddress());
}
values.add(createNamePortBundle(host,5222));
values.add(createNamePortBundle(host, 5222, false));
bundle.putParcelableArrayList("values", values);
return bundle;
}
for (SRV srv : result) {
for (final TlsSrv tlsSrv : result) {
final SRV srv = tlsSrv.srv;
if (ips6.containsKey(srv.getName())) {
values.add(createNamePortBundle(srv.getName(),srv.getPort(),ips6));
values.add(createNamePortBundle(srv.getName(),srv.getPort(),ips6, tlsSrv.tls));
} else {
try {
DNSMessage response = client.query(srv.getName(), TYPE.AAAA, CLASS.IN, dnsServer.getHostAddress());
for (int i = 0; i < response.getAnswers().length; ++i) {
values.add(createNamePortBundle(srv.getName(), srv.getPort(), response.getAnswers()[i].getPayload()));
values.add(createNamePortBundle(srv.getName(), srv.getPort(), response.getAnswers()[i].getPayload(), tlsSrv.tls));
}
} catch (SocketTimeoutException e) {
Log.d(Config.LOGTAG,"ignoring timeout exception when querying AAAA record on "+dnsServer.getHostAddress());
}
}
if (ips4.containsKey(srv.getName())) {
values.add(createNamePortBundle(srv.getName(),srv.getPort(),ips4));
values.add(createNamePortBundle(srv.getName(),srv.getPort(),ips4, tlsSrv.tls));
} else {
DNSMessage response = client.query(srv.getName(), TYPE.A, CLASS.IN, dnsServer.getHostAddress());
for(int i = 0; i < response.getAnswers().length; ++i) {
values.add(createNamePortBundle(srv.getName(),srv.getPort(),response.getAnswers()[i].getPayload()));
values.add(createNamePortBundle(srv.getName(),srv.getPort(),response.getAnswers()[i].getPayload(), tlsSrv.tls));
}
}
values.add(createNamePortBundle(srv.getName(), srv.getPort()));
values.add(createNamePortBundle(srv.getName(), srv.getPort(), tlsSrv.tls));
}
bundle.putParcelableArrayList("values", values);
} catch (SocketTimeoutException e) {
@ -195,28 +213,31 @@ public class DNSHelper {
return bundle;
}
private static Bundle createNamePortBundle(String name, int port) {
private static Bundle createNamePortBundle(String name, int port, final boolean tls) {
Bundle namePort = new Bundle();
namePort.putString("name", name);
namePort.putBoolean("tls", tls);
namePort.putInt("port", port);
return namePort;
}
private static Bundle createNamePortBundle(String name, int port, TreeMap<String, ArrayList<String>> ips) {
private static Bundle createNamePortBundle(String name, int port, Map<String, List<String>> ips, final boolean tls) {
Bundle namePort = new Bundle();
namePort.putString("name", name);
namePort.putBoolean("tls", tls);
namePort.putInt("port", port);
if (ips!=null) {
ArrayList<String> ip = ips.get(name);
List<String> ip = ips.get(name);
Collections.shuffle(ip, new Random());
namePort.putString("ip", ip.get(0));
}
return namePort;
}
private static Bundle createNamePortBundle(String name, int port, Data data) {
private static Bundle createNamePortBundle(String name, int port, Data data, final boolean tls) {
Bundle namePort = new Bundle();
namePort.putString("name", name);
namePort.putBoolean("tls", tls);
namePort.putInt("port", port);
if (data instanceof A) {
namePort.putString("ip", data.toString());

View file

@ -24,6 +24,7 @@ import eu.siacs.conversations.entities.Account;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.ui.ConversationActivity;
import eu.siacs.conversations.xmpp.jid.InvalidJidException;
import eu.siacs.conversations.xmpp.jid.Jid;
@ -35,14 +36,13 @@ public class ExceptionHelper {
}
}
public static void checkForCrash(Context context,
final XmppConnectionService service) {
public static boolean checkForCrash(ConversationActivity activity, final XmppConnectionService service) {
try {
final SharedPreferences preferences = PreferenceManager
.getDefaultSharedPreferences(context);
.getDefaultSharedPreferences(activity);
boolean neverSend = preferences.getBoolean("never_send", false);
if (neverSend) {
return;
return false;
}
List<Account> accounts = service.getAccounts();
Account account = null;
@ -53,24 +53,25 @@ public class ExceptionHelper {
}
}
if (account == null) {
return;
return false;
}
final Account finalAccount = account;
FileInputStream file = context.openFileInput("stacktrace.txt");
FileInputStream file = activity.openFileInput("stacktrace.txt");
InputStreamReader inputStreamReader = new InputStreamReader(file);
BufferedReader stacktrace = new BufferedReader(inputStreamReader);
final StringBuilder report = new StringBuilder();
PackageManager pm = context.getPackageManager();
PackageManager pm = activity.getPackageManager();
PackageInfo packageInfo = null;
try {
packageInfo = pm.getPackageInfo(context.getPackageName(), 0);
packageInfo = pm.getPackageInfo(activity.getPackageName(), 0);
report.append("Version: " + packageInfo.versionName + '\n');
report.append("Last Update: "
+ DateUtils.formatDateTime(context,
packageInfo.lastUpdateTime,
DateUtils.FORMAT_SHOW_TIME
| DateUtils.FORMAT_SHOW_DATE) + '\n');
+ DateUtils.formatDateTime(activity,
packageInfo.lastUpdateTime,
DateUtils.FORMAT_SHOW_TIME
| DateUtils.FORMAT_SHOW_DATE) + '\n');
} catch (NameNotFoundException e) {
return false;
}
String line;
while ((line = stacktrace.readLine()) != null) {
@ -78,11 +79,11 @@ public class ExceptionHelper {
report.append('\n');
}
file.close();
context.deleteFile("stacktrace.txt");
AlertDialog.Builder builder = new AlertDialog.Builder(context);
builder.setTitle(context.getString(R.string.crash_report_title));
builder.setMessage(context.getText(R.string.crash_report_message));
builder.setPositiveButton(context.getText(R.string.send_now),
activity.deleteFile("stacktrace.txt");
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setTitle(activity.getString(R.string.crash_report_title));
builder.setMessage(activity.getText(R.string.crash_report_message));
builder.setPositiveButton(activity.getText(R.string.send_now),
new OnClickListener() {
@Override
@ -91,18 +92,19 @@ public class ExceptionHelper {
Log.d(Config.LOGTAG, "using account="
+ finalAccount.getJid().toBareJid()
+ " to send in stack trace");
Conversation conversation = null;
try {
conversation = service.findOrCreateConversation(finalAccount,
Jid.fromString("bugs@pix-art.de"), false);
} catch (final InvalidJidException ignored) {
}
Message message = new Message(conversation, report
Conversation conversation = null;
try {
conversation = service.findOrCreateConversation(finalAccount,
Jid.fromString("bugs@pix-art.de"), false);
} catch (final InvalidJidException ignored) {
}
Message message = new Message(conversation, report
.toString(), Message.ENCRYPTION_NONE);
service.sendMessage(message);
}
});
builder.setNegativeButton(context.getText(R.string.send_never),
builder.setNegativeButton(activity.getText(R.string.send_never),
new OnClickListener() {
@Override
@ -112,8 +114,9 @@ public class ExceptionHelper {
}
});
builder.create().show();
return true;
} catch (final IOException ignored) {
}
return false;
}
}
}

View file

@ -0,0 +1,62 @@
package eu.siacs.conversations.utils;
import java.lang.reflect.Method;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
public class SSLSocketHelper {
public static void setSecurity(final SSLSocket sslSocket) throws NoSuchAlgorithmException {
final String[] supportProtocols;
final Collection<String> supportedProtocols = new LinkedList<>(
Arrays.asList(sslSocket.getSupportedProtocols()));
supportedProtocols.remove("SSLv3");
supportProtocols = supportedProtocols.toArray(new String[supportedProtocols.size()]);
sslSocket.setEnabledProtocols(supportProtocols);
final String[] cipherSuites = CryptoHelper.getOrderedCipherSuites(
sslSocket.getSupportedCipherSuites());
if (cipherSuites.length > 0) {
sslSocket.setEnabledCipherSuites(cipherSuites);
}
}
public static void setSNIHost(final SSLSocketFactory factory, final SSLSocket socket, final String hostname) {
if (factory instanceof android.net.SSLCertificateSocketFactory && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN_MR1) {
((android.net.SSLCertificateSocketFactory) factory).setHostname(socket, hostname);
} else {
try {
socket.getClass().getMethod("setHostname", String.class).invoke(socket, hostname);
} catch (Throwable e) {
// ignore any error, we just can't set the hostname...
}
}
}
public static void setAlpnProtocol(final SSLSocketFactory factory, final SSLSocket socket, final String protocol) {
try {
if (factory instanceof android.net.SSLCertificateSocketFactory && android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) {
// can't call directly because of @hide?
//((android.net.SSLCertificateSocketFactory)factory).setAlpnProtocols(new byte[][]{protocol.getBytes("UTF-8")});
android.net.SSLCertificateSocketFactory.class.getMethod("setAlpnProtocols", byte[][].class).invoke(socket, new Object[]{new byte[][]{protocol.getBytes("UTF-8")}});
} else {
final Method method = socket.getClass().getMethod("setAlpnProtocols", byte[].class);
// the concatenation of 8-bit, length prefixed protocol names, just one in our case...
// http://tools.ietf.org/html/draft-agl-tls-nextprotoneg-04#page-4
final byte[] protocolUTF8Bytes = protocol.getBytes("UTF-8");
final byte[] lengthPrefixedProtocols = new byte[protocolUTF8Bytes.length + 1];
lengthPrefixedProtocols[0] = (byte) protocol.length(); // cannot be over 255 anyhow
System.arraycopy(protocolUTF8Bytes, 0, lengthPrefixedProtocols, 1, protocolUTF8Bytes.length);
method.invoke(socket, new Object[]{lengthPrefixedProtocols});
}
} catch (Throwable e) {
// ignore any error, we just can't set the alpn protocol...
}
}
}

View file

@ -20,7 +20,6 @@ import org.xmlpull.v1.XmlPullParserException;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.net.ConnectException;
import java.net.IDN;
@ -35,12 +34,9 @@ import java.security.Principal;
import java.security.PrivateKey;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map.Entry;
@ -66,6 +62,7 @@ import eu.siacs.conversations.generator.IqGenerator;
import eu.siacs.conversations.services.XmppConnectionService;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.DNSHelper;
import eu.siacs.conversations.utils.SSLSocketHelper;
import eu.siacs.conversations.utils.SocksSocketFactory;
import eu.siacs.conversations.utils.Xmlns;
import eu.siacs.conversations.xml.Element;
@ -247,6 +244,7 @@ public class XmppConnection implements Runnable {
}
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": connect to "+destination+" via TOR");
socket = SocksSocketFactory.createSocketOverTor(destination,account.getPort());
startXmpp();
} else if (DNSHelper.isIp(account.getServer().toString())) {
socket = new Socket();
try {
@ -254,13 +252,12 @@ public class XmppConnection implements Runnable {
} catch (IOException e) {
throw new UnknownHostException();
}
startXmpp();
} else {
final Bundle result = DNSHelper.getSRVRecord(account.getServer(),mXmppConnectionService);
final Bundle result = DNSHelper.getSRVRecord(account.getServer(), mXmppConnectionService);
final ArrayList<Parcelable>values = result.getParcelableArrayList("values");
int i = 0;
boolean socketError = true;
while (socketError && values.size() > i) {
final Bundle namePort = (Bundle) values.get(i);
for(Iterator<Parcelable> iterator = values.iterator(); iterator.hasNext();) {
final Bundle namePort = (Bundle) iterator.next();
try {
String srvRecordServer;
try {
@ -271,48 +268,57 @@ public class XmppConnection implements Runnable {
}
final int srvRecordPort = namePort.getInt("port");
final String srvIpServer = namePort.getString("ip");
// if tls is true, encryption is implied and must not be started
features.encryptionEnabled = namePort.getBoolean("tls");
final InetSocketAddress addr;
if (srvIpServer != null) {
addr = new InetSocketAddress(srvIpServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
+ ": using values from dns " + srvRecordServer
+ "[" + srvIpServer + "]:" + srvRecordPort);
+ "[" + srvIpServer + "]:" + srvRecordPort + " tls: " + features.encryptionEnabled);
} else {
addr = new InetSocketAddress(srvRecordServer, srvRecordPort);
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString()
+ ": using values from dns "
+ srvRecordServer + ":" + srvRecordPort);
+ srvRecordServer + ":" + srvRecordPort + " tls: " + features.encryptionEnabled);
}
socket = new Socket();
socket.connect(addr, Config.SOCKET_TIMEOUT * 1000);
socketError = false;
if (!features.encryptionEnabled) {
socket = new Socket();
socket.connect(addr, Config.SOCKET_TIMEOUT * 1000);
} else {
final TlsFactoryVerifier tlsFactoryVerifier = getTlsFactoryVerifier();
socket = tlsFactoryVerifier.factory.createSocket();
if (socket == null) {
throw new IOException("could not initialize ssl socket");
}
SSLSocketHelper.setSecurity((SSLSocket) socket);
SSLSocketHelper.setSNIHost(tlsFactoryVerifier.factory, (SSLSocket) socket, account.getServer().getDomainpart());
SSLSocketHelper.setAlpnProtocol(tlsFactoryVerifier.factory, (SSLSocket) socket, "xmpp-client");
socket.connect(addr, Config.SOCKET_TIMEOUT * 1000);
if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), ((SSLSocket) socket).getSession())) {
Log.d(Config.LOGTAG, account.getJid().toBareJid() + ": TLS certificate verification failed");
throw new SecurityException();
}
}
if (startXmpp())
break; // successfully connected to server that speaks xmpp
} catch(final SecurityException e) {
throw e;
} catch (final Throwable e) {
Log.d(Config.LOGTAG, account.getJid().toBareJid().toString() + ": " + e.getMessage() +"("+e.getClass().getName()+")");
i++;
if (!iterator.hasNext()) {
throw new UnknownHostException();
}
}
}
if (socketError) {
throw new UnknownHostException();
}
}
final OutputStream out = socket.getOutputStream();
tagWriter.setOutputStream(out);
final InputStream in = socket.getInputStream();
tagReader.setInputStream(in);
tagWriter.beginDocument();
sendStartStream();
Tag nextTag;
while ((nextTag = tagReader.readTag()) != null) {
if (nextTag.isStart("stream")) {
processStream();
break;
} else {
throw new IOException("unknown tag on connect");
}
}
if (socket.isConnected()) {
socket.close();
}
processStream();
} catch (final IncompatibleServerException e) {
this.changeStatus(Account.State.INCOMPATIBLE_SERVER);
} catch (final SecurityException e) {
@ -344,6 +350,66 @@ public class XmppConnection implements Runnable {
}
}
/**
* Starts xmpp protocol, call after connecting to socket
* @return true if server returns with valid xmpp, false otherwise
* @throws IOException Unknown tag on connect
* @throws XmlPullParserException Bad Xml
* @throws NoSuchAlgorithmException Other error
*/
private boolean startXmpp() throws IOException, XmlPullParserException, NoSuchAlgorithmException {
tagWriter.setOutputStream(socket.getOutputStream());
tagReader.setInputStream(socket.getInputStream());
tagWriter.beginDocument();
sendStartStream();
Tag nextTag;
while ((nextTag = tagReader.readTag()) != null) {
if (nextTag.isStart("stream")) {
return true;
} else {
throw new IOException("unknown tag on connect");
}
}
if (socket.isConnected()) {
socket.close();
}
return false;
}
private static class TlsFactoryVerifier {
private final SSLSocketFactory factory;
private final HostnameVerifier verifier;
public TlsFactoryVerifier(final SSLSocketFactory factory, final HostnameVerifier verifier) throws IOException {
this.factory = factory;
this.verifier = verifier;
if (factory == null || verifier == null) {
throw new IOException("could not setup ssl");
}
}
}
private TlsFactoryVerifier getTlsFactoryVerifier() throws NoSuchAlgorithmException, KeyManagementException, IOException {
final SSLContext sc = SSLContext.getInstance("TLS");
MemorizingTrustManager trustManager = this.mXmppConnectionService.getMemorizingTrustManager();
KeyManager[] keyManager;
if (account.getPrivateKeyAlias() != null && account.getPassword().isEmpty()) {
keyManager = new KeyManager[]{mKeyManager};
} else {
keyManager = null;
}
sc.init(keyManager, new X509TrustManager[]{mInteractive ? trustManager : trustManager.getNonInteractive()}, mXmppConnectionService.getRNG());
final SSLSocketFactory factory = sc.getSocketFactory();
final HostnameVerifier verifier;
if (mInteractive) {
verifier = trustManager.wrapHostnameVerifier(new XmppDomainVerifier());
} else {
verifier = trustManager.wrapHostnameVerifierNonInteractive(new XmppDomainVerifier());
}
return new TlsFactoryVerifier(factory, verifier);
}
@Override
public void run() {
try {
@ -605,53 +671,27 @@ public class XmppConnection implements Runnable {
tagWriter.writeTag(startTLS);
}
private void switchOverToTls(final Tag currentTag) throws XmlPullParserException, IOException {
tagReader.readTag();
try {
final SSLContext sc = SSLContext.getInstance("TLS");
MemorizingTrustManager trustManager = this.mXmppConnectionService.getMemorizingTrustManager();
KeyManager[] keyManager;
if (account.getPrivateKeyAlias() != null && account.getPassword().isEmpty()) {
keyManager = new KeyManager[]{ mKeyManager };
} else {
keyManager = null;
}
sc.init(keyManager,new X509TrustManager[]{mInteractive ? trustManager : trustManager.getNonInteractive()},mXmppConnectionService.getRNG());
final SSLSocketFactory factory = sc.getSocketFactory();
final HostnameVerifier verifier;
if (mInteractive) {
verifier = trustManager.wrapHostnameVerifier(new XmppDomainVerifier());
} else {
verifier = trustManager.wrapHostnameVerifierNonInteractive(new XmppDomainVerifier());
}
final TlsFactoryVerifier tlsFactoryVerifier = getTlsFactoryVerifier();
final InetAddress address = socket == null ? null : socket.getInetAddress();
if (factory == null || address == null || verifier == null) {
if (address == null) {
throw new IOException("could not setup ssl");
}
final SSLSocket sslSocket = (SSLSocket) factory.createSocket(socket,address.getHostAddress(), socket.getPort(),true);
final SSLSocket sslSocket = (SSLSocket) tlsFactoryVerifier.factory.createSocket(socket, address.getHostAddress(), socket.getPort(), true);
if (sslSocket == null) {
throw new IOException("could not initialize ssl socket");
}
final String[] supportProtocols;
final Collection<String> supportedProtocols = new LinkedList<>(
Arrays.asList(sslSocket.getSupportedProtocols()));
supportedProtocols.remove("SSLv3");
supportProtocols = supportedProtocols.toArray(new String[supportedProtocols.size()]);
SSLSocketHelper.setSecurity(sslSocket);
sslSocket.setEnabledProtocols(supportProtocols);
final String[] cipherSuites = CryptoHelper.getOrderedCipherSuites(
sslSocket.getSupportedCipherSuites());
//Log.d(Config.LOGTAG, "Using ciphers: " + Arrays.toString(cipherSuites));
if (cipherSuites.length > 0) {
sslSocket.setEnabledCipherSuites(cipherSuites);
}
if (!verifier.verify(account.getServer().getDomainpart(),sslSocket.getSession())) {
if (!tlsFactoryVerifier.verifier.verify(account.getServer().getDomainpart(), sslSocket.getSession())) {
Log.d(Config.LOGTAG,account.getJid().toBareJid()+": TLS certificate verification failed");
throw new SecurityException();
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 765 B

After

Width:  |  Height:  |  Size: 765 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 757 B

After

Width:  |  Height:  |  Size: 757 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 779 B

After

Width:  |  Height:  |  Size: 779 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 687 B

After

Width:  |  Height:  |  Size: 687 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 594 B

After

Width:  |  Height:  |  Size: 594 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 598 B

After

Width:  |  Height:  |  Size: 598 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 610 B

After

Width:  |  Height:  |  Size: 610 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 B

After

Width:  |  Height:  |  Size: 558 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 929 B

After

Width:  |  Height:  |  Size: 929 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 921 B

After

Width:  |  Height:  |  Size: 921 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 935 B

After

Width:  |  Height:  |  Size: 935 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 857 B

After

Width:  |  Height:  |  Size: 857 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.7 KiB

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View file

@ -177,6 +177,48 @@
</LinearLayout>
</RelativeLayout>
<RelativeLayout
android:id="@+id/battery_optimization"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="@dimen/activity_vertical_margin"
android:layout_marginLeft="@dimen/activity_horizontal_margin"
android:layout_marginRight="@dimen/activity_horizontal_margin"
android:layout_marginTop="@dimen/activity_vertical_margin"
android:background="@drawable/infocard_border"
android:orientation="vertical"
android:padding="@dimen/infocard_padding"
android:visibility="gone">
<TextView
android:id="@+id/batt_op_headline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/battery_optimizations_enabled"
android:textColor="@color/black87"
android:textSize="?attr/TextSizeHeadline"
android:textStyle="bold"/>
<TextView
android:id="@+id/batt_op_body"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/batt_op_headline"
android:layout_marginBottom="8dp"
android:layout_marginTop="8dp"
android:text="@string/battery_optimizations_enabled_explained"
android:textColor="@color/black87"
android:textSize="?attr/TextSizeBody"/>
<Button
android:id="@+id/batt_op_disable"
style="?android:attr/borderlessButtonStyle"
android:layout_marginRight="-8dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentBottom="true"
android:layout_alignParentEnd="true"
android:layout_alignParentRight="true" android:layout_below="@+id/batt_op_body"
android:text="@string/disable" android:textColor="@color/accent"/>
</RelativeLayout>
<LinearLayout
android:id="@+id/stats"
android:layout_width="fill_parent"
@ -205,7 +247,7 @@
android:layout_height="wrap_content"
android:text="@string/server_info_session_established"
android:textColor="@color/black87"
android:textSize="?attr/TextSizeBody" />
android:textSize="?attr/TextSizeBody"/>
<TextView
android:id="@+id/session_est"
@ -235,7 +277,7 @@
android:layout_height="wrap_content"
android:text="@string/server_info_pep"
android:textColor="@color/black87"
android:textSize="?attr/TextSizeBody" />
android:textSize="?attr/TextSizeBody"/>
<TextView
android:id="@+id/server_info_pep"
@ -256,7 +298,7 @@
android:layout_height="wrap_content"
android:text="@string/server_info_blocking"
android:textColor="@color/black87"
android:textSize="?attr/TextSizeBody" />
android:textSize="?attr/TextSizeBody"/>
<TextView
android:id="@+id/server_info_blocking"
@ -277,7 +319,7 @@
android:layout_height="wrap_content"
android:text="@string/server_info_stream_management"
android:textColor="@color/black87"
android:textSize="?attr/TextSizeBody" />
android:textSize="?attr/TextSizeBody"/>
<TextView
android:id="@+id/server_info_sm"
@ -298,7 +340,7 @@
android:layout_height="wrap_content"
android:text="@string/server_info_roster_version"
android:textColor="@color/black87"
android:textSize="?attr/TextSizeBody" />
android:textSize="?attr/TextSizeBody"/>
<TextView
android:id="@+id/server_info_roster_version"
@ -319,7 +361,7 @@
android:layout_height="wrap_content"
android:text="@string/server_info_carbon_messages"
android:textColor="@color/black87"
android:textSize="?attr/TextSizeBody" />
android:textSize="?attr/TextSizeBody"/>
<TextView
android:id="@+id/server_info_carbons"
@ -340,7 +382,7 @@
android:layout_height="wrap_content"
android:text="@string/server_info_mam"
android:textColor="@color/black87"
android:textSize="?attr/TextSizeBody" />
android:textSize="?attr/TextSizeBody"/>
<TextView
android:id="@+id/server_info_mam"
@ -361,7 +403,7 @@
android:layout_height="wrap_content"
android:text="@string/server_info_csi"
android:textColor="@color/black87"
android:textSize="?attr/TextSizeBody" />
android:textSize="?attr/TextSizeBody"/>
<TextView
android:id="@+id/server_info_csi"
@ -382,7 +424,7 @@
android:layout_height="wrap_content"
android:text="@string/server_info_http_upload"
android:textColor="@color/black87"
android:textSize="?attr/TextSizeBody" />
android:textSize="?attr/TextSizeBody"/>
<TextView
android:id="@+id/server_info_http_upload"
@ -416,13 +458,14 @@
android:textColor="@color/black87"
android:textSize="?attr/TextSizeBody"
android:typeface="monospace" />
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/otr_fingerprint"
android:textColor="@color/black54"
android:textSize="?attr/TextSizeInfo" />
</LinearLayout>
<ImageButton
@ -487,7 +530,7 @@
android:visibility="visible" />
<ImageButton
android:id="@+id/action_regenerate_omemo_key"
android:id="@+id/action_regenerate_axolotl_key"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="?android:selectableItemBackground"
@ -495,7 +538,6 @@
android:padding="@dimen/image_button_padding"
android:src="?attr/icon_refresh"
android:visibility="gone" />
</LinearLayout>
</RelativeLayout>
</LinearLayout>
@ -528,7 +570,8 @@
android:layout_height="wrap_content"
android:divider="?android:dividerHorizontal"
android:orientation="vertical"
android:showDividers="middle"></LinearLayout>
android:showDividers="middle">
</LinearLayout>
</LinearLayout>
</LinearLayout>
</ScrollView>
@ -550,14 +593,14 @@
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/cancel"
android:textColor="@color/black87" />
android:textColor="@color/black87"/>
<View
android:layout_width="1dp"
android:layout_height="fill_parent"
android:layout_marginBottom="7dp"
android:layout_marginTop="7dp"
android:background="@color/black12" />
android:background="@color/black12"/>
<Button
android:id="@+id/save_button"
@ -567,7 +610,7 @@
android:layout_weight="1"
android:enabled="false"
android:text="@string/save"
android:textColor="@color/black54" />
android:textColor="@color/black54"/>
</LinearLayout>
</RelativeLayout>

View file

@ -6,13 +6,13 @@
<View
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_height="match_parent"
android:background="@color/primary"/>
<FrameLayout
android:id="@+id/swipeable_item"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:layout_height="wrap_content"
android:background="@color/grey50">
<RelativeLayout

View file

@ -9,7 +9,7 @@
<string name="action_secure">Verschlüsselte Unterhaltung</string>
<string name="action_add_account">Konto hinzufügen</string>
<string name="action_edit_contact">Namen bearbeiten</string>
<string name="action_add_phone_book">Zum Telefonbuch hinzufügen</string>
<string name="action_add_phone_book">Zu Telefonbuch hinzufügen</string>
<string name="action_delete_contact">Aus Kontaktliste entfernen</string>
<string name="action_block_contact">Kontakt sperren</string>
<string name="action_unblock_contact">Kontakt entsperren</string>
@ -108,8 +108,6 @@
<string name="pref_vibrate_summary">Vibrieren bei Erhalt einer neuen Nachricht</string>
<string name="pref_sound">Benachrichtigungston</string>
<string name="pref_sound_summary">Benachrichtigungston wiedergeben</string>
<string name="pref_conference_notifications">Benachrichtigungen in öffentlichen Konferenzen</string>
<string name="pref_conference_notifications_summary">Bei jeder Nachricht in öffentlichen Konferenzen benachrichtigen und nicht nur, wenn ich angesprochen werde</string>
<string name="pref_notification_grace_period">Gnadenfrist</string>
<string name="pref_notification_grace_period_summary">Deaktiviere Benachrichtigungen für eine kurze Zeit nach Erhalt einer Nachricht, die von einem anderen deiner Clients kommt.</string>
<string name="pref_advanced_options">Erweiterte Optionen</string>
@ -174,7 +172,7 @@
<string name="passwords_do_not_match">Passwörter stimmen nicht überein</string>
<string name="invalid_jid">Ungültige Jabber-ID</string>
<string name="error_out_of_memory">Zu wenig Speicher vorhanden. Das Bild ist zu groß</string>
<string name="add_phone_book_text">Möchtest du %s zum Telefonbuch hinzufügen?</string>
<string name="add_phone_book_text">%s zum Telefonbuch hinzufügen</string>
<string name="contact_status_online">online</string>
<string name="contact_status_free_to_chat">bereit</string>
<string name="contact_status_away">abwesend</string>
@ -244,7 +242,7 @@
<string name="add_back">Auch hinzufügen</string>
<string name="contact_has_read_up_to_this_point">%s hat bis zu diesem Punkt gelesen</string>
<string name="publish">Veröffentlichen</string>
<string name="touch_to_choose_picture">Avatar anklicken, um ein Bild aus der Galerie auszuwählen</string>
<string name="touch_to_choose_picture">Avatar antippen, um Bild aus Galerie auszuwählen</string>
<string name="publish_avatar_explanation">Achtung: Jeder, der deinen Status sehen darf, sieht auch deinen Avatar.</string>
<string name="publishing">Veröffentliche…</string>
<string name="error_publish_avatar_server_reject">Der Server hat die Veröffentlichung des Avatars abgelehnt.</string>
@ -263,7 +261,6 @@
<string name="skip">Überspringen</string>
<string name="disable_notifications">Benachrichtigungen deaktivieren</string>
<string name="disable_notifications_for_this_conversation">Benachrichtigungen für diese Unterhaltung deaktivieren</string>
<string name="notifications_disabled">Benachrichtigungen sind deaktiviert</string>
<string name="enable">Aktivieren</string>
<string name="conference_requires_password">Konferenz ist passwortgeschützt</string>
<string name="enter_password">Passwort eingeben</string>
@ -322,7 +319,6 @@
<string name="verify_otr">OTR prüfen</string>
<string name="remote_fingerprint">Fingerabdruck der Gegenseite</string>
<string name="scan">Scannen</string>
<string name="or_touch_phones">(oder Touch-Handys)</string>
<string name="smp">Socialist Millionaire Protocol</string>
<string name="shared_secret_hint">Hinweis oder Frage</string>
<string name="shared_secret_secret">Gemeinsamer Schlüssel</string>
@ -509,7 +505,7 @@
<string name="pref_away_when_screen_off">Abwesend bei abgeschaltetem Bildschirm</string>
<string name="pref_away_when_screen_off_summary">Setzt deinen Status auf \"abwesend\", solange dein Bildschirm abgeschaltet ist</string>
<string name="pref_xa_on_silent_mode">Nicht verfügbar bei Stummschaltung</string>
<string name="pref_xa_on_silent_mode_summary">Setzt deinen Status auf \"nicht verfügbar\", solange dein Gerät stummgeschaltet ist</string>
<string name="pref_xa_on_silent_mode_summary">Setzt deinen Status auf \"nicht verfügbar\", solange dein Telefon lautlos ist</string>
<string name="action_add_account_with_certificate">Konto mit Zertifikat hinzufügen</string>
<string name="unable_to_parse_certificate">Zertifikat kann nicht gelesen werden</string>
<string name="authenticate_with_certificate">Leer lassen, um mit Zertifikat anzumelden</string>
@ -536,7 +532,7 @@
<string name="send_omemo_x509_message">v\\OMEMO-verschlüsselte Nachricht senden</string>
<string name="verified_omemo_key_with_certificate">OMEMO Schlüssel mit Zertifikat bestätigt!</string>
<string name="pref_connection_options">Verbindungs-Optionen</string>
<string name="pref_use_tor">Mit TOR verbinden</string>
<string name="pref_use_tor">Über TOR verbinden</string>
<string name="pref_use_tor_summary">Alle Verbindungen über das TOR-Netzwerk tunneln. Benötigt Orbot</string>
<string name="account_settings_hostname">Hostname</string>
<string name="account_settings_port">Port</string>
@ -552,21 +548,25 @@
<string name="shared_image_with_x">Bild mit %s geteilt</string>
<string name="no_storage_permission">Pix-Art Messenger benötigt Zugriff auf externen Speicher</string>
<string name="sync_with_contacts">Mit Kontakten synchronisieren</string>
<string name="sync_with_contacts_long">Pix-Art Messenger möchte deine Chat-Kontaktliste mit deinem Telefon-Kontakten abgleichen, um vollständige Namen und Avatare anzuzeigen.\n\nPix-Art Messenger wird deine Kontakte nur lokal lesen und abgleichen und benötigt keinen Abgleich mit dem Server.\n\nDu wirst gefragt, ob du den Zugriff auf deine Kontakte erlauben möchtest.</string>
<string name="always">Immer</string>
<string name="automatically">Automatisch</string>
<string name="certicate_info_not_available">(nicht verfügbar)</string>
<string name="certificate_cn">Gemeinsamer Name</string>
<string name="sync_with_contacts_long">Pix-Art Messenger möchte deine XMPP-Kontaktliste mit deinen Kontakten abgleichen, um deren vollständige Namen und Avatare anzuzeigen.\n\nConversations wird deine Kontakte nur lokal lesen und abgleichen und überträgt diese nicht auf den Server.\n\nDu wirst nun gefragt, ob du den Zugriff auf deine Kontakte erlauben möchtest.</string>
<string name="certificate_information">Zertifikatinformationen</string>
<string name="certificate_subject">Betreff</string>
<string name="certificate_sha1"></string>
<string name="certificate_o">Organisation</string>
<string name="certificate_not_found">Kein Zertifikat gefunden</string>
<string name="certificate_issuer">Aussteller</string>
<string name="certificate_information">Zertifikat-Information</string>
<string name="notify_never">Benachrichtigungen deaktivierten</string>
<string name="certificate_cn">Gemeinsamer Name</string>
<string name="certificate_o">Organisation</string>
<string name="certificate_sha1">SHA1</string>
<string name="certicate_info_not_available">(Nicht verfügbar)</string>
<string name="certificate_not_found">Kein Zertifikat gefunden</string>
<string name="notify_on_all_messages">Bei allen Nachrichten benachrichtigen</string>
<string name="notify_only_when_highlighted">Nur benachrichtigen, wenn ich angesprochen werde</string>
<string name="notify_never">Benachrichtigungen deaktiviert</string>
<string name="notify_paused">Benachrichtigungen pausiert</string>
<string name="pref_picture_compression">Bilder komprimieren</string>
<string name="pref_picture_compression_summary">Bildgröße ändern und komprimieren</string>
<string name="pref_picture_compression_summary">Bildgröße anpassen und komprimieren</string>
<string name="always">Immer</string>
<string name="automatically">Automatisch</string>
<string name="battery_optimizations_enabled">Batterieoptimierung aktiv</string>
<string name="battery_optimizations_enabled_explained">Dein Telefon wendet Batterioptimierungen bei Conversations an, welche verspätete Benachrichtigungen oder Nachrichtenverlust verursachen können.\nEs ist empfehlenswert diese zu deaktivieren.</string>
<string name="battery_optimizations_enabled_dialog">Dein Telefon wendet Batterioptimierungen bei Conversations an, welche verspätete Benachrichtigungen oder Nachrichtenverlust verursachen können. Es ist empfehlenswert dies zu deaktivieren.</string>
<string name="disable">Deaktivieren</string>
</resources>

View file

@ -11,7 +11,7 @@
<string name="action_secure">Secure conversation</string>
<string name="action_add_account">Add account</string>
<string name="action_edit_contact">Edit name</string>
<string name="action_add_phone_book">Add to phone book</string>
<string name="action_add_phone_book">Add to address book</string>
<string name="action_delete_contact">Delete from roster</string>
<string name="action_block_contact">Block contact</string>
<string name="action_unblock_contact">Unblock contact</string>
@ -175,7 +175,7 @@
<string name="passwords_do_not_match">Passwords do not match</string>
<string name="invalid_jid">This is not a valid Jabber ID</string>
<string name="error_out_of_memory">Out of memory. Image is too large</string>
<string name="add_phone_book_text">Do you want to add %s to your devicess contact list?</string>
<string name="add_phone_book_text">Do you want to add %s to your address book?</string>
<string name="contact_status_online">online</string>
<string name="contact_status_free_to_chat">free to chat</string>
<string name="contact_status_away">away</string>
@ -356,7 +356,6 @@
<string name="verify_otr">Verify OTR</string>
<string name="remote_fingerprint">Remote Fingerprint</string>
<string name="scan">scan</string>
<string name="or_touch_phones">(or touch phones)</string>
<string name="smp">Socialist Millionaire Protocol</string>
<string name="shared_secret_hint">Hint or Question</string>
<string name="shared_secret_secret">Shared Secret</string>
@ -410,6 +409,7 @@
<string name="purge_key">Purge key</string>
<string name="purge_key_desc_part1">Are you sure you want to purge this key?</string>
<string name="purge_key_desc_part2">It will irreversibly be considered compromised, and you can never build a session with it again.</string>
<string name="error_no_keys_to_trust_server_error">There are no usable keys available for this contact.\nFetching new keys from the server has been unsuccessful. Maybe there is something wrong with your contacts server.</string>
<string name="error_no_keys_to_trust">There are no usable keys available for this contact. If you have purged any of their keys, they need to generate new ones.</string>
<string name="error_trustkeys_title">Error</string>
<string name="fetching_history_from_server">Fetching history from server</string>
@ -525,7 +525,6 @@
<string name="elv_undo">undo</string>
<string name="pref_use_white_background">Use white background</string>
<string name="pref_use_white_background_summary">Show received messages as black text on a white background</string>
<string name="account_status_dns_timeout">Timeout in DNS</string>
<string name="action_check_update">Check for Updates</string>
<string name="title_activity_updater">Update Service</string>
<string name="update_available">Pix-Art Messenger %1$s with the following changes is available:\n\n%2$s\n\nUpdate Pix-Art Messenger %3$s to Pix-Art Messenger %1$s now?</string>
@ -536,14 +535,14 @@
<string name="current_version">installed version:</string>
<string name="no_update_available">No update available</string>
<string name="download_started">Download started</string>
<string name="account_status_tor_unavailable">TOR network unavailable</string>
<string name="account_status_tor_unavailable">Tor network unavailable</string>
<string name="server_info_broken">Broken</string>
<string name="pref_presence_settings">Presence settings</string>
<string name="pref_away_when_screen_off">Away when screen is off</string>
<string name="pref_away_when_screen_off_summary">Marks your resource as away when the screen is turned off</string>
<string name="pref_xa_on_silent_mode">Not available in silent mode</string>
<string name="pref_xa_on_silent_mode_summary">Marks your resource as not available when phone is in silent mode</string>
<string name="update_info">Pix-Art Messenger is checking for an update. If an update is available you will be asked, if you want to update your version. The update process is downloading and installing the new version automatically.</string>
<string name="pref_xa_on_silent_mode_summary">Marks your resource as not available when device is in silent mode</string>
<string name="action_add_account_with_certificate">Add account with certificate</string>
<string name="unable_to_parse_certificate">Unable to parse certificate</string>
<string name="authenticate_with_certificate">Leave empty to authenticate w/ certificate</string>
@ -562,8 +561,8 @@
<string name="pref_plugin_location">Share-Location</string>
<string name="pref_plugin_location_summary">Send and receive locations</string>
<string name="pref_connection_options">Connection options</string>
<string name="pref_use_tor">Connect via TOR</string>
<string name="pref_use_tor_summary">Tunnel all connections through the TOR network. Requires Orbot</string>
<string name="pref_use_tor">Connect via Tor</string>
<string name="pref_use_tor_summary">Tunnel all connections through the Tor network. Requires Orbot</string>
<string name="account_settings_hostname">Hostname</string>
<string name="account_settings_port">Port</string>
<string name="hostname_or_onion">Server- or .onion-Address</string>
@ -595,4 +594,8 @@
<string name="pref_picture_compression_summary">Resize and compressed pictures</string>
<string name="always">Always</string>
<string name="automatically">Automatically</string>
<string name="battery_optimizations_enabled">Battery optimizations enabled</string>
<string name="battery_optimizations_enabled_explained">Your device is doing some heavy battery optimizations on Conversations that might lead to delayed notifications or even message loss.\nIt is recommended to disable those.</string>
<string name="battery_optimizations_enabled_dialog">Your device is doing some heavy battery optimizations on Conversations that might lead to delayed notifications or even message loss.\n\nYou will now be asked to disable those.</string>
<string name="disable">Disable</string>
</resources>