Started work on improved device guest sharing.

Ylian Saint-Hilaire committed Apr 9, 2021 at 00:28 UTC 9bf2e211ab85a29be0bbb03ff404184da02ed57c
77 files changed +2740 -132
emails/translations/account-check-min_cs.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Ověření e-mailem</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Ověření</b></table><p>Ahoj [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> požaduje ověření e-mailem a dokončete proces kliknutím na následující odkaz.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Kliknutím sem ověřte svou e-mailovou adresu.</a></p>Pokud jste tento požadavek nezačali, ignorujte tento e-mail.</div>
\ No newline at end of file
emails/translations/account-check-min_de.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - E-Mail-Überprüfung</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Überprüfung</b></table><p>Hallo [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> Wenn Sie eine E-Mail-Bestätigung anfordern, klicken Sie auf den folgenden Link, um den Vorgang abzuschließen.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Klicken Sie hier, um Ihre E-Mail-Adresse zu bestätigen.</a></p>Wenn Sie diese Anfrage nicht initiiert haben, ignorieren Sie diese Mail bitte.</div>
\ No newline at end of file
emails/translations/account-check-min_es.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Verificación de Correo Electrónico</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Verificación</b></table><p>Hola [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> solicita la verificación por correo electrónico, haga clic en el siguiente enlace para completar el proceso.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Haga clic aquí para verificar su dirección de correo electrónico.</a></p>Si Ud. no inicio este requerimiento, por favor ignore este correo.</div>
\ No newline at end of file
emails/translations/account-check-min_fi.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Sähköpostivarmistus</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Todentaminen</b></table><p>Moi [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> pyytää sähköpostitse vahvistusta, suorita prosessi napsauttamalla seuraavaa linkkiä.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Napsauta tätä vahvistaaksesi sähköpostiosoitteesi.</a></p>Jos et suorittanut tätä pyyntöä, voit ohitaa tämän sähköpostin.</div>
\ No newline at end of file
emails/translations/account-check-min_fr.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Vérification E-mail</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Vérification</b></table><p>Bonjour [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> demande une vérification par e-mail, cliquez sur le lien suivant pour terminer le processus.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Cliquez ici pour vérifier votre adresse e-mail.</a></p>Si vous n'avez pas initié cette demande, veuillez ignorer ce courrier.</div>
\ No newline at end of file
emails/translations/account-check-min_hi.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - ईमेल सत्यापन</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - सत्यापन</b></table><p>हाय [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> ईमेल सत्यापन का अनुरोध कर रहा है, प्रक्रिया को पूरा करने के लिए निम्न लिंक पर क्लिक करें।<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">अपना ई-मेल पता सत्यापित करने के लिए यहां क्लिक करें।</a></p>यदि आपने यह अनुरोध आरंभ नहीं किया है, तो कृपया इस मेल को अनदेखा करें।</div>
\ No newline at end of file
emails/translations/account-check-min_ja.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - メールの確認</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - 確認</b></table><p>[[[USERNAME]]]様 <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> がメールの確認をリクエストしている場合は、次のリンクをクリックしてプロセスを完了してください。<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">ここをクリックして、電子メールアドレスを確認してください。</a></p>このリクエストを開始していない場合は、このメールを無視してください。</div>
\ No newline at end of file
emails/translations/account-check-min_ko.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Email 인증</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - 인증</b></table><p>안녕하세요, [[[USERNAME]]]님. <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> 이메일 검증을 요구하는 경우, 다음 링크를 클릭하여 과정을 완료하십시오.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">이메일 주소를 검증하려면 여기를 클릭하십시오.</a></p>이 요청을 시작하지 않은 경우, 이 메일을 무시하십시오.</div>
\ No newline at end of file
emails/translations/account-check-min_nl.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - E-mail Verificatie</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Verificatie</b></table><p>Hallo [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> vraagt om e-mailverificatie, klik op de volgende link om het proces te voltooien.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Klik hier om uw e-mailadres te verifiëren.</a></p>Als u dit verzoek niet heeft ingediend, dan kunt u deze e-mail negeren.</div>
\ No newline at end of file
emails/translations/account-check-min_pt.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Verificação de Email</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Verificação</b></table><p>Olá [[[NOME DE USUÁRIO]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> está solicitando verificação de e-mail, clique no link a seguir para concluir o processo.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Clique aqui para verificar seu endereço de e-mail.</a></p>Se você não iniciou esta solicitação, ignore este e-mail.</div>
\ No newline at end of file
emails/translations/account-check-min_ru.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - подтверждение по электронной почте</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Подтверждение</b></table><p>Привет [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> запрашивает подтверждение по электронной почте, нажмите на следующую ссылку, чтобы завершить процесс.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Нажмите здесь, чтобы подтвердить свой адрес электронной почты.</a></p>Если вы не инициировали этот запрос, игнорируйте это письмо.</div>
\ No newline at end of file
emails/translations/account-check-min_tr.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - E-posta Doğrulaması</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Doğrulama</b></table><p>Merhaba [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> e-posta doğrulaması istiyorsa, işlemi tamamlamak için aşağıdaki bağlantıya tıklayın.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">E-posta adresinizi doğrulamak için burayı tıklayın.</a></p>Bu isteği siz başlatmadıysanız, lütfen bu postayı dikkate almayın.</div>
\ No newline at end of file
emails/translations/account-check-min_zh-chs.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]]-电邮验证</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]]-验证</b></table><p>[[[USERNAME]],你好, <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> 正在请求电邮验证,请单击以下连结以完成该过程。<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">单击此处以验证您的电邮地址。</a></p>如果您没有发起此请求,请不理此邮件。</div>
\ No newline at end of file
emails/translations/account-check-min_zh-cht.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]]-電郵驗證</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]]-驗證</b></table><p>[[[USERNAME]],你好, <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]</a> 正在請求電郵驗證,請單擊以下鏈結以完成該過程。<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">單擊此處以驗證你的電郵地址。</a></p>如果你沒有發起此請求,請不理此電郵。</div>
\ No newline at end of file
emails/translations/account-invite-min_cs.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Pozvánka na účet</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Pozvánka na účet</b></table><p>Účet byl pro vás vytvořen na serveru <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>, nyní k němu máte přístup:<p>&nbsp;&nbsp;&nbsp;Uživatelské jméno: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;Heslo: <b notrans=1>[[[PASSWORD]]]</b></p>S pozdravem,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_de.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Kontoeinladung</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Kontoeinladung</b></table><p>Auf dem Server wurde ein Konto für Sie erstellt <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>können Sie jetzt darauf zugreifen mit:<p>&nbsp;&nbsp;&nbsp;Benutzername: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;Passwort: <b notrans=1>[[[PASSWORD]]]</b></p>Freundliche Grüße,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_es.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Invitación de Cuenta</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Invitación de Cuenta</b></table><p>Una cuenta ha sido creada en su servidor <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>, ahora puede acceder con:<p>&nbsp;&nbsp;&nbsp;Nombre de usuario: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;Contraseña: <b notrans=1>[[[PASSWORD]]]</b></p>Atentamente,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_fi.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Tili kutsu</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Tili kutsu</b></table><p>Sinulle on luotu tili palvelimelle <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>, voit käyttää sitä nyt:<p>&nbsp;&nbsp;&nbsp;Käyttäjätunnus: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;Salasana: <b notrans=1>[[[PASSWORD]]]</b></p>Ystävällisin terveisin,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_fr.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Invitation au compte</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Invitation au compte</b></table><p>Un compte a été créé pour vous sur le serveur <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>, vous pouvez y accéder maintenant avec :<p>&nbsp;&nbsp;&nbsp;Nom d'utilisateur: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;Mot de passe: <b notrans=1>[[[PASSWORD]]]</b></p>Meilleures salutations,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_hi.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - खाता निमंत्रण</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - खाता निमंत्रण</b></table><p>सर्वर पर आपके लिए एक खाता बनाया गया था <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>, आप इसे अभी एक्सेस कर सकते हैं:<p>&nbsp;&nbsp;&nbsp;उपयोगकर्ता नाम: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;कुंजिका: <b notrans=1>[[[PASSWORD]]]</b></p>सादर,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_ja.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - アカウントの招待</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - アカウントの招待</b></table><p>サーバー上にアカウントが作成されました <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>、あなたは今それを使ってそれにアクセスできます:<p>&nbsp;&nbsp;&nbsp;ユーザー名: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;パスワード: <b notrans=1>[[[PASSWORD]]]</b></p>宜しくお願いします、<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_ko.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - 계정 초대</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - 계정 초대</b></table><p>당신을 위해 서버에서 한 계정이 생성되었습니다. <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>이제 당신은 다음으로 접근 가능합니다:<p>&nbsp;&nbsp;&nbsp;사용자 이름: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;암호: <b notrans=1>[[[PASSWORD]]]</b></p>최고의 안부를 전합니다,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_nl.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Account uitnodiging</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Account uitnodiging</b></table><p>Er is een account voor je aangemaakt op de server <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>, je hebt er nu toegang toe met:<p>&nbsp;&nbsp;&nbsp;Gebruikersnaam: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;Wachtwoord: <b notrans=1>[[[PASSWORD]]]</b></p>Vriendelijke groeten,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_pt.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Convite para conta</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Convite para conta</b></table><p>Uma conta foi criada para você no servidor <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>, você pode acessá-lo agora com:<p>&nbsp;&nbsp;&nbsp;Nome de usuário: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;Senha: <b notrans=1>[[[PASSWORD]]]</b></p>Cumprimentos,<br>[[[NOME DO USUÁRIO]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_ru.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - приглашение в аккаунт</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - приглашение в аккаунт</b></table><p>Учетная запись была создана для вас на сервере <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>Вы можете получить к нему доступ сейчас:<p>&nbsp;&nbsp;&nbsp;Имя пользователя: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;Пароль: <b notrans=1>[[[PASSWORD]]]</b></p>С уважением,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_tr.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Hesap Davetiyesi</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Hesap Davetiyesi</b></table><p>Sunucuda sizin için bir hesap oluşturuldu <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>, şimdi şununla erişebilirsiniz:<p>&nbsp;&nbsp;&nbsp;Kullanıcı adı: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;Parola: <b notrans=1>[[[PASSWORD]]]</b></p>Saygılarımla,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_zh-chs.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]]-帐户邀请</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]]-帐户邀请</b></table><p>在服务器上为您创建了一个帐户 <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>,您现在可以通过以下方式访问它:<p>&nbsp;&nbsp;&nbsp;用户名: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;密码: <b notrans=1>[[[PASSWORD]]]</b></p>最好的祝福,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-invite-min_zh-cht.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]]-帳戶邀請</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]]-帳戶邀請</b></table><p>在伺服器上為你創建了一個帳戶 <a href=[[[SERVERURL]]][[[URLARGS1]]] notrans=1>[[[SERVERNAME]]]</a>,你現在可以通過以下方式訪問它:<p>&nbsp;&nbsp;&nbsp;用戶名: <b notrans=1>[[[ACCOUNTNAME]]]</b><br>&nbsp;&nbsp;&nbsp;密碼: <b notrans=1>[[[PASSWORD]]]</b></p>最好的祝福,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/account-login-min_cs.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Přihlášení k účtu</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Přihlášení k účtu</b></table><p>Váš přihlašovací token je: [[[TOKEN]]]<p>Tento token lze použít pouze jednou a je platný po dobu 5 minut.</div>
\ No newline at end of file
emails/translations/account-login-min_de.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Konto-Login</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Konto-Login</b></table><p>Ihr Login-Token lautet: [[[TOKEN]]]<p>Dieser Token kann nur einmal verwendet werden und ist 5 Minuten gültig.</div>
\ No newline at end of file
emails/translations/account-login-min_es.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Inicio de Sesión</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Inicio de Sesión</b></table><p>Su token de inicio de sesión es: [[[TOKEN]]]<p>Este token sólo se puede usar una vez y es válido durante 5 minutos.</div>
\ No newline at end of file
emails/translations/account-login-min_fi.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Tilille Kirjautuminen</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Tilille Kirjautuminen</b></table><p>Kirjautumistunnuksesi on: [[[TOKEN]]]<p>Tätä tunnusta voidaan käyttää vain kerran ja se on voimassa 5 minuuttia.</div>
\ No newline at end of file
emails/translations/account-login-min_fr.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Connexion au compte</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Connexion au compte</b></table><p>Votre jeton de connexion est: [[[TOKEN]]]<p>Ce jeton ne peut être utilisé qu'une seule fois et est valide pendant 5 minutes.</div>
\ No newline at end of file
emails/translations/account-login-min_hi.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - खाता लॉगिन</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - खाता लॉगिन</b></table><p>आपका लॉगिन टोकन है: [[[TOKEN]]]<p>यह टोकन केवल एक बार उपयोग किया जा सकता है और 5 मिनट के लिए वैध है।</div>
\ No newline at end of file
emails/translations/account-login-min_ja.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - アカウントログイン</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - アカウントログイン</b></table><p>ログイントークンは次のとおりです:[[[TOKEN]]]<p>このトークンは1回だけ使用でき、5分間有効です。</div>
\ No newline at end of file
emails/translations/account-login-min_ko.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - 계정 로그인</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - 계정 로그인</b></table><p>당신이 로그인한 토큰은 다음과 같습니다 : [[[TOKEN]]]<p>이 토큰은 오직 한 번만 사용될 수 있으며, 5분 동안만 유효합니다.</div>
\ No newline at end of file
emails/translations/account-login-min_nl.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Inloggen account</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Inloggen account</b></table><p>Uw login token is: [[[TOKEN]]]<p>Dit token kan maar één keer worden gebruikt en is 5 minuten geldig.</div>
\ No newline at end of file
emails/translations/account-login-min_pt.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Login da conta</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Login da conta</b></table><p>Seu token de login é: [[[TOKEN]]]<p>Este token só pode ser usado uma vez e é válido por 5 minutos.</div>
\ No newline at end of file
emails/translations/account-login-min_ru.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Вход в аккаунт</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Вход в аккаунт</b></table><p>Ваш токен для входа: [[[TOKEN]]]<p>Этот токен может быть использован только один раз и действителен в течение 5 минут.</div>
\ No newline at end of file
emails/translations/account-login-min_tr.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Hesap Girişi</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Hesap Girişi</b></table><p>Giriş jetonunuz: [[[TOKEN]]]<p>Bu simge yalnızca bir kez kullanılabilir ve 5 dakika geçerlidir.</div>
\ No newline at end of file
emails/translations/account-login-min_zh-chs.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]]-帐户登录</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]]-帐户登录</b></table><p>您的登录保安编码为:[[[TOKEN]]]<p>此保安编码只能使用一次,有效期为5分钟。</div>
\ No newline at end of file
emails/translations/account-login-min_zh-cht.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]]-帳戶登入</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]]-帳戶登入</b></table><p>你的登入保安編碼為:[[[TOKEN]]]<p>該保安編碼只能使用一次,有效期為5分鐘。</div>
\ No newline at end of file
emails/translations/account-reset-min_cs.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Reset účtu</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Ověření</b></table><p>Ahoj [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> požaduje obnovení hesla k účtu, dokončete proces kliknutím na následující odkaz.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Kliknutím sem obnovíte heslo svého účtu.</a></p>Pokud jste tento požadavek nezačali, ignorujte tento e-mail.</div>
\ No newline at end of file
emails/translations/account-reset-min_de.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Zurücksetzen des Kontos</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Überprüfung</b></table><p>Hallo [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> Wenn Sie ein Zurücksetzen des Kontokennworts anfordern, klicken Sie auf den folgenden Link, um den Vorgang abzuschließen.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Klicken Sie hier, um Ihr Kontopasswort zurückzusetzen.</a></p>Wenn Sie diese Anfrage nicht initiiert haben, ignorieren Sie diese Mail bitte.</div>
\ No newline at end of file
emails/translations/account-reset-min_es.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Restablecimiento de Cuenta</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Verificación</b></table><p>Hola [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> solicita restablecer la contraseña de la cuenta, haga clic en el siguiente enlace para completar el proceso.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Haga clic aquí para restablecer la contraseña de su cuenta.</a></p>Si Ud. no inicio este requerimiento, por favor ignore este correo.</div>
\ No newline at end of file
emails/translations/account-reset-min_fi.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Tili nollattu</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Todentaminen</b></table><p>Moi [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> pyytää tilin salasanan palauttamista, suorita prosessi napsauttamalla seuraavaa linkkiä.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Palauta tilisi salasana napsauttamalla tätä.</a></p>Jos et suorittanut tätä pyyntöä, voit ohitaa tämän sähköpostin.</div>
\ No newline at end of file
emails/translations/account-reset-min_fr.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Réinitialisation du compte</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Vérification</b></table><p>Bonjour [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> demande une réinitialisation du mot de passe du compte, cliquez sur le lien suivant pour terminer le processus.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Cliquez ici pour réinitialiser le mot de passe de votre compte.</a></p>Si vous n'avez pas initié cette demande, veuillez ignorer ce courrier.</div>
\ No newline at end of file
emails/translations/account-reset-min_hi.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - खाता रीसेट</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - सत्यापन</b></table><p>हाय [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> खाता पासवर्ड रीसेट का अनुरोध कर रहा है, प्रक्रिया पूरी करने के लिए निम्न लिंक पर क्लिक करें।<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">अपना खाता पासवर्ड रीसेट करने के लिए यहां क्लिक करें।</a></p>यदि आपने यह अनुरोध आरंभ नहीं किया है, तो कृपया इस मेल को अनदेखा करें।</div>
\ No newline at end of file
emails/translations/account-reset-min_ja.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - アカウントのリセット</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - 確認</b></table><p>[[[USERNAME]]]様 <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> がアカウントパスワードのリセットを要求している場合は、次のリンクをクリックしてプロセスを完了します。<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">ここをクリックしてアカウントのパスワードをリセットしてください。</a></p>このリクエストを開始していない場合は、このメールを無視してください。</div>
\ No newline at end of file
emails/translations/account-reset-min_ko.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - 계정 재설정</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - 인증</b></table><p>안녕하세요, [[[USERNAME]]]님. <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> 계정 비밀번호 재설정을 요청하는 경우, 다음 링크를 클릭하여 과정을 완료하십시오.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">당신의 계정 암호를 초기화하려면 여기를 클릭하십시오.</a></p>이 요청을 시작하지 않은 경우, 이 메일을 무시하십시오.</div>
\ No newline at end of file
emails/translations/account-reset-min_nl.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Account Reset</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Verificatie</b></table><p>Hallo [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> vraagt om het opnieuw instellen van het wachtwoord van een account, klik op de volgende link om het proces te voltooien.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Klik hier om je wachtwoord opnieuw in te stellen.</a></p>Als u dit verzoek niet heeft ingediend, dan kunt u deze e-mail negeren.</div>
\ No newline at end of file
emails/translations/account-reset-min_pt.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Redefinição de conta</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Verificação</b></table><p>Olá [[[NOME DE USUÁRIO]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> está solicitando a redefinição da senha da conta, clique no link a seguir para concluir o processo.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Clique aqui para redefinir a senha da sua conta.</a></p>Se você não iniciou esta solicitação, ignore este e-mail.</div>
\ No newline at end of file
emails/translations/account-reset-min_ru.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Сброс учетной записи</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Подтверждение</b></table><p>Привет [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> запрашивает сброс пароля учетной записи, нажмите на следующую ссылку, чтобы завершить процесс.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Нажмите здесь, чтобы сбросить пароль учетной записи.</a></p>Если вы не инициировали этот запрос, игнорируйте это письмо.</div>
\ No newline at end of file
emails/translations/account-reset-min_tr.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Hesabı Sıfırlama</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Doğrulama</b></table><p>Merhaba [[[USERNAME]]], <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> bir hesap şifresi sıfırlama talep ediyor, işlemi tamamlamak için aşağıdaki bağlantıya tıklayın.<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">Hesap şifrenizi sıfırlamak için burayı tıklayın.</a></p>Bu isteği siz başlatmadıysanız, lütfen bu postayı dikkate almayın.</div>
\ No newline at end of file
emails/translations/account-reset-min_zh-chs.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]]-帐户重置</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]]-验证</b></table><p>[[[USERNAME]],你好, <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> 正在要求重置帐户密码,请单击以下连结以完成该过程。<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">单击此处重置您的帐户密码。</a></p>如果您没有发起此请求,请不理此邮件。</div>
\ No newline at end of file
emails/translations/account-reset-min_zh-cht.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]]-帳戶重置</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]]-驗證</b></table><p>[[[USERNAME]],你好, <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]</a> 正在要求重置帳戶密碼,請單擊以下鏈結以完成該過程。<p style=margin-left:30px><a href="[[[SERVERURL]]]/checkmail?c=[[[COOKIE]]][[[URLARGS2]]]">單擊此處重置你的帳戶密碼。</a></p>如果你沒有發起此請求,請不理此電郵。</div>
\ No newline at end of file
emails/translations/mesh-invite-min_cs.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Pozvánka</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Instalace agenta</b></table><area-name><p>Dobrý den, [[[NAME]]],</p></area-name><p>Uživatel [[[USERNAME]]] na serveru <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> vás žádá o instalaci softwaru pro spuštění relace dálkového ovládání.</p><area-msg><p>Zpráva: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Kliknutím sem stáhnete MeshAgent pro Windows.</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Kliknutím sem stáhnete MeshAgent pro Apple OSX.</a></p></area-osx><area-linux><p>V případě systému Linux vyjměte a vložte do terminálu a nainstalujte agenta:<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>Chcete-li nainstalovat software, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>klikněte zde</a> a postupujte podle pokynů.</p></area-link><p>Pokud jste tento požadavek nezačali, ignorujte tento e-mail.</p>S pozdravem,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_de.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Einladung</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Agenteninstallation</b></table><area-name><p>Hallo [[[NAME]]],</p></area-name><p>Benutzer [[[USERNAME]]] auf dem Server <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> fordert Sie auf, Software zu installieren, um eine Fernsteuerungssitzung zu starten.</p><area-msg><p>Botschaft: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Klicken Sie hier, um den MeshAgent für Windows herunterzuladen.</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Klicken Sie hier, um den MeshAgent für Apple OSX herunterzuladen.</a></p></area-osx><area-linux><p>Schneiden Sie unter Linux Folgendes aus und fügen Sie es in ein Terminal ein, um den Agenten zu installieren:<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>Um die Software zu installieren, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>hier klicken</a> und folgen Sie den Anweisungen.</p></area-link><p>Wenn Sie diese Anfrage nicht initiiert haben, ignorieren Sie diese Mail bitte.</p>Freundliche Grüße,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_es.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Invitación</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Instalación de Agente</b></table><area-name><p>Hola [[[NAME]]],</p></area-name><p>Usuario [[[USERNAME]]] en servidor <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> le solicita que instale software para iniciar una sesión de control remoto.</p><area-msg><p>Mensaje: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Haga clic aquí para descargar el Agente Mesh para Windows.</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Haga clic aquí para descargar el Agente Mesh para Apple OSX.</a></p></area-osx><area-linux><p>Para Linux, copie y pegue lo siguiente en la terminal para instalar el agente:<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>Para instalar el software, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>haga clic aquí</a> y siga las instrucciones.</p></area-link><p>Si Ud. no inicio este requerimiento, por favor ignore este correo.</p>Atentamente,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_fi.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Kutsu</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Agentin asennus</b></table><area-name><p>Hei [[[NAME]]],</p></area-name><p>Käyttäjä [[[USERNAME]]] palvelimella <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> pyytää sinua asentamaan ohjelmiston etäohjausistunnon aloittamiseksi.</p><area-msg><p>Viesti: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Napsauta tätä ladataksesi MeshAgent Windows:lle.</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Napsauta tätä ladataksesi MeshAgent Apple OSX:lle.</a></p></area-osx><area-linux><p>Linux: leikkaa ja liitä seuraava päätelaitteeseen agentin asentamiseksi:<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>Asentaaksesi ohjelman, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>klikkaa tästä</a> ja seuraa ohjeita.</p></area-link><p>Jos et suorittanut tätä pyyntöä, voit ohitaa tämän sähköpostin.</p>Ystävällisin terveisin,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_fr.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Invitation</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Installation de l'agent</b></table><area-name><p>Bonjour [[[NAME]]],</p></area-name><p>Utilisateur [[[USERNAME]]] sur le serveur <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> vous demande d'installer un logiciel pour démarrer une session de contrôle à distance.</p><area-msg><p>Message: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Cliquez ici pour télécharger le MeshAgent pour Windows.</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Cliquez ici pour télécharger le MeshAgent pour Apple OSX.</a></p></area-osx><area-linux><p>Pour Linux, copiez et collez les éléments suivants dans un terminal pour installer l'agent:<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>Pour installer le logiciel, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>cliquez ici</a> et suivez les instructions.</p></area-link><p>Si vous n'avez pas initié cette demande, veuillez ignorer ce courrier.</p>Meilleures salutations,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_hi.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - निमंत्रण</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - एजेंट स्थापना</b></table><area-name><p>नमस्कार [[[NAME]]],</p></area-name><p>उपयोगकर्ता [[[USERNAME]]] सर्वर पर <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> रिमोट कंट्रोल सेशन शुरू करने के लिए आपको सॉफ्टवेयर इंस्टॉल करने का अनुरोध कर रहा है।</p><area-msg><p>संदेश: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">विंडोज के लिए मेशजेंट को डाउनलोड करने के लिए यहां क्लिक करें।</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Apple OSX के लिए मेशजेंट को डाउनलोड करने के लिए यहां क्लिक करें।</a></p></area-osx><area-linux><p>लिनक्स में, एजेंट को स्थापित करने के लिए टर्मिनल में निम्नलिखित को काटें और चिपकाएँ:<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>सॉफ़्टवेयर स्थापित करने के लिए, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>यहाँ क्लिक करें</a> और निर्देशों का पालन करें।</p></area-link><p>यदि आपने यह अनुरोध आरंभ नहीं किया है, तो कृपया इस मेल को अनदेखा करें।</p>सादर,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_ja.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - 招待</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - エージェントのインストール</b></table><area-name><p>[[[NAME]]]様</p></area-name><p>サーバー上のユーザー[[[USERNAME]]] <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> リモートコントロールセッションを開始するソフトウェアをインストールするように要求しています。</p><area-msg><p>メッセージ: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Windows用のMeshAgentをダウンロードするには、ここをクリックしてください。</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">ここをクリックして、Apple OSX用のMeshAgentをダウンロードしてください。</a></p></area-osx><area-linux><p>Linuxの場合は、ターミナルで以下をカットアンドペーストしてエージェントをインストールします。<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>ソフトウェアをインストールするには、 <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>ここをクリック</a> 指示に従ってください。</p></area-link><p>このリクエストを開始していない場合は、このメールを無視してください。</p>宜しくお願いします、<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_ko.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - 초대</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - 에이전트 설치</b></table><area-name><p>안녕하세요, [[[NAME]]]님.</p></area-name><p>서버의 [[[USERNAME]]] 사용자 <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> 원격 제어 세션을 시작하기 위해 소프트웨어 설치를 요청하고 있습니다.</p><area-msg><p>메시지: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Windows를 위한 MeshAgent를 다운로드 하려면 여기를 클릭하십시오.</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Apple OSX를 위한 MeshAgent를 다운로드 하려면 여기를 클릭하십시오.</a></p></area-osx><area-linux><p>Linux의 경우, 다음을 잘라내어 터미널에 붙여 넣어 에이전트를 설치하십시오.<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>소프트웨어를 설치하려면, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>여기를 클릭하십시오.</a> 그리고 다음 지시들을 따르십시오.</p></area-link><p>이 요청을 시작하지 않은 경우, 이 메일을 무시하십시오.</p>최고의 안부를 전합니다,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_nl.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Uitnodiging</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Agent installatie</b></table><area-name><p>Hallo [[[NAME]]],</p></area-name><p>Gebruiker [[[USERNAME]]] op server <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> vraagt u om de software te installeren om een ondersteunings sessie te starten.</p><area-msg><p>Bericht: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Klik hier om de MeshAgent te downloaden voor Windows.</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Klik hier om de MeshAgent te downloaden voor Apple OSX.</a></p></area-osx><area-linux><p>Voor Linux, knip het volgende en plak dit in een terminal om de agent te installeren:<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>Om de software te installeren, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>Klik hier</a> en volg de instructies.</p></area-link><p>Als u dit verzoek niet heeft ingediend, dan kunt u deze e-mail negeren.</p>Vriendelijke groeten,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_pt.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Convite</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Instalação do Agente</b></table><area-name><p>Olá [[[NAME]]],</p></area-name><p>Usuário [[[USERNAME]]] no servidor <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> está solicitando a instalação de um software para iniciar uma sessão de controle remoto.</p><area-msg><p>Mensagem: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Clique aqui para baixar o MeshAgent para Windows.</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Clique aqui para baixar o MeshAgent para Apple OSX.</a></p></area-osx><area-linux><p>Para Linux, recorte e cole o seguinte em um terminal para instalar o agente:<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>Para instalar o software, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>Clique aqui</a> e siga as instruções.</p></area-link><p>Se você não iniciou esta solicitação, ignore este e-mail.</p>Cumprimentos,<br>[[[NOME DO USUÁRIO]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_ru.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Приглашение</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Установка агента</b></table><area-name><p>Здравствуйте, [[[NAME]]],</p></area-name><p>Пользователь [[[USERNAME]]] на сервере <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> просит вас установить программное обеспечение, чтобы начать сеанс удаленного управления.</p><area-msg><p>Сообщение: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Нажмите здесь, чтобы загрузить MeshAgent для Windows.</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Нажмите здесь, чтобы загрузить MeshAgent для Apple OSX.</a></p></area-osx><area-linux><p>Для Linux вырезайте и вставляйте в терминал следующее, чтобы установить агент:<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>Чтобы установить программное обеспечение, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>кликните сюда</a> и следуйте инструкциям.</p></area-link><p>Если вы не инициировали этот запрос, игнорируйте это письмо.</p>С уважением,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_tr.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]] - Davet</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]] - Aracı Kurulumu</b></table><area-name><p>Merhaba [[[NAME]]],</p></area-name><p>Sunucudaki kullanıcı [[[USERNAME]]] <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> bir uzaktan kontrol oturumu başlatmak için yazılım yüklemenizi istiyor.</p><area-msg><p>İleti: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Windows için MeshAgent'ı indirmek için buraya tıklayın.</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">Apple OSX için MeshAgent'ı indirmek için burayı tıklayın.</a></p></area-osx><area-linux><p>Linux için, aracıyı yüklemek için aşağıdakileri kesip bir terminale yapıştırın:<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>Yazılımı kurmak için, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>buraya Tıkla</a> ve talimatları izleyin.</p></area-link><p>Bu isteği siz başlatmadıysanız, lütfen bu postayı dikkate almayın.</p>Saygılarımla,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_zh-chs.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]]-邀请</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]]-代理程序安装</b></table><area-name><p>您好[[[NAME]]],</p></area-name><p>服务器上的使用者[[[USERNAME]]] <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]]</a> 正在要求您安装软件以启动远程控制会话。</p><area-msg><p>消息: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">单击此处下载适用于Windows的MeshAgent。</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">单击此处下载适用于Apple OSX的MeshAgent。</a></p></area-osx><area-linux><p>对于Linux,将以下内容剪切并粘贴到终端中以安装代理软件:<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>要安装软件, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>点击这里</a> 并按照说明进行操作。</p></area-link><p>如果您没有发起此请求,请不理此邮件。</p>最好的祝福,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
emails/translations/mesh-invite-min_zh-cht.html new
+1
@@ -0,0 +1 @@
1 +<div>[[[SERVERNAME]]]-邀請</div><div style=font-family:Arial,Helvetica,sans-serif><table style=background-color:#036;color:#d3d3d3;width:100% cellpadding=8><tr><td><b style=font-size:20px;font-family:Arial,Helvetica,sans-serif>[[[SERVERNAME]]]-代理程序安裝</b></table><area-name><p>你好[[[NAME]]],</p></area-name><p>伺服器上的使用者[[[USERNAME]]] <a href=[[[SERVERURL]]][[[URLARGS1]]]>[[[SERVERNAME]]</a> 正在要求你安裝軟體以啟動遠程控制會話。</p><area-msg><p>訊息: <b notrans=1>[[[MSG]]]</b></p></area-msg><area-windows><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshagents?id=4&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">單擊此處下載適用於Windows的MeshAgent。</a></p></area-windows><area-osx><p style=margin-left:30px><a href="[[[SERVERURL]]]/meshosxagent?id=16&amp;meshid=[[[MESHIDHEX]]]&amp;tag=mailto:[[[EMAIL]]]&amp;installflags=[[[INSTALLFLAGS]]]">單擊此處下載適用於Apple OSX的MeshAgent。</a></p></area-osx><area-linux><p>對於Linux,將以下內容剪切並粘貼到終端中以安裝代理軟體:<br><pre style=margin-left:30px notrans=1>wget -q "[[[SERVERURL]]]/meshagents?script=1" --no-check-certificate -O ./meshinstall.sh &amp;&amp; chmod 755 ./meshinstall.sh &amp;&amp; sudo ./meshinstall.sh [[[SERVERURL]]] \'[[[MESHIDHEX]]]\'</pre><p></p></area-linux><area-link><p>要安裝軟體, <a href=[[[SERVERURL]]][[[LINKURL]]][[[URLARGS2]]]>點擊這裡</a> 並按照說明進行操作。</p></area-link><p>如果你沒有發起此請求,請不理此電郵。</p>最好的祝福,<br>[[[USERNAME]]]<br></div>
\ No newline at end of file
public/images/sharing-32.png
Binary files /dev/null and b/public/images/sharing-32.png differ
public/images/sharing-64.png
Binary files /dev/null and b/public/images/sharing-64.png differ
public/styles/style-sharing.css new
+65
@@ -0,0 +1,65 @@
1 +.slbbutton {
2 + width: 44px;
3 + height: 44px;
4 + border-radius: 5px;
5 + background-color: #BBB;
6 + margin-left: 4px;
7 + margin-top: 8px;
8 + position: relative;
9 + cursor: pointer;
10 + opacity: 0.5;
11 +}
12 +
13 + .night .slbbutton {
14 + background-color: black;
15 + }
16 +
17 + .slbbutton:hover {
18 + opacity: 1;
19 + }
20 +
21 +.slbbuttonsel {
22 + opacity: 0.9;
23 +}
24 +
25 +.slbbuttonsel2 {
26 + width: 70px;
27 + border-radius: 5px 0px 0px 5px;
28 + opacity: 1;
29 +}
30 +
31 +.slb1 {
32 + background: url(../images/sharing-32.png) 0px 0px;
33 + background-image: image-set(url(../images/sharing-32.png) 1x, url(../images/sharing-64.png) 2x);
34 + height: 32px;
35 + width: 32px;
36 + cursor: pointer;
37 + border: none;
38 + position: absolute;
39 + top: 3px;
40 + left: 3px;
41 +}
42 +
43 +.slb2 {
44 + background: url(../images/sharing-32.png) -32px 0px;
45 + background-image: image-set(url(../images/sharing-32.png) 1x, url(../images/sharing-64.png) 2x);
46 + height: 32px;
47 + width: 32px;
48 + cursor: pointer;
49 + border: none;
50 + position: absolute;
51 + top: 3px;
52 + left: 3px;
53 +}
54 +
55 +.slb3 {
56 + background: url(../images/sharing-32.png) -64px 0px;
57 + background-image: image-set(url(../images/sharing-32.png) 1x, url(../images/sharing-64.png) 2x);
58 + height: 32px;
59 + width: 32px;
60 + cursor: pointer;
61 + border: none;
62 + position: absolute;
63 + top: 3px;
64 + left: 3px;
65 +}
\ No newline at end of file
translate/translate.js
+2
@@ -38,6 +38,7 @@ var meshCentralSourceFiles = [
38 "../views/player.handlebars",
39 "../views/desktop.handlebars",
40 "../views/terminal.handlebars",
41 + "../views/sharing.handlebars",
42 "../views/mstsc.handlebars",
43 "../emails/account-check.html",
44 "../emails/account-invite.html",
@@ -75,6 +76,7 @@ var minifyMeshCentralSourceFiles = [
76 "../views/player.handlebars",
77 "../views/desktop.handlebars",
78 "../views/terminal.handlebars",
79 + "../views/sharing.handlebars",
80 "../views/mstsc.handlebars",
81 "../public/scripts/agent-desktop-0.0.2.js",
82 "../public/scripts/agent-redir-rtc-0.1.0.js",
translate/translate.json
+340 -125
@@ -600,7 +600,8 @@
600 "zh-cht": ",軟體KVM",
601 "xloc": [
602 "default.handlebars->31->938",
603 - "desktop.handlebars->3->12"
603 + "desktop.handlebars->3->12",
604 + "sharing.handlebars->11->12"
605 ]
606 },
607 {
@@ -644,6 +645,9 @@
645 "default.handlebars->31->1019",
646 "default.handlebars->31->945",
647 "desktop.handlebars->3->19",
648 + "sharing.handlebars->11->19",
649 + "sharing.handlebars->11->27",
650 + "sharing.handlebars->11->44",
651 "terminal.handlebars->3->9",
652 "xterm.handlebars->9->6"
653 ]
@@ -667,6 +671,7 @@
671 "xloc": [
672 "default.handlebars->container->column_l->p11->p11warning->3->p11warninga",
673 "default.handlebars->container->column_l->p12->p12warning->3->p12warninga",
674 + "sharing.handlebars->p12->p12warning->3->p12warninga",
675 "terminal.handlebars->p12->p12warning->3->p12warninga"
676 ]
677 },
@@ -766,7 +771,8 @@
771 "zh-cht": ",{0}觀看",
772 "xloc": [
773 "default.handlebars->31->939",
769 - "desktop.handlebars->3->13"
774 + "desktop.handlebars->3->13",
775 + "sharing.handlebars->11->13"
776 ]
777 },
778 {
@@ -832,7 +838,8 @@
838 "default-mobile.handlebars->11->376",
839 "default.handlebars->31->1025",
840 "default.handlebars->31->1706",
835 - "default.handlebars->31->2229"
841 + "default.handlebars->31->2229",
842 + "sharing.handlebars->11->50"
843 ]
844 },
845 {
@@ -913,7 +920,8 @@
920 "default-mobile.handlebars->11->626",
921 "default.handlebars->31->1730",
922 "download.handlebars->3->1",
916 - "download2.handlebars->5->1"
923 + "download2.handlebars->5->1",
924 + "sharing.handlebars->11->96"
925 ]
926 },
927 {
@@ -934,7 +942,8 @@
942 "zh-cht": "1位聯絡文",
943 "xloc": [
944 "default.handlebars->31->941",
937 - "desktop.handlebars->3->15"
945 + "desktop.handlebars->3->15",
946 + "sharing.handlebars->11->15"
947 ]
948 },
949 {
@@ -1300,7 +1309,8 @@
1309 "xloc": [
1310 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->2->3->d7bitmapscaling->1",
1311 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->1",
1303 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->1"
1312 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->1",
1313 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->1"
1314 ]
1315 },
1316 {
@@ -1321,6 +1331,7 @@
1331 "zh-cht": "100x30",
1332 "xloc": [
1333 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSizeDropDown->termSizeList->1",
1334 + "sharing.handlebars->p12->9->1->terminalSizeDropDown->termSizeList->1",
1335 "terminal.handlebars->p12->9->1->terminalSizeDropDown->termSizeList->1"
1336 ]
1337 },
@@ -1383,7 +1394,8 @@
1394 "xloc": [
1395 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->2->3->d7bitmapscaling->15",
1396 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->15",
1386 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->15"
1397 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->15",
1398 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->15"
1399 ]
1400 },
1401 {
@@ -1589,7 +1601,8 @@
1601 "xloc": [
1602 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->2->3->d7bitmapscaling->13",
1603 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->13",
1592 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->13"
1604 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->13",
1605 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->13"
1606 ]
1607 },
1608 {
@@ -1812,7 +1825,8 @@
1825 "xloc": [
1826 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->2->3->d7bitmapscaling->11",
1827 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->11",
1815 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->11"
1828 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->11",
1829 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->11"
1830 ]
1831 },
1832 {
@@ -2039,7 +2053,8 @@
2053 "xloc": [
2054 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->2->3->d7bitmapscaling->9",
2055 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->9",
2042 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->9"
2056 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->9",
2057 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->9"
2058 ]
2059 },
2060 {
@@ -2123,7 +2138,8 @@
2138 "xloc": [
2139 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->2->3->d7bitmapscaling->7",
2140 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->7",
2126 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->7"
2141 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->7",
2142 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->7"
2143 ]
2144 },
2145 {
@@ -2264,7 +2280,8 @@
2280 "xloc": [
2281 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->2->3->d7bitmapscaling->5",
2282 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->5",
2267 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->5"
2283 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->5",
2284 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->5"
2285 ]
2286 },
2287 {
@@ -2307,6 +2324,7 @@
2324 "zh-cht": "80x25",
2325 "xloc": [
2326 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSizeDropDown->termSizeList->0",
2327 + "sharing.handlebars->p12->9->1->terminalSizeDropDown->termSizeList->0",
2328 "terminal.handlebars->p12->9->1->terminalSizeDropDown->termSizeList->0"
2329 ]
2330 },
@@ -2329,7 +2347,8 @@
2347 "xloc": [
2348 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->2->3->d7bitmapscaling->3",
2349 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->3",
2332 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->3"
2350 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->3",
2351 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->5->d7bitmapscaling->3"
2352 ]
2353 },
2354 {
@@ -4551,7 +4570,8 @@
4570 "xloc": [
4571 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->1",
4572 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->1",
4554 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->1"
4573 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->1",
4574 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->1"
4575 ]
4576 },
4577 {
@@ -4986,7 +5006,8 @@
5006 "zh-cht": "Alt-F4",
5007 "xloc": [
5008 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->19",
4989 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->17"
5009 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->17",
5010 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->17"
5011 ]
5012 },
5013 {
@@ -5007,7 +5028,8 @@
5028 "zh-cht": "Alt-Tab",
5029 "xloc": [
5030 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->23",
5010 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->21"
5031 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->21",
5032 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->21"
5033 ]
5034 },
5035 {
@@ -5028,6 +5050,7 @@
5050 "zh-cht": "備用(F10 = ESC + 0)",
5051 "xloc": [
5052 "default.handlebars->31->1012",
5053 + "sharing.handlebars->11->37",
5054 "terminal.handlebars->3->19"
5055 ]
5056 },
@@ -6138,7 +6161,8 @@
6161 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3",
6162 "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3",
6163 "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->3",
6141 - "desktop.handlebars->p11->deskarea0->deskarea1->3"
6164 + "desktop.handlebars->p11->deskarea0->deskarea1->3",
6165 + "sharing.handlebars->p11->deskarea0->deskarea1->3"
6166 ]
6167 },
6168 {
@@ -6426,6 +6450,7 @@
6450 "zh-cht": "退格鍵",
6451 "xloc": [
6452 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3",
6453 + "sharing.handlebars->p12->9->3",
6454 "terminal.handlebars->p12->9->3"
6455 ]
6456 },
@@ -7036,6 +7061,9 @@
7061 "default.handlebars->31->1005",
7062 "default.handlebars->31->1014",
7063 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons",
7064 + "sharing.handlebars->11->25",
7065 + "sharing.handlebars->11->39",
7066 + "sharing.handlebars->p12->9->1->terminalSettingsButtons",
7067 "terminal.handlebars->3->21",
7068 "terminal.handlebars->3->7",
7069 "terminal.handlebars->p12->9->1->terminalSettingsButtons"
@@ -7148,6 +7176,7 @@
7176 "login.handlebars->dialog->idx_dlgButtonBar",
7177 "login2.handlebars->dialog->idx_dlgButtonBar",
7178 "player.handlebars->p11->dialog->idx_dlgButtonBar",
7179 + "sharing.handlebars->dialog->idx_dlgButtonBar",
7180 "terminal.handlebars->p12->dialog->idx_dlgButtonBar",
7181 "xterm.handlebars->p11->dialog->idx_dlgButtonBar"
7182 ]
@@ -8064,7 +8093,11 @@
8093 "default.handlebars->31->1745",
8094 "default.handlebars->container->column_l->p15->consoleTable->1->6->1->1->1->0->7",
8095 "default.handlebars->container->column_l->p41->3->1",
8067 - "messenger.handlebars->xbottom->1->1->0->5"
8096 + "messenger.handlebars->xbottom->1->1->0->5",
8097 + "sharing.handlebars->11->75",
8098 + "sharing.handlebars->11->77",
8099 + "sharing.handlebars->11->79",
8100 + "sharing.handlebars->11->81"
8101 ]
8102 },
8103 {
@@ -8523,7 +8556,8 @@
8556 "zh-cht": "剪貼板",
8557 "xloc": [
8558 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3",
8526 - "desktop.handlebars->p11->deskarea0->deskarea4->3"
8559 + "desktop.handlebars->p11->deskarea0->deskarea4->3",
8560 + "sharing.handlebars->p11->deskarea0->deskarea4->3"
8561 ]
8562 },
8563 {
@@ -8548,7 +8582,8 @@
8582 "default.handlebars->31->152",
8583 "default.handlebars->31->160",
8584 "default.handlebars->31->2343",
8551 - "default.handlebars->31->994"
8585 + "default.handlebars->31->994",
8586 + "sharing.handlebars->11->52"
8587 ]
8588 },
8589 {
@@ -8765,7 +8800,8 @@
8800 "zh-chs": "压缩档案...",
8801 "zh-cht": "壓縮檔案...",
8802 "xloc": [
8768 - "default.handlebars->31->1022"
8803 + "default.handlebars->31->1022",
8804 + "sharing.handlebars->11->47"
8805 ]
8806 },
8807 {
@@ -8815,7 +8851,8 @@
8851 "zh-cht": "確認將1個副本複製到此位置?",
8852 "xloc": [
8853 "default-mobile.handlebars->11->390",
8818 - "default.handlebars->31->1045"
8854 + "default.handlebars->31->1045",
8855 + "sharing.handlebars->11->70"
8856 ]
8857 },
8858 {
@@ -8835,7 +8872,8 @@
8872 "zh-chs": "确认{0}个条目的复制到此位置?",
8873 "zh-cht": "確認{0}個條目的複製到此位置?",
8874 "xloc": [
8838 - "default.handlebars->31->1044"
8875 + "default.handlebars->31->1044",
8876 + "sharing.handlebars->11->69"
8877 ]
8878 },
8879 {
@@ -8996,7 +9034,8 @@
9034 "zh-cht": "確認將1個條目移動到此位置?",
9035 "xloc": [
9036 "default-mobile.handlebars->11->392",
8999 - "default.handlebars->31->1047"
9037 + "default.handlebars->31->1047",
9038 + "sharing.handlebars->11->72"
9039 ]
9040 },
9041 {
@@ -9016,7 +9055,8 @@
9055 "zh-chs": "确认将{0}个条目移到此位置?",
9056 "zh-cht": "確認將{0}個條目移到該位置?",
9057 "xloc": [
9019 - "default.handlebars->31->1046"
9058 + "default.handlebars->31->1046",
9059 + "sharing.handlebars->11->71"
9060 ]
9061 },
9062 {
@@ -9381,6 +9421,10 @@
9421 "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->3",
9422 "desktop.handlebars->p11->deskarea0->deskarea1->3->connectbutton1span",
9423 "mstsc.handlebars->main->1->3->1->8->1->0",
9424 + "sharing.handlebars->11->42",
9425 + "sharing.handlebars->p11->deskarea0->deskarea1->3->connectbutton1span",
9426 + "sharing.handlebars->p12->5->3->connectbutton2span",
9427 + "sharing.handlebars->p13->p13toolbar->1->3",
9428 "terminal.handlebars->p12->5->3->connectbutton2span",
9429 "xterm.handlebars->p11->deskarea0->deskarea1->3"
9430 ]
@@ -9463,7 +9507,8 @@
9507 "zh-chs": "使用Intel AMT硬件KVM连接",
9508 "zh-cht": "使用Intel AMT硬件KVM連接",
9509 "xloc": [
9466 - "desktop.handlebars->p11->deskarea0->deskarea1->3->connectbutton1hspan"
9510 + "desktop.handlebars->p11->deskarea0->deskarea1->3->connectbutton1hspan",
9511 + "sharing.handlebars->p11->deskarea0->deskarea1->3->connectbutton1hspan"
9512 ]
9513 },
9514 {
@@ -9524,6 +9569,7 @@
9569 "default-mobile.handlebars->11->4",
9570 "default.handlebars->31->11",
9571 "desktop.handlebars->3->4",
9572 + "sharing.handlebars->11->4",
9573 "terminal.handlebars->3->4",
9574 "xterm.handlebars->9->4"
9575 ]
@@ -9635,6 +9681,8 @@
9681 "default.handlebars->31->310",
9682 "default.handlebars->31->9",
9683 "desktop.handlebars->3->2",
9684 + "sharing.handlebars->11->2",
9685 + "sharing.handlebars->11->93",
9686 "terminal.handlebars->3->2",
9687 "xterm.handlebars->9->2"
9688 ]
@@ -9850,7 +9898,8 @@
9898 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->3",
9899 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->3",
9900 "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
9853 - "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3"
9901 + "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3",
9902 + "sharing.handlebars->p13->p13toolbar->fileArea2->3"
9903 ]
9904 },
9905 {
@@ -10699,6 +10748,7 @@
10748 "zh-cht": "Ctl-C",
10749 "xloc": [
10750 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3",
10751 + "sharing.handlebars->p12->9->3",
10752 "terminal.handlebars->p12->9->3"
10753 ]
10754 },
@@ -10720,6 +10770,7 @@
10770 "zh-cht": "Ctl-X",
10771 "xloc": [
10772 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3",
10773 + "sharing.handlebars->p12->9->3",
10774 "terminal.handlebars->p12->9->3"
10775 ]
10776 },
@@ -10745,6 +10796,7 @@
10796 "default.handlebars->31->57",
10797 "default.handlebars->31->970",
10798 "default.handlebars->31->974",
10799 + "sharing.handlebars->11->24",
10800 "terminal.handlebars->3->6"
10801 ]
10802 },
@@ -10772,7 +10824,8 @@
10824 "zh-cht": "Ctrl + Alt + Del",
10825 "xloc": [
10826 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->1",
10775 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->1"
10827 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->1",
10828 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->1"
10829 ]
10830 },
10831 {
@@ -10810,7 +10863,8 @@
10863 "zh-cht": "Ctrl-W",
10864 "xloc": [
10865 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->21",
10813 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->19"
10866 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->19",
10867 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->19"
10868 ]
10869 },
10870 {
@@ -10901,7 +10955,8 @@
10955 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->2->1->3",
10956 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->3",
10957 "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
10904 - "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3"
10958 + "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3",
10959 + "sharing.handlebars->p13->p13toolbar->fileArea2->3"
10960 ]
10961 },
10962 {
@@ -10992,7 +11047,8 @@
11047 "zh-cht": "數據通道",
11048 "xloc": [
11049 "default.handlebars->31->937",
10995 - "desktop.handlebars->3->11"
11050 + "desktop.handlebars->3->11",
11051 + "sharing.handlebars->11->11"
11052 ]
11053 },
11054 {
@@ -11178,6 +11234,9 @@
11234 "default.handlebars->filesContextMenu->5",
11235 "desktop.handlebars->p11->dialog->idx_dlgButtonBar->5",
11236 "player.handlebars->p11->dialog->idx_dlgButtonBar->5",
11237 + "sharing.handlebars->11->61",
11238 + "sharing.handlebars->dialog->idx_dlgButtonBar->5",
11239 + "sharing.handlebars->p13->p13toolbar->fileArea2->3",
11240 "terminal.handlebars->p12->dialog->idx_dlgButtonBar->5",
11241 "xterm.handlebars->p11->dialog->idx_dlgButtonBar->5"
11242 ]
@@ -11511,7 +11570,8 @@
11570 "default-mobile.handlebars->11->147",
11571 "default-mobile.handlebars->11->384",
11572 "default.handlebars->31->1038",
11514 - "default.handlebars->31->1736"
11573 + "default.handlebars->31->1736",
11574 + "sharing.handlebars->11->63"
11575 ]
11576 },
11577 {
@@ -11554,7 +11614,8 @@
11614 "default-mobile.handlebars->11->146",
11615 "default-mobile.handlebars->11->383",
11616 "default.handlebars->31->1037",
11557 - "default.handlebars->31->1735"
11617 + "default.handlebars->31->1735",
11618 + "sharing.handlebars->11->62"
11619 ]
11620 },
11621 {
@@ -11637,6 +11698,8 @@
11698 "default-mobile.handlebars->11->334",
11699 "default.handlebars->31->933",
11700 "desktop.handlebars->3->7",
11701 + "sharing.handlebars->11->29",
11702 + "sharing.handlebars->11->7",
11703 "terminal.handlebars->3->11"
11704 ]
11705 },
@@ -11660,7 +11723,8 @@
11723 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->11",
11724 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->11",
11725 "default.handlebars->container->column_l->p13->p13toolbar->1->4->1->1->p13sortdropdown->11",
11663 - "default.handlebars->container->column_l->p5->p5toolbar->1->2->p5filesubhead->1->p5sortdropdown->11"
11726 + "default.handlebars->container->column_l->p5->p5toolbar->1->2->p5filesubhead->1->p5sortdropdown->11",
11727 + "sharing.handlebars->p13->p13toolbar->5->1->p13sortdropdown->11"
11728 ]
11729 },
11730 {
@@ -11683,7 +11747,8 @@
11747 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->7",
11748 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->7",
11749 "default.handlebars->container->column_l->p13->p13toolbar->1->4->1->1->p13sortdropdown->7",
11686 - "default.handlebars->container->column_l->p5->p5toolbar->1->2->p5filesubhead->1->p5sortdropdown->7"
11750 + "default.handlebars->container->column_l->p5->p5toolbar->1->2->p5filesubhead->1->p5sortdropdown->7",
11751 + "sharing.handlebars->p13->p13toolbar->5->1->p13sortdropdown->7"
11752 ]
11753 },
11754 {
@@ -11706,7 +11771,8 @@
11771 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->9",
11772 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->9",
11773 "default.handlebars->container->column_l->p13->p13toolbar->1->4->1->1->p13sortdropdown->9",
11709 - "default.handlebars->container->column_l->p5->p5toolbar->1->2->p5filesubhead->1->p5sortdropdown->9"
11774 + "default.handlebars->container->column_l->p5->p5toolbar->1->2->p5filesubhead->1->p5sortdropdown->9",
11775 + "sharing.handlebars->p13->p13toolbar->5->1->p13sortdropdown->9"
11776 ]
11777 },
11778 {
@@ -11792,7 +11858,9 @@
11858 "default.handlebars->31->805",
11859 "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevDesktop",
11860 "default.handlebars->contextMenu->cxdesktop",
11795 - "desktop.handlebars->3->23"
11861 + "desktop.handlebars->3->23",
11862 + "sharing.handlebars->11->23",
11863 + "sharing.handlebars->LeftSideToolBar"
11864 ]
11865 },
11866 {
@@ -11902,7 +11970,8 @@
11970 "zh-cht": "桌面會話延遲",
11971 "xloc": [
11972 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1",
11905 - "desktop.handlebars->p11->deskarea0->deskarea4->1"
11973 + "desktop.handlebars->p11->deskarea0->deskarea4->1",
11974 + "sharing.handlebars->p11->deskarea0->deskarea4->1"
11975 ]
11976 },
11977 {
@@ -13044,6 +13113,9 @@
13113 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->disconnectbutton1span",
13114 "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->disconnectbutton2span",
13115 "desktop.handlebars->p11->deskarea0->deskarea1->3->disconnectbutton1span",
13116 + "sharing.handlebars->11->43",
13117 + "sharing.handlebars->p11->deskarea0->deskarea1->3->disconnectbutton1span",
13118 + "sharing.handlebars->p12->5->3->disconnectbutton2span",
13119 "terminal.handlebars->p12->5->3->disconnectbutton2span",
13120 "xterm.handlebars->p11->deskarea0->deskarea1->3"
13121 ]
@@ -13099,6 +13171,10 @@
13171 "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->3->p13Status",
13172 "desktop.handlebars->3->1",
13173 "desktop.handlebars->p11->deskarea0->deskarea1->3->deskstatus",
13174 + "sharing.handlebars->11->1",
13175 + "sharing.handlebars->p11->deskarea0->deskarea1->3->deskstatus",
13176 + "sharing.handlebars->p12->5->3->termstatus",
13177 + "sharing.handlebars->p13->p13toolbar->1->3->p13Status",
13178 "terminal.handlebars->3->1",
13179 "terminal.handlebars->p12->5->3->termstatus",
13180 "xterm.handlebars->9->1"
@@ -13522,7 +13598,8 @@
13598 "zh-cht": "下載檔案",
13599 "xloc": [
13600 "default-mobile.handlebars->11->403",
13525 - "default.handlebars->31->1057"
13601 + "default.handlebars->31->1057",
13602 + "sharing.handlebars->11->82"
13603 ]
13604 },
13605 {
@@ -14365,6 +14442,7 @@
14442 "xloc": [
14443 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3",
14444 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3",
14445 + "sharing.handlebars->p12->9->3",
14446 "terminal.handlebars->p12->9->3"
14447 ]
14448 },
@@ -14386,7 +14464,8 @@
14464 "zh-cht": "編輯",
14465 "xloc": [
14466 "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
14389 - "default.handlebars->filesContextMenu->3"
14467 + "default.handlebars->filesContextMenu->3",
14468 + "sharing.handlebars->p13->p13toolbar->fileArea2->3"
14469 ]
14470 },
14471 {
@@ -14785,7 +14864,8 @@
14864 "zh-cht": "編輯遠程桌面設置",
14865 "xloc": [
14866 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1",
14788 - "desktop.handlebars->p11->deskarea0->deskarea1->1"
14867 + "desktop.handlebars->p11->deskarea0->deskarea1->1",
14868 + "sharing.handlebars->p11->deskarea0->deskarea1->1"
14869 ]
14870 },
14871 {
@@ -15717,7 +15797,8 @@
15797 "default.handlebars->31->1030",
15798 "default.handlebars->31->1439",
15799 "default.handlebars->31->1440",
15720 - "default.handlebars->31->954"
15800 + "default.handlebars->31->954",
15801 + "sharing.handlebars->11->55"
15802 ]
15803 },
15804 {
@@ -15777,7 +15858,8 @@
15858 "zh-chs": "输入文本,然后单击“确定”以使用美式英语键盘远程输入文本。在继续操作之前,请确保将远程鼠标放置在正确的位置。",
15859 "zh-cht": "輸入文本,然後單擊“確定”以使用美式英語鍵盤遠程輸入文本。在繼續操作之前,請確保將遠程光標放置在正確的位置。",
15860 "xloc": [
15780 - "desktop.handlebars->3->21"
15861 + "desktop.handlebars->3->21",
15862 + "sharing.handlebars->11->21"
15863 ]
15864 },
15865 {
@@ -16155,6 +16237,7 @@
16237 "zh-cht": "於{0}到期",
16238 "xloc": [
16239 "desktop.handlebars->3->26",
16240 + "sharing.handlebars->11->94",
16241 "terminal.handlebars->3->24"
16242 ]
16243 },
@@ -16176,6 +16259,7 @@
16259 "zh-cht": "過期{0}",
16260 "xloc": [
16261 "desktop.handlebars->3->27",
16262 + "sharing.handlebars->11->95",
16263 "terminal.handlebars->3->25"
16264 ]
16265 },
@@ -16217,6 +16301,7 @@
16301 "zh-cht": "擴充式ASCII",
16302 "xloc": [
16303 "default.handlebars->31->1009",
16304 + "sharing.handlebars->11->34",
16305 "terminal.handlebars->3->16"
16306 ]
16307 },
@@ -16238,6 +16323,7 @@
16323 "zh-cht": "擴充式ASCII",
16324 "xloc": [
16325 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons",
16326 + "sharing.handlebars->p12->9->1->terminalSettingsButtons",
16327 "terminal.handlebars->p12->9->1->terminalSettingsButtons"
16328 ]
16329 },
@@ -16411,6 +16497,8 @@
16497 "default-mobile.handlebars->11->335",
16498 "default.handlebars->31->934",
16499 "desktop.handlebars->3->8",
16500 + "sharing.handlebars->11->30",
16501 + "sharing.handlebars->11->8",
16502 "terminal.handlebars->3->12"
16503 ]
16504 },
@@ -16453,7 +16541,8 @@
16541 "xloc": [
16542 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->4->3->d7framelimiter->1",
16543 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->1",
16456 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->1"
16544 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->1",
16545 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->1"
16546 ]
16547 },
16548 {
@@ -16535,7 +16624,8 @@
16624 "xloc": [
16625 "default-mobile.handlebars->11->387",
16626 "default.handlebars->31->1041",
16538 - "default.handlebars->31->571"
16627 + "default.handlebars->31->571",
16628 + "sharing.handlebars->11->66"
16629 ]
16630 },
16631 {
@@ -16572,7 +16662,9 @@
16662 "zh-cht": "檔案操作",
16663 "xloc": [
16664 "default.handlebars->31->1021",
16575 - "default.handlebars->31->1023"
16665 + "default.handlebars->31->1023",
16666 + "sharing.handlebars->11->46",
16667 + "sharing.handlebars->11->48"
16668 ]
16669 },
16670 {
@@ -16638,7 +16730,8 @@
16730 "default.handlebars->31->2211",
16731 "default.handlebars->31->295",
16732 "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevFiles",
16641 - "default.handlebars->contextMenu->cxfiles"
16733 + "default.handlebars->contextMenu->cxfiles",
16734 + "sharing.handlebars->LeftSideToolBar"
16735 ]
16736 },
16737 {
@@ -16728,7 +16821,8 @@
16821 "default.handlebars->31->1026",
16822 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devListToolbar",
16823 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->kvmListToolbar",
16731 - "default.handlebars->container->column_l->p4->3->1->0->3->3"
16824 + "default.handlebars->container->column_l->p4->3->1->0->3->3",
16825 + "sharing.handlebars->11->51"
16826 ]
16827 },
16828 {
@@ -16748,7 +16842,8 @@
16842 "zh-chs": "找",
16843 "zh-cht": "找",
16844 "xloc": [
16751 - "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3"
16845 + "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
16846 + "sharing.handlebars->p13->p13toolbar->fileArea2->3"
16847 ]
16848 },
16849 {
@@ -16768,7 +16863,8 @@
16863 "zh-chs": "查找文件",
16864 "zh-cht": "查找文件",
16865 "xloc": [
16771 - "default.handlebars->31->1029"
16866 + "default.handlebars->31->1029",
16867 + "sharing.handlebars->11->54"
16868 ]
16869 },
16870 {
@@ -17127,7 +17223,8 @@
17223 "zh-cht": "框速率",
17224 "xloc": [
17225 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->1",
17130 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->1"
17226 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->1",
17227 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->7->1"
17228 ]
17229 },
17230 {
@@ -18409,7 +18506,8 @@
18506 "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea1->1->3",
18507 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->3->connectbutton1hspan",
18508 "default.handlebars->container->column_l->p12->termTable->1->1->0->1->3->connectbutton2hspan",
18412 - "desktop.handlebars->p11->deskarea0->deskarea1->3->connectbutton1hspan"
18509 + "desktop.handlebars->p11->deskarea0->deskarea1->3->connectbutton1hspan",
18510 + "sharing.handlebars->p11->deskarea0->deskarea1->3->connectbutton1hspan"
18511 ]
18512 },
18513 {
@@ -18794,7 +18892,8 @@
18892 "zh-cht": "保存1個項目進行複製",
18893 "xloc": [
18894 "default-mobile.handlebars->11->396",
18797 - "default.handlebars->31->1051"
18895 + "default.handlebars->31->1051",
18896 + "sharing.handlebars->11->76"
18897 ]
18898 },
18899 {
@@ -18815,7 +18914,8 @@
18914 "zh-cht": "保存1個項目進行移動",
18915 "xloc": [
18916 "default-mobile.handlebars->11->400",
18818 - "default.handlebars->31->1055"
18917 + "default.handlebars->31->1055",
18918 + "sharing.handlebars->11->80"
18919 ]
18920 },
18921 {
@@ -18836,7 +18936,8 @@
18936 "zh-cht": "保留{0}個項目進行複製",
18937 "xloc": [
18938 "default-mobile.handlebars->11->394",
18839 - "default.handlebars->31->1049"
18939 + "default.handlebars->31->1049",
18940 + "sharing.handlebars->11->74"
18941 ]
18942 },
18943 {
@@ -18857,7 +18958,8 @@
18958 "zh-cht": "保存{0}個項目以進行移動",
18959 "xloc": [
18960 "default-mobile.handlebars->11->398",
18860 - "default.handlebars->31->1053"
18961 + "default.handlebars->31->1053",
18962 + "sharing.handlebars->11->78"
18963 ]
18964 },
18965 {
@@ -19403,7 +19505,8 @@
19505 "zh-cht": "影像編碼",
19506 "xloc": [
19507 "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->1",
19406 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->1"
19508 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->1",
19509 + "sharing.handlebars->dialog->dialogBody->dialog7->d7amtkvm->3->1"
19510 ]
19511 },
19512 {
@@ -19534,7 +19637,8 @@
19637 "xloc": [
19638 "default-mobile.handlebars->container->page_content->column_l->p10->p10desktop->deskarea4->1->3->11->DeskControlSpan",
19639 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->11->DeskControlSpan",
19537 - "desktop.handlebars->p11->deskarea0->deskarea4->3->9->DeskControlSpan"
19640 + "desktop.handlebars->p11->deskarea0->deskarea4->3->9->DeskControlSpan",
19641 + "sharing.handlebars->p11->deskarea0->deskarea4->3->9->DeskControlSpan"
19642 ]
19643 },
19644 {
@@ -19702,6 +19806,8 @@
19806 "xloc": [
19807 "default.handlebars->31->1011",
19808 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons",
19809 + "sharing.handlebars->11->36",
19810 + "sharing.handlebars->p12->9->1->terminalSettingsButtons",
19811 "terminal.handlebars->3->18",
19812 "terminal.handlebars->p12->9->1->terminalSettingsButtons"
19813 ]
@@ -19752,6 +19858,7 @@
19858 "zh-cht": "Intel ASCII",
19859 "xloc": [
19860 "default.handlebars->31->1010",
19861 + "sharing.handlebars->11->35",
19862 "terminal.handlebars->3->17"
19863 ]
19864 },
@@ -19908,6 +20015,7 @@
20015 "default-mobile.handlebars->11->5",
20016 "default.handlebars->31->12",
20017 "desktop.handlebars->3->5",
20018 + "sharing.handlebars->11->5",
20019 "terminal.handlebars->3->5",
20020 "xterm.handlebars->9->5"
20021 ]
@@ -20532,7 +20640,8 @@
20640 "xloc": [
20641 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->1",
20642 "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->1",
20535 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->1"
20643 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->1",
20644 + "sharing.handlebars->dialog->dialogBody->dialog7->d7amtkvm->1"
20645 ]
20646 },
20647 {
@@ -20554,6 +20663,7 @@
20663 "xloc": [
20664 "default.handlebars->container->column_l->p11->p11warning->3",
20665 "default.handlebars->container->column_l->p12->p12warning->3",
20666 + "sharing.handlebars->p12->p12warning->3",
20667 "terminal.handlebars->p12->p12warning->3"
20668 ]
20669 },
@@ -21704,6 +21814,8 @@
21814 "xloc": [
21815 "default.handlebars->31->1006",
21816 "default.handlebars->31->1015",
21817 + "sharing.handlebars->11->26",
21818 + "sharing.handlebars->11->40",
21819 "terminal.handlebars->3->22",
21820 "terminal.handlebars->3->8"
21821 ]
@@ -23109,7 +23221,8 @@
23221 "zh-cht": "本地鍵盤圖",
23222 "xloc": [
23223 "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->5",
23112 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->5"
23224 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->5",
23225 + "sharing.handlebars->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->5"
23226 ]
23227 },
23228 {
@@ -24568,7 +24681,8 @@
24681 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->4->3->d7framelimiter->3",
24682 "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->9->devListToolbarSize->sizeselect->3",
24683 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->3",
24571 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->3"
24684 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->3",
24685 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->3"
24686 ]
24687 },
24688 {
@@ -26416,7 +26530,9 @@
26530 "default.handlebars->31->1034",
26531 "default.handlebars->31->1732",
26532 "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
26419 - "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3"
26533 + "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3",
26534 + "sharing.handlebars->11->59",
26535 + "sharing.handlebars->p13->p13toolbar->fileArea2->3"
26536 ]
26537 },
26538 {
@@ -27274,7 +27390,8 @@
27390 "zh-chs": "找不到文件",
27391 "zh-cht": "找不到文件",
27392 "xloc": [
27277 - "default.handlebars->31->1020"
27393 + "default.handlebars->31->1020",
27394 + "sharing.handlebars->11->45"
27395 ]
27396 },
27397 {
@@ -28139,6 +28256,7 @@
28256 "login.handlebars->dialog->idx_dlgButtonBar",
28257 "login2.handlebars->dialog->idx_dlgButtonBar",
28258 "player.handlebars->p11->dialog->idx_dlgButtonBar",
28259 + "sharing.handlebars->dialog->idx_dlgButtonBar",
28260 "terminal.handlebars->p12->dialog->idx_dlgButtonBar",
28261 "xterm.handlebars->p11->dialog->idx_dlgButtonBar"
28262 ]
@@ -28389,7 +28507,8 @@
28507 "xloc": [
28508 "default-mobile.handlebars->11->388",
28509 "default.handlebars->31->1042",
28392 - "default.handlebars->31->572"
28510 + "default.handlebars->31->572",
28511 + "sharing.handlebars->11->67"
28512 ]
28513 },
28514 {
@@ -28698,7 +28817,8 @@
28817 "xloc": [
28818 "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->1",
28819 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->d7desktopOtherSettings->1",
28701 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->5->1"
28820 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->5->1",
28821 + "sharing.handlebars->dialog->dialogBody->dialog7->d7amtkvm->5->1"
28822 ]
28823 },
28824 {
@@ -29271,6 +29391,10 @@
29391 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3",
29392 "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
29393 "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3",
29394 + "sharing.handlebars->11->41",
29395 + "sharing.handlebars->11->73",
29396 + "sharing.handlebars->p12->9->3",
29397 + "sharing.handlebars->p13->p13toolbar->fileArea2->3",
29398 "terminal.handlebars->3->23",
29399 "terminal.handlebars->p12->9->3"
29400 ]
@@ -29293,6 +29417,7 @@
29417 "zh-cht": "將文本黏貼到終端中",
29418 "xloc": [
29419 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->3",
29420 + "sharing.handlebars->p12->9->3",
29421 "terminal.handlebars->p12->9->3"
29422 ]
29423 },
@@ -30768,7 +30893,8 @@
30893 "xloc": [
30894 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->0->1",
30895 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->3->1",
30771 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->3->1"
30896 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->3->1",
30897 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->3->1"
30898 ]
30899 },
30900 {
@@ -30810,7 +30936,8 @@
30936 "xloc": [
30937 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->1->0->3->d7desktopmode->7",
30938 "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->7",
30813 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->7"
30939 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->7",
30940 + "sharing.handlebars->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->7"
30941 ]
30942 },
30943 {
@@ -30832,7 +30959,8 @@
30959 "xloc": [
30960 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->1->0->3->d7desktopmode->5",
30961 "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->5",
30835 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->5"
30962 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->5",
30963 + "sharing.handlebars->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->5"
30964 ]
30965 },
30966 {
@@ -30932,7 +31060,8 @@
31060 "xloc": [
31061 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->1->0->3->d7desktopmode->3",
31062 "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->3",
30935 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->3"
31063 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->3",
31064 + "sharing.handlebars->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->3"
31065 ]
31066 },
31067 {
@@ -30954,7 +31083,8 @@
31083 "xloc": [
31084 "default-mobile.handlebars->dialog->3->dialog7->d7amtkvm->3->1->0->3->d7desktopmode->1",
31085 "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->1",
30957 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->1"
31086 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->1",
31087 + "sharing.handlebars->dialog->dialogBody->dialog7->d7amtkvm->3->d7desktopmode->1"
31088 ]
31089 },
31090 {
@@ -31136,6 +31266,8 @@
31266 "default-mobile.handlebars->11->337",
31267 "default.handlebars->31->936",
31268 "desktop.handlebars->3->10",
31269 + "sharing.handlebars->11->10",
31270 + "sharing.handlebars->11->32",
31271 "terminal.handlebars->3->14"
31272 ]
31273 },
@@ -31259,7 +31391,8 @@
31391 "default-mobile.handlebars->11->144",
31392 "default-mobile.handlebars->11->381",
31393 "default.handlebars->31->1035",
31262 - "default.handlebars->31->1733"
31394 + "default.handlebars->31->1733",
31395 + "sharing.handlebars->11->60"
31396 ]
31397 },
31398 {
@@ -31308,7 +31441,8 @@
31441 "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsAreaTop->DeskToolsRefreshButton",
31442 "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
31443 "default.handlebars->container->column_l->p40->3->3",
31311 - "default.handlebars->container->column_l->p52->3->1->0->3->3"
31444 + "default.handlebars->container->column_l->p52->3->1->0->3->3",
31445 + "sharing.handlebars->p13->p13toolbar->fileArea2->3"
31446 ]
31447 },
31448 {
@@ -31761,7 +31895,8 @@
31895 "default-mobile.handlebars->11->339",
31896 "default.handlebars->31->312",
31897 "default.handlebars->31->947",
31764 - "desktop.handlebars->3->20"
31898 + "desktop.handlebars->3->20",
31899 + "sharing.handlebars->11->20"
31900 ]
31901 },
31902 {
@@ -31782,7 +31917,8 @@
31917 "zh-cht": "遠程鍵盤輸入",
31918 "xloc": [
31919 "default.handlebars->31->980",
31785 - "desktop.handlebars->3->22"
31920 + "desktop.handlebars->3->22",
31921 + "sharing.handlebars->11->22"
31922 ]
31923 },
31924 {
@@ -31904,6 +32040,7 @@
32040 "xloc": [
32041 "default.handlebars->container->column_l->p11->p11warning2->3",
32042 "default.handlebars->container->column_l->p12->p12warning2->3",
32043 + "sharing.handlebars->p12->p12warning2->3",
32044 "terminal.handlebars->p12->p12warning2->3"
32045 ]
32046 },
@@ -32617,7 +32754,9 @@
32754 "default.handlebars->31->570",
32755 "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
32756 "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3",
32620 - "default.handlebars->filesContextMenu->1"
32757 + "default.handlebars->filesContextMenu->1",
32758 + "sharing.handlebars->11->64",
32759 + "sharing.handlebars->p13->p13toolbar->fileArea2->3"
32760 ]
32761 },
32762 {
@@ -33170,7 +33309,8 @@
33309 "default-mobile.handlebars->11->130",
33310 "default-mobile.handlebars->11->375",
33311 "default.handlebars->31->1024",
33173 - "default.handlebars->31->1705"
33312 + "default.handlebars->31->1705",
33313 + "sharing.handlebars->11->49"
33314 ]
33315 },
33316 {
@@ -33246,7 +33386,8 @@
33386 "zh-cht": "向左旋轉",
33387 "xloc": [
33388 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1",
33249 - "desktop.handlebars->p11->deskarea0->deskarea1->1"
33389 + "desktop.handlebars->p11->deskarea0->deskarea1->1",
33390 + "sharing.handlebars->p11->deskarea0->deskarea1->1"
33391 ]
33392 },
33393 {
@@ -33267,7 +33408,8 @@
33408 "zh-cht": "向右旋轉",
33409 "xloc": [
33410 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1",
33270 - "desktop.handlebars->p11->deskarea0->deskarea1->1"
33411 + "desktop.handlebars->p11->deskarea0->deskarea1->1",
33412 + "sharing.handlebars->p11->deskarea0->deskarea1->1"
33413 ]
33414 },
33415 {
@@ -33834,7 +33976,8 @@
33976 "zh-cht": "保存遠程桌面的屏幕截圖",
33977 "xloc": [
33978 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1",
33837 - "desktop.handlebars->p11->deskarea0->deskarea4->1"
33979 + "desktop.handlebars->p11->deskarea0->deskarea4->1",
33980 + "sharing.handlebars->p11->deskarea0->deskarea4->1"
33981 ]
33982 },
33983 {
@@ -33913,7 +34056,8 @@
34056 "xloc": [
34057 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->2->1",
34058 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->5->1",
33916 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->1"
34059 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->5->1",
34060 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->5->1"
34061 ]
34062 },
34063 {
@@ -34096,7 +34240,8 @@
34240 "xloc": [
34241 "default.handlebars->31->1028",
34242 "default.handlebars->31->590",
34099 - "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devMapToolbar"
34243 + "default.handlebars->container->column_l->p1->devListToolbarSpan->1->0->devMapToolbar",
34244 + "sharing.handlebars->11->53"
34245 ]
34246 },
34247 {
@@ -34290,7 +34435,10 @@
34435 "default.handlebars->container->column_l->p4->3->1->0->3->3",
34436 "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3",
34437 "default.handlebars->container->column_l->p50->3->1->0->3->3",
34293 - "default.handlebars->meshContextMenu->cxselectall"
34438 + "default.handlebars->meshContextMenu->cxselectall",
34439 + "sharing.handlebars->11->56",
34440 + "sharing.handlebars->11->58",
34441 + "sharing.handlebars->p13->p13toolbar->fileArea2->3"
34442 ]
34443 },
34444 {
@@ -34315,7 +34463,8 @@
34463 "default.handlebars->31->1910",
34464 "default.handlebars->31->1993",
34465 "default.handlebars->31->475",
34318 - "default.handlebars->meshContextMenu->cxselectnone"
34466 + "default.handlebars->meshContextMenu->cxselectnone",
34467 + "sharing.handlebars->11->57"
34468 ]
34469 },
34470 {
@@ -34523,6 +34672,8 @@
34672 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->specialKeyDropDown",
34673 "desktop.handlebars->p11->deskarea0->deskarea4->3",
34674 "messenger.handlebars->xbottom->1->1->0->3",
34675 + "sharing.handlebars->p11->deskarea0->deskarea4->3",
34676 + "sharing.handlebars->p12->9->1->specialKeyDropDown",
34677 "terminal.handlebars->p12->9->1->specialKeyDropDown"
34678 ]
34679 },
@@ -34765,6 +34916,7 @@
34916 "zh-cht": "發送選擇的特殊鍵",
34917 "xloc": [
34918 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->specialKeyDropDown",
34919 + "sharing.handlebars->p12->9->1->specialKeyDropDown",
34920 "terminal.handlebars->p12->9->1->specialKeyDropDown"
34921 ]
34922 },
@@ -35382,6 +35534,8 @@
35534 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1",
35535 "default.handlebars->container->column_l->p12->termTable->1->1->0->1->1",
35536 "default.handlebars->container->column_l->p13->p13toolbar->1->0->1->1",
35537 + "sharing.handlebars->p12->5->1",
35538 + "sharing.handlebars->p13->p13toolbar->1->1",
35539 "terminal.handlebars->p12->5->1"
35540 ]
35541 },
@@ -35504,7 +35658,8 @@
35658 "zh-cht": "會議訊息",
35659 "xloc": [
35660 "default.handlebars->31->944",
35507 - "desktop.handlebars->3->18"
35661 + "desktop.handlebars->3->18",
35662 + "sharing.handlebars->11->18"
35663 ]
35664 },
35665 {
@@ -35527,6 +35682,8 @@
35682 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->1",
35683 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1",
35684 "desktop.handlebars->p11->deskarea0->deskarea4->1",
35685 + "sharing.handlebars->p11->deskarea0->deskarea4->1",
35686 + "sharing.handlebars->p12->9->1",
35687 "terminal.handlebars->p12->9->1"
35688 ]
35689 },
@@ -35680,7 +35837,8 @@
35837 "zh-cht": "設定...",
35838 "xloc": [
35839 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1",
35683 - "desktop.handlebars->p11->deskarea0->deskarea1->1"
35840 + "desktop.handlebars->p11->deskarea0->deskarea1->1",
35841 + "sharing.handlebars->p11->deskarea0->deskarea1->1"
35842 ]
35843 },
35844 {
@@ -35782,6 +35940,7 @@
35940 "default.handlebars->31->264",
35941 "default.handlebars->31->311",
35942 "desktop.handlebars->3->3",
35943 + "sharing.handlebars->11->3",
35944 "terminal.handlebars->3->3",
35945 "xterm.handlebars->9->3"
35946 ]
@@ -35972,7 +36131,8 @@
36131 "zh-cht": "Shift + Win + M",
36132 "xloc": [
36133 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->15",
35975 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->13"
36134 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->13",
36135 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->13"
36136 ]
36137 },
36138 {
@@ -36036,7 +36196,8 @@
36196 "zh-cht": "顯示焦點工具",
36197 "xloc": [
36198 "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->1",
36039 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->1"
36199 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->1",
36200 + "sharing.handlebars->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->1"
36201 ]
36202 },
36203 {
@@ -36079,7 +36240,8 @@
36240 "zh-cht": "顯示本地鼠標光標",
36241 "xloc": [
36242 "default.handlebars->container->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->3",
36082 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->3"
36243 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->3",
36244 + "sharing.handlebars->dialog->dialogBody->dialog7->d7amtkvm->5->d7otherset->3"
36245 ]
36246 },
36247 {
@@ -36604,7 +36766,8 @@
36766 "zh-chs": "缩放:100%",
36767 "zh-cht": "縮放:100%",
36768 "xloc": [
36607 - "default.handlebars->31->1060"
36769 + "default.handlebars->31->1060",
36770 + "sharing.handlebars->11->85"
36771 ]
36772 },
36773 {
@@ -36624,7 +36787,8 @@
36787 "zh-chs": "缩放:125%",
36788 "zh-cht": "縮放:125%",
36789 "xloc": [
36627 - "default.handlebars->31->1061"
36790 + "default.handlebars->31->1061",
36791 + "sharing.handlebars->11->86"
36792 ]
36793 },
36794 {
@@ -36644,7 +36808,8 @@
36808 "zh-chs": "缩放:150%",
36809 "zh-cht": "縮放:150%",
36810 "xloc": [
36647 - "default.handlebars->31->1062"
36811 + "default.handlebars->31->1062",
36812 + "sharing.handlebars->11->87"
36813 ]
36814 },
36815 {
@@ -36664,7 +36829,8 @@
36829 "zh-chs": "缩放:200%",
36830 "zh-cht": "縮放:200%",
36831 "xloc": [
36667 - "default.handlebars->31->1063"
36832 + "default.handlebars->31->1063",
36833 + "sharing.handlebars->11->88"
36834 ]
36835 },
36836 {
@@ -36796,7 +36962,8 @@
36962 "xloc": [
36963 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->4->3->d7framelimiter->5",
36964 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->5",
36799 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->5"
36965 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->5",
36966 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->5"
36967 ]
36968 },
36969 {
@@ -36982,7 +37149,8 @@
37149 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->5",
37150 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->5",
37151 "default.handlebars->container->column_l->p13->p13toolbar->1->4->1->1->p13sortdropdown->5",
36985 - "default.handlebars->container->column_l->p5->p5toolbar->1->2->p5filesubhead->1->p5sortdropdown->5"
37152 + "default.handlebars->container->column_l->p5->p5toolbar->1->2->p5filesubhead->1->p5sortdropdown->5",
37153 + "sharing.handlebars->p13->p13toolbar->5->1->p13sortdropdown->5"
37154 ]
37155 },
37156 {
@@ -37007,7 +37175,8 @@
37175 "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsProcessTab->deskToolsHeader",
37176 "default.handlebars->container->column_l->p11->deskarea0->deskarea3x->DeskTools->deskToolsArea->DeskToolsServiceTab->deskToolsServiceHeader",
37177 "default.handlebars->container->column_l->p13->p13toolbar->1->4->1->1->p13sortdropdown->1",
37010 - "default.handlebars->container->column_l->p5->p5toolbar->1->2->p5filesubhead->1->p5sortdropdown->1"
37178 + "default.handlebars->container->column_l->p5->p5toolbar->1->2->p5filesubhead->1->p5sortdropdown->1",
37179 + "sharing.handlebars->p13->p13toolbar->5->1->p13sortdropdown->1"
37180 ]
37181 },
37182 {
@@ -37050,7 +37219,8 @@
37219 "default-mobile.handlebars->container->page_content->column_l->p10->p10files->p13toolbar->1->4->1->1->1->0->3->p13sortdropdown->3",
37220 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->2->1->1->1->0->3->p5sortdropdown->3",
37221 "default.handlebars->container->column_l->p13->p13toolbar->1->4->1->1->p13sortdropdown->3",
37053 - "default.handlebars->container->column_l->p5->p5toolbar->1->2->p5filesubhead->1->p5sortdropdown->3"
37222 + "default.handlebars->container->column_l->p5->p5toolbar->1->2->p5filesubhead->1->p5sortdropdown->3",
37223 + "sharing.handlebars->p13->p13toolbar->5->1->p13sortdropdown->3"
37224 ]
37225 },
37226 {
@@ -37591,7 +37761,8 @@
37761 "default.handlebars->31->2203",
37762 "default.handlebars->31->2222",
37763 "default.handlebars->31->940",
37594 - "desktop.handlebars->3->14"
37764 + "desktop.handlebars->3->14",
37765 + "sharing.handlebars->11->14"
37766 ]
37767 },
37768 {
@@ -38735,7 +38906,8 @@
38906 "default.handlebars->31->748",
38907 "default.handlebars->31->806",
38908 "default.handlebars->container->topbar->1->1->MainSubMenuSpan->MainSubMenu->1->0->MainDevTerminal",
38738 - "default.handlebars->contextMenu->cxterminal"
38909 + "default.handlebars->contextMenu->cxterminal",
38910 + "sharing.handlebars->LeftSideToolBar"
38911 ]
38912 },
38913 {
@@ -38821,6 +38993,7 @@
38993 "zh-chs": "终端会话延迟",
38994 "zh-cht": "終端會話延遲",
38995 "xloc": [
38996 + "sharing.handlebars->p12->9->1",
38997 "terminal.handlebars->p12->9->1"
38998 ]
38999 },
@@ -39519,6 +39692,8 @@
39692 "default-mobile.handlebars->11->336",
39693 "default.handlebars->31->935",
39694 "desktop.handlebars->3->9",
39695 + "sharing.handlebars->11->31",
39696 + "sharing.handlebars->11->9",
39697 "terminal.handlebars->3->13"
39698 ]
39699 },
@@ -39860,6 +40035,7 @@
40035 "zh-cht": "切換F1至F10鍵仿真類型",
40036 "xloc": [
40037 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons",
40038 + "sharing.handlebars->p12->9->1->terminalSettingsButtons",
40039 "terminal.handlebars->p12->9->1->terminalSettingsButtons"
40040 ]
40041 },
@@ -39902,7 +40078,8 @@
40078 "xloc": [
40079 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1",
40080 "desktop.handlebars->p11->deskarea0->deskarea1->1",
39905 - "player.handlebars->p11->deskarea0->deskarea1->1"
40081 + "player.handlebars->p11->deskarea0->deskarea1->1",
40082 + "sharing.handlebars->p11->deskarea0->deskarea1->1"
40083 ]
40084 },
40085 {
@@ -39963,7 +40140,8 @@
40140 "zh-cht": "切換鼠標和鍵盤輸入",
40141 "xloc": [
40142 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3->11",
39966 - "desktop.handlebars->p11->deskarea0->deskarea4->3->9"
40143 + "desktop.handlebars->p11->deskarea0->deskarea4->3->9",
40144 + "sharing.handlebars->p11->deskarea0->deskarea4->3->9"
40145 ]
40146 },
40147 {
@@ -40029,6 +40207,7 @@
40207 "zh-cht": "切換終端仿真類型",
40208 "xloc": [
40209 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons",
40210 + "sharing.handlebars->p12->9->1->terminalSettingsButtons",
40211 "terminal.handlebars->p12->9->1->terminalSettingsButtons"
40212 ]
40213 },
@@ -40070,6 +40249,7 @@
40249 "zh-cht": "切換返回鍵將發送的內容",
40250 "xloc": [
40251 "default.handlebars->container->column_l->p12->termTable->1->1->6->1->1->terminalSettingsButtons",
40252 + "sharing.handlebars->p12->9->1->terminalSettingsButtons",
40253 "terminal.handlebars->p12->9->1->terminalSettingsButtons"
40254 ]
40255 },
@@ -40396,7 +40576,8 @@
40576 "default.handlebars->31->807",
40577 "default.handlebars->31->993",
40578 "default.handlebars->container->column_l->p11->deskarea0->deskarea4->3",
40399 - "desktop.handlebars->p11->deskarea0->deskarea4->3"
40579 + "desktop.handlebars->p11->deskarea0->deskarea4->3",
40580 + "sharing.handlebars->p11->deskarea0->deskarea4->3"
40581 ]
40582 },
40583 {
@@ -40478,6 +40659,7 @@
40659 "zh-cht": "UTF8終端",
40660 "xloc": [
40661 "default.handlebars->31->1008",
40662 + "sharing.handlebars->11->33",
40663 "terminal.handlebars->3->15"
40664 ]
40665 },
@@ -41144,7 +41326,8 @@
41326 "default.handlebars->31->964",
41327 "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
41328 "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3",
41147 - "default.handlebars->container->dialog->dialogBody->dialog3->d3servermode->d3serveraction"
41329 + "default.handlebars->container->dialog->dialogBody->dialog3->d3servermode->d3serveraction",
41330 + "sharing.handlebars->p13->p13toolbar->fileArea2->3"
41331 ]
41332 },
41333 {
@@ -41212,7 +41395,8 @@
41395 "default-mobile.handlebars->container->page_content->column_l->p5->p5myfiles->p5toolbar->1->0->1->3",
41396 "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
41397 "default.handlebars->container->column_l->p5->p5toolbar->1->0->p5filehead->3",
41215 - "messenger.handlebars->remoteImage->3->10"
41398 + "messenger.handlebars->remoteImage->3->10",
41399 + "sharing.handlebars->p13->p13toolbar->fileArea2->3"
41400 ]
41401 },
41402 {
@@ -41241,7 +41425,10 @@
41425 "default.handlebars->31->1067",
41426 "default.handlebars->31->1738",
41427 "default.handlebars->31->1746",
41244 - "default.handlebars->container->dialog->dialogBody->dialog3->d3localmode->1"
41428 + "default.handlebars->container->dialog->dialogBody->dialog3->d3localmode->1",
41429 + "sharing.handlebars->11->65",
41430 + "sharing.handlebars->11->89",
41431 + "sharing.handlebars->11->92"
41432 ]
41433 },
41434 {
@@ -41428,7 +41615,8 @@
41615 "xloc": [
41616 "default-mobile.handlebars->11->405",
41617 "default.handlebars->31->1065",
41431 - "default.handlebars->31->1747"
41618 + "default.handlebars->31->1747",
41619 + "sharing.handlebars->11->90"
41620 ]
41621 },
41622 {
@@ -41450,7 +41638,8 @@
41638 "xloc": [
41639 "default-mobile.handlebars->11->406",
41640 "default.handlebars->31->1066",
41453 - "default.handlebars->31->1748"
41641 + "default.handlebars->31->1748",
41642 + "sharing.handlebars->11->91"
41643 ]
41644 },
41645 {
@@ -42103,7 +42292,8 @@
42292 "zh-cht": "用戶“{0}”",
42293 "xloc": [
42294 "default.handlebars->31->943",
42106 - "desktop.handlebars->3->17"
42295 + "desktop.handlebars->3->17",
42296 + "sharing.handlebars->11->17"
42297 ]
42298 },
42299 {
@@ -42416,6 +42606,7 @@
42606 "zh-cht": "VT100 +(F10 = ESC + [OY)",
42607 "xloc": [
42608 "default.handlebars->31->1013",
42609 + "sharing.handlebars->11->38",
42610 "terminal.handlebars->3->20"
42611 ]
42612 },
@@ -42734,7 +42925,8 @@
42925 "xloc": [
42926 "default-mobile.handlebars->dialog->3->dialog7->d7meshkvm->3->1->4->3->d7framelimiter->7",
42927 "default.handlebars->container->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->7",
42737 - "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->7"
42928 + "desktop.handlebars->p11->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->7",
42929 + "sharing.handlebars->dialog->dialogBody->dialog7->d7meshkvm->7->d7framelimiter->7"
42930 ]
42931 },
42932 {
@@ -43062,6 +43254,8 @@
43254 "default-mobile.handlebars->11->333",
43255 "default.handlebars->31->932",
43256 "desktop.handlebars->3->6",
43257 + "sharing.handlebars->11->28",
43258 + "sharing.handlebars->11->6",
43259 "terminal.handlebars->3->10"
43260 ]
43261 },
@@ -43506,7 +43700,8 @@
43700 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->5",
43701 "default.handlebars->31->971",
43702 "default.handlebars->31->975",
43509 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->3"
43703 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->3",
43704 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->3"
43705 ]
43706 },
43707 {
@@ -43527,7 +43722,8 @@
43722 "zh-cht": "Win+向下",
43723 "xloc": [
43724 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->7",
43530 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->5"
43725 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->5",
43726 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->5"
43727 ]
43728 },
43729 {
@@ -43548,7 +43744,8 @@
43744 "zh-cht": "Win+L",
43745 "xloc": [
43746 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->11",
43551 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->9"
43747 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->9",
43748 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->9"
43749 ]
43750 },
43751 {
@@ -43568,7 +43765,8 @@
43765 "zh-chs": "Win+向左",
43766 "zh-cht": "Win+向左",
43767 "xloc": [
43571 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->23"
43768 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->23",
43769 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->23"
43770 ]
43771 },
43772 {
@@ -43589,7 +43787,8 @@
43787 "zh-cht": "Win+M",
43788 "xloc": [
43789 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->13",
43592 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->11"
43790 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->11",
43791 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->11"
43792 ]
43793 },
43794 {
@@ -43610,7 +43809,8 @@
43809 "zh-cht": "Win+R",
43810 "xloc": [
43811 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->17",
43613 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->15"
43812 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->15",
43813 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->15"
43814 ]
43815 },
43816 {
@@ -43630,7 +43830,8 @@
43830 "zh-chs": "Win+向右",
43831 "zh-cht": "Win+向右",
43832 "xloc": [
43633 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->25"
43833 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->25",
43834 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->25"
43835 ]
43836 },
43837 {
@@ -43651,7 +43852,8 @@
43852 "zh-cht": "Win+向上",
43853 "xloc": [
43854 "default-mobile.handlebars->dialog->3->dialog3->deskkeys->9",
43654 - "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->7"
43855 + "desktop.handlebars->p11->deskarea0->deskarea4->3->deskkeys->7",
43856 + "sharing.handlebars->p11->deskarea0->deskarea4->3->deskkeys->7"
43857 ]
43858 },
43859 {
@@ -44108,7 +44310,8 @@
44310 "zh-chs": "换行:关",
44311 "zh-cht": "换行:關",
44312 "xloc": [
44111 - "default.handlebars->31->1059"
44313 + "default.handlebars->31->1059",
44314 + "sharing.handlebars->11->84"
44315 ]
44316 },
44317 {
@@ -44128,7 +44331,8 @@
44331 "zh-chs": "换行:开",
44332 "zh-cht": "换行:開",
44333 "xloc": [
44131 - "default.handlebars->31->1058"
44334 + "default.handlebars->31->1058",
44335 + "sharing.handlebars->11->83"
44336 ]
44337 },
44338 {
@@ -44407,7 +44611,8 @@
44611 "zh-chs": "Zip",
44612 "zh-cht": "Zip",
44613 "xloc": [
44410 - "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3"
44614 + "default.handlebars->container->column_l->p13->p13toolbar->1->2->1->3",
44615 + "sharing.handlebars->p13->p13toolbar->fileArea2->3"
44616 ]
44617 },
44618 {
@@ -44427,7 +44632,8 @@
44632 "zh-chs": "邮编档案名",
44633 "zh-cht": "郵編檔案名",
44634 "xloc": [
44430 - "default.handlebars->31->1043"
44635 + "default.handlebars->31->1043",
44636 + "sharing.handlebars->11->68"
44637 ]
44638 },
44639 {
@@ -46372,7 +46578,8 @@
46578 "default.handlebars->31->1731",
46579 "default.handlebars->31->2221",
46580 "download.handlebars->3->2",
46375 - "download2.handlebars->5->2"
46581 + "download2.handlebars->5->2",
46582 + "sharing.handlebars->11->97"
46583 ]
46584 },
46585 {
@@ -46413,7 +46620,8 @@
46620 "zh-cht": "{0}個連接",
46621 "xloc": [
46622 "default.handlebars->31->942",
46416 - "desktop.handlebars->3->16"
46623 + "desktop.handlebars->3->16",
46624 + "sharing.handlebars->11->16"
46625 ]
46626 },
46627 {
@@ -47019,7 +47227,8 @@
47227 "ru": "↺",
47228 "xloc": [
47229 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1->5",
47022 - "desktop.handlebars->p11->deskarea0->deskarea1->1->5"
47230 + "desktop.handlebars->p11->deskarea0->deskarea1->1->5",
47231 + "sharing.handlebars->p11->deskarea0->deskarea1->1->5"
47232 ]
47233 },
47234 {
@@ -47036,7 +47245,8 @@
47245 "ru": "↻",
47246 "xloc": [
47247 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1->7",
47039 - "desktop.handlebars->p11->deskarea0->deskarea1->1->7"
47248 + "desktop.handlebars->p11->deskarea0->deskarea1->1->7",
47249 + "sharing.handlebars->p11->deskarea0->deskarea1->1->7"
47250 ]
47251 },
47252 {
@@ -47054,7 +47264,8 @@
47264 "xloc": [
47265 "default.handlebars->container->column_l->p11->deskarea0->deskarea1->1->3",
47266 "desktop.handlebars->p11->deskarea0->deskarea1->1->3",
47057 - "player.handlebars->p11->deskarea0->deskarea1->1->1"
47267 + "player.handlebars->p11->deskarea0->deskarea1->1->1",
47268 + "sharing.handlebars->p11->deskarea0->deskarea1->1->3"
47269 ]
47270 },
47271 {
@@ -47127,6 +47338,7 @@
47338 "default.handlebars->container->column_l->p6->p6info->p2ServerActions->3->p2ServerActionsRestore->0->0->0",
47339 "default.handlebars->container->column_l->p6->p6info->p2ServerActions->3->p2ServerActionsVersion->0->0->0",
47340 "player.handlebars->p11->deskarea0->deskarea3x->bigok->0",
47341 + "sharing.handlebars->p13->p13toolbar->fileArea4->p13filetable->p13bigok->0",
47342 "xterm.handlebars->p11->deskarea0->deskarea3x->bigok->0"
47343 ]
47344 },
@@ -47149,6 +47361,8 @@
47361 "desktop.handlebars->p11->deskarea0->deskarea1->3->idx_deskFullBtn2",
47362 "desktop.handlebars->p11->dialog->dialogHeader->id_dialogclose",
47363 "player.handlebars->p11->dialog->dialogHeader->id_dialogclose",
47364 + "sharing.handlebars->dialog->dialogHeader->id_dialogclose",
47365 + "sharing.handlebars->p11->deskarea0->deskarea1->3->idx_deskFullBtn2",
47366 "terminal.handlebars->p12->5->3->idx_termFullBtn2",
47367 "terminal.handlebars->p12->dialog->dialogHeader->id_dialogclose",
47368 "xterm.handlebars->p11->dialog->dialogHeader->id_dialogclose"
@@ -47170,6 +47384,7 @@
47384 "default.handlebars->container->column_l->p13->p13filetable->p13bigfail->0",
47385 "default.handlebars->container->column_l->p5->p5filetable->bigfail->0",
47386 "player.handlebars->p11->deskarea0->deskarea3x->bigfail->0",
47387 + "sharing.handlebars->p13->p13toolbar->fileArea4->p13filetable->p13bigfail->0",
47388 "xterm.handlebars->p11->deskarea0->deskarea3x->bigfail->0"
47389 ]
47390 }
views/sharing.handlebars new
+2209
@@ -0,0 +1,2209 @@
1 +<!DOCTYPE html>
2 +<html lang="en" dir="ltr" xmlns="http://www.w3.org/1999/xhtml">
3 +<head>
4 + <meta http-equiv="X-UA-Compatible" content="IE=edge" />
5 + <meta content="text/html;charset=utf-8" http-equiv="Content-Type" />
6 + <meta name="viewport" content="user-scalable=1.0,initial-scale=1.0,minimum-scale=1.0,maximum-scale=1.0" />
7 + <meta name="apple-mobile-web-app-capable" content="yes" />
8 + <meta name="format-detection" content="telephone=no" />
9 + <meta name="robots" content="noindex,nofollow">
10 + <link type="text/css" href="styles/style.css" media="screen" rel="stylesheet" title="CSS" />
11 + <link type="text/css" href="styles/style-sharing.css" media="screen" rel="stylesheet" title="CSS" />
12 + <link type="text/css" href="styles/xterm.css" media="screen" rel="stylesheet" title="CSS" />
13 + <link rel="apple-touch-icon" href="/favicon-303x303.png" />
14 + <script type="text/javascript" src="scripts/common-0.0.1{{min}}.js"></script>
15 + <script type="text/javascript" src="scripts/amt-redir-ws-0.1.0{{{min}}}.js"></script>
16 + <script type="text/javascript" src="scripts/amt-wsman-ws-0.2.0{{{min}}}.js"></script>
17 + <script type="text/javascript" src="scripts/agent-redir-ws-0.1.1{{{min}}}.js"></script>
18 + <script type="text/javascript" src="scripts/agent-redir-rtc-0.1.0{{{min}}}.js"></script>
19 + <script type="text/javascript" src="scripts/agent-desktop-0.0.2{{min}}.js"></script>
20 + <script type="text/javascript" src="scripts/amt-desktop-0.0.2{{min}}.js"></script>
21 + <script type="text/javascript" src="scripts/amt-terminal-0.0.2{{min}}.js"></script>
22 + <script type="text/javascript" src="scripts/zlib{{min}}.js"></script>
23 + <script type="text/javascript" src="scripts/zlib-inflate{{min}}.js"></script>
24 + <script type="text/javascript" src="scripts/zlib-adler32{{min}}.js"></script>
25 + <script type="text/javascript" src="scripts/zlib-crc32{{min}}.js"></script>
26 + <script type="text/javascript" src="scripts/amt-terminal-0.0.2{{min}}.js"></script>
27 + <script type="text/javascript" src="scripts/xterm{{{min}}}.js"></script>
28 + <script type="text/javascript" src="scripts/xterm-addon-fit{{{min}}}.js"></script>
29 + <script keeplink=1 type="text/javascript" src="scripts/filesaver.min.js"></script>
30 + <title>{{{title}}}</title>
31 +</head>
32 +<body style="overflow:hidden;background-color:black">
33 + <div id=LeftSideToolBar style="position:absolute;left:0;bottom:0;width:52px;top:0;background:#113962;background:linear-gradient(to bottom, #104893 0%,#113962 100%);color:white;border-right: 5px solid #BBB;">
34 + <div id=LeftMenuDesktop class="slbbutton slbbuttonsel2" title="Desktop" onclick=go(11)>
35 + <div class="slb1" style="position:absolute;top:6px;left:6px"></div>
36 + </div>
37 + <div id=LeftMenuTerminal class="slbbutton" title="Terminal" onclick=go(12)>
38 + <div class="slb2" style="position:absolute;top:6px;left:6px"></div>
39 + </div>
40 + <div id=LeftMenuFiles class="slbbutton" title="Files" onclick=go(13)>
41 + <div class="slb3" style="position:absolute;top:6px;left:6px"></div>
42 + </div>
43 + </div>
44 + <div id=p11 class="noselect" style="overflow:hidden;position:absolute;left:54px;top:0;right:0;bottom:0;display:none">
45 + <div id=deskarea0>
46 + <div id=deskarea1 class="areaHead">
47 + <div class="toright2">
48 + <span id="p11power"></span>&nbsp;
49 + <div class='deskareaicon' title="Toggle View Mode" onclick="toggleAspectRatio(1)">&#8690;</div>
50 + <div class='deskareaicon' title="Rotate Left" onclick="drotate(-1)">&olarr;</div>
51 + <div class='deskareaicon' title="Rotate Right" onclick="drotate(1)">&orarr;</div>
52 + <input id="deskActionsSettings" type="button" value="Settings..." title="Edit remote desktop settings" onkeypress="return false" onkeydown="return false" onclick="showDesktopSettings()" class="mR" />
53 + <div id="desktopCustomUiButtons" style="float:left"></div>
54 + </div>
55 + <div>
56 + <div id="idx_deskFullBtn2" onclick=deskToggleFull(event)>&nbsp;&#x2716;</div>
57 + <input type="button" id="autoconnectbutton1" value="AutoConnect" onclick=autoConnectDesktop(event) onkeypress="return false" onkeydown="return false" style="display:none" />
58 + <span id=connectbutton1span><input type=button id=connectbutton1 cmenu="deskConnectButton" value="Connect" onclick=connectDesktop(event,3) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span>
59 + <span id=connectbutton1hspan>&nbsp;<input type=button id=connectbutton1h value="HW Connect" title="Connect using Intel AMT hardware KVM" onclick=connectDesktop(event,2) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span>
60 + <span id=disconnectbutton1span>&nbsp;<input type=button id=disconnectbutton1 value="Disconnect" onclick=connectDesktop(event,0) onkeypress="return false" onkeydown="return false" /></span>
61 + &nbsp;<span id="deskstatus">Disconnected</span><span id="deskmetadata"></span>
62 + </div>
63 + </div>
64 + <div id=deskarea3x style="max-height:calc(100vh - 52px);height:calc(100vh - 56px);">
65 + <div id=DeskFocus oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></div>
66 + <div id=DeskParent>
67 + <canvas id=Desk width=640 height=480 oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event) onmousewheel=dmousewheel(event)></canvas>
68 + </div>
69 + <div id=p11DeskConsoleMsg style="display:none;cursor:pointer;position:absolute;left:30px;top:17px;color:yellow;background-color:rgba(0,0,0,0.6);padding:10px;border-radius:5px" onclick=clearConsoleMsg()></div>
70 + </div>
71 + <div id=deskarea4 class="areaFoot" style="min-height:24px">
72 + <div class="toright2">
73 + <span id="DeskLatency" title="Desktop Session Latency"></span>
74 + <span id="DeskTimer" style="display:none" title="Session time"></span>&nbsp;
75 + <select id=termdisplays style="display:none" onchange=deskSetDisplay(event) onkeypress="return false" onkeydown="return false"></select>&nbsp;
76 + <span id=DeskSaveImageButton title="Save a screenshot of the remote desktop"><img src='images/icon-camera.png' onclick=deskSaveImage() height=16 width=16 style=padding-top:2px /></span>
77 + </div>
78 + <div style="height:22px">
79 + <select id="deskkeys">
80 + <option value=10>Ctrl+Alt+Del</option>
81 + <option value=5>Win</option>
82 + <option value=0>Win+Down</option>
83 + <option value=1>Win+Up</option>
84 + <option value=2>Win+L</option>
85 + <option value=3>Win+M</option>
86 + <option value=4>Shift+Win+M</option>
87 + <option value=6>Win+R</option>
88 + <option value=7>Alt-F4</option>
89 + <option value=8>Ctrl-W</option>
90 + <option value=9>Alt-Tab</option>
91 + <option value=11>Win+Left</option>
92 + <option value=12>Win+Right</option>
93 + </select>
94 + <input id="DeskWD" type=button value="Send" onkeypress="return false" onkeydown="return false" onclick="deskSendKeys()" />
95 + <input id="DeskClip" style="" type="button" value="Clipboard" onkeypress="return false" onkeydown="return false" onclick="showDeskClip()" />
96 + <input id="DeskType" style="" type="button" value="Type" onkeypress="return false" onkeydown="return false" onclick="showDeskType()" />
97 + <label><span id="DeskControlSpan" title="Toggle mouse and keyboard input"><input id="DeskControl" type="checkbox" onkeypress="return false" onkeydown="return false" onclick="toggleKvmControl()" />Input</span></label>&nbsp;
98 + </div>
99 + </div>
100 + </div>
101 + </div>
102 + <div id=p12 class="noselect" style="overflow:hidden;position:absolute;left:54px;top:0;right:0;bottom:0;display:none;background-color:black">
103 + <div id="p12warning" onclick=showFeaturesDlg()>
104 + <div class="icon2"></div>
105 + <div class="warningbox">Intel&reg; AMT Redirection port or KVM feature is disabled<span id="p12warninga">, click here to enable it.</span></div>
106 + </div>
107 + <div id="p12warning2" onclick=showPowerActionDlg()>
108 + <div class="icon2"></div>
109 + <div class="warningbox">Remote computer is not powered on, click here to issue a power command.</div>
110 + </div>
111 + <div class="areaHead" style="position:absolute;top:0;left:0;right:0;height:24px">
112 + <div class="toright2">
113 + <div id="p12power" style="margin-top:3px;margin-right:4px"></div>
114 + <div id="termRecordIcon" class='deskareaicon' title="Server is recording this session" style="display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-left:5px"></div>
115 + </div>
116 + <div>
117 + <span id="connectbutton2span"><input type="button" id="connectbutton2" cmenu="termConnectButton" value="Connect" onclick=connectTerminal(event,1) onkeypress="return false" onkeydown="return false" disabled="disabled" /></span>
118 + <span id="disconnectbutton2span">&nbsp;<input type="button" id="disconnectbutton2" value="Disconnect" onclick=connectTerminal(event,0) onkeypress="return false" onkeydown="return false" /></span>
119 + &nbsp;<span id="termstatus">Disconnected</span><span id="termtitle"></span>
120 + </div>
121 + </div>
122 + <div id="termarea3xdiv" style="position:absolute;top:28px;bottom:28px;left:0;right:0"></div>
123 + <div class="areaFoot" style="position:absolute;bottom:0;left:0;right:0;height:24px">
124 + <div class="toright2">
125 + <span id="TermLatency" title="Terminal Session Latency"></span>
126 + <span id="TermTimer" title="Session time"></span>&nbsp;
127 + <span id="terminalSettingsButtons" style="display:none">
128 + <input id="id_tcrbutton" type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" value="CR+LF" title="Toggle what the return key will send" onclick="termToggleCr()" />
129 + <input id="id_tfxkeysbutton" type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" value="Intel (F10 = ESC+[OM)" title="Toggle F1 to F10 keys emulation type" onclick="termToggleFx()" />
130 + <input id="id_ttypebutton" type="button" onkeypress="return false" onkeydown="return false" class="bottombutton" value="Extended Ascii" title="Toggle terminal emulation type" onclick="termToggleType()" />
131 + </span>
132 + <span id="terminalSizeDropDown" style="display:none">
133 + <select id="termSizeList" onkeypress="return false"><option value="1">80x25</option><option value="2">100x30</option></select>
134 + </span>
135 + <span id="specialKeyDropDown">
136 + <select id="specialkeylist" onkeypress="return false"></select>
137 + <input id="specialkeylistinput" type="button" onkeypress="return false" class="bottombutton" value="Send" title="Send the selected special key" onclick="sendSpecialKey()" />
138 + </span>
139 + </div>
140 + <div>
141 + &nbsp;
142 + <input type=button onkeypress="return false" onkeydown="return false" class="bottombutton" id="ctrlcbutton" value="Ctl-C" onclick="termSendKey(3,'ctrlcbutton')" />
143 + <input type=button onkeypress="return false" onkeydown="return false" class="bottombutton" id="ctrlxbutton" value="Ctl-X" onclick="termSendKey(24,'ctrlxbutton')" />
144 + <input type=button onkeypress="return false" onkeydown="return false" class="bottombutton" id="escbutton" value="ESC" onclick="termSendKey(27,'escbutton')" />
145 + <input type=button onkeypress="return false" onkeydown="return false" class="bottombutton" id="bsbutton" value="Backspace" onclick="termSendKey(8,'bsbutton')" style="display:none" />
146 + <input type=button onkeypress="return false" onkeydown="return false" class="bottombutton" id="pastebutton" value="Paste" title="Paste text into the terminal" onclick="showTermPasteDialog()" style="display:none" />
147 + </div>
148 + </div>
149 + <div id=p12TermConsoleMsg style="display:none;cursor:pointer;position:absolute;left:30px;top:45px;color:yellow;background-color:rgba(0,0,0,0.6);padding:10px;border-radius:5px" onclick=p12clearConsoleMsg()></div>
150 + </div>
151 + <div id=p13 class="noselect" style="overflow:hidden;position:absolute;left:54px;top:0;right:0;bottom:0;display:none;background-color:white">
152 + <div id="p13toolbar" style="position:absolute;left:0;top:0;right:0;bottom:28px">
153 + <div class="areaHead">
154 + <div class="toright2">
155 + <div id="p13power" style="margin-top:3px;margin-right:4px"></div>
156 + <div id="filesRecordIcon" class='deskareaicon' title="Server is recording this session" style="display:none;background-color:red;width:12px;height:12px;border-radius:6px;margin-top:5px;margin-left:5px"></div>
157 + </div>
158 + <div>
159 + <input id=p13Connect value="Connect" onclick=connectFiles(event) type="button" />
160 + &nbsp;<span id=p13Status>Disconnected</span>
161 + </div>
162 + </div>
163 + <div id="fileArea2" class="areaHead2" valign=bottom>
164 + <div id="p13rightOfButtons" class="toright2"></div>
165 + <div>
166 + <input type=button id=p13FolderUp disabled="disabled" onclick="p13folderup()" value="Up" />&nbsp;
167 + <input type=button id=p13SelectAllButton disabled="disabled" onclick="p13selectallfile()" value="Select All" />&nbsp;
168 + <input type=button id=p13RenameFileButton disabled="disabled" value="Rename" onclick="p13renamefile()" />&nbsp;
169 + <input type=button id=p13DeleteFileButton disabled="disabled" value="Delete" onclick="p13deletefile()" />&nbsp;
170 + <input type=button id=p13ViewFileButton disabled="disabled" value="Edit" onclick="p13viewfile()" />&nbsp;
171 + <input type=button id=p13NewFolderButton disabled="disabled" value="New Folder" onclick="p13createfolder()" />&nbsp;
172 + <input type=button id=p13UploadButton disabled="disabled" value="Upload" onclick="p13uploadFile()" />&nbsp;
173 + <input type=button id=p13CutButton disabled="disabled" value="Cut" onclick="p13copyFile(1)" />&nbsp;
174 + <input type=button id=p13CopyButton disabled="disabled" value="Copy" onclick="p13copyFile(0)" />&nbsp;
175 + <input type=button id=p13PasteButton disabled="disabled" value="Paste" onclick="p13pasteFile()" />&nbsp;
176 + <input type=button id=p13ZipButton disabled="disabled" value="Zip" onclick="p13zipFiles()" />&nbsp;
177 + <input type=button id=p13RefreshButton disabled="disabled" value="Refresh" onclick="p13folderup(9999)" />&nbsp;
178 + <input type=button id=p13FindButton disabled="disabled" value="Find" onclick="p13findfile()" />&nbsp;
179 + </div>
180 + </div>
181 + <div class="areaHead3" style="line-height:28px">
182 + <div class="toright2">
183 + <select id=p13sortdropdown onchange=p13updateFiles()>
184 + <option value=1 selected="selected">Sort by name</option>
185 + <option value=2>Sort by size</option>
186 + <option value=3>Sort by date</option>
187 + <option value=4>Descend by name</option>
188 + <option value=5>Descend by size</option>
189 + <option value=6>Descend by date</option>
190 + </select>
191 + </div>
192 + <div>&nbsp;&nbsp;<span id="p13currentpath"></span></div>
193 + </div>
194 + <div id="fileArea4" style="height:calc(100vh - 146px)">
195 + <div id=p13FilesConsoleMsg style="display:none;cursor:pointer;position:absolute;left:30px;top:165px;color:yellow;background-color:rgba(0,0,0,0.6);padding:10px;border-radius:5px" onclick=p13clearConsoleMsg()></div>
196 + <div id="p13filetable" style="width:100%;height:100%">
197 + <div id="p13bigok" style="display:none"><b>&checkmark;</b></div>
198 + <div id="p13bigfail" style="display:none"><b>&#10007;</b></div>
199 + <span id="p13files"></span>
200 + </div>
201 + </div>
202 + </div>
203 + <div class="areaFoot" style="position:absolute;left:0;right:0;bottom:0;height:28px">
204 + &nbsp;<span id="p13bottomstatus"></span>
205 + </div>
206 + </div>
207 + <div id=dialog class="noselect" style="display:none">
208 + <div id=dialogHeader>
209 + <div tabindex=0 id=id_dialogclose onclick=setDialogMode() onkeypress="if (event.key == 'Enter') setDialogMode()">&#x2716;</div>
210 + <div id=id_dialogtitle></div>
211 + </div>
212 + <div id=dialogBody>
213 + <div id=dialog1>
214 + <div id=id_dialogMessage style=""></div>
215 + </div>
216 + <div id=dialog2 style="">
217 + <div id=id_dialogOptions></div>
218 + </div>
219 + <div id=dialog7 style="">
220 + <div id="d7meshkvm">
221 + <h4>Agent Remote Desktop</h4>
222 + <div>
223 + <div>Quality</div>
224 + <select id="d7bitmapquality" dir="rtl"></select>
225 + </div>
226 + <div>
227 + <div>Scaling</div>
228 + <select id="d7bitmapscaling" style="" dir="rtl">
229 + <option selected=selected value=1024>100%</option>
230 + <option value=896>87.5%</option>
231 + <option value=768>75%</option>
232 + <option value=640>62.5%</option>
233 + <option value=512>50%</option>
234 + <option value=384>37.5%</option>
235 + <option value=256>25%</option>
236 + <option value=128>12.5%</option>
237 + </select>
238 + </div>
239 + <div>
240 + <div>Frame rate</div>
241 + <select id="d7framelimiter" dir="rtl">
242 + <option selected=selected value=50>Fast</option>
243 + <option value=100>Medium</option>
244 + <option value=400>Slow</option>
245 + <option value=1000>Very slow</option>
246 + </select>
247 + </div>
248 + </div>
249 + <div id="d7amtkvm">
250 + <h4>Intel&reg; AMT Hardware KVM</h4>
251 + <div>
252 + <div>Image Encoding</div>
253 + <select id="d7desktopmode">
254 + <option value="1">RLE8, Fastest</option>
255 + <option value="2">RLE16, Recommended</option>
256 + <option value="3">RAW8, Slow</option>
257 + <option value="4">RAW16, Very Slow</option>
258 + </select>
259 + </div>
260 + <div>
261 + <div>Other Settings</div>
262 + <div id="d7otherset" style="display:block">
263 + <label style="display:block"><input type="checkbox" id="d7showfocus" />Show Focus Tool</label>
264 + <label style="display:block"><input type="checkbox" id="d7showcursor" />Show Local Mouse Cursor</label>
265 + <label style="display:block"><input type="checkbox" id="d7localKeyMap" />Local Keyboard Map</label>
266 + </div>
267 + </div>
268 + </div>
269 + </div>
270 + </div>
271 + <div id="idx_dlgButtonBar">
272 + <input id="idx_dlgCancelButton" type="button" value="Cancel" style="" onclick="dialogclose(0)">
273 + <input id="idx_dlgOkButton" type="button" value="OK" style="" onclick="dialogclose(1)">
274 + <div><input id="idx_dlgDeleteButton" type="button" value="Delete" style="display:none" onclick="dialogclose(2)"></div>
275 + </div>
276 + </div>
277 + <script>
278 + var sessionActivity = null;
279 + var desktop = null;
280 + var agentPresent = true;
281 + var intelAmtPresent = false;
282 + var deskAspectRatio = 0;
283 + var desktopsettings = { encoding: 2, showfocus: false, showmouse: true, showcad: true, quality: 40, scaling: 1024, framerate: 100, localkeymap: false };
284 + var serverPublicNamePort = '{{{serverDnsName}}}:{{{serverPublicPort}}}';
285 + var domain = '{{{domain}}}';
286 + var domainUrl = '{{{domainurl}}}';
287 + var authCookie = '{{{authCookie}}}';
288 + var nodeid = '{{{nodeid}}}';
289 + var viewOnly = parseInt('{{{viewOnly}}}');
290 + var urlargs = parseUriArgs();
291 + var debugmode = urlargs.debug;
292 + var attemptWebRTC = false;
293 + var updateSessionTimer = null;
294 + var StatusStrs = ["Disconnected", "Connecting...", "Setup...", "Connected", "Intel&reg; AMT Connected"];
295 + var nodeName = decodeURIComponent('{{{nodeName}}}');
296 + var webPageFullScreen = false;
297 + var expire = '{{{expire}}}';
298 + if (expire != '') {
299 + QH('p11power', printFlexDateTime(new Date(parseInt(expire))));
300 + QH('p12power', printFlexDateTime(new Date(parseInt(expire))));
301 + QH('p13power', printFlexDateTime(new Date(parseInt(expire))));
302 + }
303 +
304 + // Terminal
305 + var terminal = null;
306 + var xterm = null;
307 + var xtermfit = null;
308 + var xtermResizeTimer = null;
309 +
310 + // Files
311 + var files = null
312 +
313 + // Console messages timers
314 + var p11DeskConsoleMsgTimer = null;
315 + var p12TermConsoleMsgTimer = null;
316 + var p13FilesConsoleMsgTimer = null;
317 +
318 + function start() {
319 + window.onresize = deskAdjust;
320 + document.onkeypress = ondockeypress;
321 + document.onkeydown = ondockeydown;
322 + document.onkeyup = ondockeyup;
323 + setupDesktop();
324 + setupTerminal();
325 + setupFiles();
326 +
327 + // Set the document title
328 + if (nodeName.length > 0) { document.title += ' - ' + nodeName; }
329 +
330 + // View only mode
331 + if (viewOnly == 1) {
332 + QV('deskkeys', false);
333 + QV('DeskWD', false);
334 + QV('DeskClip', false);
335 + QV('DeskType', false);
336 + QV('DeskControlSpan', false);
337 + }
338 +
339 + // Setup upload drag & drop
340 + Q('p13filetable').addEventListener('drop', p13fileDragDrop, false);
341 + Q('p13filetable').addEventListener('dragover', p13fileDragOver, false);
342 + Q('p13filetable').addEventListener('dragleave', p13fileDragLeave, false);
343 +
344 + go(11); // Go to desktop
345 + deskAdjust();
346 + }
347 +
348 +
349 + //
350 + // Desktop
351 + //
352 +
353 + function isInputAllowed() { return (viewOnly != 1) && (Q('DeskControl').checked == true); }
354 + function clearConsoleMsg() { QH('p11DeskConsoleMsg', ''); }
355 +
356 + // Toggle the web page to full screen
357 + function toggleAspectRatio(toggle) {
358 + if (toggle === 1) { deskAspectRatio = ((deskAspectRatio + 1) % 3); }
359 + deskAdjust();
360 + }
361 +
362 + function deskAdjust() {
363 + if ((xxcurrentView == 12) && (terminal != null) && (xtermfit != null)) { xtermfit.fit(); } // Terminal
364 + QS('fileArea4')['height'] = 'calc(100vh - ' + (90 + Q('fileArea2').clientHeight) + 'px)'; // Files
365 + var parentH = Q('DeskParent').clientHeight, parentW = Q('DeskParent').clientWidth;
366 + var deskH = Q('Desk').height, deskW = Q('Desk').width;
367 +
368 + if (deskAspectRatio == 2) {
369 + // Scale mode
370 + QS('Desk')['margin-top'] = null;
371 + QS('Desk').height = '100%';
372 + QS('Desk').width = '100%';
373 + QS('DeskParent').overflow = 'hidden';
374 + } else if (deskAspectRatio == 1) {
375 + // Zoomed mode
376 + QS('Desk')['margin-top'] = '0px';
377 + //QS('Desk')['margin-left'] = '0px';
378 + QS('Desk').height = deskH + 'px';
379 + QS('Desk').width = deskW + 'px';
380 + QS('DeskParent').overflow = 'scroll';
381 + } else {
382 + // Fixed aspect ratio
383 + if ((parentH / parentW) > (deskH / deskW)) {
384 + var hNew = ((deskH * parentW) / deskW) + 'px';
385 + //if (webPageFullScreen || fullscreen) {
386 + //QS('deskarea3x').height = null;
387 + //} else {
388 + // QS('deskarea3x').height = hNew;
389 + //QS('deskarea3x').height = null;
390 + //}
391 + QS('Desk').height = hNew;
392 + QS('Desk').width = '100%';
393 + } else {
394 + var wNew = ((deskW * parentH) / deskH) + 'px';
395 + //if (webPageFullScreen || fullscreen) {
396 + //QS('Desk').height = null;
397 + //} else {
398 + QS('Desk').height = '100%';
399 + //}
400 + QS('Desk').width = wNew;
401 + }
402 + QS('Desk')['margin-top'] = null;
403 + QS('DeskParent').overflow = 'hidden';
404 + }
405 + }
406 +
407 + function setupDesktop() {
408 + // Setup the remote desktop
409 + if (desktop != null) { desktop.Stop(); desktop = null; }
410 +
411 + // If the device desktop is already connected in multi-desktop, use that.
412 + if (desktop == null) {
413 + // Device is not already connected, just setup a blank canvas
414 + QH('DeskParent', '<canvas id=Desk oncontextmenu="return false" onmousedown=dmousedown(event) onmouseup=dmouseup(event) onmousemove=dmousemove(event)></canvas>');
415 +
416 + // Setup the mouse wheel
417 + Q('Desk').addEventListener('DOMMouseScroll', function (e) { return dmousewheel(e); });
418 + Q('Desk').addEventListener('mousewheel', function (e) { return dmousewheel(e); });
419 + }
420 + updateDesktopButtons();
421 + deskAdjust();
422 + updateMetadata(desktop, 'deskmetadata');
423 + }
424 +
425 + // Show and enable the right buttons
426 + function updateDesktopButtons() {
427 + var deskState = 0;
428 + if (desktop != null) { deskState = desktop.State; }
429 +
430 + // Show the right buttons
431 + QV('disconnectbutton1span', (deskState != 0));
432 + QV('connectbutton1span', (deskState == 0) && (agentPresent));
433 + QV('connectbutton1hspan', (deskState == 0) && (intelAmtPresent));
434 +
435 + // Show the right settings
436 + QV('d7meshkvm', agentPresent && ((deskState == 0) || (desktop.contype == 1)));
437 + QV('d7amtkvm', intelAmtPresent && ((deskState == 0) || (desktop.contype == 2)));
438 +
439 + // Enable buttons
440 + QE('connectbutton1', agentPresent);
441 + QE('connectbutton1h', intelAmtPresent);
442 + //QV('DeskClip', agentPresent && ((desktop == null) || (desktop.contype != 2))); // Clipboard not supported on macOS
443 + QV('DeskClip', false); // Clipboard not supported on this page
444 + QE('DeskClip', deskState == 3);
445 + QE('DeskType', deskState == 3);
446 + QV('DeskWD', viewOnly != 1);
447 + QE('DeskWD', deskState == 3);
448 + QV('deskkeys', viewOnly != 1);
449 + QE('deskkeys', deskState == 3);
450 +
451 + // Display this only if we have Chat & Notify permissions
452 + QV('DeskSaveImageButton', (deskState == 3) && (Q('Desk')['toBlob'] != null));
453 + QV('DeskControlSpan', viewOnly != 1);
454 + QV('deskActionsBtn', (browserfullscreen == false));
455 + QV('deskActionsSettings', (browserfullscreen == false));
456 + Q('DeskControl').checked = true;
457 + QS('DeskControlSpan').color = Q('DeskControl').checked ? null : 'red';
458 + }
459 +
460 + // Debug
461 + var autoConnectDesktopTimer = null;
462 + function autoConnectDesktop(e) { if (autoConnectDesktopTimer == null) { autoConnectDesktopTimer = setInterval(function () { connectDesktop(null, 1) }, 1000); } else { clearInterval(autoConnectDesktopTimer); autoConnectDesktopTimer = null; } }
463 +
464 + // Used to translate incoming agent console messages
465 + var agentConsoleMessages = ['', "Waiting for user to grant access...", "Denied", "Failed to start remote terminal session, {0} ({1})", "Timeout", "Received invalid network data"];
466 + function formatAgentConsoleMessage(msg, msgid, msgargs) {
467 + var r;
468 + if (msgargs == null) { msgargs = []; }
469 + while (msgargs.length < 3) { msgargs.push(''); } // We need to call the format function in a way that works with older browsers and minifier, can't use apply() or ...
470 + if (msgid && (msgid < agentConsoleMessages.length)) { r = EscapeHtml(format(agentConsoleMessages[msgid], (msgargs[0]), (msgargs[1]), (msgargs[2]))); } else { r = EscapeHtml(msg); }
471 + return r.split('\n').join('<br />') + '<br /><br />';
472 + }
473 +
474 + function connectDesktop(e, contype, tsid, consent) {
475 + if (xxdialogMode) return;
476 + if ((e != null) && (e.shiftKey != false) && (contype == 3)) { contype = 1; } // If the shift key is not pressed, don't try to ask for session list.
477 + QV('p11DeskSessionSelector', false);
478 + p11clearConsoleMsg();
479 + if (desktop == null) {
480 + if (contype == 2) {
481 + // Setup the Intel AMT remote desktop
482 + //if ((desktopNode.intelamt.user == null) || (desktopNode.intelamt.user == '')) { editDeviceAmtSettings(desktopNode._id, connectDesktop, 2); return; }
483 + desktop = CreateAmtRedirect(CreateAmtRemoteDesktop('Desk'), authCookie);
484 + desktop.debugmode = debugmode;
485 + desktop.onStateChanged = onDesktopStateChange;
486 + desktop.m.stopInput = (viewOnly == 1);
487 + desktop.m.bpp = (desktopsettings.encoding == 1 || desktopsettings.encoding == 3) ? 1 : 2;
488 + desktop.m.useZRLE = (desktopsettings.encoding < 3);
489 + desktop.m.localKeyMap = desktopsettings.localkeymap;
490 + desktop.m.showmouse = desktopsettings.showmouse;
491 + desktop.m.onScreenSizeChange = deskAdjust;
492 + desktop.m.onKvmData = function (x) {
493 + //console.log('onKvmData (' + x.length + '): ' + x);
494 + // Send the presense probe only once if needed.
495 + if (x.length == 0) { if (!desktop.m._sentPresence) { desktop.m._sentPresence = true; desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 })); } return; }
496 + var data = null;
497 + try { data = JSON.parse(x); } catch (e) { }
498 + if ((data != null) && (data.action != null)) {
499 + if (data.action == 'restart') {
500 + // Clear WebRTC channel
501 + webRtcDesktopReset();
502 + desktop.m.sendKvmData(JSON.stringify({ action: 'present', ver: 1 }));
503 + } else if ((data.action == 'present') && (webRtcDesktop == null)) {
504 + // Setup WebRTC channel
505 + webRtcDesktop = { platform: data.platform };
506 + var configuration = null; //{ "iceServers": [ { 'urls': 'stun:stun.services.mozilla.com' }, { 'urls': 'stun:stun.l.google.com:19302' } ] };
507 + if (typeof RTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new RTCPeerConnection(configuration); }
508 + else if (typeof webkitRTCPeerConnection !== 'undefined') { webRtcDesktop.webrtc = new webkitRTCPeerConnection(configuration); }
509 +
510 + webRtcDesktop.webchannel = webRtcDesktop.webrtc.createDataChannel("DataChannel", {}); // { ordered: false, maxRetransmits: 2 }
511 + webRtcDesktop.webchannel.onopen = function () {
512 + // Switch to software KVM
513 + //if (urlvars && urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Open'); }
514 + console.log('WebRTC Data Channel Open');
515 + Q('deskstatus').textContent = StatusStrs[desktop.State] + ", Soft-KVM";
516 + desktop.m.hold(true);
517 + webRtcDesktop.webRtcActive = true;
518 + webRtcDesktop.softdesktop = CreateKvmDataChannel(webRtcDesktop.webchannel, CreateAgentRemoteDesktop('Desk', Q('id_mainarea')), desktop.m);
519 + webRtcDesktop.softdesktop.m.setRotation(desktop.m.rotation);
520 + webRtcDesktop.softdesktop.m.onScreenSizeChange = deskAdjust;
521 + if (desktopsettings.quality) { webRtcDesktop.softdesktop.m.CompressionLevel = desktopsettings.quality; } // Number from 1 to 100. 50 or less is best.
522 + if (desktopsettings.scaling) { webRtcDesktop.softdesktop.m.ScalingLevel = desktopsettings.scaling; }
523 + webRtcDesktop.softdesktop.Start();
524 +
525 + // Check if we can get remote file access
526 + // ###BEGIN###{DesktopInbandFiles}
527 + /*
528 + QV('go24', true); // Files
529 + downloadFile = null;
530 + p24files = webRtcDesktop.softdesktop;
531 + p24targetpath = '';
532 + webRtcDesktop.softdesktop.onControlMsg = onFilesControlData;
533 + webRtcDesktop.softdesktop.sendCtrlMsg(JSON.stringify({ action: 'ls', reqid: 1, path: '' })); // Ask for the root folder
534 + */
535 + // ###END###{DesktopInbandFiles}
536 + }
537 + webRtcDesktop.webchannel.onclose = function (event) {
538 + //if (urlvars['kvmdatatrace']) { console.log('WebRTC Data Channel Closed'); }
539 + console.log('WebRTC Data Channel Closed');
540 + webRtcDesktopReset();
541 + }
542 + webRtcDesktop.webrtc.onicecandidate = function (e) {
543 + if (e.candidate == null) {
544 + desktop.m.sendKvmData(JSON.stringify({ action: 'offer', ver: 1, sdp: webRtcDesktop.webrtcoffer.sdp }));
545 + } else {
546 + webRtcDesktop.webrtcoffer.sdp += ('a=' + e.candidate.candidate + '\r\n'); // New candidate, add it to the SDP
547 + }
548 + }
549 + webRtcDesktop.webrtc.oniceconnectionstatechange = function () {
550 + if ((webRtcDesktop != null) && (webRtcDesktop.webrtc != null) && ((webRtcDesktop.webrtc.iceConnectionState == 'disconnected') || (webRtcDesktop.webrtc.iceConnectionState == 'failed'))) { /*console.log('WebRTC ICE Failed');*/ webRtcDesktopReset(); }
551 + }
552 + webRtcDesktop.webrtc.createOffer(function (offer) {
553 + // Got the offer
554 + webRtcDesktop.webrtcoffer = offer;
555 + webRtcDesktop.webrtc.setLocalDescription(offer, function () { }, webRtcDesktopReset);
556 + }, webRtcDesktopReset, { mandatory: { OfferToReceiveAudio: false, OfferToReceiveVideo: false } });
557 + } else if ((data.action == 'answer') && (webRtcDesktop != null)) {
558 + // Complete the WebRTC channel
559 + webRtcDesktop.webrtc.setRemoteDescription(new RTCSessionDescription({ type: 'answer', sdp: data.sdp }), function () { }, webRtcDesktopReset);
560 + }
561 + }
562 + };
563 + desktop.Start(null, 16994, '*', '*', 0);
564 + desktop.contype = 2;
565 + } else if ((contype == null) || (contype == 1) || (contype == 3)) {
566 + // Setup the Mesh Agent remote desktop
567 + desktop = CreateAgentRedirect(null, CreateAgentRemoteDesktop('Desk'), serverPublicNamePort, authCookie, null, domainUrl);
568 + desktop.m.stopInput = (viewOnly == 1);
569 + desktop.m.mouseCursorActive(true);
570 + desktop.debugmode = debugmode;
571 + desktop.m.debugmode = debugmode;
572 + desktop.attemptWebRTC = attemptWebRTC;
573 + desktop.options = {};
574 + if (tsid != null) { desktop.options.tsid = tsid; }
575 + if (consent != null) { desktop.options.consent = consent; }
576 + desktop.onStateChanged = onDesktopStateChange;
577 + desktop.onConsoleMessageChange = function () {
578 + if (desktop.consoleMessage) {
579 + Q('p11DeskConsoleMsg').innerHTML += formatAgentConsoleMessage(desktop.consoleMessage, desktop.consoleMessageId, desktop.consoleMessageArgs);
580 + QV('p11DeskConsoleMsg', true);
581 + if (p11DeskConsoleMsgTimer != null) { clearTimeout(p11DeskConsoleMsgTimer); }
582 + if (desktop.consoleMessageTimeout) { p11DeskConsoleMsgTimer = setTimeout(p11clearConsoleMsg, desktop.consoleMessageTimeout * 1000); }
583 + } else {
584 + p11clearConsoleMsg();
585 + }
586 + }
587 + desktop.onMetadataChange = function (metadata) { updateMetadata(desktop, 'deskmetadata'); }
588 + desktop.m.CompressionLevel = desktopsettings.quality; // Number from 1 to 100. 50 or less is best.
589 + desktop.m.ScalingLevel = desktopsettings.scaling;
590 + if (desktopsettings.framerate) { desktop.m.FrameRateTimer = desktopsettings.framerate; }
591 + desktop.m.onDisplayinfo = deskDisplayInfo;
592 + desktop.m.onScreenSizeChange = deskAdjust;
593 + desktop.Start(null);
594 + desktop.latency.callback = function (ms) { console.log('latency', ms); updateSessionTime(); };
595 + desktop.contype = 1;
596 + }
597 + } else {
598 + // Disconnect and clean up the remote desktop
599 + desktop.Stop();
600 + webRtcDesktopReset();
601 + desktop = null;
602 + //if (pluginHandler != null) { pluginHandler.callHook('onDesktopDisconnect'); }
603 + }
604 + }
605 +
606 + function updateMetadata(conn, elementid) {
607 + var str = '', viewerCount = 0;
608 + if (conn && (conn.State == 3)) {
609 + if (conn.metadata && conn.metadata.users) { for (var i in conn.metadata.users) { viewerCount += conn.metadata.users[i]; } }
610 + if (viewerCount > 1) { str = '<span onclick=showSessionMetadata(1) style=cursor:pointer>' + format(", {0} watching", viewerCount) + '</span>'; }
611 + }
612 + QH('deskmetadata', str);
613 + if ((conn == desktop) && (xxdialogTag == ('sessionMetadata1'))) { showSessionMetadata(1); }
614 + }
615 +
616 + function showSessionMetadata(cid) {
617 + if (xxdialogMode && (xxdialogTag != ('sessionMetadata' + cid))) return;
618 + if (xxdialogMode) { setDialogMode(0); }
619 + var conn = null;
620 + if (cid == 1) { conn = desktop; }
621 + if (conn && conn.metadata) {
622 + var x = '';
623 + if (conn.metadata.startTime) { x += addHtmlValue4("Start Time", printDateTime(new Date(conn.metadata.startTime))); }
624 + if (conn.metadata.users) {
625 + for (var i in conn.metadata.users) {
626 + var val = (conn.metadata.users[i] == 1) ? "1 connection" : format("{0} connections", conn.metadata.users[i]);
627 + var username = i.split('/')[2];
628 + if ((users != null) && (users[i] != null)) { username = users[i].name; }
629 + x += addHtmlValue4(format("User \"{0}\"", username), val);
630 + }
631 + }
632 + setDialogMode(2, "Session Information", 1, null, x, 'sessionMetadata' + cid);
633 + }
634 + }
635 +
636 + function p11clearConsoleMsg() { QH('p11DeskConsoleMsg', ''); QV('p11DeskConsoleMsg', false); if (p11DeskConsoleMsgTimer) { clearTimeout(p11DeskConsoleMsgTimer); p11DeskConsoleMsgTimer = null; } }
637 + function p12clearConsoleMsg() { QH('p12TermConsoleMsg', ''); QV('p12TermConsoleMsg', false); if (p12TermConsoleMsgTimer) { clearTimeout(p12TermConsoleMsgTimer); p12TermConsoleMsgTimer = null; } }
638 + function p13clearConsoleMsg() { QH('p13FilesConsoleMsg', ''); QV('p13FilesConsoleMsg', false); if (p13FilesConsoleMsgTimer) { clearTimeout(p13FilesConsoleMsgTimer); p13FilesConsoleMsgTimer = null; } }
639 +
640 + var webRtcDesktop = null;
641 + function webRtcDesktopReset() {
642 + if (webRtcDesktop == null) return;
643 + if (webRtcDesktop.softdesktop != null) { webRtcDesktop.softdesktop.Stop(); webRtcDesktop.softdesktop = null; }
644 + if (webRtcDesktop.webchannel != null) { try { webRtcDesktop.webchannel.close(); } catch (e) { } webRtcDesktop.webchannel = null; }
645 + if (webRtcDesktop.webrtc != null) { try { webRtcDesktop.webrtc.close(); } catch (e) { } webRtcDesktop.webrtc = null; }
646 + webRtcDesktop = null;
647 + // Switch back to hardware KVM
648 + if (desktop && desktop.m) {
649 + desktop.m.hold(false);
650 + Q('deskstatus').textContent = StatusStrs[desktop.State];
651 + }
652 + // ###BEGIN###{DesktopInbandFiles}
653 + /*
654 + p24files = null;
655 + p24downloadFileCancel() // If any downloads are in process, cancel them.
656 + p24uploadFileCancel(); // If any uploads are in process, cancel them.
657 + QV('go24', false); // Files
658 + if (currentView == 24) { go(14); }
659 + */
660 + // ###END###{DesktopInbandFiles}
661 + }
662 +
663 + function onDesktopStateChange(xdesktop, state) {
664 + var xstate = state;
665 + if ((xstate == 3) && (xdesktop.contype == 2)) { xstate++; }
666 + var str = StatusStrs[xstate];
667 + if ((desktop != null) && (desktop.webRtcActive == true)) { str += ", WebRTC"; }
668 + //if (desktop.m.stopInput == true) { str += ', Loopback'; }
669 + QH('deskstatus', str);
670 + switch (state) {
671 + case 0:
672 + // Stop recording
673 + if (desktop.m.recordedData != null) { deskRecordSession(); }
674 +
675 + // Disconnect and clean up the remote desktop
676 + desktop.Stop();
677 + desktop = null;
678 + QV('DeskFocus', false);
679 + QV('termdisplays', false);
680 + QV('deskRecordIcon', false);
681 + if (fullscreen == true) { deskToggleFull(); }
682 + webRtcDesktopReset();
683 + deskPreferedStickyDisplay = 0;
684 + break;
685 + case 2:
686 + break;
687 + case 3:
688 + if (desktop && (desktop.serverIsRecording == true)) { QV('deskRecordIcon', true); }
689 + desktop.startTime = new Date();
690 + if (updateSessionTimer == null) { updateSessionTimer = setInterval(updateSessionTime, 1000); }
691 + break;
692 + default:
693 + //console.log('Unknown onDesktopStateChange state', state);
694 + break;
695 + }
696 + updateDesktopButtons();
697 + deskAdjust();
698 + setTimeout(deskAdjust, 50);
699 + updateMetadata(desktop, 'deskmetadata');
700 + }
701 +
702 + function updateSessionTime() {
703 + // Desktop
704 + var latencyStr = '', seconds = 0;
705 + if (desktop && desktop.startTime) {
706 + if (desktop.latency && (desktop.latency.current >= 0)) { latencyStr = format('{0} ms, ', desktop.latency.current); }
707 + seconds = Math.floor((new Date() - desktop.startTime) / 1000);
708 + QH('DeskTimer', latencyStr + zeroPad(Math.floor(seconds / 3600), 2) + ':' + zeroPad((Math.floor(seconds / 60) % 60), 2) + ':' + zeroPad((seconds % 60), 2));
709 + } else {
710 + QH('DeskTimer', '');
711 + }
712 +
713 + if (desktop == null) { clearInterval(updateSessionTimer); updateSessionTimer = null; }
714 + }
715 +
716 + function showDesktopSettings() {
717 + if (xxdialogMode) return;
718 + applyDesktopSettings();
719 + updateDesktopButtons();
720 + setDialogMode(7, "Remote Desktop Settings", 3, showDesktopSettingsChanged);
721 + }
722 +
723 + function showDesktopSettingsChanged() {
724 + desktopsettings.encoding = d7desktopmode.value;
725 + desktopsettings.showfocus = d7showfocus.checked;
726 + desktopsettings.showmouse = d7showcursor.checked;
727 + desktopsettings.quality = d7bitmapquality.value;
728 + desktopsettings.scaling = d7bitmapscaling.value;
729 + desktopsettings.framerate = d7framelimiter.value;
730 + desktopsettings.localkeymap = d7localKeyMap.checked;
731 + localStorage.setItem('desktopsettings', JSON.stringify(desktopsettings));
732 + applyDesktopSettings();
733 + if (desktop) {
734 + if (desktop.contype == 1) {
735 + if (desktop.State != 0) {
736 + desktop.m.SendCompressionLevel(1, desktopsettings.quality, desktopsettings.scaling, desktopsettings.framerate);
737 + }
738 + }
739 + if (desktop.contype == 2) {
740 + if (desktop.State != 0) { desktop.Stop(); setTimeout(function () { connectDesktop(null, 2); }, 50); }
741 + }
742 + }
743 + }
744 +
745 + function applyDesktopSettings() {
746 + var r = '', ops = [60, 50, 40, 30, 20, 10, 5, 1];
747 + for (var i in ops) { r += '<option value=' + ops[i] + '>' + ops[i] + '%</option>'; }
748 + QH('d7bitmapquality', r);
749 + d7desktopmode.value = desktopsettings.encoding;
750 + d7showfocus.checked = desktopsettings.showfocus;
751 + d7showcursor.checked = desktopsettings.showmouse;
752 + d7bitmapquality.value = 40; // Default value
753 + if (ops.indexOf(parseInt(desktopsettings.quality)) >= 0) { d7bitmapquality.value = desktopsettings.quality; }
754 + d7bitmapscaling.value = desktopsettings.scaling;
755 + if (desktopsettings.framerate) { d7framelimiter.value = desktopsettings.framerate; } else { d7framelimiter.value = 100; }
756 + if (desktopsettings.localkeymap) { d7localKeyMap.checked = desktopsettings.localkeymap; }
757 + }
758 +
759 + // Enter browser fullscreen
760 + function enterBrowserFullscreen(elem) {
761 + if (elem.requestFullscreen) { elem.requestFullscreen(); }
762 + else if (elem.msRequestFullscreen) { elem.msRequestFullscreen(); }
763 + else if (elem.mozRequestFullScreen) { elem.mozRequestFullScreen(); }
764 + else if (elem.webkitRequestFullscreen) { elem.webkitRequestFullscreen(Element.ALLOW_KEYBOARD_INPUT); }
765 + }
766 +
767 + // Exit browser fullscreen
768 + function exitBrowserFullscreen() {
769 + if (document.exitFullscreen) { document.exitFullscreen(); }
770 + else if (document.msExitFullscreen) { document.msExitFullscreen(); }
771 + else if (document.mozCancelFullScreen) { document.mozCancelFullScreen(); }
772 + else if (document.webkitExitFullscreen) { document.webkitExitFullscreen(); }
773 + }
774 +
775 + // Return true if the browser is fullscreen. This is a delayed method that will return true/false late. Not very useful.
776 + function isBrowserFullscreen() {
777 + if (!document.fullscreenElement && !document.mozFullScreenElement && !document.webkitFullscreenElement && !document.msFullscreenElement) { return false; } else { return true; }
778 + }
779 +
780 + var fullscreen = false;
781 + var browserfullscreen = false;
782 + function deskToggleFull(e) {
783 + var xtermActive = !((urlargs.xterm === 0) || ((terminal != null) && (xterm == null)));
784 + fullscreen = !fullscreen;
785 + if (fullscreen) {
786 + QC('body').add('fulldesk');
787 + QS('deskarea3x')['height'] = '100%';
788 + QS('deskarea3x')['max-height'] = '100%';
789 + if (xtermActive) {
790 + // XTerm terminal
791 + QS('termTable')['position'] = 'absolute';
792 + QS('termTable')['top'] = QS('termTable')['bottom'] = QS('termTable')['left'] = QS('termTable')['right'] = '0';
793 + } else {
794 + // Legacy terminal
795 + QS('termTable')['height'] = '100%';
796 + QS('termTable')['max-height'] = '100%';
797 + }
798 +
799 + // If shift is pressed, enter browser full screen.
800 + if (e.shiftKey == true) {
801 + enterBrowserFullscreen(Q('container'));
802 + browserfullscreen = true;
803 + }
804 + } else {
805 + QC('body').remove('fulldesk');
806 + var hide = urlargs.hide;
807 + if (footerBar == false) { hide |= 4; }
808 + var xh = (((hide & 1) ? 0 : 66) + ((hide & 2) ? 0 : 24) + ((hide & 4) ? 0 : 45) + ((hide & 8) ? 0 : 60)); // 0 to 195
809 + QS('deskarea3x')['height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
810 + QS('deskarea3x')['max-height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
811 + if (xtermActive) {
812 + // XTerm terminal
813 + QS('termTable')['position'] = null;
814 + QS('termTable')['top'] = QS('termTable')['bottom'] = QS('termTable')['left'] = QS('termTable')['right'] = null;
815 + } else {
816 + // Legacy terminal
817 + QS('termTable')['height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
818 + QS('termTable')['max-height'] = 'calc(100vh - ' + (75 + xh) + 'px)';
819 + }
820 + if (browserfullscreen == true) { exitBrowserFullscreen(); browserfullscreen = false; }
821 + }
822 + deskAdjust();
823 + updateDesktopButtons();
824 + adjustPanels();
825 + //setTimeout(adjustPanels, 10);
826 + //setTimeout(function() { xtermfit.fit(); }, 10);
827 + if (xterm != null) { if (xxcurrentView == 12) { xtermfit.fit(); xterm.focus(); } }
828 + }
829 +
830 + function mdeskAdjust(mod, sw, sh, cv) {
831 + if (!mod || !sw || !sh || !cv) return;
832 +
833 + // Check if we are in single desktop mode
834 + if (cv.id == 'Desk') { deskAdjust(); return; }
835 +
836 + // Figure out and adjust the size to fill the width of the div
837 + var vsize = [{ x: 180, y: 101 }, { x: 302, y: 169 }, { x: 454, y: 255 }][Q('sizeselect').selectedIndex];
838 + var realw = vsize.x + 2, tw = Q('xdevices').clientWidth - 30, xw = Math.floor(tw / realw);
839 + xw = realw + Math.floor((tw - (xw * realw)) / xw);
840 + vsize.y = vsize.y * (xw / vsize.x);
841 + vsize.x = xw;
842 + var mh = vsize.y, mw = vsize.x;
843 + if (mod.State != 0) { mh = vsize.y; mw = (sw / sh) * vsize.y; }
844 + QS(cv.id)['max-height'] = mh + 'px';
845 + QS(cv.id)['max-width'] = mw + 'px';
846 + QS(cv.id)['margin-top'] = '0';
847 + QS(cv.id)['margin-bottom'] = '0';
848 + }
849 +
850 + // Remote desktop special key combos for Windows
851 + function deskSendKeys() {
852 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
853 + var ks = Q('deskkeys').value;
854 + if (ks == 0) { // WIN+Down arrow
855 + if (desktop.contype == 2) {
856 + desktop.m.sendkey([[0xffe7, 1], [0xff54, 1], [0xff54, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Down arrow press, Down arrow release, Meta-left release
857 + } else {
858 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 40], [desktop.m.KeyAction.UP, 40], [desktop.m.KeyAction.EXUP, 0x5B]]); // Agent: L-Winkey press, Down arrow press, Down arrow release, L-Winkey release
859 + }
860 + } else if (ks == 1) { // WIN+Up arrow
861 + if (desktop.contype == 2) {
862 + desktop.m.sendkey([[0xffe7, 1], [0xff52, 1], [0xff52, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Up arrow press, Up arrow release, Meta-left release
863 + } else {
864 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 38], [desktop.m.KeyAction.UP, 38], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, Up arrow press, Up arrow release, L-Winkey release
865 + }
866 + } else if (ks == 2) { // WIN+L arrow
867 + if (desktop.contype == 2) {
868 + desktop.m.sendkey([[0xffe7, 1], [0x6c, 1], [0x6c, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, 'l' press, 'l' release, Meta-left release
869 + } else {
870 + desktop.sendCtrlMsg('{"action":"lock"}');
871 + //desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN,0x5B],[desktop.m.KeyAction.DOWN,76],[desktop.m.KeyAction.UP,76],[desktop.m.KeyAction.EXUP,0x5B]]); // MeshAgent: L-Winkey press, 'L' press, 'L' release, L-Winkey release
872 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.EXDOWN, 0x5B);
873 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.DOWN, 76);
874 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.UP, 76);
875 + //desktop.m.SendKeyMsgKC(desktop.m.KeyAction.EXUP, 0x5B);
876 + }
877 + } else if (ks == 3) { // WIN+M arrow
878 + if (desktop.contype == 2) {
879 + desktop.m.sendkey([[0xffe7, 1], [0x6d, 1], [0x6d, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, 'm' press, 'm' release, Meta-left release
880 + } else {
881 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 77], [desktop.m.KeyAction.UP, 77], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, 'M' press, 'M' release, L-Winkey release
882 + }
883 + } else if (ks == 4) { // Shift+WIN+M arrow
884 + if (desktop.contype == 2) {
885 + desktop.m.sendkey([[0xffe1, 1], [0xffe7, 1], [0x6d, 1], [0x6d, 0], [0xffe7, 0], [0xffe1, 0]]); // Intel AMT: Shift-left down, Meta-left down, 'm' press, 'm' release, Meta-left release, Shift-left release
886 + } else {
887 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.DOWN, 16], [desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 77], [desktop.m.KeyAction.UP, 77], [desktop.m.KeyAction.EXUP, 0x5B], [desktop.m.KeyAction.UP, 16]]); // MeshAgent: L-shift press, L-Winkey press, 'M' press, 'M' release, L-Winkey release, L-shift release
888 + }
889 + } else if (ks == 5) { // WIN
890 + if (desktop.contype == 2) {
891 + desktop.m.sendkey([[0xffe7, 1], [0xffe7, 0]]); // Intel AMT: Meta-left down, Meta-left release
892 + } else {
893 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, L-Winkey release
894 + }
895 + } else if (ks == 6) { // WIN+R
896 + if (desktop.contype == 2) {
897 + desktop.m.sendkey([[0xffe7, 1], [0x72, 1], [0x72, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, 'r' press, 'r' release, Meta-left release
898 + } else {
899 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 82], [desktop.m.KeyAction.UP, 82], [desktop.m.KeyAction.EXUP, 0x5B]]); // MeshAgent: L-Winkey press, 'R' press, 'R' release, L-Winkey release
900 + }
901 + } else if (ks == 7) { // ALT-F4
902 + if (desktop.contype == 2) {
903 + desktop.m.sendkey([[0xffe9, 1], [0xffc1, 1], [0xffc1, 0], [0xffe9, 0]]); // Intel AMT: Alt down, 'F4' press, 'F4' release, Alt release
904 + } else {
905 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 18], [desktop.m.KeyAction.DOWN, 115], [desktop.m.KeyAction.UP, 115], [desktop.m.KeyAction.EXUP, 18]]); // MeshAgent: Alt press, 'F4' press, 'F4' release, Alt release
906 + }
907 + } else if (ks == 8) { // CTRL-W
908 + if (desktop.contype == 2) {
909 + desktop.m.sendkey([[0xffe3, 1], [0x77, 1], [0x77, 0], [0xffe3, 0]]); // Intel AMT: Ctrl down, 'w' press, 'w' release, Ctrl release
910 + } else {
911 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 17], [desktop.m.KeyAction.DOWN, 87], [desktop.m.KeyAction.UP, 87], [desktop.m.KeyAction.EXUP, 17]]); // MeshAgent: Ctrl press, 'W' press, 'W' release, Ctrl release
912 + }
913 + } else if (ks == 9) { // ALT-TAB
914 + if (desktop.contype == 2) {
915 + desktop.m.sendkey([[0xffe9, 1], [0xff09, 1], [0xff09, 0], [0xffe9, 0]]); // Intel AMT: Alt down, 'TAB' press, 'TAB' release, Alt release
916 + } else {
917 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 18], [desktop.m.KeyAction.DOWN, 9], [desktop.m.KeyAction.UP, 9], [desktop.m.KeyAction.EXUP, 18]]); // MeshAgent: Alt press, 'TAB' press, 'TAB' release, Alt release
918 + }
919 + } else if (ks == 10) { // CTRL-ALT-DEL
920 + desktop.m.sendcad();
921 + } else if (ks == 11) { // WIN-LEFT
922 + if (desktop.contype == 2) {
923 + desktop.m.sendkey([[0xffe7, 1], [0xff51, 1], [0xff51, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Left arrow press, Left arrow release, Meta-left release
924 + } else {
925 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 37], [desktop.m.KeyAction.UP, 37], [desktop.m.KeyAction.EXUP, 0x5B]]);
926 + }
927 + } else if (ks == 12) { // WIN-RIGHT
928 + if (desktop.contype == 2) {
929 + desktop.m.sendkey([[0xffe7, 1], [0xff53, 1], [0xff53, 0], [0xffe7, 0]]); // Intel AMT: Meta-left down, Right arrow press, Right arrow release, Meta-left release
930 + } else {
931 + desktop.m.SendKeyMsgKC([[desktop.m.KeyAction.EXDOWN, 0x5B], [desktop.m.KeyAction.DOWN, 39], [desktop.m.KeyAction.UP, 39], [desktop.m.KeyAction.EXUP, 0x5B]]);
932 + }
933 + }
934 + }
935 +
936 + function ondockeypress(e) {
937 + setSessionActivity();
938 + if (!xxdialogMode && desktop && isInputAllowed()) {
939 + // Check what keys we are allows to send
940 + /*
941 + if (currentNode != null) {
942 + var meshrights = GetNodeRights(currentNode);
943 + var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
944 + if (inputAllowed == false) return false;
945 + var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
946 + if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
947 + }
948 + */
949 + return desktop.m.handleKeys(e);
950 + }
951 + }
952 +
953 + function ondockeydown(e) {
954 + setSessionActivity();
955 + if (!xxdialogMode && desktop && isInputAllowed()) {
956 + // Check what keys we are allows to send
957 + /*
958 + if (currentNode != null) {
959 + var meshrights = GetNodeRights(currentNode);
960 + var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
961 + if (inputAllowed == false) return false;
962 + var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
963 + if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
964 + }
965 + */
966 + return desktop.m.handleKeyDown(e);
967 + }
968 + }
969 +
970 + function ondockeyup(e) {
971 + setSessionActivity();
972 + if (!xxdialogMode && desktop && isInputAllowed()) {
973 + // Check what keys we are allows to send
974 + /*
975 + if (currentNode != null) {
976 + var meshrights = GetNodeRights(currentNode);
977 + var inputAllowed = ((meshrights == 0xFFFFFFFF) || (((meshrights & 8) != 0) && ((meshrights & 256) == 0)));
978 + if (inputAllowed == false) return false;
979 + var limitedInputAllowed = ((meshrights != 0xFFFFFFFF) && (((meshrights & 8) != 0) && ((meshrights & 256) == 0) && ((meshrights & 4096) != 0)));
980 + if (limitedInputAllowed == true) { if ((e.altKey == true) || (e.ctrlKey == true) || ((e.keyCode < 32) && (e.keyCode != 8) && (e.keyCode != 13)) || (e.keyCode > 90)) return false; }
981 + }
982 + */
983 + return desktop.m.handleKeyUp(e);
984 + }
985 + }
986 +
987 + // Remote desktop typing
988 + function showDeskType() {
989 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
990 + Q('DeskType').blur();
991 + var x = '<div>' + "Enter text and click OK to remotely type it using a US english keyboard. Make sure to place the remote cursor at the correct position before proceeding." + '<div>';
992 + x += '<textarea id=d2typeText style="margin-top:5px;width:100%;height:184px;resize:none" maxlength=2000></textarea>';
993 + setDialogMode(2, "Remote Keyboard Entry", 3, showDeskTypeEx, x);
994 + Q('d2typeText').focus();
995 + }
996 +
997 + var AmtDeskTypeTimer = null;
998 + var AmtDeskTypeContent = null;
999 + var DeskTypeTranslate = { 39: 222, 42: 106, 43: 107, 44: 188, 45: 189, 46: 190, 47: 191, 59: 186, 61: 187, 91: 219, 92: 220, 93: 221, 96: 192, 191: 111 };
1000 + var DeskTypeShiftTranslate = { 33: 49, 34: 222, 35: 51, 36: 52, 37: 53, 38: 55, 40: 57, 41: 48, 58: 186, 60: 188, 62: 190, 63: 191, 64: 50, 94: 54, 95: 189, 106: 56, 107: 187, 123: 219, 124: 220, 125: 221, 126: 192 };
1001 + function showDeskTypeEx() {
1002 + var txt = Q('d2typeText').value, ltxt = Q('d2typeText').value.toUpperCase(), x = [], shift = false;
1003 + if (desktop.contype == 2) {
1004 + // Intel AMT
1005 + for (var i in txt) { var a = txt.charCodeAt(i); x.push([a, 1], [a, 0]); }
1006 + AmtDeskTypeContent = x;
1007 + AmtDeskTypeTimer = setInterval(function () {
1008 + var key = AmtDeskTypeContent.shift();
1009 + if (desktop) { desktop.m.sendkey(key[0], key[1]); }
1010 + if ((desktop == null) || (AmtDeskTypeContent.length == 0)) { clearInterval(AmtDeskTypeTimer); AmtDeskTypeContent = null; }
1011 + }, 10);
1012 + } else {
1013 + // MeshAgent
1014 + for (var i in txt) {
1015 + var a = txt.charCodeAt(i), b = ltxt.charCodeAt(i);
1016 + if (((a >= 65) && (a <= 90)) || ((a >= 97) && (a <= 122))) {
1017 + if ((a == b) && (shift == false)) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
1018 + if ((a != b) && (shift == true)) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // LShift up
1019 + } else if ((a >= 48) && (a <= 57)) {
1020 + if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
1021 + } else if (DeskTypeTranslate[a]) {
1022 + if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
1023 + b = DeskTypeTranslate[a];
1024 + } else if (DeskTypeShiftTranslate[a]) {
1025 + if (shift == false) { x.push([desktop.m.KeyAction.DOWN, 16]); shift = true; } // LShift down
1026 + b = DeskTypeShiftTranslate[a];
1027 + }
1028 + x.push([desktop.m.KeyAction.DOWN, b], [desktop.m.KeyAction.UP, b]);
1029 + }
1030 + if (shift == true) { x.push([desktop.m.KeyAction.UP, 16]); shift = false; } // Shift up
1031 + desktop.m.SendKeyMsgKC(x);
1032 + }
1033 + }
1034 +
1035 + /*
1036 + // Show clipboard dialog
1037 + function showDeskClip() {
1038 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
1039 + Q('DeskClip').blur();
1040 + var x = '';
1041 + x += '<input id=dlgClipGet type=button value="Get Clipboard" style=width:120px onclick=showDeskClipGet()>';
1042 + x += '<input id=dlgClipSet type=button value="Set Clipboard" style=width:120px onclick=showDeskClipSet()>';
1043 + x += '<div id=dlgClipStatus style="display:inline-block;margin-left:8px" ></div>';
1044 + x += '<textarea id=d2clipText style="width:100%;height:184px;resize:none" maxlength=65535></textarea>';
1045 + x += '<input type=button value="Close" style=width:80px;float:right onclick=dialogclose(0)><div style=height:26px;margin-top:3px><span id=linuxClipWarn style=display:none>' + "Remote clipboard is valid for 60 seconds." + '</span>&nbsp;</div><div></div>';
1046 + setDialogMode(2, "Remote Clipboard", 8, null, x, 'clipboard');
1047 + Q('d2clipText').focus();
1048 + }
1049 +
1050 + function showDeskClipGet() {
1051 + if (desktop == null || desktop.State != 3) return;
1052 + meshserver.send({ action: 'msg', type: 'getclip', nodeid: currentNode._id });
1053 + }
1054 +
1055 + function showDeskClipSet() {
1056 + if (desktop == null || desktop.State != 3) return;
1057 + meshserver.send({ action: 'msg', type: 'setclip', nodeid: currentNode._id, data: Q('d2clipText').value });
1058 + //QV('linuxClipWarn', currentNode && currentNode.agent && (currentNode.agent.id > 4) && (currentNode.agent.id != 21) && (currentNode.agent.id != 22));
1059 + }
1060 + */
1061 +
1062 + // Send CTRL-ALT-DEL
1063 + function sendCAD() {
1064 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
1065 + desktop.m.sendcad();
1066 + }
1067 +
1068 + /*
1069 + // Show process dialogs
1070 + function toggleDeskTools() {
1071 + if (xxdialogMode) return;
1072 + if (QS('DeskTools').display == 'none') {
1073 + QV('DeskTools', true);
1074 + Q('DeskTools').nodeid = currentNode._id;
1075 + QH('DeskToolsProcesses', '');
1076 + QH('DeskToolsServices', '');
1077 + QV('deskToolsTopTabService', false);
1078 + changeDeskToolTab(0)
1079 + refreshDeskTools(0);
1080 + refreshDeskTools(1);
1081 + } else {
1082 + QV('DeskTools', false);
1083 + }
1084 + }
1085 +
1086 + var deskToolTabSelection = 0;
1087 + function changeDeskToolTab(tabnum) {
1088 + deskToolTabSelection = tabnum;
1089 + QV('DeskToolsProcessTab', tabnum == 0);
1090 + QV('DeskToolsServiceTab', tabnum == 1);
1091 + QS('deskToolsTopTabProcess')['bottom'] = (tabnum == 0) ? '0px' : '3px';
1092 + QS('deskToolsTopTabService')['bottom'] = (tabnum == 1) ? '0px' : '3px';
1093 + QS('deskToolsTopTabProcess')['color'] = (tabnum == 0) ? 'black' : 'gray';
1094 + QS('deskToolsTopTabService')['color'] = (tabnum == 1) ? 'black' : 'gray';
1095 + }
1096 +
1097 + // Refresh all of the desktop tool panels
1098 + function refreshDeskTools(x) {
1099 + var sel = (x == null) ? deskToolTabSelection : x;
1100 + QV('DeskToolsRefreshButton', false);
1101 + setTimeout(refreshDeskToolsEx, 500);
1102 + if (sel == 0) meshserver.send({ action: 'msg', type: 'ps', nodeid: currentNode._id });
1103 + if (sel == 1) meshserver.send({ action: 'msg', type: 'services', nodeid: currentNode._id });
1104 + }
1105 + function refreshDeskToolsEx() { QV('DeskToolsRefreshButton', true); }
1106 + var deskTools = { sort: 1, ssort: 1, msg: null, smsg: null };
1107 + function sortProcess(sort) { deskTools.sort = sort; showDeskToolsProcesses(deskTools.msg); }
1108 + function sortService(sort) { deskTools.ssort = sort; showDeskToolsServices(deskTools.smsg); }
1109 + function sortProcessPid(a, b) { if (a.p > b.p) return 1; if (a.p < b.p) return (-1); return sortProcessName(a, b); }
1110 + function sortProcessName(a, b) { if (a.d > b.d) return 1; if (a.d < b.d) return (-1); return 0; }
1111 + function showDeskToolsProcesses(message) {
1112 + deskTools.msg = message;
1113 + if (message == null) { QH('DeskToolsProcesses', ''); return; }
1114 + if (Q('DeskTools').nodeid != message.nodeid) return;
1115 + var p = [], processes = null;
1116 + try { processes = JSON.parse(message.value); } catch (e) { }
1117 + if (processes != null) {
1118 + for (var pid in processes) { p.push({ p: parseInt(pid), c: processes[pid].cmd, d: processes[pid].cmd.toLowerCase(), u: processes[pid].user }); }
1119 + if (deskTools.sort == 0) { p.sort(sortProcessPid); } else if (deskTools.sort == 1) { p.sort(sortProcessName); }
1120 + var x = '';
1121 + for (var i in p) {
1122 + if (p[i].p != 0) {
1123 + var c = p[i].c;
1124 + if (c.length > 30) { c = '<span title="' + EscapeHtml(c) + '">' + EscapeHtml(c.substring(0, 30)) + '...</span>' } else { c = EscapeHtml(c); }
1125 + x += '<div class=deskToolsBar><div style=width:50px;float:left;text-align:right;padding-right:5px>' + EscapeHtml(p[i].p) + '</div><a href=# style=float:right;padding-right:5px;cursor:pointer title="' + "Stop process" + '" onclick=\'return stopProcess(' + EscapeHtml(p[i].p) + ',"' + EscapeHtml(p[i].c) + '")\'><img width=10 height=10 src="images/trash.png"></a><div style=float:right;padding-right:5px>' + (p[i].u ? EscapeHtml(p[i].u) : '') + '</div><div>' + c + '</div></div>';
1126 + }
1127 + }
1128 + QH('DeskToolsProcesses', x);
1129 + }
1130 + }
1131 + function showDeskToolsServices(message) {
1132 + deskTools.smsg = message;
1133 + if (message == null) { QH('DeskToolsProcesses', ''); return; }
1134 + if (Q('DeskTools').nodeid != message.nodeid) return;
1135 + QV('deskToolsTopTabService', true);
1136 + var s = [], services = null;
1137 + try { services = JSON.parse(message.value); } catch (e) { }
1138 + deskTools.services = services;
1139 + if (services != null) {
1140 + for (var i in services) {
1141 + if (services[i].status) {
1142 + // Windows
1143 + s.push({ p: capitalizeFirstLetter(services[i].status.state.toLowerCase()), d: services[i].displayName, i: i });
1144 + } else if (services[i].serviceType) {
1145 + // Linux (TODO: This the service status is not displayed, not sure start/stop/restart will work).
1146 + s.push({ p: services[i].serviceType, d: services[i].name, i: i });
1147 + }
1148 + }
1149 + if (deskTools.ssort == 0) { s.sort(sortProcessPid); } else if (deskTools.ssort == 1) { s.sort(sortProcessName); }
1150 + var x = '';
1151 + for (var i in s) {
1152 + if (s[i].p != 0) {
1153 + var c = s[i].d;
1154 + if (c.length > 30) { c = '<span title="' + c + '">' + c.substring(0, 30) + '...</span>' } else { c = EscapeHtml(c); }
1155 + x += '<div onclick=showServiceDetailsDialog(' + s[i].i + ') class=deskToolsBar><div style=width:70px;float:left;padding-right:5px>' + EscapeHtml(s[i].p) + '</div><div>' + c + '</div></div>';
1156 + }
1157 + }
1158 + QH('DeskToolsServices', x);
1159 + }
1160 + }
1161 +
1162 + function showServiceDetailsDialog(index) {
1163 + if (xxdialogMode) return;
1164 + var service = deskTools.services[index];
1165 + if (service != null) {
1166 + var x = '';
1167 + if (service.name) { x += addHtmlValue("Name", service.name); }
1168 + if (service.displayName) { x += addHtmlValue("Display name", service.displayName); }
1169 + if (service.status) {
1170 + if (service.status.state) { x += addHtmlValue("State", capitalizeFirstLetter(service.status.state.toLowerCase())); }
1171 + if (service.status.pid) { x += addHtmlValue("PID", service.status.pid); }
1172 + var serviceTypes = [];
1173 + if (service.status.isFileSystemDriver === true) { serviceTypes.push("FileSystemDriver"); }
1174 + if (service.status.isInteractive === true) { serviceTypes.push("Interactive"); }
1175 + if (service.status.isKernelDriver === true) { serviceTypes.push("KernelDriver"); }
1176 + if (service.status.isOwnProcess === true) { serviceTypes.push("OwnProcess"); }
1177 + if (service.status.isSharedProcess === true) { serviceTypes.push("SharedProcess"); }
1178 + if (serviceTypes.length > 0) { x += addHtmlValue("Type", serviceTypes.join(', ')); }
1179 + }
1180 + x += '<br/><div style=float:right;margin-bottom:12px><input type=button value="' + "Close" + '" onclick=showServiceDetailsDialogEx(0,' + index + ')></div><div style=margin-bottom:12px><input type=button value="' + "Start" + '" onclick=showServiceDetailsDialogEx(1,' + index + ')><input type=button value="' + "Stop" + '" onclick=showServiceDetailsDialogEx(2,' + index + ')><input type=button value="' + "Restart" + '" onclick=showServiceDetailsDialogEx(3,' + index + ')></div>';
1181 + setDialogMode(2, "Service Details", 8, null, x, name);
1182 + }
1183 + }
1184 +
1185 + function showServiceDetailsDialogEx(action, index) {
1186 + setDialogMode(0);
1187 + if (action == 0) return;
1188 + var service = deskTools.services[index];
1189 + if (service != null) {
1190 + if (action == 1) { meshserver.send({ action: 'msg', type: 'serviceStart', nodeid: currentNode._id, serviceName: service.name }); }
1191 + if (action == 2) { meshserver.send({ action: 'msg', type: 'serviceStop', nodeid: currentNode._id, serviceName: service.name }); }
1192 + if (action == 3) { meshserver.send({ action: 'msg', type: 'serviceRestart', nodeid: currentNode._id, serviceName: service.name }); }
1193 + setTimeout(function () { refreshDeskTools(1) }, 1000);
1194 + }
1195 + }
1196 + */
1197 +
1198 + // Toggle mouse and keyboard input
1199 + function toggleKvmControl() { QS('DeskControlSpan').color = Q('DeskControl').checked ? null : 'red'; }
1200 +
1201 + // Save the desktop image to file
1202 + function deskSaveImage() {
1203 + if (xxdialogMode || desktop == null || desktop.State != 3) return;
1204 + var d = new Date(), n = "Desktop" + '-' + d.getFullYear() + '-' + ('0' + (d.getMonth() + 1)).slice(-2) + '-' + ('0' + d.getDate()).slice(-2) + '-' + ('0' + d.getHours()).slice(-2) + '-' + ('0' + d.getMinutes()).slice(-2);
1205 + Q('Desk')['toBlob'](function (blob) { saveAs(blob, n + '.png'); });
1206 + }
1207 +
1208 + function deskDisplayInfo(sender, displays, selDisplay) {
1209 + var displayCount = 0, displaySelector = '';
1210 + for (var i in displays) {
1211 + displayCount++;
1212 + displaySelector += '<option' + ((selDisplay == i) ? ' selected' : '') + ' value=' + i + '>' + displays[i] + '</option>';
1213 + if ((deskPreferedStickyDisplay == i) && (selDisplay != deskPreferedStickyDisplay)) { desktop.m.SetDisplay(i); }
1214 + deskPreferedStickyDisplay = -1;
1215 + }
1216 + QH('termdisplays', displaySelector);
1217 + QV('termdisplays', displayCount > 1);
1218 + }
1219 +
1220 + function deskGetDisplayNumbers(e) { desktop.m.GetDisplayNumbers(); }
1221 + var deskPreferedStickyDisplay = -1;
1222 + function deskSetDisplay(e) { desktop.m.SetDisplay(deskPreferedStickyDisplay = parseInt(Q('termdisplays').value)); Q('termdisplays').blur(); }
1223 +
1224 + // Double click detection. This is important for macOS.
1225 + var dblClickDetectArgs = { t: 0, x: 0, y: 0 };
1226 + function dblClickDetect(e) {
1227 + if (e.buttons != 1) return;
1228 + var t = Date.now();
1229 + if (((t - dblClickDetectArgs.t) < 250) && (Math.abs(e.clientX - dblClickDetectArgs.x) < 2) && (Math.abs(e.clientY - dblClickDetectArgs.y) < 2)) {
1230 + if (!xxdialogMode && desktop != null && isInputAllowed()) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousedblclick(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousedblclick(e); } }
1231 + }
1232 + dblClickDetectArgs.t = t;
1233 + dblClickDetectArgs.x = e.clientX;
1234 + dblClickDetectArgs.y = e.clientY;
1235 + }
1236 +
1237 + function dmousedown(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && isInputAllowed()) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousedown(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousedown(e); } } dblClickDetect(e); }
1238 + function dmouseup(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && isInputAllowed()) if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mouseup(e); desktop.m.sendKeepAlive(); } else { desktop.m.mouseup(e); } }
1239 + function dmousemove(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && isInputAllowed()) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousemove(e); desktop.m.sendKeepAlive(); } else { desktop.m.mousemove(e); } } }
1240 + function dmousewheel(e) { setSessionActivity(); e.addx = Q('DeskParent').scrollLeft; e.addy = Q('DeskParent').scrollTop; if (!xxdialogMode && desktop != null && isInputAllowed()) { if ((webRtcDesktop != null) && (webRtcDesktop.softdesktop != null)) { webRtcDesktop.softdesktop.m.mousewheel(e); desktop.m.sendKeepAlive(); } else { if (desktop.m.mousewheel) { desktop.m.mousewheel(e); } } haltEvent(e); return true; } return false; }
1241 + function drotate(x) { if (!xxdialogMode && desktop != null) { desktop.m.setRotation(desktop.m.rotation + x); deskAdjust(); deskAdjust(); } }
1242 +
1243 +
1244 + //
1245 + // Terminal
1246 + //
1247 +
1248 + function setupTerminal() {
1249 + // Setup the terminal
1250 + if (terminal != null) { terminal.Stop(); terminal = null; }
1251 + updateTerminalButtons();
1252 +
1253 + // Terminal special keys
1254 + var x = '';
1255 + for (var c = 1; c < 27; c++) x += '<option value=\'' + c + '\'>' + "Ctrl" + '-' + String.fromCharCode(64 + c) + ' (' + c + ')</option>';
1256 + QH('specialkeylist', x);
1257 + }
1258 +
1259 + // Show and enable the right buttons
1260 + function updateTerminalButtons() {
1261 + var termState = ((terminal != null) && (terminal.state != 0));
1262 +
1263 + // Show the right buttons
1264 + QV('disconnectbutton2span', termState == true);
1265 + QV('connectbutton2span', termState == false);
1266 + //QV('terminalSizeDropDown', termState == false);
1267 +
1268 + // Enable buttons
1269 + QE('connectbutton2', true);
1270 +
1271 + // Key buttons
1272 + QE('ctrlcbutton', termState);
1273 + QE('ctrlxbutton', termState);
1274 + QE('escbutton', termState);
1275 + QE('bsbutton', termState);
1276 + QE('pastebutton', termState);
1277 + QE('specialkeylist', termState);
1278 + QE('specialkeylistinput', termState);
1279 +
1280 + // Terminal settings
1281 + QV('terminalSettingsButtons', (terminal) && (terminal.contype == 2));
1282 + if (terminal) {
1283 + Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
1284 + Q('id_tfxkeysbutton').value = fxEmulations[terminal.m.fxEmulation];
1285 + Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n') ? "CR+LF" : "LF";
1286 + }
1287 +
1288 + // Display extra buttons on legacy terminal
1289 + var xtermActive = true;
1290 + QV('termarea3xdiv', xtermActive);
1291 + QV('bsbutton', !xtermActive);
1292 + QV('pastebutton', !xtermActive);
1293 + QV('devListToolbarViewIcons2', xtermActive);
1294 + QE('termSizeList', terminal == null);
1295 + }
1296 +
1297 + // Called when the terminal state changes
1298 + function onTerminalStateChange(xterminal, state) {
1299 + var xstate = state;
1300 + if ((xstate == 3) && (xterminal.contype == 2)) { xstate++; }
1301 + var str = StatusStrs[xstate];
1302 + if (terminal.webRtcActive == true) { str += ", WebRTC"; }
1303 + QH('termstatus', str);
1304 + switch (state) {
1305 + case 0:
1306 + // Disconnected, clear the terminal
1307 + QH('termtitle', '');
1308 + QV('termRecordIcon', false);
1309 + if (xterm == null) {
1310 + xterminal.m.TermResetScreen();
1311 + xterminal.m.TermDraw();
1312 + } else {
1313 + xterm.dispose();
1314 + xterm = xtermfit = null;
1315 + }
1316 + if (terminal != null) { terminal.Stop(); terminal = null; }
1317 + break;
1318 + case 3:
1319 + if (xterminal && (xterminal.serverIsRecording == true)) { QV('termRecordIcon', true); }
1320 + terminal.startTime = new Date();
1321 + if (updateSessionTimer == null) { updateSessionTimer = setInterval(updateSessionTime, 1000); }
1322 + if (xterm != null) { xterm.focus(); }
1323 + break;
1324 + default:
1325 + //console.log('Unhandled onTerminalStateChange state', state);
1326 + break;
1327 + }
1328 + updateTerminalButtons();
1329 + }
1330 +
1331 + function updateSessionTime() {
1332 + // Terminal
1333 + var latencyStr = '', seconds = 0;
1334 + if (terminal && terminal.startTime) {
1335 + if (terminal.latency && (terminal.latency.current >= 0)) { latencyStr = format('{0} ms, ', terminal.latency.current); }
1336 + seconds = Math.floor((new Date() - terminal.startTime) / 1000);
1337 + QH('TermTimer', latencyStr + zeroPad(Math.floor(seconds / 3600), 2) + ':' + zeroPad((Math.floor(seconds / 60) % 60), 2) + ':' + zeroPad((seconds % 60), 2));
1338 + } else {
1339 + QH('TermTimer', '');
1340 + }
1341 +
1342 + if (terminal == null) { clearInterval(updateSessionTimer); updateSessionTimer = null; }
1343 + }
1344 +
1345 + // DEBUG
1346 + var autoConnectTerminalTimer = null;
1347 + function autoConnectTerminal(e) { if (autoConnectTerminalTimer == null) { autoConnectTerminalTimer = setInterval(connectTerminal, 100); } else { clearInterval(autoConnectTerminalTimer); autoConnectTerminalTimer = null; } }
1348 +
1349 + // Handles a tunnel to a remote shell
1350 + function CreateRemoteTunnel(onTunnelUpdate, options) {
1351 + var obj = { protocol: 1 };
1352 + if ((options != null) && (typeof options.protocol == 'number')) { obj.protocol = options.protocol; }
1353 + obj.onTunnelUpdate = onTunnelUpdate;
1354 + obj.xxStateChange = function (state) { }
1355 + obj.ProcessBinaryData = function (data) { obj.onTunnelUpdate(data); }
1356 + obj.ProcessData = function (data) { obj.onTunnelUpdate(data); }
1357 + obj.terminalEmulation = 1;
1358 + obj.fxEmulation = 0;
1359 + obj.lineFeed = '\r\n';
1360 + return obj;
1361 + }
1362 +
1363 + function tunnelUpdate(data) { if (typeof data == 'string') { xterm.writeUtf8(data); } else { xterm.writeUtf8(new Uint8Array(data)); } }
1364 +
1365 + // Send the new terminal size to the agent
1366 + function xTermSendResize() {
1367 + xtermResizeTimer = null;
1368 + if ((xterm != null) && (terminal != null) && (terminal.sendCtrlMsg != null)) { terminal.sendCtrlMsg(JSON.stringify({ ctrlChannel: '102938', type: 'termsize', cols: xterm.cols, rows: xterm.rows })); }
1369 + }
1370 +
1371 + // Used to translate incoming agent console messages
1372 + var agentConsoleMessages = ['', "Waiting for user to grant access...", "Denied", "Failed to start remote terminal session, {0} ({1})", "Timeout", "Received invalid network data"];
1373 + function formatAgentConsoleMessage(msg, msgid, msgargs) {
1374 + var r;
1375 + if (msgargs == null) { msgargs = []; }
1376 + while (msgargs.length < 3) { msgargs.push(''); } // We need to call the format function in a way that works with older browsers and minifier, can't use apply() or ...
1377 + if (msgid && (msgid < agentConsoleMessages.length)) { r = EscapeHtml(format(agentConsoleMessages[msgid], (msgargs[0]), (msgargs[1]), (msgargs[2]))); } else { r = EscapeHtml(msg); }
1378 + return r.split('\n').join('<br />') + '<br /><br />';
1379 + }
1380 +
1381 + function connectTerminal(e, contype, options) {
1382 + p12clearConsoleMsg();
1383 + if (!terminal) {
1384 + // Terminal setup
1385 + var termoptions = { protocol: ((options != null) && (typeof options.protocol == 'number')) ? options.protocol : 1 };
1386 + if (options && options.requireLogin) { termoptions.requireLogin = true; }
1387 + /*
1388 + if ([1, 2, 3, 4, 21, 22].indexOf(currentNode.agent.id) == -1) {
1389 + if (Q('termSizeList').value == 1) { termoptions.cols = 80; termoptions.rows = 25; termoptions.xterm = true; }
1390 + else if (Q('termSizeList').value == 2) { termoptions.cols = 100; termoptions.rows = 30; termoptions.xterm = true; }
1391 + else if (Q('termSizeList').value == 3) {
1392 + // TODO: Try to improve terminal auto-size.
1393 + termoptions.cols = Math.floor((Q('column_l').clientWidth - 60) / 10);
1394 + termoptions.rows = Math.floor((Q('column_l').clientHeight - 120) / 20);
1395 + termoptions.xterm = true;
1396 + }
1397 + }
1398 + */
1399 +
1400 + /*
1401 + // If shift is pressed
1402 + if ((e && (e.shiftKey == true))) {
1403 + if (currentNode.agent.id > 4) {
1404 + if (termoptions.protocol == 1) { termoptions.protocol = 7; } // Switch to user shell
1405 + } else {
1406 + if (termoptions.protocol == 1) { termoptions.protocol = 6; } // Switch to Powershell
1407 + }
1408 + }
1409 + */
1410 +
1411 + // Setup a mesh agent xterm terminal
1412 + QV('termarea3xdiv', true);
1413 +
1414 + // Setup the terminal with auto-fit
1415 + if (xterm != null) { xterm.dispose(); }
1416 + xtermfit = new FitAddon.FitAddon();
1417 + xterm = new Terminal();
1418 + if (xtermfit) { xterm.loadAddon(xtermfit); }
1419 + xterm.open(Q('termarea3xdiv')); // termarea3x
1420 + xterm.onData(function (data) { if (terminal != null) { terminal.sendText(data); } })
1421 + if (xtermfit) { xtermfit.fit(); }
1422 + xterm.onTitleChange(function (title) { QH('termtitle', ' - ' + EscapeHtml(title)); });
1423 + xterm.onResize(function (size) {
1424 + // Despam resize
1425 + if (xtermResizeTimer) clearTimeout(xtermResizeTimer);
1426 + xtermResizeTimer = setTimeout(xTermSendResize, 200);
1427 + });
1428 +
1429 + // Setup a terminal tunnel to the agent
1430 + terminal = CreateAgentRedirect(null, CreateRemoteTunnel(tunnelUpdate, options), serverPublicNamePort, authCookie, null, domainUrl);
1431 + terminal.debugmode = debugmode;
1432 + terminal.m.debugmode = debugmode;
1433 + terminal.options = { cols: xterm.cols, rows: xterm.rows };
1434 + if (options && options.requireLogin) { terminal.options.requireLogin = true; }
1435 + terminal.Start(null);
1436 + terminal.onStateChanged = onTerminalStateChange;
1437 + terminal.contype = 1;
1438 + terminal.attemptWebRTC = false; // Never do WebRTC on terminal, because of a race condition we can't do it.
1439 + terminal.onConsoleMessageChange = function (server, msg) {
1440 + if (terminal.consoleMessage) {
1441 + Q('p12TermConsoleMsg').innerHTML += formatAgentConsoleMessage(terminal.consoleMessage, terminal.consoleMessageId, terminal.consoleMessageArgs);
1442 + QV('p12TermConsoleMsg', true);
1443 + if (p12TermConsoleMsgTimer != null) { clearTimeout(p12TermConsoleMsgTimer); }
1444 + if (terminal.consoleMessageTimeout) { p12TermConsoleMsgTimer = setTimeout(p12clearConsoleMsg, terminal.consoleMessageTimeout * 1000); }
1445 + } else {
1446 + p12clearConsoleMsg();
1447 + }
1448 + };
1449 + } else {
1450 + terminal.Stop();
1451 + terminal = null;
1452 + }
1453 + Q('connectbutton2').blur(); // Deselect the connect button so the button does not get key presses.
1454 + }
1455 +
1456 + var terminalEmulations = ["UTF8 Terminal", "Extended ASCII", "Intel ASCII"];
1457 + function termToggleType() {
1458 + if (!terminal || xxdialogMode) return;
1459 + terminal.m.terminalEmulation = (terminal.m.terminalEmulation + 1) % 3;
1460 + Q('id_ttypebutton').value = terminalEmulations[terminal.m.terminalEmulation];
1461 + Q('id_ttypebutton').blur(); // Deselect the connect button so the button does not get key presses.
1462 + }
1463 +
1464 + var fxEmulations = ["Intel (F10 = ESC+[OM)", "Alternate (F10 = ESC+0)", "VT100+ (F10 = ESC+[OY)"];
1465 + function termToggleFx() {
1466 + if (!terminal || xxdialogMode) return;
1467 + terminal.m.fxEmulation = (terminal.m.fxEmulation + 1) % 3;
1468 + Q('id_tfxkeysbutton').value = fxEmulations[terminal.m.fxEmulation];
1469 + Q('id_tfxkeysbutton').blur(); // Deselect the connect button so the button does not get key presses.
1470 + }
1471 +
1472 + function termToggleCr() {
1473 + if (!terminal || xxdialogMode) return;
1474 + if (terminal.m.lineFeed == '\n') { terminal.m.lineFeed = '\r\n'; } else { terminal.m.lineFeed = '\n'; }
1475 + Q('id_tcrbutton').value = (terminal.m.lineFeed == '\r\n') ? "CR+LF" : "LF";
1476 + }
1477 +
1478 + function termSendKey(key, id) {
1479 + if (!terminal || xxdialogMode) return;
1480 + if (xterm != null) {
1481 + if (terminal.sendText) {
1482 + // MeshAgent
1483 + terminal.sendText(String.fromCharCode(key));
1484 + } else {
1485 + // CIRA
1486 + terminal.send(String.fromCharCode(key));
1487 + }
1488 + xterm.focus();
1489 + } else if (terminal != null) {
1490 + terminal.m.TermSendKey(key);
1491 + Q(id).blur(); // Deselect the connect button so the button does not get key presses.
1492 + }
1493 + }
1494 +
1495 + function showTermPasteDialog() {
1496 + if (!terminal || xxdialogMode) return;
1497 + Q('pastebutton').blur();
1498 + setDialogMode(2, "Paste", 3, showTermPasteDialogEx, '<textarea id=d2pasteText style="width:100%;height:184px;resize:none"></textarea>');
1499 + Q('d2pasteText').focus();
1500 + }
1501 +
1502 + function showTermPasteDialogEx() {
1503 + if (!terminal) return;
1504 + terminal.m.TermSendKeys(Q('d2pasteText').value);
1505 + }
1506 +
1507 + // Send special key
1508 + function sendSpecialKey() {
1509 + if (xterm != null) {
1510 + terminal.sendText(String.fromCharCode(Q('specialkeylist').value));
1511 + xterm.focus();
1512 + } else if (terminal != null) {
1513 + terminal.m.TermSendKey(Q('specialkeylist').value);
1514 + Q('specialkeylist').blur();
1515 + Q('specialkeylistinput').blur();
1516 + }
1517 + }
1518 +
1519 + function p12clearConsoleMsg() { QH('p12TermConsoleMsg', ''); QV('p12TermConsoleMsg', false); if (p12TermConsoleMsgTimer) { clearTimeout(p12TermConsoleMsgTimer); p12TermConsoleMsgTimer = null; } }
1520 +
1521 +
1522 +
1523 + //
1524 + // Files
1525 + //
1526 +
1527 + function setupFiles() {
1528 + // Setup the files tab
1529 + if (files != null) { files.Stop(); files = null; }
1530 + }
1531 +
1532 + function onFilesStateChange(xfiles, state) {
1533 + p13Connect.value = (state == 0) ? "Connect" : "Disconnect";
1534 + var str = StatusStrs[state];
1535 + if (files.webRtcActive == true) { str += ", WebRTC"; }
1536 + Q('p13Status').textContent = str;
1537 + switch (state) {
1538 + case 0:
1539 + // Disconnected, clear the files
1540 + QH('p13files', '');
1541 + p13filetree = null;
1542 + p13filetreelocation = [];
1543 + QH('p13currentpath', '');
1544 + QE('p13FolderUp', false);
1545 + QV('filesRecordIcon', false);
1546 + p13setActions();
1547 + if (files != null) { files.Stop(); files = null; }
1548 + if (xxdialogTag == 'fileMsgDialog') { setDialogMode(0); }
1549 + break;
1550 + case 3:
1551 + p13targetpath = '';
1552 + if (files) {
1553 + files.sendText({ action: 'ls', reqid: 1, path: '' });
1554 + if (files.serverIsRecording == true) { QV('filesRecordIcon', true); }
1555 + }
1556 + break;
1557 + default:
1558 + //console.log('Unknown onFilesStateChange state', state);
1559 + break;
1560 + }
1561 + }
1562 +
1563 + function CreateRemoteFiles(onFileUpdate) {
1564 + var obj = { protocol: 5 };
1565 + obj.onFileUpdate = onFileUpdate;
1566 + obj.xxStateChange = function (state) { }
1567 + obj.ProcessData = function (data) { obj.onFileUpdate(data); }
1568 + return obj;
1569 + }
1570 +
1571 + function connectFiles(e) {
1572 + p13clearConsoleMsg();
1573 + if (!files) {
1574 + // Setup a mesh agent files
1575 + files = CreateAgentRedirect(null, CreateRemoteFiles(p13gotFiles), serverPublicNamePort, authCookie, null, domainUrl);
1576 + files.attemptWebRTC = attemptWebRTC;
1577 + files.onStateChanged = onFilesStateChange;
1578 + files.onConsoleMessageChange = function () {
1579 + if (files.consoleMessage) {
1580 + Q('p13FilesConsoleMsg').innerHTML += formatAgentConsoleMessage(files.consoleMessage, files.consoleMessageId, files.consoleMessageArgs);
1581 + QV('p13FilesConsoleMsg', true);
1582 + if (p13FilesConsoleMsgTimer != null) { clearTimeout(p13FilesConsoleMsgTimer); }
1583 + if (files.consoleMessageTimeout) { p13FilesConsoleMsgTimer = setTimeout(p13clearConsoleMsg, files.consoleMessageTimeout * 1000); }
1584 + } else {
1585 + p13clearConsoleMsg();
1586 + }
1587 + }
1588 + files.Start(null);
1589 + } else {
1590 + //QH('Term', '');
1591 + files.Stop();
1592 + files = null;
1593 + }
1594 + p13clipboard = p13clipboardFolder = null;
1595 + p13clipboardCut = 0;
1596 + p13updateClipview();
1597 + }
1598 +
1599 + var p13filetree = null;
1600 + var p13targetpath = null;
1601 + var p13filetreelocation = [];
1602 +
1603 + function p13fileOperationDialogEx(b) { if ((b == 0) && (files != null)) { files.sendText({ action: 'cancel' }); } }
1604 +
1605 + function p13gotFiles(data) {
1606 + if ((data.length > 0) && (data.charCodeAt(0) != 123)) { p13gotDownloadBinaryData(data); return; } // This is ok because 4 first bytes is a control value.
1607 + //console.log('p13gotFiles', data);
1608 + try { data = JSON.parse(decode_utf8(data)); } catch (ex) { data = JSON.parse(data); }
1609 + if (data.action == 'download') { p13gotDownloadCommand(data); return; }
1610 +
1611 + // Find file result
1612 + if (data.action == 'findfile') {
1613 + if (xxdialogTag == data.reqid) {
1614 + if (data.r == null) {
1615 + QE('d2findFilter', true);
1616 + QE('filefind_dlgOkButton', true);
1617 + xxdialogTag = null;
1618 + if (Q('d2findResults').innerHTML == '') { QH('d2findResults', '<div style=text-align:center;margin:10px><i>' + "No files found" + '</i></div>'); }
1619 + } else {
1620 + QA('d2findResults', '<div style=white-space:nowrap>' + EscapeHtml(data.r) + '</div>');
1621 + }
1622 + }
1623 + return;
1624 + }
1625 +
1626 + // Process file upload commands
1627 + if ((data.action != null) && (data.action.startsWith('upload'))) { p13gotUploadData(data); return; }
1628 +
1629 + // Display a dialog message
1630 + if (data.action == 'dialogmessage') {
1631 + if ((data.msg == null) && (xxdialogTag == 'fileMsgDialog')) {
1632 + setDialogMode(0); // Close the dialog box
1633 + } else if ((data.msg == 'zipping') && ((!xxdialogMode) || (xxdialogTag == 'fileMsgDialog'))) {
1634 + // Show the dialog box message
1635 + setDialogMode(2, "File Operation", 10, p13fileOperationDialogEx, '<div style=margin:10px>' + "Compressing files..." + '<div>', 'fileMsgDialog');
1636 + } else if ((data.msg == 'zippingFile') && ((!xxdialogMode) || (xxdialogTag == 'fileMsgDialog'))) {
1637 + // Show the dialog box message
1638 + setDialogMode(2, "File Operation", 10, p13fileOperationDialogEx, '<div style=margin:10px>' + EscapeHtml(data.file) + '<div><br /><progress value=' + EscapeHtml(data.progress) + ' style=width:100% max=100 />', 'fileMsgDialog');
1639 + }
1640 + return;
1641 + }
1642 +
1643 + // Refresh file folder
1644 + if (data.action == 'refresh') { p13folderup(9999); return; }
1645 +
1646 + if (data.path != null) {
1647 + data.path = data.path.replace(/\//g, '\\');
1648 + if ((p13filetree != null) && (data.path == p13filetree.path)) {
1649 + // This is an update to the same folder
1650 + var checkedNames = p13getCheckedNames();
1651 + p13filetree = data;
1652 + p13updateFiles(checkedNames);
1653 + } else {
1654 + // Make both paths use the same seperator not start with /
1655 + var x1 = data.path.replace(/\//g, '\\'), x2 = p13targetpath.replace(/\//g, '\\');
1656 + while ((x1.length > 0) && (x1[0] == '\\')) { x1 = x1.substring(1); }
1657 + while ((x2.length > 0) && (x2[0] == '\\')) { x2 = x2.substring(1); }
1658 + if ((x1 == x2) || ((data.path == '\\') && (p13targetpath == ''))) {
1659 + // This is a different folder
1660 + p13filetree = data;
1661 + p13updateFiles();
1662 + }
1663 + }
1664 + }
1665 + }
1666 +
1667 + function p13getCheckedNames() {
1668 + // Save all existing checked boxes
1669 + var checkedNames = [], checkboxes = document.getElementsByName('fd');
1670 + for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { checkedNames.push(p13filetree.dir[checkboxes[i].value].n) }; }
1671 + return checkedNames;
1672 + }
1673 +
1674 + function p13updateFiles(checkedNames) {
1675 + var html1 = '', html2 = '', displayPath = '<a href=# style=cursor:pointer onclick="return p13folderup(0)">' + "Root" + '</a>', fullPath = 'Root';
1676 +
1677 + // Work on parsing the file path
1678 + var x = p13filetree.path.split('\\');
1679 + p13filetreelocation = [];
1680 + for (var i in x) { if (x[i] != '') { p13filetreelocation.push(x[i]); } } // Remove empty spaces
1681 + for (var i in p13filetreelocation) { displayPath += ' / <a href=# style=cursor:pointer onclick="return p13folderup(' + (parseInt(i) + 1) + ')">' + EscapeHtml(p13filetreelocation[i]) + '</a>' } // Setup the path we display
1682 + var newlinkpath = p13filetreelocation.join('/');
1683 +
1684 + // Sort the files
1685 + var filetreexx = p13sort_files(p13filetree.dir);
1686 +
1687 + // Display all files and folders at this location
1688 + for (var i in filetreexx) {
1689 + // Figure out the name and shortname
1690 + var f = filetreexx[i], name = f.n, shortname;
1691 + shortname = name;
1692 + if (name.length > 70) { shortname = '<span title="' + EscapeHtml(name) + '">' + EscapeHtml(name.substring(0, 70)) + ("..." + '</span>'); } else { shortname = EscapeHtml(name); }
1693 + name = EscapeHtml(name);
1694 +
1695 + // Figure out the date
1696 + var fdatestr = '';
1697 + if (f.d != null) {
1698 + var fdate = new Date(f.d);
1699 + if (typeof f.d == 'number') { fdate = new Date(f.d * 1000); }
1700 + var fdatestr = printDateTime(fdate) + '&nbsp;';
1701 + }
1702 +
1703 + // Figure out the size
1704 + var fsize = '';
1705 + if (f.s != null) { fsize = getFileSizeStr(f.s); }
1706 +
1707 + var h = '';
1708 + if (f.t < 3) {
1709 + var right = '', title = '';
1710 + h = '<div class=filelist file=999><input file=999 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'>&nbsp;<span style=float:right title="' + title + '">' + right + '</span><span><div class=fileIcon' + f.t + ' onclick=p13folderset("' + encodeURIComponentEx(f.nx) + '")></div><a href=# style=cursor:pointer onclick=\'return p13folderset("' + encodeURIComponentEx(f.nx) + '")\'>' + shortname + '</a></span></div>';
1711 + } else {
1712 + var link = shortname;
1713 + if (f.s > 0) {
1714 + // Local link
1715 + //link = '<a href=# style=cursor:pointer onclick="return p13downloadfile(\'' + encodeURIComponentEx(newlinkpath + '/' + name) + '\',\'' + encodeURIComponentEx(name) + '\',' + f.s + ')">' + shortname + '</a>';
1716 + // Server link
1717 + //link = '<a href="devicefile.ashx?c=' + authCookie + '&m=' + currentNode.meshid.split('/')[2] + '&n=' + currentNode._id.split('/')[2] + '&f=' + encodeURIComponentEx(newlinkpath + '/' + name) + '" download="' + name + '" style=cursor:pointer>' + shortname + '</a>';
1718 + // Server link
1719 + //link = '<a onclick=downloadFile("devicefile.ashx?c=' + authCookie + '&m=' + currentNode.meshid.split('/')[2] + '&n=' + currentNode._id.split('/')[2] + '&f=' + encodeURIComponentEx(newlinkpath + '/' + name) + '","' + encodeURIComponentEx(name) + '") style=cursor:pointer>' + shortname + '</a>';
1720 + link = '<a onclick=downloadFile("devicefile.ashx?c=' + authCookie + '&n=' + nodeid.split('/')[2] + '&f=' + encodeURIComponentEx(newlinkpath + '/' + name) + '","' + encodeURIComponentEx(name) + '") style=cursor:pointer>' + shortname + '</a>';
1721 + }
1722 + h = '<div id=fileEntry cmenu=filesContextMenu fileIndex=' + i + ' class=filelist file=3><input file=3 style=float:left name=fd class=fcb type=checkbox onchange=p13setActions() value=\'' + f.nx + '\'>&nbsp;<span class=fsize>' + fdatestr + '</span><span style=float:right>' + EscapeHtml(fsize) + '</span><span><div class=fileIcon' + f.t + '></div>' + link + '</span></div>';
1723 + }
1724 +
1725 + if (f.t < 3) { html1 += h; } else { html2 += h; }
1726 + }
1727 +
1728 + // Display the files and path
1729 + QH('p13files', html1 + html2);
1730 + QH('p13currentpath', displayPath);
1731 + QE('p13FolderUp', p13filetreelocation.length != 0);
1732 +
1733 + // Re-check all boxes if needed using names
1734 + if (checkedNames != null) { var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkedNames.indexOf(p13filetree.dir[checkboxes[i].value].n) >= 0) { checkboxes[i].checked = true; } } }
1735 +
1736 + // Update the actions buttons
1737 + p13setActions();
1738 + }
1739 +
1740 + function p13folderset(x) {
1741 + p13targetpath = joinPaths(p13filetree.path, p13filetree.dir[x].n).split('\\').join('/');
1742 + files.sendText({ action: 'ls', reqid: 1, path: p13targetpath });
1743 + }
1744 +
1745 + function p13folderup(x) {
1746 + if (x == null) { p13filetreelocation.pop(); } else { while (p13filetreelocation.length > x) { p13filetreelocation.pop(); } }
1747 + p13targetpath = p13filetreelocation.join('/');
1748 + files.sendText({ action: 'ls', reqid: 1, path: p13targetpath });
1749 + return false;
1750 + }
1751 +
1752 + function p13findfile() {
1753 + if (xxdialogMode) return;
1754 + var x = addHtmlValue("Filter", '<input id=d2findFilter style="width:230px" onkeyup=p13findfileValidate() onkeydown=p13findfileDown(event) placeholder="*.txt"></input>');
1755 + x += '<div id=d2findResults style="width:100%;height:184px;background-color:white;border:1px solid black;padding:3px;overflow:scroll;margin-top:8px"></div>';
1756 + x += '<div style=margin-top:8px><input id=filefind_dlgCancelButton type=button value=' + "Close" + ' style=float:right;width:80px;margin-left:5px onclick=p13findfileCancel()>';
1757 + x += '<input id=filefind_dlgOkButton type=submit value=' + "Search" + ' style=float:right;width:80px onclick=p13findfileEx()><br /><br /></div>';
1758 + setDialogMode(2, "Find Files", 0, null, x);
1759 + p13findfileValidate();
1760 + Q('d2findFilter').focus();
1761 + }
1762 +
1763 + function p13findfileDown(e) { if (e.code == "Enter") { p13findfileEx(); } }
1764 + function p13findfileValidate() { QE('filefind_dlgOkButton', Q('d2findFilter').value.length > 0); }
1765 + function p13findfileCancel() { if (xxdialogTag != null) { files.sendText({ action: 'cancelfindfile', reqid: xxdialogTag }); } dialogclose(0) }
1766 +
1767 + function p13findfileEx(b, t) {
1768 + if (Q('d2findFilter').value.length == 0) return;
1769 + var winagent = true;//((currentNode.agent.id > 0) && (currentNode.agent.id < 5));
1770 + var slash = winagent ? '\\' : '/';
1771 + var path = p13filetreelocation.join(slash) + slash;
1772 + if (!winagent) { path = slash + path; }
1773 + xxdialogTag = 'find:' + Math.random();
1774 + files.sendText({ action: 'findfile', reqid: xxdialogTag, path: path, filter: Q('d2findFilter').value });
1775 + QH('d2findResults', '');
1776 + QE('d2findFilter', false);
1777 + QE('filefind_dlgOkButton', false);
1778 + }
1779 +
1780 + var p13sortorder;
1781 + function p13sort_filename(a, b) { if (a.ln > b.ln) return (1 * p13sortorder); if (a.ln < b.ln) return (-1 * p13sortorder); return 0; }
1782 + function p13sort_timestamp(a, b) { if (a.d > b.d) return (1 * p13sortorder); if (a.d < b.d) return (-1 * p13sortorder); return 0; }
1783 + function p13sort_bysize(a, b) { if (a.s == b.s) return p13sort_filename(a, b); return (((a.s - b.s)) * p13sortorder); }
1784 +
1785 + function p13sort_files(files) {
1786 + var r = [], sortselection = Q('p13sortdropdown').value;
1787 + for (var i in files) { files[i].nx = i; if (files[i].s == null) { files[i].s = 0; } if (files[i].n == null) { files[i].n = i; } files[i].ln = files[i].n.toLowerCase(); r.push(files[i]); }
1788 + p13sortorder = 1;
1789 + if (sortselection > 3) { p13sortorder = -1; sortselection -= 3; }
1790 + if (sortselection == 1) { r.sort(p13sort_filename); }
1791 + else if (sortselection == 2) { r.sort(p13sort_bysize); }
1792 + else if (sortselection == 3) { r.sort(p13sort_timestamp); }
1793 + return r;
1794 + }
1795 +
1796 + function p13setActions() {
1797 + var advancedFeatures = true; //(currentNode.agent.id != 14); // Reduct file feature on some devices.
1798 + if (p13filetree == null) {
1799 + QE('p13DeleteFileButton', false);
1800 + QE('p13NewFolderButton', false);
1801 + QE('p13UploadButton', false);
1802 + QE('p13RenameFileButton', false);
1803 + QE('p13ViewFileButton', false);
1804 + QE('p13SelectAllButton', false);
1805 + Q('p13SelectAllButton').value = "Select All";
1806 + QE('p13RefreshButton', false);
1807 + QE('p13FindButton', false);
1808 + QE('p13CutButton', false);
1809 + QE('p13CopyButton', false);
1810 + QE('p13ZipButton', false);
1811 + QE('p13PasteButton', false);
1812 + } else {
1813 + var cc = p13getFileSelCount(), tc = p13getFileCount(), sfc = p13getFileSelCount(false); // In order: number of entires selected, number of total entries, number of selected entires that are files (not folders)
1814 + var winAgent = true; //((currentNode.agent.id > 0) && (currentNode.agent.id < 5)) || (currentNode.agent.id == 14);
1815 + QE('p13DeleteFileButton', (cc > 0) && ((p13filetreelocation.length > 0) || (winAgent == false)));
1816 + QE('p13NewFolderButton', advancedFeatures && ((p13filetreelocation.length > 0) || (winAgent == false)));
1817 + QE('p13UploadButton', ((p13filetreelocation.length > 0) || (winAgent == false) /*|| (currentNode.agent.id == 14)*/));
1818 + QE('p13RenameFileButton', advancedFeatures && (cc == 1) && ((p13filetreelocation.length > 0) || (winAgent == false)));
1819 + QE('p13ViewFileButton', advancedFeatures && (cc == 1) && (sfc == 1) && ((p13filetreelocation.length > 0) || (winAgent == false)));
1820 + QE('p13SelectAllButton', tc > 0);
1821 + Q('p13SelectAllButton').value = (cc > 0 ? "Select None" : "Select All");
1822 + QE('p13RefreshButton', true);
1823 + QE('p13FindButton', advancedFeatures && ((p13filetreelocation.length > 0) || (winAgent == false)));
1824 + QE('p13CutButton', advancedFeatures && (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
1825 + QE('p13CopyButton', advancedFeatures && (cc > 0) && (cc == sfc) && ((p13filetreelocation.length > 0) || (winAgent == false)));
1826 + QE('p13ZipButton', advancedFeatures && (cc > 0) && ((p13filetreelocation.length > 0) || (winAgent == false)));
1827 + QE('p13PasteButton', advancedFeatures && ((p13filetreelocation.length > 0) || (winAgent == false)) && ((p13clipboard != null) && (p13clipboard.length > 0)));
1828 + }
1829 + }
1830 +
1831 + function p13getFileSelCount(includeDirs) { var cc = 0; var checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && ((includeDirs != false) || (checkboxes[i].attributes.file.value == '3'))) cc++; } return cc; }
1832 + function p13getFileSelDirCount() { var cc = 0, checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '999')) cc++; } return cc; }
1833 + function p13getFileCount() { var cc = 0; var checkboxes = document.getElementsByName('fd'); return checkboxes.length; }
1834 + function p13selectallfile() { var nv = (p13getFileSelCount() == 0), checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { checkboxes[i].checked = nv; } p13setActions(); }
1835 + function p13createfolder() { setDialogMode(2, "New Folder", 3, p13createfolderEx, '<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% />'); focusTextBox('p13renameinput'); p13fileNameCheck(); }
1836 + function p13createfolderEx() { files.sendText({ action: 'mkdir', reqid: 1, path: p13filetreelocation.join('/') + '/' + Q('p13renameinput').value }); p13folderup(999); }
1837 + function p13deletefile() { var cc = p13getFileSelCount(), rec = (p13getFileSelDirCount() > 0) ? '<br /><br /><label><input type=checkbox id=p13recdeleteinput>' + "Recursive delete" + '</label><br>' : '<input type=checkbox id=p13recdeleteinput style=\'display:none\'>'; setDialogMode(2, "Delete", 3, p13deletefileEx, (cc > 1) ? (format("Delete {0} selected items?", cc) + rec) : ("Delete selected item?" + rec)); }
1838 + function p13deletefileEx() { var delfiles = [], checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { delfiles.push(p13filetree.dir[checkboxes[i].value].n); } } files.sendText({ action: 'rm', reqid: 1, path: p13filetreelocation.join('/'), delfiles: delfiles, rec: Q('p13recdeleteinput').checked }); p13folderup(999); }
1839 + function p13renamefile() { var renamefile, checkboxes = document.getElementsByName('fd'); for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { renamefile = p13filetree.dir[checkboxes[i].value].n; } } setDialogMode(2, "Rename", 3, p13renamefileEx, '<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% value="' + renamefile + '" />', { action: 'rename', path: p13filetreelocation.join('/'), oldname: renamefile }); focusTextBox('p13renameinput'); p13fileNameCheck(); }
1840 + function p13renamefileEx(b, t) { t.newname = Q('p13renameinput').value; files.sendText(t); p13folderup(999); }
1841 + function p13fileNameCheck(e) { var x = isFilenameValid(Q('p13renameinput').value); QE('idx_dlgOkButton', x); if ((x == true) && (e != null) && (e.keyCode == 13)) { dialogclose(1); } }
1842 + function p13uploadFile() { setDialogMode(2, "Upload File", 3, p13uploadFileEx, '<input type=file name=files id=p13uploadinput style=width:100% multiple=multiple onchange="updateUploadDialogOk(\'p13uploadinput\')" />'); updateUploadDialogOk('p13uploadinput'); }
1843 + function updateUploadDialogOk(x) { QE('idx_dlgOkButton', Q('p13uploadinput').files.length > 0); }
1844 + function p13uploadFileEx() { p13doUploadFiles(Q('p13uploadinput').files); }
1845 + function p13viewfile() {
1846 + var checkboxes = document.getElementsByName('fd');
1847 + for (var i = 0; i < checkboxes.length; i++) {
1848 + if (checkboxes[i].checked) {
1849 + if (p13filetree.dir[checkboxes[i].value].s <= 204800) {
1850 + p13downloadfile(encodeURIComponentEx(p13filetreelocation.join('/') + '/' + p13filetree.dir[checkboxes[i].value].n), encodeURIComponentEx(p13filetree.dir[checkboxes[i].value].n), p13filetree.dir[checkboxes[i].value].s, 'viewer');
1851 + } else { messagebox("File Editor", "Only files less than 200k can be edited."); }
1852 + break;
1853 + }
1854 + }
1855 + }
1856 +
1857 + function p13zipFiles() {
1858 + var inputFiles = [], checkboxes = document.getElementsByName('fd');
1859 + for (var i = 0; i < checkboxes.length; i++) { if (checkboxes[i].checked) { inputFiles.push(p13filetree.dir[checkboxes[i].value].n); } }
1860 + setDialogMode(2, "Zip Filename", 3, p13zipFilesEx, '<input type=text id=p13renameinput maxlength=64 onkeyup=p13fileNameCheck(event) style=width:100% value="" />', { action: 'zip', path: p13filetreelocation.join('/'), files: inputFiles });
1861 + focusTextBox('p13renameinput');
1862 + p13fileNameCheck();
1863 + }
1864 +
1865 + function p13zipFilesEx(b, tag) {
1866 + tag.output = Q('p13renameinput').value;
1867 + if (!tag.output.toLowerCase().endsWith('.zip')) { tag.output += '.zip'; }
1868 + files.sendText(tag);
1869 + }
1870 +
1871 + var p13clipboard = null, p13clipboardFolder = null, p13clipboardCut = 0;
1872 + function p13copyFile(cut) { var checkboxes = document.getElementsByName('fd'); p13clipboard = []; p13clipboardCut = cut, p13clipboardFolder = p13targetpath; for (var i = 0; i < checkboxes.length; i++) { if ((checkboxes[i].checked) && (checkboxes[i].attributes.file.value == '3')) { p13clipboard.push(p13filetree.dir[checkboxes[i].value].n); } } p13updateClipview(); }
1873 + function p13pasteFile() {
1874 + var x = '';
1875 + if ((p13clipboard != null) && (p13clipboard.length > 0)) {
1876 + if (p13clipboardCut == 0) {
1877 + if (p13clipboard.length > 1) { x = format("Confirm copy of {0} entries to this location?", p13clipboard.length); } else { x = format("Confirm copy of 1 entrie to this location?"); }
1878 + } else {
1879 + if (p13clipboard.length > 1) { x = format("Confirm move of {0} entries to this location?", p13clipboard.length); } else { x = format("Confirm move of 1 entrie to this location?"); }
1880 + }
1881 + }
1882 + setDialogMode(2, "Paste", 3, p13pasteFileEx, x);
1883 + }
1884 + function p13pasteFileEx() { files.sendText({ action: (p13clipboardCut == 0 ? 'copy' : 'move'), reqid: 1, scpath: p13clipboardFolder, dspath: p13targetpath, names: p13clipboard }); p13folderup(999); if (p13clipboardCut == 1) { p13clipboard = null, p13clipboardFolder = null, p13clipboardCut = 0; p13updateClipview(); } }
1885 + function p13updateClipview() {
1886 + var x = '';
1887 + if ((p13clipboard != null) && (p13clipboard.length > 0)) {
1888 + if (p13clipboardCut == 0) {
1889 + if (p13clipboard.length > 1) {
1890 + x = format("Holding {0} entries for copy" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Clear" + '</a>.', p13clipboard.length);
1891 + } else {
1892 + x = format("Holding 1 entrie for copy" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Clear" + '</a>.');
1893 + }
1894 + } else {
1895 + if (p13clipboard.length > 1) {
1896 + x = format("Holding {0} entries for move" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Clear" + '</a>.', p13clipboard.length);
1897 + } else {
1898 + x = format("Holding 1 entrie for move" + ', <a href=# onclick="return p13clearClip()" style=cursor:pointer>' + "Clear" + '</a>.');
1899 + }
1900 + }
1901 + }
1902 + QH('p13bottomstatus', x);
1903 + p13setActions();
1904 + }
1905 + function p13clearClip() { p13clipboard = null; p13clipboardFolder = null; p13clipboardCut = 0; p13updateClipview(); return false; }
1906 +
1907 + function p13fileDragDrop(e) {
1908 + haltEvent(e);
1909 + QV('p13bigfail', false);
1910 + QV('p13bigok', false);
1911 + if ((e.dataTransfer == null) || (e.dataTransfer.files.length == 0) || (p13filetree == null)) return;
1912 +
1913 + // Check if these are files we can upload, remove all folders.
1914 + var files = [];
1915 + for (var i in e.dataTransfer.files) { if ((e.dataTransfer.files[i].size != null) && (e.dataTransfer.files[i].size != 0)) { files.push(e.dataTransfer.files[i]); } }
1916 + if (files.length == 0) return;
1917 +
1918 + p13doUploadFiles(files);
1919 + }
1920 +
1921 + var p13dragtimer = null;
1922 + function p13fileDragOver(e) {
1923 + haltEvent(e);
1924 + if (p13dragtimer != null) { clearTimeout(p13dragtimer); p13dragtimer = null; }
1925 + var ac = (p13filetree != null); // Set to true if we can accept the file
1926 + QV('p13bigok', ac);
1927 + QV('p13bigfail', !ac);
1928 + }
1929 +
1930 + function p13fileDragLeave(e) {
1931 + haltEvent(e);
1932 + if (e.target.id != 'p13filetable') {
1933 + QV('p13bigfail', false);
1934 + QV('p13bigok', false);
1935 + } else {
1936 + p13dragtimer = setTimeout(function () { QV('p13bigfail', false); QV('p13bigok', false); p13dragtimer = null; }, 10);
1937 + }
1938 + }
1939 +
1940 + //
1941 + // FILES DOWNLOAD
1942 + //
1943 +
1944 + var gdownloadFile; // Global state for file download
1945 +
1946 + // Called by the html page to start a download, arguments are: path, file name and file size.
1947 + function p13downloadfile(x, y, z, tag) {
1948 + if (xxdialogMode || !files) return;
1949 + gdownloadFile = { path: decodeURIComponent(x), file: decodeURIComponent(y), size: z, tsize: 0, data: '', state: 0, id: Math.random(), tag: tag }
1950 + //console.log('p13downloadFileCancel', gdownloadFile);
1951 + files.sendText({ action: 'download', sub: 'start', id: gdownloadFile.id, path: gdownloadFile.path });
1952 + setDialogMode(2, "Download File", 10, p13downloadFileCancel, '<div>' + gdownloadFile.file + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=' + z + ' />');
1953 + }
1954 +
1955 + // Called by the html page to cancel the download
1956 + function p13downloadFileCancel() { setDialogMode(0); files.sendText({ action: 'download', sub: 'cancel', id: gdownloadFile.id }); gdownloadFile = null; }
1957 +
1958 + // Called by the transport when download control command is received
1959 + function p13gotDownloadCommand(cmd) {
1960 + //console.log('p13gotDownloadCommand', cmd);
1961 + if ((gdownloadFile == null) || (cmd.id != gdownloadFile.id)) return;
1962 + if (cmd.sub == 'start') { gdownloadFile.state = 1; files.sendText({ action: 'download', sub: 'startack', id: gdownloadFile.id }); }
1963 + else if (cmd.sub == 'cancel') { gdownloadFile = null; setDialogMode(0); }
1964 + }
1965 +
1966 + // Called by the transport when binary data is received
1967 + function p13gotDownloadBinaryData(data) {
1968 + if (!gdownloadFile || gdownloadFile.state == 0) return;
1969 + if (data.length > 4) {
1970 + gdownloadFile.tsize += (data.length - 4); // Add to the total bytes received
1971 + gdownloadFile.data += data.substring(4); // Append the data
1972 + Q('d2progressBar').value = gdownloadFile.tsize; // Change the progress bar
1973 + }
1974 + if ((ReadInt(data, 0) & 1) != 0) { // Check end flag
1975 + if (gdownloadFile.tag == 'viewer') {
1976 + // View the file in the dialog box
1977 + setDialogMode(4, EscapeHtml(gdownloadFile.file), 3, p13editSaveBack, null, gdownloadFile.file);
1978 + QS('dialog').width = 'auto';
1979 + QS('dialog').bottom = '80px';
1980 + QS('dialog').top = QS('dialog').left = QS('dialog').right = '100px';
1981 + Q('d4editorarea').value = gdownloadFile.data;
1982 + gdownloadFile = null;
1983 + } else {
1984 + // Save the file to disk
1985 + saveAs(data2blob(gdownloadFile.data), gdownloadFile.file); gdownloadFile = null; setDialogMode(0); // Save the file
1986 + }
1987 + } else {
1988 + files.sendText({ action: 'download', sub: 'ack', id: gdownloadFile.id }); // Send the ACK
1989 + }
1990 + }
1991 +
1992 + var d4EditWrapVal = 0;
1993 + var d4EditSizeVal = 0;
1994 + function d4ToggleWrap(update) {
1995 + if (!update) { d4EditWrapVal = ++d4EditWrapVal % 2; }
1996 + Q('d4WrapButton').value = ["Wrap: ON", "Wrap: OFF"][d4EditWrapVal];
1997 + QS('d4editorarea').overflow = (d4EditWrapVal == 0) ? 'auto' : 'scroll';
1998 + QS('d4editorarea')['white-space'] = (d4EditWrapVal == 0) ? null : 'pre';
1999 + putstore('editorWrap', d4EditWrapVal);
2000 + }
2001 +
2002 + function d4ToggleSize(update) {
2003 + if (!update) { d4EditSizeVal = ++d4EditSizeVal % 4; }
2004 + QS('d4editorarea')['font-size'] = ['100%', '125%', '150%', '200%'][d4EditSizeVal];
2005 + Q('d4SizeButton').value = ["Size: 100%", "Size: 125%", "Size: 150%", "Size: 200%"][d4EditSizeVal];
2006 + putstore('editorSize', d4EditSizeVal);
2007 + }
2008 +
2009 + function p13editSaveBack(b, tag) {
2010 + var data = new TextEncoder().encode(Q('d4editorarea').value);
2011 + p13uploadFileContinue(1, [{ name: tag, size: data.byteLength, type: 'text/plain', xdata: data }]);
2012 + }
2013 +
2014 + //
2015 + // FILES UPLOAD
2016 + //
2017 +
2018 + var uploadFile;
2019 + function p13doUploadFiles(files) {
2020 + if (xxdialogMode) return;
2021 +
2022 + // Check if we are going to overwrite any files
2023 + var winAgent = true;//((currentNode.agent.id > 0) && (currentNode.agent.id < 5));
2024 + var targetFiles = [], overWriteCount = 0;
2025 + for (var i in p13filetree.dir) { if (winAgent) { targetFiles.push(p13filetree.dir[i].n.toLowerCase()); } else { targetFiles.push(p13filetree.dir[i].n); } }
2026 + for (var i = 0; i < files.length; i++) {
2027 + if (winAgent) {
2028 + if (targetFiles.indexOf(files[i].name.toLowerCase()) >= 0) { overWriteCount++; }
2029 + } else {
2030 + if (targetFiles.indexOf(files[i].name) >= 0) { overWriteCount++; }
2031 + }
2032 + }
2033 +
2034 + if (overWriteCount == 0) {
2035 + // If no overwrite, go ahead with upload
2036 + p13uploadFileContinue(1, files);
2037 + } else {
2038 + // Otherwise, prompt for confirmation
2039 + setDialogMode(2, "Upload File", 3, p13uploadFileContinue, format((overWriteCount == 1) ? "Upload will overwrite 1 file. Continue?" : "Upload will overwrite {0} files. Continue?", overWriteCount), files);
2040 + }
2041 + }
2042 +
2043 + function p13uploadFileContinue(b, files) {
2044 + uploadFile = {};
2045 + uploadFile.xpath = p13filetreelocation.join('/');
2046 + uploadFile.xfiles = files;
2047 + uploadFile.xfilePtr = -1;
2048 + setDialogMode(2, "Upload File", 10, p13uploadFileCancel, '<div id=p13dfileName>' + "Connecting..." + '</div><br /><progress id=d2progressBar style=width:100% value=0 max=0 />');
2049 + p13uploadNextFile();
2050 + }
2051 +
2052 + // Push the next file
2053 + function p13uploadNextFile() {
2054 + uploadFile.xfilePtr++;
2055 + if (uploadFile.xfiles.length > uploadFile.xfilePtr) {
2056 + uploadFile.xptr = 0;
2057 + var file = uploadFile.xfiles[uploadFile.xfilePtr];
2058 + QH('p13dfileName', file.name);
2059 + Q('d2progressBar').max = file.size;
2060 + Q('d2progressBar').value = 0;
2061 + if (file.xdata == null) {
2062 + // Load the data
2063 + uploadFile.xreader = new FileReader();
2064 + uploadFile.xreader.onload = function () {
2065 + uploadFile.xdata = uploadFile.xreader.result;
2066 + files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
2067 + };
2068 + uploadFile.xreader.readAsArrayBuffer(file);
2069 + } else {
2070 + // Data already loaded
2071 + uploadFile.xdata = file.xdata;
2072 + files.sendText(JSON.stringify({ action: 'upload', reqid: uploadFile.xfilePtr, path: uploadFile.xpath, name: file.name, size: uploadFile.xdata.byteLength }));
2073 + }
2074 + } else {
2075 + p13uploadFileTransferDone();
2076 + }
2077 + }
2078 +
2079 + // Used to cancel the entire transfer.
2080 + function p13uploadFileCancel(button, tag) {
2081 + if (uploadFile != null) { files.sendText(JSON.stringify({ action: 'uploadcancel', reqid: uploadFile.xfilePtr })); uploadFile = null; }
2082 + p13uploadFileTransferDone();
2083 + }
2084 +
2085 + // Used to cancel the entire transfer.
2086 + function p13uploadFileTransferDone() {
2087 + uploadFile = null; // No more files to upload, clean up.
2088 + setDialogMode(0); // Close the dialog box
2089 + p13folderup(9999); // Refresh the current folder
2090 + }
2091 +
2092 + // Receive upload ack from the mesh agent, use this to keep sending more data
2093 + function p13gotUploadData(cmd) {
2094 + if ((uploadFile == null) || (parseInt(uploadFile.xfilePtr) != parseInt(cmd.reqid))) { return; }
2095 + switch (cmd.action) {
2096 + case 'uploadstart': { p13uploadNextPart(false); for (var i = 0; i < 8; i++) { p13uploadNextPart(true); } break; } // Send 8 more blocks of 16k to fill the websocket.
2097 + case 'uploadack': { p13uploadNextPart(false); break; }
2098 + case 'uploaddone': { if (uploadFile.xfiles.length > uploadFile.xfilePtr + 1) { p13uploadNextFile(); } else { p13uploadFileTransferDone(); } break; }
2099 + case 'uploaderror': { p13uploadFileCancel(); break; }
2100 + }
2101 + }
2102 +
2103 + // Push the next part of the file into the websocket. If dataPriming is true, push more data only if it's not the last block of the file.
2104 + function p13uploadNextPart(dataPriming) {
2105 + var data = uploadFile.xdata, start = uploadFile.xptr;
2106 + if (start >= data.byteLength) {
2107 + files.sendText(JSON.stringify({ action: 'uploaddone', reqid: uploadFile.xfilePtr }));
2108 + } else {
2109 + var end = uploadFile.xptr + 16384;
2110 + if (end > data.byteLength) { if (dataPriming == true) { return; } end = data.byteLength; }
2111 + var dataslice = new Uint8Array(data.slice(start, end))
2112 + if ((dataslice[0] == 123) || (dataslice[0] == 0)) {
2113 + var datapart = new Uint8Array(end - start + 1);
2114 + datapart.set(dataslice, 1); // Add a zero char at the start of the send, this will indicate that it's not a JSON command.
2115 + files.send(datapart);
2116 + } else {
2117 + files.send(dataslice); // The data does not start with 0 or 123 "{" so it can't be confused for JSON.
2118 + }
2119 + uploadFile.xptr = end;
2120 + Q('d2progressBar').value = end;
2121 + }
2122 + }
2123 +
2124 +
2125 +
2126 + //
2127 + // POPUP DIALOG
2128 + //
2129 +
2130 + // null = Hidden, 1 = Generic Message
2131 + var xxdialogMode;
2132 + var xxdialogFunc;
2133 + var xxdialogButtons;
2134 + var xxdialogTag;
2135 + var xxcurrentView = -1;
2136 +
2137 + // Display a dialog box
2138 + // Parameters: Dialog Mode (0 = none), Dialog Title, Buttons (1 = OK, 2 = Cancel, 3 = OK & Cancel), Call back function(0 = Cancel, 1 = OK), Dialog Content (Mode 2 only)
2139 + function setDialogMode(x, y, b, f, c, tag) {
2140 + xxdialogMode = x;
2141 + xxdialogFunc = f;
2142 + xxdialogButtons = b;
2143 + xxdialogTag = tag;
2144 + QE('idx_dlgOkButton', true);
2145 + QV('idx_dlgOkButton', b & 1);
2146 + QV('idx_dlgCancelButton', b & 2);
2147 + QV('id_dialogclose', (b & 2) || (b & 8));
2148 + QV('idx_dlgDeleteButton', b & 4);
2149 + QV('idx_dlgButtonBar', b & 7);
2150 + if (y) QH('id_dialogtitle', y);
2151 + for (var i = 1; i < 8; i++) { QV('dialog' + i, i == x); } // Edit this line when more dialogs are added
2152 + QV('dialog', x);
2153 + if (c) { if (x == 2) { QH('id_dialogOptions', c); } else { QH('id_dialogMessage', c); } }
2154 + }
2155 +
2156 + function dialogclose(x) {
2157 + var f = xxdialogFunc, b = xxdialogButtons, t = xxdialogTag;
2158 + setDialogMode();
2159 + if (((b & 8) || x) && f) f(x, t);
2160 + }
2161 +
2162 + function go(x) {
2163 + if (xxdialogMode) return;
2164 + QV('p11', x == 11);
2165 + QV('p12', x == 12);
2166 + QV('p13', x == 13);
2167 +
2168 + var leftBarItems = ['LeftMenuDesktop', 'LeftMenuTerminal', 'LeftMenuFiles'];
2169 + for (var i in leftBarItems) { Q(leftBarItems[i]).classList.remove('slbbuttonsel'); Q(leftBarItems[i]).classList.remove('slbbuttonsel2'); }
2170 + if (x == 11) { Q('LeftMenuDesktop').classList.add('slbbuttonsel2'); }
2171 + if (x == 12) { Q('LeftMenuTerminal').classList.add('slbbuttonsel2'); }
2172 + if (x == 13) { Q('LeftMenuFiles').classList.add('slbbuttonsel2'); }
2173 + xxcurrentView = x;
2174 + }
2175 +
2176 + function messagebox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t, 1); }
2177 + function statusbox(t, m) { setSessionActivity(); QH('id_dialogMessage', m); setDialogMode(1, t); }
2178 + function haltEvent(e) { if (e.preventDefault) e.preventDefault(); if (e.stopPropagation) e.stopPropagation(); return false; }
2179 + function pad2(num) { var s = '00' + num; return s.substr(s.length - 2); }
2180 + function format(format) { var args = Array.prototype.slice.call(arguments, 1); return format.replace(/{(\d+)}/g, function (match, number) { return typeof args[number] != 'undefined' ? args[number] : match; }); };
2181 + function setSessionActivity() { sessionActivity = Date.now(); /*QH('idleTimeoutNotify', '');*/ }
2182 + function printDate(d) { return d.toLocaleDateString(urlargs.locale); }
2183 + function printTime(d) { return d.toLocaleTimeString(urlargs.locale); }
2184 + function printDateTime(d) { return d.toLocaleString(urlargs.locale); }
2185 + function printFlexDateTime(d) { if (printDate(new Date()) == printDate(d)) { return format("Expires at {0}", printTime(d)); } else { return format("Expires {0}", printDateTime(d)); } }
2186 + function getFileSizeStr(size) { if (typeof size != 'number') { size = 0; } if (size == 1) return "1 byte"; return format("{0} bytes", size); }
2187 + function encodeURIComponentEx(txt) { return encodeURIComponent(txt).replace(/'/g, '%27'); };
2188 + function joinPaths() { var x = []; for (var i in arguments) { var w = arguments[i]; if ((w != null) && (w != '')) { while (w.endsWith('/') || w.endsWith('\\')) { w = w.substring(0, w.length - 1); } while (w.startsWith('/') || w.startsWith('\\')) { w = w.substring(1); } x.push(w); } } return x.join('/'); }
2189 + function focusTextBox(x) { setTimeout(function () { Q(x).selectionStart = Q(x).selectionEnd = 65535; Q(x).focus(); }, 0); }
2190 + var isFilenameValid = (function () { var x1 = /^[^\\/:\*\?"<>\|]+$/, x2 = /^\./, x3 = /^(nul|prn|con|lpt[0-9]|com[0-9])(\.|$)/i; return function isFilenameValid(fname) { return x1.test(fname) && !x2.test(fname) && !x3.test(fname) && (fname[0] != '.'); } })();
2191 +
2192 + // Webkit seems to have a problem with "download" tag causing "network error", but openning the download in a hidden frame fixes it.
2193 + // So we do that for all browsers except FireFox
2194 + function downloadFile(link, name, closeDialog) {
2195 + var element = document.createElement('a');
2196 + element.setAttribute('href', link);
2197 + element.setAttribute('rel', 'noreferrer noopener');
2198 + element.setAttribute('target', 'fileDownloadFrame');
2199 + if (navigator.userAgent.indexOf('Firefox') >= 0) { element.setAttribute('download', decodeURIComponent(name ? name : '')); }
2200 + document.body.appendChild(element);
2201 + element.click();
2202 + document.body.removeChild(element);
2203 + if (closeDialog) { setDialogMode(0); }
2204 + }
2205 +
2206 + start();
2207 + </script>
2208 +</body>
2209 +</html>
\ No newline at end of file
webserver.js
+54 -7
@@ -2992,7 +2992,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
2992 function handleDeviceFile(req, res) {
2993 const domain = checkUserIpAddress(req, res);
2994 if (domain == null) { return; }
2995 - if ((req.query.c == null) || (req.query.m == null) || (req.query.n == null) || (req.query.f == null)) { res.sendStatus(404); return; }
2995 + if ((req.query.c == null) || (req.query.n == null) || (req.query.f == null)) { res.sendStatus(404); return; }
2996
2997 // Check the inbound desktop sharing cookie
2998 var c = obj.parent.decodeCookie(req.query.c, obj.parent.loginCookieEncryptionKey, 60); // 60 minute timeout
@@ -3003,13 +3003,13 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
3003 if ((c == user)) { res.sendStatus(404); return; }
3004
3005 // Check if this user has permission to manage this computer
3006 - const meshid = 'mesh/' + domain.id + '/' + req.query.m;
3007 - const nodeid = 'node/' + domain.id + '/' + req.query.n;
3008 - if ((obj.GetNodeRights(c.userid, meshid, nodeid) & MESHRIGHT_REMOTECONTROL) == 0) { res.sendStatus(404); return; }
3006 + obj.GetNodeWithRights(domain, user, 'node/' + domain.id + '/' + req.query.n, function (node, rights, visible) {
3007 + if ((node == null) || ((rights & MESHRIGHT_REMOTECONTROL) == 0) || (visible == false)) { res.sendStatus(404); return; } // We don't have remote control rights to this device
3008
3010 - // All good, start the file transfer
3011 - req.query.id = getRandomLowerCase(12);
3012 - obj.meshDeviceFileHandler.CreateMeshDeviceFile(obj, null, res, req, domain, user, meshid, nodeid);
3009 + // All good, start the file transfer
3010 + req.query.id = getRandomLowerCase(12);
3011 + obj.meshDeviceFileHandler.CreateMeshDeviceFile(obj, null, res, req, domain, user, node.meshid, node._id);
3012 + });
3013 }
3014
3015 // Handle download of a server file by an agent
@@ -3301,6 +3301,52 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
3301 });
3302 }
3303
3304 + // Serve the guest sharing page
3305 + function handleSharingRequest(req, res) {
3306 + const domain = getDomain(req, res);
3307 + if (domain == null) { return; }
3308 + if (req.query.c == null) { res.sendStatus(404); return; }
3309 + if (domain.guestdevicesharing === false) { res.sendStatus(404); return; } // This feature is not allowed.
3310 +
3311 + // Check the inbound desktop sharing cookie
3312 + var c = obj.parent.decodeCookie(req.query.c, obj.parent.invitationLinkEncryptionKey, 60); // 60 minute timeout
3313 + if ((c == null) || (c.a !== 5) || ((c.p !== 2) && (c.p != null)) || (typeof c.uid != 'string') || (typeof c.nid != 'string') || (typeof c.gn != 'string') || (typeof c.cf != 'number') || (typeof c.start != 'number') || (typeof c.expire != 'number') || (typeof c.pid != 'string')) { res.sendStatus(404); return; }
3314 +
3315 + // Check the expired time, expire message.
3316 + if (c.expire <= Date.now()) { render(req, res, getRenderPage((domain.sitestyle == 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 12, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
3317 +
3318 + // Check the public id
3319 + obj.db.GetAllTypeNodeFiltered([c.nid], domain.id, 'deviceshare', null, function (err, docs) {
3320 + // Check if any desktop sharing links are present, expire message.
3321 + if ((err != null) || (docs.length == 0)) { render(req, res, getRenderPage((domain.sitestyle == 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 12, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
3322 +
3323 + // Search for the device share public identifier, expire message.
3324 + var found = false;
3325 + for (var i = 0; i < docs.length; i++) { if (docs[i].publicid == c.pid) { found = true; } }
3326 + if (found == false) { render(req, res, getRenderPage((domain.sitestyle == 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 12, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
3327 +
3328 + // Get information about this node
3329 + obj.db.Get(c.nid, function (err, nodes) {
3330 + if ((err != null) || (nodes == null) || (nodes.length != 1)) { res.sendStatus(404); return; }
3331 + var node = nodes[0];
3332 +
3333 + // Check the start time, not yet valid message.
3334 + if ((c.start > Date.now()) || (c.start > c.expire)) { render(req, res, getRenderPage((domain.sitestyle == 2) ? 'message2' : 'message', req, domain), getRenderArgs({ titleid: 2, msgid: 11, domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27') }, req, domain)); return; }
3335 +
3336 + // Looks good, let's create the outbound session cookies.
3337 + // Consent flags are 1 = Notify, 8 = Prompt, 64 = Privacy Bar.
3338 + const authCookie = obj.parent.encodeCookie({ userid: c.uid, domainid: domain.id, nid: c.nid, ip: req.clientIp, p: 2, gn: c.gn, cf: 65 | c.cf, r: 8, expire: c.expire, pid: c.pid, vo: c.vo }, obj.parent.loginCookieEncryptionKey);
3339 +
3340 + // Lets respond by sending out the desktop viewer.
3341 + var httpsPort = ((obj.args.aliasport == null) ? obj.args.port : obj.args.aliasport); // Use HTTPS alias port is specified
3342 + parent.debug('web', 'handleDesktopRequest: Sending guest sharing page for \"' + c.uid + '\", guest \"' + c.gn + '\".');
3343 + res.set({ 'Cache-Control': 'no-store' });
3344 + render(req, res, getRenderPage('sharing', req, domain), getRenderArgs({ authCookie: authCookie, authRelayCookie: '', domainurl: encodeURIComponent(domain.url).replace(/'/g, '%27'), nodeid: c.nid, serverDnsName: obj.getWebServerName(domain), serverRedirPort: args.redirport, serverPublicPort: httpsPort, expire: c.expire, viewOnly: (c.vo == 1) ? 1 : 0, nodeName: encodeURIComponent(node.name) }, req, domain));
3345 + });
3346 + });
3347 + }
3348 +
3349 +
3350 // Handle domain redirection
3351 obj.handleDomainRedirect = function (req, res) {
3352 const domain = checkUserIpAddress(req, res);
@@ -5286,6 +5332,7 @@ module.exports.CreateWebServer = function (parent, db, args, certificates) {
5332 obj.app.get(url + 'player', handlePlayerRequest);
5333 obj.app.get(url + 'desktop', handleDesktopRequest);
5334 obj.app.get(url + 'terminal', handleTerminalRequest);
5335 + obj.app.get(url + 'sharing', handleSharingRequest);
5336 obj.app.ws(url + 'agenttransfer.ashx', handleAgentFileTransfer); // Setup agent to/from server file transfer handler
5337 obj.app.ws(url + 'meshrelay.ashx', function (ws, req) {
5338 PerformWSSessionAuth(ws, req, true, function (ws1, req1, domain, user, cookie) {