Browse Source

merged with master

gh-pages
Igor Zhukov 11 years ago
parent
commit
54f74680ed
  1. 5
      app.manifest
  2. 4
      css/app.css
  3. 25
      css/desktop.css
  4. 17
      css/mobile.css
  5. BIN
      img/icons/IconsetW.png
  6. BIN
      img/icons/IconsetW_1x.png
  7. 2
      index.html
  8. 38
      js/app.js
  9. 2
      js/background.js
  10. 119
      js/lib/bin_utils.js
  11. 13
      js/lib/crypto_worker.js
  12. 33
      js/lib/polyfill.js
  13. 5
      js/locales/de-de.json
  14. 6
      js/locales/en-us.json
  15. 31
      js/locales/es-es.json
  16. 11
      js/locales/it-it.json
  17. 2
      manifest.json
  18. 2
      manifest.webapp
  19. 10
      nacl/mtproto_crypto.nmf
  20. BIN
      nacl/mtproto_crypto.pexe
  21. 2
      vendor/angular/i18n/angular-locale_de-de.js
  22. 2
      vendor/angular/i18n/angular-locale_en-us.js
  23. 2
      vendor/angular/i18n/angular-locale_es-es.js
  24. 2
      vendor/angular/i18n/angular-locale_it-it.js
  25. 2
      vendor/angular/i18n/angular-locale_ru-ru.js
  26. 392
      vendor/rusha/rusha.js
  27. 5
      webogram.appcache

5
app.manifest

@ -1,5 +1,5 @@
CACHE MANIFEST CACHE MANIFEST
# Time: Sun Oct 19 2014 12:06:12 GMT+0200 (CEST) # Time: Tue Nov 11 2014 19:24:43 GMT+0300 (MSK)
CACHE: CACHE:
@ -31,6 +31,8 @@ img/logo_dogogram.png
img/logo_share.png img/logo_share.png
img/sound_a.wav img/sound_a.wav
js/app.js js/app.js
nacl/mtproto_crypto.nmf
nacl/mtproto_crypto.pexe
img/changelog/card_wecandoit.png img/changelog/card_wecandoit.png
img/changelog/search.png img/changelog/search.png
img/icons/AboutLogos_1x.png img/icons/AboutLogos_1x.png
@ -76,6 +78,7 @@ vendor/closure/long.js
vendor/cryptoJS/crypto.js vendor/cryptoJS/crypto.js
vendor/jsbn/jsbn_combined.js vendor/jsbn/jsbn_combined.js
vendor/leemon_bigint/bigint.js vendor/leemon_bigint/bigint.js
vendor/rusha/rusha.js
vendor/angular/i18n/angular-locale_de-de.js vendor/angular/i18n/angular-locale_de-de.js
vendor/angular/i18n/angular-locale_en-us.js vendor/angular/i18n/angular-locale_en-us.js
vendor/angular/i18n/angular-locale_es-es.js vendor/angular/i18n/angular-locale_es-es.js

4
css/app.css

File diff suppressed because one or more lines are too long

25
css/desktop.css

@ -179,7 +179,7 @@ a.footer_lang_link.active:active {
.im_history_col .nano > .nano-pane, .im_history_col .nano > .nano-pane,
.contacts_modal_col .nano > .nano-pane, .contacts_modal_col .nano > .nano-pane,
.im_dialogs_modal_col .nano > .nano-pane { .im_dialogs_modal_col .nano > .nano-pane {
background : rgba(3,36,64,0.08); background : rgba(216,223,225,0.45); /*45% d8dfe5*/
width : 9px; width : 9px;
right: 0; right: 0;
top: 0; top: 0;
@ -218,7 +218,7 @@ a.footer_lang_link.active:active {
.im_history_col .nano > .nano-pane > .nano-slider, .im_history_col .nano > .nano-pane > .nano-slider,
.contacts_modal_col .nano > .nano-pane > .nano-slider, .contacts_modal_col .nano > .nano-pane > .nano-slider,
.im_dialogs_modal_col .nano > .nano-pane > .nano-slider { .im_dialogs_modal_col .nano > .nano-pane > .nano-slider {
background : rgba(3,46,79,0.22); background : rgba(137,160,179,0.50); /*50% 89a0b3*/
margin: 0; margin: 0;
-moz-border-radius : 2px; -moz-border-radius : 2px;
-webkit-border-radius : 2px; -webkit-border-radius : 2px;
@ -324,7 +324,7 @@ a.footer_lang_link.active:active {
} }
.icon-message-status { .icon-message-status {
background: #43A4DB; background: #6ba2cb;
border: 0; border: 0;
display: block; display: block;
width: 10px; width: 10px;
@ -381,6 +381,7 @@ a.footer_lang_link.active:active {
font-size: 13px; font-size: 13px;
line-height: 17px; line-height: 17px;
min-width: 60px; min-width: 60px;
border-radius: 2px;
} }
.im_message_selected .im_message_date, .im_message_selected .im_message_date,
@ -393,7 +394,7 @@ a.footer_lang_link.active:active {
.im_history_selectable .im_message_outer_wrap:hover .im_message_audio_duration, .im_history_selectable .im_message_outer_wrap:hover .im_message_audio_duration,
.im_history_selectable .im_message_outer_wrap:hover .im_message_audio_size, .im_history_selectable .im_message_outer_wrap:hover .im_message_audio_size,
.im_history_selectable .im_message_outer_wrap:hover .im_message_fwd_date { .im_history_selectable .im_message_outer_wrap:hover .im_message_fwd_date {
color: #68839c; color: #899daf;
} }
.im_content_message_select_area { .im_content_message_select_area {
@ -492,7 +493,7 @@ a.footer_lang_link.active:active {
.im_panel_own_photo { .im_panel_own_photo {
width: 50px; width: 50px;
height: 50px; height: 50px;
border-radius: 3px; border-radius: 0;
overflow: hidden; overflow: hidden;
} }
div.im_panel_peer_photo { div.im_panel_peer_photo {
@ -505,7 +506,7 @@ div.im_panel_own_photo {
} }
.im_panel_peer_online { .im_panel_peer_online {
background: #6DBF69; background: #6ec26d;
border: 1px solid #FFF; border: 1px solid #FFF;
display: block; display: block;
width: 11px; width: 11px;
@ -516,6 +517,10 @@ div.im_panel_own_photo {
margin-top: -7px; margin-top: -7px;
margin-left: 43px; margin-left: 43px;
} }
.emoji-wysiwyg-editor,
.im_message_field {
border-radius: 0;
}
/* Peer modals */ /* Peer modals */
.user_modal_window .modal-dialog { .user_modal_window .modal-dialog {
@ -547,7 +552,7 @@ div.im_panel_own_photo {
.modal_section_body dt { .modal_section_body dt {
font-weight: normal; font-weight: normal;
display: inline-block; display: inline-block;
width: 80px; width: 100px;
} }
.modal_section_body dd { .modal_section_body dd {
display: inline-block; display: inline-block;
@ -787,6 +792,12 @@ div.im_panel_own_photo {
display: none; display: none;
} }
.settings_volume_slider {
width: 100%;
max-width: 362px;
display: inline-block;
}
.im_message_selected .im_message_outer_wrap, .im_message_selected .im_message_outer_wrap,
.im_message_focus .im_message_outer_wrap { .im_message_focus .im_message_outer_wrap {

17
css/mobile.css

@ -130,7 +130,7 @@ html {
vertical-align: text-top; vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -15px -835px no-repeat; background: url(../img/icons/IconsetW.png) -15px -835px no-repeat;
background-size: 42px 971px; background-size: 42px 1171px;
opacity: 0.8; opacity: 0.8;
} }
.is_1x .icon-back { .is_1x .icon-back {
@ -535,9 +535,7 @@ img.im_message_video_thumb,
color: #93a2ae; color: #93a2ae;
} }
.im_message_out .icon-document, .im_message_out .icon-document {
.im_message_out .icon-photo,
.im_message_out .icon-video {
background-color: #dae6f0; background-color: #dae6f0;
background-position: -2px -542px; background-position: -2px -542px;
} }
@ -961,7 +959,7 @@ a.mobile_modal_action .tg_checkbox_label {
.im_submit:active, .im_submit:active,
.im_submit:hover { .im_submit:hover {
background: url(../img/icons/IconsetW.png) 2px -860px no-repeat; background: url(../img/icons/IconsetW.png) 2px -860px no-repeat;
background-size: 42px 971px; background-size: 42px 1171px;
color: transparent; color: transparent;
box-shadow: none; box-shadow: none;
} }
@ -985,7 +983,7 @@ a.mobile_modal_action .tg_checkbox_label {
height: 23px; height: 23px;
vertical-align: text-top; vertical-align: text-top;
background: url(../img/icons/IconsetW.png) -12px -68px no-repeat; background: url(../img/icons/IconsetW.png) -12px -68px no-repeat;
background-size: 42px 971px; background-size: 42px 1171px;
opacity: 0.8; opacity: 0.8;
} }
.is_1x .icon-paperclip { .is_1x .icon-paperclip {
@ -1022,7 +1020,7 @@ a.mobile_modal_action .tg_checkbox_label {
opacity: 1; opacity: 1;
margin: 0; margin: 0;
background: url(../img/icons/IconsetW.png) -10px -771px no-repeat; background: url(../img/icons/IconsetW.png) -10px -771px no-repeat;
background-size: 42px 971px; background-size: 42px 1171px;
} }
.is_1x .icon-emoji { .is_1x .icon-emoji {
background-image: url(../img/icons/IconsetW_1x.png); background-image: url(../img/icons/IconsetW_1x.png);
@ -1120,3 +1118,8 @@ a.mobile_modal_action .tg_checkbox_label {
.countries_scrollable_wrap a.countries_modal_country { .countries_scrollable_wrap a.countries_modal_country {
padding: 8px 8px; padding: 8px 8px;
} }
.import_modal_phonebook_wrap {
margin-top: 40px;
text-align: center;
}

BIN
img/icons/IconsetW.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 26 KiB

BIN
img/icons/IconsetW_1x.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 13 KiB

2
index.html

@ -1 +1 @@
<!doctype html><html lang=en manifest=webogram.appcache ng-csp xmlns:ng=http://angularjs.org id=ng-app><head><meta charset=utf-8><meta name=viewport content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"><title>Telegram Web</title><link rel=stylesheet href=css/app.css><link rel=icon href=favicon.ico type=image/x-icon><link rel=apple-touch-icon href=img/iphone_home120.png><link rel=apple-touch-icon sizes=120x120 href=img/iphone_home120.png><link rel=apple-touch-startup-image media="(device-width: 320px)" href=img/iphone_startup.png><meta name=apple-mobile-web-app-title content="Telegram Web"><meta name=mobile-web-app-capable content=yes><meta name=apple-mobile-web-app-capable content=yes><meta name=apple-mobile-web-app-status-bar-style content=black-translucent><meta property=og:title content="Telegram Web"><meta property=og:url content="http://zhukov.github.io/webogram/"><meta property=og:image content=http://zhukov.github.io/webogram/img/logo_share.png><meta property=og:site_name content="Telegram Web"><meta property=og:description content="Welcome to the Web application of Telegram messenger. See https://github.com/zhukov/webogram for more info."></head><body><div class=page_wrap ng-view></div><div id=notify_sound></div><script src=js/app.js></script></body></html> <!doctype html><html lang=en manifest=webogram.appcache ng-csp="" xmlns:ng=http://angularjs.org id=ng-app><head><meta charset=utf-8><meta name=viewport content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no"><title>Telegram Web</title><link rel=stylesheet href=css/app.css><link rel=icon href=favicon.ico type=image/x-icon><link rel=apple-touch-icon href=img/iphone_home120.png><link rel=apple-touch-icon sizes=120x120 href=img/iphone_home120.png><link rel=apple-touch-startup-image media="(device-width: 320px)" href=img/iphone_startup.png><meta name=apple-mobile-web-app-title content="Telegram Web"><meta name=mobile-web-app-capable content=yes><meta name=apple-mobile-web-app-capable content=yes><meta name=apple-mobile-web-app-status-bar-style content=black-translucent><meta property=og:title content="Telegram Web"><meta property=og:url content="http://zhukov.github.io/webogram/"><meta property=og:image content=http://zhukov.github.io/webogram/img/logo_share.png><meta property=og:site_name content="Telegram Web"><meta property=og:description content="Welcome to the Web application of Telegram messenger. See https://github.com/zhukov/webogram for more info."></head><body><div class=page_wrap ng-view=""></div><div id=notify_sound></div><script src=js/app.js></script></body></html>

38
js/app.js

File diff suppressed because one or more lines are too long

2
js/background.js

@ -1,5 +1,5 @@
/*! /*!
* Webogram v0.3.2 - messaging web application for MTProto * Webogram v0.3.3 - messaging web application for MTProto
* https://github.com/zhukov/webogram * https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com> * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE * https://github.com/zhukov/webogram/blob/master/LICENSE

119
js/lib/bin_utils.js

@ -1,5 +1,5 @@
/*! /*!
* Webogram v0.3.2 - messaging web application for MTProto * Webogram v0.3.3 - messaging web application for MTProto
* https://github.com/zhukov/webogram * https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com> * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE * https://github.com/zhukov/webogram/blob/master/LICENSE
@ -112,10 +112,12 @@ function bytesXor (bytes1, bytes2) {
} }
function bytesToWords (bytes) { function bytesToWords (bytes) {
if (bytes instanceof ArrayBuffer) {
bytes = new Uint8Array(bytes);
}
var len = bytes.length, var len = bytes.length,
words = []; words = [], i;
for (i = 0; i < len; i++) {
for (var i = 0; i < len; i++) {
words[i >>> 2] |= bytes[i] << (24 - (i % 4) * 8); words[i >>> 2] |= bytes[i] << (24 - (i % 4) * 8);
} }
@ -154,6 +156,37 @@ function bytesToArrayBuffer (b) {
return (new Uint8Array(b)).buffer; return (new Uint8Array(b)).buffer;
} }
function convertToArrayBuffer(bytes) {
// Be careful with converting subarrays!!
if (bytes instanceof ArrayBuffer) {
return bytes;
}
if (bytes.buffer !== undefined &&
bytes.buffer.byteLength == bytes.length * bytes.BYTES_PER_ELEMENT) {
return bytes.buffer;
}
return bytesToArrayBuffer(bytes);
}
function convertToUint8Array(bytes) {
if (bytes.buffer !== undefined) {
return bytes;
}
return new Uint8Array(bytes);
}
function convertToByteArray(bytes) {
if (Array.isArray(bytes)) {
return bytes;
}
bytes = convertToUint8Array(bytes);
var newBytes = [];
for (var i = 0, len = bytes.length; i < len; i++) {
newBytes.push(bytes[i]);
}
return newBytes;
}
function bytesFromArrayBuffer (buffer) { function bytesFromArrayBuffer (buffer) {
var len = buffer.byteLength, var len = buffer.byteLength,
byteView = new Uint8Array(buffer), byteView = new Uint8Array(buffer),
@ -166,6 +199,16 @@ function bytesFromArrayBuffer (buffer) {
return bytes; return bytes;
} }
function bufferConcat(buffer1, buffer2) {
var l1 = buffer1.byteLength || buffer1.length,
l2 = buffer2.byteLength || buffer2.length;
var tmp = new Uint8Array(l1 + l2);
tmp.set(buffer1 instanceof ArrayBuffer ? new Uint8Array(buffer1) : buffer1, 0);
tmp.set(buffer2 instanceof ArrayBuffer ? new Uint8Array(buffer2) : buffer2, l1);
return tmp.buffer;
}
function longToInts (sLong) { function longToInts (sLong) {
var divRem = bigStringInt(sLong).divideAndRemainder(bigint(0x100000000)); var divRem = bigStringInt(sLong).divideAndRemainder(bigint(0x100000000));
@ -195,24 +238,24 @@ function uintToInt (val) {
return val; return val;
} }
function sha1Hash (bytes) { function sha1HashSync (bytes) {
// console.log('SHA-1 hash start'); this.rushaInstance = this.rushaInstance || new Rusha(1024 * 1024);
var hashBytes = sha1.hash(bytes, true);
// console.log('SHA-1 hash finish'); // console.log(dT(), 'SHA-1 hash start', bytes.byteLength || bytes.length);
var hashBytes = rushaInstance.rawDigest(bytes).buffer;
// console.log(dT(), 'SHA-1 hash finish');
return hashBytes; return hashBytes;
} }
function sha1BytesSync (bytes) {
return bytesFromArrayBuffer(sha1HashSync(bytes));
}
function rsaEncrypt (publicKey, bytes) {
var needPadding = 255 - bytes.length;
if (needPadding > 0) {
var padding = new Array(needPadding);
(new SecureRandom()).nextBytes(padding);
bytes = bytes.concat(padding); function rsaEncrypt (publicKey, bytes) {
} bytes = addPadding(bytes, 255);
// console.log('RSA encrypt start'); // console.log('RSA encrypt start');
var N = new BigInteger(publicKey.modulus, 16), var N = new BigInteger(publicKey.modulus, 16),
@ -220,22 +263,34 @@ function rsaEncrypt (publicKey, bytes) {
X = new BigInteger(bytes), X = new BigInteger(bytes),
encryptedBigInt = X.modPowInt(E, N), encryptedBigInt = X.modPowInt(E, N),
encryptedBytes = bytesFromBigInt(encryptedBigInt, 256); encryptedBytes = bytesFromBigInt(encryptedBigInt, 256);
// console.log('RSA encrypt finish'); // console.log('RSA encrypt finish');
return encryptedBytes; return encryptedBytes;
} }
function aesEncrypt (bytes, keyBytes, ivBytes) { function addPadding(bytes, blockSize) {
// console.log('AES encrypt start', bytes.length/*, bytesToHex(keyBytes), bytesToHex(ivBytes)*/); blockSize = blockSize || 16;
var len = bytes.byteLength || bytes.length;
var needPadding = 16 - (bytes.length % 16); var needPadding = blockSize - (len % blockSize);
if (needPadding > 0 && needPadding < 16) { if (needPadding > 0 && needPadding < blockSize) {
var padding = new Array(needPadding); var padding = new Array(needPadding);
(new SecureRandom()).nextBytes(padding); (new SecureRandom()).nextBytes(padding);
if (bytes instanceof ArrayBuffer) {
bytes = bufferConcat(bytes, padding);
} else {
bytes = bytes.concat(padding); bytes = bytes.concat(padding);
} }
}
return bytes;
}
function aesEncryptSync (bytes, keyBytes, ivBytes) {
var len = bytes.byteLength || bytes.length;
// console.log(dT(), 'AES encrypt start', len/*, bytesToHex(keyBytes), bytesToHex(ivBytes)*/);
bytes = addPadding(bytes);
var encryptedWords = CryptoJS.AES.encrypt(bytesToWords(bytes), bytesToWords(keyBytes), { var encryptedWords = CryptoJS.AES.encrypt(bytesToWords(bytes), bytesToWords(keyBytes), {
iv: bytesToWords(ivBytes), iv: bytesToWords(ivBytes),
@ -244,15 +299,14 @@ function aesEncrypt (bytes, keyBytes, ivBytes) {
}).ciphertext; }).ciphertext;
var encryptedBytes = bytesFromWords(encryptedWords); var encryptedBytes = bytesFromWords(encryptedWords);
// console.log(dT(), 'AES encrypt finish');
// console.log('AES encrypt finish');
return encryptedBytes; return encryptedBytes;
} }
function aesDecrypt (encryptedBytes, keyBytes, ivBytes) { function aesDecryptSync (encryptedBytes, keyBytes, ivBytes) {
// console.log('AES decrypt start', encryptedBytes.length/*, bytesToHex(keyBytes), bytesToHex(ivBytes)*/);
// console.log(dT(), 'AES decrypt start', encryptedBytes.length);
var decryptedWords = CryptoJS.AES.decrypt({ciphertext: bytesToWords(encryptedBytes)}, bytesToWords(keyBytes), { var decryptedWords = CryptoJS.AES.decrypt({ciphertext: bytesToWords(encryptedBytes)}, bytesToWords(keyBytes), {
iv: bytesToWords(ivBytes), iv: bytesToWords(ivBytes),
padding: CryptoJS.pad.NoPadding, padding: CryptoJS.pad.NoPadding,
@ -260,8 +314,7 @@ function aesDecrypt (encryptedBytes, keyBytes, ivBytes) {
}); });
var bytes = bytesFromWords(decryptedWords); var bytes = bytesFromWords(decryptedWords);
// console.log(dT(), 'AES decrypt finish');
// console.log('AES decrypt finish');
return bytes; return bytes;
} }
@ -281,7 +334,7 @@ function pqPrimeFactorization (pqBytes) {
var what = new BigInteger(pqBytes), var what = new BigInteger(pqBytes),
result = false; result = false;
console.log('PQ start', pqBytes, what.toString(16), what.bitLength()); // console.log(dT(), 'PQ start', pqBytes, what.toString(16), what.bitLength());
try { try {
result = pqPrimeLeemon(str2bigInt(what.toString(16), 16, Math.ceil(64 / bpe) + 1)) result = pqPrimeLeemon(str2bigInt(what.toString(16), 16, Math.ceil(64 / bpe) + 1))
@ -306,7 +359,7 @@ function pqPrimeFactorization (pqBytes) {
// console.timeEnd('pq BigInt'); // console.timeEnd('pq BigInt');
} }
console.log('PQ finish'); // console.log(dT(), 'PQ finish');
return result; return result;
} }
@ -520,13 +573,15 @@ function pqPrimeLeemon (what) {
function bytesModPow (x, y, m) { function bytesModPow (x, y, m) {
try { try {
var xBigInt = str2bigInt(x, 64), var xBigInt = str2bigInt(bytesToHex(x), 16),
yBigInt = str2bigInt(y, 64), yBigInt = str2bigInt(bytesToHex(y), 16),
mBigInt = str2bigInt(bytesToHex(m), 16, 2), mBigInt = str2bigInt(bytesToHex(m), 16, 2),
resBigInt = powMod(xBigInt, yBigInt, mBigInt); resBigInt = powMod(xBigInt, yBigInt, mBigInt);
return bytesFromHex(bigInt2str(resBigInt, 16)); return bytesFromHex(bigInt2str(resBigInt, 16));
} catch (e) {} } catch (e) {
console.error('mod pow error', e);
}
return bytesFromBigInt(new BigInteger(x).modPow(new BigInteger(y), new BigInteger(m))); return bytesFromBigInt(new BigInteger(x).modPow(new BigInteger(y), new BigInteger(m)));
} }

13
js/lib/crypto_worker.js

@ -1,5 +1,5 @@
/*! /*!
* Webogram v0.3.2 - messaging web application for MTProto * Webogram v0.3.3 - messaging web application for MTProto
* https://github.com/zhukov/webogram * https://github.com/zhukov/webogram
* Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com> * Copyright (C) 2014 Igor Zhukov <igor.beatle@gmail.com>
* https://github.com/zhukov/webogram/blob/master/LICENSE * https://github.com/zhukov/webogram/blob/master/LICENSE
@ -11,7 +11,8 @@ importScripts(
'../../vendor/jsbn/jsbn_combined.js', '../../vendor/jsbn/jsbn_combined.js',
'../../vendor/leemon_bigint/bigint.js', '../../vendor/leemon_bigint/bigint.js',
'../../vendor/closure/long.js', '../../vendor/closure/long.js',
'../../vendor/cryptoJS/crypto.js' '../../vendor/cryptoJS/crypto.js',
'../../vendor/rusha/rusha.js'
); );
onmessage = function (e) { onmessage = function (e) {
@ -28,15 +29,15 @@ onmessage = function (e) {
break; break;
case 'sha1-hash': case 'sha1-hash':
result = sha1Hash(e.data.bytes); result = sha1HashSync(e.data.bytes);
break; break;
case 'aes-encrypt': case 'aes-encrypt':
result = aesEncrypt(e.data.bytes, e.data.keyBytes, e.data.ivBytes); result = aesEncryptSync(e.data.bytes, e.data.keyBytes, e.data.ivBytes);
break; break;
case 'aes-decrypt': case 'aes-decrypt':
result = aesDecrypt(e.data.encryptedBytes, e.data.keyBytes, e.data.ivBytes); result = aesDecryptSync(e.data.encryptedBytes, e.data.keyBytes, e.data.ivBytes);
break; break;
default: default:
@ -45,3 +46,5 @@ onmessage = function (e) {
postMessage({taskID: taskID, result: result}); postMessage({taskID: taskID, result: result});
} }
postMessage('ready');

33
js/lib/polyfill.js

@ -96,3 +96,36 @@ if (!Function.prototype.bind) {
return fBound; return fBound;
}; };
} }
/* setZeroTimeout polyfill, from http://dbaron.org/log/20100309-faster-timeouts */
(function(global) {
var timeouts = [];
var messageName = 'zero-timeout-message';
function setZeroTimeout(fn) {
timeouts.push(fn);
global.postMessage(messageName, '*');
}
function handleMessage(event) {
if (event.source == global && event.data == messageName) {
event.stopPropagation();
if (timeouts.length > 0) {
var fn = timeouts.shift();
fn();
}
}
}
global.addEventListener('message', handleMessage, true);
var originalSetTimeout = global.setTimeout;
global.setTimeout = function (callback, delay) {
if (!delay || delay <= 5) {
return setZeroTimeout(callback);
}
return originalSetTimeout(callback, delay);
};
global.setZeroTimeout = setZeroTimeout;
})(this);

5
js/locales/de-de.json

@ -171,6 +171,7 @@
"message_service_kicked_user": "hat {user} entfernt", "message_service_kicked_user": "hat {user} entfernt",
"message_service_left_group": "hat die Gruppe verlassen", "message_service_left_group": "hat die Gruppe verlassen",
"message_service_unsupported_action": "Nicht unterstützte Aktion {action}", "message_service_unsupported_action": "Nicht unterstützte Aktion {action}",
"error_modal_warning_title": "Warnung",
"error_modal_bad_request_title": "Fehler", "error_modal_bad_request_title": "Fehler",
"error_modal_unauthorized_title": "Nicht autorisiert", "error_modal_unauthorized_title": "Nicht autorisiert",
"error_modal_forbidden_title": "Zugang verweigert", "error_modal_forbidden_title": "Zugang verweigert",
@ -190,6 +191,7 @@
"error_modal_no_phone_user_description_md": "Es gibt leider kein **Telegram** Konto mit der angegebenen Nummer.", "error_modal_no_phone_user_description_md": "Es gibt leider kein **Telegram** Konto mit der angegebenen Nummer.",
"error_modal_no_phone_users_description_md": "Es gibt gibt leider keine **Telegram** Konten mit den angegebenen Nummern.", "error_modal_no_phone_users_description_md": "Es gibt gibt leider keine **Telegram** Konten mit den angegebenen Nummern.",
"error_modal_username_invalid_description": "Verzeihung, dieser Benutzername ist nicht erlaubt.", "error_modal_username_invalid_description": "Verzeihung, dieser Benutzername ist nicht erlaubt.",
"error_modal_phonebook_required_description": "Telegram benötigt Zugriff aufs Telefonbuch um Kontakte zu importieren.",
"error_modal_username_occupied_description": "Benutzername ist leider schon belegt.", "error_modal_username_occupied_description": "Benutzername ist leider schon belegt.",
"error_modal_bad_request_description": "Eine Parameter fehlt oder ist ungültig.", "error_modal_bad_request_description": "Eine Parameter fehlt oder ist ungültig.",
"error_modal_unauthorized_description": "Diese Aktion benötigt autorisierten Zugriff. Bitte {login-link: melde dich an}.", "error_modal_unauthorized_description": "Diese Aktion benötigt autorisierten Zugriff. Bitte {login-link: melde dich an}.",
@ -198,6 +200,7 @@
"error_modal_flood_description": "Du führst zu viele Anfragen durch. Bitte versuche es später wieder.", "error_modal_flood_description": "Du führst zu viele Anfragen durch. Bitte versuche es später wieder.",
"error_modal_internal_description": "Ein interner Serverfehler ist aufgetreten. Bitte versuche es später wieder.", "error_modal_internal_description": "Ein interner Serverfehler ist aufgetreten. Bitte versuche es später wieder.",
"error_modal_tech_details": "Hier gibt es die technischen Details", "error_modal_tech_details": "Hier gibt es die technischen Details",
"error_modal_multiple_open_tabs": "Bitte andere Telegram App Tabs schliessen.",
"head_new_group": "Neue Gruppe", "head_new_group": "Neue Gruppe",
"head_new_contact": "Neuer Kontakt", "head_new_contact": "Neuer Kontakt",
"head_contacts": "Kontakte", "head_contacts": "Kontakte",
@ -292,8 +295,10 @@
"message_attach_audio_play": "Abspielen", "message_attach_audio_play": "Abspielen",
"message_attach_document_open": "Öffnen", "message_attach_document_open": "Öffnen",
"message_attach_document_download": "Download", "message_attach_document_download": "Download",
"message_attach_document_save": "Datei speichern",
"message_attach_video_video": "Video", "message_attach_video_video": "Video",
"message_attach_video_download": "Download", "message_attach_video_download": "Download",
"message_attach_video_save": "Datei speichern",
"message_attach_video_play": "Video abspielen", "message_attach_video_play": "Video abspielen",
"conversation_select_modal_title": "Unterhaltung auswählen", "conversation_select_modal_title": "Unterhaltung auswählen",
"conversation_select_modal_contacts": "Kontakte", "conversation_select_modal_contacts": "Kontakte",

6
js/locales/en-us.json

@ -195,6 +195,7 @@
"message_service_left_group": "left group", "message_service_left_group": "left group",
"message_service_unsupported_action": "Unsupported action {action}", "message_service_unsupported_action": "Unsupported action {action}",
"error_modal_warning_title": "Warning",
"error_modal_bad_request_title": "Error", "error_modal_bad_request_title": "Error",
"error_modal_unauthorized_title": "Unauthorized", "error_modal_unauthorized_title": "Unauthorized",
"error_modal_forbidden_title": "Access denied", "error_modal_forbidden_title": "Access denied",
@ -215,6 +216,7 @@
"error_modal_no_phone_user_description_md": "Sorry, there is no **Telegram** account with the phone number you provided.", "error_modal_no_phone_user_description_md": "Sorry, there is no **Telegram** account with the phone number you provided.",
"error_modal_no_phone_users_description_md": "Sorry, there are no **Telegram** accounts with the phone numbers you provided.", "error_modal_no_phone_users_description_md": "Sorry, there are no **Telegram** accounts with the phone numbers you provided.",
"error_modal_username_invalid_description": "Sorry, this username is not allowed.", "error_modal_username_invalid_description": "Sorry, this username is not allowed.",
"error_modal_phonebook_required_description": "Telegram needs access to phonebook to import contacts.",
"error_modal_username_occupied_description": "Sorry, this username is already taken.", "error_modal_username_occupied_description": "Sorry, this username is already taken.",
"error_modal_bad_request_description": "One of the params is missing or invalid.", "error_modal_bad_request_description": "One of the params is missing or invalid.",
@ -224,6 +226,8 @@
"error_modal_flood_description": "You are performing too many actions. Please try again later.", "error_modal_flood_description": "You are performing too many actions. Please try again later.",
"error_modal_internal_description": "Internal server error occured. Please try again later.", "error_modal_internal_description": "Internal server error occured. Please try again later.",
"error_modal_tech_details": "Technical details here", "error_modal_tech_details": "Technical details here",
"error_modal_multiple_open_tabs": "Please close other Telegram app tabs.",
"head_new_group": "New Group", "head_new_group": "New Group",
"head_new_contact": "New Contact", "head_new_contact": "New Contact",
@ -325,9 +329,11 @@
"message_attach_document_open": "Open", "message_attach_document_open": "Open",
"message_attach_document_download": "Download", "message_attach_document_download": "Download",
"message_attach_document_save": "Save File",
"message_attach_video_video": "Video", "message_attach_video_video": "Video",
"message_attach_video_download": "Download", "message_attach_video_download": "Download",
"message_attach_video_save": "Save File",
"message_attach_video_play": "Play video", "message_attach_video_play": "Play video",
"conversation_select_modal_title": "Select conversation", "conversation_select_modal_title": "Select conversation",

31
js/locales/es-es.json

@ -27,8 +27,8 @@
"settings_modal_set_photo": "Establecer foto de perfil", "settings_modal_set_photo": "Establecer foto de perfil",
"settings_modal_photo_updating": "Actualizando", "settings_modal_photo_updating": "Actualizando",
"settings_modal_edit_profile": "Editar perfil", "settings_modal_edit_profile": "Editar perfil",
"settings_modal_edit_username": "Cambiar nombre de usuario", "settings_modal_edit_username": "Cambiar apodo",
"settings_modal_empty_username_set": "Establecer nombre de usuario", "settings_modal_empty_username_set": "Establecer apodo",
"settings_modal_terminate_sessions": "Cerrar todas las otras sesiones", "settings_modal_terminate_sessions": "Cerrar todas las otras sesiones",
"settings_modal_settings": "Ajustes", "settings_modal_settings": "Ajustes",
"settings_modal_notification_alert": "Alertas de notificaciones", "settings_modal_notification_alert": "Alertas de notificaciones",
@ -47,12 +47,12 @@
"page_title_pluralize_notifications": "{'0': 'Sin notificaciones', 'one': '1 notificación', 'other': '{} notificaciones'}", "page_title_pluralize_notifications": "{'0': 'Sin notificaciones', 'one': '1 notificación', 'other': '{} notificaciones'}",
"profile_edit_modal_title": "Editar perfil", "profile_edit_modal_title": "Editar perfil",
"profile_edit_first_name": "Nombre", "profile_edit_first_name": "Nombre",
"profile_edit_last_name": "Apellido", "profile_edit_last_name": "Apellidos",
"profile_edit_submit": "Guardar", "profile_edit_submit": "Guardar",
"profile_edit_submit_active": "Guardando...", "profile_edit_submit_active": "Guardando...",
"username_edit_modal_title": "Cambiar nombre de usuario", "username_edit_modal_title": "Cambiar apodo",
"username_edit_placeholder": "Nombre de usuario", "username_edit_placeholder": "Apodo",
"username_edit_description_md": "Puedes elegir un nombre de usuario en **Telegram**. Si lo haces, otros usuarios podrán encontrarte mediante ese nombre y contactarte sin necesidad de saber tu número.\n\nPuedes usar a-z, 0-9 y guión bajo. La longitud mínima es de 5 caracteres.", "username_edit_description_md": "Puedes elegir un apodo en **Telegram**. Si lo haces, otros usuarios te podrán encontrar por ese nombre y contactarte sin necesidad de saber tu número.\n\nPuedes usar a-z, 0-9 y guión bajo. La longitud mínima es de 5 caracteres.",
"username_edit_submit": "Guardar", "username_edit_submit": "Guardar",
"username_edit_submit_active": "Guardando...", "username_edit_submit_active": "Guardando...",
"user_modal_menu_more": "Más", "user_modal_menu_more": "Más",
@ -64,7 +64,7 @@
"user_modal_delete_chat": "Eliminar chat", "user_modal_delete_chat": "Eliminar chat",
"user_modal_info": "Información", "user_modal_info": "Información",
"user_modal_phone": "Teléfono", "user_modal_phone": "Teléfono",
"user_modal_username": "Nombre de usuario", "user_modal_username": "Apodo",
"user_modal_settings": "Ajustes", "user_modal_settings": "Ajustes",
"user_modal_notifications": "Notificaciones", "user_modal_notifications": "Notificaciones",
"user_modal_contact_info": "Información", "user_modal_contact_info": "Información",
@ -132,7 +132,7 @@
"contacts_modal_new_contact": "Nuevo contacto", "contacts_modal_new_contact": "Nuevo contacto",
"contacts_modal_empty_list": "Tu lista de contactos está vacía . Puedes {import-link: añadir un nuevo contacto} con su número de teléfono.", "contacts_modal_empty_list": "Tu lista de contactos está vacía . Puedes {import-link: añadir un nuevo contacto} con su número de teléfono.",
"contact_edit_modal_first_name": "Nombe", "contact_edit_modal_first_name": "Nombe",
"contact_edit_modal_last_name": "Apellido", "contact_edit_modal_last_name": "Apellidos",
"contact_edit_modal_title": "Editar contacto", "contact_edit_modal_title": "Editar contacto",
"contact_edit_modal_submit": "Guardar", "contact_edit_modal_submit": "Guardar",
"contact_edit_modal_submit_active": "Guardando...", "contact_edit_modal_submit_active": "Guardando...",
@ -171,6 +171,7 @@
"message_service_kicked_user": "expulsó a {user}", "message_service_kicked_user": "expulsó a {user}",
"message_service_left_group": "dejó el grupo", "message_service_left_group": "dejó el grupo",
"message_service_unsupported_action": "Acción no soportada: {action}", "message_service_unsupported_action": "Acción no soportada: {action}",
"error_modal_warning_title": "Advertencia",
"error_modal_bad_request_title": "Error", "error_modal_bad_request_title": "Error",
"error_modal_unauthorized_title": "No autorizado", "error_modal_unauthorized_title": "No autorizado",
"error_modal_forbidden_title": "Acceso denegado", "error_modal_forbidden_title": "Acceso denegado",
@ -181,7 +182,7 @@
"error_modal_alert": "Alerta", "error_modal_alert": "Alerta",
"error_modal_network_description": "Por favor, revisa tu conexión a internet.", "error_modal_network_description": "Por favor, revisa tu conexión a internet.",
"error_modal_firstname_invali_description": "El nombre introducido no es válido.", "error_modal_firstname_invali_description": "El nombre introducido no es válido.",
"error_modal_lastname_invalid_description": "El apellido introducido no es válido.", "error_modal_lastname_invalid_description": "Los apellidos introducidos no son válidos.",
"error_modal_phone_invalid_description": "El número de teléfono introducido no es válido.", "error_modal_phone_invalid_description": "El número de teléfono introducido no es válido.",
"error_modal_users_too_much_description": "Has seleccionado demasiados usuarios.", "error_modal_users_too_much_description": "Has seleccionado demasiados usuarios.",
"error_modal_photo_dimensions_invalid_description": "Las dimensiones de la foto no son válidas. Por favor, selecciona otro archivo.", "error_modal_photo_dimensions_invalid_description": "Las dimensiones de la foto no son válidas. Por favor, selecciona otro archivo.",
@ -189,8 +190,9 @@
"error_modal_photo_too_small_description": "La foto entregada es muy pequeña.", "error_modal_photo_too_small_description": "La foto entregada es muy pequeña.",
"error_modal_no_phone_user_description_md": "Lo siento, no existe una cuenta de **Telegram** asociada al teléfono introducido.", "error_modal_no_phone_user_description_md": "Lo siento, no existe una cuenta de **Telegram** asociada al teléfono introducido.",
"error_modal_no_phone_users_description_md": "Lo siento, no existen cuentas de **Telegram** asociadas a los teléfonos introducidos.", "error_modal_no_phone_users_description_md": "Lo siento, no existen cuentas de **Telegram** asociadas a los teléfonos introducidos.",
"error_modal_username_invalid_description": "Lo siento, no puedes usar ese nombre de usuario.", "error_modal_username_invalid_description": "Lo siento, este apodo no está permitido.",
"error_modal_username_occupied_description": "Lo siento, ese nombre de usuario ya está ocupado.", "error_modal_phonebook_required_description": "Telegram necesita acceso a tu agenda para importar contactos.",
"error_modal_username_occupied_description": "Lo siento, este apodo ya está ocupado.",
"error_modal_bad_request_description": "Falta uno de los parámetros o es inválido.", "error_modal_bad_request_description": "Falta uno de los parámetros o es inválido.",
"error_modal_unauthorized_description": "Esta acción requiere acceso autorizado. Por favor, {login-link: inicia sesión}.", "error_modal_unauthorized_description": "Esta acción requiere acceso autorizado. Por favor, {login-link: inicia sesión}.",
"error_modal_forbidden_description": "No estás autorizado para esta acción.", "error_modal_forbidden_description": "No estás autorizado para esta acción.",
@ -198,6 +200,7 @@
"error_modal_flood_description": "Estás realizando demasiadas acciones. Por favor, reinténtalo más tarde.", "error_modal_flood_description": "Estás realizando demasiadas acciones. Por favor, reinténtalo más tarde.",
"error_modal_internal_description": "Error interno del servidor. Por favor, reinténtalo más tarde.", "error_modal_internal_description": "Error interno del servidor. Por favor, reinténtalo más tarde.",
"error_modal_tech_details": "Detalles técnicos aquí", "error_modal_tech_details": "Detalles técnicos aquí",
"error_modal_multiple_open_tabs": "Por favor, cierra las otras pestañas de la app de Telegram.",
"head_new_group": "Nuevo grupo", "head_new_group": "Nuevo grupo",
"head_new_contact": "Nuevo contacto", "head_new_contact": "Nuevo contacto",
"head_contacts": "Contactos", "head_contacts": "Contactos",
@ -281,8 +284,8 @@
"login_fulll_name_label": "Por favor, inserta tu nombre completo para crear tu cuenta de Telegram.", "login_fulll_name_label": "Por favor, inserta tu nombre completo para crear tu cuenta de Telegram.",
"login_incorrect_first_name": "Nombre incorrecto", "login_incorrect_first_name": "Nombre incorrecto",
"login_first_name": "Nombre", "login_first_name": "Nombre",
"login_incorrect_last_name": "Apellido incorrecto", "login_incorrect_last_name": "Apellidos incorrectos",
"login_last_name": "Apellido", "login_last_name": "Apellidos",
"login_signing_up": "Registrándose", "login_signing_up": "Registrándose",
"login_sign_up": "Registrarse", "login_sign_up": "Registrarse",
"login_controller_unknown_country": "Desconocido", "login_controller_unknown_country": "Desconocido",
@ -292,8 +295,10 @@
"message_attach_audio_play": "Reproducir", "message_attach_audio_play": "Reproducir",
"message_attach_document_open": "Abrir", "message_attach_document_open": "Abrir",
"message_attach_document_download": "Descargar", "message_attach_document_download": "Descargar",
"message_attach_document_save": "Guardar archivo",
"message_attach_video_video": "Vídeo", "message_attach_video_video": "Vídeo",
"message_attach_video_download": "Descargar", "message_attach_video_download": "Descargar",
"message_attach_video_save": "Guardar archivo",
"message_attach_video_play": "Ver vídeo", "message_attach_video_play": "Ver vídeo",
"conversation_select_modal_title": "Seleccionar conversación", "conversation_select_modal_title": "Seleccionar conversación",
"conversation_select_modal_contacts": "Contactos", "conversation_select_modal_contacts": "Contactos",

11
js/locales/it-it.json

@ -145,7 +145,7 @@
"conversation_you": "Tu", "conversation_you": "Tu",
"conversation_media_photo": "Foto", "conversation_media_photo": "Foto",
"conversation_media_video": "Video", "conversation_media_video": "Video",
"conversation_media_document": "Documento", "conversation_media_document": "File",
"conversation_media_audio": "Audio", "conversation_media_audio": "Audio",
"conversation_media_location": "Posizione", "conversation_media_location": "Posizione",
"conversation_media_contact": "Contatto", "conversation_media_contact": "Contatto",
@ -171,6 +171,7 @@
"message_service_kicked_user": "allontanato {user}", "message_service_kicked_user": "allontanato {user}",
"message_service_left_group": "gruppo abbandonato", "message_service_left_group": "gruppo abbandonato",
"message_service_unsupported_action": "Azione non supportata {action}", "message_service_unsupported_action": "Azione non supportata {action}",
"error_modal_warning_title": "Attenzione",
"error_modal_bad_request_title": "Errore", "error_modal_bad_request_title": "Errore",
"error_modal_unauthorized_title": "Non autorizzato", "error_modal_unauthorized_title": "Non autorizzato",
"error_modal_forbidden_title": "Accesso negato", "error_modal_forbidden_title": "Accesso negato",
@ -190,6 +191,7 @@
"error_modal_no_phone_user_description_md": "Siamo spiacenti, non c'è alcun account **Telegram** associato al numero che hai fornito.", "error_modal_no_phone_user_description_md": "Siamo spiacenti, non c'è alcun account **Telegram** associato al numero che hai fornito.",
"error_modal_no_phone_users_description_md": "Siamo spiacenti, non c'è alcun account **Telegram** associato al numero che hai fornito.", "error_modal_no_phone_users_description_md": "Siamo spiacenti, non c'è alcun account **Telegram** associato al numero che hai fornito.",
"error_modal_username_invalid_description": "Ci spiace, questo nome utente non è consentito.", "error_modal_username_invalid_description": "Ci spiace, questo nome utente non è consentito.",
"error_modal_phonebook_required_description": "Telegram ha bisogno di accedere alla tua rubrica per importare i contatti.",
"error_modal_username_occupied_description": "Ci spiace, questo nome utente è già stato preso", "error_modal_username_occupied_description": "Ci spiace, questo nome utente è già stato preso",
"error_modal_bad_request_description": "Un parametro è mancante o errato.", "error_modal_bad_request_description": "Un parametro è mancante o errato.",
"error_modal_unauthorized_description": "L'azione necessita dell'autorizzazione d'accesso. Per favore {login-link: log in}.", "error_modal_unauthorized_description": "L'azione necessita dell'autorizzazione d'accesso. Per favore {login-link: log in}.",
@ -198,6 +200,7 @@
"error_modal_flood_description": "Stai effettuando troppe operazioni. Si prega di riprovare più tardi.", "error_modal_flood_description": "Stai effettuando troppe operazioni. Si prega di riprovare più tardi.",
"error_modal_internal_description": "Si è verificato un errore internamente al server. Si prega di riprovare più tardi.", "error_modal_internal_description": "Si è verificato un errore internamente al server. Si prega di riprovare più tardi.",
"error_modal_tech_details": "Dettagli tecnici qui", "error_modal_tech_details": "Dettagli tecnici qui",
"error_modal_multiple_open_tabs": "Per favore chiudi le altre finestre dell'app di Telegram.",
"head_new_group": "Nuovo Gruppo", "head_new_group": "Nuovo Gruppo",
"head_new_contact": "Nuovo Contatto", "head_new_contact": "Nuovo Contatto",
"head_contacts": "Contatti", "head_contacts": "Contatti",
@ -208,7 +211,7 @@
"head_edit_messages": "Modifica messaggi", "head_edit_messages": "Modifica messaggi",
"head_media_photos": "Foto", "head_media_photos": "Foto",
"head_media_video": "Video", "head_media_video": "Video",
"head_media_documents": "Documenti", "head_media_documents": "File",
"head_media_audio": "Messaggi vocali", "head_media_audio": "Messaggi vocali",
"head_about": "Informazioni su", "head_about": "Informazioni su",
"head_clear_all": "Elimina tutto", "head_clear_all": "Elimina tutto",
@ -242,7 +245,7 @@
"im_media": "Media", "im_media": "Media",
"im_media_photos": "Foto", "im_media_photos": "Foto",
"im_media_video": "Video", "im_media_video": "Video",
"im_media_documents": "Documenti", "im_media_documents": "File",
"im_media_audio": "Messaggi vocali", "im_media_audio": "Messaggi vocali",
"im_pluralize_participants": "{'0': 'Nessun membro', 'one': '1 membro', 'other': '{} membri'}", "im_pluralize_participants": "{'0': 'Nessun membro', 'one': '1 membro', 'other': '{} membri'}",
"im_show_recent_messages": "Mostra messaggi recenti", "im_show_recent_messages": "Mostra messaggi recenti",
@ -292,8 +295,10 @@
"message_attach_audio_play": "Riproduci", "message_attach_audio_play": "Riproduci",
"message_attach_document_open": "Apri", "message_attach_document_open": "Apri",
"message_attach_document_download": "Scarica", "message_attach_document_download": "Scarica",
"message_attach_document_save": "Salva file",
"message_attach_video_video": "Video", "message_attach_video_video": "Video",
"message_attach_video_download": "Scarica", "message_attach_video_download": "Scarica",
"message_attach_video_save": "Salva file",
"message_attach_video_play": "Riproduci video", "message_attach_video_play": "Riproduci video",
"conversation_select_modal_title": "Seleziona conversazione", "conversation_select_modal_title": "Seleziona conversazione",
"conversation_select_modal_contacts": "Contatti", "conversation_select_modal_contacts": "Contatti",

2
manifest.json

@ -1,7 +1,7 @@
{ {
"name": "Telegram", "name": "Telegram",
"description": "Telegram Web App.\nMore info & source code here: https://github.com/zhukov/webogram", "description": "Telegram Web App.\nMore info & source code here: https://github.com/zhukov/webogram",
"version": "0.3.2", "version": "0.3.3",
"short_name": "Webogram", "short_name": "Webogram",
"manifest_version": 2, "manifest_version": 2,
"app": { "app": {

2
manifest.webapp

@ -1,7 +1,7 @@
{ {
"name": "Telegram", "name": "Telegram",
"description": "Telegram Web App.\nMore info & source code here: https://github.com/zhukov/webogram", "description": "Telegram Web App.\nMore info & source code here: https://github.com/zhukov/webogram",
"version": "0.3.2", "version": "0.3.3",
"type": "privileged", "type": "privileged",
"launch_path": "/index.html", "launch_path": "/index.html",
"developer": { "developer": {

10
nacl/mtproto_crypto.nmf

@ -0,0 +1,10 @@
{
"program": {
"portable": {
"pnacl-translate": {
"url": "mtproto_crypto.pexe?67",
"optlevel": 2
}
}
}
}

BIN
nacl/mtproto_crypto.pexe

Binary file not shown.

2
vendor/angular/i18n/angular-locale_de-de.js vendored

@ -110,6 +110,6 @@ $provide.value("$locale", {
] ]
}, },
"id": "de-de", "id": "de-de",
"pluralCat": function (n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;} "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
}); });
}]); }]);

2
vendor/angular/i18n/angular-locale_en-us.js vendored

@ -110,6 +110,6 @@ $provide.value("$locale", {
] ]
}, },
"id": "en-us", "id": "en-us",
"pluralCat": function (n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;} "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
}); });
}]); }]);

2
vendor/angular/i18n/angular-locale_es-es.js vendored

@ -92,6 +92,6 @@ $provide.value("$locale", {
] ]
}, },
"id": "es-es", "id": "es-es",
"pluralCat": function (n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;} "pluralCat": function(n, opt_precision) { if (n == 1) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
}); });
}]); }]);

2
vendor/angular/i18n/angular-locale_it-it.js vendored

@ -110,6 +110,6 @@ $provide.value("$locale", {
] ]
}, },
"id": "it-it", "id": "it-it",
"pluralCat": function (n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;} "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (i == 1 && vf.v == 0) { return PLURAL_CATEGORY.ONE; } return PLURAL_CATEGORY.OTHER;}
}); });
}]); }]);

2
vendor/angular/i18n/angular-locale_ru-ru.js vendored

@ -110,6 +110,6 @@ $provide.value("$locale", {
] ]
}, },
"id": "ru-ru", "id": "ru-ru",
"pluralCat": function (n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;} "pluralCat": function(n, opt_precision) { var i = n | 0; var vf = getVF(n, opt_precision); if (vf.v == 0 && i % 10 == 1 && i % 100 != 11) { return PLURAL_CATEGORY.ONE; } if (vf.v == 0 && i % 10 >= 2 && i % 10 <= 4 && (i % 100 < 12 || i % 100 > 14)) { return PLURAL_CATEGORY.FEW; } if (vf.v == 0 && i % 10 == 0 || vf.v == 0 && i % 10 >= 5 && i % 10 <= 9 || vf.v == 0 && i % 100 >= 11 && i % 100 <= 14) { return PLURAL_CATEGORY.MANY; } return PLURAL_CATEGORY.OTHER;}
}); });
}]); }]);

392
vendor/rusha/rusha.js vendored

@ -0,0 +1,392 @@
/*
* Rusha, a JavaScript implementation of the Secure Hash Algorithm, SHA-1,
* as defined in FIPS PUB 180-1, tuned for high performance with large inputs.
* (http://github.com/srijs/rusha)
*
* Inspired by Paul Johnstons implementation (http://pajhome.org.uk/crypt/md5).
*
* Copyright (c) 2013 Sam Rijs (http://awesam.de).
* Released under the terms of the MIT license as follows:
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
(function (global) {
// If we'e running in Node.JS, export a module.
if (typeof module !== 'undefined') {
module.exports = Rusha;
}
// If we're running in a DOM context, export
// the Rusha object to toplevel.
if (typeof global !== 'undefined') {
global.Rusha = Rusha;
}
// If we're running in a webworker, accept
// messages containing a jobid and a buffer
// or blob object, and return the hash result.
if (typeof FileReaderSync !== 'undefined') {
var reader = new FileReaderSync(), hasher = new Rusha(4 * 1024 * 1024);
self.onmessage = function onMessage(event) {
var hash, data = event.data.data;
if (data instanceof Blob) {
try {
data = reader.readAsBinaryString(data);
} catch (e) {
self.postMessage({
id: event.data.id,
error: e.name
});
return;
}
}
hash = hasher.digest(data);
self.postMessage({
id: event.data.id,
hash: hash
});
};
}
var util = {
getDataType: function (data) {
if (typeof data === 'string') {
return 'string';
}
if (data instanceof Array) {
return 'array';
}
if (typeof global !== 'undefined' && global.Buffer && global.Buffer.isBuffer(data)) {
return 'buffer';
}
if (data instanceof ArrayBuffer) {
return 'arraybuffer';
}
if (data.buffer instanceof ArrayBuffer) {
return 'view';
}
throw new Error('Unsupported data type.');
}
};
// The Rusha object is a wrapper around the low-level RushaCore.
// It provides means of converting different inputs to the
// format accepted by RushaCore as well as other utility methods.
function Rusha(chunkSize) {
'use strict';
// Private object structure.
var self$2 = { fill: 0 };
// Calculate the length of buffer that the sha1 routine uses
// including the padding.
var padlen = function (len) {
for (len += 9; len % 64 > 0; len += 1);
return len;
};
var padZeroes = function (bin, len) {
for (var i = len >> 2; i < bin.length; i++)
bin[i] = 0;
};
var padData = function (bin, chunkLen, msgLen) {
bin[chunkLen >> 2] |= 128 << 24 - (chunkLen % 4 << 3);
bin[((chunkLen >> 2) + 2 & ~15) + 15] = msgLen << 3;
};
// Convert a binary string and write it to the heap.
// A binary string is expected to only contain char codes < 256.
var convStr = function (H8, H32, start, len, off) {
var str = this, i, om = off % 4, lm = len % 4, j = len - lm;
if (j > 0) {
switch (om) {
case 0:
H8[off + 3 | 0] = str.charCodeAt(start);
case 1:
H8[off + 2 | 0] = str.charCodeAt(start + 1);
case 2:
H8[off + 1 | 0] = str.charCodeAt(start + 2);
case 3:
H8[off | 0] = str.charCodeAt(start + 3);
}
}
for (i = om; i < j; i = i + 4 | 0) {
H32[off + i >> 2] = str.charCodeAt(start + i) << 24 | str.charCodeAt(start + i + 1) << 16 | str.charCodeAt(start + i + 2) << 8 | str.charCodeAt(start + i + 3);
}
switch (lm) {
case 3:
H8[off + j + 1 | 0] = str.charCodeAt(start + j + 2);
case 2:
H8[off + j + 2 | 0] = str.charCodeAt(start + j + 1);
case 1:
H8[off + j + 3 | 0] = str.charCodeAt(start + j);
}
};
// Convert a buffer or array and write it to the heap.
// The buffer or array is expected to only contain elements < 256.
var convBuf = function (H8, H32, start, len, off) {
var buf = this, i, om = off % 4, lm = len % 4, j = len - lm;
if (j > 0) {
switch (om) {
case 0:
H8[off + 3 | 0] = buf[start];
case 1:
H8[off + 2 | 0] = buf[start + 1];
case 2:
H8[off + 1 | 0] = buf[start + 2];
case 3:
H8[off | 0] = buf[start + 3];
}
}
for (i = 4 - om; i < j; i = i += 4 | 0) {
H32[off + i >> 2] = buf[start + i] << 24 | buf[start + i + 1] << 16 | buf[start + i + 2] << 8 | buf[start + i + 3];
}
switch (lm) {
case 3:
H8[off + j + 1 | 0] = buf[start + j + 2];
case 2:
H8[off + j + 2 | 0] = buf[start + j + 1];
case 1:
H8[off + j + 3 | 0] = buf[start + j];
}
};
var convFn = function (data) {
switch (util.getDataType(data)) {
case 'string':
return convStr.bind(data);
case 'array':
return convBuf.bind(data);
case 'buffer':
return convBuf.bind(data);
case 'arraybuffer':
return convBuf.bind(new Uint8Array(data));
case 'view':
return convBuf.bind(new Uint8Array(data.buffer));
}
};
var slice = function (data, offset) {
switch (util.getDataType(data)) {
case 'string':
return data.slice(offset);
case 'array':
return data.slice(offset);
case 'buffer':
return data.slice(offset);
case 'arraybuffer':
return data.slice(offset);
case 'view':
return data.buffer.slice(offset);
}
};
// Convert an ArrayBuffer into its hexadecimal string representation.
var hex = function (arrayBuffer) {
var i, x, hex_tab = '0123456789abcdef', res = [], binarray = new Uint8Array(arrayBuffer);
for (i = 0; i < binarray.length; i++) {
x = binarray[i];
res[i] = hex_tab.charAt(x >> 4 & 15) + hex_tab.charAt(x >> 0 & 15);
}
return res.join('');
};
var ceilHeapSize = function (v) {
// The asm.js spec says:
// The heap object's byteLength must be either
// 2^n for n in [12, 24) or 2^24 * n for n ≥ 1.
// Also, byteLengths smaller than 2^16 are deprecated.
var p;
// If v is smaller than 2^16, the smallest possible solution
// is 2^16.
if (v <= 65536)
return 65536;
// If v < 2^24, we round up to 2^n,
// otherwise we round up to 2^24 * n.
if (v < 16777216) {
for (p = 1; p < v; p = p << 1);
} else {
for (p = 16777216; p < v; p += 16777216);
}
return p;
};
// Initialize the internal data structures to a new capacity.
var init = function (size) {
if (size % 64 > 0) {
throw new Error('Chunk size must be a multiple of 128 bit');
}
self$2.maxChunkLen = size;
self$2.padMaxChunkLen = padlen(size);
// The size of the heap is the sum of:
// 1. The padded input message size
// 2. The extended space the algorithm needs (320 byte)
// 3. The 160 bit state the algoritm uses
self$2.heap = new ArrayBuffer(ceilHeapSize(self$2.padMaxChunkLen + 320 + 20));
self$2.h32 = new Int32Array(self$2.heap);
self$2.h8 = new Int8Array(self$2.heap);
self$2.core = RushaCore({
Int32Array: Int32Array,
DataView: DataView
}, {}, self$2.heap);
self$2.buffer = null;
};
// Iinitializethe datastructures according
// to a chunk siyze.
init(chunkSize || 64 * 1024);
var initState = function (heap, padMsgLen) {
var io = new Int32Array(heap, padMsgLen + 320, 5);
io[0] = 1732584193;
io[1] = -271733879;
io[2] = -1732584194;
io[3] = 271733878;
io[4] = -1009589776;
};
var padChunk = function (chunkLen, msgLen) {
var padChunkLen = padlen(chunkLen);
var view = new Int32Array(self$2.heap, 0, padChunkLen >> 2);
padZeroes(view, chunkLen);
padData(view, chunkLen, msgLen);
return padChunkLen;
};
// Write data to the heap.
var write = function (data, chunkOffset, chunkLen) {
convFn(data)(self$2.h8, self$2.h32, chunkOffset, chunkLen, 0);
};
// Initialize and call the RushaCore,
// assuming an input buffer of length len * 4.
var coreCall = function (data, chunkOffset, chunkLen, msgLen, finalize) {
var padChunkLen = chunkLen;
if (finalize) {
padChunkLen = padChunk(chunkLen, msgLen);
}
write(data, chunkOffset, chunkLen);
self$2.core.hash(padChunkLen, self$2.padMaxChunkLen);
};
var getRawDigest = function (heap, padMaxChunkLen) {
var io = new Int32Array(heap, padMaxChunkLen + 320, 5);
var out = new Int32Array(5);
var arr = new DataView(out.buffer);
arr.setInt32(0, io[0], false);
arr.setInt32(4, io[1], false);
arr.setInt32(8, io[2], false);
arr.setInt32(12, io[3], false);
arr.setInt32(16, io[4], false);
return out;
};
// Calculate the hash digest as an array of 5 32bit integers.
var rawDigest = this.rawDigest = function (str) {
var msgLen = str.byteLength || str.length;
initState(self$2.heap, self$2.padMaxChunkLen);
var chunkOffset = 0, chunkLen = self$2.maxChunkLen, last;
for (chunkOffset = 0; msgLen > chunkOffset + chunkLen; chunkOffset += chunkLen) {
coreCall(str, chunkOffset, chunkLen, msgLen, false);
}
coreCall(str, chunkOffset, msgLen - chunkOffset, msgLen, true);
return getRawDigest(self$2.heap, self$2.padMaxChunkLen);
};
// The digest and digestFrom* interface returns the hash digest
// as a hex string.
this.digest = this.digestFromString = this.digestFromBuffer = this.digestFromArrayBuffer = function (str) {
return hex(rawDigest(str).buffer);
};
}
;
// The low-level RushCore module provides the heart of Rusha,
// a high-speed sha1 implementation working on an Int32Array heap.
// At first glance, the implementation seems complicated, however
// with the SHA1 spec at hand, it is obvious this almost a textbook
// implementation that has a few functions hand-inlined and a few loops
// hand-unrolled.
function RushaCore(stdlib, foreign, heap) {
'use asm';
var H = new stdlib.Int32Array(heap);
function hash(k, x) {
// k in bytes
k = k | 0;
x = x | 0;
var i = 0, j = 0, y0 = 0, z0 = 0, y1 = 0, z1 = 0, y2 = 0, z2 = 0, y3 = 0, z3 = 0, y4 = 0, z4 = 0, t0 = 0, t1 = 0;
y0 = H[x + 320 >> 2] | 0;
y1 = H[x + 324 >> 2] | 0;
y2 = H[x + 328 >> 2] | 0;
y3 = H[x + 332 >> 2] | 0;
y4 = H[x + 336 >> 2] | 0;
for (i = 0; (i | 0) < (k | 0); i = i + 64 | 0) {
z0 = y0;
z1 = y1;
z2 = y2;
z3 = y3;
z4 = y4;
for (j = 0; (j | 0) < 64; j = j + 4 | 0) {
t1 = H[i + j >> 2] | 0;
t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | ~y1 & y3) | 0) + ((t1 + y4 | 0) + 1518500249 | 0) | 0;
y4 = y3;
y3 = y2;
y2 = y1 << 30 | y1 >>> 2;
y1 = y0;
y0 = t0;
;
H[k + j >> 2] = t1;
}
for (j = k + 64 | 0; (j | 0) < (k + 80 | 0); j = j + 4 | 0) {
t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | ~y1 & y3) | 0) + ((t1 + y4 | 0) + 1518500249 | 0) | 0;
y4 = y3;
y3 = y2;
y2 = y1 << 30 | y1 >>> 2;
y1 = y0;
y0 = t0;
;
H[j >> 2] = t1;
}
for (j = k + 80 | 0; (j | 0) < (k + 160 | 0); j = j + 4 | 0) {
t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
t0 = ((y0 << 5 | y0 >>> 27) + (y1 ^ y2 ^ y3) | 0) + ((t1 + y4 | 0) + 1859775393 | 0) | 0;
y4 = y3;
y3 = y2;
y2 = y1 << 30 | y1 >>> 2;
y1 = y0;
y0 = t0;
;
H[j >> 2] = t1;
}
for (j = k + 160 | 0; (j | 0) < (k + 240 | 0); j = j + 4 | 0) {
t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
t0 = ((y0 << 5 | y0 >>> 27) + (y1 & y2 | y1 & y3 | y2 & y3) | 0) + ((t1 + y4 | 0) - 1894007588 | 0) | 0;
y4 = y3;
y3 = y2;
y2 = y1 << 30 | y1 >>> 2;
y1 = y0;
y0 = t0;
;
H[j >> 2] = t1;
}
for (j = k + 240 | 0; (j | 0) < (k + 320 | 0); j = j + 4 | 0) {
t1 = (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) << 1 | (H[j - 12 >> 2] ^ H[j - 32 >> 2] ^ H[j - 56 >> 2] ^ H[j - 64 >> 2]) >>> 31;
t0 = ((y0 << 5 | y0 >>> 27) + (y1 ^ y2 ^ y3) | 0) + ((t1 + y4 | 0) - 899497514 | 0) | 0;
y4 = y3;
y3 = y2;
y2 = y1 << 30 | y1 >>> 2;
y1 = y0;
y0 = t0;
;
H[j >> 2] = t1;
}
y0 = y0 + z0 | 0;
y1 = y1 + z1 | 0;
y2 = y2 + z2 | 0;
y3 = y3 + z3 | 0;
y4 = y4 + z4 | 0;
}
H[x + 320 >> 2] = y0;
H[x + 324 >> 2] = y1;
H[x + 328 >> 2] = y2;
H[x + 332 >> 2] = y3;
H[x + 336 >> 2] = y4;
}
return { hash: hash };
}
}(this));

5
webogram.appcache

@ -1,5 +1,5 @@
CACHE MANIFEST CACHE MANIFEST
# Time: Sun Oct 19 2014 12:06:12 GMT+0200 (CEST) # Time: Tue Nov 11 2014 19:24:43 GMT+0300 (MSK)
CACHE: CACHE:
@ -31,6 +31,8 @@ img/logo_dogogram.png
img/logo_share.png img/logo_share.png
img/sound_a.wav img/sound_a.wav
js/app.js js/app.js
nacl/mtproto_crypto.nmf
nacl/mtproto_crypto.pexe
img/changelog/card_wecandoit.png img/changelog/card_wecandoit.png
img/changelog/search.png img/changelog/search.png
img/icons/AboutLogos_1x.png img/icons/AboutLogos_1x.png
@ -76,6 +78,7 @@ vendor/closure/long.js
vendor/cryptoJS/crypto.js vendor/cryptoJS/crypto.js
vendor/jsbn/jsbn_combined.js vendor/jsbn/jsbn_combined.js
vendor/leemon_bigint/bigint.js vendor/leemon_bigint/bigint.js
vendor/rusha/rusha.js
vendor/angular/i18n/angular-locale_de-de.js vendor/angular/i18n/angular-locale_de-de.js
vendor/angular/i18n/angular-locale_en-us.js vendor/angular/i18n/angular-locale_en-us.js
vendor/angular/i18n/angular-locale_es-es.js vendor/angular/i18n/angular-locale_es-es.js

Loading…
Cancel
Save