update 1.0.1
1
source/AUTHORS.md
Executable file → Normal file
|
@ -63,6 +63,7 @@ Translators
|
||||||
* mbajur
|
* mbajur
|
||||||
* mentalo
|
* mentalo
|
||||||
* mkwm
|
* mkwm
|
||||||
|
* Natureshadow
|
||||||
* Och.Oyuka
|
* Och.Oyuka
|
||||||
* Otourly
|
* Otourly
|
||||||
* piotr.moskal
|
* piotr.moskal
|
||||||
|
|
253
source/CHANGELOG.md
Normal file
|
@ -0,0 +1,253 @@
|
||||||
|
Jappix Changelog
|
||||||
|
================
|
||||||
|
|
||||||
|
Here's the log of what has changed over the Jappix releases.
|
||||||
|
|
||||||
|
|
||||||
|
One, v1.0.1 (January 2014)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
* Changed MAM namespace to a temporary one
|
||||||
|
* Fixed broken Jappix Mini CSS loader in some cases
|
||||||
|
* Libs update
|
||||||
|
|
||||||
|
|
||||||
|
One, v1.0.0 (January 2014)
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
* XEP-0166: Jingle
|
||||||
|
* XEP-0292: vCard4 Over XMPP
|
||||||
|
* XEP-0280: Message Carbons
|
||||||
|
* IE9, IE10, IE11 support
|
||||||
|
* Libs update
|
||||||
|
* Client code rewrite
|
||||||
|
* Directory tree re-organization
|
||||||
|
* Tested code (pass CSSLint, JSHint and PHPLint)
|
||||||
|
|
||||||
|
|
||||||
|
Nemesis Alpha 9, v0.9.9 (August 2013)
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
* XEP-0313: Message Archive Management
|
||||||
|
* Drop support for Message Archiving (XEP-0136), outpaced by MAM (XEP-0313)
|
||||||
|
* Jappix Desktop performances improved (noticeable with big rosters)
|
||||||
|
* Fix Jappix Desktop avatar system, unable to cache avatars (thus increasing network load and delays)
|
||||||
|
* New translations added (Mongolian), and a few ones updated
|
||||||
|
|
||||||
|
|
||||||
|
Nemesis Alpha 8, v0.9.8 (May 2013)
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
* RTL (Right-To-Left Languages) support
|
||||||
|
* Various bufixes
|
||||||
|
|
||||||
|
|
||||||
|
Nemesis Alpha 7, v0.9.7 (April 2013)
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
* Fix overflow events in Mini
|
||||||
|
* Fix user info display bug with formatted text
|
||||||
|
* Jappix Me notification system
|
||||||
|
* Update JSJaC
|
||||||
|
* Update jQuery (v1.10.1)
|
||||||
|
|
||||||
|
|
||||||
|
Nemesis Alpha 6, v0.9.6 (April 2013)
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
* Fix login with accented usernames
|
||||||
|
* WOFF Get API headers fixed
|
||||||
|
* Better Get API URL generator
|
||||||
|
* Fix broken Jappix Mini extraction script
|
||||||
|
* Show when user joins/exits MUC in Jappix Mini
|
||||||
|
|
||||||
|
|
||||||
|
Nemesis Alpha 5, v0.9.5 (March 2013)
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
* Jappix Mini enhancements
|
||||||
|
* Fix Jappix over non-standard ports
|
||||||
|
* Locale detector improved
|
||||||
|
* Load more items on social channel scroll
|
||||||
|
* Fix a lot of English base language typos
|
||||||
|
* Support for XHTML microblog entries (Movim compatibility)
|
||||||
|
* Show Jappix Desktop on tablets (not mobile anymore)
|
||||||
|
* Option to disable Jappix Mini on mobile phones
|
||||||
|
* Fix broken MUC bookmarks retrieval
|
||||||
|
|
||||||
|
|
||||||
|
Nemesis Alpha 4, v0.9.4 (March 2013)
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
* [SECURITY] Fix insafe HTML escaping
|
||||||
|
* PHP 5.4 compatibility
|
||||||
|
* Auto-populate microblog on connect
|
||||||
|
* Register API support for Metronome XMPPd
|
||||||
|
* Non-blocking PHP sessions
|
||||||
|
* Permissive geoloc selector in microblog
|
||||||
|
* Select priority more easily
|
||||||
|
* Compliancy with Atom specification (social inbox)
|
||||||
|
* Added project mirrors
|
||||||
|
|
||||||
|
|
||||||
|
Nemesis Alpha 3, v0.9.3 (February 2013)
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
* [SECURITY] More randomness in CAPTCHA
|
||||||
|
* Fix buggy roster filter with groups
|
||||||
|
* Add Piwik tracking feature (configurable in manager)
|
||||||
|
* Easy popup close by clicking away
|
||||||
|
* Fix cropped uploaded pictures
|
||||||
|
* Revert to old File Share API (which is far better)
|
||||||
|
* Fixes broken translations (strange UTF-8 chars due to bugged Gettext compiler)
|
||||||
|
|
||||||
|
|
||||||
|
Nemesis Alpha 2, v0.9.2 (January 2013)
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
* [SECURITY] Introduced the Register API (prevents register flood by spam bots)
|
||||||
|
* Reworked Storage API
|
||||||
|
* Jappix Mini code beautify
|
||||||
|
* Lighter and Web-safe font files
|
||||||
|
* Better error logging
|
||||||
|
* Fix Openfire ping request
|
||||||
|
* Typing notification in Jappix Mini
|
||||||
|
* Support for WebKit notifications
|
||||||
|
* Jappix Mini groupchat suggest
|
||||||
|
* Enhanced Download API
|
||||||
|
* Mini animated chat icon, much sexier
|
||||||
|
* IE custom font compatibility
|
||||||
|
* Legal changes
|
||||||
|
* Update licensing with real names
|
||||||
|
|
||||||
|
|
||||||
|
Nemesis Alpha 1, v0.9.1 (2012)
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
* Show an 'add to home' button on iOS devices
|
||||||
|
* Ability to suspend statistics
|
||||||
|
* Fix IE9 issue with clustering
|
||||||
|
* Show profile button in user search results
|
||||||
|
* Ability to change message font, font size and color
|
||||||
|
* Fix choppy Jappix Mini status picker
|
||||||
|
* Sounds for Safari & IE9
|
||||||
|
* Enhance new file storage functions
|
||||||
|
* No resize for textareas
|
||||||
|
* Add a configurable legal disclaimer
|
||||||
|
* Fix a loop bug on presence if no support for sessionStorage
|
||||||
|
* Universal fonts
|
||||||
|
* Add ability to configure the node owner name & website
|
||||||
|
* HTTP authentication for LDAP
|
||||||
|
* Better notification + comments management
|
||||||
|
|
||||||
|
|
||||||
|
Spaco, v0.9 (2011)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* [SECURITY] Fix when sending files to a contact
|
||||||
|
* Better Jappix Mini performances
|
||||||
|
* Fix Jappix Mini display issues
|
||||||
|
* Connection issue fixed with BOSH API
|
||||||
|
* Open XMPP links when Jappix is ready
|
||||||
|
|
||||||
|
|
||||||
|
Suno, v0.8 (2011)
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
* XEP-0066: Out of Band Data
|
||||||
|
* Switch from OpenStreetMap to Google Maps for geolocation
|
||||||
|
|
||||||
|
|
||||||
|
Stelo, v0.7 (2011)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* Lighter Jappix Mini
|
||||||
|
* Welcome popup
|
||||||
|
* Support for /me command in Jappix Mini
|
||||||
|
* Fixes in social channel
|
||||||
|
* Bigger BOSH poll interval (avoids some overactivity errors)
|
||||||
|
* Compression disabled by default in Get API
|
||||||
|
* Send chatstates in MUC
|
||||||
|
* Social notification inbox
|
||||||
|
|
||||||
|
|
||||||
|
Lumo, v0.6 (2011)
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
* Smoother Mini animation
|
||||||
|
* Show avatars in social channel comments
|
||||||
|
* Legacy mode for microblog comments
|
||||||
|
* Microblog updated to comply with a new version of XEP-0277
|
||||||
|
* Fix DNS SRV issue because of a 'route' attribute on BOSH initiation
|
||||||
|
|
||||||
|
|
||||||
|
Ribelo, v0.5 (2011)
|
||||||
|
-------------------
|
||||||
|
|
||||||
|
* Add support for comments in microblog
|
||||||
|
* Jappix Mini fixes and improvements
|
||||||
|
|
||||||
|
|
||||||
|
Lupo, v0.4 (2011)
|
||||||
|
-----------------
|
||||||
|
|
||||||
|
* Full IE5.5 compatibility for Jappix Mini
|
||||||
|
* BOSH without cURL (if cURL unavailable)
|
||||||
|
* Handle multiple microblog attached files
|
||||||
|
* Microblog attached files thumbnails
|
||||||
|
* BOM (Byte Order Mark) filtering for Get API
|
||||||
|
* Autoplay for new YouTube HTML5 player
|
||||||
|
* Support for privacy lists pushs
|
||||||
|
* Roster-side privacy lists (make contact blocking/unblocking easy)
|
||||||
|
* Better update checker
|
||||||
|
* XEP-0144: Roster Item Exchange
|
||||||
|
* Cross domain support for Internet Explorer and legacy browsers
|
||||||
|
* Update jQuery (v1.4.4)
|
||||||
|
* TZO fix (for negative timezones, e.g.: UTC-5)
|
||||||
|
* Better language detection
|
||||||
|
* Use HTML5 or Flash for YouTube embedded videos
|
||||||
|
|
||||||
|
|
||||||
|
Prism, v0.3 (2011)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* [SECURITY] Fix JS escape bug for quotes
|
||||||
|
* [SECURITY] HTML-encode notification username
|
||||||
|
* Introduction of Jappix Mini
|
||||||
|
* Introduction of Jappix Manager
|
||||||
|
* Introduction of Jappix Install
|
||||||
|
* XEP-0050: Ad-Hoc Commands
|
||||||
|
* XEP-0136: Message Archiving
|
||||||
|
* Update Jappix logo
|
||||||
|
* Declare application language to XMPP server
|
||||||
|
* Add a buddy search tool
|
||||||
|
* Support for old/legacy vCard server implementations
|
||||||
|
* Inbox messages sorted by date
|
||||||
|
* Better music search
|
||||||
|
* Human-readable geolocation
|
||||||
|
* Gateway show/hide
|
||||||
|
* HTML5 forms
|
||||||
|
* Better notification management
|
||||||
|
* Unified chat design
|
||||||
|
* Dynamic DOM load (better performances)
|
||||||
|
* Jappix logo shown when connected (improves branding)
|
||||||
|
|
||||||
|
|
||||||
|
Lidar, v0.2 (2010)
|
||||||
|
------------------
|
||||||
|
|
||||||
|
* Introduction of Jappix Mobile
|
||||||
|
* UI redesign (from grey to black and blue)
|
||||||
|
* Social channel introduced (microblog)
|
||||||
|
|
||||||
|
|
||||||
|
Genesis, v0.1 (2010)
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
* Initial version, released after private beta
|
||||||
|
* Introduction of Jappix Desktop
|
||||||
|
* Basic chat, groupchat, roster and profile features
|
||||||
|
* Basic UI
|
||||||
|
|
||||||
|
|
||||||
|
**For more information about what changed through time, check the changes made to our source code on GitHub: https://github.com/jappix/jappix/commits/master**
|
0
source/COPYING.md
Executable file → Normal file
0
source/COPYING_FONT.md
Executable file → Normal file
0
source/COPYING_MINI.md
Executable file → Normal file
2
source/INSTALL.md
Executable file → Normal file
|
@ -10,7 +10,7 @@ Installation
|
||||||
* The HTTP server: https://github.com/jappix/jappix/wiki/HttpServer
|
* The HTTP server: https://github.com/jappix/jappix/wiki/HttpServer
|
||||||
* The XMPP server: https://github.com/jappix/jappix/wiki/XmppServer
|
* The XMPP server: https://github.com/jappix/jappix/wiki/XmppServer
|
||||||
* The BOSH server: https://github.com/jappix/jappix/wiki/BoshServer
|
* The BOSH server: https://github.com/jappix/jappix/wiki/BoshServer
|
||||||
* The Jappix app.: https://github.com/jappix/jappix/wiki/JappixApp
|
* The Jappix app : https://github.com/jappix/jappix/wiki/JappixApp
|
||||||
|
|
||||||
More
|
More
|
||||||
----
|
----
|
||||||
|
|
68
source/PROTOCOL.md
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
Jappix Protocol Support
|
||||||
|
=======================
|
||||||
|
|
||||||
|
Here are listed the XMPP Protocol Extensions that Jappix supports, as well as their implementation version.
|
||||||
|
|
||||||
|
|
||||||
|
# XMPP Core
|
||||||
|
|
||||||
|
* RFC-6120: Extensible Messaging and Presence Protocol (XMPP): Core
|
||||||
|
* RFC-6121: Extensible Messaging and Presence Protocol (XMPP): Instant Messaging and Presence
|
||||||
|
* RFC-6122: Extensible Messaging and Presence Protocol (XMPP): Address Format
|
||||||
|
|
||||||
|
|
||||||
|
# XMPP Extensions
|
||||||
|
|
||||||
|
* XEP-0045: Multi-User Chat *v1.25*
|
||||||
|
* XEP-0030: Service Discovery *v2.4*
|
||||||
|
* XEP-0060: Publish-Subscribe *v1.13*
|
||||||
|
* XEP-0124: Bidirectional-streams Over Synchronous HTTP (BOSH) *v1.10*
|
||||||
|
* XEP-0115: Entity Capabilities *v1.5*
|
||||||
|
* XEP-0107: User Mood *v1.2*
|
||||||
|
* XEP-0108: User Activity *v1.3*
|
||||||
|
* XEP-0118: User Tune *v1.2*
|
||||||
|
* XEP-0080: User Location *v1.7*
|
||||||
|
* XEP-0172: User Nickname *v1.1*
|
||||||
|
* XEP-0084: User Avatar *v1.1*
|
||||||
|
* XEP-0277: Microblogging over XMPP *v0.6*
|
||||||
|
* XEP-xxxx: Notification Inbox *v0.1*
|
||||||
|
* Alternate URL: http://xmpp.org/extensions/inbox/notification-inbox.html
|
||||||
|
* XEP-0203: Delayed Delivery *v2.0*
|
||||||
|
* XEP-0144: Roster Item Exchange *v1.0*
|
||||||
|
* XEP-0072: SOAP Over XMPP *v1.0*
|
||||||
|
* XEP-0085: Chat State Notifications *v2.1*
|
||||||
|
* XEP-0071: XHTML-IM *v1.5*
|
||||||
|
* XEP-0313: Message Archive Management *v0.3*
|
||||||
|
* Alternate URL: https://demo.frenchtouch.pro/valerian.saliou/xmpp/extensions/xep-0313.html
|
||||||
|
* XEP-0012: Last Activity *v2.0*
|
||||||
|
* XEP-0049: Private XML Storage *v1.2*
|
||||||
|
* XEP-0077: In-Band Registration *v2.4*
|
||||||
|
* XEP-0055: Jabber Search *v1.3*
|
||||||
|
* XEP-0050: Ad-Hoc Commands *v1.2*
|
||||||
|
* XEP-0092: Software Version *v1.1*
|
||||||
|
* XEP-0004: Data Forms *v2.9*
|
||||||
|
* XEP-0054: vcard-temp *v1.2*
|
||||||
|
* XEP-0202: Entity Time *v2.0*
|
||||||
|
* XEP-0199: XMPP Ping *v2.0*
|
||||||
|
* XEP-0184: Message Delivery Receipts *v1.2*
|
||||||
|
* XEP-0016: Privacy Lists *v1.6*
|
||||||
|
* XEP-0066: Out of Band Data *v1.5*
|
||||||
|
* XEP-0280: Message Carbons *v0.9*
|
||||||
|
* XEP-0292: vCard4 Over XMPP *v0.10*
|
||||||
|
* XEP-0166: Jingle *v1.1*
|
||||||
|
* XEP-0167: Jingle RTP Sessions *v1.1*
|
||||||
|
* XEP-0176: Jingle ICE-UDP Transport Method *v1.0*
|
||||||
|
* XEP-0215: External Service Discovery *v0.5*
|
||||||
|
* XEP-0262: Use of ZRTP in Jingle RTP Sessions *v1.0*
|
||||||
|
* XEP-0266: Codecs for Jingle Audio *v1.0*
|
||||||
|
* XEP-0269: Jingle Early Media *v0.1*
|
||||||
|
* XEP-0293: Jingle RTP Feedback Negotiation *v0.1*
|
||||||
|
* XEP-0294: Jingle RTP Header Extensions Negotiation *v0.1*
|
||||||
|
* XEP-0299: Codecs for Jingle Video *v0.1*
|
||||||
|
* XEP-0320: Use of DTLS-SRTP in Jingle Sessions *v0.2*
|
||||||
|
* XEP-0338: Jingle Grouping Framework *v0.1*
|
||||||
|
|
||||||
|
|
||||||
|
# Others
|
||||||
|
|
||||||
|
* RFC-3264: An Offer/Answer Model with Session Description Protocol (SDP)
|
16
source/README.md
Executable file → Normal file
|
@ -1,5 +1,13 @@
|
||||||
Jappix - An open social platform
|
<img src="https://project.jappix.com/img/logos/jappix_github.png" alt="Jappix" />
|
||||||
================================
|
|
||||||
|
|
||||||
|
Jappix is a fresh new open social platform which enables you to create your own cloud, wherever you want to. People must be able to get in touch with all their friends on a free decentralized network!
|
||||||
|
|
||||||
|
You can build your own Jappix installation for your own requirements: if you want to use it as a personal social client, you can download it and put it on your webserver. It's easy, fast and free.
|
||||||
|
|
||||||
|
|
||||||
|
[![build status](https://ci.frenchtouch.pro/projects/7/status.png?ref=master)](https://ci.frenchtouch.pro/projects/7?ref=master)
|
||||||
|
|
||||||
|
|
||||||
License
|
License
|
||||||
-------
|
-------
|
||||||
|
@ -28,7 +36,7 @@ Links
|
||||||
* Jappix project dev panel: https://github.com/jappix/jappix
|
* Jappix project dev panel: https://github.com/jappix/jappix
|
||||||
* Jappix nodes list: http://jappix.net/
|
* Jappix nodes list: http://jappix.net/
|
||||||
* Jappix main service: https://jappix.com/
|
* Jappix main service: https://jappix.com/
|
||||||
* Jappix commercial support: http://jappix.pro/
|
* Jappix commercial support: https://jappix.pro/
|
||||||
|
|
||||||
|
|
||||||
Mirrors
|
Mirrors
|
||||||
|
@ -37,7 +45,7 @@ Mirrors
|
||||||
In case a master service is down (GitHub for Git access or Jappix.org for project download), here is a list of available mirrors:
|
In case a master service is down (GitHub for Git access or Jappix.org for project download), here is a list of available mirrors:
|
||||||
|
|
||||||
* Project website mirror: https://project.jappix.com/
|
* Project website mirror: https://project.jappix.com/
|
||||||
* Git read-only mirror: git clone https://code.frenchtouch.pro/jappix/jappix.git
|
* Development repository mirror: https://code.frenchtouch.pro/jappix/jappix
|
||||||
|
|
||||||
|
|
||||||
MUC Links
|
MUC Links
|
||||||
|
|
0
source/THANKS.md
Executable file → Normal file
2
source/VERSION
Executable file → Normal file
|
@ -1 +1 @@
|
||||||
Nemesis Alpha 9 [0.9.9]
|
One [1.0.1]
|
2
source/app/.htaccess
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
# Security rule
|
||||||
|
deny from all
|
5
source/app/bundles/anonymous.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<jappix xmlns="jappix:file:get">
|
||||||
|
<css>anonymous.css</css>
|
||||||
|
<js>anonymous.js</js>
|
||||||
|
</jappix>
|
5
source/app/bundles/desktop.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<jappix xmlns="jappix:file:get">
|
||||||
|
<css>fonts.css~main.css~images.css~board.css~home.css~others.css~tools.css~roster.css~myinfos.css~pageengine.css~channel.css~pageswitch.css~smileys.css~popup.css~vcard.css~options.css~favorites.css~discovery.css~directory.css~adhoc.css~privacy.css~inbox.css~mucadmin.css~integratebox.css~userinfos.css~search.css~welcome.css~me.css~rosterx.css~jingle.css</css>
|
||||||
|
<js>origin.js~jxhr.js~datejs.js~jquery.js~jquery.ui.js~jquery.json.js~jquery.form.js~jquery.timers.js~jquery.placeholder.js~jquery.textrange.js~base64.js~jsjac.js~jsjac.jingle.js~system.js~constants.js~datastore.js~browser-detect.js~home.js~talk.js~popup.js~audio.js~board.js~bubble.js~chat.js~groupchat.js~smileys.js~oob.js~avatar.js~mucadmin.js~connection.js~dataform.js~discovery.js~directory.js~adhoc.js~privacy.js~errors.js~name.js~favorites.js~features.js~interface.js~xmpplinks.js~iq.js~message.js~chatstate.js~receipts.js~tooltip.js~filter.js~links.js~inbox.js~microblog.js~music.js~notification.js~httpreply.js~options.js~integratebox.js~pubsub.js~pep.js~presence.js~roster.js~jingle.js~storage.js~console.js~common.js~utilities.js~date.js~caps.js~vcard.js~userinfos.js~search.js~autocompletion.js~welcome.js~me.js~rosterx.js~mam.js~carbons.js</js>
|
||||||
|
</jappix>
|
4
source/app/bundles/httpauth.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<jappix xmlns="jappix:file:get">
|
||||||
|
<js>httpauth.js</js>
|
||||||
|
</jappix>
|
5
source/app/bundles/install.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<jappix xmlns="jappix:file:get">
|
||||||
|
<css>main.css~install.css~images.css</css>
|
||||||
|
<js></js>
|
||||||
|
</jappix>
|
5
source/app/bundles/manager.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<jappix xmlns="jappix:file:get">
|
||||||
|
<css>main.css~manager.css~images.css</css>
|
||||||
|
<js></js>
|
||||||
|
</jappix>
|
5
source/app/bundles/mini.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<jappix xmlns="jappix:file:get">
|
||||||
|
<css>mini.css</css>
|
||||||
|
<js>origin.js~jxhr.js~base64.js~jsjac.js~jquery.json.js~jquery.timers.js~jquery.scrollto.js~system.js~constants.js~datastore.js~browser-detect.js~console.js~common.js~date.js~links.js~mini.js</js>
|
||||||
|
</jappix>
|
5
source/app/bundles/mobile.xml
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8" ?>
|
||||||
|
<jappix xmlns="jappix:file:get">
|
||||||
|
<css>mobile.css~ios.css~images.css</css>
|
||||||
|
<js>origin.js~jxhr.js~base64.js~jsjac.js~system.js~constants.js~console.js~browser-detect.js~links.js~mobile.js~ios.js</js>
|
||||||
|
</jappix>
|
BIN
source/app/fonts/eot/ptsans.eot
Normal file
BIN
source/app/fonts/eot/ptsansbold.eot
Normal file
BIN
source/app/fonts/eot/ptsansbolditalic.eot
Normal file
BIN
source/app/fonts/eot/ptsansitalic.eot
Normal file
242
source/app/fonts/svg/ptsans.svg
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<metadata></metadata>
|
||||||
|
<defs>
|
||||||
|
<font id="pt_sansregular" horiz-adv-x="1116" >
|
||||||
|
<font-face units-per-em="2048" ascent="1536" descent="-512" />
|
||||||
|
<missing-glyph horiz-adv-x="546" />
|
||||||
|
<glyph unicode="fi" horiz-adv-x="1105" d="M45 881v143h160v57q0 193 95 280t280 87q121 0 215 -23.5t147 -56.5l-55 -131q-55 35 -131 51.5t-162 16.5q-76 0 -120 -17.5t-67.5 -53.5t-30.5 -89t-7 -121h577v-1024h-164v881h-413v-881h-164v881h-160z" />
|
||||||
|
<glyph unicode="fl" horiz-adv-x="1193" d="M45 881v143h160v57q0 193 83 285t277 92q41 0 92.5 -3t103.5 -8t98 -11t75 -15v-1169q0 -72 25.5 -102.5t68.5 -30.5q29 0 59.5 4t69.5 18l17 -129q-16 -8 -40 -15t-50.5 -11t-53 -7.5t-47.5 -3.5q-92 0 -152.5 52.5t-60.5 177.5v1093q-31 6 -88 11.5t-113 5.5 q-70 0 -109.5 -19.5t-60 -57.5t-25.5 -92t-5 -122h211v-143h-211v-881h-164v881h-160z" />
|
||||||
|
<glyph horiz-adv-x="2048" />
|
||||||
|
<glyph horiz-adv-x="2048" />
|
||||||
|
<glyph unicode="
" horiz-adv-x="546" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="546" />
|
||||||
|
<glyph unicode="	" horiz-adv-x="546" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="546" />
|
||||||
|
<glyph unicode="!" horiz-adv-x="624" d="M225 94q0 55 32 87t85 32q55 0 88 -31.5t33 -87.5q0 -53 -33 -86t-88 -33q-53 0 -85 33t-32 86zM260 723v711h170v-711l-35 -361h-100z" />
|
||||||
|
<glyph unicode=""" horiz-adv-x="686" d="M184 1038v396h160l-63 -396h-97zM424 1038v396h160l-63 -396h-97z" />
|
||||||
|
<glyph unicode="#" d="M57 461l29 131h162l63 268h-151l28 131h154l78 324h141l-78 -324h215l78 324h142l-78 -324h157l-32 -131h-156l-64 -268h150l-33 -131h-147l-80 -342h-141l79 342h-215l-79 -342h-142l80 342h-160zM389 592h215l64 268h-215z" />
|
||||||
|
<glyph unicode="$" d="M156 41l55 149q41 -25 111.5 -45t173.5 -22v553q-61 31 -122 65.5t-108 82.5t-75.5 114t-28.5 156q0 147 83 241.5t251 116.5v186h139v-180q104 -4 170.5 -19.5t120.5 -39.5l-49 -144q-41 20 -98.5 36t-143.5 20v-506q63 -33 126.5 -71t114 -87t81 -114.5t30.5 -153.5 q0 -160 -89 -263.5t-263 -131.5v-189h-139v180q-113 2 -200 19.5t-140 46.5zM332 1104q0 -88 56 -143.5t140 -100.5v449q-109 -12 -152.5 -71.5t-43.5 -133.5zM602 127q94 14 154.5 73t60.5 165q0 49 -17.5 88t-46 69.5t-67.5 55t-84 47.5v-498z" />
|
||||||
|
<glyph unicode="%" horiz-adv-x="1583" d="M143 1110q0 92 24.5 157.5t66.5 108.5t100.5 62.5t126.5 19.5t126 -18.5t100 -59.5t66.5 -107.5t24.5 -162.5t-24.5 -162.5t-66.5 -107.5t-100.5 -59.5t-125.5 -18.5q-68 0 -126.5 18.5t-100.5 59.5t-66.5 107.5t-24.5 162.5zM252 55l1053 1405l100 -78l-1051 -1407z M295 1110q0 -123 44 -176t122 -53q39 0 69.5 11t52 36.5t32.5 69.5t11 112t-11 112t-32.5 69.5t-52.5 36.5t-69 11q-78 0 -122 -48t-44 -181zM874 350q0 92 24.5 157.5t66.5 108.5t100.5 62.5t126.5 19.5t126 -18.5t100 -59.5t66.5 -107.5t24.5 -162.5t-24.5 -162.5 t-66.5 -107.5t-100.5 -59.5t-125.5 -18.5q-68 0 -126.5 18.5t-100.5 59.5t-66.5 107.5t-24.5 162.5zM1026 350q0 -123 44 -176t122 -53q39 0 69.5 11t52 36.5t32.5 69.5t11 112t-11 112t-32.5 69.5t-52.5 36.5t-69 11q-78 0 -122 -48t-44 -181z" />
|
||||||
|
<glyph unicode="&" horiz-adv-x="1667" d="M242 383q0 82 28.5 156.5t77.5 138t111.5 117t130.5 94.5q-49 74 -85 147.5t-36 159.5q0 49 16.5 96t52 84t92 59.5t136.5 22.5q84 0 141.5 -21.5t92 -56t50 -77.5t15.5 -89q0 -86 -66.5 -177t-210.5 -175q33 -59 77 -121.5t93.5 -124t100.5 -122t102 -111.5 q23 25 45.5 62.5t44 79.5t39 87t31.5 86l127 -59q-12 -35 -34.5 -83t-50.5 -98t-56.5 -96.5t-53.5 -76.5q43 -41 78 -71t64.5 -51.5t57.5 -39t56 -33.5l-102 -115q-109 53 -248 191q-37 -37 -81 -71t-99 -60.5t-121.5 -43t-146.5 -16.5q-96 0 -181.5 27t-149 79t-101 128 t-37.5 174zM406 387q0 -63 26.5 -113.5t72.5 -84t105.5 -52t124.5 -18.5q51 0 99.5 13t91.5 33.5t78.5 47t58.5 55.5q-59 59 -116.5 129t-110 139.5t-96.5 134t-74 113.5q-55 -41 -102.5 -84t-83.5 -91t-55 -103t-19 -119zM629 1196q0 -61 25.5 -121.5t66.5 -120.5 q109 70 150.5 127.5t41.5 100.5q0 66 -31.5 106.5t-109.5 40.5q-74 0 -108.5 -37t-34.5 -96z" />
|
||||||
|
<glyph unicode="'" horiz-adv-x="446" d="M184 1038v396h160l-63 -396h-97z" />
|
||||||
|
<glyph unicode="(" horiz-adv-x="573" d="M123 498q0 113 18.5 237.5t59.5 250.5t107.5 247t162.5 225l98 -72q-82 -104 -136 -215.5t-87 -226.5t-46 -228.5t-13 -217.5q0 -98 15 -214t49 -231.5t88.5 -226.5t129.5 -201l-104 -76q-94 98 -159.5 216t-105.5 242t-58.5 250t-18.5 241z" />
|
||||||
|
<glyph unicode=")" horiz-adv-x="573" d="M4 -379q82 104 137.5 217t87 227.5t45 227.5t13.5 217q0 98 -16.5 213t-50.5 231.5t-87 227t-129 200.5l105 76q94 -98 159.5 -216t105.5 -241.5t58.5 -249.5t18.5 -241q0 -113 -18.5 -238t-59.5 -250.5t-107.5 -246.5t-163.5 -226z" />
|
||||||
|
<glyph unicode="*" horiz-adv-x="718" d="M82 1133v114h102l127 -24l-92 90l-53 94l100 57l51 -86l37 -114l43 116l49 82l99 -53l-53 -88l-95 -98l140 24h98v-114h-94l-131 24l94 -98l47 -80l-96 -57l-54 86l-47 125l-39 -119l-51 -86l-102 57l55 86l86 86l-119 -24h-102z" />
|
||||||
|
<glyph unicode="+" horiz-adv-x="1034" d="M82 618v148h360v369h148v-369h360v-148h-360v-368h-148v368h-360z" />
|
||||||
|
<glyph unicode="," horiz-adv-x="399" d="M86 -225q74 29 109.5 89t35.5 122q-18 -6 -34 -6q-41 0 -69 27.5t-28 80.5q0 49 33 80t84 31q63 0 103 -45t40 -131q0 -74 -20.5 -129.5t-53 -95.5t-71.5 -65.5t-78 -37.5z" />
|
||||||
|
<glyph unicode="-" horiz-adv-x="737" d="M121 514v152h495v-152h-495z" />
|
||||||
|
<glyph unicode="." horiz-adv-x="438" d="M100 94q0 55 32 87t85 32q55 0 88 -31.5t33 -87.5q0 -53 -33 -86t-88 -33q-53 0 -85 33t-32 86z" />
|
||||||
|
<glyph unicode="/" horiz-adv-x="724" d="M-76 -229l748 1687l129 -57l-748 -1688z" />
|
||||||
|
<glyph unicode="0" d="M88 717q0 369 120 555t349 186q248 0 359.5 -183t111.5 -558q0 -369 -120 -555.5t-351 -186.5q-244 0 -356.5 195t-112.5 547zM258 717q0 -133 17.5 -242.5t54.5 -188.5t93 -123t134 -44q156 0 228.5 144.5t72.5 453.5q0 131 -15.5 241.5t-51 190.5t-93 123t-141.5 43 q-154 0 -226.5 -145.5t-72.5 -452.5z" />
|
||||||
|
<glyph unicode="1" d="M143 1110l451 348h74v-1306h280v-152h-727v152h287v991l20 121l-82 -97l-225 -161z" />
|
||||||
|
<glyph unicode="2" d="M127 0v59q45 47 108.5 117t132 155t135 180t121 193.5t87 194.5t32.5 182q0 100 -57 167t-174 67q-78 0 -151.5 -32t-127.5 -73l-67 117q72 61 170 96t211 35q88 0 155.5 -25.5t114.5 -72.5t71.5 -111.5t24.5 -140.5q0 -109 -39.5 -222.5t-104 -228t-144.5 -224 t-160 -208.5l-100 -88v-8l131 23h446v-152h-815z" />
|
||||||
|
<glyph unicode="3" d="M180 27l43 145q47 -23 111.5 -38t144.5 -15q70 0 129.5 20.5t102.5 60.5t67.5 95t24.5 121q0 143 -85 212.5t-235 69.5h-151v60l295 454l94 91l-133 -21h-406v152h731v-60l-325 -489l-72 -60v-4l70 15q82 -2 151.5 -30t120.5 -80t80 -125t29 -165q0 -111 -39 -196.5 t-105.5 -144t-157 -89.5t-190.5 -31q-92 0 -165.5 14.5t-129.5 37.5z" />
|
||||||
|
<glyph unicode="4" d="M41 440v68l680 948h110v-872h242v-144h-242v-440h-159v440h-631zM227 567l144 17h301v446l20 168h-6l-72 -139l-288 -391z" />
|
||||||
|
<glyph unicode="5" d="M158 16l43 140q47 -18 101 -27.5t134 -9.5q141 0 233.5 82t92.5 237q0 150 -91 223.5t-251 73.5l-172 -10v709h639v-152h-486v-408l88 5q203 -2 320 -113t117 -317q0 -115 -39 -204t-105.5 -148.5t-156.5 -90.5t-193 -31q-92 0 -155.5 10.5t-118.5 30.5z" />
|
||||||
|
<glyph unicode="6" d="M123 481q0 203 52 374t144.5 298t218.5 206t273 99l35 -131q-115 -20 -209 -77.5t-165 -141.5t-116 -188.5t-61 -214.5q33 55 110.5 101t190.5 46q193 0 302.5 -110.5t109.5 -309.5q0 -94 -29 -177t-84 -145.5t-137 -98.5t-187 -36q-102 0 -184 33t-141.5 97.5t-91 158.5 t-31.5 217zM283 461q0 -63 17 -125t54 -110t91.5 -77.5t127.5 -29.5q59 0 107.5 22.5t83.5 61.5t54.5 94.5t19.5 118.5q0 145 -68 219t-209 74q-100 0 -173 -49.5t-101 -110.5q-4 -29 -4 -47.5v-40.5z" />
|
||||||
|
<glyph unicode="7" d="M125 1282v152h856v-56l-590 -1378h-166l514 1200l90 100l-120 -18h-584z" />
|
||||||
|
<glyph unicode="8" d="M139 342q0 129 67.5 224.5t211.5 172.5q-51 31 -95 65t-78 77t-53.5 96t-19.5 123q0 80 27.5 145.5t80 112.5t125 73.5t164.5 26.5q86 0 156 -24.5t118 -67.5t74.5 -102.5t26.5 -130.5q0 -117 -53 -206t-176 -175q53 -31 101 -68t84 -82t56.5 -101.5t20.5 -127.5 q0 -88 -28.5 -161t-84 -125t-135.5 -82t-182 -30q-98 0 -174 29t-128 78t-79 115.5t-27 144.5zM299 362q0 -49 16.5 -94t49 -77.5t81 -52t111.5 -19.5q51 0 98 15.5t83 45t57.5 75.5t21.5 107t-24.5 107.5t-64.5 84.5t-91 68.5t-107 59.5q-125 -70 -178 -156t-53 -164z M332 1104q0 -57 22.5 -101.5t60.5 -79t87 -64.5t102 -56q92 72 136 141.5t44 153.5q0 104 -64.5 160.5t-154.5 56.5q-55 0 -98 -18.5t-74 -47t-46 -66.5t-15 -79z" />
|
||||||
|
<glyph unicode="9" d="M106 999q0 98 29 182.5t84 146t138 96t194 34.5q209 0 325.5 -135t116.5 -381q0 -231 -52 -404t-144 -292t-218 -185.5t-274 -85.5l-37 131q119 18 214.5 69.5t164 129.5t111.5 177.5t59 215.5q-55 -66 -121.5 -91t-175.5 -25q-84 0 -158.5 27.5t-132 80.5t-90.5 131 t-33 178zM276 1016q0 -145 77 -218t202 -73q100 0 172 33t102 86q4 27 4.5 47t0.5 43q0 74 -17.5 142.5t-52.5 122.5t-91.5 85t-131.5 31q-125 0 -195 -79t-70 -220z" />
|
||||||
|
<glyph unicode=":" horiz-adv-x="448" d="M186 94q0 55 32 87t85 32q55 0 88 -31.5t33 -87.5q0 -53 -33 -86t-88 -33q-53 0 -85 33t-32 86zM186 920q0 55 32 86.5t85 31.5q55 0 88 -31.5t33 -86.5q0 -53 -33 -86t-88 -33q-53 0 -85 33t-32 86z" />
|
||||||
|
<glyph unicode=";" horiz-adv-x="524" d="M168 -225q74 29 109.5 89t35.5 122q-18 -6 -34 -6q-41 0 -69 27.5t-28 80.5q0 49 33 80t84 31q63 0 103 -45t40 -131q0 -74 -20.5 -129.5t-53 -95.5t-71.5 -65.5t-78 -37.5zM197 920q0 55 31.5 86.5t84.5 31.5q55 0 88 -31.5t33 -86.5q0 -53 -32.5 -86t-88.5 -33 q-53 0 -84.5 33t-31.5 86z" />
|
||||||
|
<glyph unicode="<" horiz-adv-x="1034" d="M86 625v59l774 473l78 -127l-485 -297l-187 -78l185 -65l497 -295l-78 -123z" />
|
||||||
|
<glyph unicode="=" horiz-adv-x="1034" d="M82 449v147h868v-147h-868zM82 788v148h868v-148h-868z" />
|
||||||
|
<glyph unicode=">" horiz-adv-x="1034" d="M86 1032l78 125l784 -452v-60l-774 -473l-78 125l486 297l186 78l-184 65z" />
|
||||||
|
<glyph unicode="?" horiz-adv-x="892" d="M76 1356q78 47 164 74.5t213 27.5q90 0 158.5 -25.5t114.5 -70.5t68.5 -106.5t22.5 -131.5q0 -92 -27.5 -160.5t-69.5 -125t-90 -105.5t-90 -103.5t-70 -117.5t-28 -150h-135q-2 10 -2 22.5v23.5q0 86 25.5 151.5t63.5 119.5t82 101t82 95.5t63.5 102.5t25.5 124 q0 94 -54 153.5t-181 59.5q-74 0 -150 -25.5t-131 -60.5zM266 94q0 55 32 87t85 32q55 0 88 -31.5t33 -87.5q0 -53 -33 -86t-88 -33q-53 0 -85 33t-32 86z" />
|
||||||
|
<glyph unicode="@" horiz-adv-x="2179" d="M178 483q0 223 77 403.5t208 307.5t305 195.5t369 68.5q184 0 341.5 -54t273.5 -155.5t182.5 -248t66.5 -332.5q0 -131 -45 -251t-122 -210t-179.5 -144.5t-216.5 -54.5q-86 0 -137.5 37t-51.5 137q0 18 2 40t6 46h-8q-29 -47 -67.5 -93t-86.5 -83t-102.5 -60.5 t-113.5 -23.5q-49 0 -94.5 21.5t-78 62.5t-52 97.5t-19.5 127.5q0 131 43 258t115.5 225.5t170 159t205.5 60.5q76 0 121 -22.5t88 -55.5l70 64h70l-105 -588q-10 -53 -15 -95t-5 -75q0 -51 17 -74.5t60 -23.5q70 0 138.5 36.5t122 104t87 163t33.5 214.5q0 158 -53 278.5 t-149.5 203.5t-229.5 126t-293 43q-166 0 -312 -61.5t-253.5 -170t-170 -260t-62.5 -329.5q0 -182 56 -325.5t160.5 -242t250 -149.5t323.5 -51q59 0 135 13t138 44l41 -131q-92 -39 -170 -52.5t-168 -13.5q-190 0 -357.5 57.5t-291 170t-195.5 279.5t-72 386zM795 344 q0 -80 32.5 -136t118.5 -56q41 0 85 26.5t87 72.5t82 103.5t70 116.5l61 334q-35 41 -69.5 56.5t-87.5 15.5q-80 0 -150 -48.5t-120 -125t-79.5 -172t-29.5 -187.5z" />
|
||||||
|
<glyph unicode="A" horiz-adv-x="1198" d="M16 0l543 1456h78l545 -1456h-178l-148 397h-528l-144 -397h-168zM383 545h422l-160 436l-51 217h-2l-51 -221z" />
|
||||||
|
<glyph unicode="B" horiz-adv-x="1196" d="M174 10v1411q76 12 176.5 20.5t218.5 8.5q80 0 163 -13.5t150.5 -51t111.5 -105.5t44 -174q0 -51 -16 -104.5t-49 -99.5t-84 -81t-121 -53v-8q61 -10 117.5 -35t99.5 -68t69.5 -104t26.5 -145q0 -111 -46 -192t-120.5 -132t-171 -75.5t-196.5 -24.5h-82t-98.5 3t-102.5 8 t-90 15zM344 145q14 -4 41 -6t57.5 -4t63 -3t57.5 -1q66 0 127.5 15.5t108.5 49t74.5 83t27.5 116.5q0 84 -33.5 135.5t-88 80t-122 38.5t-135.5 10h-178v-514zM344 803h107q35 0 84 2t81 6q49 16 92.5 39.5t77 55.5t53 74t19.5 91q0 68 -25.5 112t-68.5 70.5t-98.5 38 t-112.5 11.5q-68 0 -124 -3.5t-85 -9.5v-487z" />
|
||||||
|
<glyph unicode="C" horiz-adv-x="1169" d="M115 717q0 201 54 341t143 229t200 130t225 41q123 0 201 -13t133 -36l-41 -149q-98 47 -280 47q-84 0 -166 -31t-146.5 -100.5t-103.5 -182t-39 -276.5q0 -147 37 -258t101.5 -184.5t151.5 -110.5t189 -37q92 0 161 18.5t116 47.5l41 -134q-61 -47 -155.5 -65.5 t-201.5 -18.5q-129 0 -241.5 44t-196.5 134.5t-133 230.5t-49 333z" />
|
||||||
|
<glyph unicode="D" horiz-adv-x="1339" d="M174 -2v1436q39 6 87 9t100.5 4t102.5 2t93 1q172 0 298 -53.5t208 -148.5t122 -228t40 -293q0 -145 -38 -279.5t-120 -238t-213 -165.5t-317 -62q-33 0 -85.5 1t-107.5 4t-102 5t-68 6zM344 141q10 -2 39 -3t59.5 -2t59 -2t39.5 -1q143 0 240.5 49t155.5 132t82.5 190.5 t24.5 222.5q0 100 -22.5 201.5t-77.5 183.5t-148.5 134t-234.5 52h-58.5t-62 -2t-56.5 -4t-40 -4v-1147z" />
|
||||||
|
<glyph unicode="E" horiz-adv-x="1097" d="M174 0v1434h780v-152h-610v-469h559v-151h-559v-510h621v-152h-791z" />
|
||||||
|
<glyph unicode="F" horiz-adv-x="1058" d="M174 0v1434h780v-152h-610v-489h569v-152h-569v-641h-170z" />
|
||||||
|
<glyph unicode="G" horiz-adv-x="1253" d="M115 717q0 199 57 340t149.5 230t207 130t229.5 41q123 0 202.5 -13t135.5 -36l-43 -149q-98 47 -281 47q-86 0 -171 -30t-152.5 -99.5t-110.5 -182t-43 -278.5q0 -152 35 -262.5t97 -183t150.5 -108.5t192.5 -36q131 0 223 51v400l-336 40v97h482v-631 q-33 -25 -79 -45.5t-98.5 -34.5t-108.5 -21.5t-110 -7.5q-137 0 -251.5 44t-198.5 135.5t-131 231.5t-47 331z" />
|
||||||
|
<glyph unicode="H" horiz-adv-x="1376" d="M174 0v1434h170v-625h688v625h170v-1434h-170v657h-688v-657h-170z" />
|
||||||
|
<glyph unicode="I" horiz-adv-x="595" d="M213 0v1434h170v-1434h-170z" />
|
||||||
|
<glyph unicode="J" horiz-adv-x="595" d="M-70 12l33 146q57 -27 125 -27q86 0 113.5 60.5t27.5 164.5v1078h170v-1119q0 -164 -72.5 -249.5t-220.5 -85.5q-16 0 -40.5 2t-49 6t-48 10t-38.5 14z" />
|
||||||
|
<glyph unicode="K" horiz-adv-x="1249" d="M174 0v1434h170v-668l92 29l482 639h196l-479 -617l-86 -67l104 -82l525 -668h-215l-523 664h-96v-664h-170z" />
|
||||||
|
<glyph unicode="L" horiz-adv-x="1058" d="M174 0v1434h170v-1282h678v-152h-848z" />
|
||||||
|
<glyph unicode="M" horiz-adv-x="1619" d="M174 0v1434h127l449 -734l67 -159h4l64 164l428 729h133v-1434h-170v963l20 215h-10l-78 -197l-372 -647h-52l-395 649l-74 195h-10l29 -213v-965h-160z" />
|
||||||
|
<glyph unicode="N" horiz-adv-x="1378" d="M174 0v1456h90l686 -956l107 -197h10l-23 197v934h160v-1457h-90l-682 961l-110 207h-9l21 -207v-938h-160z" />
|
||||||
|
<glyph unicode="O" horiz-adv-x="1400" d="M115 717q0 358 151.5 549.5t431.5 191.5q152 0 262.5 -53t183.5 -150.5t107.5 -233.5t34.5 -304q0 -358 -152.5 -550t-435.5 -192q-150 0 -259 53.5t-182 150.5t-107.5 233.5t-34.5 304.5zM295 717q0 -119 23.5 -225.5t72.5 -187.5t126 -129t181 -48q190 0 299 144.5 t109 445.5q0 117 -23.5 224.5t-74 188t-127 129t-183.5 48.5q-188 0 -295.5 -144.5t-107.5 -445.5z" />
|
||||||
|
<glyph unicode="P" horiz-adv-x="1144" d="M174 0v1419q78 18 168 24.5t178 6.5q94 0 191.5 -18.5t177.5 -67.5t130 -135t50 -219q0 -131 -47 -221.5t-125 -146.5t-178.5 -80.5t-206.5 -24.5h-33.5t-49.5 1t-50.5 3t-34.5 4v-545h-170zM344 696q10 -4 32.5 -5t47.5 -2t47.5 -1h32.5q70 0 138.5 13.5t123.5 48t89 98 t34 162.5q0 84 -32 140t-84 90t-117.5 48.5t-131.5 14.5q-53 0 -102 -2.5t-78 -10.5v-594z" />
|
||||||
|
<glyph unicode="Q" horiz-adv-x="1400" d="M115 717q0 358 151.5 549.5t431.5 191.5q152 0 262.5 -53t183.5 -150.5t107.5 -233.5t34.5 -304q0 -358 -152.5 -550t-435.5 -192q-150 0 -259 53.5t-182 150.5t-107.5 233.5t-34.5 304.5zM295 717q0 -119 23.5 -225.5t72.5 -187.5t126 -129t181 -48q190 0 299 144.5 t109 445.5q0 117 -23.5 224.5t-74 188t-127 129t-183.5 48.5q-188 0 -295.5 -144.5t-107.5 -445.5zM434 -100q29 6 55.5 10t55.5 4q86 0 171 -21.5t173 -47t180 -47t195 -21.5q90 0 178 20v-147q-49 -14 -96.5 -19.5t-94.5 -5.5q-102 0 -199.5 21.5t-188.5 47t-175 47 t-160 21.5q-49 0 -94 -12v150z" />
|
||||||
|
<glyph unicode="R" horiz-adv-x="1218" d="M174 0v1419q78 14 179.5 22.5t185.5 8.5q94 0 179 -20.5t149.5 -67.5t103.5 -123t39 -184q0 -168 -92.5 -272.5t-233.5 -139.5l98 -76l357 -567h-199l-395 618l-201 31v-649h-170zM344 762h160q141 0 233 69.5t92 217.5q0 111 -75.5 182.5t-210.5 71.5h-55.5t-55 -2.5 t-50.5 -4.5t-38 -6v-528z" />
|
||||||
|
<glyph unicode="S" horiz-adv-x="1087" d="M94 51l58 154q47 -27 139 -52.5t207 -25.5q68 0 127 13.5t102 43t68.5 75t25.5 106.5q0 86 -51 140t-128 96t-167 79t-167 89t-128 129t-51 196q0 168 116.5 266t332.5 98q125 0 227 -18.5t160 -46.5l-52 -150q-47 23 -138 43.5t-206 20.5q-135 0 -202.5 -60.5 t-67.5 -142.5q0 -80 51 -133t128 -95t167 -83t167 -95.5t128 -130t51 -188.5q0 -92 -32.5 -166t-96 -127t-154 -82t-204.5 -29q-154 0 -254 24t-156 52z" />
|
||||||
|
<glyph unicode="T" horiz-adv-x="1136" d="M37 1282v152h1063v-152h-447v-1282h-170v1282h-446z" />
|
||||||
|
<glyph unicode="U" horiz-adv-x="1335" d="M174 444v990h170v-910q0 -109 21.5 -183.5t64.5 -120.5t107.5 -66.5t150.5 -20.5q166 0 237.5 91t71.5 300v910h164v-957q0 -129 -33.5 -223t-96 -154.5t-150.5 -89t-195 -28.5q-254 0 -383 114.5t-129 347.5z" />
|
||||||
|
<glyph unicode="V" horiz-adv-x="1163" d="M-4 1434h186l365 -985l49 -218h2l53 222l346 981h170l-542 -1457h-76z" />
|
||||||
|
<glyph unicode="W" horiz-adv-x="1695" d="M16 1434h181l258 -961l32 -237h2l35 241l295 957h82l297 -961l35 -237h2l37 241l241 957h166l-399 -1457h-94l-291 961l-37 217h-10l-37 -219l-291 -959h-94z" />
|
||||||
|
<glyph unicode="X" horiz-adv-x="1265" d="M53 0l477 729l-436 705h205l291 -486l51 -117l49 117l307 486h189l-451 -691l471 -743h-198l-324 514l-55 123l-54 -123l-331 -514h-191z" />
|
||||||
|
<glyph unicode="Y" horiz-adv-x="1142" d="M16 1434h199l336 -627l35 -125h2l37 129l321 623h182l-469 -863v-571h-170v569z" />
|
||||||
|
<glyph unicode="Z" d="M78 0v154l723 1046l86 82h-809v152h962v-154l-727 -1053l-86 -75h813v-152h-962z" />
|
||||||
|
<glyph unicode="[" horiz-adv-x="622" d="M174 -471v1905h371v-144h-211v-1618h211v-143h-371z" />
|
||||||
|
<glyph unicode="\" horiz-adv-x="778" d="M-76 1401l137 57l756 -1685l-135 -60z" />
|
||||||
|
<glyph unicode="]" horiz-adv-x="622" d="M78 -328h213v1618h-213v144h373v-1905h-373v143z" />
|
||||||
|
<glyph unicode="^" horiz-adv-x="1024" d="M98 891l381 565h60l346 -565h-168l-164 276l-47 142l-64 -144l-188 -274h-156z" />
|
||||||
|
<glyph unicode="_" horiz-adv-x="835" d="M0 -276h836v-144h-836v144z" />
|
||||||
|
<glyph unicode="`" horiz-adv-x="573" d="M123 1432v43h194l134 -306h-93z" />
|
||||||
|
<glyph unicode="a" horiz-adv-x="1015" d="M80 274q0 90 37 150.5t103.5 96.5t159.5 51.5t206 15.5h56.5t55.5 -4q6 61 7 110q0 113 -45.5 158t-163.5 45q-35 0 -75 -5t-82 -14.5t-80 -22.5t-66 -30l-52 123q78 47 181.5 69.5t216.5 22.5q106 0 170.5 -28.5t98.5 -74.5t45 -101.5t11 -110.5q0 -123 -6 -239.5 t-6 -221.5q0 -76 6 -143.5t23 -124.5h-121l-43 143h-10q-18 -29 -46 -56.5t-67 -49t-90 -35.5t-117 -14t-122 20.5t-97 58t-64.5 91t-23.5 120.5zM250 291q0 -72 51 -118t131 -46q57 0 102.5 15.5t78 39t54 52t31.5 55.5v170q-29 2 -58.5 3t-57.5 1q-63 0 -124 -7 t-107 -26.5t-73.5 -53.5t-27.5 -85z" />
|
||||||
|
<glyph unicode="b" horiz-adv-x="1105" d="M158 59v1375h164v-510h8q47 59 119.5 92t158.5 33q199 0 298.5 -127t99.5 -394q0 -268 -131.5 -407t-368.5 -139q-115 0 -208 24.5t-140 52.5zM322 170q39 -23 94 -34t114 -11q139 0 222.5 98.5t83.5 306.5q0 80 -14.5 150t-45.5 119t-78.5 77.5t-117.5 28.5 q-102 0 -166 -57t-92 -162v-516z" />
|
||||||
|
<glyph unicode="c" horiz-adv-x="923" d="M100 512q0 260 115 398.5t330 138.5q98 0 166.5 -15.5t124.5 -44.5l-48 -141q-47 27 -104 42t-123 15q-291 0 -291 -393q0 -78 15.5 -148.5t51.5 -125t94 -87t144 -32.5q74 0 132.5 22.5t95.5 51.5l53 -125q-61 -45 -145 -69t-176 -24q-119 0 -201 38t-134.5 109t-76 170 t-23.5 220z" />
|
||||||
|
<glyph unicode="d" horiz-adv-x="1101" d="M100 508q0 262 124 398t341 136q76 0 120 -8t95 -26v426h164v-1082q0 -104 2 -189t19 -167h-111l-41 145h-8q-41 -72 -119 -119t-182 -47q-205 0 -304.5 129t-99.5 404zM270 508q0 -84 13.5 -155.5t44 -123t80.5 -81t122 -29.5q104 0 166 54t84 165v508q-37 29 -84 41 t-125 12q-141 0 -221 -93t-80 -298z" />
|
||||||
|
<glyph unicode="e" horiz-adv-x="1040" d="M100 512q0 262 117 399.5t334 137.5q70 0 139.5 -15.5t124.5 -58.5t90 -122t35 -208q0 -68 -12 -149h-658q0 -90 18.5 -160t57.5 -118t101.5 -73.5t152.5 -25.5q70 0 139.5 24.5t104.5 57.5l61 -119q-61 -49 -154.5 -78t-197.5 -29q-117 0 -203 38t-141 109t-82 169 t-27 221zM272 625h508q0 156 -59 218t-168 62q-121 0 -193.5 -63.5t-87.5 -216.5z" />
|
||||||
|
<glyph unicode="f" horiz-adv-x="653" d="M45 881v143h160v57q0 94 15.5 164t50 114t90 65.5t137.5 21.5q66 0 116 -8t105 -31l-37 -137q-47 20 -89 26.5t-79 6.5q-53 0 -83 -16.5t-43 -48.5t-16 -78t-3 -107v-29h272v-143h-272v-881h-164v881h-160z" />
|
||||||
|
<glyph unicode="g" horiz-adv-x="1099" d="M100 508q0 262 125 398t369 136q117 0 200 -18t148 -43v-1028q0 -199 -105.5 -293t-312.5 -94q-123 0 -197.5 15.5t-127.5 39.5l43 139q47 -18 104 -34.5t150 -16.5q86 0 140 15.5t87 51.5t45 92t12 134v98h-8q-41 -59 -104.5 -91t-165.5 -32q-207 0 -304.5 129.5 t-97.5 401.5zM270 510q0 -86 14.5 -157.5t45 -123t79.5 -80t121 -28.5q104 0 164 52t84 163v524q-82 39 -209 39q-139 0 -219 -94t-80 -295z" />
|
||||||
|
<glyph unicode="h" horiz-adv-x="1120" d="M158 0v1434h164v-525h8q53 63 127.5 101.5t185.5 38.5q86 0 149.5 -19.5t105.5 -69t61.5 -132.5t19.5 -210v-618h-164v584q0 80 -9 140t-33.5 100t-66.5 60.5t-110 20.5q-96 0 -174 -62.5t-100 -160.5v-682h-164z" />
|
||||||
|
<glyph unicode="i" horiz-adv-x="548" d="M158 1335q0 47 31.5 81t80.5 34t84 -34t35 -81t-35 -77.5t-84 -30.5t-80.5 30.5t-31.5 77.5zM193 0v1024h163v-1024h-163z" />
|
||||||
|
<glyph unicode="j" horiz-adv-x="546" d="M18 -291q57 0 91 17.5t52.5 54.5t23.5 93t5 132v1018h164v-1079q0 -190 -65.5 -284.5t-208.5 -94.5q-16 0 -30.5 1t-31.5 3v139zM156 1335q0 47 31.5 81t80.5 34t84 -34t35 -81t-35 -77.5t-84 -30.5t-80.5 30.5t-31.5 77.5z" />
|
||||||
|
<glyph unicode="k" horiz-adv-x="980" d="M158 0v1434h164v-873l84 29l317 434h190l-313 -412l-84 -67l102 -82l343 -463h-203l-342 461h-94v-461h-164z" />
|
||||||
|
<glyph unicode="l" horiz-adv-x="598" d="M176 205v1229h164v-1182q0 -72 24.5 -102.5t69.5 -30.5q27 0 57.5 4t69.5 18l19 -129q-33 -16 -91.5 -26.5t-101.5 -10.5q-92 0 -151.5 52.5t-59.5 177.5z" />
|
||||||
|
<glyph unicode="m" horiz-adv-x="1662" d="M158 0v1024h114l31 -125h8q55 66 128 108t190 42q98 0 160.5 -38t97.5 -132q47 80 130 125t187 45q86 0 145.5 -19.5t98.5 -69t56.5 -133.5t17.5 -213v-614h-164v616q0 74 -7.5 128.5t-29 90t-59 53t-99.5 17.5q-102 0 -159.5 -57t-81.5 -164v-684h-164v580 q0 82 -7.5 142t-28 101t-58 61.5t-99.5 20.5q-94 0 -156.5 -57t-86.5 -143v-705h-164z" />
|
||||||
|
<glyph unicode="n" horiz-adv-x="1120" d="M158 0v1024h114l31 -125h8q49 66 132 108t198 42q84 0 147.5 -19.5t105.5 -69t63.5 -132.5t21.5 -210v-618h-164v584q0 160 -46 240.5t-169 80.5q-109 0 -179.5 -58.5t-98.5 -146.5v-700h-164z" />
|
||||||
|
<glyph unicode="o" horiz-adv-x="1097" d="M100 512q0 260 116 398.5t333 138.5q115 0 200 -38t140 -109t81.5 -170t26.5 -220q0 -260 -115.5 -398.5t-332.5 -138.5q-115 0 -200 38t-140 109t-82 170t-27 220zM270 512q0 -78 15.5 -149.5t48.5 -125t86 -86t129 -32.5h3q275 0 275 390q0 83 -15 154.5t-48 125 t-86 85t-129 31.5h-3q-276 0 -276 -393z" />
|
||||||
|
<glyph unicode="p" horiz-adv-x="1107" d="M158 -410v1434h112l31 -123h8q47 72 122 110t171 38q205 0 305.5 -121t100.5 -396q0 -129 -34 -232t-95.5 -175t-148.5 -111t-193 -39q-76 0 -120 9.5t-95 31.5v-426h-164zM322 178q37 -29 84 -44t124 -15q141 0 224.5 105.5t83.5 310.5q0 84 -14.5 152.5t-46.5 116.5 t-82 74.5t-124 26.5q-104 0 -164.5 -54t-84.5 -165v-508z" />
|
||||||
|
<glyph unicode="q" horiz-adv-x="1099" d="M100 508q0 264 127 399t371 135q109 0 204 -20.5t140 -42.5v-1389h-164v512h-8q-41 -61 -103.5 -94t-164.5 -33q-205 0 -303.5 130.5t-98.5 402.5zM270 510q0 -86 14.5 -158.5t45 -124t79.5 -80t121 -28.5q104 0 164 53t84 164v524q-76 39 -209 39q-141 0 -220 -95 t-79 -294z" />
|
||||||
|
<glyph unicode="r" horiz-adv-x="696" d="M158 0v1024h114l31 -125h8q39 70 93.5 107.5t138.5 37.5q59 0 133 -20l-35 -158q-61 20 -117 21q-88 0 -139 -48t-63 -122v-717h-164z" />
|
||||||
|
<glyph unicode="s" horiz-adv-x="862" d="M80 51l49 139q47 -27 123 -49t154 -22q88 0 145 35t57 125q0 61 -36.5 96t-91 58.5t-119 45t-119 55t-91 87t-36.5 143.5q0 147 84 216t233 69q111 0 185.5 -19.5t130.5 -46.5l-39 -135q-47 23 -114 40t-142 17q-90 0 -132 -30.5t-42 -106.5q0 -53 36.5 -83t91 -53.5 t119 -46t118.5 -59.5t91 -93t37 -148q0 -66 -21.5 -123.5t-66.5 -98t-111.5 -64.5t-156.5 -24q-117 0 -199 22.5t-137 53.5z" />
|
||||||
|
<glyph unicode="t" horiz-adv-x="694" d="M23 881v143h159v203l164 47v-250h279v-143h-279v-568q0 -106 26.5 -150t90.5 -44q53 0 90 11t82 30l37 -125q-55 -27 -121 -43.5t-141 -16.5q-125 0 -176.5 71t-51.5 237v598h-159z" />
|
||||||
|
<glyph unicode="u" horiz-adv-x="1103" d="M141 406v618h164v-584q0 -80 9.5 -140t32 -100t61 -60.5t98.5 -20.5q55 0 98 17.5t77 48t59.5 70.5t41.5 85v684h164v-733q0 -74 5 -153t18 -138h-113l-41 162h-10q-47 -80 -127 -133.5t-203 -53.5q-82 0 -144.5 19.5t-104.5 69t-63.5 132.5t-21.5 210z" />
|
||||||
|
<glyph unicode="v" horiz-adv-x="987" d="M18 1024h189l246 -600l57 -195h2l51 199l230 596h176l-437 -1047h-69z" />
|
||||||
|
<glyph unicode="w" horiz-adv-x="1505" d="M16 1024h179l202 -596l35 -199h2l49 203l219 592h119l236 -598l51 -197h4l39 201l182 594h156l-344 -1047h-80l-268 676l-39 168h-6l-41 -170l-258 -674h-80z" />
|
||||||
|
<glyph unicode="x" horiz-adv-x="1054" d="M57 0l369 524l-344 500h201l194 -283l58 -116l59 116l199 283h184l-346 -492l366 -532h-194l-217 311l-62 123l-63 -123l-221 -311h-183z" />
|
||||||
|
<glyph unicode="y" horiz-adv-x="954" d="M25 1024h188l246 -664l57 -196h10l45 198l199 662h166l-303 -920q-35 -100 -69 -194t-74.5 -168t-92 -118t-118.5 -44q-74 0 -121 21l28 141q27 -10 52 -10q57 0 110 60.5t88 207.5z" />
|
||||||
|
<glyph unicode="z" horiz-adv-x="915" d="M86 0v143l473 652l86 86h-559v143h729v-143l-477 -658l-84 -80h561v-143h-729z" />
|
||||||
|
<glyph unicode="{" horiz-adv-x="708" d="M117 410v143q78 0 121 41t43 131v496q0 96 48 155.5t146 59.5h174v-144h-102q-55 0 -81 -27.5t-26 -93.5v-485q0 -90 -43 -137t-100 -57v-13q55 -8 99 -62.5t44 -140.5v-483q0 -63 24.5 -92t84.5 -29h100v-143h-174q-92 0 -143 54.5t-51 158.5v487q0 104 -43 142.5 t-121 38.5z" />
|
||||||
|
<glyph unicode="|" horiz-adv-x="487" d="M174 -266v1700h139v-1700h-139z" />
|
||||||
|
<glyph unicode="}" horiz-adv-x="708" d="M113 -328h102q55 0 81 28t26 93v486q0 90 42 137t99 57v12q-55 8 -98 62.5t-43 140.5v483q0 63 -25 92t-82 29h-102v144h176q90 0 141 -54.5t51 -158.5v-488q0 -104 43 -142t121 -38v-143q-78 0 -121 -41t-43 -131v-496q0 -96 -48 -155.5t-146 -59.5h-174v143z" />
|
||||||
|
<glyph unicode="~" horiz-adv-x="1034" d="M63 739q88 68 160 94.5t131 26.5q57 0 106.5 -17.5t94.5 -39t88 -38.5t90 -17q39 0 80 16t88 57l70 -125q-78 -53 -140.5 -74.5t-113.5 -21.5q-55 0 -101.5 17.5t-88.5 39t-84 39t-91 17.5q-47 0 -100 -21.5t-119 -75.5z" />
|
||||||
|
<glyph unicode="¡" horiz-adv-x="622" d="M152 928q0 55 31.5 87t84.5 32q55 0 88 -32t33 -87q0 -53 -32.5 -86t-88.5 -33q-53 0 -84.5 33t-31.5 86zM190 301l35 361h101l34 -361v-711h-170v711z" />
|
||||||
|
<glyph unicode="¢" d="M178 512q0 236 97.5 372t277.5 158v187h145v-182q72 -4 127.5 -19.5t100.5 -38.5l-47 -139q-41 20 -91.5 34.5t-103.5 18.5v-784q66 4 119 25.5t88 48.5l53 -125q-49 -35 -111.5 -56.5t-134.5 -29.5v-187h-145v185q-102 10 -173 52t-116 110.5t-65.5 162.5t-20.5 207z M348 512q0 -68 11.5 -130.5t38 -114.5t69.5 -89t106 -51v772q-225 -43 -225 -387z" />
|
||||||
|
<glyph unicode="£" d="M86 0v147q66 0 112 24t75.5 61.5t44 86t14.5 97.5q0 68 -13.5 122t-33.5 103h-199v143h135q-25 53 -41 117t-16 150q0 201 114.5 304t313.5 103q125 0 217 -18.5t152 -46.5l-54 -146q-47 23 -126 41.5t-191 18.5q-123 0 -189.5 -66.5t-66.5 -179.5q0 -86 20.5 -151.5 t48.5 -125.5h330v-143h-268q16 -47 26.5 -98t10.5 -113q0 -61 -18.5 -125.5t-55.5 -105.5l-80 -68v-8l127 29h524v-152h-913z" />
|
||||||
|
<glyph unicode="¤" d="M43 293l158 160l69 45q-63 86 -63 209q0 59 17.5 112t45.5 99l-69 43l-158 159l100 101l160 -158l43 -72q86 68 211 68q121 0 211 -68l45 72l160 158l100 -101l-158 -159l-71 -46q66 -88 65 -208q0 -123 -65 -211l71 -43l158 -160l-100 -98l-160 157l-43 68 q-88 -63 -213 -64q-127 0 -211 64l-43 -68l-160 -157zM348 707q0 -92 58.5 -153.5t150.5 -61.5t151.5 61t59.5 154q0 92 -59.5 154.5t-151.5 62.5t-150.5 -62.5t-58.5 -154.5z" />
|
||||||
|
<glyph unicode="¥" d="M4 1434h199l336 -627l34 -125h2l37 129l322 623h182l-416 -762h193v-123h-248v-129h248v-123h-248v-297h-170v297h-248v123h248v129h-248v123h193z" />
|
||||||
|
<glyph unicode="¦" horiz-adv-x="487" d="M174 -266v688h139v-688h-139zM174 745v689h139v-689h-139z" />
|
||||||
|
<glyph unicode="§" horiz-adv-x="1017" d="M117 723q0 63 31.5 123.5t84.5 107.5l84 29q-53 33 -88.5 83t-35.5 134q0 115 84.5 186.5t236.5 71.5q111 0 187.5 -18.5t132.5 -44.5l-39 -138q-49 23 -117 40.5t-141 17.5q-92 0 -136.5 -33t-44.5 -88q0 -53 40 -83t101.5 -52.5t131 -45t131 -58t101.5 -94t40 -150.5 q0 -63 -30.5 -123t-84.5 -107l-92 -28q55 -33 93 -84.5t38 -135.5q0 -63 -24.5 -111t-68.5 -81t-103.5 -49.5t-126.5 -16.5q-115 0 -188.5 19.5t-131.5 48.5l41 133q47 -23 113.5 -40t144.5 -17q86 0 133.5 27.5t47.5 93.5q0 53 -40 83.5t-101.5 53t-131.5 45t-131 58.5 t-101 93.5t-40 149.5zM281 727q0 -51 26.5 -84t68.5 -56.5t96 -40t110 -36.5q29 12 56.5 32.5t50 46t35.5 55.5t13 63q0 51 -26.5 83.5t-70.5 56t-99.5 41t-110.5 38.5q-59 -27 -104 -76t-45 -123z" />
|
||||||
|
<glyph unicode="¨" horiz-adv-x="841" d="M123 1337q0 47 27.5 76t72.5 29t73 -29t28 -76q0 -43 -28 -71.5t-73 -28.5t-72.5 28.5t-27.5 71.5zM516 1337q0 47 27.5 76t72.5 29q47 0 75 -29t28 -76q0 -43 -27.5 -71.5t-75.5 -28.5q-45 0 -72.5 28.5t-27.5 71.5z" />
|
||||||
|
<glyph unicode="©" horiz-adv-x="1650" d="M104 594q0 170 57.5 304t156 226.5t229.5 141.5t278 49t278.5 -49t230 -141.5t155.5 -226.5t57 -304t-57 -304t-155.5 -226.5t-229.5 -141.5t-279 -49q-164 0 -297 49t-227 141.5t-145.5 226.5t-51.5 304zM248 594q0 -141 45 -251t123 -183.5t183.5 -112.5t225.5 -39 q121 0 226.5 39t183.5 112.5t123 183.5t45 251t-45 250.5t-123 183.5t-183.5 113t-226.5 39t-226 -39t-183 -113t-123 -183.5t-45 -250.5zM481 594q0 186 93.5 287.5t246.5 101.5q37 0 67 -4t55.5 -11t50 -17.5t55.5 -22.5l-54 -125q-45 23 -86 31t-69 8q-86 0 -140.5 -53.5 t-54.5 -194.5q0 -119 53.5 -183.5t157.5 -66.5q96 0 164 37l43 -121q-47 -27 -105.5 -41t-136.5 -14q-166 0 -253 104.5t-87 284.5z" />
|
||||||
|
<glyph unicode="ª" horiz-adv-x="790" d="M98 965q0 63 31 106t83 69.5t123 39t152 12.5q14 0 27.5 -1t28.5 -1q2 12 2 23.5v21.5q0 55 -24.5 77.5t-94.5 22.5q-82 0 -149.5 -15t-106.5 -36l-31 102q51 27 135 45.5t187 18.5q127 0 174 -53.5t47 -153.5q0 -78 -3 -149.5t-3 -137.5q0 -49 3 -94t13 -84h-112l-27 94 h-8q-27 -35 -76 -68.5t-137 -33.5q-106 0 -170 52t-64 143zM242 975q0 -41 29.5 -65.5t82.5 -24.5q43 0 75 10t54.5 27.5t37 37t22.5 37.5v86q-23 2 -43.5 2h-42.5q-43 0 -82 -4t-69 -16t-47 -33.5t-17 -56.5z" />
|
||||||
|
<glyph unicode="«" horiz-adv-x="978" d="M80 530l328 471l110 -88l-201 -297l-98 -84l98 -73l213 -291l-110 -90zM455 530l323 467l109 -86l-199 -295l-98 -84l98 -73l211 -289l-106 -88z" />
|
||||||
|
<glyph unicode="¬" horiz-adv-x="1034" d="M84 655v148h868v-393h-147v245h-721z" />
|
||||||
|
<glyph unicode="­" horiz-adv-x="737" d="M121 514v152h495v-152h-495z" />
|
||||||
|
<glyph unicode="®" horiz-adv-x="1433" d="M174 924q0 131 43 232t118 170t173 104.5t209 35.5q113 0 212 -35.5t173 -104.5t116 -170t42 -232t-43 -232.5t-118 -170t-173.5 -104.5t-208.5 -36q-115 0 -213 36t-172 104.5t-116 170t-42 232.5zM303 924q0 -106 33 -185.5t89 -131.5t132 -78.5t160 -26.5 q88 0 163.5 25.5t131 77.5t87 131t31.5 188q0 106 -32.5 185t-89 131t-131 79t-160.5 27q-90 0 -166 -27t-131 -79t-86 -131t-31 -185zM506 659v531q33 10 92 15t113 5q86 0 147.5 -35.5t61.5 -123.5q0 -66 -42 -101t-104 -39l57 -28l152 -224h-125l-147 213l-99 31v-244 h-106zM612 965h70q59 0 92 18t33 64q0 71 -119 71q-23 0 -43 -1t-33 -7v-145z" />
|
||||||
|
<glyph unicode="¯" horiz-adv-x="851" d="M123 1190v127h606v-127h-606z" />
|
||||||
|
<glyph unicode="°" horiz-adv-x="870" d="M174 1169q0 63 22.5 116.5t61.5 91.5t92 59.5t113 21.5q59 0 112.5 -19.5t92.5 -57.5t61.5 -91t22.5 -121t-22.5 -121t-61.5 -90.5t-92.5 -57t-112.5 -19.5t-112.5 19.5t-92.5 57t-61.5 90.5t-22.5 121zM303 1169q0 -78 48 -121.5t112 -43.5q63 0 111.5 44t48.5 121 q0 78 -48.5 122t-111.5 44t-111.5 -44t-48.5 -122z" />
|
||||||
|
<glyph unicode="±" horiz-adv-x="1034" d="M82 365v147h868v-147h-868zM82 864v148h360v368h148v-368h360v-148h-360v-248h-148v248h-360z" />
|
||||||
|
<glyph unicode="²" horiz-adv-x="806" d="M98 778v68q47 39 118 104.5t136.5 141t111.5 155.5t46 148q0 63 -41 95t-100 32q-55 0 -107.5 -19.5t-91.5 -44.5l-45 117q53 37 123.5 57.5t144.5 20.5q129 0 194.5 -63.5t65.5 -176.5q0 -63 -21.5 -122.5t-57 -117t-85 -114t-104.5 -113.5l-94 -65v-4l117 30h286v-129 h-596z" />
|
||||||
|
<glyph unicode="³" horiz-adv-x="808" d="M137 803l31 123q35 -16 80 -27.5t98 -11.5q98 0 150.5 39t52.5 114q0 66 -47 107t-152 41h-112v47l198 237l70 56l-100 -13h-267v123h525v-67l-211 -252l-52 -37v-4l48 6q113 -2 178 -67.5t65 -176.5q0 -125 -91 -200.5t-243 -75.5q-74 0 -127 12t-94 27z" />
|
||||||
|
<glyph unicode="´" horiz-adv-x="548" d="M123 1169l121 306h182v-43l-207 -263h-96z" />
|
||||||
|
<glyph unicode="¶" horiz-adv-x="1011" d="M76 1036q0 76 23.5 147.5t68.5 127t110.5 89.5t147.5 34h92v-1700h-139v901q-66 0 -121 33.5t-95 90t-63.5 129.5t-23.5 148zM698 -266v1700h140v-1700h-140z" />
|
||||||
|
<glyph unicode="·" horiz-adv-x="546" d="M155 606q0 55 32 87t85 32q55 0 88 -31.5t33 -87.5q0 -53 -33 -86t-88 -33q-53 0 -85 33t-32 86z" />
|
||||||
|
<glyph unicode="¸" horiz-adv-x="587" d="M123 -418l14 101q12 -2 22.5 -3.5t47.5 -3.5q25 0 48.5 3.5t36.5 13.5t17 22.5t4 24.5q2 59 -176 76l99 184h116l-49 -88q86 -16 124 -53t38 -101q0 -84 -67.5 -134t-182.5 -50q-23 0 -45.5 2t-46.5 6z" />
|
||||||
|
<glyph unicode="¹" horiz-adv-x="806" d="M109 1444l315 209h84v-750h194v-125h-555v125h218v520l14 74l-55 -57l-160 -97z" />
|
||||||
|
<glyph unicode="º" horiz-adv-x="815" d="M90 1110q0 92 24.5 157.5t66.5 108.5t100.5 62.5t126.5 19.5t126 -18.5t100 -59.5t66.5 -107.5t24.5 -162.5t-24.5 -162.5t-66.5 -107.5t-100.5 -59.5t-125.5 -18.5q-68 0 -126.5 18.5t-100.5 59.5t-66.5 107.5t-24.5 162.5zM242 1110q0 -123 44 -176t122 -53 q39 0 69.5 11t52 36.5t32.5 69.5t11 112t-11 112t-32.5 69.5t-52.5 36.5t-69 11q-78 0 -122 -48t-44 -181z" />
|
||||||
|
<glyph unicode="»" horiz-adv-x="978" d="M80 909l106 88l340 -448l-327 -467l-107 86l197 295l100 84l-100 74zM449 911l108 90l342 -452l-328 -471l-110 88l201 297l98 84l-98 74z" />
|
||||||
|
<glyph unicode="¼" horiz-adv-x="1714" d="M109 1239l315 209h86v-875h-143v646l14 73l-57 -57l-160 -96zM330 49l997 1411l106 -71l-997 -1414zM907 197v76l463 618h92v-573h170v-121h-170v-197h-137v197h-418zM1061 307l102 11h162v262l12 100h-4l-45 -94l-160 -215z" />
|
||||||
|
<glyph unicode="½" horiz-adv-x="1740" d="M109 1239l315 209h86v-875h-143v646l14 73l-57 -57l-160 -96zM330 49l997 1411l106 -71l-997 -1414zM1063 0v68q47 39 118 104.5t136.5 141t111.5 155.5t46 148q0 63 -41 95t-100 32q-55 0 -107.5 -19.5t-91.5 -44.5l-45 117q53 37 123.5 57.5t144.5 20.5 q129 0 194.5 -63.5t65.5 -176.5q0 -63 -21.5 -122.5t-57 -117t-85 -114t-104.5 -113.5l-94 -65v-4l117 30h286v-129h-596z" />
|
||||||
|
<glyph unicode="¾" horiz-adv-x="1794" d="M155 598l31 123q35 -16 80 -27.5t98 -11.5q98 0 150.5 39t52.5 114q0 66 -47 107t-152 41h-112v47l198 237l70 56l-100 -13h-267v123h525v-67l-211 -252l-52 -37v-4l48 6q113 -2 178 -67.5t65 -176.5q0 -125 -91 -200.5t-243 -75.5q-74 0 -127 12t-94 27zM410 49 l997 1411l106 -71l-997 -1414zM987 197v76l463 618h92v-573h170v-121h-170v-197h-137v197h-418zM1141 307l102 11h162v262l12 100h-4l-45 -94l-160 -215z" />
|
||||||
|
<glyph unicode="¿" horiz-adv-x="892" d="M76 -100q0 92 27.5 160.5t69.5 125t90 105.5t90 103.5t70 117.5t28 150h135q2 -10 2 -22.5v-23.5q0 -86 -25.5 -151.5t-63.5 -119.5t-82 -101t-82 -95.5t-63.5 -102.5t-25.5 -124q0 -94 54 -153.5t181 -59.5q74 0 150 25.5t131 60.5l55 -127q-78 -47 -164 -74.5 t-213 -27.5q-90 0 -158.5 25.5t-114.5 70.5t-68.5 105.5t-22.5 132.5zM391 930q0 55 32 87t85 32q55 0 88 -32t33 -87q0 -53 -33 -86t-88 -33q-53 0 -85 33t-32 86z" />
|
||||||
|
<glyph unicode="À" horiz-adv-x="1198" d="M16 0l543 1456h78l545 -1456h-178l-148 397h-528l-144 -397h-168zM277 1739v43h233l242 -242h-152zM383 545h422l-160 436l-51 217h-2l-51 -221z" />
|
||||||
|
<glyph unicode="Á" horiz-adv-x="1198" d="M16 0l543 1456h78l545 -1456h-178l-148 397h-528l-144 -397h-168zM383 545h422l-160 436l-51 217h-2l-51 -221zM436 1540l242 242h233v-43l-334 -199h-141z" />
|
||||||
|
<glyph unicode="Â" horiz-adv-x="1198" d="M16 0l543 1456h78l545 -1456h-178l-148 397h-528l-144 -397h-168zM270 1530v45l272 207h123l260 -209v-43h-166l-123 100l-34 72l-39 -70l-131 -102h-162zM383 545h422l-160 436l-51 217h-2l-51 -221z" />
|
||||||
|
<glyph unicode="Ã" horiz-adv-x="1198" d="M16 0l543 1456h78l545 -1456h-178l-148 397h-528l-144 -397h-168zM277 1608q63 66 117.5 89t103.5 23q39 0 76 -10t70.5 -23.5t66.5 -23.5t64 -10q53 0 102 43l51 -88q-55 -51 -104 -70.5t-92 -19.5q-39 0 -74 10t-69 23.5t-66.5 23.5t-65.5 10t-64.5 -13t-66.5 -48z M383 545h422l-160 436l-51 217h-2l-51 -221z" />
|
||||||
|
<glyph unicode="Ä" horiz-adv-x="1198" d="M16 0l543 1456h78l545 -1456h-178l-148 397h-528l-144 -397h-168zM295 1626q0 43 30.5 69.5t79.5 26.5q47 0 77 -26.5t30 -69.5q0 -41 -29.5 -67.5t-77.5 -26.5q-49 0 -79.5 26.5t-30.5 67.5zM383 545h422l-160 436l-51 217h-2l-51 -221zM688 1626q0 43 29.5 69.5 t77.5 26.5q49 0 79.5 -26.5t30.5 -69.5q0 -41 -30.5 -67.5t-79.5 -26.5q-47 0 -77 26.5t-30 67.5z" />
|
||||||
|
<glyph unicode="Å" horiz-adv-x="1198" d="M16 0l525 1407q-78 12 -117 56t-39 110q0 76 51 125t164 49q102 0 159.5 -44t57.5 -130q0 -66 -41 -110t-121 -56l527 -1407h-178l-148 397h-528l-144 -397h-168zM383 545h422l-160 436l-51 217h-2l-51 -221zM510 1573q0 -35 21.5 -58.5t68.5 -23.5q45 0 68.5 22.5 t23.5 59.5q0 39 -22.5 62.5t-69.5 23.5q-45 0 -67.5 -23.5t-22.5 -62.5z" />
|
||||||
|
<glyph unicode="Æ" horiz-adv-x="1732" d="M-45 0l850 1434h784v-152h-610v-469h559v-151h-559v-510h620v-152h-790v406h-438l-230 -406h-186zM459 549h350v680h-8l-70 -211z" />
|
||||||
|
<glyph unicode="Ç" horiz-adv-x="1169" d="M115 717q0 201 54 341t143 229t200 130t225 41q123 0 201 -13t133 -36l-41 -149q-98 47 -280 47q-84 0 -166 -31t-146.5 -100.5t-103.5 -182t-39 -276.5q0 -147 37 -258t101.5 -184.5t151.5 -110.5t189 -37q92 0 161 18.5t116 47.5l41 -134q-53 -41 -131 -59t-170 -23 l-35 -65q86 -16 124 -53t38 -101q0 -80 -66 -132t-184 -52q-23 0 -45.5 2t-47.5 6l19 80q12 -2 22.5 -2h20.5q45 0 70.5 8t39 19.5t16.5 26t3 26.5q0 57 -176 76l86 164q-119 8 -221.5 56t-178 138t-118.5 225.5t-43 317.5z" />
|
||||||
|
<glyph unicode="È" horiz-adv-x="1097" d="M174 0v1434h780v-152h-610v-469h559v-151h-559v-510h621v-152h-791zM193 1739v43h233l242 -242h-152z" />
|
||||||
|
<glyph unicode="É" horiz-adv-x="1097" d="M174 0v1434h780v-152h-610v-469h559v-151h-559v-510h621v-152h-791zM434 1540l242 242h233v-43l-334 -199h-141z" />
|
||||||
|
<glyph unicode="Ê" horiz-adv-x="1097" d="M174 0v1434h780v-152h-610v-469h559v-151h-559v-510h621v-152h-791zM223 1530v45l272 207h123l260 -209v-43h-166l-123 100l-34 72l-39 -70l-131 -102h-162z" />
|
||||||
|
<glyph unicode="Ë" horiz-adv-x="1097" d="M174 0v1434h780v-152h-610v-469h559v-151h-559v-510h621v-152h-791zM246 1626q0 43 30.5 69.5t79.5 26.5q47 0 77 -26.5t30 -69.5q0 -41 -29.5 -67.5t-77.5 -26.5q-49 0 -79.5 26.5t-30.5 67.5zM639 1626q0 43 29.5 69.5t77.5 26.5q49 0 79.5 -26.5t30.5 -69.5 q0 -41 -30.5 -67.5t-79.5 -26.5q-47 0 -77 26.5t-30 67.5z" />
|
||||||
|
<glyph unicode="Ì" horiz-adv-x="595" d="M-76 1739v43h233l242 -242h-152zM213 0v1434h170v-1434h-170z" />
|
||||||
|
<glyph unicode="Í" horiz-adv-x="595" d="M127 1540l242 242h233v-43l-334 -199h-141zM213 0v1434h170v-1434h-170z" />
|
||||||
|
<glyph unicode="Î" horiz-adv-x="595" d="M-31 1530v45l272 207h123l260 -209v-43h-166l-123 100l-34 72l-39 -70l-131 -102h-162zM213 0v1434h170v-1434h-170z" />
|
||||||
|
<glyph unicode="Ï" horiz-adv-x="595" d="M-4 1626q0 43 30.5 69.5t79.5 26.5q47 0 77 -26.5t30 -69.5q0 -41 -29.5 -67.5t-77.5 -26.5q-49 0 -79.5 26.5t-30.5 67.5zM213 0v1434h170v-1434h-170zM389 1626q0 43 29.5 69.5t77.5 26.5q49 0 79.5 -26.5t30.5 -69.5q0 -41 -30.5 -67.5t-79.5 -26.5q-47 0 -77 26.5 t-30 67.5z" />
|
||||||
|
<glyph unicode="Ð" horiz-adv-x="1347" d="M-2 680v123h184v631q39 6 87 9t100.5 4t102.5 2t93 1q172 0 298 -53.5t208 -148.5t122 -228t40 -293q0 -145 -38 -279.5t-120 -238t-213 -165.5t-317 -62q-33 0 -85 1t-107.5 4t-102.5 5t-68 6v682h-184zM352 141q10 -2 39 -3t59.5 -2t59.5 -2t39 -1q143 0 240.5 49 t156 132t83 190.5t24.5 222.5q0 100 -22.5 201.5t-78 183.5t-149 134t-234.5 52h-58.5t-62 -2t-56 -4t-40.5 -4v-485h301v-123h-301v-539z" />
|
||||||
|
<glyph unicode="Ñ" horiz-adv-x="1378" d="M174 0v1456h90l686 -956l107 -197h10l-23 197v934h160v-1457h-90l-682 961l-110 207h-9l21 -207v-938h-160zM367 1608q63 66 117.5 89t103.5 23q39 0 76 -10t70.5 -23.5t66.5 -23.5t64 -10q53 0 102 43l51 -88q-55 -51 -104 -70.5t-92 -19.5q-39 0 -74 10t-69 23.5 t-66.5 23.5t-65.5 10t-64.5 -13t-66.5 -48z" />
|
||||||
|
<glyph unicode="Ò" horiz-adv-x="1400" d="M115 717q0 358 151.5 549.5t431.5 191.5q152 0 262.5 -53t183.5 -150.5t107.5 -233.5t34.5 -304q0 -358 -152.5 -550t-435.5 -192q-150 0 -259 53.5t-182 150.5t-107.5 233.5t-34.5 304.5zM295 717q0 -119 23.5 -225.5t72.5 -187.5t126 -129t181 -48q190 0 299 144.5 t109 445.5q0 117 -23.5 224.5t-74 188t-127 129t-183.5 48.5q-188 0 -295.5 -144.5t-107.5 -445.5zM365 1739v43h233l242 -242h-152z" />
|
||||||
|
<glyph unicode="Ó" horiz-adv-x="1400" d="M115 717q0 358 151.5 549.5t431.5 191.5q152 0 262.5 -53t183.5 -150.5t107.5 -233.5t34.5 -304q0 -358 -152.5 -550t-435.5 -192q-150 0 -259 53.5t-182 150.5t-107.5 233.5t-34.5 304.5zM295 717q0 -119 23.5 -225.5t72.5 -187.5t126 -129t181 -48q190 0 299 144.5 t109 445.5q0 117 -23.5 224.5t-74 188t-127 129t-183.5 48.5q-188 0 -295.5 -144.5t-107.5 -445.5zM608 1540l242 242h233v-43l-334 -199h-141z" />
|
||||||
|
<glyph unicode="Ô" horiz-adv-x="1400" d="M115 717q0 358 151.5 549.5t431.5 191.5q152 0 262.5 -53t183.5 -150.5t107.5 -233.5t34.5 -304q0 -358 -152.5 -550t-435.5 -192q-150 0 -259 53.5t-182 150.5t-107.5 233.5t-34.5 304.5zM295 717q0 -119 23.5 -225.5t72.5 -187.5t126 -129t181 -48q190 0 299 144.5 t109 445.5q0 117 -23.5 224.5t-74 188t-127 129t-183.5 48.5q-188 0 -295.5 -144.5t-107.5 -445.5zM367 1530v45l272 207h123l260 -209v-43h-166l-123 100l-34 72l-39 -70l-131 -102h-162z" />
|
||||||
|
<glyph unicode="Õ" horiz-adv-x="1400" d="M115 717q0 358 151.5 549.5t431.5 191.5q152 0 262.5 -53t183.5 -150.5t107.5 -233.5t34.5 -304q0 -358 -152.5 -550t-435.5 -192q-150 0 -259 53.5t-182 150.5t-107.5 233.5t-34.5 304.5zM295 717q0 -119 23.5 -225.5t72.5 -187.5t126 -129t181 -48q190 0 299 144.5 t109 445.5q0 117 -23.5 224.5t-74 188t-127 129t-183.5 48.5q-188 0 -295.5 -144.5t-107.5 -445.5zM373 1608q63 66 117.5 89t103.5 23q39 0 76 -10t70.5 -23.5t66.5 -23.5t64 -10q53 0 102 43l51 -88q-55 -51 -104 -70.5t-92 -19.5q-39 0 -74 10t-69 23.5t-66.5 23.5 t-65.5 10t-64.5 -13t-66.5 -48z" />
|
||||||
|
<glyph unicode="Ö" horiz-adv-x="1400" d="M115 717q0 358 151.5 549.5t431.5 191.5q152 0 262.5 -53t183.5 -150.5t107.5 -233.5t34.5 -304q0 -358 -152.5 -550t-435.5 -192q-150 0 -259 53.5t-182 150.5t-107.5 233.5t-34.5 304.5zM295 717q0 -119 23.5 -225.5t72.5 -187.5t126 -129t181 -48q190 0 299 144.5 t109 445.5q0 117 -23.5 224.5t-74 188t-127 129t-183.5 48.5q-188 0 -295.5 -144.5t-107.5 -445.5zM389 1626q0 43 30.5 69.5t79.5 26.5q47 0 77 -26.5t30 -69.5q0 -41 -29.5 -67.5t-77.5 -26.5q-49 0 -79.5 26.5t-30.5 67.5zM782 1626q0 43 29.5 69.5t77.5 26.5 q49 0 79.5 -26.5t30.5 -69.5q0 -41 -30.5 -67.5t-79.5 -26.5q-47 0 -77 26.5t-30 67.5z" />
|
||||||
|
<glyph unicode="×" horiz-adv-x="1034" d="M152 430l262 264l-258 256l104 109l258 -260l260 260l105 -109l-258 -258l258 -260l-105 -106l-260 262l-260 -262z" />
|
||||||
|
<glyph unicode="Ø" horiz-adv-x="1400" d="M115 717q0 358 151.5 549.5t431.5 191.5q117 0 207 -30.5t160 -90.5l86 123l106 -71l-104 -148q68 -98 100.5 -230t32.5 -294q0 -358 -152.5 -550t-435.5 -192q-219 0 -358 115l-80 -115l-106 74l96 137q-70 98 -102.5 231.5t-32.5 299.5zM295 717q0 -104 17.5 -196.5 t54.5 -170.5l594 842q-47 53 -112 84t-151 31q-188 0 -295.5 -144.5t-107.5 -445.5zM442 233q47 -51 110.5 -78.5t145.5 -27.5q190 0 299 144.5t109 445.5q0 98 -17.5 190t-52.5 168z" />
|
||||||
|
<glyph unicode="Ù" horiz-adv-x="1335" d="M174 444v990h170v-910q0 -109 21.5 -183.5t64.5 -120.5t107.5 -66.5t150.5 -20.5q166 0 237.5 91t71.5 300v910h164v-957q0 -129 -33.5 -223t-96 -154.5t-150.5 -89t-195 -28.5q-254 0 -383 114.5t-129 347.5zM359 1739v43h233l242 -242h-152z" />
|
||||||
|
<glyph unicode="Ú" horiz-adv-x="1335" d="M174 444v990h170v-910q0 -109 21.5 -183.5t64.5 -120.5t107.5 -66.5t150.5 -20.5q166 0 237.5 91t71.5 300v910h164v-957q0 -129 -33.5 -223t-96 -154.5t-150.5 -89t-195 -28.5q-254 0 -383 114.5t-129 347.5zM557 1540l242 242h233v-43l-334 -199h-141z" />
|
||||||
|
<glyph unicode="Û" horiz-adv-x="1335" d="M174 444v990h170v-910q0 -109 21.5 -183.5t64.5 -120.5t107.5 -66.5t150.5 -20.5q166 0 237.5 91t71.5 300v910h164v-957q0 -129 -33.5 -223t-96 -154.5t-150.5 -89t-195 -28.5q-254 0 -383 114.5t-129 347.5zM344 1530v45l272 207h123l260 -209v-43h-166l-123 100 l-34 72l-39 -70l-131 -102h-162z" />
|
||||||
|
<glyph unicode="Ü" horiz-adv-x="1335" d="M174 444v990h170v-910q0 -109 21.5 -183.5t64.5 -120.5t107.5 -66.5t150.5 -20.5q166 0 237.5 91t71.5 300v910h164v-957q0 -129 -33.5 -223t-96 -154.5t-150.5 -89t-195 -28.5q-254 0 -383 114.5t-129 347.5zM365 1626q0 43 30.5 69.5t79.5 26.5q47 0 77 -26.5t30 -69.5 q0 -41 -29.5 -67.5t-77.5 -26.5q-49 0 -79.5 26.5t-30.5 67.5zM758 1626q0 43 29.5 69.5t77.5 26.5q49 0 79.5 -26.5t30.5 -69.5q0 -41 -30.5 -67.5t-79.5 -26.5q-47 0 -77 26.5t-30 67.5z" />
|
||||||
|
<glyph unicode="Ý" horiz-adv-x="1142" d="M16 1434h199l336 -627l35 -125h2l37 129l321 623h182l-469 -863v-571h-170v569zM485 1540l242 242h233v-43l-334 -199h-141z" />
|
||||||
|
<glyph unicode="Þ" horiz-adv-x="1144" d="M174 0v1638h170v-358q86 6 176 6q94 0 191.5 -18.5t177.5 -67.5t130 -135t50 -219q0 -131 -47 -221t-125 -146.5t-178.5 -81t-206.5 -24.5h-33.5t-49.5 1t-50.5 3t-34.5 4v-381h-170zM344 532q10 -4 32.5 -5t47.5 -2t47.5 -1h32.5q70 0 138.5 13.5t123.5 48.5t89 98.5 t34 161.5q0 84 -32 140t-84 90t-117.5 48.5t-131.5 14.5q-53 0 -102 -2t-78 -11v-594z" />
|
||||||
|
<glyph unicode="ß" horiz-adv-x="1212" d="M45 881v143h160v47q0 199 97 287t269 88q84 0 154 -21.5t120 -61.5t77.5 -94.5t27.5 -121.5q0 -78 -39 -125t-85 -84t-85 -72t-39 -86q0 -45 31 -71.5t78 -47t100.5 -42t100.5 -56.5t77.5 -91t30.5 -146q0 -66 -24.5 -128.5t-70.5 -111.5t-115.5 -80t-157.5 -31 q-47 0 -83 3.5t-66 10.5t-56.5 17t-52.5 27l47 137q25 -12 43 -22.5t39.5 -16.5t48 -9t65.5 -3q43 0 83 15.5t71 42t48 62t17 80.5q0 61 -30.5 97.5t-76.5 61t-100.5 44t-100.5 49t-76.5 75.5t-30.5 124q0 80 37.5 128t86 86t85 73t36.5 88q0 35 -19 63.5t-50 50t-68 33 t-71 11.5q-57 0 -97.5 -14.5t-66 -47.5t-35.5 -87t-10 -134v-1020h-164v881h-160z" />
|
||||||
|
<glyph unicode="à" horiz-adv-x="1015" d="M80 274q0 90 37 150.5t103.5 96.5t159.5 51.5t206 15.5h56.5t55.5 -4q6 61 7 110q0 113 -45.5 158t-163.5 45q-35 0 -75 -5t-82 -14.5t-80 -22.5t-66 -30l-52 123q78 47 181.5 69.5t216.5 22.5q106 0 170.5 -28.5t98.5 -74.5t45 -101.5t11 -110.5q0 -123 -6 -239.5 t-6 -221.5q0 -76 6 -143.5t23 -124.5h-121l-43 143h-10q-18 -29 -46 -56.5t-67 -49t-90 -35.5t-117 -14t-122 20.5t-97 58t-64.5 91t-23.5 120.5zM250 291q0 -72 51 -118t131 -46q57 0 102.5 15.5t78 39t54 52t31.5 55.5v170q-29 2 -58.5 3t-57.5 1q-63 0 -124 -7 t-107 -26.5t-73.5 -53.5t-27.5 -85zM297 1432v43h194l134 -306h-93z" />
|
||||||
|
<glyph unicode="á" horiz-adv-x="1015" d="M80 274q0 90 37 150.5t103.5 96.5t159.5 51.5t206 15.5h56.5t55.5 -4q6 61 7 110q0 113 -45.5 158t-163.5 45q-35 0 -75 -5t-82 -14.5t-80 -22.5t-66 -30l-52 123q78 47 181.5 69.5t216.5 22.5q106 0 170.5 -28.5t98.5 -74.5t45 -101.5t11 -110.5q0 -123 -6 -239.5 t-6 -221.5q0 -76 6 -143.5t23 -124.5h-121l-43 143h-10q-18 -29 -46 -56.5t-67 -49t-90 -35.5t-117 -14t-122 20.5t-97 58t-64.5 91t-23.5 120.5zM250 291q0 -72 51 -118t131 -46q57 0 102.5 15.5t78 39t54 52t31.5 55.5v170q-29 2 -58.5 3t-57.5 1q-63 0 -124 -7 t-107 -26.5t-73.5 -53.5t-27.5 -85zM367 1169l121 306h182v-43l-207 -263h-96z" />
|
||||||
|
<glyph unicode="â" horiz-adv-x="1015" d="M80 274q0 90 37 150.5t103.5 96.5t159.5 51.5t206 15.5h56.5t55.5 -4q6 61 7 110q0 113 -45.5 158t-163.5 45q-35 0 -75 -5t-82 -14.5t-80 -22.5t-66 -30l-52 123q78 47 181.5 69.5t216.5 22.5q106 0 170.5 -28.5t98.5 -74.5t45 -101.5t11 -110.5q0 -123 -6 -239.5 t-6 -221.5q0 -76 6 -143.5t23 -124.5h-121l-43 143h-10q-18 -29 -46 -56.5t-67 -49t-90 -35.5t-117 -14t-122 20.5t-97 58t-64.5 91t-23.5 120.5zM238 1126l252 373h65l228 -373h-148l-80 136l-43 118l-45 -118l-92 -136h-137zM250 291q0 -72 51 -118t131 -46 q57 0 102.5 15.5t78 39t54 52t31.5 55.5v170q-29 2 -58.5 3t-57.5 1q-63 0 -124 -7t-107 -26.5t-73.5 -53.5t-27.5 -85z" />
|
||||||
|
<glyph unicode="ã" horiz-adv-x="1015" d="M80 274q0 90 37 150.5t103.5 96.5t159.5 51.5t206 15.5h56.5t55.5 -4q6 61 7 110q0 113 -45.5 158t-163.5 45q-35 0 -75 -5t-82 -14.5t-80 -22.5t-66 -30l-52 123q78 47 181.5 69.5t216.5 22.5q106 0 170.5 -28.5t98.5 -74.5t45 -101.5t11 -110.5q0 -123 -6 -239.5 t-6 -221.5q0 -76 6 -143.5t23 -124.5h-121l-43 143h-10q-18 -29 -46 -56.5t-67 -49t-90 -35.5t-117 -14t-122 20.5t-97 58t-64.5 91t-23.5 120.5zM223 1343q59 68 108.5 93.5t90.5 25.5q35 0 64.5 -13t57 -28.5t53 -28t54.5 -12.5q45 0 94 50l49 -89q-53 -59 -97 -80.5 t-81 -21.5q-33 0 -61.5 12.5t-56 27.5t-55.5 28.5t-56 13.5q-27 0 -54.5 -14.5t-62.5 -49.5zM250 291q0 -72 51 -118t131 -46q57 0 102.5 15.5t78 39t54 52t31.5 55.5v170q-29 2 -58.5 3t-57.5 1q-63 0 -124 -7t-107 -26.5t-73.5 -53.5t-27.5 -85z" />
|
||||||
|
<glyph unicode="ä" horiz-adv-x="1015" d="M80 274q0 90 37 150.5t103.5 96.5t159.5 51.5t206 15.5h56.5t55.5 -4q6 61 7 110q0 113 -45.5 158t-163.5 45q-35 0 -75 -5t-82 -14.5t-80 -22.5t-66 -30l-52 123q78 47 181.5 69.5t216.5 22.5q106 0 170.5 -28.5t98.5 -74.5t45 -101.5t11 -110.5q0 -123 -6 -239.5 t-6 -221.5q0 -76 6 -143.5t23 -124.5h-121l-43 143h-10q-18 -29 -46 -56.5t-67 -49t-90 -35.5t-117 -14t-122 20.5t-97 58t-64.5 91t-23.5 120.5zM215 1337q0 47 27.5 76t72.5 29t73 -29t28 -76q0 -43 -28 -71.5t-73 -28.5t-72.5 28.5t-27.5 71.5zM250 291q0 -72 51 -118 t131 -46q57 0 102.5 15.5t78 39t54 52t31.5 55.5v170q-29 2 -58.5 3t-57.5 1q-63 0 -124 -7t-107 -26.5t-73.5 -53.5t-27.5 -85zM608 1337q0 47 27.5 76t72.5 29q47 0 75 -29t28 -76q0 -43 -27.5 -71.5t-75.5 -28.5q-45 0 -72.5 28.5t-27.5 71.5z" />
|
||||||
|
<glyph unicode="å" horiz-adv-x="1015" d="M80 274q0 90 37 150.5t103.5 96.5t159.5 51.5t206 15.5h56.5t55.5 -4q6 61 7 110q0 113 -45.5 158t-163.5 45q-35 0 -75 -5t-82 -14.5t-80 -22.5t-66 -30l-52 123q78 47 181.5 69.5t216.5 22.5q106 0 170.5 -28.5t98.5 -74.5t45 -101.5t11 -110.5q0 -123 -6 -239.5 t-6 -221.5q0 -76 6 -143.5t23 -124.5h-121l-43 143h-10q-18 -29 -46 -56.5t-67 -49t-90 -35.5t-117 -14t-122 20.5t-97 58t-64.5 91t-23.5 120.5zM250 291q0 -72 51 -118t131 -46q57 0 102.5 15.5t78 39t54 52t31.5 55.5v170q-29 2 -58.5 3t-57.5 1q-63 0 -124 -7 t-107 -26.5t-73.5 -53.5t-27.5 -85zM311 1317q0 86 54 136t145 50q86 0 143 -45t57 -141q0 -80 -57 -132t-143 -52t-142.5 48t-56.5 136zM421 1317q0 -41 27 -63.5t62 -22.5q39 0 64.5 20.5t25.5 65.5t-28 66.5t-62 21.5q-35 0 -62 -20.5t-27 -67.5z" />
|
||||||
|
<glyph unicode="æ" horiz-adv-x="1630" d="M80 274q0 90 37 150.5t103.5 96.5t159.5 51.5t206 15.5h56.5t55.5 -4q2 31 4.5 58.5t2.5 51.5q0 113 -45.5 159t-163.5 44q-35 0 -75 -5t-82 -14.5t-80 -22.5t-66 -30l-52 123q78 47 181.5 69.5t216.5 22.5q215 0 278 -133q53 74 143.5 108t180.5 34q70 0 139.5 -15.5 t124.5 -59.5t90 -124t35 -209q0 -33 -3 -68.5t-7 -76.5h-662q0 -178 75 -277.5t255 -99.5q72 0 140.5 25.5t105.5 56.5l61 -119q-61 -49 -154.5 -78t-197.5 -29q-125 0 -226.5 51.5t-150.5 145.5h-14q-27 -37 -62 -70.5t-79 -59.5t-100 -42t-124 -16q-66 0 -122 20.5t-97 58 t-64.5 91t-23.5 120.5zM250 291q0 -72 51 -118t131 -46q57 0 102.5 15.5t78 39t54 52t31.5 55.5v170q-29 2 -58.5 3t-57.5 1q-63 0 -124 -7t-107 -26.5t-73.5 -53.5t-27.5 -85zM862 625h508v24q0 139 -62.5 197.5t-164.5 58.5q-121 0 -195 -63.5t-86 -216.5z" />
|
||||||
|
<glyph unicode="ç" horiz-adv-x="923" d="M100 512q0 260 115 398.5t330 138.5q98 0 166.5 -15.5t124.5 -44.5l-48 -141q-47 27 -104 42t-123 15q-291 0 -291 -393q0 -78 15.5 -148.5t51.5 -125t94 -86t144 -31.5q74 0 132.5 21.5t95.5 50.5l53 -125q-100 -72 -248 -88l-37 -68q86 -16 124 -53t38 -101 q0 -80 -65.5 -132t-184.5 -52q-23 0 -45 2t-47 6l19 80q12 -2 22 -2h21q45 0 70.5 8t38.5 19.5t16.5 26t3.5 26.5q0 57 -176 76l86 161q-106 6 -180 47.5t-121.5 111t-69 164.5t-21.5 212z" />
|
||||||
|
<glyph unicode="è" horiz-adv-x="1040" d="M100 512q0 262 117 399.5t334 137.5q70 0 139.5 -15.5t124.5 -58.5t90 -122t35 -208q0 -68 -12 -149h-658q0 -90 18.5 -160t57.5 -118t101.5 -73.5t152.5 -25.5q70 0 139.5 24.5t104.5 57.5l61 -119q-61 -49 -154.5 -78t-197.5 -29q-117 0 -203 38t-141 109t-82 169 t-27 221zM272 625h508q0 156 -59 218t-168 62q-121 0 -193.5 -63.5t-87.5 -216.5zM348 1432v43h194l134 -306h-93z" />
|
||||||
|
<glyph unicode="é" horiz-adv-x="1040" d="M100 512q0 262 117 399.5t334 137.5q70 0 139.5 -15.5t124.5 -58.5t90 -122t35 -208q0 -68 -12 -149h-658q0 -90 18.5 -160t57.5 -118t101.5 -73.5t152.5 -25.5q70 0 139.5 24.5t104.5 57.5l61 -119q-61 -49 -154.5 -78t-197.5 -29q-117 0 -203 38t-141 109t-82 169 t-27 221zM272 625h508q0 156 -59 218t-168 62q-121 0 -193.5 -63.5t-87.5 -216.5zM475 1169l121 306h182v-43l-207 -263h-96z" />
|
||||||
|
<glyph unicode="ê" horiz-adv-x="1040" d="M100 512q0 262 117 399.5t334 137.5q70 0 139.5 -15.5t124.5 -58.5t90 -122t35 -208q0 -68 -12 -149h-658q0 -90 18.5 -160t57.5 -118t101.5 -73.5t152.5 -25.5q70 0 139.5 24.5t104.5 57.5l61 -119q-61 -49 -154.5 -78t-197.5 -29q-117 0 -203 38t-141 109t-82 169 t-27 221zM250 1126l252 373h65l228 -373h-148l-80 136l-43 118l-45 -118l-92 -136h-137zM272 625h508q0 156 -59 218t-168 62q-121 0 -193.5 -63.5t-87.5 -216.5z" />
|
||||||
|
<glyph unicode="ë" horiz-adv-x="1040" d="M100 512q0 262 117 399.5t334 137.5q70 0 139.5 -15.5t124.5 -58.5t90 -122t35 -208q0 -68 -12 -149h-658q0 -90 18.5 -160t57.5 -118t101.5 -73.5t152.5 -25.5q70 0 139.5 24.5t104.5 57.5l61 -119q-61 -49 -154.5 -78t-197.5 -29q-117 0 -203 38t-141 109t-82 169 t-27 221zM244 1337q0 47 27.5 76t72.5 29t73 -29t28 -76q0 -43 -28 -71.5t-73 -28.5t-72.5 28.5t-27.5 71.5zM272 625h508q0 156 -59 218t-168 62q-121 0 -193.5 -63.5t-87.5 -216.5zM637 1337q0 47 27.5 76t72.5 29q47 0 75 -29t28 -76q0 -43 -27.5 -71.5t-75.5 -28.5 q-45 0 -72.5 28.5t-27.5 71.5z" />
|
||||||
|
<glyph unicode="ì" horiz-adv-x="548" d="M25 1432v43h194l134 -306h-93zM193 0v1024h163v-1024h-163z" />
|
||||||
|
<glyph unicode="í" horiz-adv-x="548" d="M193 0v1024h163v-1024h-163zM195 1169l121 306h182v-43l-207 -263h-96z" />
|
||||||
|
<glyph unicode="î" horiz-adv-x="548" d="M-4 1126l252 373h65l228 -373h-148l-80 136l-43 118l-45 -118l-92 -136h-137zM193 0v1024h163v-1024h-163z" />
|
||||||
|
<glyph unicode="ï" horiz-adv-x="548" d="M-24 1337q0 47 27.5 76t72.5 29t73 -29t28 -76q0 -43 -28 -71.5t-73 -28.5t-72.5 28.5t-27.5 71.5zM193 0v1024h163v-1024h-163zM369 1337q0 47 27.5 76t72.5 29q47 0 75 -29t28 -76q0 -43 -27.5 -71.5t-75.5 -28.5q-45 0 -72.5 28.5t-27.5 71.5z" />
|
||||||
|
<glyph unicode="ð" horiz-adv-x="1148" d="M115 514q0 106 29.5 202.5t88 169t143.5 115.5t197 43q92 0 163 -28.5t100 -65.5q-23 76 -69 143.5t-105 120.5l-156 -84l-55 91l116 63q-78 47 -155 66l71 110q37 -14 94.5 -38.5t118.5 -67.5l140 76l53 -93l-103 -55q49 -47 94.5 -109.5t80 -145.5t55 -187.5 t20.5 -235.5q0 -166 -36.5 -284.5t-99 -195.5t-145.5 -113t-177 -36q-125 0 -213.5 43t-143.5 117t-80.5 171t-25.5 208zM283 512q0 -100 22.5 -174t62.5 -123t96 -72.5t122 -23.5q61 0 113.5 26.5t91 84t61 147.5t22.5 217q0 20 -1 46t-2 51.5t-4 49t-7 39.5 q-16 29 -46 51.5t-66.5 38t-77.5 22.5t-80 7q-80 0 -138.5 -29.5t-96.5 -82t-55 -123t-17 -152.5z" />
|
||||||
|
<glyph unicode="ñ" horiz-adv-x="1120" d="M158 0v1024h114l31 -125h8q49 66 132 108t198 42q84 0 147.5 -19.5t105.5 -69t63.5 -132.5t21.5 -210v-618h-164v584q0 160 -46 240.5t-169 80.5q-109 0 -179.5 -58.5t-98.5 -146.5v-700h-164zM275 1343q59 68 108.5 93.5t90.5 25.5q35 0 64.5 -13t57 -28.5t53 -28 t54.5 -12.5q45 0 94 50l49 -89q-53 -59 -97 -80.5t-81 -21.5q-33 0 -61.5 12.5t-56 27.5t-55.5 28.5t-56 13.5q-27 0 -54.5 -14.5t-62.5 -49.5z" />
|
||||||
|
<glyph unicode="ò" horiz-adv-x="1097" d="M100 512q0 260 116 398.5t333 138.5q115 0 200 -38t140 -109t81.5 -170t26.5 -220q0 -260 -115.5 -398.5t-332.5 -138.5q-115 0 -200 38t-140 109t-82 170t-27 220zM270 512q0 -78 15.5 -149.5t48.5 -125t86 -86t129 -32.5q279 -2 278 393q0 80 -15 151.5t-48 125t-86 85 t-129 31.5q-279 2 -279 -393zM322 1432v43h194l134 -306h-93z" />
|
||||||
|
<glyph unicode="ó" horiz-adv-x="1097" d="M100 512q0 260 116 398.5t333 138.5q115 0 200 -38t140 -109t81.5 -170t26.5 -220q0 -260 -115.5 -398.5t-332.5 -138.5q-115 0 -200 38t-140 109t-82 170t-27 220zM270 512q0 -78 15.5 -149.5t48.5 -125t86 -86t129 -32.5q279 -2 278 393q0 80 -15 151.5t-48 125t-86 85 t-129 31.5q-279 2 -279 -393zM465 1169l121 306h182v-43l-207 -263h-96z" />
|
||||||
|
<glyph unicode="ô" horiz-adv-x="1097" d="M100 512q0 260 116 398.5t333 138.5q115 0 200 -38t140 -109t81.5 -170t26.5 -220q0 -260 -115.5 -398.5t-332.5 -138.5q-115 0 -200 38t-140 109t-82 170t-27 220zM270 512q0 -78 15.5 -149.5t48.5 -125t86 -86t129 -32.5q279 -2 278 393q0 80 -15 151.5t-48 125t-86 85 t-129 31.5q-279 2 -279 -393zM277 1126l252 373h65l228 -373h-148l-80 136l-43 118l-45 -118l-92 -136h-137z" />
|
||||||
|
<glyph unicode="õ" horiz-adv-x="1097" d="M100 512q0 260 116 398.5t333 138.5q115 0 200 -38t140 -109t81.5 -170t26.5 -220q0 -260 -115.5 -398.5t-332.5 -138.5q-115 0 -200 38t-140 109t-82 170t-27 220zM264 1343q59 68 108.5 93.5t90.5 25.5q35 0 64.5 -13t57 -28.5t53 -28t54.5 -12.5q45 0 94 50l49 -89 q-53 -59 -97 -80.5t-81 -21.5q-33 0 -61.5 12.5t-56 27.5t-55.5 28.5t-56 13.5q-27 0 -54.5 -14.5t-62.5 -49.5zM270 512q0 -78 15.5 -149.5t48.5 -125t86 -86t129 -32.5q279 -2 278 393q0 80 -15 151.5t-48 125t-86 85t-129 31.5q-279 2 -279 -393z" />
|
||||||
|
<glyph unicode="ö" horiz-adv-x="1097" d="M100 512q0 260 116 398.5t333 138.5q115 0 200 -38t140 -109t81.5 -170t26.5 -220q0 -260 -115.5 -398.5t-332.5 -138.5q-115 0 -200 38t-140 109t-82 170t-27 220zM254 1337q0 47 27.5 76t72.5 29t73 -29t28 -76q0 -43 -28 -71.5t-73 -28.5t-72.5 28.5t-27.5 71.5z M270 512q0 -78 15.5 -149.5t48.5 -125t86 -86t129 -32.5q279 -2 278 393q0 80 -15 151.5t-48 125t-86 85t-129 31.5q-279 2 -279 -393zM647 1337q0 47 27.5 76t72.5 29q47 0 75 -29t28 -76q0 -43 -27.5 -71.5t-75.5 -28.5q-45 0 -72.5 28.5t-27.5 71.5z" />
|
||||||
|
<glyph unicode="÷" horiz-adv-x="1034" d="M82 618v148h868v-148h-868zM397 307q0 55 32 87t85 32q55 0 88 -32t33 -87q0 -53 -33 -86t-88 -33q-53 0 -85 33t-32 86zM397 1075q0 55 32 87t85 32q55 0 88 -32t33 -87q0 -53 -33 -86t-88 -33q-53 0 -85 33t-32 86z" />
|
||||||
|
<glyph unicode="ø" horiz-adv-x="1097" d="M100 512q0 260 116 398.5t333 138.5q150 0 250 -66l53 72l102 -76l-59 -86q53 -70 77.5 -166t24.5 -215q0 -260 -115.5 -398.5t-332.5 -138.5q-160 0 -262 72l-56 -76l-106 78l68 94q-47 70 -70 163t-23 206zM270 512q0 -61 9.5 -118.5t27.5 -104.5l404 561 q-31 25 -71 40t-91 15q-279 2 -279 -393zM377 180q33 -27 75 -44t97 -17q278 -2 278 393q0 66 -10 126t-33 110z" />
|
||||||
|
<glyph unicode="ù" horiz-adv-x="1103" d="M141 406v618h164v-584q0 -80 9.5 -140t32 -100t61 -60.5t98.5 -20.5q55 0 98 17.5t77 48t59.5 70.5t41.5 85v684h164v-733q0 -74 5 -153t18 -138h-113l-41 162h-10q-47 -80 -127 -133.5t-203 -53.5q-82 0 -144.5 19.5t-104.5 69t-63.5 132.5t-21.5 210zM303 1432v43h194 l134 -306h-93z" />
|
||||||
|
<glyph unicode="ú" horiz-adv-x="1103" d="M141 406v618h164v-584q0 -80 9.5 -140t32 -100t61 -60.5t98.5 -20.5q55 0 98 17.5t77 48t59.5 70.5t41.5 85v684h164v-733q0 -74 5 -153t18 -138h-113l-41 162h-10q-47 -80 -127 -133.5t-203 -53.5q-82 0 -144.5 19.5t-104.5 69t-63.5 132.5t-21.5 210zM463 1169l121 306 h182v-43l-207 -263h-96z" />
|
||||||
|
<glyph unicode="û" horiz-adv-x="1103" d="M141 406v618h164v-584q0 -80 9.5 -140t32 -100t61 -60.5t98.5 -20.5q55 0 98 17.5t77 48t59.5 70.5t41.5 85v684h164v-733q0 -74 5 -153t18 -138h-113l-41 162h-10q-47 -80 -127 -133.5t-203 -53.5q-82 0 -144.5 19.5t-104.5 69t-63.5 132.5t-21.5 210zM281 1126l252 373 h65l228 -373h-148l-80 136l-43 118l-45 -118l-92 -136h-137z" />
|
||||||
|
<glyph unicode="ü" horiz-adv-x="1103" d="M141 406v618h164v-584q0 -80 9.5 -140t32 -100t61 -60.5t98.5 -20.5q55 0 98 17.5t77 48t59.5 70.5t41.5 85v684h164v-733q0 -74 5 -153t18 -138h-113l-41 162h-10q-47 -80 -127 -133.5t-203 -53.5q-82 0 -144.5 19.5t-104.5 69t-63.5 132.5t-21.5 210zM256 1337 q0 47 27.5 76t72.5 29t73 -29t28 -76q0 -43 -28 -71.5t-73 -28.5t-72.5 28.5t-27.5 71.5zM649 1337q0 47 27.5 76t72.5 29q47 0 75 -29t28 -76q0 -43 -27.5 -71.5t-75.5 -28.5q-45 0 -72.5 28.5t-27.5 71.5z" />
|
||||||
|
<glyph unicode="ý" horiz-adv-x="954" d="M25 1024h188l246 -664l57 -196h10l45 198l199 662h166l-303 -920q-35 -100 -69 -194t-74.5 -168t-92 -118t-118.5 -44q-74 0 -121 21l28 141q27 -10 52 -10q57 0 110 60.5t88 207.5zM447 1169l121 306h182v-43l-207 -263h-96z" />
|
||||||
|
<glyph unicode="þ" horiz-adv-x="1107" d="M158 -410v1844h164v-512h8q41 59 108.5 93t163.5 34q205 0 305.5 -121t100.5 -396q0 -129 -34 -232t-95.5 -175t-148.5 -111t-193 -39q-76 0 -120 9.5t-95 31.5v-426h-164zM322 176q37 -29 84 -43t124 -14q141 0 224.5 105.5t83.5 310.5q0 84 -14.5 152.5t-46.5 116.5 t-82 74.5t-124 26.5q-201 2 -249 -219v-510z" />
|
||||||
|
<glyph unicode="ÿ" horiz-adv-x="954" d="M25 1024h188l246 -664l57 -196h10l45 198l199 662h166l-303 -920q-35 -100 -69 -194t-74.5 -168t-92 -118t-118.5 -44q-74 0 -121 21l28 141q27 -10 52 -10q57 0 110 60.5t88 207.5zM182 1337q0 47 27.5 76t72.5 29t73 -29t28 -76q0 -43 -28 -71.5t-73 -28.5t-72.5 28.5 t-27.5 71.5zM575 1337q0 47 27.5 76t72.5 29q47 0 75 -29t28 -76q0 -43 -27.5 -71.5t-75.5 -28.5q-45 0 -72.5 28.5t-27.5 71.5z" />
|
||||||
|
<glyph unicode="Œ" horiz-adv-x="1908" d="M115 717q0 358 151.5 549.5t431.5 191.5q96 0 159 -7t128 -17h780v-152h-610v-469h559v-151h-559v-510h621v-152h-791q-51 -10 -122.5 -17.5t-164.5 -7.5q-150 0 -259 53.5t-182 150.5t-107.5 233.5t-34.5 304.5zM295 717q0 -119 23.5 -225.5t74.5 -187.5t131 -129 t191 -48q59 0 121.5 4t148.5 31v1104q-57 23 -133 32t-154 9q-188 0 -295.5 -144.5t-107.5 -445.5z" />
|
||||||
|
<glyph unicode="œ" horiz-adv-x="1757" d="M100 512q0 260 116 398.5t333 138.5q129 0 218 -53.5t142 -135.5q53 86 144.5 137.5t214.5 51.5q70 0 139.5 -15.5t124.5 -58.5t90 -122t35 -208q0 -35 -2 -71.5t-8 -77.5h-662q0 -90 18.5 -161t57.5 -120t102.5 -73.5t153.5 -24.5q72 0 140.5 25.5t103.5 58.5l61 -119 q-61 -49 -154.5 -78t-197.5 -29q-127 0 -219.5 51.5t-145.5 139.5q-55 -92 -144 -141.5t-212 -49.5q-115 0 -200 38t-140 109t-82 170t-27 220zM270 512q0 -78 15.5 -149.5t48.5 -126t86 -86t129 -31.5q276 -2 276 393q0 80 -14 151.5t-47 125t-86 85t-129 31.5 q-279 2 -279 -393zM989 625h508v18q0 141 -61.5 202.5t-165.5 61.5q-119 0 -192.5 -64.5t-88.5 -217.5z" />
|
||||||
|
<glyph unicode="Ÿ" horiz-adv-x="1142" d="M16 1434h199l336 -627l35 -125h2l37 129l321 623h182l-469 -863v-571h-170v569zM273 1626q0 43 30.5 69.5t79.5 26.5q47 0 77 -26.5t30 -69.5q0 -41 -29.5 -67.5t-77.5 -26.5q-49 0 -79.5 26.5t-30.5 67.5zM666 1626q0 43 29.5 69.5t77.5 26.5q49 0 79.5 -26.5 t30.5 -69.5q0 -41 -30.5 -67.5t-79.5 -26.5q-47 0 -77 26.5t-30 67.5z" />
|
||||||
|
<glyph unicode="ˆ" horiz-adv-x="790" d="M123 1126l252 373h65l228 -373h-148l-80 136l-43 118l-45 -118l-92 -136h-137z" />
|
||||||
|
<glyph unicode="˜" horiz-adv-x="817" d="M123 1343q59 68 108.5 93.5t90.5 25.5q35 0 64.5 -13t57 -28.5t53 -28t54.5 -12.5q45 0 94 50l49 -89q-53 -59 -97 -80.5t-81 -21.5q-33 0 -61.5 12.5t-56 27.5t-55.5 28.5t-56 13.5q-27 0 -54.5 -14.5t-62.5 -49.5z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="891" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="1782" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="891" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="1782" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="594" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="445" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="297" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="297" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="222" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="356" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="99" />
|
||||||
|
<glyph unicode="‐" horiz-adv-x="737" d="M121 514v152h495v-152h-495z" />
|
||||||
|
<glyph unicode="‑" horiz-adv-x="737" d="M121 514v152h495v-152h-495z" />
|
||||||
|
<glyph unicode="‒" horiz-adv-x="737" d="M121 514v152h495v-152h-495z" />
|
||||||
|
<glyph unicode="–" horiz-adv-x="1351" d="M242 514v152h868v-152h-868z" />
|
||||||
|
<glyph unicode="—" horiz-adv-x="1679" d="M242 514v152h1196v-152h-1196z" />
|
||||||
|
<glyph unicode="‘" horiz-adv-x="397" d="M82 1313q0 68 19.5 116t47 81.5t57.5 54t52 28.5l51 -71q-45 -23 -72.5 -61t-27.5 -95q8 2 22 2q41 0 63.5 -28.5t22.5 -69.5q0 -47 -30.5 -75t-77.5 -28q-55 0 -91 37t-36 109z" />
|
||||||
|
<glyph unicode="’" horiz-adv-x="397" d="M82 1350q0 47 29.5 73.5t76.5 26.5q57 0 93 -36t36 -107q0 -68 -19 -117t-47 -83t-58.5 -54.5t-53.5 -28.5l-51 70q47 25 73.5 61.5t26.5 95.5q-8 -2 -22 -2q-39 0 -61.5 28t-22.5 73z" />
|
||||||
|
<glyph unicode="‚" horiz-adv-x="397" d="M82 103q0 47 29.5 73.5t76.5 26.5q57 0 93 -36t36 -107q0 -68 -19 -117t-47 -83t-58.5 -54.5t-53.5 -28.5l-51 70q47 25 73.5 61.5t26.5 95.5q-8 -2 -22 -2q-39 0 -61.5 28t-22.5 73z" />
|
||||||
|
<glyph unicode="“" horiz-adv-x="696" d="M82 1313q0 68 19.5 116t47 81.5t57.5 54t52 28.5l51 -71q-45 -23 -72.5 -61t-27.5 -95q8 2 22 2q41 0 63.5 -28.5t22.5 -69.5q0 -47 -30.5 -75t-77.5 -28q-55 0 -91 37t-36 109zM381 1313q0 68 19.5 116t47 81.5t57.5 54t52 28.5l51 -71q-45 -23 -72.5 -61t-27.5 -95 q8 2 22 2q41 0 63.5 -28.5t22.5 -69.5q0 -47 -30.5 -75t-77.5 -28q-55 0 -91 37t-36 109z" />
|
||||||
|
<glyph unicode="”" horiz-adv-x="696" d="M82 1350q0 47 29.5 73.5t76.5 26.5q57 0 93 -36t36 -107q0 -68 -19 -117t-47 -83t-58.5 -54.5t-53.5 -28.5l-51 70q47 25 73.5 61.5t26.5 95.5q-8 -2 -22 -2q-39 0 -61.5 28t-22.5 73zM381 1350q0 47 29.5 73.5t76.5 26.5q57 0 93 -36t36 -107q0 -68 -19 -117t-47 -83 t-58.5 -54.5t-53.5 -28.5l-51 70q47 25 73.5 61.5t26.5 95.5q-8 -2 -22 -2q-39 0 -61.5 28t-22.5 73z" />
|
||||||
|
<glyph unicode="„" horiz-adv-x="696" d="M82 103q0 47 29.5 73.5t76.5 26.5q57 0 93 -36t36 -107q0 -68 -19 -117t-47 -83t-58.5 -54.5t-53.5 -28.5l-51 70q47 25 73.5 61.5t26.5 95.5q-8 -2 -22 -2q-39 0 -61.5 28t-22.5 73zM381 103q0 47 29.5 73.5t76.5 26.5q57 0 93 -36t36 -107q0 -68 -19 -117t-47 -83 t-58.5 -54.5t-53.5 -28.5l-51 70q47 25 73.5 61.5t26.5 95.5q-8 -2 -22 -2q-39 0 -61.5 28t-22.5 73z" />
|
||||||
|
<glyph unicode="•" horiz-adv-x="925" d="M178 637q0 63 22.5 115.5t60.5 90.5t90 58.5t112 20.5q59 0 111.5 -19.5t90 -56.5t60.5 -89t23 -120t-23 -120t-60.5 -89t-90 -56.5t-111.5 -19.5t-111.5 19.5t-90.5 56.5t-60.5 89t-22.5 120z" />
|
||||||
|
<glyph unicode="…" horiz-adv-x="1554" d="M145 94q0 55 32 87t85 32q55 0 88 -31.5t33 -87.5q0 -53 -33 -86t-88 -33q-53 0 -85 33t-32 86zM666 94q0 55 31.5 87t84.5 32q55 0 88 -31.5t33 -87.5q0 -53 -32.5 -86t-88.5 -33q-53 0 -84.5 33t-31.5 86zM1186 94q0 55 31.5 87t85.5 32q55 0 87.5 -31.5t32.5 -87.5 q0 -53 -32.5 -86t-87.5 -33q-53 0 -85 33t-32 86z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="356" />
|
||||||
|
<glyph unicode="‹" horiz-adv-x="608" d="M80 530l328 471l108 -88l-199 -297l-98 -84l98 -73l211 -291l-108 -90z" />
|
||||||
|
<glyph unicode="›" horiz-adv-x="608" d="M80 911l108 90l340 -452l-327 -471l-109 88l199 297l98 84l-98 74z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="445" />
|
||||||
|
<glyph unicode="€" d="M20 514l37 135h111v68v38.5t2 39.5h-150l37 135h127q23 141 76 240.5t128 164t168 94t198 29.5q104 0 180 -13t131 -36l-45 -145q-47 23 -110.5 35t-153.5 12q-70 0 -133.5 -20.5t-115.5 -65.5t-90 -118t-59 -177h578l-35 -135h-557q-2 -18 -2 -38v-40v-34.5t2 -33.5h516 l-35 -135h-467q35 -199 142.5 -295t283.5 -96q80 0 146.5 18.5t113.5 46.5l41 -129q-61 -47 -152 -65.5t-183 -18.5q-236 0 -382.5 130.5t-187.5 408.5h-160z" />
|
||||||
|
<glyph unicode="™" horiz-adv-x="1812" d="M78 1294v140h717v-140h-279v-598h-160v598h-278zM877 696v738h159l215 -344l58 -119h2l61 123l199 340h162v-738h-156v342l20 211h-8l-80 -174l-178 -287h-67l-183 285l-73 176h-9l27 -209v-344h-149z" />
|
||||||
|
<glyph unicode="" horiz-adv-x="1024" d="M0 0v1024h1024v-1024h-1024z" />
|
||||||
|
</font>
|
||||||
|
</defs></svg>
|
After Width: | Height: | Size: 64 KiB |
242
source/app/fonts/svg/ptsansbold.svg
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<metadata></metadata>
|
||||||
|
<defs>
|
||||||
|
<font id="pt_sansbold" horiz-adv-x="1161" >
|
||||||
|
<font-face units-per-em="2048" ascent="1536" descent="-512" />
|
||||||
|
<missing-glyph horiz-adv-x="518" />
|
||||||
|
<glyph unicode="fi" horiz-adv-x="1132" d="M25 799v225h141v57q0 195 100.5 284t290.5 89q141 0 251 -21.5t177 -60.5l-70 -207q-53 29 -128.5 46.5t-168.5 17.5q-59 0 -96 -13.5t-57.5 -39t-26.5 -64.5t-6 -88h576v-1024h-267v799h-309v-799h-266v799h-141z" />
|
||||||
|
<glyph unicode="fl" horiz-adv-x="1214" d="M25 799v225h141v57q0 193 93 286t321 93q47 0 108.5 -4t121.5 -9t112.5 -11t81.5 -13v-1079q0 -72 18 -104.5t57 -32.5q25 0 48.5 4t58.5 18l31 -209q-33 -16 -101.5 -32.5t-140.5 -16.5q-117 0 -177.5 54.5t-60.5 179.5v1016q-27 6 -73 10t-89 4q-47 0 -75.5 -14.5 t-44 -41t-19.5 -66.5t-4 -89h154v-225h-154v-799h-266v799h-141z" />
|
||||||
|
<glyph horiz-adv-x="2048" />
|
||||||
|
<glyph horiz-adv-x="2048" />
|
||||||
|
<glyph unicode="
" horiz-adv-x="518" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="518" />
|
||||||
|
<glyph unicode="	" horiz-adv-x="518" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="518" />
|
||||||
|
<glyph unicode="!" horiz-adv-x="602" d="M176 135q0 72 45 114t119 42q78 0 123 -42t45 -114t-45 -115t-123 -43q-74 0 -119 43t-45 115zM205 760v674h274v-674l-53 -334h-168z" />
|
||||||
|
<glyph unicode=""" horiz-adv-x="823" d="M184 991v443h234l-74 -443h-160zM487 991v443h234l-74 -443h-160z" />
|
||||||
|
<glyph unicode="#" d="M39 420l45 198h154l51 218h-148l45 198h150l72 295h217l-70 -295h182l72 295h217l-70 -295h148l-51 -198h-144l-51 -218h141l-49 -198h-139l-74 -316h-219l74 316h-182l-74 -316h-219l73 316h-151zM457 618h182l51 218h-182z" />
|
||||||
|
<glyph unicode="$" d="M141 1053q0 176 93.5 273t252.5 126v186h213v-178q90 -6 158 -24.5t125 -42.5l-74 -228q-35 16 -88 32.5t-121 25.5v-383q63 -29 128 -65t115 -85t82 -115.5t32 -158.5q0 -188 -95.5 -294t-261.5 -136v-191h-213v178q-117 4 -204.5 24.5t-137.5 47.5l80 231 q37 -23 103.5 -43t158.5 -28v420q-63 29 -125.5 63.5t-111.5 83.5t-79 117.5t-30 163.5zM408 1075q0 -61 48 -102t119 -76v332q-96 -4 -131.5 -47.5t-35.5 -106.5zM612 205q90 10 134.5 57t44.5 123q0 66 -52.5 108t-126.5 76v-364z" />
|
||||||
|
<glyph unicode="%" horiz-adv-x="1720" d="M105 1110q0 92 26.5 157.5t73.5 108.5t113.5 62.5t144.5 19.5t143.5 -18.5t113.5 -59.5t74.5 -107.5t28.5 -162.5q-2 -96 -28.5 -162.5t-74.5 -107.5t-113.5 -59.5t-143.5 -18.5t-144.5 18.5t-113.5 59.5t-73.5 107.5t-26.5 162.5zM207 113l1179 1349l150 -135 l-1180 -1356zM342 1110q0 -176 121 -176q63 0 91 38t30 138q-2 98 -29.5 137t-91.5 39q-63 0 -92 -39t-29 -137zM936 350q0 92 26.5 157.5t73.5 108.5t113.5 62.5t144.5 19.5t143.5 -18.5t113.5 -59.5t74.5 -107.5t28.5 -162.5q-2 -96 -28.5 -162.5t-74.5 -107.5 t-113.5 -59.5t-143.5 -18.5t-144.5 18.5t-113.5 59.5t-73.5 107.5t-26.5 162.5zM1173 350q0 -176 121 -176q63 0 91 38t30 138q-2 98 -29.5 137t-91.5 39q-63 0 -92 -39t-29 -137z" />
|
||||||
|
<glyph unicode="&" horiz-adv-x="1667" d="M188 397q0 78 26 148.5t72 132t109.5 115t136.5 94.5q-51 68 -83.5 137.5t-32.5 146.5q0 51 19.5 103.5t61.5 94.5t109.5 67.5t163.5 25.5q94 0 160.5 -22.5t107.5 -59.5t59.5 -84t18.5 -96q0 -84 -59.5 -175t-202.5 -175q72 -111 143.5 -203t159.5 -182q47 51 85 128 t67 157l192 -103q-12 -37 -33.5 -81t-47 -89t-52.5 -85t-49 -68q66 -59 115 -93t100 -63l-141 -197q-57 27 -118 71t-120 101q-74 -68 -184.5 -120t-272.5 -52q-106 0 -199 29t-162 84t-109 134t-40 179zM455 420q0 -104 76.5 -163.5t201.5 -59.5q82 0 153.5 33.5 t108.5 74.5q-104 109 -190 216.5t-150 203.5q-98 -76 -149 -146.5t-51 -158.5zM682 1159q0 -86 74 -184q80 51 115.5 96t35.5 86q0 49 -27.5 78t-88.5 29q-55 0 -82 -29t-27 -76z" />
|
||||||
|
<glyph unicode="'" horiz-adv-x="520" d="M184 991v443h234l-74 -443h-160z" />
|
||||||
|
<glyph unicode="(" horiz-adv-x="669" d="M123 498q0 113 18.5 237.5t59.5 250.5t107.5 247t162.5 225l172 -110q-72 -96 -120 -201t-77.5 -214.5t-43 -220t-13.5 -214.5q0 -98 14.5 -209t45 -220.5t80 -214t118.5 -190.5l-182 -115q-94 98 -159.5 216t-105.5 242t-58.5 250t-18.5 241z" />
|
||||||
|
<glyph unicode=")" horiz-adv-x="667" d="M23 1341l180 117q94 -98 159.5 -216t105.5 -241.5t58.5 -249.5t18.5 -241q0 -113 -18.5 -238t-59.5 -250.5t-107.5 -246.5t-162.5 -226l-172 113q76 102 125 207.5t77.5 213t40 215.5t11.5 212q0 98 -15.5 207.5t-46.5 219.5t-79 213t-115 191z" />
|
||||||
|
<glyph unicode="*" horiz-adv-x="774" d="M82 1112v152h123l121 -35l-105 90l-57 102l131 76l57 -94l31 -121l31 113l57 100l131 -72l-61 -106l-99 -88l133 33h117v-150h-112l-125 33l102 -96l51 -86l-131 -76l-55 94l-41 131l-27 -119l-59 -100l-131 76l59 100l92 76l-112 -33h-121z" />
|
||||||
|
<glyph unicode="+" horiz-adv-x="1079" d="M88 578v229h332v346h239v-346h334v-229h-334v-351h-239v351h-332z" />
|
||||||
|
<glyph unicode="," horiz-adv-x="466" d="M76 -193q55 23 96 74t45 109q-47 -6 -89 28.5t-42 112.5q0 70 46 111t114 41q86 0 135 -57.5t49 -151.5q0 -92 -28.5 -159t-70.5 -111t-90 -69.5t-87 -37.5z" />
|
||||||
|
<glyph unicode="-" horiz-adv-x="737" d="M111 471v236h514v-236h-514z" />
|
||||||
|
<glyph unicode="." horiz-adv-x="503" d="M86 135q0 72 45 114t119 42q78 0 123 -42t45 -114t-45 -115t-123 -43q-74 0 -119 43t-45 115z" />
|
||||||
|
<glyph unicode="/" horiz-adv-x="835" d="M-49 -193l731 1651l201 -90l-731 -1655z" />
|
||||||
|
<glyph unicode="0" d="M82 719q0 377 129 560t371 183q258 0 378.5 -181t120.5 -562q0 -379 -130 -563.5t-371 -184.5q-256 0 -377 194t-121 554zM348 719q0 -250 54.5 -386t179.5 -136q121 0 177 124.5t56 397.5q0 248 -53 383t-182 135q-123 0 -177.5 -127t-54.5 -391z" />
|
||||||
|
<glyph unicode="1" d="M129 1081l467 377h149v-1233h279v-225h-817v225h285v809l30 140l-98 -121l-182 -125z" />
|
||||||
|
<glyph unicode="2" d="M141 0v137q49 51 110.5 120t124 145.5t122 158.5t106.5 165t75 161t28 147q0 84 -48.5 138.5t-152.5 54.5q-66 0 -134.5 -28t-115.5 -71l-106 189q80 66 181 105.5t238 39.5q88 0 162 -24.5t127 -71.5t84 -118t31 -165q0 -104 -38 -210.5t-96.5 -209t-129 -197.5 t-138.5 -175l-108 -84v-10l147 28h394v-225h-863z" />
|
||||||
|
<glyph unicode="3" d="M160 35l71 221q53 -27 118 -43t145 -16q127 0 193.5 67.5t66.5 163.5q0 117 -70 172t-219 55h-148v142l248 338l117 92l-162 -19h-344v226h782v-146l-288 -387l-90 -55v-10l86 12q72 -6 136 -33t112.5 -77t77 -123.5t28.5 -170.5q0 -121 -40 -209t-110.5 -147t-165 -88 t-202.5 -29q-90 0 -186.5 16.5t-155.5 47.5z" />
|
||||||
|
<glyph unicode="4" d="M39 399v152l649 893h219v-832h226v-213h-226v-399h-248v399h-620zM285 596l131 16h243v314l19 172h-8l-70 -148l-213 -276z" />
|
||||||
|
<glyph unicode="5" d="M139 29l72 221q47 -20 103.5 -31.5t136.5 -11.5q135 0 206.5 65.5t71.5 180.5q0 123 -84 180t-239 57l-162 -6v750h704v-250h-475v-277l84 8q100 -4 181 -36.5t138.5 -91t88 -141.5t30.5 -185q0 -121 -41 -213t-113.5 -153.5t-171 -92.5t-214.5 -31q-92 0 -175 15.5 t-141 42.5z" />
|
||||||
|
<glyph unicode="6" d="M106 514q0 203 58.5 366.5t158 285.5t231.5 197t280 99l59 -211q-102 -16 -188.5 -63t-153 -112.5t-112.5 -146.5t-64 -167q41 51 106.5 87t163.5 36q92 0 170 -29t133.5 -85t86 -138.5t30.5 -188.5q0 -100 -34 -186t-95.5 -149.5t-148.5 -100.5t-191 -37 q-106 0 -195.5 34t-155 101.5t-102.5 170t-37 237.5zM360 465q0 -49 14.5 -97.5t42 -86t70.5 -61t103 -23.5q96 0 156.5 65.5t60.5 167.5q0 229 -225 229q-82 0 -138.5 -36.5t-78.5 -85.5q-4 -23 -4.5 -39.5t-0.5 -32.5z" />
|
||||||
|
<glyph unicode="7" d="M123 1184v250h924v-78l-574 -1356h-260l469 1104l90 100l-123 -20h-526z" />
|
||||||
|
<glyph unicode="8" d="M125 350q0 72 18.5 128.5t52 102.5t80 82.5t99.5 67.5q-100 63 -157.5 146.5t-57.5 205.5q0 80 29.5 150t86 121t136.5 79.5t180 28.5q92 0 168 -24.5t130 -69.5t84 -109.5t30 -142.5q0 -121 -54.5 -205t-158.5 -153q123 -72 185 -158t62 -221q0 -92 -33.5 -167t-95 -128 t-147.5 -83t-189 -30q-102 0 -185 28t-141.5 77t-90 118.5t-31.5 155.5zM367 395q0 -82 56 -140t157 -58q92 0 148 45t56 135q0 47 -22.5 86t-58 70.5t-79.5 58t-89 51.5q-96 -55 -132 -119.5t-36 -128.5zM414 1079q0 -49 18.5 -86t50 -64.5t71.5 -51t83 -43.5 q123 104 123 229q0 86 -50.5 130t-121.5 44q-90 0 -132 -47.5t-42 -110.5z" />
|
||||||
|
<glyph unicode="9" d="M92 985q0 104 32 192.5t92 151t147.5 98t199.5 35.5q231 0 363.5 -138t132.5 -402q0 -238 -60.5 -411t-162 -289t-234.5 -177t-280 -74l-58 209q113 14 201 55t151.5 101.5t103.5 137.5t56 165q-49 -53 -105.5 -73.5t-150.5 -20.5q-78 0 -154.5 26.5t-137 81t-98.5 137 t-38 195.5zM350 999q0 -117 65.5 -176t164.5 -59q84 0 137 26.5t82 65.5q6 43 6 82q0 57 -14.5 112.5t-44 98.5t-75.5 68.5t-110 25.5q-100 0 -155.5 -64.5t-55.5 -179.5z" />
|
||||||
|
<glyph unicode=":" horiz-adv-x="550" d="M190 135q0 72 45 114t119 42q78 0 123 -42t45 -114t-45 -115t-123 -43q-74 0 -119 43t-45 115zM190 876q0 72 45 114t119 42q78 0 123 -42t45 -114t-45 -115t-123 -43q-74 0 -119 43t-45 115z" />
|
||||||
|
<glyph unicode=";" horiz-adv-x="593" d="M158 -193q55 23 96 74t45 109q-47 -6 -89 28.5t-42 112.5q0 70 46 111t114 41q86 0 135 -57.5t49 -151.5q0 -92 -28.5 -159t-70.5 -111t-90 -69.5t-87 -37.5zM168 876q0 72 45 114t119 42q78 0 123 -42t45 -114t-45 -115t-123 -43q-74 0 -119 43t-45 115z" />
|
||||||
|
<glyph unicode="<" horiz-adv-x="1079" d="M82 584v143l790 473l117 -184l-459 -285l-186 -72l184 -63l471 -281l-116 -184z" />
|
||||||
|
<glyph unicode="=" horiz-adv-x="1079" d="M88 383v229h905v-229h-905zM88 775v229h905v-229h-905z" />
|
||||||
|
<glyph unicode=">" horiz-adv-x="1079" d="M80 1018l117 182l800 -452v-144l-790 -473l-117 186l459 283l186 74l-184 61z" />
|
||||||
|
<glyph unicode="?" horiz-adv-x="929" d="M47 1339q78 53 179.5 88t244.5 35q193 0 301.5 -93t108.5 -251q0 -104 -28 -172.5t-69 -117t-90 -85t-90 -78.5t-69.5 -97.5t-28.5 -141.5h-227q-10 106 10 181t56 129.5t82 94t86 76.5t66.5 77t26.5 95q0 72 -40 115t-142 43q-33 0 -70 -7t-73.5 -20.5t-70.5 -31 t-60 -35.5zM238 135q0 72 45 114t118 42q78 0 123 -42t45 -114t-45 -115t-123 -43q-74 0 -118.5 43t-44.5 115z" />
|
||||||
|
<glyph unicode="@" horiz-adv-x="2168" d="M150 483q0 223 79.5 403.5t215 307.5t313.5 195.5t377 68.5q188 0 350 -54t280.5 -155.5t186 -248t67.5 -332.5q0 -131 -46 -246t-127 -199t-188.5 -133t-230.5 -49q-51 0 -95 11t-73.5 38t-44 70t-8.5 106h-8q-31 -43 -66.5 -84t-78.5 -72.5t-94.5 -50t-112.5 -18.5 q-49 0 -94 21.5t-78 60.5t-52.5 94t-19.5 123q0 127 41 247t111.5 212t164 148.5t197.5 56.5q72 0 121 -21.5t90 -56.5l64 65h143l-98 -555q-16 -96 -1 -139t68 -43t104.5 24.5t92.5 76t66.5 129t25.5 184.5q0 154 -51 262t-140.5 179t-210 103.5t-260.5 32.5 q-160 0 -297 -57.5t-238 -157.5t-158.5 -238.5t-57.5 -299.5q0 -160 48 -287t140 -216t228.5 -137.5t312.5 -48.5q59 0 135 14.5t137 43.5l64 -197q-84 -41 -171 -57.5t-200 -16.5q-199 0 -367.5 57.5t-292.5 170t-193.5 279.5t-69.5 386zM852 408q0 -68 27.5 -111t95.5 -43 q29 0 61.5 17.5t63 46t59.5 65.5t51 78l52 282q-27 23 -55.5 35.5t-71.5 12.5q-61 0 -113.5 -35t-90.5 -90.5t-58.5 -124t-20.5 -133.5z" />
|
||||||
|
<glyph unicode="A" horiz-adv-x="1239" d="M0 0l516 1444h207l516 -1444h-295l-115 317h-440l-108 -317h-281zM461 543h307l-106 319l-44 225h-10l-43 -227z" />
|
||||||
|
<glyph unicode="B" horiz-adv-x="1210" d="M123 10v1413q39 6 89 12.5t107.5 10.5t118 6t119.5 2q100 0 195.5 -15.5t170 -54t119.5 -108.5t45 -176q0 -53 -13 -106.5t-44 -97.5t-80 -78t-119 -50v-12q61 -10 117 -35t96.5 -68t64.5 -104.5t24 -145.5q0 -111 -47.5 -191.5t-126 -131.5t-179 -75.5t-207.5 -24.5h-89 t-116.5 3t-127 9t-117.5 18zM393 223q10 -4 33 -6t48.5 -3t53 -2t47.5 -1q51 0 99.5 12.5t85.5 38t59.5 64.5t22.5 92q0 68 -27 106.5t-70 60t-96 27.5t-106 6h-150v-395zM393 831h90q29 0 67 2.5t62 6.5q78 25 134.5 74t56.5 128q0 53 -20.5 88t-54.5 55.5t-77 29t-90 8.5 q-53 0 -98 -2t-70 -7v-383z" />
|
||||||
|
<glyph unicode="C" horiz-adv-x="1144" d="M78 717q0 211 58.5 353t151.5 229t207.5 125t229.5 38q123 0 208 -16t140 -39l-55 -238q-47 23 -111.5 33t-156.5 10q-170 0 -273.5 -120.5t-103.5 -374.5q0 -111 24.5 -202t74.5 -155.5t125 -100.5t173 -36q92 0 155.5 18.5t110.5 47.5l58 -230q-66 -47 -167.5 -67.5 t-207.5 -20.5q-129 0 -245 40t-204 129t-140 231.5t-52 345.5z" />
|
||||||
|
<glyph unicode="D" horiz-adv-x="1325" d="M123 -2v1436q43 6 97 10t111.5 6t112 3t97.5 1q190 0 325 -53t219 -149.5t123 -229.5t39 -293q0 -145 -36.5 -280.5t-123 -240t-226.5 -168t-347 -63.5q-33 0 -87 2.5t-112.5 5.5t-111.5 6t-80 7zM403 236q8 -2 28 -3.5t42.5 -2.5t43 -2t30.5 -1q119 0 197.5 42 t124.5 112t64.5 161t18.5 187q0 84 -16 169t-60.5 152.5t-120 110.5t-192.5 43q-45 0 -91 -2t-69 -6v-960z" />
|
||||||
|
<glyph unicode="E" horiz-adv-x="1069" d="M123 0v1434h850v-250h-570v-334h519v-250h-519v-350h580v-250h-860z" />
|
||||||
|
<glyph unicode="F" horiz-adv-x="1040" d="M123 0v1434h850v-250h-570v-355h525v-249h-525v-580h-280z" />
|
||||||
|
<glyph unicode="G" horiz-adv-x="1247" d="M78 717q0 203 58.5 345t153.5 231t214 129t241 40q123 0 216.5 -18.5t148.5 -38.5l-57 -236q-51 20 -115 31.5t-162 11.5q-88 0 -161.5 -26.5t-128 -87t-84 -154.5t-29.5 -229q0 -129 28.5 -222.5t79.5 -153.5t120 -89t147 -29q53 0 104 13.5t86 39.5v271l-309 33v170 h534v-639q-86 -72 -205.5 -105t-236.5 -33q-137 0 -255 43t-204 134.5t-135 232.5t-49 336z" />
|
||||||
|
<glyph unicode="H" horiz-adv-x="1333" d="M123 0v1434h280v-584h525v584h280v-1434h-280v600h-525v-600h-280z" />
|
||||||
|
<glyph unicode="I" horiz-adv-x="583" d="M152 0v1434h280v-1434h-280z" />
|
||||||
|
<glyph unicode="J" horiz-adv-x="684" d="M-47 23l61 229q53 -27 121 -27q86 0 109.5 63.5t23.5 168.5v977h281v-1049q0 -82 -18.5 -155.5t-60.5 -130t-107.5 -90.5t-159.5 -34q-59 0 -129 12.5t-121 35.5z" />
|
||||||
|
<glyph unicode="K" horiz-adv-x="1269" d="M123 0v1434h280v-635l66 28l395 607h320l-418 -603l-111 -77l115 -80l477 -674h-346l-424 612h-74v-612h-280z" />
|
||||||
|
<glyph unicode="L" horiz-adv-x="1052" d="M123 0v1434h280v-1184h627v-250h-907z" />
|
||||||
|
<glyph unicode="M" horiz-adv-x="1638" d="M123 0v1434h256l383 -656l67 -164h9l61 168l363 652h254v-1434h-281v743l31 285h-13l-88 -229l-305 -535h-90l-321 537l-91 227h-10l41 -283v-745h-266z" />
|
||||||
|
<glyph unicode="N" horiz-adv-x="1345" d="M123 0v1444h205l542 -764l109 -219h10l-33 219v754h267v-1444h-205l-539 758l-112 225h-11l33 -225v-748h-266z" />
|
||||||
|
<glyph unicode="O" horiz-adv-x="1372" d="M78 717q0 358 157.5 551.5t450.5 193.5q154 0 268.5 -53t190.5 -151.5t112.5 -235.5t36.5 -305q0 -358 -158.5 -552t-449.5 -194q-156 0 -270.5 53.5t-189 151.5t-111.5 235.5t-37 305.5zM373 717q0 -109 18.5 -200t56 -156.5t97 -102.5t141.5 -37q150 0 231.5 117 t81.5 379q0 104 -17 194t-54 158t-96.5 105.5t-145.5 37.5q-150 0 -231.5 -119.5t-81.5 -375.5z" />
|
||||||
|
<glyph unicode="P" horiz-adv-x="1171" d="M123 0v1419q86 16 189.5 25.5t205.5 9.5q106 0 214 -17.5t194 -69.5t140 -145.5t54 -242.5q0 -135 -47 -228.5t-125 -152.5t-177 -86t-206 -27h-32.5t-47 1t-48 3.5t-34.5 4.5v-494h-280zM403 737q8 -2 24.5 -4t35 -3t36 -1h25.5q55 0 109.5 10.5t97.5 38t68.5 76.5 t25.5 129q0 68 -24.5 112t-64.5 70.5t-91 36.5t-104 10q-41 0 -78 -3t-60 -7v-465z" />
|
||||||
|
<glyph unicode="Q" horiz-adv-x="1372" d="M78 717q0 358 157.5 551.5t450.5 193.5q154 0 268.5 -53t190.5 -151.5t112.5 -235.5t36.5 -305q0 -358 -158.5 -552t-449.5 -194q-156 0 -270.5 53.5t-189 151.5t-111.5 235.5t-37 305.5zM373 717q0 -109 18.5 -200t56 -156.5t97 -102.5t141.5 -37q150 0 231.5 117 t81.5 379q0 104 -17 194t-54 158t-96.5 105.5t-145.5 37.5q-150 0 -231.5 -119.5t-81.5 -375.5zM412 -76q57 12 118 13q86 0 171 -20.5t173.5 -44.5t180.5 -44.5t194 -20.5q45 0 92.5 5.5t96.5 17.5v-244q-94 -26 -192 -26h-7q-104 0 -202.5 21.5t-190.5 46t-178 46 t-162 21.5q-49 0 -94 -12v241z" />
|
||||||
|
<glyph unicode="R" horiz-adv-x="1232" d="M123 0v1419q47 8 101.5 15.5t108.5 11.5t105 6t94 2q100 0 197.5 -18.5t174.5 -63.5t123 -124t46 -197q0 -176 -82 -287t-219 -154l100 -63l328 -547h-323l-326 561l-148 27v-588h-280zM403 778h119q117 0 186.5 53.5t69.5 176.5q0 92 -57 144t-168 52q-43 0 -85 -2 t-65 -8v-416z" />
|
||||||
|
<glyph unicode="S" horiz-adv-x="1085" d="M55 57l90 240q23 -12 59 -26.5t81 -27t95 -20.5t103 -8q125 0 191.5 42t66.5 128q0 66 -48 106.5t-120.5 74.5t-157.5 70t-158 88t-121 130t-48 199q0 104 35 181t99.5 128t152.5 75.5t196 24.5q125 0 236 -21.5t182 -62.5l-88 -235q-45 29 -135 52.5t-195 23.5 q-98 0 -150 -39t-52 -105q0 -61 48 -102t120.5 -76t157.5 -72t158 -89t121 -129t48 -191q0 -115 -38 -198t-106.5 -138t-166 -82t-213.5 -27q-154 0 -270.5 29t-172.5 57z" />
|
||||||
|
<glyph unicode="T" horiz-adv-x="1163" d="M23 1184v250h1118v-250h-418v-1184h-281v1184h-419z" />
|
||||||
|
<glyph unicode="U" horiz-adv-x="1284" d="M117 473v961h280v-906q0 -84 15.5 -142t48.5 -94t82 -51.5t114 -15.5q129 0 186.5 72t57.5 231v906h266v-926q0 -139 -36.5 -239.5t-102 -166t-160 -96.5t-206.5 -31q-545 0 -545 498z" />
|
||||||
|
<glyph unicode="V" horiz-adv-x="1232" d="M-18 1434h325l287 -842l37 -244h10l41 246l274 840h295l-532 -1444h-201z" />
|
||||||
|
<glyph unicode="W" horiz-adv-x="1765" d="M0 1434h305l191 -801l26 -254h8l29 258l250 797h184l246 -801l29 -254h8l31 258l174 797h284l-395 -1444h-188l-256 796l-35 220h-10l-35 -222l-254 -794h-199z" />
|
||||||
|
<glyph unicode="X" horiz-adv-x="1296" d="M20 0l441 729l-400 705h338l222 -414l49 -146l47 146l231 414h305l-413 -691l434 -743h-334l-252 442l-55 152l-53 -152l-254 -442h-306z" />
|
||||||
|
<glyph unicode="Y" horiz-adv-x="1212" d="M-4 1434h334l262 -539l29 -152h10l31 156l253 535h302l-469 -899v-535h-281v532z" />
|
||||||
|
<glyph unicode="Z" horiz-adv-x="1103" d="M55 0v250l607 848l106 86h-713v250h994v-250l-611 -856l-104 -78h715v-250h-994z" />
|
||||||
|
<glyph unicode="[" horiz-adv-x="663" d="M123 -471v1905h481v-226h-227v-1454h227v-225h-481z" />
|
||||||
|
<glyph unicode="\" horiz-adv-x="868" d="M-49 1368l209 88l737 -1651l-203 -92z" />
|
||||||
|
<glyph unicode="]" horiz-adv-x="663" d="M59 -246h228v1454h-228v226h482v-1905h-482v225z" />
|
||||||
|
<glyph unicode="^" horiz-adv-x="1024" d="M41 846l401 598h142l379 -598h-269l-145 250l-43 143l-51 -145l-160 -248h-254z" />
|
||||||
|
<glyph unicode="_" horiz-adv-x="909" d="M0 -240h909v-219h-909v219z" />
|
||||||
|
<glyph unicode="`" horiz-adv-x="647" d="M123 1413v62h278l123 -316h-147z" />
|
||||||
|
<glyph unicode="a" horiz-adv-x="1015" d="M47 283q0 94 42 158.5t121 104.5q78 40 188 55q78 11 170 10q36 0 75 -1q4 36 4 66q-1 65 -21 99q-30 50 -137 50q-80 0 -169 -16t-146 -43l-63 199q82 37 194.5 58t235.5 21q106 0 178 -25.5t113.5 -72.5t59 -112.5t17.5 -147.5q0 -90 -6 -181t-7 -179v-25q0 -75 5 -146 q6 -83 31 -157h-217l-43 141h-10q-41 -63 -114 -109t-188 -46q-72 0 -129 21.5t-98 61t-63.5 94t-22.5 122.5zM322 324q0 -57 34 -89t93 -32q80 0 127 35.5t69 76.5v134q-36 3 -71 3q-26 0 -50 -2q-58 -4 -103.5 -18t-72 -40.5t-26.5 -67.5z" />
|
||||||
|
<glyph unicode="b" horiz-adv-x="1097" d="M117 45v1389h266v-492h8q43 49 110.5 78t149.5 29q184 0 281.5 -126t97.5 -384q0 -276 -136 -420t-374 -144q-131 0 -239.5 21.5t-163.5 48.5zM383 229q33 -16 71 -22t81 -6q109 0 165 78.5t56 250.5q-1 293 -183 293q-74 0 -119.5 -37.5t-70.5 -109.5v-447z" />
|
||||||
|
<glyph unicode="c" horiz-adv-x="886" d="M68 512q0 260 116.5 400.5t339.5 140.5q113 0 181.5 -18.5t123.5 -47.5l-63 -217q-47 23 -93 35t-106 12q-111 0 -168 -72.5t-57 -232.5q0 -66 14.5 -121t43 -96t74.5 -64.5t108 -23.5q68 0 114.5 17.5t83.5 41.5l62 -203q-61 -45 -148.5 -68.5t-179.5 -23.5 q-123 0 -208 39t-138 109.5t-76.5 171t-23.5 221.5z" />
|
||||||
|
<glyph unicode="d" horiz-adv-x="1103" d="M68 496q0 262 118.5 407.5t348.5 145.5q63 0 104 -7.5t82 -23.5v416h266v-1074q0 -86 2 -172t19 -190h-191l-37 133h-8q-41 -72 -117.5 -116t-181.5 -44q-193 0 -299 127t-106 398zM342 487q0 -131 46.5 -210.5t146.5 -79.5q78 0 122.5 37.5t63.5 109.5v434 q-29 23 -63.5 34t-90.5 11q-113 0 -169 -75.5t-56 -260.5z" />
|
||||||
|
<glyph unicode="e" horiz-adv-x="1040" d="M68 512q0 270 129 405.5t362 135.5q78 0 151.5 -20.5t131 -67.5t92.5 -127t35 -199q0 -43 -5.5 -92t-15.5 -103h-614q6 -129 66.5 -194.5t195.5 -65.5q84 0 150.5 26t101.5 52l88 -174q-61 -49 -166.5 -83t-224.5 -34q-248 0 -362.5 144.5t-114.5 396.5zM340 610h381 q1 18 1 34q0 86 -35 136q-42 60 -132 60q-104 0 -154.5 -62.5t-60.5 -167.5z" />
|
||||||
|
<glyph unicode="f" horiz-adv-x="657" d="M23 799v225h141v57q0 195 82 282t237 87q164 0 273 -39l-51 -213q-47 16 -83 21.5t-75 5.5q-41 0 -64.5 -12.5t-35 -38t-14.5 -63.5t-3 -87h225v-225h-225v-799h-266v799h-141z" />
|
||||||
|
<glyph unicode="g" horiz-adv-x="1097" d="M68 492q0 274 131 415.5t381 141.5q131 0 234.5 -18.5t168.5 -43.5v-987q0 -223 -121 -328.5t-338 -105.5q-147 0 -232 20.5t-128 42.5l55 211q47 -18 109.5 -36.5t154.5 -18.5q139 0 189.5 60.5t50.5 168.5v66h-8q-72 -96 -254 -96q-199 0 -296 122.5t-97 385.5z M342 502q0 -150 49 -227.5t141 -77.5q78 0 120 34.5t65 104.5v461q-61 26 -151 26h-7q-102 0 -159.5 -76.5t-57.5 -244.5z" />
|
||||||
|
<glyph unicode="h" horiz-adv-x="1116" d="M117 0v1434h266v-525h8q49 66 121 105t182 39q78 0 137.5 -20.5t99.5 -67.5t59.5 -128t19.5 -200v-637h-267v582q0 125 -34.5 180t-126.5 55q-68 0 -124.5 -46t-74.5 -118v-653h-266z" />
|
||||||
|
<glyph unicode="i" horiz-adv-x="550" d="M100 1313q0 59 44 101t122 42t126 -42t48 -101t-48 -99t-126 -40t-122 40t-44 99zM139 0v1024h267v-1024h-267z" />
|
||||||
|
<glyph unicode="j" horiz-adv-x="548" d="M-33 -188q8 0 14.5 -1t12.5 -1q92 0 119.5 59t27.5 164v991h267v-1067q0 -186 -74 -284.5t-236 -98.5q-61 0 -131 14v224zM105 1313q0 59 44 101t122 42t126 -42t48 -101t-48 -99t-126 -40t-122 40t-44 99z" />
|
||||||
|
<glyph unicode="k" horiz-adv-x="1005" d="M117 0v1434h266v-846l61 28l234 408h293l-246 -389l-104 -78l112 -80l277 -477h-305l-250 424h-72v-424h-266z" />
|
||||||
|
<glyph unicode="l" horiz-adv-x="602" d="M125 205v1229h266v-1090q0 -72 18.5 -104.5t59.5 -32.5q25 0 48.5 4t57.5 18l29 -209q-33 -16 -100.5 -32.5t-138.5 -16.5q-117 0 -178.5 54.5t-61.5 179.5z" />
|
||||||
|
<glyph unicode="m" horiz-adv-x="1648" d="M117 0v1024h207l30 -135h8q47 66 120 115t188 49q98 0 160.5 -40t97.5 -134q47 80 120.5 127t178.5 47q86 0 146.5 -20.5t98 -71t56 -134.5t18.5 -213v-614h-266v575q0 121 -25.5 181.5t-113.5 60.5q-72 0 -114 -39t-62 -106v-672h-267v557q0 141 -26.5 200.5 t-110.5 59.5q-70 0 -112.5 -38t-65.5 -97v-682h-266z" />
|
||||||
|
<glyph unicode="n" horiz-adv-x="1116" d="M117 0v1024h211l30 -135h9q47 66 124.5 115t200.5 49q76 0 135.5 -20.5t100.5 -67.5t61.5 -128t20.5 -200v-637h-267v582q0 125 -35.5 180t-121.5 55q-76 0 -128 -44t-75 -109v-664h-266z" />
|
||||||
|
<glyph unicode="o" horiz-adv-x="1099" d="M68 512q0 260 127 400.5t356 140.5q123 0 213 -39t149.5 -109.5t89 -171t29.5 -221.5q0 -260 -126 -400.5t-355 -140.5q-123 0 -213 39t-150.5 109.5t-90 171t-29.5 221.5zM342 512q0 -68 12.5 -125t37 -100t64.5 -66.5t95 -23.5q104 0 155.5 75.5t51.5 239.5 q0 141 -47 228t-160 87q-98 0 -153.5 -73.5t-55.5 -241.5z" />
|
||||||
|
<glyph unicode="p" horiz-adv-x="1105" d="M117 -410v1434h194l31 -123h8q53 78 126 115t177 37q193 0 289 -122t96 -392q0 -131 -30.5 -236.5t-91 -179.5t-147.5 -113t-200 -39q-63 0 -104 9.5t-82 29.5v-420h-266zM383 246q29 -23 62.5 -36t89.5 -13q115 0 172 80.5t57 267.5q0 135 -45.5 208.5t-145.5 73.5 q-78 0 -121.5 -38.5t-68.5 -116.5v-426z" />
|
||||||
|
<glyph unicode="q" horiz-adv-x="1097" d="M68 492q0 274 138 415.5t396 141.5q55 0 110.5 -5.5t105.5 -14.5t93 -20.5t72 -21.5v-1397h-266v498h-8q-35 -53 -94.5 -85t-153.5 -32q-190 0 -291.5 129t-101.5 392zM342 502q0 -150 49 -227.5t141 -77.5q78 0 120 34.5t65 104.5v461q-31 16 -70 21t-88 5 q-109 0 -163 -82t-54 -239z" />
|
||||||
|
<glyph unicode="r" horiz-adv-x="718" d="M117 0v1024h207l30 -135h8q35 76 94.5 117t139.5 41q53 0 121 -23l-35 -250q-63 23 -115 23q-72 0 -120 -38t-64 -97v-662h-266z" />
|
||||||
|
<glyph unicode="s" horiz-adv-x="864" d="M51 63l74 199q47 -27 125 -52.5t160 -25.5q59 0 95 23t36 76q0 41 -35 65.5t-86 45t-112.5 42t-113 59t-86 96t-34.5 150.5q0 152 90 232t260 80q117 0 211 -24.5t147 -55.5l-59 -193q-47 18 -119 39t-145 21q-119 0 -119 -92q0 -37 35 -59.5t86 -42t112.5 -42 t112.5 -58.5t86 -93.5t35 -147.5q0 -156 -99.5 -245t-297.5 -89q-109 0 -204 28t-155 64z" />
|
||||||
|
<glyph unicode="t" horiz-adv-x="714" d="M10 799v225h142v193l266 75v-268h250v-225h-250v-393q0 -106 21.5 -152.5t80.5 -46.5q41 0 71 8t66 25l48 -205q-55 -27 -129 -45.5t-150 -18.5q-141 0 -207.5 73t-66.5 239v516h-142z" />
|
||||||
|
<glyph unicode="u" horiz-adv-x="1101" d="M106 387v637h267v-582q0 -125 29.5 -180t115.5 -55q76 0 126 45t75 110v662h266v-713q0 -84 8 -164.5t25 -146.5h-201l-47 152h-8q-47 -78 -131 -129.5t-199 -51.5q-78 0 -139.5 20.5t-102 67.5t-62.5 127t-22 201z" />
|
||||||
|
<glyph unicode="v" horiz-adv-x="976" d="M-29 1024h310l190 -537l35 -157h10l29 162l174 532h287l-428 -1034h-162z" />
|
||||||
|
<glyph unicode="w" horiz-adv-x="1476" d="M-16 1024h288l150 -514l24 -182h11l35 184l170 512h196l186 -524l37 -170h9l28 172l131 522h244l-315 -1034h-197l-207 573l-26 129h-11l-24 -131l-197 -571h-203z" />
|
||||||
|
<glyph unicode="x" horiz-adv-x="1075" d="M16 0l332 524l-307 500h317l134 -219l57 -143l61 143l140 219h288l-309 -492l330 -532h-309l-158 246l-62 151l-65 -151l-158 -246h-291z" />
|
||||||
|
<glyph unicode="y" horiz-adv-x="978" d="M-18 1024h319l188 -575l37 -160h13l26 162l156 573h274l-311 -924q-39 -115 -75 -210t-79 -164.5t-95 -107.5t-124 -38q-106 0 -170 35l49 213q31 -12 62 -12q47 0 91 40t67 144z" />
|
||||||
|
<glyph unicode="z" horiz-adv-x="937" d="M63 0v225l404 486l104 88h-508v225h803v-225l-399 -494l-102 -80h501v-225h-803z" />
|
||||||
|
<glyph unicode="{" horiz-adv-x="759" d="M88 379v205q78 0 121 42t43 132v428q0 111 52 180.5t167 69.5h246v-226h-103q-55 0 -80.5 -28.5t-25.5 -94.5v-399q0 -90 -43 -136t-100 -56v-21q55 -8 99 -61.5t44 -139.5v-397q0 -66 24.5 -94.5t83.5 -28.5h101v-225h-246q-106 0 -162.5 64.5t-56.5 183.5v420 q0 104 -43 143t-121 39z" />
|
||||||
|
<glyph unicode="|" horiz-adv-x="464" d="M123 -266v1700h219v-1700h-219z" />
|
||||||
|
<glyph unicode="}" horiz-adv-x="759" d="M72 -246h102q55 0 81 28t26 95v399q0 90 43 136.5t100 56.5v20q-55 8 -99 61.5t-44 139.5v397q0 63 -25 93t-84 30h-100v226h243q109 0 164.5 -64.5t55.5 -183.5v-420q0 -104 43 -143t120 -39v-205q-78 0 -120.5 -42t-42.5 -132v-428q0 -111 -54.5 -180.5t-169.5 -69.5 h-239v225z" />
|
||||||
|
<glyph unicode="~" horiz-adv-x="1079" d="M57 774q96 78 173 107.5t143 29.5q59 0 110.5 -17t98.5 -36.5t93 -37t93 -17.5q37 0 76 12t82 47l96 -211q-74 -55 -135.5 -77.5t-114.5 -22.5q-57 0 -106.5 18.5t-95.5 41t-93 41t-100 18.5q-49 0 -105.5 -21.5t-124.5 -79.5z" />
|
||||||
|
<glyph unicode="¡" horiz-adv-x="600" d="M90 891q0 72 45 114t119 42q78 0 123 -42t45 -114t-45 -115t-123 -43q-74 0 -119 43t-45 115zM117 264l53 332h168l53 -332v-674h-274v674z" />
|
||||||
|
<glyph unicode="¢" d="M172 512q0 229 98.5 365.5t284.5 166.5v185h248v-185q57 -8 102 -21t82 -32l-61 -217q-31 14 -66 22.5t-72 12.5v-596q47 6 85 20.5t67 30.5l61 -201q-35 -27 -87 -46t-111 -29v-193h-248v182q-104 14 -177 58.5t-119 113t-66.5 160.5t-20.5 203zM434 512q0 -104 39 -183 t131 -108v586q-86 -23 -128 -93.5t-42 -201.5z" />
|
||||||
|
<glyph unicode="£" d="M104 0v236h5q63 2 111 22.5t80 54t48.5 78.5t16.5 94q0 55 -13 103h-248v219h140q-27 49 -46.5 110.5t-19.5 147.5q0 100 34 175t94.5 124t144.5 73.5t184 24.5q125 0 227.5 -23.5t175.5 -58.5l-86 -237q-41 23 -112.5 46t-171.5 23q-98 0 -153.5 -46t-55.5 -138 q0 -70 25.5 -120t56.5 -101h288v-219h-200q6 -35 6 -70q0 -61 -20.5 -128.5t-63.5 -110.5l-88 -64v-10l137 31h471v-236h-967z" />
|
||||||
|
<glyph unicode="¤" d="M10 307l158 160l74 35q-25 43 -39.5 93t-14.5 112q0 59 15.5 110t42.5 98l-78 35l-158 160l156 164l160 -158l39 -76q41 31 97 46.5t118 15.5q59 0 117.5 -15.5t97.5 -44.5l41 74l159 158l158 -164l-158 -160l-75 -32q29 -43 41 -97.5t12 -113.5q0 -61 -13.5 -115.5 t-39.5 -91.5l75 -33l158 -160l-158 -164l-159 158l-37 76q-39 -29 -99.5 -45.5t-119.5 -16.5q-61 0 -117.5 15.5t-97.5 44.5l-39 -74l-160 -158zM412 709q0 -78 47 -127.5t123 -49.5t122 49.5t46 127.5q0 74 -46.5 125t-121.5 51q-76 0 -123 -51t-47 -125z" />
|
||||||
|
<glyph unicode="¥" d="M-29 1434h334l262 -539l29 -152h10l31 156l254 535h301l-389 -744h184v-164h-264v-116h264v-164h-264v-246h-281v246h-270v164h270v116h-270v164h186z" />
|
||||||
|
<glyph unicode="¦" horiz-adv-x="464" d="M123 -266v702h217v-702h-217zM123 731v703h217v-703h-217z" />
|
||||||
|
<glyph unicode="§" horiz-adv-x="1085" d="M100 723q0 63 31 123.5t84 107.5l84 29q-53 33 -88 83t-35 134q0 115 89 188.5t270 73.5q121 0 225 -20.5t160 -46.5l-66 -215q-47 23 -125 40t-149 17q-76 0 -107 -22.5t-31 -57.5q0 -37 40 -57.5t100.5 -36.5t131 -36.5t131 -57.5t100.5 -98.5t40 -159.5 q0 -63 -29.5 -123t-83.5 -107l-92 -28q55 -33 92 -84.5t37 -135.5q0 -129 -100 -195.5t-266 -66.5q-139 0 -232.5 28t-152.5 60l69 205q47 -23 115 -45t158 -22q76 0 109.5 19.5t33.5 62.5q0 39 -40 60t-100.5 38.5t-131 38t-131 56.5t-100.5 95.5t-40 155.5zM367 727 q0 -72 65.5 -106.5t179.5 -67.5q45 25 76 66t31 88q0 37 -17.5 61.5t-50.5 43.5t-80 35.5t-106 35.5q-41 -25 -69.5 -65t-28.5 -91z" />
|
||||||
|
<glyph unicode="¨" horiz-adv-x="980" d="M123 1333q0 66 40 105t105 39q66 0 104 -39t38 -105q0 -61 -38 -100t-104 -39t-105.5 39t-39.5 100zM571 1333q0 66 38 105t104 39t105.5 -39t39.5 -105q0 -61 -40 -100t-105 -39q-66 0 -104 39t-38 100z" />
|
||||||
|
<glyph unicode="©" horiz-adv-x="1705" d="M113 594q0 170 57 306t156.5 232.5t234.5 148.5t291 52t290 -52t234.5 -148.5t157.5 -232.5t57 -306t-57 -306t-157.5 -232.5t-234.5 -148.5t-290 -52q-170 0 -307 52t-233.5 148.5t-147.5 232.5t-51 306zM313 594q0 -127 40 -229.5t113 -173t171 -108.5t215 -38t216 38 t172 108.5t113 173t40 229.5t-40 229.5t-113 173t-172 108.5t-216 38t-215 -38t-171 -108.5t-113 -173t-40 -229.5zM508 594q0 186 93 287.5t247 101.5q76 0 134 -17.5t112 -47.5l-66 -179q-37 18 -66.5 24.5t-58.5 6.5q-59 0 -94 -39t-35 -137q0 -176 144 -176q39 0 69.5 7 t61.5 24l59 -181q-45 -29 -113.5 -46t-146.5 -17q-166 0 -253 104.5t-87 284.5z" />
|
||||||
|
<glyph unicode="ª" horiz-adv-x="860" d="M86 973q0 68 36 112.5t96.5 71.5t141 36t170.5 5q4 53 -14 76.5t-90 23.5q-82 0 -148.5 -16t-107.5 -33l-45 131q53 29 150.5 49.5t218.5 20.5q156 0 213 -56.5t57 -172.5q0 -123 -6 -238t16 -205h-207l-26 94h-9q-27 -35 -75.5 -68.5t-137.5 -33.5q-106 0 -169.5 56.5 t-63.5 146.5zM322 999q0 -33 21 -51t54 -18q66 0 92.5 23.5t40.5 47.5v72q-88 10 -148 -4t-60 -70z" />
|
||||||
|
<glyph unicode="«" horiz-adv-x="999" d="M59 530l328 471l162 -127l-178 -258l-99 -84l99 -73l190 -254l-162 -127zM457 535l315 442l146 -115l-166 -250l-95 -80l95 -71l178 -248l-146 -115z" />
|
||||||
|
<glyph unicode="¬" horiz-adv-x="1079" d="M92 614v230h905v-463h-245v233h-660z" />
|
||||||
|
<glyph unicode="­" horiz-adv-x="737" d="M111 471v236h514v-236h-514z" />
|
||||||
|
<glyph unicode="®" horiz-adv-x="1413" d="M127 924q0 137 46 244.5t126 181t185.5 112.5t222.5 39q121 0 226 -39t183 -112.5t123 -181t45 -244.5q0 -139 -46 -247t-125 -181.5t-184.5 -111.5t-221.5 -38q-121 0 -226.5 38t-184.5 111.5t-124 181.5t-45 247zM319 924q0 -98 32 -173t85 -124t123 -74t148 -25 q82 0 152.5 23.5t121.5 73t81 124t30 175.5q0 98 -31 171.5t-83 123t-123 74t-148 24.5q-86 0 -158 -26.5t-123 -78t-79 -124t-28 -164.5zM496 659v531q33 10 92 15t112 5q86 0 147.5 -35.5t61.5 -123.5q0 -66 -42 -101t-103 -39l57 -28l133 -224h-125l-129 213l-98 31v-244 h-106zM602 965h70q59 0 92 18t33 64q0 71 -119 71q-23 0 -43.5 -1t-32.5 -7v-145z" />
|
||||||
|
<glyph unicode="¯" horiz-adv-x="907" d="M123 1159v189h661v-189h-661z" />
|
||||||
|
<glyph unicode="°" horiz-adv-x="894" d="M123 1122q0 76 26.5 138.5t72.5 107.5t106.5 69.5t130.5 24.5t132 -22.5t109.5 -66.5t74 -107.5t26.5 -143.5t-26.5 -142t-74 -105.5t-110 -66t-131.5 -22.5q-70 0 -130.5 22.5t-106.5 66t-72.5 105.5t-26.5 142zM328 1122q0 -66 39 -103.5t94 -37.5t96 38t41 103 q0 66 -41 106t-96 40t-94 -40t-39 -106z" />
|
||||||
|
<glyph unicode="±" horiz-adv-x="1079" d="M88 289v229h905v-229h-905zM88 831v228h332v338h239v-338h334v-228h-334v-219h-239v219h-332z" />
|
||||||
|
<glyph unicode="²" horiz-adv-x="843" d="M102 1571q72 43 153 62.5t155 19.5q145 0 224 -66.5t79 -193.5q0 -121 -61.5 -207t-147.5 -164l-96 -51v-8l120 22h217v-207h-641v146q53 37 119 86t122 105t94 115.5t38 112.5q0 100 -115 101q-55 0 -104 -17.5t-86 -40.5z" />
|
||||||
|
<glyph unicode="³" horiz-adv-x="843" d="M115 813l47 184q84 -39 182 -39q92 0 130 29t40 76q-2 47 -41 73.5t-143 26.5h-88v78l149 164l88 51l-119 -12h-235v194h582v-127l-181 -188l-69 -37v-10l61 6q109 -4 169.5 -64.5t62.5 -171.5q-2 -74 -32 -127t-80 -87.5t-117.5 -51t-141.5 -16.5q-78 0 -146.5 13 t-117.5 36z" />
|
||||||
|
<glyph unicode="´" horiz-adv-x="624" d="M123 1159l108 316h271v-62l-228 -254h-151z" />
|
||||||
|
<glyph unicode="¶" horiz-adv-x="1083" d="M53 1020q0 82 26.5 156.5t76 132t119 91.5t155.5 34h152v-1700h-217v868q-68 0 -125.5 34t-99.5 92t-64.5 133t-22.5 159zM741 -266v1700h220v-1700h-220z" />
|
||||||
|
<glyph unicode="·" horiz-adv-x="518" d="M92 647q0 72 45 114t119 42q78 0 123 -42t45 -114t-45 -115t-123 -43q-74 0 -119 43t-45 115z" />
|
||||||
|
<glyph unicode="¸" horiz-adv-x="679" d="M123 -418l16 117q92 -14 133 -4t41 45q0 57 -176 65l117 195h172l-49 -88q84 -8 132 -44t48 -110q0 -59 -37 -99t-97.5 -62.5t-139 -26.5t-160.5 12z" />
|
||||||
|
<glyph unicode="¹" horiz-adv-x="843" d="M84 1425l324 228h176v-670h178v-205h-615v205h201v336l21 94l-64 -65l-121 -80z" />
|
||||||
|
<glyph unicode="º" horiz-adv-x="858" d="M70 1110q0 92 26.5 157.5t73.5 108.5t113.5 62.5t144.5 19.5t143.5 -18.5t113.5 -59.5t74.5 -107.5t28.5 -162.5q-2 -96 -28.5 -162.5t-74.5 -107.5t-113.5 -59.5t-143.5 -18.5t-144.5 18.5t-113.5 59.5t-73.5 107.5t-26.5 162.5zM307 1110q0 -176 121 -176q63 0 91 38 t30 138q-2 98 -29.5 137t-91.5 39q-63 0 -92 -39t-29 -137z" />
|
||||||
|
<glyph unicode="»" horiz-adv-x="999" d="M70 866l143 115l328 -436l-314 -443l-147 115l168 250l92 80l-92 71zM438 874l162 127l340 -452l-328 -471l-161 127l178 258l98 84l-98 74z" />
|
||||||
|
<glyph unicode="¼" horiz-adv-x="1802" d="M76 1221l324 227h174v-875h-236v541l23 94l-64 -65l-121 -80zM364 80l883 1384l174 -102l-881 -1391zM920 160v137l446 580h187v-535h153v-182h-153v-160h-209v160h-424zM1129 326l106 16h109v176l12 109h-10l-45 -100l-99 -136z" />
|
||||||
|
<glyph unicode="½" horiz-adv-x="1849" d="M76 1221l324 227h174v-875h-236v541l23 94l-64 -65l-121 -80zM364 80l883 1384l174 -102l-881 -1391zM1112 793q72 43 153 62.5t155 19.5q145 0 224 -66.5t79 -193.5q0 -121 -61.5 -207t-147.5 -164l-96 -51v-8l120 22h217v-207h-641v146q53 37 119 86t122 105t94 115.5 t38 112.5q0 100 -115 101q-55 0 -104 -17.5t-86 -40.5z" />
|
||||||
|
<glyph unicode="¾" horiz-adv-x="1853" d="M99 608l47 184q84 -39 182 -39q92 0 130 29t40 76q-2 47 -41 73.5t-143 26.5h-88v78l149 164l88 51l-119 -12h-235v194h582v-127l-181 -188l-69 -37v-10l61 6q109 -4 169.5 -64.5t62.5 -171.5q-2 -74 -32 -127t-80 -87.5t-117.5 -51t-141.5 -16.5q-78 0 -146.5 13 t-117.5 36zM416 80l883 1384l174 -102l-881 -1391zM971 160v137l446 580h187v-535h153v-182h-153v-160h-209v160h-424zM1180 326l106 16h109v176l12 109h-10l-45 -100l-99 -136z" />
|
||||||
|
<glyph unicode="¿" horiz-adv-x="929" d="M47 -90q0 104 27.5 172t69.5 116t90.5 84.5t90.5 78.5t69.5 97.5t27.5 141.5h227q10 -106 -9 -181t-56 -129t-82 -93t-85 -76t-67.5 -77t-27.5 -95q0 -72 40.5 -116t143.5 -44q33 0 69.5 7t73.5 20.5t71 31t60 37.5l101 -196q-78 -53 -178.5 -88t-243.5 -35 q-193 0 -302.5 92t-109.5 252zM365 891q0 72 45 114t118 42q78 0 123 -42t45 -114t-45 -115t-123 -43q-74 0 -118.5 43t-44.5 115z" />
|
||||||
|
<glyph unicode="À" horiz-adv-x="1239" d="M0 0l516 1444h207l516 -1444h-295l-115 317h-440l-108 -317h-281zM279 1720v62h326l213 -242h-216zM461 543h307l-106 319l-44 225h-10l-43 -227z" />
|
||||||
|
<glyph unicode="Á" horiz-adv-x="1239" d="M0 0l516 1444h207l516 -1444h-295l-115 317h-440l-108 -317h-281zM420 1540l213 242h326v-62l-328 -180h-211zM461 543h307l-106 319l-44 225h-10l-43 -227z" />
|
||||||
|
<glyph unicode="Â" horiz-adv-x="1239" d="M0 0l516 1444h207l516 -1444h-295l-115 317h-440l-108 -317h-281zM254 1511v82l272 189h197l260 -191v-80h-203l-117 84l-40 70l-43 -68l-127 -86h-199zM461 543h307l-106 319l-44 225h-10l-43 -227z" />
|
||||||
|
<glyph unicode="Ã" horiz-adv-x="1239" d="M0 0l516 1444h207l516 -1444h-295l-115 317h-440l-108 -317h-281zM232 1638q66 72 126 98.5t120 26.5q45 0 90 -11t87 -24.5t83 -24.5t78 -11q33 0 63.5 10t58.5 39l52 -137q-57 -53 -111.5 -75t-105.5 -22q-47 0 -90.5 11.5t-85.5 26t-82.5 25.5t-79.5 11t-77 -15.5 t-77 -56.5zM461 543h307l-106 319l-44 225h-10l-43 -227z" />
|
||||||
|
<glyph unicode="Ä" horiz-adv-x="1239" d="M0 0l516 1444h207l516 -1444h-295l-115 317h-440l-108 -317h-281zM254 1634q0 53 37 86t119 33q80 0 116.5 -32.5t36.5 -86.5q0 -53 -37 -84.5t-116 -31.5q-82 0 -119 31.5t-37 84.5zM461 543h307l-106 319l-44 225h-10l-43 -227zM692 1634q0 53 37 86t117 33 q82 0 118.5 -32.5t36.5 -86.5q0 -53 -36.5 -84.5t-118.5 -31.5q-80 0 -117 31.5t-37 84.5z" />
|
||||||
|
<glyph unicode="Å" horiz-adv-x="1239" d="M0 0l504 1411q-80 18 -113 63.5t-33 104.5q0 37 12.5 70.5t42 59.5t80 40t128.5 14q143 0 202.5 -49t59.5 -135q0 -59 -33 -103t-117 -65l506 -1411h-295l-115 317h-440l-108 -317h-281zM461 543h307l-106 319l-44 225h-10l-43 -227zM530 1579q0 -63 91 -63q51 0 71.5 16 t20.5 47q0 35 -21.5 51.5t-70.5 16.5q-91 0 -91 -68z" />
|
||||||
|
<glyph unicode="Æ" horiz-adv-x="1765" d="M-59 0l868 1434h858v-250h-567v-334h516v-250h-516v-350h577v-250h-858v348h-381l-202 -348h-295zM561 575h258v515h-12l-74 -211z" />
|
||||||
|
<glyph unicode="Ç" horiz-adv-x="1144" d="M78 717q0 211 58.5 353t151.5 229t207.5 125t229.5 38q123 0 208 -16t140 -39l-55 -238q-47 23 -111.5 33t-156.5 10q-170 0 -273.5 -120.5t-103.5 -374.5q0 -111 24.5 -202t74.5 -155.5t125 -100.5t173 -36q92 0 155.5 18.5t110.5 47.5l58 -230q-53 -39 -134 -59 t-172 -27l-32 -61q84 -8 132 -44t48 -110q0 -47 -23.5 -81.5t-64.5 -58.5t-96.5 -36t-118.5 -12t-131 12l18 99q14 -2 26.5 -2.5t22.5 -0.5q78 0 100.5 18.5t22.5 43.5q0 57 -176 65l102 172q-113 14 -211 62.5t-171.5 138.5t-115.5 223.5t-42 315.5z" />
|
||||||
|
<glyph unicode="È" horiz-adv-x="1069" d="M123 0v1434h850v-250h-570v-334h519v-250h-519v-350h580v-250h-860zM182 1720v62h326l213 -242h-216z" />
|
||||||
|
<glyph unicode="É" horiz-adv-x="1069" d="M123 0v1434h850v-250h-570v-334h519v-250h-519v-350h580v-250h-860zM387 1540l213 242h326v-62l-328 -180h-211z" />
|
||||||
|
<glyph unicode="Ê" horiz-adv-x="1069" d="M123 0v1434h850v-250h-570v-334h519v-250h-519v-350h580v-250h-860zM176 1511v82l272 189h197l260 -191v-80h-203l-117 84l-40 70l-43 -68l-127 -86h-199z" />
|
||||||
|
<glyph unicode="Ë" horiz-adv-x="1069" d="M123 0v1434h850v-250h-570v-334h519v-250h-519v-350h580v-250h-860zM172 1634q0 53 37 86t119 33q80 0 116.5 -32.5t36.5 -86.5q0 -53 -37 -84.5t-116 -31.5q-82 0 -119 31.5t-37 84.5zM610 1634q0 53 37 86t117 33q82 0 118.5 -32.5t36.5 -86.5q0 -53 -36.5 -84.5 t-118.5 -31.5q-80 0 -117 31.5t-37 84.5z" />
|
||||||
|
<glyph unicode="Ì" horiz-adv-x="583" d="M-45 1720v62h326l213 -242h-216zM152 0v1434h280v-1434h-280z" />
|
||||||
|
<glyph unicode="Í" horiz-adv-x="583" d="M100 1540l213 242h326v-62l-328 -180h-211zM152 0v1434h280v-1434h-280z" />
|
||||||
|
<glyph unicode="Î" horiz-adv-x="583" d="M-74 1511v82l272 189h197l260 -191v-80h-203l-117 84l-40 70l-43 -68l-127 -86h-199zM152 0v1434h280v-1434h-280z" />
|
||||||
|
<glyph unicode="Ï" horiz-adv-x="583" d="M-78 1634q0 53 37 86t119 33q80 0 116.5 -32.5t36.5 -86.5q0 -53 -37 -84.5t-116 -31.5q-82 0 -119 31.5t-37 84.5zM152 0v1434h280v-1434h-280zM360 1634q0 53 37 86t117 33q82 0 118.5 -32.5t36.5 -86.5q0 -53 -36.5 -84.5t-118.5 -31.5q-80 0 -117 31.5t-37 84.5z" />
|
||||||
|
<glyph unicode="Ð" horiz-adv-x="1370" d="M-12 657v164h180v613q43 6 97 10t111.5 6t112 3t97.5 1q190 0 325.5 -53t219 -149.5t122.5 -229.5t39 -293q0 -145 -36.5 -280.5t-122.5 -240t-226.5 -168t-347.5 -63.5q-33 0 -87 2.5t-112.5 5.5t-111.5 6t-80 7v659h-180zM449 233q8 -2 27.5 -3t42 -2t43 -1h30.5 q119 0 197.5 42t125 112t64.5 161t18 187q0 84 -16 169t-60 152.5t-120 110.5t-193 43q-45 0 -91 -2t-68 -6v-375h286v-164h-286v-424z" />
|
||||||
|
<glyph unicode="Ñ" horiz-adv-x="1345" d="M123 0v1444h205l542 -764l109 -219h10l-33 219v754h267v-1444h-205l-539 758l-112 225h-11l33 -225v-748h-266zM283 1638q66 72 126 98.5t120 26.5q45 0 90 -11t87 -24.5t83 -24.5t78 -11q33 0 63.5 10t58.5 39l52 -137q-57 -53 -111.5 -75t-105.5 -22q-47 0 -90.5 11.5 t-85.5 26t-82.5 25.5t-79.5 11t-77 -15.5t-77 -56.5z" />
|
||||||
|
<glyph unicode="Ò" horiz-adv-x="1372" d="M78 717q0 358 157.5 551.5t450.5 193.5q154 0 268.5 -53t190.5 -151.5t112.5 -235.5t36.5 -305q0 -358 -158.5 -552t-449.5 -194q-156 0 -270.5 53.5t-189 151.5t-111.5 235.5t-37 305.5zM305 1720v62h326l213 -242h-216zM373 717q0 -109 18.5 -200t56 -156.5t97 -102.5 t141.5 -37q150 0 231.5 117t81.5 379q0 104 -17 194t-54 158t-96.5 105.5t-145.5 37.5q-150 0 -231.5 -119.5t-81.5 -375.5z" />
|
||||||
|
<glyph unicode="Ó" horiz-adv-x="1372" d="M78 717q0 358 157.5 551.5t450.5 193.5q154 0 268.5 -53t190.5 -151.5t112.5 -235.5t36.5 -305q0 -358 -158.5 -552t-449.5 -194q-156 0 -270.5 53.5t-189 151.5t-111.5 235.5t-37 305.5zM373 717q0 -109 18.5 -200t56 -156.5t97 -102.5t141.5 -37q150 0 231.5 117 t81.5 379q0 104 -17 194t-54 158t-96.5 105.5t-145.5 37.5q-150 0 -231.5 -119.5t-81.5 -375.5zM541 1540l213 242h326v-62l-328 -180h-211z" />
|
||||||
|
<glyph unicode="Ô" horiz-adv-x="1372" d="M78 717q0 358 157.5 551.5t450.5 193.5q154 0 268.5 -53t190.5 -151.5t112.5 -235.5t36.5 -305q0 -358 -158.5 -552t-449.5 -194q-156 0 -270.5 53.5t-189 151.5t-111.5 235.5t-37 305.5zM316 1511v82l272 189h197l260 -191v-80h-203l-117 84l-40 70l-43 -68l-127 -86 h-199zM373 717q0 -109 18.5 -200t56 -156.5t97 -102.5t141.5 -37q150 0 231.5 117t81.5 379q0 104 -17 194t-54 158t-96.5 105.5t-145.5 37.5q-150 0 -231.5 -119.5t-81.5 -375.5z" />
|
||||||
|
<glyph unicode="Õ" horiz-adv-x="1372" d="M78 717q0 358 157.5 551.5t450.5 193.5q154 0 268.5 -53t190.5 -151.5t112.5 -235.5t36.5 -305q0 -358 -158.5 -552t-449.5 -194q-156 0 -270.5 53.5t-189 151.5t-111.5 235.5t-37 305.5zM295 1638q66 72 126 98.5t120 26.5q45 0 90 -11t87 -24.5t83 -24.5t78 -11 q33 0 63.5 10t58.5 39l52 -137q-57 -53 -111.5 -75t-105.5 -22q-47 0 -90.5 11.5t-85.5 26t-82.5 25.5t-79.5 11t-77 -15.5t-77 -56.5zM373 717q0 -109 18.5 -200t56 -156.5t97 -102.5t141.5 -37q150 0 231.5 117t81.5 379q0 104 -17 194t-54 158t-96.5 105.5t-145.5 37.5 q-150 0 -231.5 -119.5t-81.5 -375.5z" />
|
||||||
|
<glyph unicode="Ö" horiz-adv-x="1372" d="M78 717q0 358 157.5 551.5t450.5 193.5q154 0 268.5 -53t190.5 -151.5t112.5 -235.5t36.5 -305q0 -358 -158.5 -552t-449.5 -194q-156 0 -270.5 53.5t-189 151.5t-111.5 235.5t-37 305.5zM307 1634q0 53 37 86t119 33q80 0 116.5 -32.5t36.5 -86.5q0 -53 -37 -84.5 t-116 -31.5q-82 0 -119 31.5t-37 84.5zM373 717q0 -109 18.5 -200t56 -156.5t97 -102.5t141.5 -37q150 0 231.5 117t81.5 379q0 104 -17 194t-54 158t-96.5 105.5t-145.5 37.5q-150 0 -231.5 -119.5t-81.5 -375.5zM745 1634q0 53 37 86t117 33q82 0 118.5 -32.5t36.5 -86.5 q0 -53 -36.5 -84.5t-118.5 -31.5q-80 0 -117 31.5t-37 84.5z" />
|
||||||
|
<glyph unicode="×" horiz-adv-x="1079" d="M111 426l268 268l-264 260l159 166l269 -266l266 266l162 -166l-266 -260l266 -264l-162 -168l-266 268l-271 -270z" />
|
||||||
|
<glyph unicode="Ø" horiz-adv-x="1372" d="M78 717q0 358 157.5 551.5t450.5 193.5q92 0 170 -20.5t141 -57.5l52 80l174 -102l-72 -115q72 -98 107.5 -232t35.5 -298q0 -358 -158.5 -552t-449.5 -194q-90 0 -163.5 17.5t-137.5 50.5l-43 -68l-176 109l61 96q-76 98 -112.5 234.5t-36.5 306.5zM373 717 q0 -74 8 -139.5t25 -120.5l448 700q-72 55 -168 55q-150 0 -231.5 -119.5t-81.5 -375.5zM530 266q68 -45 156 -45q150 0 231.5 117t81.5 379q0 68 -6 130t-22 116z" />
|
||||||
|
<glyph unicode="Ù" horiz-adv-x="1284" d="M117 473v961h280v-906q0 -84 15.5 -142t48.5 -94t82 -51.5t114 -15.5q129 0 186.5 72t57.5 231v906h266v-926q0 -139 -36.5 -239.5t-102 -166t-160 -96.5t-206.5 -31q-545 0 -545 498zM270 1720v62h326l213 -242h-216z" />
|
||||||
|
<glyph unicode="Ú" horiz-adv-x="1284" d="M117 473v961h280v-906q0 -84 15.5 -142t48.5 -94t82 -51.5t114 -15.5q129 0 186.5 72t57.5 231v906h266v-926q0 -139 -36.5 -239.5t-102 -166t-160 -96.5t-206.5 -31q-545 0 -545 498zM535 1540l213 242h326v-62l-328 -180h-211z" />
|
||||||
|
<glyph unicode="Û" horiz-adv-x="1284" d="M117 473v961h280v-906q0 -84 15.5 -142t48.5 -94t82 -51.5t114 -15.5q129 0 186.5 72t57.5 231v906h266v-926q0 -139 -36.5 -239.5t-102 -166t-160 -96.5t-206.5 -31q-545 0 -545 498zM287 1511v82l272 189h197l260 -191v-80h-203l-117 84l-40 70l-43 -68l-127 -86h-199z " />
|
||||||
|
<glyph unicode="Ü" horiz-adv-x="1284" d="M117 473v961h280v-906q0 -84 15.5 -142t48.5 -94t82 -51.5t114 -15.5q129 0 186.5 72t57.5 231v906h266v-926q0 -139 -36.5 -239.5t-102 -166t-160 -96.5t-206.5 -31q-545 0 -545 498zM273 1634q0 53 37 86t119 33q80 0 116.5 -32.5t36.5 -86.5q0 -53 -37 -84.5 t-116 -31.5q-82 0 -119 31.5t-37 84.5zM711 1634q0 53 37 86t117 33q82 0 118.5 -32.5t36.5 -86.5q0 -53 -36.5 -84.5t-118.5 -31.5q-80 0 -117 31.5t-37 84.5z" />
|
||||||
|
<glyph unicode="Ý" horiz-adv-x="1212" d="M-4 1434h334l262 -539l29 -152h10l31 156l253 535h302l-469 -899v-535h-281v532zM455 1540l213 242h326v-62l-328 -180h-211z" />
|
||||||
|
<glyph unicode="Þ" horiz-adv-x="1171" d="M123 0v1434h280v-148q29 2 57.5 3t57.5 1q106 0 214 -17.5t194 -69.5t140 -145t54 -243q0 -135 -47 -228t-125 -152.5t-177 -86t-206 -26.5h-32.5t-47 1t-48 3t-34.5 4v-330h-280zM403 573q8 -2 24.5 -4t35 -3t36 -1h25.5q55 0 109.5 10.5t97.5 38t68.5 76.5t25.5 129 q0 68 -24.5 112t-64.5 70.5t-91 37t-104 10.5q-41 0 -78 -3.5t-60 -7.5v-465z" />
|
||||||
|
<glyph unicode="ß" horiz-adv-x="1290" d="M25 799v225h141q0 119 32.5 200t91 131t139.5 72.5t177 22.5q104 0 187.5 -23.5t141.5 -66.5t90 -103.5t32 -134.5q0 -80 -36 -129t-80 -84t-80 -65.5t-36 -75.5q0 -37 30 -59.5t76 -42t98 -41t98.5 -56t76 -89t29.5 -138.5q0 -72 -22.5 -138.5t-70.5 -118.5t-121 -83 t-171 -31q-96 0 -177 23.5t-139 58.5l72 199q47 -27 94 -47.5t127 -20.5q61 0 101.5 42t40.5 102q0 43 -30 69.5t-76 48t-98 42t-98.5 52t-76 79t-29.5 120.5q0 88 36 137.5t80 83t80 62.5t36 78q0 27 -14.5 50.5t-39 39.5t-55.5 26.5t-61 10.5q-98 0 -144.5 -48.5 t-46.5 -179.5v-999h-264v799h-141z" />
|
||||||
|
<glyph unicode="à" horiz-adv-x="1015" d="M47 283q0 94 42 158.5t121 104.5t188.5 55t244.5 9q14 115 -16.5 165t-137.5 50q-80 0 -169 -16t-146 -43l-63 199q82 37 194.5 58t235.5 21q106 0 178 -25.5t113.5 -72.5t59 -112.5t17.5 -147.5q0 -90 -6 -181t-7 -179t5 -171t31 -157h-217l-43 141h-10 q-41 -63 -114 -109t-188 -46q-72 0 -129 21.5t-98 61t-63.5 94t-22.5 122.5zM236 1413v62h278l123 -316h-147zM322 324q0 -57 34 -89t93 -32q80 0 127 35.5t69 76.5v134q-63 6 -121.5 1.5t-103.5 -18.5t-71.5 -40.5t-26.5 -67.5z" />
|
||||||
|
<glyph unicode="á" horiz-adv-x="1015" d="M47 283q0 94 42 158.5t121 104.5t188.5 55t244.5 9q14 115 -16.5 165t-137.5 50q-80 0 -169 -16t-146 -43l-63 199q82 37 194.5 58t235.5 21q106 0 178 -25.5t113.5 -72.5t59 -112.5t17.5 -147.5q0 -90 -6 -181t-7 -179t5 -171t31 -157h-217l-43 141h-10 q-41 -63 -114 -109t-188 -46q-72 0 -129 21.5t-98 61t-63.5 94t-22.5 122.5zM322 324q0 -57 34 -89t93 -32q80 0 127 35.5t69 76.5v134q-63 6 -121.5 1.5t-103.5 -18.5t-71.5 -40.5t-26.5 -67.5zM377 1159l108 316h271v-62l-228 -254h-151z" />
|
||||||
|
<glyph unicode="â" horiz-adv-x="1015" d="M47 283q0 94 42 158.5t121 104.5t188.5 55t244.5 9q14 115 -16.5 165t-137.5 50q-80 0 -169 -16t-146 -43l-63 199q82 37 194.5 58t235.5 21q106 0 178 -25.5t113.5 -72.5t59 -112.5t17.5 -147.5q0 -90 -6 -181t-7 -179t5 -171t31 -157h-217l-43 141h-10 q-41 -63 -114 -109t-188 -46q-72 0 -129 21.5t-98 61t-63.5 94t-22.5 122.5zM191 1126l252 373h176l227 -373h-211l-80 136l-34 100l-35 -100l-92 -136h-203zM322 324q0 -57 34 -89t93 -32q80 0 127 35.5t69 76.5v134q-63 6 -121.5 1.5t-103.5 -18.5t-71.5 -40.5 t-26.5 -67.5z" />
|
||||||
|
<glyph unicode="ã" horiz-adv-x="1015" d="M47 283q0 94 42 158.5t121 104.5t188.5 55t244.5 9q14 115 -16.5 165t-137.5 50q-80 0 -169 -16t-146 -43l-63 199q82 37 194.5 58t235.5 21q106 0 178 -25.5t113.5 -72.5t59 -112.5t17.5 -147.5q0 -90 -6 -181t-7 -179t5 -171t31 -157h-217l-43 141h-10 q-41 -63 -114 -109t-188 -46q-72 0 -129 21.5t-98 61t-63.5 94t-22.5 122.5zM176 1348q63 76 117.5 104.5t103.5 28.5q41 0 79 -14.5t75 -31t71.5 -30.5t71.5 -14q29 0 58.5 12t62.5 43l41 -143q-59 -66 -109.5 -90.5t-97.5 -24.5q-41 0 -80 13t-76 29.5t-73.5 30 t-73.5 13.5q-31 0 -63.5 -13.5t-67.5 -46.5zM322 324q0 -57 34 -89t93 -32q80 0 127 35.5t69 76.5v134q-63 6 -121.5 1.5t-103.5 -18.5t-71.5 -40.5t-26.5 -67.5z" />
|
||||||
|
<glyph unicode="ä" horiz-adv-x="1015" d="M47 283q0 94 42 158.5t121 104.5t188.5 55t244.5 9q14 115 -16.5 165t-137.5 50q-80 0 -169 -16t-146 -43l-63 199q82 37 194.5 58t235.5 21q106 0 178 -25.5t113.5 -72.5t59 -112.5t17.5 -147.5q0 -90 -6 -181t-7 -179t5 -171t31 -157h-217l-43 141h-10 q-41 -63 -114 -109t-188 -46q-72 0 -129 21.5t-98 61t-63.5 94t-22.5 122.5zM154 1333q0 66 40 105t105 39q66 0 104 -39t38 -105q0 -61 -38 -100t-104 -39t-105.5 39t-39.5 100zM322 324q0 -57 34 -89t93 -32q80 0 127 35.5t69 76.5v134q-63 6 -121.5 1.5t-103.5 -18.5 t-71.5 -40.5t-26.5 -67.5zM602 1333q0 66 38 105t104 39t105.5 -39t39.5 -105q0 -61 -40 -100t-105 -39q-66 0 -104 39t-38 100z" />
|
||||||
|
<glyph unicode="å" horiz-adv-x="1015" d="M47 283q0 94 42 158.5t121 104.5t188.5 55t244.5 9q14 115 -16.5 165t-137.5 50q-80 0 -169 -16t-146 -43l-63 199q82 37 194.5 58t235.5 21q106 0 178 -25.5t113.5 -72.5t59 -112.5t17.5 -147.5q0 -90 -6 -181t-7 -179t5 -171t31 -157h-217l-43 141h-10 q-41 -63 -114 -109t-188 -46q-72 0 -129 21.5t-98 61t-63.5 94t-22.5 122.5zM295 1325q0 86 58.5 141.5t168.5 55.5q104 0 166 -50.5t62 -146.5q0 -80 -60.5 -136t-167.5 -56q-109 0 -168 52t-59 140zM322 324q0 -57 34 -89t93 -32q80 0 127 35.5t69 76.5v134 q-63 6 -121.5 1.5t-103.5 -18.5t-71.5 -40.5t-26.5 -67.5zM442 1325q0 -33 24.5 -50.5t55.5 -17.5q35 0 57.5 16.5t22.5 51.5t-23.5 52.5t-56.5 17.5q-31 0 -55.5 -16.5t-24.5 -53.5z" />
|
||||||
|
<glyph unicode="æ" horiz-adv-x="1607" d="M47 283q0 94 42 158.5t120 104.5t187.5 55t244.5 9q14 115 -15.5 165t-136.5 50q-80 0 -162.5 -21.5t-146.5 -51.5l-69 192q78 41 192.5 70.5t237.5 29.5q106 0 169.5 -27.5t104.5 -82.5q51 57 133 88t178 31q78 0 152 -20.5t131 -67.5t92 -127t35 -199q0 -43 -5 -91 t-15 -104h-617q8 -129 68.5 -194.5t195.5 -65.5q84 0 150.5 26t101.5 52l88 -174q-61 -49 -166.5 -83t-224.5 -34q-131 0 -230.5 48.5t-154.5 136.5h-10q-55 -70 -136 -121t-221 -51q-72 0 -129 21.5t-98 61t-63.5 94t-22.5 122.5zM322 324q0 -57 34 -89t93 -32 q80 0 127 35.5t69 76.5v134q-63 6 -121.5 1.5t-103.5 -18.5t-71.5 -40.5t-26.5 -67.5zM907 610h383q6 111 -35 170.5t-133 59.5q-104 0 -154 -62.5t-61 -167.5z" />
|
||||||
|
<glyph unicode="ç" horiz-adv-x="886" d="M68 512q0 260 116.5 400.5t339.5 140.5q113 0 181.5 -18.5t123.5 -47.5l-63 -217q-47 23 -93 35t-106 12q-111 0 -168 -72.5t-57 -232.5q0 -66 14.5 -121t43 -96t74.5 -64.5t108 -23.5q68 0 114.5 17.5t83.5 41.5l62 -203q-47 -35 -107.5 -55t-128.5 -31l-37 -65 q84 -8 132.5 -44t48.5 -110q0 -47 -24 -81.5t-64.5 -58.5t-96 -36t-119.5 -12q-63 0 -131 12l19 99q14 -2 26.5 -2.5t22.5 -0.5q78 0 100.5 18.5t22.5 43.5q0 57 -176 65l102 172q-100 12 -169.5 56.5t-113 113t-62.5 161.5t-19 204z" />
|
||||||
|
<glyph unicode="è" horiz-adv-x="1040" d="M68 512q0 270 129 405.5t362 135.5q78 0 151.5 -20.5t131 -67.5t92.5 -127t35 -199q0 -43 -5.5 -92t-15.5 -103h-614q6 -129 66.5 -194.5t195.5 -65.5q84 0 150.5 26t101.5 52l88 -174q-61 -49 -166.5 -83t-224.5 -34q-248 0 -362.5 144.5t-114.5 396.5zM273 1413v62h278 l123 -316h-147zM340 610h381q8 111 -34 170.5t-132 59.5q-104 0 -154.5 -62.5t-60.5 -167.5z" />
|
||||||
|
<glyph unicode="é" horiz-adv-x="1040" d="M68 512q0 270 129 405.5t362 135.5q78 0 151.5 -20.5t131 -67.5t92.5 -127t35 -199q0 -43 -5.5 -92t-15.5 -103h-614q6 -129 66.5 -194.5t195.5 -65.5q84 0 150.5 26t101.5 52l88 -174q-61 -49 -166.5 -83t-224.5 -34q-248 0 -362.5 144.5t-114.5 396.5zM340 610h381 q8 111 -34 170.5t-132 59.5q-104 0 -154.5 -62.5t-60.5 -167.5zM453 1159l108 316h271v-62l-228 -254h-151z" />
|
||||||
|
<glyph unicode="ê" horiz-adv-x="1040" d="M68 512q0 270 129 405.5t362 135.5q78 0 151.5 -20.5t131 -67.5t92.5 -127t35 -199q0 -43 -5.5 -92t-15.5 -103h-614q6 -129 66.5 -194.5t195.5 -65.5q84 0 150.5 26t101.5 52l88 -174q-61 -49 -166.5 -83t-224.5 -34q-248 0 -362.5 144.5t-114.5 396.5zM201 1126 l252 373h176l227 -373h-211l-80 136l-34 100l-35 -100l-92 -136h-203zM340 610h381q8 111 -34 170.5t-132 59.5q-104 0 -154.5 -62.5t-60.5 -167.5z" />
|
||||||
|
<glyph unicode="ë" horiz-adv-x="1040" d="M68 512q0 270 129 405.5t362 135.5q78 0 151.5 -20.5t131 -67.5t92.5 -127t35 -199q0 -43 -5.5 -92t-15.5 -103h-614q6 -129 66.5 -194.5t195.5 -65.5q84 0 150.5 26t101.5 52l88 -174q-61 -49 -166.5 -83t-224.5 -34q-248 0 -362.5 144.5t-114.5 396.5zM168 1333 q0 66 40 105t105 39q66 0 104 -39t38 -105q0 -61 -38 -100t-104 -39t-105.5 39t-39.5 100zM340 610h381q8 111 -34 170.5t-132 59.5q-104 0 -154.5 -62.5t-60.5 -167.5zM616 1333q0 66 38 105t104 39t105.5 -39t39.5 -105q0 -61 -40 -100t-105 -39q-66 0 -104 39t-38 100z " />
|
||||||
|
<glyph unicode="ì" horiz-adv-x="550" d="M-4 1413v62h278l123 -316h-147zM143 0v1024h267v-1024h-267z" />
|
||||||
|
<glyph unicode="í" horiz-adv-x="550" d="M143 0v1024h267v-1024h-267zM146 1159l108 316h271v-62l-228 -254h-151z" />
|
||||||
|
<glyph unicode="î" horiz-adv-x="550" d="M-61 1126l252 373h176l227 -373h-211l-80 136l-34 100l-35 -100l-92 -136h-203zM143 0v1024h267v-1024h-267z" />
|
||||||
|
<glyph unicode="ï" horiz-adv-x="550" d="M-92 1333q0 66 40 105t105 39q66 0 104 -39t38 -105q0 -61 -38 -100t-104 -39t-105.5 39t-39.5 100zM143 0v1024h267v-1024h-267zM356 1333q0 66 38 105t104 39t105.5 -39t39.5 -105q0 -61 -40 -100t-105 -39q-66 0 -104 39t-38 100z" />
|
||||||
|
<glyph unicode="ð" horiz-adv-x="1153" d="M76 502q0 111 34.5 205t97 164.5t150.5 110.5t193 40q78 0 144.5 -21.5t107.5 -62.5q-25 74 -70 135q-45 59 -102 105l-139 -95l-89 113l91 61q-70 31 -142 43l107 164q51 -14 116 -41q47 -18 97 -45l108 74l86 -113l-67 -47q25 -18 47 -41q66 -61 117 -150t82.5 -208 t31.5 -275q0 -166 -38 -287.5t-105.5 -201.5t-161.5 -119t-207 -39q-121 0 -213 39t-153.5 109.5t-92 168t-30.5 214.5zM334 498q0 -147 67.5 -223t180.5 -76q106 0 173.5 91t67.5 283q0 27 -3 70t-11 68q-33 47 -98.5 66.5t-126.5 19.5q-123 0 -186.5 -85t-63.5 -214z" />
|
||||||
|
<glyph unicode="ñ" horiz-adv-x="1116" d="M117 0v1024h211l30 -135h9q47 66 124.5 115t200.5 49q76 0 135.5 -20.5t100.5 -67.5t61.5 -128t20.5 -200v-637h-267v582q0 125 -35.5 180t-121.5 55q-76 0 -128 -44t-75 -109v-664h-266zM219 1348q63 76 117.5 104.5t103.5 28.5q41 0 79 -14.5t75 -31t71.5 -30.5 t71.5 -14q29 0 58.5 12t62.5 43l41 -143q-59 -66 -109.5 -90.5t-97.5 -24.5q-41 0 -80 13t-76 29.5t-73.5 30t-73.5 13.5q-31 0 -63.5 -13.5t-67.5 -46.5z" />
|
||||||
|
<glyph unicode="ò" horiz-adv-x="1099" d="M68 512q0 260 127 400.5t356 140.5q123 0 213 -39t149.5 -109.5t89 -171t29.5 -221.5q0 -260 -126 -400.5t-355 -140.5q-123 0 -213 39t-150.5 109.5t-90 171t-29.5 221.5zM277 1413v62h278l123 -316h-147zM342 512q0 -68 12.5 -125t37 -100t64.5 -66.5t95 -23.5 q104 0 155.5 75.5t51.5 239.5q0 141 -47 228t-160 87q-98 0 -153.5 -73.5t-55.5 -241.5z" />
|
||||||
|
<glyph unicode="ó" horiz-adv-x="1099" d="M68 512q0 260 127 400.5t356 140.5q123 0 213 -39t149.5 -109.5t89 -171t29.5 -221.5q0 -260 -126 -400.5t-355 -140.5q-123 0 -213 39t-150.5 109.5t-90 171t-29.5 221.5zM342 512q0 -68 12.5 -125t37 -100t64.5 -66.5t95 -23.5q104 0 155.5 75.5t51.5 239.5 q0 141 -47 228t-160 87q-98 0 -153.5 -73.5t-55.5 -241.5zM455 1159l108 316h271v-62l-228 -254h-151z" />
|
||||||
|
<glyph unicode="ô" horiz-adv-x="1099" d="M68 512q0 260 127 400.5t356 140.5q123 0 213 -39t149.5 -109.5t89 -171t29.5 -221.5q0 -260 -126 -400.5t-355 -140.5q-123 0 -213 39t-150.5 109.5t-90 171t-29.5 221.5zM221 1126l252 373h176l227 -373h-211l-80 136l-34 100l-35 -100l-92 -136h-203zM342 512 q0 -68 12.5 -125t37 -100t64.5 -66.5t95 -23.5q104 0 155.5 75.5t51.5 239.5q0 141 -47 228t-160 87q-98 0 -153.5 -73.5t-55.5 -241.5z" />
|
||||||
|
<glyph unicode="õ" horiz-adv-x="1099" d="M68 512q0 260 127 400.5t356 140.5q123 0 213 -39t149.5 -109.5t89 -171t29.5 -221.5q0 -260 -126 -400.5t-355 -140.5q-123 0 -213 39t-150.5 109.5t-90 171t-29.5 221.5zM213 1348q63 76 117.5 104.5t103.5 28.5q41 0 79 -14.5t75 -31t71.5 -30.5t71.5 -14 q29 0 58.5 12t62.5 43l41 -143q-59 -66 -109.5 -90.5t-97.5 -24.5q-41 0 -80 13t-76 29.5t-73.5 30t-73.5 13.5q-31 0 -63.5 -13.5t-67.5 -46.5zM342 512q0 -68 12.5 -125t37 -100t64.5 -66.5t95 -23.5q104 0 155.5 75.5t51.5 239.5q0 141 -47 228t-160 87 q-98 0 -153.5 -73.5t-55.5 -241.5z" />
|
||||||
|
<glyph unicode="ö" horiz-adv-x="1099" d="M68 512q0 260 127 400.5t356 140.5q123 0 213 -39t149.5 -109.5t89 -171t29.5 -221.5q0 -260 -126 -400.5t-355 -140.5q-123 0 -213 39t-150.5 109.5t-90 171t-29.5 221.5zM184 1333q0 66 40 105t105 39q66 0 104 -39t38 -105q0 -61 -38 -100t-104 -39t-105.5 39 t-39.5 100zM342 512q0 -68 12.5 -125t37 -100t64.5 -66.5t95 -23.5q104 0 155.5 75.5t51.5 239.5q0 141 -47 228t-160 87q-98 0 -153.5 -73.5t-55.5 -241.5zM632 1333q0 66 38 105t104 39t105.5 -39t39.5 -105q0 -61 -40 -100t-105 -39q-66 0 -104 39t-38 100z" />
|
||||||
|
<glyph unicode="÷" horiz-adv-x="1079" d="M88 578v229h905v-229h-905zM377 297q0 72 45 114t119 42q78 0 123 -42t45 -114t-45.5 -115t-122.5 -43q-74 0 -119 43t-45 115zM377 1090q0 72 45 113.5t119 41.5q78 0 123 -42t45 -113q0 -72 -45.5 -115t-122.5 -43q-74 0 -119 43t-45 115z" />
|
||||||
|
<glyph unicode="ø" horiz-adv-x="1097" d="M68 512q0 260 125.5 400.5t355.5 140.5q66 0 121 -11.5t102 -33.5l49 69l164 -121l-55 -77q51 -70 75.5 -163t24.5 -204q0 -260 -126 -400.5t-355 -140.5q-70 0 -128.5 13.5t-107.5 35.5l-51 -69l-170 123l64 88q-45 68 -66.5 157t-21.5 193zM342 512q0 -72 12 -133 l301 418q-43 31 -106 30q-98 0 -152.5 -73.5t-54.5 -241.5zM434 233q45 -37 115 -36q104 0 155.5 75.5t51.5 239.5q0 76 -17 145z" />
|
||||||
|
<glyph unicode="ù" horiz-adv-x="1101" d="M106 387v637h267v-582q0 -125 29.5 -180t115.5 -55q76 0 126 45t75 110v662h266v-713q0 -84 8 -164.5t25 -146.5h-201l-47 152h-8q-47 -78 -131 -129.5t-199 -51.5q-78 0 -139.5 20.5t-102 67.5t-62.5 127t-22 201zM250 1413v62h278l123 -316h-147z" />
|
||||||
|
<glyph unicode="ú" horiz-adv-x="1101" d="M106 387v637h267v-582q0 -125 29.5 -180t115.5 -55q76 0 126 45t75 110v662h266v-713q0 -84 8 -164.5t25 -146.5h-201l-47 152h-8q-47 -78 -131 -129.5t-199 -51.5q-78 0 -139.5 20.5t-102 67.5t-62.5 127t-22 201zM426 1159l108 316h271v-62l-228 -254h-151z" />
|
||||||
|
<glyph unicode="û" horiz-adv-x="1101" d="M106 387v637h267v-582q0 -125 29.5 -180t115.5 -55q76 0 126 45t75 110v662h266v-713q0 -84 8 -164.5t25 -146.5h-201l-47 152h-8q-47 -78 -131 -129.5t-199 -51.5q-78 0 -139.5 20.5t-102 67.5t-62.5 127t-22 201zM223 1126l252 373h176l227 -373h-211l-80 136l-34 100 l-35 -100l-92 -136h-203z" />
|
||||||
|
<glyph unicode="ü" horiz-adv-x="1101" d="M106 387v637h267v-582q0 -125 29.5 -180t115.5 -55q76 0 126 45t75 110v662h266v-713q0 -84 8 -164.5t25 -146.5h-201l-47 152h-8q-47 -78 -131 -129.5t-199 -51.5q-78 0 -139.5 20.5t-102 67.5t-62.5 127t-22 201zM180 1333q0 66 40 105t105 39q66 0 104 -39t38 -105 q0 -61 -38 -100t-104 -39t-105.5 39t-39.5 100zM628 1333q0 66 38 105t104 39t105.5 -39t39.5 -105q0 -61 -40 -100t-105 -39q-66 0 -104 39t-38 100z" />
|
||||||
|
<glyph unicode="ý" horiz-adv-x="978" d="M-18 1024h319l188 -575l37 -160h13l26 162l156 573h274l-311 -924q-39 -115 -75 -210t-79 -164.5t-95 -107.5t-124 -38q-106 0 -170 35l49 213q31 -12 62 -12q47 0 91 40t67 144zM412 1159l108 316h271v-62l-228 -254h-151z" />
|
||||||
|
<glyph unicode="þ" horiz-adv-x="1105" d="M117 -410v1844h266v-498h8q43 53 103.5 85t158.5 32q193 0 289 -122t96 -392q0 -131 -30.5 -236.5t-91 -179.5t-147.5 -113t-200 -39q-63 0 -104 9.5t-82 29.5v-420h-266zM383 246q29 -23 62.5 -36t89.5 -13q115 0 172 80.5t57 267.5q0 135 -45.5 208.5t-145.5 73.5 q-74 0 -119.5 -38.5t-70.5 -116.5v-426z" />
|
||||||
|
<glyph unicode="ÿ" horiz-adv-x="978" d="M-18 1024h319l188 -575l37 -160h13l26 162l156 573h274l-311 -924q-39 -115 -75 -210t-79 -164.5t-95 -107.5t-124 -38q-106 0 -170 35l49 213q31 -12 62 -12q47 0 91 40t67 144zM135 1333q0 66 40 105t105 39q66 0 104 -39t38 -105q0 -61 -38 -100t-104 -39t-105.5 39 t-39.5 100zM583 1333q0 66 38 105t104 39t105.5 -39t39.5 -105q0 -61 -40 -100t-105 -39q-66 0 -104 39t-38 100z" />
|
||||||
|
<glyph unicode="Œ" horiz-adv-x="1873" d="M78 717q0 358 157.5 551.5t450.5 193.5q80 0 138.5 -9t103.5 -19h850v-250h-570v-334h518v-250h-518v-350h580v-250h-860q-39 -14 -107.5 -21.5t-134.5 -7.5q-156 0 -270.5 53.5t-189 151.5t-111.5 235.5t-37 305.5zM373 717q0 -109 18.5 -200t58 -156.5t101 -102.5 t149.5 -37q59 0 113.5 7.5t114.5 31.5v901q-43 23 -104.5 37t-137.5 14q-150 0 -231.5 -119.5t-81.5 -375.5z" />
|
||||||
|
<glyph unicode="œ" horiz-adv-x="1722" d="M68 512q0 260 127 400.5t356 140.5q135 0 217 -46t129 -102q47 59 130 103.5t214 44.5q78 0 151.5 -20.5t131 -67.5t92.5 -127t35 -199q0 -43 -5.5 -92t-15.5 -103h-616q6 -129 67.5 -194.5t196.5 -65.5q84 0 150.5 26t101.5 52l88 -174q-61 -49 -166.5 -83t-224.5 -34 q-227 0 -344 152q-51 -68 -132 -110t-200 -42q-123 0 -213 39t-150.5 109.5t-90 171t-29.5 221.5zM342 512q0 -68 12.5 -125t37 -100t64.5 -66.5t95 -23.5q104 0 155.5 75.5t51.5 239.5q0 141 -47 228t-160 87q-98 0 -153.5 -73.5t-55.5 -241.5zM1022 610h381q0 8 1 16.5 t1 16.5q0 94 -42 145.5t-126 51.5q-104 0 -154.5 -62.5t-60.5 -167.5z" />
|
||||||
|
<glyph unicode="Ÿ" horiz-adv-x="1212" d="M-4 1434h334l262 -539l29 -152h10l31 156l253 535h302l-469 -899v-535h-281v532zM238 1634q0 53 37 86t119 33q80 0 116.5 -32.5t36.5 -86.5q0 -53 -37 -84.5t-116 -31.5q-82 0 -119 31.5t-37 84.5zM676 1634q0 53 37 86t117 33q82 0 118.5 -32.5t36.5 -86.5 q0 -53 -36.5 -84.5t-118.5 -31.5q-80 0 -117 31.5t-37 84.5z" />
|
||||||
|
<glyph unicode="ˆ" horiz-adv-x="901" d="M123 1126l252 373h176l227 -373h-211l-80 136l-34 100l-35 -100l-92 -136h-203z" />
|
||||||
|
<glyph unicode="˜" horiz-adv-x="925" d="M123 1348q63 76 117.5 104.5t103.5 28.5q41 0 79 -14.5t75 -31t71.5 -30.5t71.5 -14q29 0 58.5 12t62.5 43l41 -143q-59 -66 -109.5 -90.5t-97.5 -24.5q-41 0 -80 13t-76 29.5t-73.5 30t-73.5 13.5q-31 0 -63.5 -13.5t-67.5 -46.5z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="891" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="1782" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="891" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="1782" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="594" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="445" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="297" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="297" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="222" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="356" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="99" />
|
||||||
|
<glyph unicode="‐" horiz-adv-x="737" d="M111 471v236h514v-236h-514z" />
|
||||||
|
<glyph unicode="‑" horiz-adv-x="737" d="M111 471v236h514v-236h-514z" />
|
||||||
|
<glyph unicode="‒" horiz-adv-x="737" d="M111 471v236h514v-236h-514z" />
|
||||||
|
<glyph unicode="–" horiz-adv-x="1351" d="M223 471v238h905v-238h-905z" />
|
||||||
|
<glyph unicode="—" horiz-adv-x="1679" d="M223 471v238h1233v-238h-1233z" />
|
||||||
|
<glyph unicode="‘" horiz-adv-x="456" d="M78 1311q0 82 25.5 139t61.5 95t75 59.5t67 31.5l66 -110q-41 -16 -70 -52t-33 -77q41 0 75 -36t34 -95t-40 -95t-99 -36q-76 0 -119 48t-43 128z" />
|
||||||
|
<glyph unicode="’" horiz-adv-x="456" d="M78 1319q0 59 40 96t101 37q74 0 117 -49t43 -129q0 -82 -25.5 -139.5t-61.5 -95.5t-76 -59.5t-66 -31.5l-68 113q41 18 72.5 49t35.5 78q-41 -2 -76.5 31.5t-35.5 99.5z" />
|
||||||
|
<glyph unicode="‚" horiz-adv-x="456" d="M78 127q0 59 40 96t101 37q74 0 117 -49t43 -129q0 -82 -25.5 -139.5t-61.5 -95.5t-76 -59.5t-66 -31.5l-68 113q41 18 72.5 49t35.5 78q-41 -2 -76.5 31.5t-35.5 99.5z" />
|
||||||
|
<glyph unicode="“" horiz-adv-x="811" d="M78 1311q0 82 25.5 139t61.5 95t75 59.5t67 31.5l66 -110q-41 -16 -70 -52t-33 -77q41 0 75 -36t34 -95t-40 -95t-99 -36q-76 0 -119 48t-43 128zM432 1311q0 82 25.5 139t61.5 95t75 59.5t67 31.5l66 -110q-41 -16 -70 -52t-33 -77q41 0 75 -36t34 -95t-40 -95t-99 -36 q-76 0 -119 48t-43 128z" />
|
||||||
|
<glyph unicode="”" horiz-adv-x="811" d="M78 1319q0 59 40 96t101 37q74 0 117 -49t43 -129q0 -82 -25.5 -139.5t-61.5 -95.5t-76 -59.5t-66 -31.5l-68 113q41 18 72.5 49t35.5 78q-41 -2 -76.5 31.5t-35.5 99.5zM432 1319q0 59 40 96t101 37q74 0 117 -49t43 -129q0 -82 -25.5 -139.5t-61.5 -95.5t-76 -59.5 t-66 -31.5l-68 113q41 18 72.5 49t35.5 78q-41 -2 -76.5 31.5t-35.5 99.5z" />
|
||||||
|
<glyph unicode="„" horiz-adv-x="811" d="M78 127q0 59 40 96t101 37q74 0 117 -49t43 -129q0 -82 -25.5 -139.5t-61.5 -95.5t-76 -59.5t-66 -31.5l-68 113q41 18 72.5 49t35.5 78q-41 -2 -76.5 31.5t-35.5 99.5zM432 127q0 59 40 96t101 37q74 0 117 -49t43 -129q0 -82 -25.5 -139.5t-61.5 -95.5t-76 -59.5 t-66 -31.5l-68 113q41 18 72.5 49t35.5 78q-41 -2 -76.5 31.5t-35.5 99.5z" />
|
||||||
|
<glyph unicode="•" horiz-adv-x="925" d="M150 637q0 70 24.5 127t67.5 98t99 64.5t120 23.5q66 0 123 -21.5t99 -61.5t66.5 -98t24.5 -132t-24.5 -131t-66.5 -97t-99.5 -61.5t-122.5 -21.5q-63 0 -119.5 21.5t-99.5 61.5t-67.5 97t-24.5 131z" />
|
||||||
|
<glyph unicode="…" horiz-adv-x="1656" d="M109 135q0 72 45 114t119 42q78 0 123 -42t45 -114t-45 -115t-123 -43q-74 0 -119 43t-45 115zM666 135q0 72 45 114t119 42q78 0 123 -42t45 -114t-45 -115t-123 -43q-74 0 -119 43t-45 115zM1223 135q0 72 45 114t119 42q78 0 123 -42t45 -114t-45 -115t-123 -43 q-74 0 -119 43t-45 115z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="356" />
|
||||||
|
<glyph unicode="‹" horiz-adv-x="628" d="M59 530l328 471l154 -127l-170 -258l-99 -84l99 -73l186 -250l-158 -131z" />
|
||||||
|
<glyph unicode="›" horiz-adv-x="628" d="M70 872l159 129l340 -452l-327 -471l-156 125l172 260l98 84l-98 74z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="445" />
|
||||||
|
<glyph unicode="€" d="M4 473l66 191h100v53v32.5t2 32.5h-168l66 191h127q31 135 89 227t136 150.5t171 85t193 26.5q106 0 189.5 -16t138.5 -39l-72 -211q-45 18 -104 27.5t-139 9.5q-123 0 -211 -61.5t-133 -198.5h530l-53 -191h-510q-2 -16 -2 -31.5v-33.5v-53h471l-53 -191h-385 q41 -135 130 -203.5t236 -68.5q86 0 148.5 18.5t111.5 46.5l56 -207q-31 -23 -74 -40t-90 -27t-96.5 -15.5t-94.5 -5.5q-225 0 -379.5 120t-207.5 382h-189z" />
|
||||||
|
<glyph unicode="™" horiz-adv-x="1941" d="M59 1208v226h750v-226h-242v-512h-266v512h-242zM879 696v738h266l186 -308l49 -129h2l52 133l172 304h264v-738h-232v295l35 211h-12l-74 -174l-139 -240h-160l-139 234l-80 180h-10l47 -209v-297h-227z" />
|
||||||
|
<glyph unicode="" horiz-adv-x="1024" d="M0 0v1024h1024v-1024h-1024z" />
|
||||||
|
</font>
|
||||||
|
</defs></svg>
|
After Width: | Height: | Size: 61 KiB |
242
source/app/fonts/svg/ptsansbolditalic.svg
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<metadata></metadata>
|
||||||
|
<defs>
|
||||||
|
<font id="pt_sansbold_italic" horiz-adv-x="1116" >
|
||||||
|
<font-face units-per-em="2048" ascent="1536" descent="-512" />
|
||||||
|
<missing-glyph horiz-adv-x="518" />
|
||||||
|
<glyph unicode="fi" horiz-adv-x="1077" d="M-264 -369l69 187q35 -14 70 -18.5t88 -4.5q66 0 101.5 51.5t52.5 153.5l123 813h-136l43 211h134l12 57q41 195 155.5 284t294.5 89q135 0 234.5 -22.5t155.5 -59.5l-103 -190q-45 29 -115.5 46t-158.5 17q-57 0 -95 -15.5t-63 -45t-40 -70.5t-26 -90h519l-154 -1024 h-252l123 813h-276l-123 -813q-16 -104 -42 -184t-68 -133.5t-104.5 -81t-152.5 -27.5q-74 0 -144.5 11.5t-121.5 45.5z" />
|
||||||
|
<glyph unicode="fl" horiz-adv-x="1144" d="M-264 -369l69 187q35 -14 70 -18.5t88 -4.5q66 0 101.5 51.5t52.5 153.5l125 813h-136l44 211h133l12 57q41 193 149.5 286t323.5 93q45 0 102.5 -4t112.5 -9t103.5 -11t74.5 -13l-184 -1091q-4 -23 -7 -40.5t-3 -33.5q0 -72 55 -72q23 0 46.5 4.5t57.5 16.5l-8 -182 q-18 -8 -44.5 -17.5t-59.5 -16.5t-69 -11.5t-68 -4.5q-90 0 -137.5 35t-47.5 117q0 39 8 78l172 1028q-23 6 -65.5 11t-83.5 5q-90 0 -129 -62.5t-59 -162.5h147l-41 -211h-147l-125 -813q-18 -104 -44 -184t-67 -133.5t-103.5 -81t-152.5 -27.5q-74 0 -144.5 11.5 t-121.5 45.5z" />
|
||||||
|
<glyph horiz-adv-x="2048" />
|
||||||
|
<glyph horiz-adv-x="2048" />
|
||||||
|
<glyph unicode="
" horiz-adv-x="518" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="518" />
|
||||||
|
<glyph unicode="	" horiz-adv-x="518" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="518" />
|
||||||
|
<glyph unicode="!" horiz-adv-x="579" d="M152 135q0 72 45 114t118 42q76 0 121 -42t45 -114t-45 -115t-121 -43q-74 0 -118.5 43t-44.5 115zM283 426l18 334l143 674h263l-144 -674l-121 -334h-159z" />
|
||||||
|
<glyph unicode=""" horiz-adv-x="724" d="M143 991l95 443h221l-162 -443h-154zM430 991l95 443h221l-162 -443h-154z" />
|
||||||
|
<glyph unicode="#" d="M98 420l45 198h154l51 218h-147l45 198h149l72 295h219l-72 -295h183l71 295h219l-71 -295h147l-51 -198h-143l-51 -218h141l-49 -198h-140l-73 -316h-219l73 316h-182l-74 -316h-219l74 316h-152zM516 618h182l52 218h-183z" />
|
||||||
|
<glyph unicode="$" d="M121 88l96 199q29 -20 87 -47t136 -41l97 452q-47 31 -92.5 67t-81 82t-57 104.5t-21.5 135.5q0 98 33.5 172t92 125.5t134.5 80t162 38.5l41 182h202l-39 -184q78 -10 137.5 -29.5t102.5 -42.5l-102 -208q-29 16 -78 32.5t-109 26.5l-88 -416q47 -33 94 -69.5t84 -85 t59.5 -108.5t22.5 -138q0 -98 -32.5 -175t-91 -132.5t-139.5 -88t-177 -43.5l-37 -182h-203l39 185q-106 14 -171.5 46.5t-100.5 61.5zM551 1073q0 -59 33.5 -101t87.5 -83l73 352q-98 -4 -146 -51t-48 -117zM557 193q109 8 160 63t51 129q0 66 -37 111t-92 86z" />
|
||||||
|
<glyph unicode="%" horiz-adv-x="1646" d="M113 1022q0 111 38 192.5t99.5 136t136 81t148.5 26.5q135 0 205.5 -62.5t70.5 -183.5q0 -117 -34.5 -201.5t-94 -140t-136.5 -82t-159 -26.5q-127 0 -200.5 70.5t-73.5 189.5zM164 113l1179 1349l150 -135l-1180 -1356zM338 1034q-2 -45 20.5 -72.5t65.5 -27.5 q68 0 115 70.5t47 181.5q0 100 -88 100q-35 0 -63.5 -20.5t-51 -54t-35 -80t-10.5 -97.5zM860 262q0 111 38 192.5t99.5 136t136 81t148.5 26.5q135 0 205.5 -62.5t70.5 -183.5q0 -117 -34.5 -201.5t-94 -140t-136.5 -82t-159 -26.5q-127 0 -200.5 70.5t-73.5 189.5z M1085 274q-2 -45 20.5 -72.5t65.5 -27.5q68 0 115 70.5t47 181.5q0 100 -88 100q-35 0 -63.5 -20.5t-51 -54t-35 -80t-10.5 -97.5z" />
|
||||||
|
<glyph unicode="&" horiz-adv-x="1603" d="M150 332q0 94 37.5 178t100 153.5t141.5 126t163 97.5q-35 68 -44 123t-9 110q0 68 22.5 129.5t71.5 108.5t125 75.5t180 28.5q82 0 134 -20.5t83 -54t42 -75.5t11 -83q0 -104 -83 -199.5t-236 -179.5q45 -111 93 -203t114 -182q53 51 106 128t98 157l162 -103 q-20 -37 -51 -81t-64.5 -89t-67.5 -85t-60 -68q49 -59 107 -111.5t116 -77.5l-178 -196q-31 12 -64 35.5t-64.5 51t-60 58.5t-49.5 59q-88 -68 -203.5 -120t-269.5 -52q-94 0 -169 28t-127 76t-79.5 113.5t-27.5 143.5zM416 381q0 -86 55 -135t164 -49q78 0 152.5 33.5 t119.5 74.5q-76 109 -135 216.5t-98 203.5q-121 -82 -189.5 -165t-68.5 -179zM786 1133q0 -45 7.5 -77t29.5 -81q86 51 133.5 100t47.5 105q0 39 -18.5 61.5t-70.5 22.5q-63 0 -96 -39t-33 -92z" />
|
||||||
|
<glyph unicode="'" horiz-adv-x="446" d="M186 991l95 443h221l-162 -443h-154z" />
|
||||||
|
<glyph unicode="(" horiz-adv-x="634" d="M127 178q0 197 47 382t126 350t183.5 304.5t218.5 243.5l132 -110q-96 -106 -179.5 -238.5t-144.5 -282t-97 -310.5t-36 -324q0 -129 18.5 -255t83.5 -274l-157 -110q-59 78 -96.5 158.5t-60 160.5t-30.5 156.5t-8 148.5z" />
|
||||||
|
<glyph unicode=")" horiz-adv-x="634" d="M-158 -338q92 102 176 236.5t146.5 286t99.5 311t37 313.5q0 170 -24.5 300t-79.5 232l178 115q92 -123 134 -277.5t42 -340.5q0 -197 -46 -383.5t-125 -352t-182.5 -307t-217.5 -246.5z" />
|
||||||
|
<glyph unicode="*" horiz-adv-x="729" d="M160 1112v152h121l120 -35l-102 90l-57 102l131 76l57 -94l31 -121l31 113l57 100l129 -72l-62 -106l-96 -88l131 33h117v-150h-111l-125 33l103 -96l51 -86l-131 -76l-55 94l-41 131l-27 -119l-59 -100l-133 76l61 100l92 76l-112 -33h-121z" />
|
||||||
|
<glyph unicode="+" horiz-adv-x="1034" d="M119 578v229h332v346h239v-346h334v-229h-334v-351h-239v351h-332z" />
|
||||||
|
<glyph unicode="," horiz-adv-x="442" d="M-53 -193q59 23 108.5 74.5t67.5 108.5q-35 2 -65.5 34.5t-30.5 86.5q0 82 52 127t124 45t107.5 -47.5t33.5 -108.5q-2 -100 -41 -175t-93 -127t-112.5 -84t-97.5 -44z" />
|
||||||
|
<glyph unicode="-" horiz-adv-x="702" d="M115 483l51 213h489l-51 -213h-489z" />
|
||||||
|
<glyph unicode="." horiz-adv-x="514" d="M68 135q0 72 45 114t118 42q76 0 121 -42t45 -114t-45 -115t-121 -43q-74 0 -118.5 43t-44.5 115z" />
|
||||||
|
<glyph unicode="/" horiz-adv-x="794" d="M-158 -193l1043 1651l176 -94l-1045 -1655z" />
|
||||||
|
<glyph unicode="0" d="M113 469q0 213 48 394t134 314.5t203.5 209t257.5 75.5q80 0 150.5 -24.5t123.5 -82t84 -153.5t31 -237q0 -190 -44 -369.5t-127 -318t-203 -222.5t-269 -84q-100 0 -174 39t-121 105.5t-70.5 158t-23.5 195.5zM367 471q0 -84 14 -137t37.5 -84t56.5 -42t70 -11 q72 0 134 67.5t109.5 176t75 244.5t27.5 276q0 63 -7 114t-26.5 87t-52.5 55.5t-84 19.5q-68 0 -131.5 -63.5t-113.5 -169t-79.5 -244.5t-29.5 -289z" />
|
||||||
|
<glyph unicode="1" d="M119 0l47 225h270l174 809l58 140l-119 -121l-199 -127l-80 157l527 375h143l-262 -1233h264l-47 -225h-776z" />
|
||||||
|
<glyph unicode="2" d="M74 0l28 137q57 53 135 126t162 156t165 172t144.5 175t103.5 166t40 145q0 68 -35 111t-133 43q-63 0 -130 -30t-132 -77l-62 193q98 72 197.5 108.5t230.5 36.5q152 0 235 -87t83 -228q0 -115 -53.5 -232.5t-135 -230.5t-180 -213t-186.5 -180l-121 -84v-10l143 28h367 l-47 -225h-819z" />
|
||||||
|
<glyph unicode="3" d="M84 35l117 227q41 -27 100 -43t137 -16q80 0 138.5 22.5t97.5 59.5t57.5 85t18.5 97q0 98 -52.5 143t-189.5 45h-143l30 142l301 338l131 92l-155 -19h-326l49 226h744l-31 -146l-350 -389l-99 -55v-10l82 12q41 -4 87 -24.5t85 -60.5t65 -102.5t26 -152.5 q0 -117 -38 -215t-114 -169t-188.5 -111t-260.5 -40q-88 0 -178 16.5t-141 47.5z" />
|
||||||
|
<glyph unicode="4" d="M57 399l31 152l805 893h209l-176 -834h215l-45 -211h-215l-84 -399h-236l84 399h-588zM336 596l127 14h227l68 316l53 172h-6l-98 -148l-258 -276z" />
|
||||||
|
<glyph unicode="5" d="M74 33l114 217q41 -20 93.5 -33.5t130.5 -13.5q86 0 147.5 24.5t101 65.5t59 94t19.5 113q0 102 -62.5 145t-207.5 43l-158 -6l158 752h670l-52 -250h-450l-59 -283l75 8q82 0 144.5 -26.5t105.5 -73.5t65.5 -112.5t22.5 -141.5q0 -283 -159.5 -433.5t-458.5 -150.5 q-41 0 -84 5.5t-83 13.5t-74 19t-58 24z" />
|
||||||
|
<glyph unicode="6" d="M127 432q0 209 78 390.5t206 317.5t291.5 220t337.5 102l15 -211q-102 -16 -200.5 -58t-183.5 -106.5t-150.5 -146.5t-100.5 -176q55 59 136 90t167 31q158 0 246 -99.5t88 -263.5q0 -111 -33 -211t-99.5 -175t-167 -120t-233.5 -45q-66 0 -136.5 23.5t-128.5 78 t-95 142.5t-37 217zM367 449q0 -111 46 -181.5t142 -70.5q117 0 184.5 77.5t67.5 200.5q0 82 -42 133t-140 51q-78 0 -145.5 -34.5t-102.5 -87.5q-4 -20 -7 -46t-3 -42z" />
|
||||||
|
<glyph unicode="7" d="M127 0l674 1104l104 100l-119 -20h-481l51 250h881l-16 -78l-830 -1356h-264z" />
|
||||||
|
<glyph unicode="8" d="M111 313q0 78 26.5 144.5t71.5 121t104.5 95.5t124.5 65q-29 27 -54.5 54.5t-45 62.5t-30.5 81t-11 107q0 100 38 179.5t103.5 131.5t151.5 79.5t182 27.5q172 0 262 -89t90 -228q0 -72 -23.5 -130.5t-63.5 -107.5t-92 -89t-109 -70q92 -72 132 -153t40 -175 q0 -104 -38 -187t-105.5 -141.5t-162 -89.5t-206.5 -31q-80 0 -151 22.5t-123 65.5t-81.5 106.5t-29.5 147.5zM350 362q0 -72 43 -118.5t142 -46.5q45 0 87 12t74.5 35.5t51 59.5t18.5 85q0 47 -15.5 84t-41 66.5t-60.5 55.5t-71 48q-104 -53 -166 -123.5t-62 -157.5z M539 1047q0 -72 45 -122.5t114 -90.5q37 27 70 57.5t58.5 63t41 67.5t15.5 68q0 74 -37 110.5t-105 36.5q-86 0 -144 -49t-58 -141z" />
|
||||||
|
<glyph unicode="9" d="M203 934q0 123 41 221t113.5 166t170 104.5t211.5 36.5q86 0 160 -26.5t128 -83t86 -141.5t32 -201q0 -164 -42 -302.5t-112.5 -251t-164 -200.5t-196 -149.5t-208 -95.5t-199.5 -40l-12 209q113 20 212 64.5t179 105t138.5 135t90.5 154.5q-59 -47 -128.5 -70.5 t-167.5 -23.5q-57 0 -117 21.5t-107 67.5t-77.5 121t-30.5 179zM453 973q0 -59 15 -98t42 -64t58.5 -35t66.5 -10q78 0 145.5 24.5t106.5 65.5q6 23 11 64t5 59q0 117 -46 189.5t-150 72.5q-49 0 -94.5 -15.5t-81 -48t-57 -83.5t-21.5 -121z" />
|
||||||
|
<glyph unicode=":" horiz-adv-x="643" d="M184 160q0 72 45 113.5t119 41.5q76 0 121 -42t45 -113q0 -72 -45 -115t-121 -43q-74 0 -119 43t-45 115zM338 877q0 72 45 113.5t119 41.5q76 0 121 -42t45 -113q0 -72 -45 -115t-121 -43q-74 0 -119 43t-45 115z" />
|
||||||
|
<glyph unicode=";" horiz-adv-x="628" d="M106 -193q59 23 109 74.5t68 108.5q-35 2 -66 34.5t-31 86.5q0 82 52.5 127t123.5 45q72 0 108 -47.5t34 -108.5q-2 -100 -41 -175t-93.5 -127t-112.5 -84t-97 -44zM324 877q0 72 45 113.5t118 41.5q76 0 121 -42t45 -113q0 -72 -45 -115t-121 -43q-74 0 -118.5 43 t-44.5 115z" />
|
||||||
|
<glyph unicode="<" horiz-adv-x="1034" d="M104 584v143l791 473l117 -184l-459 -285l-186 -72l184 -63l471 -281l-117 -184z" />
|
||||||
|
<glyph unicode="=" horiz-adv-x="1034" d="M119 383v229h905v-229h-905zM119 775v229h905v-229h-905z" />
|
||||||
|
<glyph unicode=">" horiz-adv-x="1034" d="M123 1018l115 182l802 -452v-144l-792 -473l-115 186l457 283l186 74l-184 61z" />
|
||||||
|
<glyph unicode="?" horiz-adv-x="880" d="M168 135q0 72 45 114t119 42q76 0 121 -42t45 -114t-45 -115t-121 -43q-74 0 -119 43t-45 115zM233 1339q84 51 182.5 87t239.5 36q172 0 252 -72.5t80 -195.5q0 -109 -32.5 -183.5t-84 -131t-113 -100.5t-117.5 -93t-101 -110.5t-62 -149.5h-217q12 111 50 189.5 t88.5 137t106.5 102.5t102 85t77 84t31 100q0 55 -32 86t-114 31q-63 0 -139 -27.5t-133 -66.5z" />
|
||||||
|
<glyph unicode="@" horiz-adv-x="2168" d="M205 483q0 223 80 403.5t215 307.5t313 195.5t377 68.5q188 0 350 -54t280.5 -155.5t186.5 -248t68 -332.5q0 -131 -47.5 -246t-127 -199t-187 -133t-230.5 -49q-51 0 -95.5 11t-75 38t-45 70t-7.5 106h-9q-31 -43 -65.5 -84t-77.5 -72.5t-94 -50t-113 -18.5 q-51 0 -95 21.5t-77 60.5t-52.5 94t-19.5 123q0 127 41 247t111 212t163 148.5t197 56.5q72 0 121 -21.5t92 -56.5l64 65h143l-100 -555q-4 -25 -6 -46t-2 -38q0 -98 75 -98q53 0 105.5 24.5t93.5 76t65.5 129t24.5 184.5q0 154 -51 263t-140 180t-210 103.5t-258 32.5 q-160 0 -298 -57t-239.5 -158.5t-159 -240t-57.5 -299.5q0 -160 48 -287t141.5 -217t229.5 -138.5t312 -48.5q59 0 135 15.5t138 44.5l63 -197q-86 -41 -172 -57.5t-199 -16.5q-201 0 -369.5 57.5t-291.5 170t-192.5 279.5t-69.5 386zM905 408q0 -68 29 -112t96 -44 q29 0 61.5 17.5t63.5 47t58.5 66.5t50.5 78l53 282q-29 23 -57.5 36.5t-69.5 13.5q-61 0 -113.5 -36t-90.5 -91.5t-59.5 -124t-21.5 -133.5z" />
|
||||||
|
<glyph unicode="A" horiz-adv-x="1191" d="M-78 0l797 1444h196l187 -1444h-268l-41 317h-418l-170 -317h-283zM492 543h290l-32 319l2 225h-11l-82 -227z" />
|
||||||
|
<glyph unicode="B" horiz-adv-x="1163" d="M41 10l299 1413q39 6 88 12.5t104.5 10.5t114 6t113.5 2q94 0 175 -19.5t139.5 -60.5t92 -105.5t33.5 -154.5q0 -68 -22.5 -130t-64.5 -111.5t-100.5 -82t-131.5 -42.5v-11q39 -8 77.5 -29.5t69.5 -55.5t49.5 -80t18.5 -103q0 -131 -51.5 -224t-137.5 -151.5t-200.5 -86 t-241.5 -27.5h-85t-111.5 3t-119 9t-108.5 18zM342 223q8 -4 29.5 -6t47 -3t52.5 -2t45 -1q51 0 105.5 12.5t98.5 41t72.5 73.5t28.5 111q0 51 -22.5 83.5t-59.5 52t-85 26.5t-99 7h-131zM471 831h88q29 0 68 1.5t65 5.5q37 6 79 20t76 41t56.5 68t22.5 102q0 88 -58.5 121 t-148.5 33q-53 0 -98.5 -2t-69.5 -7z" />
|
||||||
|
<glyph unicode="C" horiz-adv-x="1099" d="M119 557q0 242 67.5 413t178 280.5t253 160.5t291.5 51q117 0 200 -17.5t130 -39.5l-104 -238q-41 23 -98.5 34t-145.5 11q-104 0 -194.5 -43t-156 -122.5t-103.5 -194.5t-38 -260q0 -174 87 -272.5t233 -98.5q92 0 152.5 19.5t113.5 48.5l4 -230q-137 -88 -336 -88 q-135 0 -235.5 45t-167 125t-99 186.5t-32.5 229.5z" />
|
||||||
|
<glyph unicode="D" horiz-adv-x="1269" d="M41 -2l303 1436q43 6 94 10t95.5 6t76.5 2q18 0 52 1t75 1q125 0 227.5 -31.5t175 -97t112.5 -168t40 -244.5q0 -90 -15 -193.5t-52 -207.5t-101.5 -200.5t-162 -170t-233.5 -119t-316 -45.5q-31 0 -62 1.5t-43 1.5q-41 2 -91 5l-100 6t-75 7zM356 233q8 -2 25.5 -3 t38 -2t39 -1h28.5q143 0 243.5 64.5t163 162t90.5 211t28 212.5q0 164 -69 245.5t-228 81.5q-41 0 -86 -2t-70 -6z" />
|
||||||
|
<glyph unicode="E" horiz-adv-x="1030" d="M41 0l303 1434h266h541l-53 -250h-541l-72 -334h494l-55 -250h-490l-76 -350h551l-51 -250h-551h-266z" />
|
||||||
|
<glyph unicode="F" horiz-adv-x="1001" d="M41 0l303 1434h266h541l-53 -250h-541l-76 -355h498l-51 -249h-498l-123 -580h-266z" />
|
||||||
|
<glyph unicode="G" horiz-adv-x="1198" d="M119 553q0 236 64.5 408t175 283.5t258 164.5t311.5 53q117 0 208 -19.5t138 -39.5l-107 -236q-43 20 -107.5 32.5t-156.5 12.5q-109 0 -201 -41t-159.5 -120.5t-105.5 -197.5t-38 -269q0 -170 80 -266.5t215 -96.5q100 0 176 51l58 273l-209 33l37 170h430l-135 -639 q-92 -72 -193.5 -105t-218.5 -33q-113 0 -208 39t-164.5 113t-108.5 182.5t-39 247.5z" />
|
||||||
|
<glyph unicode="H" horiz-adv-x="1277" d="M41 0l303 1434h266l-123 -584h498l123 584h266l-303 -1434h-266l127 600h-498l-127 -600h-266z" />
|
||||||
|
<glyph unicode="I" horiz-adv-x="569" d="M72 0l303 1434h264l-303 -1434h-264z" />
|
||||||
|
<glyph unicode="J" horiz-adv-x="663" d="M-104 23l102 229q47 -27 111 -27q43 0 71.5 17.5t48 48.5t31.5 73t25 93l204 977h267l-224 -1049q-18 -86 -46.5 -160.5t-76 -130t-118 -87.5t-170.5 -32q-57 0 -120.5 12.5t-104.5 35.5z" />
|
||||||
|
<glyph unicode="K" horiz-adv-x="1214" d="M41 0l303 1434h266l-135 -635l64 22l485 613h319l-516 -609l-122 -71l90 -80l311 -674h-297l-277 612h-96l-129 -612h-266z" />
|
||||||
|
<glyph unicode="L" horiz-adv-x="1013" d="M41 0l303 1434h266l-252 -1184h596l-51 -250h-596h-266z" />
|
||||||
|
<glyph unicode="M" horiz-adv-x="1570" d="M41 0l303 1434h236l215 -656l26 -164h10l95 168l483 652h256l-303 -1434h-264l157 743l91 283h-13l-135 -231l-403 -531h-84l-193 537l-37 225h-10l-20 -281l-158 -745h-252z" />
|
||||||
|
<glyph unicode="N" horiz-adv-x="1292" d="M41 0l307 1444h184l353 -766l63 -223h13l14 223l162 756h252l-308 -1444h-184l-350 760l-68 229h-10l-18 -229l-158 -750h-252z" />
|
||||||
|
<glyph unicode="O" horiz-adv-x="1318" d="M119 537q0 190 52 359t148.5 295t232.5 198.5t304 72.5q111 0 200 -32.5t151.5 -101t97 -173t34.5 -248.5q0 -193 -52 -362.5t-147.5 -297.5t-227.5 -202t-291 -74q-242 0 -371 142.5t-131 423.5zM399 545q0 -147 56.5 -235.5t185.5 -88.5q94 0 171 56.5t132 151.5 t85 218t30 256q0 162 -63.5 235.5t-174.5 73.5q-92 0 -169 -53t-133 -144t-88 -213t-32 -257z" />
|
||||||
|
<glyph unicode="P" horiz-adv-x="1126" d="M41 0l301 1419q86 16 183.5 25.5t195.5 9.5q104 0 193.5 -23.5t156 -72.5t103 -126t36.5 -183q0 -160 -55 -267.5t-146 -174t-208 -94.5t-238 -28h-31.5t-45 1t-45 3.5t-31.5 4.5l-103 -494h-266zM463 735q8 -2 22.5 -4t32 -3t32.5 -1h23q70 0 134.5 15.5t113.5 49t79 89 t30 135.5q0 59 -19.5 98t-52.5 60.5t-77 29.5t-93 8q-37 0 -70.5 -3t-56.5 -7z" />
|
||||||
|
<glyph unicode="Q" horiz-adv-x="1318" d="M119 537q0 190 52 359t148.5 295t232.5 198.5t304 72.5q111 0 200 -32.5t151.5 -101t97 -173t34.5 -248.5q0 -193 -52 -362.5t-147.5 -297.5t-227.5 -202t-291 -74q-242 0 -371 142.5t-131 423.5zM328 -317l51 241q57 12 115 13q82 0 158.5 -20.5t155.5 -44.5t163 -44.5 t180 -20.5q43 0 89 5.5t95 17.5l-51 -244q-94 -26 -187 -26h-7q-98 0 -188.5 21.5t-173.5 46t-158.5 46t-149.5 21.5q-47 0 -92 -12zM399 545q0 -147 56.5 -235.5t185.5 -88.5q94 0 171 56.5t132 151.5t85 218t30 256q0 162 -63.5 235.5t-174.5 73.5q-92 0 -169 -53 t-133 -144t-88 -213t-32 -257z" />
|
||||||
|
<glyph unicode="R" horiz-adv-x="1196" d="M41 0l301 1419q98 18 198.5 26.5t180.5 8.5q94 0 178 -22.5t145.5 -68.5t97.5 -119t36 -171q0 -113 -34 -195.5t-89.5 -139t-126 -88.5t-144.5 -42l80 -63l199 -545h-295l-197 561l-141 27l-123 -588h-266zM471 778h109q59 0 116.5 11.5t101.5 41t71.5 78.5t27.5 125 q0 70 -47 120t-152 50q-41 0 -76.5 -3t-60.5 -7z" />
|
||||||
|
<glyph unicode="S" horiz-adv-x="1044" d="M-4 57l137 238q20 -12 53 -26.5t75 -27t91 -20.5t99 -8q57 0 108 9t89 30.5t59.5 54.5t21.5 82q0 55 -37 94t-93 74t-120.5 73t-121 89t-93.5 123.5t-37 177.5q0 119 42 203t114 137t168 77.5t207 24.5q59 0 118.5 -6t112.5 -17.5t98.5 -26.5t75.5 -34l-135 -233 q-39 25 -114.5 50.5t-168.5 25.5q-47 0 -92 -9.5t-79.5 -30t-55 -53t-20.5 -77.5q0 -59 36.5 -100.5t93 -77t121 -72.5t121 -86t93 -118t36.5 -169q0 -121 -42 -208t-118.5 -142t-184 -81t-238.5 -26q-72 0 -136.5 8.5t-120 20.5t-97.5 27.5t-66 29.5z" />
|
||||||
|
<glyph unicode="T" horiz-adv-x="1120" d="M197 1184l53 250h1059l-52 -250h-397l-252 -1184h-264l250 1184h-397z" />
|
||||||
|
<glyph unicode="U" horiz-adv-x="1232" d="M129 356q0 41 5 84t16 90l192 904h264l-188 -902q-16 -78 -17 -126q0 -98 51.5 -139.5t149.5 -41.5q123 0 190.5 72t102.5 231l192 906h250l-194 -926q-31 -147 -80 -248.5t-119 -165t-164 -91.5t-217 -28q-119 0 -200.5 28t-134 79t-76 120.5t-23.5 153.5z" />
|
||||||
|
<glyph unicode="V" horiz-adv-x="1185" d="M207 1434h291l92 -840l-15 -244h9l90 244l442 840h299l-809 -1444h-192z" />
|
||||||
|
<glyph unicode="W" horiz-adv-x="1691" d="M223 1434h281l6 -799l-29 -254h11l79 258l406 795h180l60 -799l-27 -254h10l82 258l336 795h287l-682 -1444h-187l-75 796l16 220h-12l-78 -222l-408 -794h-186z" />
|
||||||
|
<glyph unicode="X" horiz-adv-x="1245" d="M-49 0l573 731l-231 703h289l123 -414l20 -146l76 146l305 414h319l-538 -693l256 -741h-285l-147 442l-25 152l-82 -152l-330 -442h-323z" />
|
||||||
|
<glyph unicode="Y" horiz-adv-x="1165" d="M217 1434h295l133 -539l-4 -152h8l64 156l358 535h305l-637 -899l-112 -535h-265l111 532z" />
|
||||||
|
<glyph unicode="Z" horiz-adv-x="1060" d="M-23 0l54 250l737 852l119 82h-658l52 250h944l-51 -250l-742 -858l-115 -76h658l-53 -250h-945z" />
|
||||||
|
<glyph unicode="[" horiz-adv-x="643" d="M4 -471l402 1905h456l-45 -224h-215l-309 -1456h215l-49 -225h-455z" />
|
||||||
|
<glyph unicode="\" horiz-adv-x="868" d="M74 1368l211 88l682 -1651l-207 -92z" />
|
||||||
|
<glyph unicode="]" horiz-adv-x="641" d="M-160 -471l49 225h215l308 1456h-215l45 224h458l-403 -1905h-457z" />
|
||||||
|
<glyph unicode="^" horiz-adv-x="1034" d="M143 846l402 598h143l379 -598h-268l-146 250l-45 143l-51 -145l-158 -248h-256z" />
|
||||||
|
<glyph unicode="_" horiz-adv-x="909" d="M-94 -240h909v-219h-909v219z" />
|
||||||
|
<glyph unicode="`" horiz-adv-x="487" d="M553 1413l14 62h264l50 -316h-142z" />
|
||||||
|
<glyph unicode="a" horiz-adv-x="1030" d="M68 295q0 150 37.5 287t117.5 241.5t202 167t290 62.5q72 0 156.5 -13.5t164.5 -35.5l-127 -594q-16 -78 -23 -158t-7 -152q0 -29 1 -54.5t3 -47.5h-187l-28 176h-9q-23 -37 -58.5 -72.5t-78.5 -65.5t-91 -47.5t-99 -17.5q-135 0 -199.5 88t-64.5 236zM328 344 q0 -66 21.5 -114t78.5 -48q37 0 69.5 15.5t60.5 40t49.5 53t37.5 53.5l103 477q-23 10 -52.5 15.5t-58.5 5.5q-74 0 -131 -44t-97 -115t-60.5 -160t-20.5 -179z" />
|
||||||
|
<glyph unicode="b" horiz-adv-x="1048" d="M45 57l291 1377h252l-127 -590h8q27 37 61.5 72.5t76.5 65.5t91.5 48.5t108.5 18.5q111 0 166 -78t55 -207q0 -195 -54 -342.5t-142.5 -246.5t-199 -149.5t-222.5 -50.5q-125 0 -220.5 24t-144.5 58zM328 215q23 -16 55.5 -22.5t71.5 -6.5q51 0 106 34t101.5 99.5 t76 160.5t29.5 216q0 141 -82 142q-41 0 -81 -22.5t-76.5 -56.5t-66.5 -73t-48 -74z" />
|
||||||
|
<glyph unicode="c" horiz-adv-x="843" d="M70 324q0 172 49 307t130 228t184.5 143.5t211.5 50.5q96 0 152.5 -18.5t101.5 -41.5l-94 -200q-39 23 -81 30.5t-91 7.5q-55 0 -107.5 -35.5t-94.5 -94t-66.5 -136.5t-24.5 -159q0 -104 45 -158.5t119 -54.5q61 0 113.5 19t93.5 44l47 -172q-66 -49 -153 -81t-173 -32 q-98 0 -166.5 29t-111.5 78t-63.5 112.5t-20.5 133.5z" />
|
||||||
|
<glyph unicode="d" horiz-adv-x="1038" d="M76 309q0 143 39 276.5t109.5 237t172 165t224.5 61.5q59 0 98 -7.5t74 -23.5l88 416h252l-228 -1074q-18 -86 -26.5 -159.5t-8.5 -139.5v-31.5t2 -31.5h-172l-28 176h-8q-23 -37 -59 -72.5t-79 -65.5t-91 -47.5t-95 -17.5q-127 0 -195.5 90.5t-68.5 247.5zM336 328 q0 -59 26.5 -102.5t75.5 -43.5q31 0 62.5 15.5t59.5 40t51.5 53t37.5 53.5l99 463q-25 16 -57 23.5t-85 7.5q-61 0 -111.5 -42t-85 -113t-54 -163t-19.5 -192z" />
|
||||||
|
<glyph unicode="e" horiz-adv-x="954" d="M70 340q0 164 51 296t134 224t187.5 142.5t208.5 50.5q84 0 144.5 -21.5t99.5 -59.5t57.5 -87t18.5 -105q0 -84 -43 -147.5t-120 -105.5t-185.5 -63.5t-237.5 -21.5q-16 0 -30.5 1t-30.5 1q-4 -25 -6.5 -44t-2.5 -35q0 -92 48.5 -137.5t136.5 -45.5q90 0 161.5 27 t108.5 53l53 -164q-63 -53 -163.5 -90t-233.5 -37q-166 0 -261 97.5t-95 271.5zM360 604q57 0 122 4t120 19.5t92 45t37 81.5q0 31 -22.5 62.5t-94.5 31.5q-90 0 -156.5 -70t-97.5 -174z" />
|
||||||
|
<glyph unicode="f" horiz-adv-x="602" d="M-264 -369l69 187q35 -14 70 -18.5t88 -4.5q66 0 101.5 52.5t54.5 168.5l129 797h-144l46 211h131l26 137q14 76 37 132.5t60.5 94t92 56t134.5 18.5q33 0 75 -3t82.5 -10t79.5 -17.5t70 -24.5l-59 -186q-47 18 -96.5 24t-96.5 6q-66 0 -95.5 -38.5t-41.5 -120.5l-12 -68 h204l-41 -211h-196l-152 -883q-12 -76 -34.5 -140t-62.5 -112.5t-101.5 -76t-151.5 -27.5q-74 0 -144.5 11.5t-121.5 45.5z" />
|
||||||
|
<glyph unicode="g" horiz-adv-x="1034" d="M-20 -342l94 186q18 -8 42.5 -19t56.5 -22.5t74 -18.5t97 -7q102 0 162.5 63.5t87.5 173.5l39 160h-8q-47 -74 -128 -132t-184 -58q-111 0 -179 83t-68 222q0 158 45 296t125.5 241.5t191.5 163t244 59.5q125 0 218 -21.5t150 -48.5l-206 -979q-27 -121 -72 -204 t-107.5 -134t-143.5 -73.5t-179 -22.5q-72 0 -128.5 10t-99.5 24.5t-74.5 30t-49.5 27.5zM326 338q0 -66 27.5 -104.5t72.5 -38.5q35 0 72 21.5t70.5 54t60 72.5t43.5 75l88 399q-23 12 -57.5 16.5t-69.5 4.5q-66 0 -122 -39t-97 -106.5t-64.5 -159t-23.5 -195.5z" />
|
||||||
|
<glyph unicode="h" horiz-adv-x="1081" d="M37 0l303 1434h252l-129 -590h8q27 33 64.5 69.5t84 67.5t100.5 51.5t118 20.5q98 0 152 -49.5t54 -174.5q0 -76 -24 -192l-135 -637h-252l123 582q20 90 20 149q0 53 -20.5 76.5t-63.5 23.5q-39 0 -82 -24.5t-82 -61t-70.5 -78.5t-47.5 -77l-121 -590h-252z" />
|
||||||
|
<glyph unicode="i" horiz-adv-x="524" d="M55 0l217 1024h252l-217 -1024h-252zM311 1315q0 68 44 104.5t112 36.5q66 0 111.5 -37t45.5 -104q0 -66 -46 -103.5t-111 -37.5q-68 0 -112 37.5t-44 103.5z" />
|
||||||
|
<glyph unicode="j" horiz-adv-x="499" d="M-229 -408l49 218q12 -1 23 -1q37 0 65 10q37 13 62.5 41.5t43 72.5t29.5 100l209 991h254l-227 -1067q-39 -184 -131.5 -281.5t-249.5 -97.5q-63 0 -127 14zM289 1315q0 68 44 104.5t112 36.5q66 0 111.5 -37t45.5 -104q0 -66 -46 -103.5t-111 -37.5q-68 0 -112 37.5 t-44 103.5z" />
|
||||||
|
<glyph unicode="k" horiz-adv-x="952" d="M37 0l303 1434h252l-180 -846l75 26l289 410h281l-305 -412l-123 -77l92 -78l156 -457h-271l-147 424h-82l-88 -424h-252z" />
|
||||||
|
<glyph unicode="l" horiz-adv-x="557" d="M68 135q0 47 12 109l252 1190h252l-240 -1131q-6 -28 -6 -50q0 -23 7 -38q13 -29 44 -29q57 0 109 23l-6 -182q-37 -23 -107 -37.5t-137 -14.5q-88 0 -134 34t-46 126z" />
|
||||||
|
<glyph unicode="m" horiz-adv-x="1570" d="M37 0l217 1024h197l-13 -180h8q31 33 67 69.5t81 67.5t100.5 51.5t120.5 20.5q82 1 124 -59q38 -54 38 -141v-17q31 39 70.5 77.5t86 69.5t98.5 50.5t107 19.5q94 0 144.5 -44t50.5 -165q0 -88 -31 -230l-129 -614h-252l121 575q10 47 16.5 88.5t6.5 71.5 q0 47 -17.5 71.5t-58.5 24.5q-33 0 -66.5 -19t-64.5 -49t-56.5 -64.5t-39.5 -65.5l-132 -633h-251l116 557q12 57 19.5 101t7.5 79q0 94 -72 94q-35 0 -69.5 -18t-64.5 -47t-55.5 -62.5t-41.5 -64.5l-131 -639h-252z" />
|
||||||
|
<glyph unicode="n" horiz-adv-x="1067" d="M37 0l217 1024h190l-10 -180h8q27 33 63 69.5t83 67.5t105.5 51.5t131.5 20.5q92 0 147.5 -50.5t55.5 -166.5q0 -31 -3 -66t-13 -76l-148 -694h-252l136 635q12 57 12 100q0 45 -18.5 70.5t-67.5 25.5q-37 0 -74 -18t-69.5 -49t-61.5 -69t-49 -77l-131 -618h-252z" />
|
||||||
|
<glyph unicode="o" horiz-adv-x="1015" d="M70 332q0 162 46 295t122.5 227t178 146.5t212.5 52.5q98 0 165.5 -31t109.5 -82t60.5 -116.5t18.5 -135.5q0 -160 -45 -292t-121 -226t-176 -146.5t-211 -52.5q-96 0 -163.5 32t-111.5 83t-64.5 115.5t-20.5 130.5zM330 367q0 -184 133 -185q49 0 96 43t84 113t58.5 158 t21.5 176q0 82 -27.5 126t-103.5 44q-49 0 -96 -41t-84 -107.5t-59.5 -152.5t-22.5 -174z" />
|
||||||
|
<glyph unicode="p" horiz-adv-x="1036" d="M-53 -410l303 1434h186l-10 -180h8q29 39 66 76.5t82 66.5t96 47.5t110 18.5q104 0 168 -72t64 -225q0 -174 -46 -318.5t-123 -248t-180.5 -161t-215.5 -57.5q-53 0 -100.5 10.5t-69.5 26.5l-88 -418h-250zM328 217q51 -35 114 -35t121 43t102 115t69.5 167t25.5 200 q0 59 -27.5 97t-75.5 38q-37 0 -71.5 -18.5t-65.5 -46t-55.5 -62.5t-42.5 -68z" />
|
||||||
|
<glyph unicode="q" horiz-adv-x="1026" d="M59 285q0 156 50.5 295t137.5 243.5t202.5 165t244.5 60.5q98 0 191.5 -21.5t144.5 -50.5l-301 -1387h-246l125 570h-8q-20 -35 -50 -68t-68 -60.5t-83 -44t-96 -16.5q-68 0 -114 26t-74.5 70t-42 100t-13.5 118zM319 317q0 -63 24 -99t65 -36q39 0 77.5 23.5t72.5 59.5 t61.5 78t44.5 79l81 395q-29 12 -59.5 16.5t-60.5 4.5q-61 0 -117.5 -44t-97.5 -117t-66 -167t-25 -193z" />
|
||||||
|
<glyph unicode="r" horiz-adv-x="702" d="M37 0l217 1024h186l2 -180h9q45 82 109.5 139t162.5 57q43 0 102 -16l-63 -219q-20 6 -38.5 10t-39.5 4q-84 0 -154.5 -54t-107.5 -126l-133 -639h-252z" />
|
||||||
|
<glyph unicode="s" horiz-adv-x="811" d="M-2 39l80 201q41 -23 105.5 -40.5t135.5 -17.5q72 0 110 28t40 85q0 41 -24.5 70.5t-62.5 56.5t-81 54.5t-81 63t-62.5 85t-24.5 118.5q0 68 26.5 125.5t75 98.5t117 63.5t154.5 22.5q119 0 196.5 -17.5t122.5 -44.5l-69 -192q-41 18 -99.5 30.5t-121.5 12.5 q-66 0 -104 -22.5t-38 -71.5q0 -33 24.5 -58.5t62.5 -52.5t81 -54.5t81 -66.5t62.5 -89t24.5 -120q0 -170 -110.5 -253t-294.5 -83q-104 0 -191.5 19.5t-134.5 48.5z" />
|
||||||
|
<glyph unicode="t" horiz-adv-x="655" d="M82 813l49 211h133l41 193l268 75l-57 -268h240l-47 -211h-238l-100 -463q-12 -55 -13 -90q0 -45 20.5 -61.5t61.5 -16.5q39 0 71 8.5t67 26.5v-188q-23 -12 -54.5 -23.5t-68.5 -18.5t-76 -11.5t-72 -4.5q-104 0 -160.5 48.5t-56.5 146.5q0 20 3 42.5t7 47.5l119 557 h-137z" />
|
||||||
|
<glyph unicode="u" horiz-adv-x="1048" d="M80 197q0 76 20 165l142 662h252l-134 -633q-12 -61 -12 -102t16.5 -63.5t57.5 -22.5q35 0 70.5 17.5t68.5 45t60.5 61t46.5 66.5l131 631h252l-129 -614q-10 -41 -17.5 -96.5t-13.5 -114t-8 -111.5q-1 -26 -1 -48t1 -40h-203l-10 184h-8q-29 -39 -67 -76.5t-84 -68.5 t-100.5 -49.5t-115.5 -18.5q-96 0 -155.5 48.5t-59.5 177.5z" />
|
||||||
|
<glyph unicode="v" horiz-adv-x="917" d="M82 1024h278l68 -537l4 -157h6l62 162l280 532h285l-627 -1034h-155z" />
|
||||||
|
<glyph unicode="w" horiz-adv-x="1388" d="M94 1024h258l33 -514l-12 -182h10l70 184l270 512h188l66 -524l-2 -170h10l62 172l237 522h246l-522 -1034h-187l-71 573v129h-9l-53 -131l-307 -571h-193z" />
|
||||||
|
<glyph unicode="x" horiz-adv-x="1015" d="M-84 0l424 524l-184 500h284l78 -219l27 -143l90 143l178 219h293l-399 -492l204 -532h-278l-98 246l-31 151l-92 -151l-203 -246h-293z" />
|
||||||
|
<glyph unicode="y" horiz-adv-x="925" d="M-35 -389l68 201q12 -6 25.5 -8.5t25.5 -2.5q49 0 100.5 47.5t102.5 151.5l-193 1024h289l59 -575l2 -160h13l55 162l279 573h268l-492 -920q-61 -115 -115.5 -211t-109.5 -165.5t-114.5 -108.5t-127.5 -39q-90 0 -135 31z" />
|
||||||
|
<glyph unicode="z" horiz-adv-x="890" d="M-27 0l45 221l461 490l146 92h-484l49 221h762l-47 -221l-471 -498l-131 -84h479l-47 -221h-762z" />
|
||||||
|
<glyph unicode="{" horiz-adv-x="729" d="M133 379l45 205q74 0 123 42t68 132l90 428q23 111 86 180.5t174 69.5h233l-47 -226h-98q-53 0 -83 -28.5t-44 -94.5l-84 -399q-18 -90 -69.5 -136t-106.5 -56l-4 -21q51 -8 80.5 -61.5t11.5 -139.5l-84 -397q-14 -66 4 -94.5t74 -28.5h96l-49 -225h-234 q-102 0 -141 64.5t-12 183.5l88 420q23 104 -9 143t-108 39z" />
|
||||||
|
<glyph unicode="|" horiz-adv-x="475" d="M193 -266v1700h217v-1700h-217z" />
|
||||||
|
<glyph unicode="}" horiz-adv-x="735" d="M-154 -471l50 225h98q51 0 79.5 28t43.5 95l86 399q18 90 68.5 136.5t107.5 56.5l6 20q-53 8 -84 61.5t-12 139.5l84 397q14 63 -3.5 93t-72.5 30h-94l45 226h231q102 0 142.5 -64.5t15.5 -183.5l-90 -420q-23 -104 10 -143t109 -39l-43 -205q-156 0 -193 -174l-92 -428 q-23 -111 -89.5 -180.5t-176.5 -69.5h-226z" />
|
||||||
|
<glyph unicode="~" horiz-adv-x="1034" d="M92 774q96 78 173 107.5t143 29.5q59 0 110 -17t98.5 -36.5t93.5 -37t93 -17.5q37 0 76 12t82 47l96 -211q-74 -55 -135.5 -77.5t-114.5 -22.5q-57 0 -106.5 18.5t-95.5 41t-93 41t-100 18.5q-49 0 -105.5 -21.5t-124.5 -79.5z" />
|
||||||
|
<glyph unicode="¡" horiz-adv-x="579" d="M-21 -410l144 674l121 334h159l-18 -334l-143 -674h-263zM205 889q0 72 45 115t121 43q74 0 118.5 -43t44.5 -115t-45 -114t-118 -42q-76 0 -121 42t-45 114z" />
|
||||||
|
<glyph unicode="¢" d="M190 324q0 154 39 277.5t105.5 215.5t155 149.5t184.5 75.5l39 187h235l-41 -189q94 -18 148 -47l-92 -200q-23 12 -52.5 20t-62.5 12l-133 -624q45 10 85 24.5t66 30.5l49 -172q-43 -35 -105 -60.5t-128 -37.5l-39 -191h-235l38 187q-68 14 -116.5 46.5t-79.5 79 t-45.5 101.5t-14.5 115zM438 406q0 -86 29 -133.5t74 -65.5l129 608q-45 -18 -87 -55t-74 -90.5t-51.5 -120t-19.5 -143.5z" />
|
||||||
|
<glyph unicode="£" d="M61 0l50 223h4q61 2 117.5 29t99.5 73t68.5 107.5t25.5 132.5v20.5t-2 20.5h-240l47 211h144q-10 41 -18.5 89t-8.5 114q0 115 44 199t118 138t168 79.5t194 25.5q92 0 175 -19.5t131 -51.5l-86 -199q-35 18 -95.5 33.5t-142.5 15.5q-49 0 -95 -17.5t-80 -50t-54.5 -77.5 t-20.5 -103q0 -59 8.5 -99t20.5 -77h287l-48 -211h-194q0 -8 1 -13t1 -13q0 -102 -43 -186.5t-94 -129.5l-97 -61l-2 -13l138 31h446l-49 -221h-918z" />
|
||||||
|
<glyph unicode="¤" d="M80 307l158 160l73 35q-25 43 -39 93t-14 112q0 59 15.5 110t41.5 98l-77 35l-158 160l156 164l159 -158l39 -76q41 31 97.5 46.5t117.5 15.5q59 0 117.5 -15.5t97.5 -44.5l41 74l160 158l158 -164l-158 -160l-76 -32q29 -43 41 -97.5t12 -113.5q0 -61 -13 -115.5 t-40 -91.5l76 -33l158 -160l-158 -164l-160 158l-37 76q-39 -29 -99 -45.5t-120 -16.5q-61 0 -117.5 15.5t-97.5 44.5l-39 -74l-159 -158zM481 709q0 -78 47 -127.5t123 -49.5t122 49.5t46 127.5q0 74 -46 125t-122 51t-123 -51t-47 -125z" />
|
||||||
|
<glyph unicode="¥" d="M133 246l35 164h254l24 116h-251l34 164h174l-210 744h311l137 -539l-6 -152h10l62 156l354 535h291l-527 -744h179l-35 -164h-256l-25 -116h256l-35 -164h-256l-51 -246h-266l51 246h-254z" />
|
||||||
|
<glyph unicode="¦" horiz-adv-x="464" d="M123 -266v702h219v-702h-219zM123 731v703h219v-703h-219z" />
|
||||||
|
<glyph unicode="§" horiz-adv-x="1034" d="M86 61l88 191q41 -23 103.5 -46.5t146.5 -23.5q72 0 115 28t43 77q0 33 -32 55.5t-79 43t-103.5 44t-103.5 56t-78.5 80.5t-31.5 120q0 92 49 156.5t114 111.5l99 33q-45 33 -67.5 79t-24.5 97q0 61 29.5 116.5t82.5 95.5t128 63.5t163 23.5q115 0 190.5 -23.5 t129.5 -52.5l-76 -194q-41 23 -109.5 41t-136.5 18q-72 0 -111 -29.5t-39 -76.5q0 -35 32 -56.5t79 -39t102.5 -36t102.5 -49t78.5 -78.5t31.5 -122q0 -98 -50 -169t-111 -114l-105 -32q47 -33 69.5 -75t20.5 -108q-2 -141 -112.5 -218t-292.5 -77q-113 0 -199 28t-135 62z M414 719q0 -63 46 -98t148 -68q47 25 90 65.5t43 98.5q0 35 -12 57.5t-36.5 41t-63.5 33.5t-90 34q-45 -25 -85 -66t-40 -98z" />
|
||||||
|
<glyph unicode="¨" horiz-adv-x="501" d="M369 1333q0 68 37.5 106t97.5 38q59 0 97 -38t38 -106q0 -66 -38 -102.5t-97 -36.5t-97 36.5t-38 102.5zM795 1335q0 66 37.5 104t97.5 38q59 0 97 -38t38 -104t-38 -103.5t-97 -37.5t-97 37.5t-38 103.5z" />
|
||||||
|
<glyph unicode="©" horiz-adv-x="1712" d="M164 594q0 170 57.5 306t156.5 232.5t234.5 148.5t290.5 52q156 0 290 -52t234.5 -148.5t157.5 -232.5t57 -306t-57 -306t-157.5 -232.5t-234.5 -148.5t-290 -52q-170 0 -307 52t-233.5 148.5t-147.5 232.5t-51 306zM365 594q0 -127 39.5 -229.5t112.5 -173t171 -108.5 t215 -38t216.5 38t172 108.5t112.5 173t40 229.5t-40 229.5t-112.5 173t-172 108.5t-216.5 38t-215 -38t-171 -108.5t-112.5 -173t-39.5 -229.5zM559 594q0 186 93 287.5t247 101.5q76 0 134.5 -17.5t111.5 -47.5l-66 -179q-37 18 -66.5 24.5t-58.5 6.5q-59 0 -94 -39 t-35 -137q0 -176 144 -176q39 0 69.5 7t61.5 24l59 -181q-45 -29 -113.5 -46t-146.5 -17q-166 0 -253 104.5t-87 284.5z" />
|
||||||
|
<glyph unicode="ª" horiz-adv-x="821" d="M123 944q0 70 30.5 116t82 74.5t119 41t141.5 12.5q25 0 49 -1t49 -3q16 51 -2.5 82.5t-85.5 31.5q-78 0 -132.5 -14t-97.5 -31l-28 127q57 29 147 49.5t207 20.5q123 0 173 -51t50 -127q0 -51 -14 -115.5t-31.5 -132.5t-31 -132.5t-13.5 -113.5h-184l-6 94h-6 q-29 -35 -84.5 -68.5t-141.5 -33.5q-47 0 -82.5 14.5t-59.5 39t-36 56t-12 64.5zM352 991q0 -27 15.5 -44t44.5 -17q61 0 90.5 23.5t50.5 47.5l14 72q-16 2 -33.5 3t-33.5 1q-61 0 -104.5 -18.5t-43.5 -67.5z" />
|
||||||
|
<glyph unicode="«" horiz-adv-x="952" d="M61 530l410 471l123 -131l-217 -258l-113 -80l74 -75l123 -252l-172 -127zM442 530l410 471l123 -131l-217 -258l-113 -80l74 -75l123 -252l-172 -127z" />
|
||||||
|
<glyph unicode="¬" horiz-adv-x="1079" d="M135 614v230h905v-463h-245v233h-660z" />
|
||||||
|
<glyph unicode="­" horiz-adv-x="702" d="M115 483l51 213h489l-51 -213h-489z" />
|
||||||
|
<glyph unicode="®" horiz-adv-x="1419" d="M240 924q0 137 46 244.5t126 181t185 112.5t222 39q121 0 226.5 -39t183.5 -112.5t123 -181t45 -244.5q0 -139 -46 -247t-125 -181.5t-184.5 -111.5t-222.5 -38q-121 0 -226.5 38t-184 111.5t-123.5 181.5t-45 247zM432 924q0 -98 32 -173t85 -124t122.5 -74t147.5 -25 q82 0 152.5 23.5t122 73t81 124t29.5 175.5q0 98 -30.5 171.5t-83 123t-123 74t-148.5 24.5q-86 0 -157.5 -26.5t-123 -78t-79 -124t-27.5 -164.5zM608 659v531q33 10 92.5 15t112.5 5q86 0 147.5 -35.5t61.5 -123.5q0 -66 -42 -101t-103 -39l57 -28l133 -224h-125l-129 213 l-98 31v-244h-107zM715 965h69q59 0 92 18t33 64q1 71 -118 71q-23 0 -43.5 -1t-32.5 -7v-145z" />
|
||||||
|
<glyph unicode="¯" horiz-adv-x="641" d="M602 1159l39 189h631l-39 -189h-631z" />
|
||||||
|
<glyph unicode="°" horiz-adv-x="897" d="M248 1122q0 76 26.5 138.5t72.5 107.5t106.5 69.5t130.5 24.5t132 -22.5t109 -66.5t74 -107.5t27 -143.5t-27 -142t-74 -105.5t-109.5 -66t-131.5 -22.5q-70 0 -130.5 22.5t-106.5 66t-72.5 105.5t-26.5 142zM453 1122q0 -66 38.5 -103.5t94.5 -37.5q55 0 96 38t41 103 q0 66 -41 106t-96 40t-94 -40t-39 -106z" />
|
||||||
|
<glyph unicode="±" horiz-adv-x="1034" d="M119 289v229h903v-229h-903zM119 829v230h332v338h239v-338h332v-230h-332v-217h-239v217h-332z" />
|
||||||
|
<glyph unicode="²" horiz-adv-x="823" d="M197 778l30 146q59 37 137 90t148 112.5t118 122t48 117.5q0 35 -19.5 55.5t-72.5 20.5t-104.5 -17.5t-90.5 -40.5l-28 187q76 43 156.5 62.5t150.5 19.5q117 0 180.5 -53.5t63.5 -151.5q0 -123 -78 -225.5t-209 -200.5l-101 -51v-8l117 22h207l-45 -207h-608z" />
|
||||||
|
<glyph unicode="³" horiz-adv-x="823" d="M213 813l82 184q82 -39 170 -39q102 0 143 38t41 85q0 41 -29.5 61.5t-127.5 20.5h-84l16 78l176 166l92 49l-114 -12h-222l43 194h551l-28 -127l-209 -190l-72 -35v-10l57 6q72 -2 123.5 -51t49.5 -131q0 -86 -32 -149.5t-87.5 -104.5t-131 -61.5t-163.5 -20.5 q-74 0 -138.5 13t-105.5 36z" />
|
||||||
|
<glyph unicode="´" horiz-adv-x="487" d="M659 1159l170 316h256l-12 -62l-272 -254h-142z" />
|
||||||
|
<glyph unicode="¶" horiz-adv-x="1101" d="M127 1020q0 82 26.5 156.5t76 132t119 91.5t155.5 34h151v-1700h-217v868q-68 0 -125 34t-99 92t-64.5 133t-22.5 159zM815 -266v1700h219v-1700h-219z" />
|
||||||
|
<glyph unicode="·" horiz-adv-x="518" d="M150 647q0 72 45 114t118 42q76 0 121 -42t45 -114t-45 -115t-121 -43q-74 0 -118.5 43t-44.5 115z" />
|
||||||
|
<glyph unicode="¸" horiz-adv-x="743" d="M483 -418l41 99q104 -10 143.5 12t39.5 51q0 66 -160 61l153 195h162l-67 -88q70 -4 106.5 -43t36.5 -98q0 -53 -23.5 -92t-63.5 -65t-94.5 -38t-115.5 -12q-78 0 -158 18z" />
|
||||||
|
<glyph unicode="¹" horiz-adv-x="823" d="M244 778l43 205h190l74 336l39 94l-74 -65l-129 -76l-69 149l360 232h166l-143 -670h170l-44 -205h-583z" />
|
||||||
|
<glyph unicode="º" horiz-adv-x="817" d="M123 1022q0 111 38 192.5t99.5 136t136 81t148.5 26.5q135 0 205.5 -62.5t70.5 -183.5q0 -117 -34.5 -201.5t-94 -140t-136.5 -82t-159 -26.5q-127 0 -200.5 70.5t-73.5 189.5zM348 1034q-2 -45 20.5 -72.5t65.5 -27.5q68 0 115 70.5t47 181.5q0 100 -88 100 q-35 0 -63.5 -20.5t-51 -54t-35 -80t-10.5 -97.5z" />
|
||||||
|
<glyph unicode="»" horiz-adv-x="952" d="M39 203l221 260l113 84l-72 80l-127 254l176 120l225 -452l-409 -471zM416 203l221 260l113 84l-72 80l-127 254l176 120l225 -452l-409 -471z" />
|
||||||
|
<glyph unicode="¼" horiz-adv-x="1720" d="M248 1223l365 225h168l-187 -875h-225l115 541l41 94l-72 -65l-129 -74zM383 80l883 1384l174 -102l-880 -1391zM833 160l29 137l542 580h179l-113 -535h147l-38 -182h-148l-35 -160h-196l34 160h-401zM1065 326l108 16h102l35 176l37 109h-10l-66 -100l-123 -136z" />
|
||||||
|
<glyph unicode="½" horiz-adv-x="1765" d="M248 1223l365 225h168l-187 -875h-225l115 541l41 94l-72 -65l-129 -74zM385 80l883 1384l174 -102l-880 -1391zM983 0l30 146q59 37 137 90t148 112.5t118 122t48 117.5q0 35 -19.5 55.5t-72.5 20.5t-104.5 -17.5t-90.5 -40.5l-28 187q76 43 156.5 62.5t150.5 19.5 q117 0 180.5 -53.5t63.5 -151.5q0 -123 -78 -225.5t-209 -200.5l-101 -51v-8l117 22h207l-45 -207h-608z" />
|
||||||
|
<glyph unicode="¾" horiz-adv-x="1769" d="M141 608l82 184q82 -39 170 -39q102 0 143 38t41 85q0 41 -29.5 61.5t-127.5 20.5h-84l16 78l176 166l92 49l-114 -12h-222l43 194h551l-28 -127l-209 -190l-72 -35v-10l57 6q72 -2 123.5 -51t49.5 -131q0 -86 -32 -149.5t-87.5 -104.5t-131 -61.5t-163.5 -20.5 q-74 0 -138.5 13t-105.5 36zM434 80l883 1384l174 -102l-880 -1391zM885 160l29 137l542 580h179l-113 -535h147l-38 -182h-148l-35 -160h-196l34 160h-401zM1117 326l108 16h102l35 176l37 109h-10l-66 -100l-123 -136z" />
|
||||||
|
<glyph unicode="¿" horiz-adv-x="880" d="M-47 -166q0 109 32.5 183.5t84 131t113 100.5t117.5 93t101 110.5t62 149.5h217q-12 -111 -50 -189.5t-88.5 -137t-106.5 -102.5t-102 -85t-77 -84t-31 -100q0 -55 32 -86t114 -31q63 0 139 27.5t133 66.5l64 -192q-84 -51 -182.5 -87t-239.5 -36q-172 0 -252 72.5 t-80 195.5zM442 893q0 72 45 115t121 43q74 0 119 -43t45 -115t-45 -114t-119 -42q-76 0 -121 42t-45 114z" />
|
||||||
|
<glyph unicode="À" horiz-adv-x="1191" d="M-78 0l797 1444h196l187 -1444h-268l-41 317h-418l-170 -317h-283zM492 543h290l-32 319l2 225h-11l-82 -227zM555 1720l12 62h287l154 -242h-185z" />
|
||||||
|
<glyph unicode="Á" horiz-adv-x="1191" d="M-78 0l797 1444h196l187 -1444h-268l-41 317h-418l-170 -317h-283zM492 543h290l-32 319l2 225h-11l-82 -227zM647 1540l256 242h321l-12 -62l-352 -180h-213z" />
|
||||||
|
<glyph unicode="Â" horiz-adv-x="1191" d="M-78 0l797 1444h196l187 -1444h-268l-41 317h-418l-170 -317h-283zM481 1511l18 82l297 189h179l206 -191l-16 -80h-180l-92 84l-27 70l-55 -68l-138 -86h-192zM492 543h290l-32 319l2 225h-11l-82 -227z" />
|
||||||
|
<glyph unicode="Ã" horiz-adv-x="1191" d="M-78 0l797 1444h196l187 -1444h-268l-41 317h-418l-170 -317h-283zM492 543h290l-32 319l2 225h-11l-82 -227zM493 1638q78 72 141.5 98.5t118.5 26.5q43 0 83 -11t78 -24.5t74 -24.5t73 -11q31 0 61.5 10t63.5 39l20 -137q-68 -55 -123 -76t-104 -21q-43 0 -81 11.5 t-75 23.5t-72.5 23.5t-74.5 11.5q-37 0 -77 -14.5t-87 -53.5z" />
|
||||||
|
<glyph unicode="Ä" horiz-adv-x="1191" d="M-78 0l797 1444h196l187 -1444h-268l-41 317h-418l-170 -317h-283zM492 543h290l-32 319l2 225h-11l-82 -227zM504 1634q0 59 41 89t107 30t106.5 -29.5t40.5 -89.5q0 -59 -41 -87.5t-106 -28.5q-66 0 -107 28.5t-41 87.5zM922 1634q0 59 41 89t106 30q66 0 107 -29.5 t41 -89.5q0 -59 -41 -87.5t-107 -28.5t-106.5 28.5t-40.5 87.5z" />
|
||||||
|
<glyph unicode="Å" horiz-adv-x="1191" d="M-78 0l783 1419q-66 23 -92.5 64t-26.5 96q0 37 12 70.5t42 59.5t80 40t128 14q143 0 202.5 -49t59.5 -135q0 -66 -42 -114t-148 -60l182 -1405h-268l-41 317h-418l-170 -317h-283zM492 543h290l-32 319l2 225h-11l-82 -227zM758 1579q0 -63 90 -63q51 0 71.5 16t20.5 47 q0 68 -92 68q-90 0 -90 -68z" />
|
||||||
|
<glyph unicode="Æ" horiz-adv-x="1691" d="M-135 0l1120 1434h272h555l-53 -250h-540l-72 -334h493l-53 -250h-491l-74 -350h551l-53 -250h-535h-283l74 348h-350l-262 -348h-299zM592 575h233l107 510h-12l-91 -192z" />
|
||||||
|
<glyph unicode="Ç" horiz-adv-x="1099" d="M119 557q0 242 67.5 413t178 280.5t253 160.5t291.5 51q117 0 200 -17.5t130 -39.5l-104 -238q-41 23 -98.5 34t-145.5 11q-104 0 -194.5 -43t-156 -122.5t-103.5 -194.5t-38 -260q0 -174 87 -272.5t233 -98.5q92 0 152.5 19.5t113.5 48.5l4 -230q-133 -86 -321 -88 l-45 -59q70 -4 106.5 -42t36.5 -97q0 -53 -23.5 -92t-63.5 -65t-94.5 -38t-115.5 -12q-78 0 -158 18l41 99q104 -10 143.5 12t39.5 51q0 35 -41 48t-119 11l141 181q-100 20 -175 72.5t-124 128t-73.5 170t-24.5 200.5z" />
|
||||||
|
<glyph unicode="È" horiz-adv-x="1030" d="M41 0l303 1434h266h541l-53 -250h-541l-72 -334h494l-55 -250h-490l-76 -350h551l-51 -250h-551h-266zM475 1720l12 62h287l154 -242h-185z" />
|
||||||
|
<glyph unicode="É" horiz-adv-x="1030" d="M41 0l303 1434h266h541l-53 -250h-541l-72 -334h494l-55 -250h-490l-76 -350h551l-51 -250h-551h-266zM613 1540l256 242h321l-12 -62l-352 -180h-213z" />
|
||||||
|
<glyph unicode="Ê" horiz-adv-x="1030" d="M41 0l303 1434h266h541l-53 -250h-541l-72 -334h494l-55 -250h-490l-76 -350h551l-51 -250h-551h-266zM422 1511l18 82l297 189h179l206 -191l-16 -80h-180l-92 84l-27 70l-55 -68l-138 -86h-192z" />
|
||||||
|
<glyph unicode="Ë" horiz-adv-x="1030" d="M41 0l303 1434h266h541l-53 -250h-541l-72 -334h494l-55 -250h-490l-76 -350h551l-51 -250h-551h-266zM430 1634q0 59 41 89t107 30t106.5 -29.5t40.5 -89.5q0 -59 -41 -87.5t-106 -28.5q-66 0 -107 28.5t-41 87.5zM848 1634q0 59 41 89t106 30q66 0 107 -29.5t41 -89.5 q0 -59 -41 -87.5t-107 -28.5t-106.5 28.5t-40.5 87.5z" />
|
||||||
|
<glyph unicode="Ì" horiz-adv-x="569" d="M72 0l303 1434h264l-303 -1434h-264zM231 1720l12 62h287l154 -242h-185z" />
|
||||||
|
<glyph unicode="Í" horiz-adv-x="569" d="M72 0l303 1434h264l-303 -1434h-264zM367 1540l256 242h321l-12 -62l-352 -180h-213z" />
|
||||||
|
<glyph unicode="Î" horiz-adv-x="569" d="M72 0l303 1434h264l-303 -1434h-264zM178 1511l18 82l297 189h179l206 -191l-16 -80h-180l-92 84l-27 70l-55 -68l-138 -86h-192z" />
|
||||||
|
<glyph unicode="Ï" horiz-adv-x="569" d="M72 0l303 1434h264l-303 -1434h-264zM188 1634q0 59 41 89t107 30t106.5 -29.5t40.5 -89.5q0 -59 -41 -87.5t-106 -28.5q-66 0 -107 28.5t-41 87.5zM606 1634q0 59 41 89t106 30q66 0 107 -29.5t41 -89.5q0 -59 -41 -87.5t-107 -28.5t-106.5 28.5t-40.5 87.5z" />
|
||||||
|
<glyph unicode="Ð" horiz-adv-x="1310" d="M47 657l35 164h174l129 613q43 6 94 10t97.5 6t74.5 2q20 0 53 1t72 1q127 0 229.5 -31.5t175 -97t112.5 -168t40 -244.5q0 -90 -15 -193.5t-52 -207.5t-101.5 -200.5t-162 -170t-233.5 -119t-316 -45.5q-31 0 -59.5 1.5t-45.5 1.5q-37 2 -89 5t-102.5 6t-74.5 7l139 659 h-174zM397 236q8 -2 25.5 -3.5t38 -2.5t39 -1h28.5q143 -2 243.5 62.5t163 162t90.5 211t28 212.5q0 164 -69 245.5t-230 81.5q-39 0 -84 -2t-70 -6l-80 -375h271l-35 -164h-271z" />
|
||||||
|
<glyph unicode="Ñ" horiz-adv-x="1292" d="M41 0l307 1444h184l353 -766l63 -223h13l14 223l162 756h252l-308 -1444h-184l-350 760l-68 229h-10l-18 -229l-158 -750h-252zM530 1638q78 72 141.5 98.5t118.5 26.5q43 0 83 -11t78 -24.5t74 -24.5t73 -11q31 0 61.5 10t63.5 39l20 -137q-68 -55 -123 -76t-104 -21 q-43 0 -81 11.5t-75 23.5t-72.5 23.5t-74.5 11.5q-37 0 -77 -14.5t-87 -53.5z" />
|
||||||
|
<glyph unicode="Ò" horiz-adv-x="1318" d="M119 537q0 190 52 359t148.5 295t232.5 198.5t304 72.5q111 0 200 -32.5t151.5 -101t97 -173t34.5 -248.5q0 -193 -52 -362.5t-147.5 -297.5t-227.5 -202t-291 -74q-242 0 -371 142.5t-131 423.5zM399 545q0 -147 56.5 -235.5t185.5 -88.5q94 0 171 56.5t132 151.5 t85 218t30 256q0 162 -63.5 235.5t-174.5 73.5q-92 0 -169 -53t-133 -144t-88 -213t-32 -257zM594 1720l12 62h287l154 -242h-185z" />
|
||||||
|
<glyph unicode="Ó" horiz-adv-x="1318" d="M119 537q0 190 52 359t148.5 295t232.5 198.5t304 72.5q111 0 200 -32.5t151.5 -101t97 -173t34.5 -248.5q0 -193 -52 -362.5t-147.5 -297.5t-227.5 -202t-291 -74q-242 0 -371 142.5t-131 423.5zM399 545q0 -147 56.5 -235.5t185.5 -88.5q94 0 171 56.5t132 151.5 t85 218t30 256q0 162 -63.5 235.5t-174.5 73.5q-92 0 -169 -53t-133 -144t-88 -213t-32 -257zM750 1540l256 242h321l-12 -62l-352 -180h-213z" />
|
||||||
|
<glyph unicode="Ô" horiz-adv-x="1318" d="M119 537q0 190 52 359t148.5 295t232.5 198.5t304 72.5q111 0 200 -32.5t151.5 -101t97 -173t34.5 -248.5q0 -193 -52 -362.5t-147.5 -297.5t-227.5 -202t-291 -74q-242 0 -371 142.5t-131 423.5zM399 545q0 -147 56.5 -235.5t185.5 -88.5q94 0 171 56.5t132 151.5 t85 218t30 256q0 162 -63.5 235.5t-174.5 73.5q-92 0 -169 -53t-133 -144t-88 -213t-32 -257zM553 1511l18 82l297 189h179l206 -191l-16 -80h-180l-92 84l-27 70l-55 -68l-138 -86h-192z" />
|
||||||
|
<glyph unicode="Õ" horiz-adv-x="1318" d="M119 537q0 190 52 359t148.5 295t232.5 198.5t304 72.5q111 0 200 -32.5t151.5 -101t97 -173t34.5 -248.5q0 -193 -52 -362.5t-147.5 -297.5t-227.5 -202t-291 -74q-242 0 -371 142.5t-131 423.5zM399 545q0 -147 56.5 -235.5t185.5 -88.5q94 0 171 56.5t132 151.5 t85 218t30 256q0 162 -63.5 235.5t-174.5 73.5q-92 0 -169 -53t-133 -144t-88 -213t-32 -257zM548 1638q78 72 141.5 98.5t118.5 26.5q43 0 83 -11t78 -24.5t74 -24.5t73 -11q31 0 61.5 10t63.5 39l20 -137q-68 -55 -123 -76t-104 -21q-43 0 -81 11.5t-75 23.5t-72.5 23.5 t-74.5 11.5q-37 0 -77 -14.5t-87 -53.5z" />
|
||||||
|
<glyph unicode="Ö" horiz-adv-x="1318" d="M119 537q0 190 52 359t148.5 295t232.5 198.5t304 72.5q111 0 200 -32.5t151.5 -101t97 -173t34.5 -248.5q0 -193 -52 -362.5t-147.5 -297.5t-227.5 -202t-291 -74q-242 0 -371 142.5t-131 423.5zM399 545q0 -147 56.5 -235.5t185.5 -88.5q94 0 171 56.5t132 151.5 t85 218t30 256q0 162 -63.5 235.5t-174.5 73.5q-92 0 -169 -53t-133 -144t-88 -213t-32 -257zM553 1634q0 59 41 89t107 30t106.5 -29.5t40.5 -89.5q0 -59 -41 -87.5t-106 -28.5q-66 0 -107 28.5t-41 87.5zM971 1634q0 59 41 89t106 30q66 0 107 -29.5t41 -89.5 q0 -59 -41 -87.5t-107 -28.5t-106.5 28.5t-40.5 87.5z" />
|
||||||
|
<glyph unicode="×" horiz-adv-x="1034" d="M135 426l268 268l-264 260l160 166l268 -266l267 266l161 -166l-266 -260l266 -264l-161 -168l-267 268l-270 -270z" />
|
||||||
|
<glyph unicode="Ø" horiz-adv-x="1318" d="M117 121l69 86q-33 66 -50 148t-17 182q0 190 52 359t148.5 295t232.5 198.5t304 72.5q176 0 291 -82l55 66l148 -127l-76 -92q31 -61 48 -141t17 -179q0 -193 -52 -362.5t-147.5 -297.5t-227.5 -202t-291 -74q-184 0 -306 84l-55 -65zM399 506q0 -19 4 -37l568 694 q-59 49 -150 49q-92 0 -169 -53t-133 -144t-88 -213t-32 -257v-39zM489 270q57 -49 152 -49q94 0 171 56.5t132 151.5t85 218t30 256v29.5t-2 28.5z" />
|
||||||
|
<glyph unicode="Ù" horiz-adv-x="1232" d="M129 356q0 41 5 84t16 90l192 904h264l-188 -902q-16 -78 -17 -126q0 -98 51.5 -139.5t149.5 -41.5q123 0 190.5 72t102.5 231l192 906h250l-194 -926q-31 -147 -80 -248.5t-119 -165t-164 -91.5t-217 -28q-119 0 -200.5 28t-134 79t-76 120.5t-23.5 153.5zM551 1720 l12 62h287l154 -242h-185z" />
|
||||||
|
<glyph unicode="Ú" horiz-adv-x="1232" d="M129 356q0 41 5 84t16 90l192 904h264l-188 -902q-16 -78 -17 -126q0 -98 51.5 -139.5t149.5 -41.5q123 0 190.5 72t102.5 231l192 906h250l-194 -926q-31 -147 -80 -248.5t-119 -165t-164 -91.5t-217 -28q-119 0 -200.5 28t-134 79t-76 120.5t-23.5 153.5zM742 1540 l256 242h321l-12 -62l-352 -180h-213z" />
|
||||||
|
<glyph unicode="Û" horiz-adv-x="1232" d="M129 356q0 41 5 84t16 90l192 904h264l-188 -902q-16 -78 -17 -126q0 -98 51.5 -139.5t149.5 -41.5q123 0 190.5 72t102.5 231l192 906h250l-194 -926q-31 -147 -80 -248.5t-119 -165t-164 -91.5t-217 -28q-119 0 -200.5 28t-134 79t-76 120.5t-23.5 153.5zM524 1511 l18 82l297 189h179l206 -191l-16 -80h-180l-92 84l-27 70l-55 -68l-138 -86h-192z" />
|
||||||
|
<glyph unicode="Ü" horiz-adv-x="1232" d="M129 356q0 41 5 84t16 90l192 904h264l-188 -902q-16 -78 -17 -126q0 -98 51.5 -139.5t149.5 -41.5q123 0 190.5 72t102.5 231l192 906h250l-194 -926q-31 -147 -80 -248.5t-119 -165t-164 -91.5t-217 -28q-119 0 -200.5 28t-134 79t-76 120.5t-23.5 153.5zM524 1634 q0 59 41 89t107 30t106.5 -29.5t40.5 -89.5q0 -59 -41 -87.5t-106 -28.5q-66 0 -107 28.5t-41 87.5zM942 1634q0 59 41 89t106 30q66 0 107 -29.5t41 -89.5q0 -59 -41 -87.5t-107 -28.5t-106.5 28.5t-40.5 87.5z" />
|
||||||
|
<glyph unicode="Ý" horiz-adv-x="1165" d="M217 1434h295l133 -539l-4 -152h8l64 156l358 535h305l-637 -899l-112 -535h-265l111 532zM668 1540l256 242h321l-12 -62l-352 -180h-213z" />
|
||||||
|
<glyph unicode="Þ" horiz-adv-x="1126" d="M41 0l305 1434h264l-30 -146q27 2 53 2h53q104 0 193.5 -23.5t156 -72.5t103.5 -126t37 -183q0 -160 -55.5 -267.5t-146.5 -174t-208 -94t-238 -27.5h-31.5t-45 1t-45 2t-31.5 3l-68 -328h-266zM428 573q8 -2 22.5 -4t32 -3t32.5 -2t24 -1q70 0 134 14.5t113.5 48t79 89 t29.5 135.5q0 61 -19.5 99t-52 59.5t-77 30t-93.5 8.5q-37 0 -70.5 -3.5t-56.5 -7.5q-25 -117 -49 -231.5t-49 -231.5z" />
|
||||||
|
<glyph unicode="ß" horiz-adv-x="1245" d="M-264 -369l69 187q35 -14 70 -18.5t88 -4.5q66 0 101.5 51.5t52.5 153.5l145 815h-168l41 209h166l12 57q25 117 72 188.5t112.5 111.5t147.5 54.5t178 14.5q104 0 176 -22.5t117 -60.5t65.5 -88t20.5 -108q0 -72 -23.5 -123t-58.5 -87.5t-77 -63.5t-76.5 -51.5t-58 -51 t-23.5 -61.5t23.5 -57.5t58 -41t76.5 -39t77 -52t58.5 -79.5t23.5 -122q0 -80 -36 -148.5t-98 -117.5t-147 -77t-184 -28q-84 0 -166 23.5t-133 58.5l115 199q43 -27 91 -47.5t118 -20.5q31 0 61.5 10.5t55 29t40 46t15.5 62.5q0 39 -23.5 64.5t-59.5 46t-78 42t-78 51 t-59.5 72.5t-23.5 109q0 59 23.5 103t59.5 77t77 58.5t77 50t59.5 52t23.5 64.5q0 47 -37 76t-107 29q-98 0 -157.5 -53.5t-81.5 -174.5l-182 -999q-18 -104 -43 -184t-67 -133.5t-103.5 -81t-151.5 -27.5q-74 0 -144.5 11.5t-121.5 45.5z" />
|
||||||
|
<glyph unicode="à" horiz-adv-x="1030" d="M68 295q0 150 37.5 287t117.5 241.5t202 167t290 62.5q72 0 156.5 -13.5t164.5 -35.5l-127 -594q-16 -78 -23 -158t-7 -152q0 -29 1 -54.5t3 -47.5h-187l-28 176h-9q-23 -37 -58.5 -72.5t-78.5 -65.5t-91 -47.5t-99 -17.5q-135 0 -199.5 88t-64.5 236zM328 344 q0 -66 21.5 -114t78.5 -48q37 0 69.5 15.5t60.5 40t49.5 53t37.5 53.5l103 477q-23 10 -52.5 15.5t-58.5 5.5q-74 0 -131 -44t-97 -115t-60.5 -160t-20.5 -179zM467 1413l14 62h264l50 -316h-142z" />
|
||||||
|
<glyph unicode="á" horiz-adv-x="1030" d="M68 295q0 150 37.5 287t117.5 241.5t202 167t290 62.5q72 0 156.5 -13.5t164.5 -35.5l-127 -594q-16 -78 -23 -158t-7 -152q0 -29 1 -54.5t3 -47.5h-187l-28 176h-9q-23 -37 -58.5 -72.5t-78.5 -65.5t-91 -47.5t-99 -17.5q-135 0 -199.5 88t-64.5 236zM328 344 q0 -66 21.5 -114t78.5 -48q37 0 69.5 15.5t60.5 40t49.5 53t37.5 53.5l103 477q-23 10 -52.5 15.5t-58.5 5.5q-74 0 -131 -44t-97 -115t-60.5 -160t-20.5 -179zM612 1159l170 316h256l-12 -62l-272 -254h-142z" />
|
||||||
|
<glyph unicode="â" horiz-adv-x="1030" d="M68 295q0 150 37.5 287t117.5 241.5t202 167t290 62.5q72 0 156.5 -13.5t164.5 -35.5l-127 -594q-16 -78 -23 -158t-7 -152q0 -29 1 -54.5t3 -47.5h-187l-28 176h-9q-23 -37 -58.5 -72.5t-78.5 -65.5t-91 -47.5t-99 -17.5q-135 0 -199.5 88t-64.5 236zM328 344 q0 -66 21.5 -114t78.5 -48q37 0 69.5 15.5t60.5 40t49.5 53t37.5 53.5l103 477q-23 10 -52.5 15.5t-58.5 5.5q-74 0 -131 -44t-97 -115t-60.5 -160t-20.5 -179zM389 1126l320 373h168l137 -373h-197l-49 136l-8 100l-55 -100l-117 -136h-199z" />
|
||||||
|
<glyph unicode="ã" horiz-adv-x="1030" d="M68 295q0 150 37.5 287t117.5 241.5t202 167t290 62.5q72 0 156.5 -13.5t164.5 -35.5l-127 -594q-16 -78 -23 -158t-7 -152q0 -29 1 -54.5t3 -47.5h-187l-28 176h-9q-23 -37 -58.5 -72.5t-78.5 -65.5t-91 -47.5t-99 -17.5q-135 0 -199.5 88t-64.5 236zM328 344 q0 -66 21.5 -114t78.5 -48q37 0 69.5 15.5t60.5 40t49.5 53t37.5 53.5l103 477q-23 10 -52.5 15.5t-58.5 5.5q-74 0 -131 -44t-97 -115t-60.5 -160t-20.5 -179zM404 1348q72 76 126 104.5t99 28.5q37 0 68.5 -14.5t63.5 -31t63.5 -30.5t68.5 -14q29 0 62.5 12t74.5 43 l9 -143q-66 -66 -117 -91.5t-94 -25.5q-37 0 -70 13t-65.5 29.5t-65.5 30t-70 13.5q-31 0 -67.5 -12.5t-77.5 -45.5z" />
|
||||||
|
<glyph unicode="ä" horiz-adv-x="1030" d="M68 295q0 150 37.5 287t117.5 241.5t202 167t290 62.5q72 0 156.5 -13.5t164.5 -35.5l-127 -594q-16 -78 -23 -158t-7 -152q0 -29 1 -54.5t3 -47.5h-187l-28 176h-9q-23 -37 -58.5 -72.5t-78.5 -65.5t-91 -47.5t-99 -17.5q-135 0 -199.5 88t-64.5 236zM328 344 q0 -66 21.5 -114t78.5 -48q37 0 69.5 15.5t60.5 40t49.5 53t37.5 53.5l103 477q-23 10 -52.5 15.5t-58.5 5.5q-74 0 -131 -44t-97 -115t-60.5 -160t-20.5 -179zM351 1333q0 68 37.5 106t97.5 38q59 0 97 -38t38 -106q0 -66 -38 -102.5t-97 -36.5t-97 36.5t-38 102.5z M777 1335q0 66 37.5 104t97.5 38q59 0 97 -38t38 -104t-38 -103.5t-97 -37.5t-97 37.5t-38 103.5z" />
|
||||||
|
<glyph unicode="å" horiz-adv-x="1030" d="M68 295q0 150 37.5 287t117.5 241.5t202 167t290 62.5q72 0 156.5 -13.5t164.5 -35.5l-127 -594q-16 -78 -23 -158t-7 -152q0 -29 1 -54.5t3 -47.5h-187l-28 176h-9q-23 -37 -58.5 -72.5t-78.5 -65.5t-91 -47.5t-99 -17.5q-135 0 -199.5 88t-64.5 236zM328 344 q0 -66 21.5 -114t78.5 -48q37 0 69.5 15.5t60.5 40t49.5 53t37.5 53.5l103 477q-23 10 -52.5 15.5t-58.5 5.5q-74 0 -131 -44t-97 -115t-60.5 -160t-20.5 -179zM522 1325q0 86 58.5 141.5t169.5 55.5q104 0 165.5 -50.5t61.5 -146.5q0 -80 -60.5 -136t-166.5 -56 q-109 0 -168.5 52t-59.5 140zM670 1325q0 -33 23.5 -50.5t56.5 -17.5q35 0 57.5 16.5t22.5 51.5t-24 52.5t-56 17.5q-33 0 -56.5 -16.5t-23.5 -53.5z" />
|
||||||
|
<glyph unicode="æ" horiz-adv-x="1523" d="M35 242q0 100 45 171.5t123 116.5t180 66.5t219 21.5h33.5t34.5 -2q23 78 22 121q0 49 -30.5 73t-104.5 24q-68 0 -143.5 -16.5t-141.5 -43.5l-36 191q84 41 193.5 60t211.5 19q94 0 159.5 -29.5t92.5 -92.5q59 63 148 97t182 34q86 0 146.5 -19.5t98 -54.5t55 -81 t17.5 -101q0 -115 -54 -184.5t-146.5 -109.5t-213 -54.5t-252.5 -14.5q-2 -16 -3 -31.5t-1 -29.5q0 -92 47.5 -141.5t155.5 -49.5q78 0 146.5 21.5t109.5 46.5l47 -176q-70 -49 -175 -76t-210 -27q-135 0 -218 49.5t-118 137.5h-10q-66 -74 -151.5 -124t-202.5 -50 q-68 0 -116 21.5t-78.5 57t-46 83t-15.5 96.5zM295 303q0 -55 28.5 -79.5t75.5 -24.5q37 0 71 15t62.5 36.5t51 45t37.5 42.5l18 119q-16 2 -33.5 2h-34.5q-117 0 -196.5 -38t-79.5 -118zM915 598q66 0 133.5 3t123 18.5t90 47t34.5 87.5q0 35 -24.5 64.5t-91.5 29.5 q-109 0 -171.5 -73t-93.5 -177z" />
|
||||||
|
<glyph unicode="ç" horiz-adv-x="843" d="M70 324q0 172 49 307t130 228t184.5 143.5t211.5 50.5q96 0 152.5 -18.5t101.5 -41.5l-94 -200q-39 23 -81 30.5t-91 7.5q-55 0 -107.5 -35.5t-94.5 -94t-66.5 -136.5t-24.5 -159q0 -104 45 -158.5t119 -54.5q61 0 113.5 19t93.5 44l47 -172q-53 -39 -119 -67.5 t-135 -39.5l-49 -65q70 -4 106.5 -42t36.5 -97q0 -53 -23.5 -92t-63.5 -65t-94.5 -38t-115.5 -12q-78 0 -158 18l41 99q104 -10 143.5 12t39.5 51q0 35 -41 48t-119 11l135 175q-74 12 -125 43.5t-84 77.5t-48 103.5t-15 119.5z" />
|
||||||
|
<glyph unicode="è" horiz-adv-x="954" d="M70 340q0 164 51 296t134 224t187.5 142.5t208.5 50.5q84 0 144.5 -21.5t99.5 -59.5t57.5 -87t18.5 -105q0 -84 -43 -147.5t-120 -105.5t-185.5 -63.5t-237.5 -21.5q-16 0 -30.5 1t-30.5 1q-4 -25 -6.5 -44t-2.5 -35q0 -92 48.5 -137.5t136.5 -45.5q90 0 161.5 27 t108.5 53l53 -164q-63 -53 -163.5 -90t-233.5 -37q-166 0 -261 97.5t-95 271.5zM360 604q57 0 122 4t120 19.5t92 45t37 81.5q0 31 -22.5 62.5t-94.5 31.5q-90 0 -156.5 -70t-97.5 -174zM426 1413l14 62h264l50 -316h-142z" />
|
||||||
|
<glyph unicode="é" horiz-adv-x="954" d="M70 340q0 164 51 296t134 224t187.5 142.5t208.5 50.5q84 0 144.5 -21.5t99.5 -59.5t57.5 -87t18.5 -105q0 -84 -43 -147.5t-120 -105.5t-185.5 -63.5t-237.5 -21.5q-16 0 -30.5 1t-30.5 1q-4 -25 -6.5 -44t-2.5 -35q0 -92 48.5 -137.5t136.5 -45.5q90 0 161.5 27 t108.5 53l53 -164q-63 -53 -163.5 -90t-233.5 -37q-166 0 -261 97.5t-95 271.5zM360 604q57 0 122 4t120 19.5t92 45t37 81.5q0 31 -22.5 62.5t-94.5 31.5q-90 0 -156.5 -70t-97.5 -174zM579 1159l170 316h256l-12 -62l-272 -254h-142z" />
|
||||||
|
<glyph unicode="ê" horiz-adv-x="954" d="M70 340q0 164 51 296t134 224t187.5 142.5t208.5 50.5q84 0 144.5 -21.5t99.5 -59.5t57.5 -87t18.5 -105q0 -84 -43 -147.5t-120 -105.5t-185.5 -63.5t-237.5 -21.5q-16 0 -30.5 1t-30.5 1q-4 -25 -6.5 -44t-2.5 -35q0 -92 48.5 -137.5t136.5 -45.5q90 0 161.5 27 t108.5 53l53 -164q-63 -53 -163.5 -90t-233.5 -37q-166 0 -261 97.5t-95 271.5zM342 1126l320 373h168l137 -373h-197l-49 136l-8 100l-55 -100l-117 -136h-199zM360 604q57 0 122 4t120 19.5t92 45t37 81.5q0 31 -22.5 62.5t-94.5 31.5q-90 0 -156.5 -70t-97.5 -174z" />
|
||||||
|
<glyph unicode="ë" horiz-adv-x="954" d="M70 340q0 164 51 296t134 224t187.5 142.5t208.5 50.5q84 0 144.5 -21.5t99.5 -59.5t57.5 -87t18.5 -105q0 -84 -43 -147.5t-120 -105.5t-185.5 -63.5t-237.5 -21.5q-16 0 -30.5 1t-30.5 1q-4 -25 -6.5 -44t-2.5 -35q0 -92 48.5 -137.5t136.5 -45.5q90 0 161.5 27 t108.5 53l53 -164q-63 -53 -163.5 -90t-233.5 -37q-166 0 -261 97.5t-95 271.5zM336 1333q0 68 37.5 106t97.5 38q59 0 97 -38t38 -106q0 -66 -38 -102.5t-97 -36.5t-97 36.5t-38 102.5zM360 604q57 0 122 4t120 19.5t92 45t37 81.5q0 31 -22.5 62.5t-94.5 31.5 q-90 0 -156.5 -70t-97.5 -174zM762 1335q0 66 37.5 104t97.5 38q59 0 97 -38t38 -104t-38 -103.5t-97 -37.5t-97 37.5t-38 103.5z" />
|
||||||
|
<glyph unicode="ì" horiz-adv-x="524" d="M55 0l217 1024h252l-217 -1024h-252zM215 1413l14 62h264l50 -316h-142z" />
|
||||||
|
<glyph unicode="í" horiz-adv-x="524" d="M55 0l217 1024h252l-217 -1024h-252zM317 1159l170 316h256l-12 -62l-272 -254h-142z" />
|
||||||
|
<glyph unicode="î" horiz-adv-x="524" d="M55 0l217 1024h252l-217 -1024h-252zM98 1126l320 373h168l137 -373h-197l-49 136l-8 100l-55 -100l-117 -136h-199z" />
|
||||||
|
<glyph unicode="ï" horiz-adv-x="524" d="M55 0l217 1024h252l-217 -1024h-252zM113 1333q0 68 37.5 106t97.5 38q59 0 97 -38t38 -106q0 -66 -38 -102.5t-97 -36.5t-97 36.5t-38 102.5zM539 1335q0 66 37.5 104t97.5 38q59 0 97 -38t38 -104t-38 -103.5t-97 -37.5t-97 37.5t-38 103.5z" />
|
||||||
|
<glyph unicode="ð" horiz-adv-x="1040" d="M76 352q0 143 42 266t112.5 213.5t163.5 140.5t198 50q141 0 207 -78q4 66 -8.5 120t-34.5 101l-154 -63l-65 110l143 60q-37 37 -81 63.5t-91 42.5l199 84q92 -35 167 -110l150 61l57 -110l-131 -56q35 -63 55.5 -141t20.5 -170q0 -252 -48 -434.5t-130 -300 t-189.5 -174t-226.5 -56.5q-164 0 -260 97.5t-96 283.5zM336 362q0 -86 33.5 -133t93.5 -47q80 0 136 57.5t91 140.5t51.5 177t14.5 166q-16 41 -54 65.5t-92 24.5q-61 0 -111 -39t-86 -102.5t-56.5 -144.5t-20.5 -165z" />
|
||||||
|
<glyph unicode="ñ" horiz-adv-x="1067" d="M29 0l217 1024h190l-10 -180h8q27 33 63 69.5t83 67.5t105.5 51.5t131.5 20.5q92 0 147.5 -50.5t55.5 -166.5q0 -31 -3 -66t-13 -76l-148 -694h-252l136 635q12 57 12 100q0 45 -18.5 70.5t-67.5 25.5q-37 0 -74 -18t-69.5 -49t-61.5 -69t-49 -77l-131 -618h-252z M416 1348q72 76 126 104.5t99 28.5q37 0 68.5 -14.5t63.5 -31t63.5 -30.5t68.5 -14q29 0 62.5 12t74.5 43l9 -143q-66 -66 -117 -91.5t-94 -25.5q-37 0 -70 13t-65.5 29.5t-65.5 30t-70 13.5q-31 0 -67.5 -12.5t-77.5 -45.5z" />
|
||||||
|
<glyph unicode="ò" horiz-adv-x="1015" d="M70 332q0 162 46 295t122.5 227t178 146.5t212.5 52.5q98 0 165.5 -31t109.5 -82t60.5 -116.5t18.5 -135.5q0 -160 -45 -292t-121 -226t-176 -146.5t-211 -52.5q-96 0 -163.5 32t-111.5 83t-64.5 115.5t-20.5 130.5zM330 367q0 -184 133 -185q49 0 96 43t84 113t58.5 158 t21.5 176q0 82 -27.5 126t-103.5 44q-49 0 -96 -41t-84 -107.5t-59.5 -152.5t-22.5 -174zM442 1413l14 62h264l50 -316h-142z" />
|
||||||
|
<glyph unicode="ó" horiz-adv-x="1015" d="M70 332q0 162 46 295t122.5 227t178 146.5t212.5 52.5q98 0 165.5 -31t109.5 -82t60.5 -116.5t18.5 -135.5q0 -160 -45 -292t-121 -226t-176 -146.5t-211 -52.5q-96 0 -163.5 32t-111.5 83t-64.5 115.5t-20.5 130.5zM330 367q0 -184 133 -185q49 0 96 43t84 113t58.5 158 t21.5 176q0 82 -27.5 126t-103.5 44q-49 0 -96 -41t-84 -107.5t-59.5 -152.5t-22.5 -174zM575 1159l170 316h256l-12 -62l-272 -254h-142z" />
|
||||||
|
<glyph unicode="ô" horiz-adv-x="1015" d="M70 332q0 162 46 295t122.5 227t178 146.5t212.5 52.5q98 0 165.5 -31t109.5 -82t60.5 -116.5t18.5 -135.5q0 -160 -45 -292t-121 -226t-176 -146.5t-211 -52.5q-96 0 -163.5 32t-111.5 83t-64.5 115.5t-20.5 130.5zM330 367q0 -184 133 -185q49 0 96 43t84 113t58.5 158 t21.5 176q0 82 -27.5 126t-103.5 44q-49 0 -96 -41t-84 -107.5t-59.5 -152.5t-22.5 -174zM335 1126l320 373h168l137 -373h-197l-49 136l-8 100l-55 -100l-117 -136h-199z" />
|
||||||
|
<glyph unicode="õ" horiz-adv-x="1015" d="M70 332q0 162 46 295t122.5 227t178 146.5t212.5 52.5q98 0 165.5 -31t109.5 -82t60.5 -116.5t18.5 -135.5q0 -160 -45 -292t-121 -226t-176 -146.5t-211 -52.5q-96 0 -163.5 32t-111.5 83t-64.5 115.5t-20.5 130.5zM330 367q0 -184 133 -185q49 0 96 43t84 113t58.5 158 t21.5 176q0 82 -27.5 126t-103.5 44q-49 0 -96 -41t-84 -107.5t-59.5 -152.5t-22.5 -174zM367 1348q72 76 126 104.5t99 28.5q37 0 68.5 -14.5t63.5 -31t63.5 -30.5t68.5 -14q29 0 62.5 12t74.5 43l9 -143q-66 -66 -117 -91.5t-94 -25.5q-37 0 -70 13t-65.5 29.5t-65.5 30 t-70 13.5q-31 0 -67.5 -12.5t-77.5 -45.5z" />
|
||||||
|
<glyph unicode="ö" horiz-adv-x="1015" d="M70 332q0 162 46 295t122.5 227t178 146.5t212.5 52.5q98 0 165.5 -31t109.5 -82t60.5 -116.5t18.5 -135.5q0 -160 -45 -292t-121 -226t-176 -146.5t-211 -52.5q-96 0 -163.5 32t-111.5 83t-64.5 115.5t-20.5 130.5zM330 367q0 -184 133 -185q49 0 96 43t84 113t58.5 158 t21.5 176q0 82 -27.5 126t-103.5 44q-49 0 -96 -41t-84 -107.5t-59.5 -152.5t-22.5 -174zM338 1333q0 68 37.5 106t97.5 38q59 0 97 -38t38 -106q0 -66 -38 -102.5t-97 -36.5t-97 36.5t-38 102.5zM764 1335q0 66 37.5 104t97.5 38q59 0 97 -38t38 -104t-38 -103.5t-97 -37.5 t-97 37.5t-38 103.5z" />
|
||||||
|
<glyph unicode="÷" horiz-adv-x="1034" d="M119 578v229h905v-229h-905zM406 297q0 72 45 114t118 42q76 0 121 -42t45 -114t-45 -115t-121 -43q-74 0 -118.5 43t-44.5 115zM406 1090q0 72 45 113.5t118 41.5q76 0 121 -42t45 -113q0 -72 -45 -115t-121 -43q-74 0 -118.5 43t-44.5 115z" />
|
||||||
|
<glyph unicode="ø" horiz-adv-x="1015" d="M0 74l96 110q-26 68 -26 148q0 162 46 295t122.5 227t178 146.5t212.5 52.5q66 0 117 -14.5t90 -39.5l69 78l131 -121l-86 -96q33 -78 33 -172q0 -160 -45 -292t-121 -226t-176 -146.5t-211 -52.5q-70 0 -124 17.5t-95 46.5l-76 -84zM330 397l360 406q-33 39 -98 39 q-47 0 -92 -38t-81 -99.5t-60.5 -141.5t-28.5 -166zM360 233q33 -51 103 -51q47 0 92 40t81 104.5t59.5 146.5t27.5 166z" />
|
||||||
|
<glyph unicode="ù" horiz-adv-x="1048" d="M80 197q0 76 20 165l142 662h252l-134 -633q-12 -61 -12 -102t16.5 -63.5t57.5 -22.5q35 0 70.5 17.5t68.5 45t60.5 61t46.5 66.5l131 631h252l-129 -614q-10 -41 -17.5 -96.5t-13.5 -114t-8 -111.5t0 -88h-203l-10 184h-8q-29 -39 -67 -76.5t-84 -68.5t-100.5 -49.5 t-115.5 -18.5q-96 0 -155.5 48.5t-59.5 177.5zM436 1413l14 62h264l50 -316h-142z" />
|
||||||
|
<glyph unicode="ú" horiz-adv-x="1048" d="M80 197q0 76 20 165l142 662h252l-134 -633q-12 -61 -12 -102t16.5 -63.5t57.5 -22.5q35 0 70.5 17.5t68.5 45t60.5 61t46.5 66.5l131 631h252l-129 -614q-10 -41 -17.5 -96.5t-13.5 -114t-8 -111.5t0 -88h-203l-10 184h-8q-29 -39 -67 -76.5t-84 -68.5t-100.5 -49.5 t-115.5 -18.5q-96 0 -155.5 48.5t-59.5 177.5zM550 1159l170 316h256l-12 -62l-272 -254h-142z" />
|
||||||
|
<glyph unicode="û" horiz-adv-x="1048" d="M80 197q0 76 20 165l142 662h252l-134 -633q-12 -61 -12 -102t16.5 -63.5t57.5 -22.5q35 0 70.5 17.5t68.5 45t60.5 61t46.5 66.5l131 631h252l-129 -614q-10 -41 -17.5 -96.5t-13.5 -114t-8 -111.5t0 -88h-203l-10 184h-8q-29 -39 -67 -76.5t-84 -68.5t-100.5 -49.5 t-115.5 -18.5q-96 0 -155.5 48.5t-59.5 177.5zM348 1126l320 373h168l137 -373h-197l-49 136l-8 100l-55 -100l-117 -136h-199z" />
|
||||||
|
<glyph unicode="ü" horiz-adv-x="1048" d="M80 197q0 76 20 165l142 662h252l-134 -633q-12 -61 -12 -102t16.5 -63.5t57.5 -22.5q35 0 70.5 17.5t68.5 45t60.5 61t46.5 66.5l131 631h252l-129 -614q-10 -41 -17.5 -96.5t-13.5 -114t-8 -111.5t0 -88h-203l-10 184h-8q-29 -39 -67 -76.5t-84 -68.5t-100.5 -49.5 t-115.5 -18.5q-96 0 -155.5 48.5t-59.5 177.5zM355 1333q0 68 37.5 106t97.5 38q59 0 97 -38t38 -106q0 -66 -38 -102.5t-97 -36.5t-97 36.5t-38 102.5zM781 1335q0 66 37.5 104t97.5 38q59 0 97 -38t38 -104t-38 -103.5t-97 -37.5t-97 37.5t-38 103.5z" />
|
||||||
|
<glyph unicode="ý" horiz-adv-x="925" d="M-35 -389l68 201q12 -6 25.5 -8.5t25.5 -2.5q49 0 100.5 47.5t102.5 151.5l-193 1024h289l59 -575l2 -160h13l55 162l279 573h268l-492 -920q-61 -115 -115.5 -211t-109.5 -165.5t-114.5 -108.5t-127.5 -39q-90 0 -135 31zM507 1159l170 316h256l-12 -62l-272 -254h-142z " />
|
||||||
|
<glyph unicode="þ" horiz-adv-x="1036" d="M-53 -410l391 1844h252l-127 -549h8q25 33 55.5 63.5t69.5 53t86 37t106 14.5q104 0 168 -72t64 -225q0 -174 -46 -318.5t-123 -248t-180.5 -161t-215.5 -57.5q-53 0 -100.5 10.5t-69.5 26.5l-88 -418h-250zM328 217q51 -35 114 -35t119.5 43t98.5 115t67 167t25 200 q0 59 -23.5 97t-71.5 38q-37 0 -71.5 -18.5t-65.5 -46t-55.5 -62.5t-42.5 -68z" />
|
||||||
|
<glyph unicode="ÿ" horiz-adv-x="925" d="M-35 -389l68 201q12 -6 25.5 -8.5t25.5 -2.5q49 0 100.5 47.5t102.5 151.5l-193 1024h289l59 -575l2 -160h13l55 162l279 573h268l-492 -920q-61 -115 -115.5 -211t-109.5 -165.5t-114.5 -108.5t-127.5 -39q-90 0 -135 31zM269 1333q0 68 37.5 106t97.5 38q59 0 97 -38 t38 -106q0 -66 -38 -102.5t-97 -36.5t-97 36.5t-38 102.5zM695 1335q0 66 37.5 104t97.5 38q59 0 97 -38t38 -104t-38 -103.5t-97 -37.5t-97 37.5t-38 103.5z" />
|
||||||
|
<glyph unicode="Œ" horiz-adv-x="1796" d="M119 537q0 215 55 387t155.5 291.5t238 183t300.5 63.5q78 0 134.5 -8t107.5 -20h807l-53 -250h-541l-72 -334h494l-53 -250h-492l-74 -350h549l-51 -250h-817q-41 -14 -95.5 -21.5t-111.5 -7.5q-88 0 -174 27t-154.5 91.5t-110.5 174t-42 273.5zM399 545 q0 -53 10.5 -109.5t38 -104.5t77.5 -79t130 -31q57 0 101.5 7.5t105.5 31.5l191 901q-37 25 -87.5 38t-131.5 13q-96 0 -175 -49t-137.5 -137t-90.5 -211t-32 -270z" />
|
||||||
|
<glyph unicode="œ" horiz-adv-x="1574" d="M70 332q0 162 46 295t123.5 227t179 146.5t212.5 52.5t181.5 -45t109.5 -123q61 72 148 120t202 48q84 0 144.5 -21.5t99 -59.5t57 -87t18.5 -105q0 -84 -43 -147.5t-119.5 -105.5t-185 -63.5t-237.5 -21.5q-16 0 -30.5 1t-31.5 1q-4 -25 -6 -44t-2 -35q0 -92 48 -137.5 t136 -45.5q90 0 162 27t109 53l53 -164q-63 -53 -163.5 -90t-233.5 -37q-59 0 -106.5 13.5t-82.5 37t-59.5 52t-38.5 59.5q-51 -70 -139.5 -116t-192.5 -46q-96 0 -163.5 32t-110.5 83t-63.5 115.5t-20.5 130.5zM330 367q0 -184 133 -185q49 0 96 43t84 113t58.5 158 t21.5 176q0 82 -27.5 126t-103.5 44q-49 0 -96 -41t-84 -107.5t-59.5 -152.5t-22.5 -174zM981 604q57 0 121.5 4t120 19.5t92.5 45t37 81.5q0 31 -22.5 62.5t-94.5 31.5q-90 0 -156.5 -70t-97.5 -174z" />
|
||||||
|
<glyph unicode="Ÿ" horiz-adv-x="1165" d="M217 1434h295l133 -539l-4 -152h8l64 156l358 535h305l-637 -899l-112 -535h-265l111 532zM491 1634q0 59 41 89t107 30t106.5 -29.5t40.5 -89.5q0 -59 -41 -87.5t-106 -28.5q-66 0 -107 28.5t-41 87.5zM909 1634q0 59 41 89t106 30q66 0 107 -29.5t41 -89.5 q0 -59 -41 -87.5t-107 -28.5t-106.5 28.5t-40.5 87.5z" />
|
||||||
|
<glyph unicode="ˆ" horiz-adv-x="882" d="M614 1126l320 373h168l137 -373h-197l-49 136l-8 100l-55 -100l-117 -136h-199z" />
|
||||||
|
<glyph unicode="˜" horiz-adv-x="714" d="M627 1348q72 76 126 104.5t99 28.5q37 0 68.5 -14.5t63.5 -31t63.5 -30.5t68.5 -14q29 0 62.5 12t74.5 43l9 -143q-66 -66 -117 -91.5t-94 -25.5q-37 0 -70 13t-65.5 29.5t-65.5 30t-70 13.5q-31 0 -67.5 -12.5t-77.5 -45.5z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="891" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="1782" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="891" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="1782" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="594" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="445" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="297" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="297" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="222" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="356" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="99" />
|
||||||
|
<glyph unicode="‐" horiz-adv-x="702" d="M115 483l51 213h489l-51 -213h-489z" />
|
||||||
|
<glyph unicode="‑" horiz-adv-x="702" d="M115 483l51 213h489l-51 -213h-489z" />
|
||||||
|
<glyph unicode="‒" horiz-adv-x="702" d="M115 483l51 213h489l-51 -213h-489z" />
|
||||||
|
<glyph unicode="–" horiz-adv-x="1284" d="M215 483l51 213h858l-51 -213h-858z" />
|
||||||
|
<glyph unicode="—" horiz-adv-x="1595" d="M215 483l51 213h1170l-52 -213h-1169z" />
|
||||||
|
<glyph unicode="‘" horiz-adv-x="440" d="M203 1282q0 82 34.5 145.5t83 107.5t96.5 69.5t77 31.5l38 -110q-41 -16 -76.5 -52t-47.5 -77q35 0 57 -31t22 -74q0 -80 -47 -118.5t-102 -38.5q-35 0 -60.5 13t-42 34.5t-24.5 47t-8 52.5z" />
|
||||||
|
<glyph unicode="’" horiz-adv-x="442" d="M203 1061q43 18 78.5 49t50.5 78q-37 4 -61.5 34t-22.5 83q0 37 15.5 64.5t38 46t49 27.5t50.5 9q72 0 103 -37t31 -100q0 -84 -32 -147.5t-78 -108.5t-96 -71.5t-87 -39.5z" />
|
||||||
|
<glyph unicode="‚" horiz-adv-x="462" d="M17 -131q43 18 78.5 49t50.5 78q-37 4 -61.5 34t-22.5 83q0 37 15.5 64.5t38 46t49 27.5t50.5 9q72 0 103 -37t31 -100q0 -84 -32 -147.5t-78 -108.5t-96 -71.5t-87 -39.5z" />
|
||||||
|
<glyph unicode="“" horiz-adv-x="776" d="M203 1282q0 82 34.5 145.5t83 107.5t96.5 69.5t77 31.5l38 -110q-41 -16 -76.5 -52t-47.5 -77q35 0 57 -31t22 -74q0 -80 -47 -118.5t-102 -38.5q-35 0 -60.5 13t-42 34.5t-24.5 47t-8 52.5zM539 1282q0 82 34.5 145.5t83 107.5t96.5 69.5t77 31.5l38 -110 q-41 -16 -76.5 -52t-47.5 -77q35 0 57 -31t22 -74q0 -80 -47 -118.5t-102 -38.5q-35 0 -60.5 13t-42 34.5t-24.5 47t-8 52.5z" />
|
||||||
|
<glyph unicode="”" horiz-adv-x="776" d="M203 1061q43 18 78.5 49t50.5 78q-37 4 -61.5 34t-22.5 83q0 37 15.5 64.5t38 46t49 27.5t50.5 9q72 0 103 -37t31 -100q0 -84 -32 -147.5t-78 -108.5t-96 -71.5t-87 -39.5zM537 1061q43 18 78.5 49t50.5 78q-37 4 -61.5 34t-22.5 83q0 37 15.5 64.5t38 46t49 27.5 t50.5 9q72 0 103 -37t31 -100q0 -84 -32 -147.5t-78 -108.5t-96 -71.5t-87 -39.5z" />
|
||||||
|
<glyph unicode="„" horiz-adv-x="796" d="M17 -131q43 18 78.5 49t50.5 78q-37 4 -61.5 34t-22.5 83q0 37 15.5 64.5t38 46t49 27.5t50.5 9q72 0 103 -37t31 -100q0 -84 -32 -147.5t-78 -108.5t-96 -71.5t-87 -39.5zM348 -131q43 18 78.5 49t50.5 78q-37 4 -61.5 34t-22.5 83q0 37 15.5 64.5t38 46t49 27.5t50.5 9 q72 0 103 -37t31 -100q0 -84 -32 -147.5t-78 -108.5t-96 -71.5t-87 -39.5z" />
|
||||||
|
<glyph unicode="•" horiz-adv-x="925" d="M201 637q0 70 24.5 127t66.5 98t98 64.5t122 23.5t123 -21.5t99 -61.5t66.5 -98t24.5 -132t-24.5 -131t-66.5 -97t-99 -61.5t-123 -21.5t-122 21.5t-98 61.5t-66.5 97t-24.5 131z" />
|
||||||
|
<glyph unicode="…" horiz-adv-x="1574" d="M37 135q0 72 45 114t119 42q76 0 121 -42t45 -114t-45.5 -115t-120.5 -43q-74 0 -119 43t-45 115zM565 135q0 72 45 114t119 42q76 0 121 -42t45 -114t-45 -115t-121 -43q-74 0 -119 43t-45 115zM1096 135q0 72 45 114t119 42q76 0 120.5 -42t44.5 -114t-45 -115 t-120 -43q-74 0 -119 43t-45 115z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="356" />
|
||||||
|
<glyph unicode="‹" horiz-adv-x="614" d="M82 530l410 471l122 -131l-217 -258l-112 -80l73 -75l123 -252l-172 -127z" />
|
||||||
|
<glyph unicode="›" horiz-adv-x="600" d="M63 203l222 260l112 84l-71 80l-127 254l176 120l225 -452l-410 -471z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="445" />
|
||||||
|
<glyph unicode="€" d="M-12 473l104 191h131q8 61 21 118h-193l107 191h149q70 156 170 262q115 119 252 173t260 54q100 0 174 -19.5t123 -47.5l-108 -185q-37 18 -91.5 28.5t-130.5 10.5q-80 0 -169 -43t-164 -131q-39 -45 -70 -102h520l-94 -191h-500q-14 -55 -20 -118h454l-94 -191h-364 q4 -45 12 -84q14 -63 50 -109.5t94.5 -71t148.5 -24.5q76 0 137 18.5t115 47.5l35 -187q-70 -45 -170.5 -68.5t-198.5 -23.5q-121 0 -208 38t-144.5 105.5t-83.5 159.5q-27 90 -27 199h-227z" />
|
||||||
|
<glyph unicode="™" horiz-adv-x="1951" d="M188 1208v226h750v-226h-242v-512h-266v512h-242zM1008 696v738h266l186 -308l49 -129h2l52 133l172 304h264v-738h-232v295l35 211h-12l-74 -174l-139 -240h-160l-139 234l-80 180h-10l47 -209v-297h-227z" />
|
||||||
|
<glyph unicode="" horiz-adv-x="1024" d="M0 0v1024h1024v-1024h-1024z" />
|
||||||
|
</font>
|
||||||
|
</defs></svg>
|
After Width: | Height: | Size: 66 KiB |
242
source/app/fonts/svg/ptsansitalic.svg
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
<?xml version="1.0" standalone="no"?>
|
||||||
|
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" >
|
||||||
|
<svg xmlns="http://www.w3.org/2000/svg">
|
||||||
|
<metadata></metadata>
|
||||||
|
<defs>
|
||||||
|
<font id="pt_sansitalic" horiz-adv-x="1064" >
|
||||||
|
<font-face units-per-em="2048" ascent="1536" descent="-512" />
|
||||||
|
<missing-glyph horiz-adv-x="546" />
|
||||||
|
<glyph unicode="fi" horiz-adv-x="1050" d="M-233 -385l45 115q41 -14 74.5 -19.5t82.5 -5.5q78 0 117 81t61 214l148 893h-152l27 131h152q25 123 64.5 205t96 131t128 68.5t157.5 19.5q117 0 200 -24.5t126 -55.5l-66 -117q-47 35 -120.5 50.5t-155.5 15.5q-72 0 -118 -20.5t-77 -58.5t-49.5 -92t-32.5 -122h512 l-172 -1024h-153l147 893h-360l-148 -893q-18 -113 -43 -192.5t-61.5 -132t-90 -77t-129.5 -24.5q-61 0 -113 9t-97 32z" />
|
||||||
|
<glyph unicode="fl" horiz-adv-x="1118" d="M-233 -385l45 115q41 -14 74.5 -19.5t82.5 -5.5q78 0 117 81t61 214l132 893h-152l27 131h151q23 121 59.5 204t90 134t124 73.5t162.5 22.5q39 0 87.5 -3t96.5 -8t90 -11t68 -15l-190 -1171q-6 -35 -6 -57q0 -80 67 -80q27 0 56.5 5t70.5 17l-8 -115q-18 -8 -42.5 -15 t-51.5 -12t-52.5 -8t-43.5 -3q-74 0 -117 32.5t-43 112.5q0 8 1 19.5t6 48t16.5 109.5t32 202t51 324.5t75.5 478.5q-29 6 -82 12t-106 6q-66 0 -109 -21.5t-71.5 -61.5t-46 -96t-31.5 -124h203l-27 -131h-203l-131 -893q-16 -113 -39.5 -192.5t-61.5 -132t-92.5 -77 t-130.5 -24.5q-61 0 -113 9t-97 32z" />
|
||||||
|
<glyph horiz-adv-x="2048" />
|
||||||
|
<glyph horiz-adv-x="2048" />
|
||||||
|
<glyph unicode="
" horiz-adv-x="546" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="546" />
|
||||||
|
<glyph unicode="	" horiz-adv-x="546" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="546" />
|
||||||
|
<glyph unicode="!" horiz-adv-x="559" d="M178 94q0 55 33 87t86 32t86 -31.5t33 -87.5q0 -53 -33 -86t-86 -33t-86 33t-33 86zM295 362l41 361l149 711h164l-149 -711l-111 -361h-94z" />
|
||||||
|
<glyph unicode=""" horiz-adv-x="620" d="M162 1038l84 396h151l-143 -396h-92zM389 1038l84 396h151l-143 -396h-92z" />
|
||||||
|
<glyph unicode="#" d="M131 461l29 131h164l63 268h-154l29 131h156l78 324h139l-78 -324h217l78 324h139l-78 -324h158l-33 -131h-155l-64 -268h150l-33 -131h-150l-79 -342h-140l80 342h-217l-80 -342h-139l80 342h-160zM463 592h217l63 268h-217z" />
|
||||||
|
<glyph unicode="$" d="M125 104l72 125q33 -23 95 -57.5t144 -48.5l123 575q-45 33 -89 70t-78 80t-55.5 97t-21.5 124q0 90 30 158.5t84 117t128 76t162 33.5l41 184h131l-39 -182q88 -8 150.5 -30.5t105.5 -45.5l-70 -129q-35 16 -90 34t-127 26l-110 -514q47 -35 93 -74t82 -88t58.5 -111.5 t22.5 -144.5q0 -84 -29 -154.5t-84 -123t-136 -85t-183 -39.5q0 -2 -6.5 -29.5t-12.5 -62.5q-8 -39 -18 -90h-131l39 187q-98 14 -172 53t-109 69zM483 1094q0 -78 41 -132.5t101 -101.5l96 453q-117 -8 -177.5 -68.5t-60.5 -150.5zM535 119q123 8 193.5 74t70.5 172 q0 92 -45 154.5t-109 115.5z" />
|
||||||
|
<glyph unicode="%" horiz-adv-x="1507" d="M123 1004q0 119 36 204.5t91 141t122.5 82t133.5 26.5q117 0 177 -63.5t60 -180.5q0 -111 -30.5 -194.5t-82.5 -141t-123 -87t-149 -29.5q-104 0 -169.5 63.5t-65.5 178.5zM180 55l1051 1405l102 -80l-1051 -1405zM264 1020q0 -66 30 -102.5t89 -36.5q43 0 83 22.5 t70.5 64.5t48 102t17.5 136q0 72 -31.5 102.5t-89.5 30.5q-43 0 -83 -25.5t-69.5 -68.5t-47 -101t-17.5 -124zM791 244q0 119 36 204.5t91 141t122.5 82t133.5 26.5q117 0 177 -63.5t60 -180.5q0 -111 -30.5 -194.5t-82.5 -141t-123 -87t-149 -29.5q-104 0 -169.5 63.5 t-65.5 178.5zM932 260q0 -66 30 -102.5t89 -36.5q43 0 83 22.5t70.5 64.5t48 102t17.5 136q0 72 -31.5 102.5t-89.5 30.5q-43 0 -83 -25.5t-69.5 -68.5t-47 -101t-17.5 -124z" />
|
||||||
|
<glyph unicode="&" horiz-adv-x="1581" d="M178 303q0 96 40 184t103.5 164t143.5 136.5t160 101.5q-14 37 -24.5 66.5t-18 59t-10.5 61.5t-3 73q0 55 20.5 110.5t63.5 99.5t107.5 71.5t154.5 27.5q72 0 116 -19.5t68.5 -48t33 -63.5t8.5 -65q0 -117 -89 -216.5t-243 -183.5q20 -59 48 -121.5t60.5 -124t69.5 -122 t74 -111.5q27 25 56.5 62.5t58 79.5t55 87t49.5 86l109 -59q-18 -35 -51 -83t-70 -98t-74 -96.5t-66 -76.5q66 -82 112 -125t97 -76l-118 -115q-47 27 -100.5 78t-104.5 119q-43 -37 -92.5 -71t-106.5 -60.5t-123.5 -43t-142.5 -16.5q-86 0 -154.5 25t-117 69t-74 103 t-25.5 131zM342 338q0 -111 67.5 -166t190.5 -55q49 0 98.5 13t94.5 34.5t82.5 48t66.5 55.5q-43 59 -83 129t-74.5 139.5t-62.5 134t-46 113.5q-74 -47 -135.5 -100t-105.5 -109.5t-68.5 -116t-24.5 -120.5zM723 1153q0 -31 2 -55.5t7 -46t12.5 -44t19.5 -53.5 q117 70 175 133.5t58 141.5q0 41 -23.5 69.5t-80.5 28.5q-47 0 -79 -14.5t-52.5 -40t-29.5 -57t-9 -62.5z" />
|
||||||
|
<glyph unicode="'" horiz-adv-x="413" d="M209 1038l84 396h151l-143 -396h-92z" />
|
||||||
|
<glyph unicode="(" horiz-adv-x="544" d="M111 150q0 211 47 401t127 356t184 304.5t219 242.5l76 -72q-115 -127 -206 -269t-156.5 -295.5t-98.5 -316.5t-33 -327q0 -131 28 -270.5t93 -278.5l-94 -71q-111 162 -148.5 312t-37.5 284z" />
|
||||||
|
<glyph unicode=")" horiz-adv-x="544" d="M-195 -375q100 104 187.5 243.5t155 294t106.5 319.5t39 323q0 197 -25.5 334t-89.5 247l103 68q47 -66 79.5 -141.5t53 -153.5t30 -154.5t9.5 -142.5q0 -209 -46.5 -400.5t-125 -358t-182 -306t-216.5 -243.5z" />
|
||||||
|
<glyph unicode="*" horiz-adv-x="681" d="M145 1133v114h103l129 -24l-92 90l-56 94l101 57l51 -86l37 -114l43 116l49 82l98 -53l-51 -88l-96 -98l139 24h98v-114h-92l-133 24l94 -98l49 -80l-98 -57l-51 86l-49 125l-37 -119l-51 -86l-103 57l54 86l88 86l-121 -24h-103z" />
|
||||||
|
<glyph unicode="+" horiz-adv-x="983" d="M113 618v148h360v371h148v-371h360v-148h-360v-370h-148v370h-360z" />
|
||||||
|
<glyph unicode="," horiz-adv-x="380" d="M-43 -225q78 29 125 90t57 121q-8 -4 -20 -4q-29 0 -56.5 24.5t-27.5 65.5q0 53 34.5 90t100.5 37q51 0 78.5 -35t27.5 -80q0 -63 -21.5 -123.5t-60 -112t-91 -91.5t-113.5 -62z" />
|
||||||
|
<glyph unicode="-" horiz-adv-x="700" d="M129 520l33 139h471l-35 -139h-469z" />
|
||||||
|
<glyph unicode="." horiz-adv-x="432" d="M72 94q0 55 32.5 87t85.5 32t86 -31.5t33 -87.5q0 -53 -32.5 -86t-86.5 -33q-53 0 -85.5 33t-32.5 86z" />
|
||||||
|
<glyph unicode="/" horiz-adv-x="688" d="M-190 -229l1067 1687l116 -63l-1067 -1690z" />
|
||||||
|
<glyph unicode="0" d="M117 449q0 215 46 400t127 320.5t193.5 212t247.5 76.5q174 0 268.5 -112.5t94.5 -358.5q0 -184 -40 -364.5t-117 -324.5t-189.5 -233.5t-260.5 -89.5q-104 0 -174.5 40t-114.5 106.5t-62.5 152t-18.5 175.5zM276 457q0 -104 20.5 -171t54.5 -103t76 -50t85 -14 q92 0 170 72.5t133 193.5t87 272.5t32 309.5q0 176 -49 262t-178 86q-82 0 -159 -63.5t-137.5 -178.5t-97.5 -272.5t-37 -343.5z" />
|
||||||
|
<glyph unicode="1" d="M129 0l31 152h272l213 991l45 121l-100 -97l-246 -161l-57 104l506 348h69l-278 -1306h266l-31 -152h-690z" />
|
||||||
|
<glyph unicode="2" d="M66 0l12 59q51 51 132 128t172 170.5t183 195.5t167 205.5t119 200t44 178.5q0 39 -8 71.5t-26.5 56t-53.5 37t-90 13.5q-74 0 -143.5 -30t-147.5 -81l-43 123q98 72 188.5 101.5t196.5 29.5q143 0 215 -81t72 -208q0 -106 -59.5 -231t-150.5 -251t-199.5 -245.5 t-209.5 -216.5l-112 -88v-8l127 23h419l-28 -152h-776z" />
|
||||||
|
<glyph unicode="3" d="M88 27l74 145q41 -23 98 -38t133 -15q96 0 169 30.5t119 81t70.5 115t24.5 131.5q0 106 -53 163.5t-199 57.5h-147l12 60l373 454l106 91l-129 -21h-379l29 152h696l-12 -60l-411 -495l-80 -60v-4l67 14q57 0 108.5 -19t91.5 -59t63.5 -101.5t23.5 -147.5 q0 -111 -36 -206t-106.5 -167t-177 -113t-247.5 -41q-88 0 -159 14.5t-122 37.5z" />
|
||||||
|
<glyph unicode="4" d="M70 440l14 68l850 948h104l-186 -876h229l-28 -140h-232l-92 -440h-149l92 440h-602zM283 565l137 15h282l97 450l55 168h-8l-96 -139l-355 -391z" />
|
||||||
|
<glyph unicode="5" d="M96 23l70 141q43 -18 91 -31.5t124 -13.5q92 0 164.5 29.5t124 82t78 122t24.5 153.5q2 117 -62.5 174t-211.5 57l-164 -10l149 707h607l-33 -152h-461l-88 -410h14.5t28.5 2q18 0 39 3q96 0 161.5 -30t105.5 -77t57.5 -109.5t17.5 -125.5q0 -158 -51.5 -265.5t-134 -173 t-186 -93.5t-210.5 -28q-82 0 -144.5 12.5t-109.5 35.5z" />
|
||||||
|
<glyph unicode="6" d="M129 418q0 205 78 387t203 320.5t282.5 226.5t317.5 106l8 -131q-113 -18 -223.5 -74.5t-203.5 -139.5t-165 -186.5t-109 -215.5q20 27 55.5 52t79.5 45.5t94 32t103 11.5q147 0 243.5 -89t96.5 -263q0 -115 -33.5 -210t-98 -166t-156 -110t-203.5 -39q-68 0 -133.5 24 t-117.5 76t-85 136t-33 207zM283 434q0 -68 13 -126t42 -101t72 -67.5t104 -24.5q82 0 141.5 31.5t97.5 83t55 116.5t17 133q0 102 -51 168t-168 66q-47 0 -93 -13.5t-88 -36t-76 -52t-54 -62.5q-4 -27 -8 -58.5t-4 -56.5z" />
|
||||||
|
<glyph unicode="7" d="M141 0l742 1200l106 100l-119 -18h-542l30 152h813l-10 -56l-852 -1378h-168z" />
|
||||||
|
<glyph unicode="8" d="M125 299q0 141 93 261t263 192q-33 27 -62.5 54.5t-53 63t-38 82.5t-14.5 115q0 94 36 167t96.5 123t140.5 75.5t166 25.5q68 0 127 -19.5t102 -57.5t67.5 -94t24.5 -130q0 -61 -23.5 -121.5t-65.5 -114t-98.5 -99.5t-123.5 -83q37 -31 70.5 -64.5t58 -73.5t40 -88 t15.5 -107q0 -86 -27.5 -164t-86 -137.5t-149.5 -94.5t-220 -35q-84 0 -146.5 26t-105.5 69t-64.5 102t-21.5 127zM285 317q0 -37 10 -73.5t33.5 -64t65.5 -44t104 -16.5q57 0 109 15.5t93 48t63.5 81t22.5 111.5q0 57 -15 101t-39.5 80t-63.5 66.5t-84 59.5 q-135 -63 -217 -155.5t-82 -209.5zM473 1075q0 -98 49 -158.5t135 -113.5q51 33 98.5 72.5t81 81.5t55 85t21.5 86q0 96 -47 141.5t-133 45.5q-53 0 -100 -15.5t-82 -46t-56.5 -76t-21.5 -102.5z" />
|
||||||
|
<glyph unicode="9" d="M190 106q129 29 239 84.5t198 132t151.5 172t100.5 203.5q-66 -57 -144 -86.5t-196 -29.5q-55 0 -111.5 20.5t-104 65.5t-77 116.5t-29.5 171.5q0 119 37 212.5t103.5 158t155.5 98t194 33.5q76 0 143.5 -27.5t118.5 -83t79.5 -136.5t28.5 -187q0 -236 -83 -423 t-212 -321.5t-284.5 -212t-298.5 -92.5zM377 975q0 -74 22.5 -123t54 -78t69.5 -41t75 -12q94 0 179 37t130 90q2 12 5 34.5t6.5 45t4.5 44t1 32.5q0 143 -61.5 229t-182.5 86q-59 0 -113.5 -20.5t-95.5 -63.5t-67.5 -107.5t-26.5 -152.5z" />
|
||||||
|
<glyph unicode=":" horiz-adv-x="546" d="M182 94q0 55 33 87t86 32t86 -31.5t33 -87.5q0 -53 -33 -86t-86 -33t-86 33t-33 86zM354 920q0 55 33 86.5t86 31.5t86 -31.5t33 -86.5q0 -53 -33 -86t-86 -33t-86 33t-33 86z" />
|
||||||
|
<glyph unicode=";" horiz-adv-x="559" d="M111 -225q78 29 125 90t57 121q-8 -4 -21 -4q-29 0 -56.5 24.5t-27.5 65.5q0 53 35 90t101 37q51 0 78.5 -35t27.5 -80q0 -63 -21.5 -123.5t-60.5 -112t-91 -91.5t-114 -62zM367 920q0 55 32.5 86.5t85.5 31.5t86 -31.5t33 -86.5q0 -53 -32.5 -86t-86.5 -33 q-53 0 -85.5 33t-32.5 86z" />
|
||||||
|
<glyph unicode="<" horiz-adv-x="983" d="M111 625v59l776 473l78 -127l-486 -297l-186 -78l184 -65l498 -295l-78 -123z" />
|
||||||
|
<glyph unicode="=" horiz-adv-x="983" d="M113 449v147h868v-147h-868zM113 788v148h868v-148h-868z" />
|
||||||
|
<glyph unicode=">" horiz-adv-x="983" d="M115 1032l78 125l786 -452v-60l-776 -473l-78 125l485 297l187 78l-185 65z" />
|
||||||
|
<glyph unicode="?" horiz-adv-x="847" d="M164 94q0 55 32.5 87t86.5 32q53 0 85.5 -31.5t32.5 -87.5q0 -53 -32.5 -86t-85.5 -33t-86 33t-33 86zM244 1356q41 25 78.5 43t80.5 31.5t93.5 20.5t115.5 7q152 0 223.5 -69.5t71.5 -180.5t-34.5 -191.5t-88 -144t-118 -118t-123 -111.5t-103.5 -123.5t-59 -157.5h-129 q10 102 51 179t95.5 139.5t115.5 117t111.5 109t84 116.5t33.5 142q0 78 -42 120t-146 42q-72 0 -142.5 -27.5t-129.5 -62.5z" />
|
||||||
|
<glyph unicode="@" horiz-adv-x="2179" d="M238 483q0 223 76.5 403.5t207.5 307.5t305 195.5t369 68.5q184 0 342 -54t274.5 -155.5t182 -248t65.5 -332.5q0 -131 -45 -251t-121.5 -210t-179 -144.5t-217.5 -54.5q-86 0 -136 37t-50 137q0 18 2 40t6 46h-8q-31 -47 -70 -93t-87 -83t-102.5 -60.5t-113.5 -23.5 q-49 0 -93 21.5t-77 62.5t-52.5 97.5t-19.5 127.5q0 131 43 258t116 225.5t170 159t206 60.5q74 0 120 -22.5t89 -55.5l67 64h70l-104 -588q-10 -53 -15.5 -95t-5.5 -75q0 -51 17.5 -76t62.5 -25q70 0 137.5 37t121.5 104.5t88 164t34 215.5q0 158 -53.5 278.5t-149.5 203.5 t-229 126t-293 43q-168 0 -313.5 -61.5t-254 -170t-171 -260t-62.5 -329.5q0 -182 56.5 -325.5t161 -242t249.5 -149.5t324 -51q59 0 135 14t137 43l41 -131q-90 -39 -169 -52.5t-169 -13.5q-190 0 -356 57.5t-291 170t-196.5 279.5t-71.5 386zM854 344q0 -80 33 -138.5 t119 -58.5q41 0 85 29t87 75t82.5 103.5t70.5 116.5l62 334q-35 41 -71 58.5t-89 17.5q-80 0 -149.5 -49.5t-120 -126t-80 -173t-29.5 -188.5z" />
|
||||||
|
<glyph unicode="A" horiz-adv-x="1140" d="M-68 0l828 1456h76l206 -1456h-157l-58 397h-499l-222 -397h-174zM408 545h403l-59 436l-4 217h-3l-92 -221z" />
|
||||||
|
<glyph unicode="B" horiz-adv-x="1138" d="M82 10l299 1411q78 12 175 20.5t210 8.5q76 0 145.5 -19.5t121.5 -58.5t84 -100.5t32 -143.5q0 -80 -24.5 -145t-69.5 -114.5t-105.5 -79t-130.5 -39.5v-9q45 -10 86 -33.5t72 -58.5t49 -81t18 -101q0 -143 -56 -236.5t-143 -148.5t-194.5 -76.5t-212.5 -21.5h-79t-117 4 q-123 12 -160 22zM272 145q12 -4 38 -6t55.5 -4t61 -3t56.5 -1q72 0 141.5 17.5t125 54.5t89 96t33.5 145q0 63 -30.5 105.5t-79.5 67t-111.5 33.5t-126.5 9h-143zM410 799h108q35 0 82 1t80 5q47 10 100.5 28.5t97.5 52.5t71.5 86t27.5 130q0 57 -17.5 95t-51.5 61.5 t-81 34t-104 10.5q-66 0 -123 -3.5t-86 -9.5z" />
|
||||||
|
<glyph unicode="C" horiz-adv-x="1114" d="M145 561q0 231 68 400t178.5 280t248.5 164t280 53q117 0 190.5 -16.5t120.5 -38.5l-74 -150q-41 23 -107.5 38.5t-152.5 15.5q-115 0 -220.5 -50.5t-185 -144.5t-127 -229t-47.5 -303q0 -98 26 -181.5t74 -143.5t118.5 -94t160.5 -34q96 0 160 21.5t115 50.5l12 -140 q-70 -47 -147.5 -65.5t-180.5 -18.5q-121 0 -215 44t-159.5 123t-100.5 185.5t-35 233.5z" />
|
||||||
|
<glyph unicode="D" horiz-adv-x="1273" d="M82 -2l305 1436q78 10 176.5 13t177.5 3q121 0 219.5 -32t167 -97.5t105.5 -165.5t37 -235q0 -90 -16.5 -196t-54.5 -209t-101.5 -199.5t-157.5 -171t-221 -118.5t-293 -44q-31 0 -81 1t-99 3q-143 8 -164 12zM276 141q8 -2 33 -3t52.5 -2t53 -2t36.5 -1q178 0 300.5 74 t199.5 186.5t112 247.5t35 256q0 92 -20.5 166t-64.5 126t-114 80.5t-170 28.5q-25 0 -55.5 -1t-59 -2t-55.5 -3t-41 -4z" />
|
||||||
|
<glyph unicode="E" horiz-adv-x="1044" d="M82 0l305 1434h739l-30 -152h-580l-100 -469h530l-31 -151h-530l-109 -510h590l-32 -152h-590h-162z" />
|
||||||
|
<glyph unicode="F" horiz-adv-x="1007" d="M82 0l305 1434h739l-30 -152h-580l-104 -489h540l-30 -152h-541l-135 -641h-164z" />
|
||||||
|
<glyph unicode="G" horiz-adv-x="1193" d="M145 557q0 252 74 424t189.5 277.5t255 152.5t270.5 47q117 0 193.5 -15.5t123.5 -37.5l-71 -150q-41 23 -110 37.5t-155 14.5q-119 0 -226 -46.5t-190 -138.5t-132.5 -228t-49.5 -316q0 -92 22.5 -174t69 -143.5t115 -97.5t162.5 -36q66 0 113 13.5t94 37.5l84 400 l-229 40l20 97h238h139l-133 -631q-145 -109 -361 -109q-102 0 -193 37t-161 110t-111 181.5t-41 253.5z" />
|
||||||
|
<glyph unicode="H" horiz-adv-x="1308" d="M82 0l303 1434h164l-131 -625h649l131 625h164l-303 -1434h-164l139 657h-651l-137 -657h-164z" />
|
||||||
|
<glyph unicode="I" horiz-adv-x="567" d="M127 0l303 1434h164l-303 -1434h-164z" />
|
||||||
|
<glyph unicode="J" horiz-adv-x="569" d="M-125 12l62 146q39 -27 110 -27q43 0 71.5 15.5t49 45t34 70.5t23.5 94l230 1078h163l-237 -1119q-18 -82 -44 -144t-66 -105t-98 -64.5t-140 -21.5q-16 0 -38 2t-44.5 6t-43 10t-32.5 14z" />
|
||||||
|
<glyph unicode="K" horiz-adv-x="1179" d="M82 0l303 1434h164l-143 -668l81 29l588 639h203l-586 -623l-94 -63l80 -82l358 -666h-186l-361 664h-104l-139 -664h-164z" />
|
||||||
|
<glyph unicode="L" horiz-adv-x="1007" d="M82 0l303 1434h164l-273 -1282h644l-31 -152h-647h-160z" />
|
||||||
|
<glyph unicode="M" horiz-adv-x="1544" d="M82 0l305 1434h113l266 -734l31 -159h2l94 164l559 729h145l-305 -1434h-164l205 963l64 215h-8l-115 -197l-492 -647h-49l-235 647l-31 197h-8l-17 -213l-204 -965h-156z" />
|
||||||
|
<glyph unicode="N" horiz-adv-x="1314" d="M82 0l309 1456h82l447 -958l67 -201h8l19 201l200 936h154l-309 -1457h-76l-448 961l-70 211h-6l-25 -211l-198 -938h-154z" />
|
||||||
|
<glyph unicode="O" horiz-adv-x="1333" d="M145 524q0 188 51.5 358.5t146.5 298.5t229.5 202.5t297.5 74.5q98 0 182.5 -29.5t144.5 -94t94 -167t34 -249.5q0 -193 -51 -364t-143.5 -300t-220.5 -204t-281 -75q-242 0 -363 140.5t-121 408.5zM317 526q0 -193 80 -298t236 -105q115 0 210 63.5t164.5 172t107.5 252 t38 302.5q0 119 -26.5 197t-70.5 122t-100.5 61.5t-113.5 17.5q-117 0 -213.5 -64.5t-165 -173t-107.5 -251t-39 -296.5z" />
|
||||||
|
<glyph unicode="P" horiz-adv-x="1089" d="M82 0l301 1419q78 18 164 24.5t170 6.5q94 0 175 -20.5t140.5 -65.5t93 -115.5t33.5 -169.5q0 -156 -56 -260t-147.5 -166.5t-206 -89t-231.5 -26.5h-31.5t-46 1t-47 3t-33.5 4l-114 -545h-164zM393 694q8 -4 27.5 -5t41 -3t42 -2h31.5q88 0 169.5 18.5t144 63.5 t100.5 116.5t38 180.5q0 74 -24.5 121t-66.5 72.5t-97.5 36t-116.5 10.5q-47 0 -91 -3.5t-73 -9.5z" />
|
||||||
|
<glyph unicode="Q" horiz-adv-x="1333" d="M145 524q0 188 51.5 358.5t146.5 298.5t229.5 202.5t297.5 74.5q98 0 182.5 -29.5t144.5 -94t94 -167t34 -249.5q0 -193 -51 -364t-143.5 -300t-220.5 -204t-281 -75q-242 0 -363 140.5t-121 408.5zM317 526q0 -193 80 -298t236 -105q115 0 210 63.5t164.5 172t107.5 252 t38 302.5q0 119 -26.5 197t-70.5 122t-100.5 61.5t-113.5 17.5q-117 0 -213.5 -64.5t-165 -173t-107.5 -251t-39 -296.5zM360 -250l31 150q55 12 109 12q82 0 157.5 -21.5t154.5 -46t163 -46t180 -21.5q84 0 174 20l-33 -147q-49 -14 -95 -19.5t-91 -5.5q-98 0 -186 21.5 t-169 46t-156 46t-146 21.5q-23 0 -46.5 -2t-46.5 -8z" />
|
||||||
|
<glyph unicode="R" horiz-adv-x="1163" d="M82 0l301 1419q86 16 166 23.5t160 7.5q78 0 151.5 -19.5t130 -61.5t90 -109.5t33.5 -163.5q0 -180 -105.5 -300t-306.5 -155l74 -74l221 -567h-178l-246 618l-192 31l-135 -649h-164zM406 762h141q74 0 144.5 14.5t126.5 51t90 100t34 159.5q0 37 -14.5 75t-43 70 t-76 51.5t-110.5 19.5q-49 0 -98 -3.5t-82 -9.5z" />
|
||||||
|
<glyph unicode="S" horiz-adv-x="1034" d="M35 51l84 150q47 -27 128 -52.5t191 -25.5q63 0 127 11t115 40t83 76t32 119q0 74 -38 125t-95.5 93t-124 81t-124 90t-95 120.5t-37.5 172.5q0 109 39.5 186.5t108.5 126.5t162 71.5t197 22.5q119 0 213.5 -18.5t147.5 -46.5l-82 -146q-41 23 -122 43.5t-187 20.5 q-135 0 -220 -61.5t-85 -178.5q0 -76 37.5 -128t95 -94t124 -81t124 -89t95.5 -120t38 -170q0 -199 -143.5 -306.5t-411.5 -107.5q-137 0 -232.5 24t-144.5 52z" />
|
||||||
|
<glyph unicode="T" horiz-adv-x="1081" d="M225 1282l31 152h1008l-31 -152h-424l-270 -1282h-164l270 1282h-420z" />
|
||||||
|
<glyph unicode="U" horiz-adv-x="1265" d="M178 338q0 84 23 190l190 906h164l-190 -908q-23 -90 -23 -164q0 -129 67.5 -179t200.5 -50q80 0 140.5 22.5t104.5 69.5t73.5 121t52.5 178l193 910h155l-201 -957q-29 -131 -71.5 -225t-107 -153.5t-154.5 -88t-209 -28.5q-113 0 -191 25.5t-126 71.5t-69.5 112.5 t-21.5 146.5z" />
|
||||||
|
<glyph unicode="V" horiz-adv-x="1107" d="M213 1434h168l137 -981v-220h4l92 224l543 977h176l-823 -1457h-76z" />
|
||||||
|
<glyph unicode="W" horiz-adv-x="1613" d="M233 1434h168l37 -957l-18 -237h2l80 241l481 953h88l76 -957l-19 -237h2l82 241l437 953h168l-689 -1457h-90l-77 961l12 217h-8l-82 -219l-480 -959h-90z" />
|
||||||
|
<glyph unicode="X" horiz-adv-x="1204" d="M-14 0l606 733l-266 701h178l176 -486l25 -117l69 117l391 486h199l-571 -695l290 -739h-178l-196 514l-29 123l-78 -123l-418 -514h-198z" />
|
||||||
|
<glyph unicode="Y" horiz-adv-x="1087" d="M221 1434h178l183 -627l6 -125h2l61 129l445 623h184l-623 -863l-120 -571h-164l121 569z" />
|
||||||
|
<glyph unicode="Z" d="M-2 0l31 154l891 1046l100 82h-750l31 152h916l-31 -154l-897 -1053l-96 -75h751l-31 -152h-915z" />
|
||||||
|
<glyph unicode="[" horiz-adv-x="595" d="M33 -471l403 1905h156h199l-31 -144h-199l-344 -1618h201l-31 -143h-201h-153z" />
|
||||||
|
<glyph unicode="\" horiz-adv-x="778" d="M84 1401l141 57l695 -1685l-136 -60z" />
|
||||||
|
<glyph unicode="]" horiz-adv-x="600" d="M-129 -471l31 143h196l342 1618h-198l30 144h203h152l-404 -1905h-153h-199z" />
|
||||||
|
<glyph unicode="^" horiz-adv-x="1024" d="M209 891l381 565h59l346 -565h-170l-161 276l-48 142l-63 -144l-191 -274h-153z" />
|
||||||
|
<glyph unicode="_" horiz-adv-x="835" d="M-90 -281h835v-139h-835v139z" />
|
||||||
|
<glyph unicode="`" horiz-adv-x="487" d="M602 1432l8 43h187l59 -306h-88z" />
|
||||||
|
<glyph unicode="a" horiz-adv-x="997" d="M92 293q0 131 34 266t104.5 243.5t182 178.5t269.5 70q57 0 140 -13.5t155 -36.5l-129 -598q-16 -76 -22.5 -153.5t-6.5 -145.5v-58.5t4 -49.5h-114l-29 178h-8q-25 -35 -61 -70.5t-79 -64.5t-92 -46.5t-104 -17.5q-244 0 -244 318zM256 293q0 -78 30.5 -132.5 t96.5 -54.5q49 0 94 24t85 58.5t71 74.5t49 75l115 553q-61 29 -156 29q-94 0 -166 -55.5t-121 -144.5t-73.5 -201.5t-24.5 -225.5z" />
|
||||||
|
<glyph unicode="b" horiz-adv-x="1067" d="M88 63l291 1371h153l-124 -586h8q29 37 65.5 72.5t81.5 64.5t96.5 46.5t110.5 17.5q121 0 176 -85t55 -214q0 -184 -51 -326.5t-135 -241t-191.5 -149.5t-220.5 -51q-111 0 -193.5 24.5t-121.5 56.5zM260 156q61 -43 174 -43q66 0 137.5 40t131 116.5t97.5 188t38 255.5 q0 104 -32 154.5t-85 50.5q-51 0 -104.5 -26t-101.5 -67t-88 -91t-65 -97z" />
|
||||||
|
<glyph unicode="c" horiz-adv-x="860" d="M102 303q0 174 47.5 312.5t126 234.5t181 147.5t211.5 51.5q78 0 128 -14.5t91 -33.5l-58 -127q-35 20 -86 32t-110 12q-70 0 -136.5 -47.5t-117.5 -124t-82 -176t-31 -203.5q0 -133 55.5 -197t149.5 -64q61 0 129 28t109 56l39 -102q-31 -27 -71 -47.5t-82 -34.5 t-83 -22.5t-78 -8.5q-100 0 -164.5 32t-101.5 81t-51.5 106.5t-14.5 108.5z" />
|
||||||
|
<glyph unicode="d" horiz-adv-x="1042" d="M102 322q0 121 35 248.5t102.5 232t169 172t234.5 67.5q37 0 63.5 -2t50 -6t44 -11t43.5 -15l90 426h153l-229 -1082q-16 -80 -24.5 -149.5t-8.5 -128.5q0 -23 1 -41.5t3 -36.5h-102l-29 178h-8q-25 -35 -61.5 -70.5t-81.5 -64.5t-95.5 -46.5t-103.5 -17.5 q-113 0 -179.5 83t-66.5 264zM266 311q0 -84 33 -144.5t107 -60.5q43 0 88 24t84.5 58.5t71.5 74.5t50 75l115 532q-35 23 -79 32t-115 9q-82 0 -147.5 -50t-112 -134t-71 -192.5t-24.5 -223.5z" />
|
||||||
|
<glyph unicode="e" horiz-adv-x="948" d="M102 332q0 168 47.5 301t124 225t174 141.5t199.5 49.5q74 0 128 -20.5t89 -54.5t51.5 -78t16.5 -93q0 -145 -141.5 -228t-411.5 -83q-25 0 -51.5 1t-55.5 3q-8 -39 -12 -74t-4 -62q0 -113 51 -183.5t160 -70.5q90 0 165 30t116 63l49 -99q-72 -61 -169.5 -93t-195.5 -32 q-164 0 -247 94.5t-83 262.5zM301 610q78 0 162 4t152.5 21.5t113.5 55.5t45 106q0 20 -7 41.5t-23.5 39t-46 29t-74.5 11.5q-113 0 -196 -77t-126 -231z" />
|
||||||
|
<glyph unicode="f" horiz-adv-x="569" d="M-233 -385l45 115q41 -14 74.5 -19.5t82.5 -5.5q78 0 117 75t66 236l143 877h-158l27 131h149l27 137q14 76 34.5 131.5t54.5 92t84 55t122 18.5q68 0 131 -13t115 -36l-45 -121q-100 39 -191 39q-76 0 -110.5 -52t-53.5 -167l-14 -84h207l-25 -131h-200l-164 -963 q-12 -76 -34 -140t-56.5 -112.5t-88 -76t-129.5 -27.5q-61 0 -113 9t-97 32z" />
|
||||||
|
<glyph unicode="g" horiz-adv-x="1034" d="M10 -342l68 115q16 -8 39.5 -21.5t57.5 -26t82 -20.5t114 -8q102 0 171.5 73.5t104.5 231.5l37 172h-8q-29 -39 -62.5 -73.5t-74.5 -62.5t-89.5 -44.5t-105.5 -16.5q-111 0 -178.5 80t-67.5 228q0 137 38 272t113 242.5t184.5 175t252.5 67.5q111 0 186.5 -18t133.5 -45 l-218 -1026q-43 -201 -148 -294t-280 -93q-133 0 -219 33.5t-131 58.5zM262 311q0 -94 38 -148t101 -54q51 0 101.5 26.5t92.5 68.5t76 91t56 92l104 494q-33 18 -79.5 24t-96.5 6q-84 0 -155.5 -49t-123.5 -132t-83 -191.5t-31 -227.5z" />
|
||||||
|
<glyph unicode="h" horiz-adv-x="1083" d="M74 0l303 1434h153l-127 -586h9q27 33 64.5 67.5t86.5 64.5t106.5 49.5t125.5 19.5q100 0 157.5 -48.5t57.5 -175.5q0 -86 -27 -207l-131 -618h-154l123 584q12 61 20.5 109t8.5 85q0 76 -31 108t-96 32q-53 0 -108.5 -28t-106.5 -71t-91 -96t-61 -102l-129 -621h-153z " />
|
||||||
|
<glyph unicode="i" horiz-adv-x="530" d="M111 0l217 1024h153l-217 -1024h-153zM360 1337q0 47 32 80t79 33t80 -33t33 -80t-33 -78.5t-80 -31.5t-79 31.5t-32 78.5z" />
|
||||||
|
<glyph unicode="j" horiz-adv-x="509" d="M-197 -422l31 133q61 0 101 17.5t68 54.5t47.5 92t35.5 131l217 1018h154l-230 -1079q-41 -190 -127 -280.5t-233 -90.5q-16 0 -31.5 1t-32.5 3zM336 1337q0 47 31.5 80t78.5 33t80 -33t33 -80t-32.5 -78.5t-80.5 -31.5q-47 0 -78.5 31.5t-31.5 78.5z" />
|
||||||
|
<glyph unicode="k" horiz-adv-x="919" d="M74 0l303 1434h153l-186 -873l88 23l369 440h188l-364 -416l-97 -67l78 -80l230 -461h-170l-232 461h-110l-97 -461h-153z" />
|
||||||
|
<glyph unicode="l" horiz-adv-x="552" d="M102 135q0 41 13 101l254 1198h153l-250 -1190q-6 -35 -6 -58q0 -39 13.5 -56t35.5 -17q41 0 69 5t67 19v-117q-18 -10 -43 -17t-50.5 -11t-51 -7t-46.5 -3q-72 0 -115 32.5t-43 120.5z" />
|
||||||
|
<glyph unicode="m" horiz-adv-x="1562" d="M74 0l217 1024h108l-12 -176h8q33 33 71 68.5t84 64.5t100.5 48.5t119.5 19.5q92 0 124 -57.5t32 -160.5q31 39 71.5 78t89 70t101.5 50.5t106 19.5q94 0 144.5 -44t50.5 -163q0 -86 -31 -228l-129 -614h-153l129 616q12 59 19 106.5t7 82.5q0 55 -22.5 84t-75.5 29 q-43 0 -91 -28t-93 -69t-81 -88t-57 -88l-133 -645h-153l123 580q16 72 24 127t8 96q0 55 -20.5 85t-69.5 30q-51 0 -100 -27t-92 -67t-79 -85t-57 -82l-135 -657h-153z" />
|
||||||
|
<glyph unicode="n" horiz-adv-x="1069" d="M74 0l217 1024h106l-8 -176h8q27 33 64 68.5t83 64.5t103.5 48.5t126.5 19.5q102 0 161.5 -49.5t59.5 -172.5q0 -61 -18 -147l-146 -680h-153l137 647q8 37 14.5 73t6.5 64q0 59 -28 96.5t-103 37.5q-53 0 -104.5 -25t-96.5 -62.5t-81 -84t-61 -91.5l-135 -655h-153z" />
|
||||||
|
<glyph unicode="o" horiz-adv-x="1019" d="M102 319q0 162 42 296.5t116 230.5t171 149.5t208 53.5q86 0 146.5 -28t98.5 -76t54 -110.5t16 -129.5q0 -154 -40 -287t-110.5 -231.5t-164.5 -155t-205 -56.5q-92 0 -154.5 30t-102.5 79t-57.5 110.5t-17.5 124.5zM266 356q0 -121 45 -185.5t144 -64.5q68 0 128 48.5 t106 130.5t74 187.5t28 219.5q0 104 -38 165t-145 61q-68 0 -129 -46.5t-109 -124t-76 -179t-28 -212.5z" />
|
||||||
|
<glyph unicode="p" horiz-adv-x="1040" d="M-10 -410l305 1434h106l-10 -176h8q29 37 65 72.5t79 64.5t94 46.5t111 17.5q49 0 92 -15.5t75.5 -51.5t52 -95.5t19.5 -145.5q0 -180 -49 -322.5t-129 -240.5t-179.5 -150.5t-197.5 -52.5q-72 0 -126 13.5t-73 27.5l-90 -426h-153zM264 154q35 -27 72 -37.5t80 -10.5 q80 0 152.5 44.5t130 126t91 196.5t33.5 256q0 82 -33.5 135.5t-99.5 53.5q-55 0 -105 -29t-92 -71t-75 -90t-53 -89z" />
|
||||||
|
<glyph unicode="q" horiz-adv-x="1030" d="M94 289q0 137 45 272t125 241.5t190.5 173t243.5 66.5q43 0 87 -6t83 -15t72 -20.5t51 -23.5l-295 -1387h-153l125 582h-9q-25 -33 -56.5 -67.5t-71 -63.5t-89 -47.5t-104.5 -18.5q-66 0 -113 24t-75.5 65.5t-42 99t-13.5 125.5zM258 303q0 -98 32 -147.5t91 -49.5 q51 0 103.5 31t97.5 77t79.5 98.5t55.5 95.5l102 473q-33 18 -79 24t-81 6q-80 0 -152.5 -51t-127.5 -136t-88 -194.5t-33 -226.5z" />
|
||||||
|
<glyph unicode="r" horiz-adv-x="669" d="M74 0l217 1024h106v-176h9q25 39 53 72.5t63 60.5t76 42t90 15q45 0 94 -14l-41 -135q-18 4 -37.5 6t-35.5 2q-104 0 -180 -65.5t-119 -159.5l-142 -672h-153z" />
|
||||||
|
<glyph unicode="s" horiz-adv-x="815" d="M6 41l57 129q41 -27 108 -45.5t138 -18.5q100 0 160.5 44.5t60.5 138.5q0 53 -26.5 90t-67.5 66.5t-88 58t-88 64.5t-67.5 84t-26.5 120q0 57 27.5 107.5t75.5 88.5t115 59.5t144 21.5q109 0 168.5 -14.5t106.5 -41.5l-51 -123q-82 47 -224 48q-86 0 -142 -36t-56 -110 q0 -43 26.5 -74.5t67.5 -60.5t88 -58.5t88 -67.5t67.5 -89t26.5 -121q0 -160 -107.5 -243t-287.5 -83q-92 0 -169 18.5t-124 47.5z" />
|
||||||
|
<glyph unicode="t" horiz-adv-x="641" d="M115 893l30 131h152l43 203l164 47l-53 -250h268l-31 -131h-266l-129 -619q-4 -25 -7 -45t-3 -36q0 -49 22.5 -68t67.5 -19q49 0 90 12.5t82 37.5v-125q-43 -25 -110.5 -40.5t-129.5 -15.5q-186 0 -186 170q0 35 10 86l139 662h-153z" />
|
||||||
|
<glyph unicode="u" horiz-adv-x="1046" d="M123 197q0 72 20 161l140 666h153l-143 -682q-12 -55 -12 -102q0 -57 22.5 -95.5t81.5 -38.5q49 0 99.5 25t96.5 63.5t83.5 86t62.5 92.5l137 651h154l-129 -608q-8 -35 -16.5 -85t-15.5 -105.5t-11 -107.5t-4 -91v-27h-121v195h-8q-31 -41 -71 -80t-88 -70t-103.5 -50.5 t-116.5 -19.5q-45 0 -83 10.5t-66.5 36t-45 67.5t-16.5 108z" />
|
||||||
|
<glyph unicode="v" horiz-adv-x="915" d="M123 1024h164l106 -600l19 -195h4l88 199l346 596h176l-639 -1047h-65z" />
|
||||||
|
<glyph unicode="w" horiz-adv-x="1402" d="M117 1024h155l64 -596l-4 -199h8l82 203l338 592h114l97 -598l8 -197h2l80 201l301 594h156l-551 -1047h-78l-109 676l-2 168h-4l-76 -170l-389 -674h-73z" />
|
||||||
|
<glyph unicode="x" horiz-adv-x="991" d="M-45 0l461 524l-219 500h174l121 -283l36 -116l84 116l248 283h187l-435 -492l244 -532h-174l-139 311l-41 123l-86 -123l-275 -311h-186z" />
|
||||||
|
<glyph unicode="y" horiz-adv-x="899" d="M-41 -401l49 141q23 -8 49 -8q59 0 119 61.5t133 206.5l-176 1024h164l100 -664l11 -196h10l78 198l340 662h163l-483 -913q-53 -100 -105.5 -195.5t-107.5 -170.5t-114.5 -120t-122.5 -45q-35 0 -60.5 4t-46.5 15z" />
|
||||||
|
<glyph unicode="z" horiz-adv-x="878" d="M-4 0l27 141l575 654l113 88h-529l31 141h690l-31 -141l-581 -660l-111 -82h535l-29 -141h-690z" />
|
||||||
|
<glyph unicode="{" horiz-adv-x="667" d="M154 412l30 139q152 0 191 174l106 496q20 96 78.5 155.5t151.5 59.5h166l-31 -144h-98q-53 0 -83 -27.5t-44 -93.5l-101 -485q-18 -90 -69.5 -137t-106.5 -57l-2 -13q41 -6 70.5 -47t27.5 -106q0 -10 -3 -24.5t-12 -65t-31.5 -153.5t-63.5 -290q-2 -12 -4 -22.5 t-2 -20.5q-2 -78 86 -78h96l-33 -143h-166q-72 0 -110.5 40t-36.5 114q0 29 8 59l102 487q8 37 9 66q4 66 -30 91.5t-95 25.5z" />
|
||||||
|
<glyph unicode="|" horiz-adv-x="487" d="M236 -266v1700h141v-1700h-141z" />
|
||||||
|
<glyph unicode="}" horiz-adv-x="677" d="M-129 -471l33 143h96q51 0 81 28t42 93l102 486q20 90 70.5 137t107.5 57l5 12q-45 6 -75 47t-28 107q0 10 2 23.5t4 25.5l105 483q4 12 5 22.5t1 20.5q2 78 -84 78h-94l28 144h166q72 0 112 -39t36 -115q0 -29 -8 -59l-103 -488q-8 -35 -8 -61q-2 -68 31.5 -94.5 t95.5 -26.5l-33 -139q-74 0 -123 -43t-69 -131q0 -2 -5.5 -24.5t-12.5 -57.5l-16 -80l-18 -90q-23 -109 -51 -244q-20 -96 -79.5 -155.5t-151.5 -59.5h-164z" />
|
||||||
|
<glyph unicode="~" horiz-adv-x="983" d="M94 739q88 68 160 94.5t131 26.5q57 0 106.5 -17.5t94.5 -39t88 -38.5t90 -17q39 0 80 16t88 57l69 -125q-78 -53 -140 -74.5t-113 -21.5q-55 0 -101.5 17.5t-88.5 39t-84 39t-91 17.5q-47 0 -100.5 -21.5t-118.5 -75.5z" />
|
||||||
|
<glyph unicode="¡" horiz-adv-x="593" d="M37 -410l151 711l109 361h96l-45 -361l-151 -711h-160zM268 928q0 55 33 87t86 32t86 -32t33 -87q0 -53 -33 -86t-86 -33t-86 33t-33 86z" />
|
||||||
|
<glyph unicode="¢" d="M207 303q0 158 39 286t105.5 223t154.5 153.5t186 74.5l41 189h137l-41 -182q53 -6 93.5 -18.5t74.5 -27.5l-57 -127q-27 16 -65.5 26.5t-86.5 14.5l-170 -804q55 8 110.5 32.5t90.5 46.5l39 -102q-51 -43 -120.5 -69.5t-135.5 -36.5l-39 -187h-135l39 185 q-78 12 -129 46.5t-80 81t-40 97.5t-11 98zM371 367q0 -113 37.5 -175.5t105.5 -78.5l168 796q-61 -16 -117.5 -66t-99.5 -124t-68.5 -165t-25.5 -187z" />
|
||||||
|
<glyph unicode="£" d="M76 0l30 145q61 0 118 31t100 83t68.5 124t25.5 158q0 41 -4 74.5t-11 66.5h-192l31 131h133q-8 37 -12.5 79t-4.5 95q0 117 41 206t110 147.5t161 88t196 29.5q82 0 155 -17.5t120 -43.5l-56 -131q-41 23 -106.5 37t-147.5 14q-63 0 -119.5 -21.5t-98.5 -63.5 t-66.5 -102.5t-24.5 -138.5q0 -63 5 -104t14 -74h317l-31 -131h-256q4 -25 6.5 -55.5t2.5 -71.5q0 -68 -13.5 -125t-33 -103t-44 -80t-47.5 -54l-92 -70l-2 -10l127 28h500l-31 -141h-868z" />
|
||||||
|
<glyph unicode="¤" d="M86 293l158 160l69 45q-63 86 -63 209q0 59 17.5 112t45.5 99l-69 43l-158 159l100 101l160 -158l43 -72q86 68 211 68q121 0 211 -68l45 72l160 158l98 -101l-156 -159l-71 -46q66 -88 65 -208q0 -123 -65 -211l71 -43l156 -160l-98 -98l-160 157l-43 68 q-88 -63 -213 -64q-127 0 -211 64l-43 -68l-160 -157zM391 707q0 -92 58.5 -153.5t150.5 -61.5t151.5 61t59.5 154q0 92 -59.5 154.5t-151.5 62.5t-150.5 -62.5t-58.5 -154.5z" />
|
||||||
|
<glyph unicode="¥" d="M184 297l25 123h240l26 129h-237l26 123h182l-235 762h178l189 -627l6 -125h2l61 129l436 623h185l-551 -762h182l-27 -123h-233l-27 -129h234l-27 -123h-233l-62 -297h-164l62 297h-238z" />
|
||||||
|
<glyph unicode="¦" horiz-adv-x="487" d="M236 -266v688h141v-688h-141zM236 745v689h141v-689h-141z" />
|
||||||
|
<glyph unicode="§" horiz-adv-x="968" d="M98 49l66 125q41 -23 99.5 -41t131.5 -18q82 0 137.5 31.5t55.5 107.5q0 45 -29 75.5t-74 54.5t-99 48.5t-99 57t-76 79.5t-31 121q0 90 44 153.5t114 110.5l94 37q-47 39 -66.5 82t-19.5 94q0 61 28.5 114.5t78 92.5t116 61.5t144.5 22.5q106 0 170.5 -18.5t111.5 -46.5 l-59 -125q-41 23 -101.5 37t-132.5 14q-88 0 -142 -44t-54 -114q0 -43 32.5 -69.5t78 -47t99.5 -41t99 -52t76 -79t31 -122.5q0 -88 -47.5 -158t-112.5 -111l-111 -37q47 -33 72 -75.5t25 -114.5q0 -70 -30 -122t-79 -87t-114.5 -52.5t-139.5 -17.5q-106 0 -173 22.5 t-114 51.5zM344 713q0 -43 18.5 -74t49 -53.5t72.5 -40t89 -35.5q31 12 63 31.5t59.5 46t45 61.5t17.5 78q0 45 -18.5 73.5t-51.5 50t-76 38t-92 37.5q-31 -12 -62.5 -32t-57 -45.5t-41 -59t-15.5 -76.5z" />
|
||||||
|
<glyph unicode="¨" horiz-adv-x="501" d="M399 1337q0 45 26 75t69 30t69.5 -30t26.5 -75q0 -41 -26.5 -70.5t-69.5 -29.5t-69 29.5t-26 70.5zM774 1339q0 43 25.5 73t68.5 30q45 0 71 -30t26 -73t-26 -72.5t-71 -29.5q-43 0 -68.5 29.5t-25.5 72.5z" />
|
||||||
|
<glyph unicode="©" horiz-adv-x="1650" d="M158 594q0 170 57 304t155.5 226.5t229.5 141.5t279 49q147 0 278 -49t229.5 -141.5t155.5 -226.5t57 -304t-57 -304t-155.5 -226.5t-229.5 -141.5t-278 -49q-164 0 -297 49t-227.5 141.5t-145.5 226.5t-51 304zM301 594q0 -141 45 -251t123 -183.5t183.5 -112.5 t226.5 -39t226 39t183 112.5t123 183.5t45 251t-45 250.5t-123 183.5t-183.5 113t-225.5 39q-121 0 -226.5 -39t-183.5 -113t-123 -183.5t-45 -250.5zM535 594q0 186 93 287.5t246 101.5q37 0 67 -4t55.5 -11t50 -17.5t55.5 -22.5l-53 -125q-45 23 -86 31t-70 8 q-86 0 -140.5 -53.5t-54.5 -194.5q0 -119 53.5 -183.5t157.5 -66.5q96 0 164 37l43 -121q-47 -27 -105.5 -41t-136.5 -14q-166 0 -252.5 104.5t-86.5 284.5z" />
|
||||||
|
<glyph unicode="ª" horiz-adv-x="780" d="M123 946q0 63 29.5 108.5t79 75t114 43t135.5 13.5q29 0 57.5 -2t57.5 -6q12 39 12 69q0 88 -116 88q-78 0 -132.5 -15t-95.5 -34l-10 100q53 27 126 45.5t171 18.5q96 0 146.5 -43t50.5 -109q0 -51 -15.5 -117.5t-35 -138t-35 -140t-15.5 -124.5h-102l-6 94h-7 q-35 -35 -88 -68.5t-137 -33.5q-92 0 -138 52t-46 124zM264 961q0 -33 20.5 -54.5t65.5 -21.5q84 0 132 38t73 74l16 86q-20 2 -39.5 2h-42.5q-43 0 -82.5 -5t-71.5 -18t-51.5 -38t-19.5 -63z" />
|
||||||
|
<glyph unicode="«" horiz-adv-x="929" d="M78 530l409 471l93 -96l-254 -297l-117 -76l72 -75l137 -291l-111 -88zM434 530l406 467l90 -94l-252 -295l-115 -76l70 -75l137 -289l-111 -86z" />
|
||||||
|
<glyph unicode="¬" horiz-adv-x="1034" d="M137 655v148h869v-393h-144v245h-725z" />
|
||||||
|
<glyph unicode="­" horiz-adv-x="700" d="M129 520l33 139h471l-35 -139h-469z" />
|
||||||
|
<glyph unicode="®" horiz-adv-x="1433" d="M281 924q0 131 43 232t117.5 170t173 104.5t208.5 35.5q113 0 212.5 -35.5t173 -104.5t115.5 -170t42 -232t-43 -232.5t-118 -170t-173 -104.5t-209 -36q-115 0 -213 36t-171.5 104.5t-115.5 170t-42 232.5zM410 924q0 -106 32.5 -185.5t89 -131.5t132 -78.5t159.5 -26.5 q88 0 164 25.5t131.5 77.5t87 131t31.5 188q0 106 -33 185t-89 131t-131 79t-161 27q-90 0 -165.5 -27t-131 -79t-86 -131t-30.5 -185zM612 659v531q33 10 92.5 15t112.5 5q86 0 147.5 -35.5t61.5 -123.5q0 -66 -42 -101t-103 -39l57 -28l152 -224h-125l-148 213l-98 31 v-244h-107zM719 965h69q59 0 92 18t33 64q1 71 -118 71q-23 0 -43.5 -1t-32.5 -7v-145z" />
|
||||||
|
<glyph unicode="¯" horiz-adv-x="641" d="M635 1190l29 127h575l-27 -127h-577z" />
|
||||||
|
<glyph unicode="°" horiz-adv-x="870" d="M289 1169q0 63 22.5 116.5t61.5 91.5t92 59.5t113 21.5q59 0 112 -19.5t92 -57.5t61.5 -91t22.5 -121t-22.5 -121t-61.5 -90.5t-92 -57t-112 -19.5t-112.5 19.5t-92.5 57t-61.5 90.5t-22.5 121zM420 1169q0 -78 47 -121.5t111 -43.5q63 0 110 44t47 121q0 78 -47 122 t-110 44t-110.5 -44t-47.5 -122z" />
|
||||||
|
<glyph unicode="±" horiz-adv-x="983" d="M113 365v147h868v-147h-868zM113 862v148h360v370h148v-370h360v-148h-360v-246h-148v246h-360z" />
|
||||||
|
<glyph unicode="²" horiz-adv-x="772" d="M182 778l15 68q37 27 89 66.5t109.5 89t112.5 104.5t100 111.5t73 109.5t28 100q0 94 -113 95q-53 0 -106.5 -19.5t-94.5 -44.5l-18 117q57 37 129 57.5t141 20.5q37 0 74 -9.5t65.5 -32t47 -59.5t18.5 -92q0 -66 -29.5 -132t-80 -133t-116 -129.5t-134.5 -119.5 l-103 -63v-6l117 32h268l-28 -131h-564z" />
|
||||||
|
<glyph unicode="³" horiz-adv-x="772" d="M236 803l53 123q29 -16 72 -27.5t96 -11.5q115 0 169 56t54 134q0 55 -32.5 83t-131.5 28h-106l8 47l237 240l78 53l-98 -13h-248l27 123h497l-14 -67l-254 -254l-53 -37l-2 -4l45 6q78 0 132 -50t54 -136q0 -66 -20.5 -126.5t-65.5 -106.5t-117.5 -72.5t-179.5 -26.5 q-70 0 -118 12t-82 27z" />
|
||||||
|
<glyph unicode="´" horiz-adv-x="487" d="M690 1169l180 306h172l-10 -43l-252 -263h-90z" />
|
||||||
|
<glyph unicode="¶" horiz-adv-x="1013" d="M154 1036q0 76 23.5 147.5t68.5 127t110.5 89.5t147.5 34h92v-1700h-141v901q-66 0 -121 33.5t-95 90t-62.5 129.5t-22.5 148zM774 -266v1700h141v-1700h-141z" />
|
||||||
|
<glyph unicode="·" horiz-adv-x="546" d="M201 606q0 55 32.5 87t85.5 32t86 -31.5t33 -87.5q0 -53 -32.5 -86t-86.5 -33q-53 0 -85.5 33t-32.5 86z" />
|
||||||
|
<glyph unicode="¸" horiz-adv-x="743" d="M485 -418l35 80q10 -2 21.5 -2h21.5q43 0 72 8t45 19.5t22.5 26t6.5 26.5q0 39 -43 57.5t-115 18.5l133 184h109l-68 -88q55 -6 91 -42t36 -101q0 -86 -64.5 -141.5t-193.5 -55.5q-25 0 -52.5 3t-56.5 7z" />
|
||||||
|
<glyph unicode="¹" horiz-adv-x="772" d="M238 778l26 125h207l111 520l28 74l-63 -57l-166 -92l-43 94l348 211h80l-160 -750h185l-27 -125h-526z" />
|
||||||
|
<glyph unicode="º" horiz-adv-x="776" d="M123 1004q0 119 36 204.5t91 141t122.5 82t133.5 26.5q117 0 177 -63.5t60 -180.5q0 -111 -30.5 -194.5t-82.5 -141t-123 -87t-149 -29.5q-104 0 -169.5 63.5t-65.5 178.5zM264 1020q0 -66 30 -102.5t89 -36.5q43 0 83 22.5t70.5 64.5t48 102t17.5 136q0 72 -31.5 102.5 t-89.5 30.5q-43 0 -83 -25.5t-69.5 -68.5t-47 -101t-17.5 -124z" />
|
||||||
|
<glyph unicode="»" horiz-adv-x="929" d="M78 174l252 295l114 78l-71 88l-140 289l117 73l223 -448l-405 -467zM428 172l254 297l115 78l-72 90l-141 291l118 73l228 -452l-410 -471z" />
|
||||||
|
<glyph unicode="¼" horiz-adv-x="1632" d="M276 1243l355 205h80l-187 -875h-135l135 646l31 73l-64 -57l-165 -92zM312 49l997 1411l107 -74l-998 -1411zM838 197l14 76l569 618h88l-121 -573h162l-26 -121h-160l-43 -197h-131l43 197h-395zM1005 307l101 11h151l56 262l34 100h-4l-63 -94l-197 -215z" />
|
||||||
|
<glyph unicode="½" horiz-adv-x="1656" d="M276 1243l355 205h80l-187 -875h-135l135 646l31 73l-64 -57l-165 -92zM312 49l997 1411l107 -74l-998 -1411zM936 0l15 68q37 27 89 66.5t109.5 89t112.5 104.5t100 111.5t73 109.5t28 100q0 94 -113 95q-53 0 -106.5 -19.5t-94.5 -44.5l-18 117q57 37 129 57.5 t141 20.5q37 0 74 -9.5t65.5 -32t47 -59.5t18.5 -92q0 -66 -29.5 -132t-80 -133t-116 -129.5t-134.5 -119.5l-103 -63v-6l117 32h268l-28 -131h-564z" />
|
||||||
|
<glyph unicode="¾" horiz-adv-x="1705" d="M207 598l53 123q29 -16 72 -27.5t96 -11.5q115 0 169 56t54 134q0 55 -32.5 83t-131.5 28h-106l8 47l237 240l78 53l-98 -13h-248l27 123h497l-14 -67l-254 -254l-53 -37l-2 -4l45 6q78 0 132 -50t54 -136q0 -66 -20.5 -126.5t-65.5 -106.5t-117.5 -72.5t-179.5 -26.5 q-70 0 -118 12t-82 27zM385 49l997 1411l107 -74l-998 -1411zM912 197l14 76l569 618h88l-121 -573h162l-26 -121h-160l-43 -197h-131l43 197h-395zM1079 307l101 11h151l56 262l34 100h-4l-63 -94l-197 -215z" />
|
||||||
|
<glyph unicode="¿" horiz-adv-x="845" d="M-29 -184q0 111 35 191.5t88 144t117.5 118t123 111.5t102.5 123.5t59 157.5h131q-10 -102 -51 -179t-96.5 -139.5t-116 -116t-110.5 -109t-84 -116.5t-34 -141t42 -122t147 -42q72 0 141.5 27.5t128.5 62.5l41 -119q-41 -25 -80 -43t-82 -31.5t-93 -20.5t-114 -7 q-152 0 -223.5 69.5t-71.5 180.5zM479 930q0 55 33 87t86 32t86 -32t33 -87q0 -53 -33 -86t-86 -33t-86 33t-33 86z" />
|
||||||
|
<glyph unicode="À" horiz-adv-x="1140" d="M-68 0l828 1456h76l206 -1456h-157l-58 397h-499l-222 -397h-174zM408 545h403l-59 436l-4 217h-3l-92 -221zM540 1739l9 43h206l179 -242h-129z" />
|
||||||
|
<glyph unicode="Á" horiz-adv-x="1140" d="M-68 0l828 1456h76l206 -1456h-157l-58 397h-499l-222 -397h-174zM408 545h403l-59 436l-4 217h-3l-92 -221zM675 1540l281 242h237l-10 -43l-358 -199h-150z" />
|
||||||
|
<glyph unicode="Â" horiz-adv-x="1140" d="M-68 0l828 1456h76l206 -1456h-157l-58 397h-499l-222 -397h-174zM408 545h403l-59 436l-4 217h-3l-92 -221zM493 1530l10 45l301 207h99l203 -209l-9 -43h-139l-94 100l-21 72l-51 -70l-145 -102h-154z" />
|
||||||
|
<glyph unicode="Ã" horiz-adv-x="1140" d="M-68 0l828 1456h76l206 -1456h-157l-58 397h-499l-222 -397h-174zM408 545h403l-59 436l-4 217h-3l-92 -221zM526 1608q72 66 128.5 89t103.5 23q37 0 68.5 -10t61.5 -23.5t58.5 -23.5t59.5 -10q51 0 108 43l33 -88q-66 -53 -116 -71.5t-91 -18.5q-37 0 -67.5 10 t-60.5 23.5t-58.5 23.5t-59.5 10t-64.5 -13t-74.5 -48z" />
|
||||||
|
<glyph unicode="Ä" horiz-adv-x="1140" d="M-68 0l828 1456h76l206 -1456h-157l-58 397h-499l-222 -397h-174zM408 545h403l-59 436l-4 217h-3l-92 -221zM539 1626q0 41 28.5 68.5t75.5 27.5t75 -27.5t28 -68.5t-28 -67.5t-75 -26.5t-75.5 26.5t-28.5 67.5zM914 1626q0 41 27.5 68.5t74.5 27.5t75.5 -27.5 t28.5 -68.5t-28.5 -67.5t-75.5 -26.5t-74.5 26.5t-27.5 67.5z" />
|
||||||
|
<glyph unicode="Å" horiz-adv-x="1140" d="M-68 0l803 1413q-129 35 -129 160q0 76 51.5 125t163.5 49q102 0 159.5 -44t57.5 -130q0 -72 -49 -118t-147 -52l200 -1403h-157l-58 397h-499l-222 -397h-174zM408 543h403l-59 438l-4 217h-3l-92 -221zM731 1573q0 -35 21.5 -58.5t68.5 -23.5q45 0 68.5 22.5t23.5 59.5 q0 39 -22.5 62.5t-69.5 23.5q-45 0 -67.5 -23.5t-22.5 -62.5z" />
|
||||||
|
<glyph unicode="Æ" horiz-adv-x="1648" d="M-127 0l1108 1434h750l-31 -150h-580l-100 -471h530l-32 -149h-529l-110 -514h589l-30 -150h-588h-164l86 403h-407l-304 -403h-188zM479 551h322l145 676h-6l-104 -207z" />
|
||||||
|
<glyph unicode="Ç" horiz-adv-x="1114" d="M145 561q0 231 68 400t178.5 280t248.5 164t280 53q117 0 190.5 -16.5t120.5 -38.5l-74 -150q-41 23 -107.5 38.5t-152.5 15.5q-115 0 -220.5 -50.5t-185 -144.5t-127 -229t-47.5 -303q0 -98 26 -181.5t74 -143.5t118.5 -94t160.5 -34q96 0 160 21.5t115 50.5l12 -140 q-66 -45 -140.5 -63.5t-170.5 -20.5l-49 -63q55 -6 91 -42t36 -101q0 -86 -64.5 -141.5t-193.5 -55.5q-25 0 -52.5 3t-56.5 7l35 80q10 -2 21.5 -2h21.5q43 0 71.5 8t45 19.5t22.5 26t6 26.5q0 39 -43 57.5t-114 18.5l118 166q-100 14 -178 64t-132 126t-83 175t-29 214z " />
|
||||||
|
<glyph unicode="È" horiz-adv-x="1044" d="M82 0l305 1434h739l-30 -152h-580l-100 -469h530l-31 -151h-530l-109 -510h590l-32 -152h-590h-162zM473 1739l9 43h206l179 -242h-129z" />
|
||||||
|
<glyph unicode="É" horiz-adv-x="1044" d="M82 0l305 1434h739l-30 -152h-580l-100 -469h530l-31 -151h-530l-109 -510h590l-32 -152h-590h-162zM643 1540l281 242h237l-10 -43l-358 -199h-150z" />
|
||||||
|
<glyph unicode="Ê" horiz-adv-x="1044" d="M82 0l305 1434h739l-30 -152h-580l-100 -469h530l-31 -151h-530l-109 -510h590l-32 -152h-590h-162zM471 1530l10 45l301 207h99l203 -209l-9 -43h-139l-94 100l-21 72l-51 -70l-145 -102h-154z" />
|
||||||
|
<glyph unicode="Ë" horiz-adv-x="1044" d="M82 0l305 1434h739l-30 -152h-580l-100 -469h530l-31 -151h-530l-109 -510h590l-32 -152h-590h-162zM492 1626q0 41 28.5 68.5t75.5 27.5t75 -27.5t28 -68.5t-28 -67.5t-75 -26.5t-75.5 26.5t-28.5 67.5zM867 1626q0 41 27.5 68.5t74.5 27.5t75.5 -27.5t28.5 -68.5 t-28.5 -67.5t-75.5 -26.5t-74.5 26.5t-27.5 67.5z" />
|
||||||
|
<glyph unicode="Ì" horiz-adv-x="567" d="M127 0l303 1434h164l-303 -1434h-164zM256 1739l9 43h206l179 -242h-129z" />
|
||||||
|
<glyph unicode="Í" horiz-adv-x="567" d="M127 0l303 1434h164l-303 -1434h-164zM387 1540l281 242h237l-10 -43l-358 -199h-150z" />
|
||||||
|
<glyph unicode="Î" horiz-adv-x="567" d="M127 0l303 1434h164l-303 -1434h-164zM227 1530l10 45l301 207h99l203 -209l-9 -43h-139l-94 100l-21 72l-51 -70l-145 -102h-154z" />
|
||||||
|
<glyph unicode="Ï" horiz-adv-x="567" d="M127 0l303 1434h164l-303 -1434h-164zM254 1626q0 41 28.5 68.5t75.5 27.5t75 -27.5t28 -68.5t-28 -67.5t-75 -26.5t-75.5 26.5t-28.5 67.5zM629 1626q0 41 27.5 68.5t74.5 27.5t75.5 -27.5t28.5 -68.5t-28.5 -67.5t-75.5 -26.5t-74.5 26.5t-27.5 67.5z" />
|
||||||
|
<glyph unicode="Ð" horiz-adv-x="1282" d="M57 680l27 123h176l135 631q78 10 176.5 13t178.5 3q119 0 217 -32t166.5 -97.5t105.5 -165.5t37 -235q0 -90 -16.5 -196t-54.5 -209t-101.5 -199.5t-157.5 -171t-220 -118.5t-292 -44q-31 0 -81 1t-103 3q-139 8 -160 12l146 682h-179zM285 141q8 -2 32.5 -3t52 -2 t53.5 -2t36 -1q178 0 300 74t198.5 186.5t111.5 247.5t35 256q0 92 -20.5 166t-64.5 126t-114 80.5t-168 28.5q-25 0 -55.5 -1t-59 -2t-55 -3t-41.5 -4l-102 -485h281l-25 -123h-283z" />
|
||||||
|
<glyph unicode="Ñ" horiz-adv-x="1314" d="M82 0l309 1456h82l447 -958l67 -201h8l19 201l200 936h154l-309 -1457h-76l-448 961l-70 211h-6l-25 -211l-198 -938h-154zM591 1608q72 66 128.5 89t103.5 23q37 0 68.5 -10t61.5 -23.5t58.5 -23.5t59.5 -10q51 0 108 43l33 -88q-66 -53 -116 -71.5t-91 -18.5 q-37 0 -67.5 10t-60.5 23.5t-58.5 23.5t-59.5 10t-64.5 -13t-74.5 -48z" />
|
||||||
|
<glyph unicode="Ò" horiz-adv-x="1333" d="M145 524q0 188 51.5 358.5t146.5 298.5t229.5 202.5t297.5 74.5q98 0 182.5 -29.5t144.5 -94t94 -167t34 -249.5q0 -193 -51 -364t-143.5 -300t-220.5 -204t-281 -75q-242 0 -363 140.5t-121 408.5zM317 526q0 -193 80 -298t236 -105q115 0 210 63.5t164.5 172t107.5 252 t38 302.5q0 119 -26.5 197t-70.5 122t-100.5 61.5t-113.5 17.5q-117 0 -213.5 -64.5t-165 -173t-107.5 -251t-39 -296.5zM637 1739l9 43h206l179 -242h-129z" />
|
||||||
|
<glyph unicode="Ó" horiz-adv-x="1333" d="M145 524q0 188 51.5 358.5t146.5 298.5t229.5 202.5t297.5 74.5q98 0 182.5 -29.5t144.5 -94t94 -167t34 -249.5q0 -193 -51 -364t-143.5 -300t-220.5 -204t-281 -75q-242 0 -363 140.5t-121 408.5zM317 526q0 -193 80 -298t236 -105q115 0 210 63.5t164.5 172t107.5 252 t38 302.5q0 119 -26.5 197t-70.5 122t-100.5 61.5t-113.5 17.5q-117 0 -213.5 -64.5t-165 -173t-107.5 -251t-39 -296.5zM809 1540l281 242h237l-10 -43l-358 -199h-150z" />
|
||||||
|
<glyph unicode="Ô" horiz-adv-x="1333" d="M145 524q0 188 51.5 358.5t146.5 298.5t229.5 202.5t297.5 74.5q98 0 182.5 -29.5t144.5 -94t94 -167t34 -249.5q0 -193 -51 -364t-143.5 -300t-220.5 -204t-281 -75q-242 0 -363 140.5t-121 408.5zM317 526q0 -193 80 -298t236 -105q115 0 210 63.5t164.5 172t107.5 252 t38 302.5q0 119 -26.5 197t-70.5 122t-100.5 61.5t-113.5 17.5q-117 0 -213.5 -64.5t-165 -173t-107.5 -251t-39 -296.5zM604 1530l10 45l301 207h99l203 -209l-9 -43h-139l-94 100l-21 72l-51 -70l-145 -102h-154z" />
|
||||||
|
<glyph unicode="Õ" horiz-adv-x="1333" d="M145 524q0 188 51.5 358.5t146.5 298.5t229.5 202.5t297.5 74.5q98 0 182.5 -29.5t144.5 -94t94 -167t34 -249.5q0 -193 -51 -364t-143.5 -300t-220.5 -204t-281 -75q-242 0 -363 140.5t-121 408.5zM317 526q0 -193 80 -298t236 -105q115 0 210 63.5t164.5 172t107.5 252 t38 302.5q0 119 -26.5 197t-70.5 122t-100.5 61.5t-113.5 17.5q-117 0 -213.5 -64.5t-165 -173t-107.5 -251t-39 -296.5zM610 1608q72 66 128.5 89t103.5 23q37 0 68.5 -10t61.5 -23.5t58.5 -23.5t59.5 -10q51 0 108 43l33 -88q-66 -53 -116 -71.5t-91 -18.5q-37 0 -67.5 10 t-60.5 23.5t-58.5 23.5t-59.5 10t-64.5 -13t-74.5 -48z" />
|
||||||
|
<glyph unicode="Ö" horiz-adv-x="1333" d="M145 524q0 188 51.5 358.5t146.5 298.5t229.5 202.5t297.5 74.5q98 0 182.5 -29.5t144.5 -94t94 -167t34 -249.5q0 -193 -51 -364t-143.5 -300t-220.5 -204t-281 -75q-242 0 -363 140.5t-121 408.5zM317 526q0 -193 80 -298t236 -105q115 0 210 63.5t164.5 172t107.5 252 t38 302.5q0 119 -26.5 197t-70.5 122t-100.5 61.5t-113.5 17.5q-117 0 -213.5 -64.5t-165 -173t-107.5 -251t-39 -296.5zM629 1626q0 41 28.5 68.5t75.5 27.5t75 -27.5t28 -68.5t-28 -67.5t-75 -26.5t-75.5 26.5t-28.5 67.5zM1004 1626q0 41 27.5 68.5t74.5 27.5t75.5 -27.5 t28.5 -68.5t-28.5 -67.5t-75.5 -26.5t-74.5 26.5t-27.5 67.5z" />
|
||||||
|
<glyph unicode="×" horiz-adv-x="983" d="M178 430l260 264l-260 256l105 109l260 -260l260 260l104 -109l-258 -256l258 -260l-104 -106l-260 260l-258 -262z" />
|
||||||
|
<glyph unicode="Ø" horiz-adv-x="1333" d="M145 524q0 188 51.5 358.5t146.5 298.5t229.5 202.5t297.5 74.5q80 0 151 -19.5t126 -60.5l59 80l101 -78l-72 -96q43 -63 66.5 -153.5t23.5 -212.5q0 -193 -51 -364t-143.5 -300t-220.5 -204t-281 -75q-180 0 -297 82l-60 -80l-102 80l70 95q-95 132 -95 372zM317 526 q0 -129 37 -221l690 934q-43 39 -95 55.5t-107 16.5q-117 0 -213.5 -64.5t-165 -173t-107.5 -251t-39 -296.5zM430 193q80 -70 203 -70q115 0 210 63.5t164.5 172t107.5 251.5t38 303q0 66 -8 119t-25 94z" />
|
||||||
|
<glyph unicode="Ù" horiz-adv-x="1265" d="M178 338q0 84 23 190l190 906h164l-190 -908q-23 -90 -23 -164q0 -129 67.5 -179t200.5 -50q80 0 140.5 22.5t104.5 69.5t73.5 121t52.5 178l193 910h155l-201 -957q-29 -131 -71.5 -225t-107 -153.5t-154.5 -88t-209 -28.5q-113 0 -191 25.5t-126 71.5t-69.5 112.5 t-21.5 146.5zM628 1739l9 43h206l179 -242h-129z" />
|
||||||
|
<glyph unicode="Ú" horiz-adv-x="1265" d="M178 338q0 84 23 190l190 906h164l-190 -908q-23 -90 -23 -164q0 -129 67.5 -179t200.5 -50q80 0 140.5 22.5t104.5 69.5t73.5 121t52.5 178l193 910h155l-201 -957q-29 -131 -71.5 -225t-107 -153.5t-154.5 -88t-209 -28.5q-113 0 -191 25.5t-126 71.5t-69.5 112.5 t-21.5 146.5zM759 1540l281 242h237l-10 -43l-358 -199h-150z" />
|
||||||
|
<glyph unicode="Û" horiz-adv-x="1265" d="M178 338q0 84 23 190l190 906h164l-190 -908q-23 -90 -23 -164q0 -129 67.5 -179t200.5 -50q80 0 140.5 22.5t104.5 69.5t73.5 121t52.5 178l193 910h155l-201 -957q-29 -131 -71.5 -225t-107 -153.5t-154.5 -88t-209 -28.5q-113 0 -191 25.5t-126 71.5t-69.5 112.5 t-21.5 146.5zM579 1530l10 45l301 207h99l203 -209l-9 -43h-139l-94 100l-21 72l-51 -70l-145 -102h-154z" />
|
||||||
|
<glyph unicode="Ü" horiz-adv-x="1265" d="M178 338q0 84 23 190l190 906h164l-190 -908q-23 -90 -23 -164q0 -129 67.5 -179t200.5 -50q80 0 140.5 22.5t104.5 69.5t73.5 121t52.5 178l193 910h155l-201 -957q-29 -131 -71.5 -225t-107 -153.5t-154.5 -88t-209 -28.5q-113 0 -191 25.5t-126 71.5t-69.5 112.5 t-21.5 146.5zM606 1626q0 41 28.5 68.5t75.5 27.5t75 -27.5t28 -68.5t-28 -67.5t-75 -26.5t-75.5 26.5t-28.5 67.5zM981 1626q0 41 27.5 68.5t74.5 27.5t75.5 -27.5t28.5 -68.5t-28.5 -67.5t-75.5 -26.5t-74.5 26.5t-27.5 67.5z" />
|
||||||
|
<glyph unicode="Ý" horiz-adv-x="1087" d="M221 1434h178l183 -627l6 -125h2l61 129l445 623h184l-623 -863l-120 -571h-164l121 569zM690 1540l281 242h237l-10 -43l-358 -199h-150z" />
|
||||||
|
<glyph unicode="Þ" horiz-adv-x="1089" d="M82 0l305 1434h162l-33 -154q82 6 166 6q94 0 174 -20.5t139.5 -65.5t94 -115.5t34.5 -169.5q0 -156 -55 -260t-147.5 -167.5t-207 -90t-231.5 -26.5h-31.5t-46 1t-47 3t-32.5 4l-80 -379h-164zM358 530q8 -4 28 -5t41.5 -3t41.5 -2h31q88 0 170 18.5t145.5 62.5t100 117 t36.5 181q0 74 -24.5 120t-66.5 71.5t-97.5 36t-116.5 10.5q-47 0 -91 -3.5t-73 -9.5z" />
|
||||||
|
<glyph unicode="ß" horiz-adv-x="1144" d="M-233 -385l45 115q41 -14 74.5 -18.5t82.5 -4.5q78 0 117 80t61 213l168 893h-176l27 131h176l14 57q41 195 153 280t282 85q86 0 145 -20.5t96 -54.5t54.5 -78t17.5 -89q0 -72 -25.5 -121t-63.5 -85.5t-83 -64.5t-83 -55.5t-63.5 -58.5t-25.5 -74q0 -39 23.5 -62.5 t59.5 -41.5t78 -37.5t77.5 -50.5t59 -77t23.5 -120q0 -80 -35.5 -149.5t-96 -120.5t-141.5 -81t-171 -30q-72 0 -133.5 13.5t-110.5 44.5l74 137q82 -51 186 -51q43 0 90.5 15.5t85 44t63.5 70.5t26 97q0 47 -24 78t-59.5 53.5t-76.5 42t-78 47t-60.5 68.5t-23.5 104 q0 61 25.5 104.5t64.5 78t84 63.5t84 57.5t62.5 61.5t23.5 76q0 61 -45 92t-127 31q-223 2 -270 -283l-197 -1020q-18 -113 -43 -192.5t-61.5 -132t-90 -77t-129.5 -24.5q-61 0 -113 9t-97 32z" />
|
||||||
|
<glyph unicode="à" horiz-adv-x="997" d="M92 293q0 131 34 266t104.5 243.5t182 178.5t269.5 70q57 0 140 -13.5t155 -36.5l-129 -598q-16 -76 -22.5 -153.5t-6.5 -145.5v-58.5t4 -49.5h-114l-29 178h-8q-25 -35 -61 -70.5t-79 -64.5t-92 -46.5t-104 -17.5q-244 0 -244 318zM256 293q0 -78 30.5 -132.5 t96.5 -54.5q49 0 94 24t85 58.5t71 74.5t49 75l115 553q-61 29 -156 29q-94 0 -166 -55.5t-121 -144.5t-73.5 -201.5t-24.5 -225.5zM483 1432l8 43h187l59 -306h-88z" />
|
||||||
|
<glyph unicode="á" horiz-adv-x="997" d="M92 293q0 131 34 266t104.5 243.5t182 178.5t269.5 70q57 0 140 -13.5t155 -36.5l-129 -598q-16 -76 -22.5 -153.5t-6.5 -145.5v-58.5t4 -49.5h-114l-29 178h-8q-25 -35 -61 -70.5t-79 -64.5t-92 -46.5t-104 -17.5q-244 0 -244 318zM256 293q0 -78 30.5 -132.5 t96.5 -54.5q49 0 94 24t85 58.5t71 74.5t49 75l115 553q-61 29 -156 29q-94 0 -166 -55.5t-121 -144.5t-73.5 -201.5t-24.5 -225.5zM624 1169l180 306h172l-10 -43l-252 -263h-90z" />
|
||||||
|
<glyph unicode="â" horiz-adv-x="997" d="M92 293q0 131 34 266t104.5 243.5t182 178.5t269.5 70q57 0 140 -13.5t155 -36.5l-129 -598q-16 -76 -22.5 -153.5t-6.5 -145.5v-58.5t4 -49.5h-114l-29 178h-8q-25 -35 -61 -70.5t-79 -64.5t-92 -46.5t-104 -17.5q-244 0 -244 318zM256 293q0 -78 30.5 -132.5 t96.5 -54.5q49 0 94 24t85 58.5t71 74.5t49 75l115 553q-61 29 -156 29q-94 0 -166 -55.5t-121 -144.5t-73.5 -201.5t-24.5 -225.5zM416 1126l319 373h62l135 -373h-129l-49 136l-13 118l-69 -118l-117 -136h-139z" />
|
||||||
|
<glyph unicode="ã" horiz-adv-x="997" d="M92 293q0 131 34 266t104.5 243.5t182 178.5t269.5 70q57 0 140 -13.5t155 -36.5l-129 -598q-16 -76 -22.5 -153.5t-6.5 -145.5v-58.5t4 -49.5h-114l-29 178h-8q-25 -35 -61 -70.5t-79 -64.5t-92 -46.5t-104 -17.5q-244 0 -244 318zM256 293q0 -78 30.5 -132.5 t96.5 -54.5q49 0 94 24t85 58.5t71 74.5t49 75l115 553q-61 29 -156 29q-94 0 -166 -55.5t-121 -144.5t-73.5 -201.5t-24.5 -225.5zM447 1343q66 68 113.5 93.5t84.5 25.5q31 0 55.5 -13t48 -28.5t47 -28t52.5 -12.5q47 0 111 50l30 -89q-59 -59 -102 -81.5t-78 -22.5 q-31 0 -55.5 12.5t-48 27.5t-48 27.5t-55.5 12.5q-27 0 -57.5 -13.5t-71.5 -46.5z" />
|
||||||
|
<glyph unicode="ä" horiz-adv-x="997" d="M92 293q0 131 34 266t104.5 243.5t182 178.5t269.5 70q57 0 140 -13.5t155 -36.5l-129 -598q-16 -76 -22.5 -153.5t-6.5 -145.5v-58.5t4 -49.5h-114l-29 178h-8q-25 -35 -61 -70.5t-79 -64.5t-92 -46.5t-104 -17.5q-244 0 -244 318zM256 293q0 -78 30.5 -132.5 t96.5 -54.5q49 0 94 24t85 58.5t71 74.5t49 75l115 553q-61 29 -156 29q-94 0 -166 -55.5t-121 -144.5t-73.5 -201.5t-24.5 -225.5zM381 1337q0 45 26 75t69 30t69.5 -30t26.5 -75q0 -41 -26.5 -70.5t-69.5 -29.5t-69 29.5t-26 70.5zM756 1339q0 43 25.5 73t68.5 30 q45 0 71 -30t26 -73t-26 -72.5t-71 -29.5q-43 0 -68.5 29.5t-25.5 72.5z" />
|
||||||
|
<glyph unicode="å" horiz-adv-x="997" d="M92 293q0 131 34 266t104.5 243.5t182 178.5t269.5 70q57 0 140 -13.5t155 -36.5l-129 -598q-16 -76 -22.5 -153.5t-6.5 -145.5v-58.5t4 -49.5h-114l-29 178h-8q-25 -35 -61 -70.5t-79 -64.5t-92 -46.5t-104 -17.5q-244 0 -244 318zM256 293q0 -78 30.5 -132.5 t96.5 -54.5q49 0 94 24t85 58.5t71 74.5t49 75l115 553q-61 29 -156 29q-94 0 -166 -55.5t-121 -144.5t-73.5 -201.5t-24.5 -225.5zM516 1317q0 86 54 136t145 50q86 0 143 -45t57 -141q0 -80 -57 -132t-143 -52t-142.5 48t-56.5 136zM627 1317q0 -41 27.5 -63.5t60.5 -22.5 q39 0 64.5 20.5t25.5 65.5t-28 66.5t-62 21.5q-35 0 -61.5 -20.5t-26.5 -67.5z" />
|
||||||
|
<glyph unicode="æ" horiz-adv-x="1544" d="M57 227q0 104 45 175t122 113t179.5 60.5t214.5 18.5h46.5t46.5 -2q41 133 41 199t-39 92t-129 26q-33 0 -73 -5t-81 -15t-79 -23.5t-68 -27.5l-25 123q86 47 187.5 63t205.5 16q98 0 160.5 -34.5t77.5 -100.5q66 76 159 110t179 34q152 0 225.5 -67t73.5 -165 q0 -109 -50.5 -174t-140.5 -102t-217 -50.5t-278 -15.5q-6 -35 -10.5 -65.5t-4.5 -59.5q0 -113 57.5 -178.5t194.5 -65.5q66 0 136.5 26t113.5 56l35 -110q-70 -49 -165 -76t-193 -27q-119 0 -200 54.5t-110 148.5h-14q-66 -80 -163 -137t-214 -57q-63 0 -109.5 20.5t-77 54 t-45 77.5t-14.5 91zM221 262q0 -78 35.5 -112.5t103.5 -34.5q55 0 105.5 26.5t91.5 62.5t70.5 71.5t44.5 58.5l16 139q-23 2 -47.5 3t-46.5 1q-78 0 -146.5 -12t-118.5 -39t-79 -67t-29 -97zM864 600q100 0 191.5 5t161 24.5t110.5 58.5t41 107q0 51 -34 87t-132 36 q-125 0 -209 -82t-129 -236z" />
|
||||||
|
<glyph unicode="ç" horiz-adv-x="860" d="M102 303q0 174 47.5 312.5t126 234.5t181 147.5t211.5 51.5q78 0 128 -14.5t91 -33.5l-58 -127q-35 20 -86 32t-110 12q-70 0 -136.5 -47.5t-117.5 -124t-82 -176t-31 -203.5q0 -133 55.5 -197t149.5 -64q61 0 129 28t109 56l39 -102q-53 -45 -126 -74.5t-139 -38.5 l-51 -63q55 -6 91 -42t36 -101q0 -86 -64.5 -141.5t-193.5 -55.5q-25 0 -52.5 3t-55.5 7l34 80q10 -2 21.5 -2h21.5q43 0 72 8t45 19.5t22.5 26t6.5 26.5q0 39 -43 57.5t-115 18.5l117 159q-82 8 -135.5 43t-84 83.5t-42 101.5t-11.5 100z" />
|
||||||
|
<glyph unicode="è" horiz-adv-x="948" d="M102 332q0 168 47.5 301t124 225t174 141.5t199.5 49.5q74 0 128 -20.5t89 -54.5t51.5 -78t16.5 -93q0 -145 -141.5 -228t-411.5 -83q-25 0 -51.5 1t-55.5 3q-8 -39 -12 -74t-4 -62q0 -113 51 -183.5t160 -70.5q90 0 165 30t116 63l49 -99q-72 -61 -169.5 -93t-195.5 -32 q-164 0 -247 94.5t-83 262.5zM301 610q78 0 162 4t152.5 21.5t113.5 55.5t45 106q0 20 -7 41.5t-23.5 39t-46 29t-74.5 11.5q-113 0 -196 -77t-126 -231zM450 1432l8 43h187l59 -306h-88z" />
|
||||||
|
<glyph unicode="é" horiz-adv-x="948" d="M102 332q0 168 47.5 301t124 225t174 141.5t199.5 49.5q74 0 128 -20.5t89 -54.5t51.5 -78t16.5 -93q0 -145 -141.5 -228t-411.5 -83q-25 0 -51.5 1t-55.5 3q-8 -39 -12 -74t-4 -62q0 -113 51 -183.5t160 -70.5q90 0 165 30t116 63l49 -99q-72 -61 -169.5 -93t-195.5 -32 q-164 0 -247 94.5t-83 262.5zM301 610q78 0 162 4t152.5 21.5t113.5 55.5t45 106q0 20 -7 41.5t-23.5 39t-46 29t-74.5 11.5q-113 0 -196 -77t-126 -231zM588 1169l180 306h172l-10 -43l-252 -263h-90z" />
|
||||||
|
<glyph unicode="ê" horiz-adv-x="948" d="M102 332q0 168 47.5 301t124 225t174 141.5t199.5 49.5q74 0 128 -20.5t89 -54.5t51.5 -78t16.5 -93q0 -145 -141.5 -228t-411.5 -83q-25 0 -51.5 1t-55.5 3q-8 -39 -12 -74t-4 -62q0 -113 51 -183.5t160 -70.5q90 0 165 30t116 63l49 -99q-72 -61 -169.5 -93t-195.5 -32 q-164 0 -247 94.5t-83 262.5zM301 610q78 0 162 4t152.5 21.5t113.5 55.5t45 106q0 20 -7 41.5t-23.5 39t-46 29t-74.5 11.5q-113 0 -196 -77t-126 -231zM383 1126l319 373h62l135 -373h-129l-49 136l-13 118l-69 -118l-117 -136h-139z" />
|
||||||
|
<glyph unicode="ë" horiz-adv-x="948" d="M102 332q0 168 47.5 301t124 225t174 141.5t199.5 49.5q74 0 128 -20.5t89 -54.5t51.5 -78t16.5 -93q0 -145 -141.5 -228t-411.5 -83q-25 0 -51.5 1t-55.5 3q-8 -39 -12 -74t-4 -62q0 -113 51 -183.5t160 -70.5q90 0 165 30t116 63l49 -99q-72 -61 -169.5 -93t-195.5 -32 q-164 0 -247 94.5t-83 262.5zM301 610q78 0 162 4t152.5 21.5t113.5 55.5t45 106q0 20 -7 41.5t-23.5 39t-46 29t-74.5 11.5q-113 0 -196 -77t-126 -231zM399 1337q0 45 26 75t69 30t69.5 -30t26.5 -75q0 -41 -26.5 -70.5t-69.5 -29.5t-69 29.5t-26 70.5zM774 1339 q0 43 25.5 73t68.5 30q45 0 71 -30t26 -73t-26 -72.5t-71 -29.5q-43 0 -68.5 29.5t-25.5 72.5z" />
|
||||||
|
<glyph unicode="ì" horiz-adv-x="530" d="M111 0l217 1024h153l-217 -1024h-153zM254 1432l8 43h187l59 -306h-88z" />
|
||||||
|
<glyph unicode="í" horiz-adv-x="530" d="M111 0l217 1024h153l-217 -1024h-153zM362 1169l180 306h172l-10 -43l-252 -263h-90z" />
|
||||||
|
<glyph unicode="î" horiz-adv-x="530" d="M111 0l217 1024h153l-217 -1024h-153zM160 1126l319 373h62l135 -373h-129l-49 136l-13 118l-69 -118l-117 -136h-139z" />
|
||||||
|
<glyph unicode="ï" horiz-adv-x="530" d="M111 0l217 1024h153l-217 -1024h-153zM184 1337q0 45 26 75t69 30t69.5 -30t26.5 -75q0 -41 -26.5 -70.5t-69.5 -29.5t-69 29.5t-26 70.5zM559 1339q0 43 25.5 73t68.5 30q45 0 71 -30t26 -73t-26 -72.5t-71 -29.5q-43 0 -68.5 29.5t-25.5 72.5z" />
|
||||||
|
<glyph unicode="ð" horiz-adv-x="1015" d="M104 319q0 141 38 271.5t107.5 232t164 161.5t209.5 60q88 0 131 -23.5t73 -57.5q2 143 -51 245l-166 -71l-45 82l160 69q-33 41 -71 68.5t-79 46.5l121 55q94 -39 156 -115l156 68l41 -84l-146 -63q33 -66 51.5 -148t18.5 -182q0 -258 -48 -439.5t-126 -297t-176.5 -169 t-198.5 -53.5q-80 0 -140.5 27t-100.5 73t-59.5 109.5t-19.5 134.5zM266 336q0 -111 47 -170.5t119 -59.5q109 0 181.5 73t116.5 177.5t61.5 221t17.5 204.5q-16 59 -68.5 94t-124.5 35q-78 0 -142 -53t-110.5 -137t-72 -185.5t-25.5 -199.5z" />
|
||||||
|
<glyph unicode="ñ" horiz-adv-x="1069" d="M54 0l217 1024h106l-8 -176h8q27 33 64 68.5t83 64.5t103.5 48.5t126.5 19.5q102 0 161.5 -49.5t59.5 -172.5q0 -61 -18 -147l-146 -680h-153l137 647q8 37 14.5 73t6.5 64q0 59 -28 96.5t-103 37.5q-53 0 -104.5 -25t-96.5 -62.5t-81 -84t-61 -91.5l-135 -655h-153z M453 1343q66 68 113.5 93.5t84.5 25.5q31 0 55.5 -13t48 -28.5t47 -28t52.5 -12.5q47 0 111 50l30 -89q-59 -59 -102 -81.5t-78 -22.5q-31 0 -55.5 12.5t-48 27.5t-48 27.5t-55.5 12.5q-27 0 -57.5 -13.5t-71.5 -46.5z" />
|
||||||
|
<glyph unicode="ò" horiz-adv-x="1019" d="M102 319q0 162 42 296.5t116 230.5t171 149.5t208 53.5q86 0 146.5 -28t98.5 -76t54 -110.5t16 -129.5q0 -154 -40 -287t-110.5 -231.5t-164.5 -155t-205 -56.5q-92 0 -154.5 30t-102.5 79t-57.5 110.5t-17.5 124.5zM266 356q0 -121 45 -185.5t144 -64.5q68 0 128 48.5 t106 130.5t74 187.5t28 219.5q0 104 -38 165t-145 61q-68 0 -129 -46.5t-109 -124t-76 -179t-28 -212.5zM475 1432l8 43h187l59 -306h-88z" />
|
||||||
|
<glyph unicode="ó" horiz-adv-x="1019" d="M102 319q0 162 42 296.5t116 230.5t171 149.5t208 53.5q86 0 146.5 -28t98.5 -76t54 -110.5t16 -129.5q0 -154 -40 -287t-110.5 -231.5t-164.5 -155t-205 -56.5q-92 0 -154.5 30t-102.5 79t-57.5 110.5t-17.5 124.5zM266 356q0 -121 45 -185.5t144 -64.5q68 0 128 48.5 t106 130.5t74 187.5t28 219.5q0 104 -38 165t-145 61q-68 0 -129 -46.5t-109 -124t-76 -179t-28 -212.5zM592 1169l180 306h172l-10 -43l-252 -263h-90z" />
|
||||||
|
<glyph unicode="ô" horiz-adv-x="1019" d="M102 319q0 162 42 296.5t116 230.5t171 149.5t208 53.5q86 0 146.5 -28t98.5 -76t54 -110.5t16 -129.5q0 -154 -40 -287t-110.5 -231.5t-164.5 -155t-205 -56.5q-92 0 -154.5 30t-102.5 79t-57.5 110.5t-17.5 124.5zM266 356q0 -121 45 -185.5t144 -64.5q68 0 128 48.5 t106 130.5t74 187.5t28 219.5q0 104 -38 165t-145 61q-68 0 -129 -46.5t-109 -124t-76 -179t-28 -212.5zM383 1126l319 373h62l135 -373h-129l-49 136l-13 118l-69 -118l-117 -136h-139z" />
|
||||||
|
<glyph unicode="õ" horiz-adv-x="1019" d="M102 319q0 162 42 296.5t116 230.5t171 149.5t208 53.5q86 0 146.5 -28t98.5 -76t54 -110.5t16 -129.5q0 -154 -40 -287t-110.5 -231.5t-164.5 -155t-205 -56.5q-92 0 -154.5 30t-102.5 79t-57.5 110.5t-17.5 124.5zM266 356q0 -121 45 -185.5t144 -64.5q68 0 128 48.5 t106 130.5t74 187.5t28 219.5q0 104 -38 165t-145 61q-68 0 -129 -46.5t-109 -124t-76 -179t-28 -212.5zM402 1343q66 68 113.5 93.5t84.5 25.5q31 0 55.5 -13t48 -28.5t47 -28t52.5 -12.5q47 0 111 50l30 -89q-59 -59 -102 -81.5t-78 -22.5q-31 0 -55.5 12.5t-48 27.5 t-48 27.5t-55.5 12.5q-27 0 -57.5 -13.5t-71.5 -46.5z" />
|
||||||
|
<glyph unicode="ö" horiz-adv-x="1019" d="M102 319q0 162 42 296.5t116 230.5t171 149.5t208 53.5q86 0 146.5 -28t98.5 -76t54 -110.5t16 -129.5q0 -154 -40 -287t-110.5 -231.5t-164.5 -155t-205 -56.5q-92 0 -154.5 30t-102.5 79t-57.5 110.5t-17.5 124.5zM266 356q0 -121 45 -185.5t144 -64.5q68 0 128 48.5 t106 130.5t74 187.5t28 219.5q0 104 -38 165t-145 61q-68 0 -129 -46.5t-109 -124t-76 -179t-28 -212.5zM389 1337q0 45 26 75t69 30t69.5 -30t26.5 -75q0 -41 -26.5 -70.5t-69.5 -29.5t-69 29.5t-26 70.5zM764 1339q0 43 25.5 73t68.5 30q45 0 71 -30t26 -73t-26 -72.5 t-71 -29.5q-43 0 -68.5 29.5t-25.5 72.5z" />
|
||||||
|
<glyph unicode="÷" horiz-adv-x="983" d="M113 618v148h868v-148h-868zM455 309q0 55 32.5 87t85.5 32t86 -31.5t33 -87.5q0 -53 -32.5 -86t-86.5 -33q-53 0 -85.5 33t-32.5 86zM455 1059q0 55 32.5 87t85.5 32t86 -32t33 -87q0 -53 -32.5 -86t-86.5 -33q-53 0 -85.5 33t-32.5 86z" />
|
||||||
|
<glyph unicode="ø" horiz-adv-x="1019" d="M27 49l102 115q-27 71 -27 155q0 162 42 296.5t116 230.5t171 149.5t208 53.5q72 0 125 -19.5t92 -54.5l74 80l82 -76l-90 -102q16 -39 24 -82t8 -90q0 -154 -40 -287t-110.5 -231.5t-164.5 -155t-205 -56.5q-82 0 -140 24t-99 64l-82 -92zM266 331.5q0 -12.5 2 -24.5 l488 545q-43 66 -148 66q-68 0 -129 -46.5t-109 -124t-76 -179t-28 -212.5v-24.5zM299 188q47 -82 156 -82q68 0 128 48.5t106 130.5t74 187t28 220v20.5t-3 20.5z" />
|
||||||
|
<glyph unicode="ù" horiz-adv-x="1046" d="M123 197q0 72 20 161l140 666h153l-143 -682q-12 -55 -12 -102q0 -57 22.5 -95.5t81.5 -38.5q49 0 99.5 25t96.5 63.5t83.5 86t62.5 92.5l137 651h154l-129 -608q-8 -35 -16.5 -85t-15.5 -105.5t-11 -107.5t-4 -91v-27h-121v195h-8q-31 -41 -71 -80t-88 -70t-103.5 -50.5 t-116.5 -19.5q-45 0 -83 10.5t-66.5 36t-45 67.5t-16.5 108zM498 1432l8 43h187l59 -306h-88z" />
|
||||||
|
<glyph unicode="ú" horiz-adv-x="1046" d="M123 197q0 72 20 161l140 666h153l-143 -682q-12 -55 -12 -102q0 -57 22.5 -95.5t81.5 -38.5q49 0 99.5 25t96.5 63.5t83.5 86t62.5 92.5l137 651h154l-129 -608q-8 -35 -16.5 -85t-15.5 -105.5t-11 -107.5t-4 -91v-27h-121v195h-8q-31 -41 -71 -80t-88 -70t-103.5 -50.5 t-116.5 -19.5q-45 0 -83 10.5t-66.5 36t-45 67.5t-16.5 108zM594 1169l180 306h172l-10 -43l-252 -263h-90z" />
|
||||||
|
<glyph unicode="û" horiz-adv-x="1046" d="M123 197q0 72 20 161l140 666h153l-143 -682q-12 -55 -12 -102q0 -57 22.5 -95.5t81.5 -38.5q49 0 99.5 25t96.5 63.5t83.5 86t62.5 92.5l137 651h154l-129 -608q-8 -35 -16.5 -85t-15.5 -105.5t-11 -107.5t-4 -91v-27h-121v195h-8q-31 -41 -71 -80t-88 -70t-103.5 -50.5 t-116.5 -19.5q-45 0 -83 10.5t-66.5 36t-45 67.5t-16.5 108zM410 1126l319 373h62l135 -373h-129l-49 136l-13 118l-69 -118l-117 -136h-139z" />
|
||||||
|
<glyph unicode="ü" horiz-adv-x="1046" d="M123 197q0 72 20 161l140 666h153l-143 -682q-12 -55 -12 -102q0 -57 22.5 -95.5t81.5 -38.5q49 0 99.5 25t96.5 63.5t83.5 86t62.5 92.5l137 651h154l-129 -608q-8 -35 -16.5 -85t-15.5 -105.5t-11 -107.5t-4 -91v-27h-121v195h-8q-31 -41 -71 -80t-88 -70t-103.5 -50.5 t-116.5 -19.5q-45 0 -83 10.5t-66.5 36t-45 67.5t-16.5 108zM430 1337q0 45 26 75t69 30t69.5 -30t26.5 -75q0 -41 -26.5 -70.5t-69.5 -29.5t-69 29.5t-26 70.5zM805 1339q0 43 25.5 73t68.5 30q45 0 71 -30t26 -73t-26 -72.5t-71 -29.5q-43 0 -68.5 29.5t-25.5 72.5z" />
|
||||||
|
<glyph unicode="ý" horiz-adv-x="899" d="M-41 -401l49 141q23 -8 49 -8q59 0 119 61.5t133 206.5l-176 1024h164l100 -664l11 -196h10l78 198l340 662h163l-483 -913q-53 -100 -105.5 -195.5t-107.5 -170.5t-114.5 -120t-122.5 -45q-35 0 -60.5 4t-46.5 15zM512 1169l180 306h172l-10 -43l-252 -263h-90z" />
|
||||||
|
<glyph unicode="þ" horiz-adv-x="1040" d="M-10 -410l395 1844h154l-127 -562h8q29 35 61.5 67t71.5 56.5t87 39t108 14.5q49 0 92 -15.5t75.5 -51.5t52 -95.5t19.5 -145.5q0 -180 -49 -322.5t-129 -240.5t-179.5 -150.5t-197.5 -52.5q-72 0 -126 13.5t-73 27.5l-90 -426h-153zM264 154q35 -27 72 -37.5t80 -10.5 q80 0 152.5 44.5t130 126t91 196.5t33.5 256q0 82 -33.5 135.5t-99.5 53.5q-55 0 -105 -29t-92 -71t-75 -90t-53 -89z" />
|
||||||
|
<glyph unicode="ÿ" horiz-adv-x="899" d="M-41 -401l49 141q23 -8 49 -8q59 0 119 61.5t133 206.5l-176 1024h164l100 -664l11 -196h10l78 198l340 662h163l-483 -913q-53 -100 -105.5 -195.5t-107.5 -170.5t-114.5 -120t-122.5 -45q-35 0 -60.5 4t-46.5 15zM309 1337q0 45 26 75t69 30t69.5 -30t26.5 -75 q0 -41 -26.5 -70.5t-69.5 -29.5t-69 29.5t-26 70.5zM684 1339q0 43 25.5 73t68.5 30q45 0 71 -30t26 -73t-26 -72.5t-71 -29.5q-43 0 -68.5 29.5t-25.5 72.5z" />
|
||||||
|
<glyph unicode="Œ" horiz-adv-x="1818" d="M147 524q0 197 51.5 368t147.5 297t233.5 197.5t311.5 71.5q45 0 77.5 -1t62.5 -4t59.5 -8t70.5 -11h742l-33 -152h-578l-100 -469h528l-30 -151h-531l-106 -510h587l-30 -152h-752q-53 -12 -100 -18.5t-123 -6.5q-96 0 -184.5 27t-156 90.5t-107.5 169t-40 262.5z M319 526q0 -61 12.5 -131.5t47.5 -131t98.5 -100.5t165.5 -40q29 0 55.5 1t55 4t61.5 10t76 20l233 1108q-47 23 -104 34t-154 11q-133 0 -235.5 -64.5t-172 -173t-104.5 -250t-35 -297.5z" />
|
||||||
|
<glyph unicode="œ" horiz-adv-x="1605" d="M102 319q0 162 42 296.5t116 230.5t171 149.5t208 53.5q129 0 195.5 -62.5t89.5 -163.5q70 109 170 167.5t211 58.5q74 0 128 -20.5t88.5 -54.5t51 -78t16.5 -93q0 -145 -141 -228t-412 -83q-25 0 -51.5 1t-54.5 3q-8 -39 -11.5 -74t-3.5 -62q0 -113 50.5 -183.5 t158.5 -70.5q90 0 165 30t116 63l49 -99q-72 -61 -169 -93t-195 -32q-59 0 -108.5 17.5t-87.5 47.5t-63.5 70t-37.5 85q-59 -98 -156.5 -159t-202.5 -61q-92 0 -154.5 30t-102.5 79t-57.5 110.5t-17.5 124.5zM266 356q0 -121 45 -185.5t144 -64.5q68 0 129 48.5t107 130.5 t74 187.5t28 219.5q0 104 -39 165t-146 61q-68 0 -129 -46.5t-109 -124t-76 -179t-28 -212.5zM958 610h33q66 0 142.5 4t143 21.5t111 55.5t44.5 106q0 20 -7.5 41.5t-24 39t-46 29t-74.5 11.5q-113 0 -194.5 -77t-127.5 -231z" />
|
||||||
|
<glyph unicode="Ÿ" horiz-adv-x="1087" d="M221 1434h178l183 -627l6 -125h2l61 129l445 623h184l-623 -863l-120 -571h-164l121 569zM516 1626q0 41 28.5 68.5t75.5 27.5t75 -27.5t28 -68.5t-28 -67.5t-75 -26.5t-75.5 26.5t-28.5 67.5zM891 1626q0 41 27.5 68.5t74.5 27.5t75.5 -27.5t28.5 -68.5t-28.5 -67.5 t-75.5 -26.5t-74.5 26.5t-27.5 67.5z" />
|
||||||
|
<glyph unicode="ˆ" horiz-adv-x="882" d="M625 1126l319 373h62l135 -373h-129l-49 136l-13 118l-69 -118l-117 -136h-139z" />
|
||||||
|
<glyph unicode="˜" horiz-adv-x="714" d="M666 1343q66 68 113.5 93.5t84.5 25.5q31 0 55.5 -13t48 -28.5t47 -28t52.5 -12.5q47 0 111 50l30 -89q-59 -59 -102 -81.5t-78 -22.5q-31 0 -55.5 12.5t-48 27.5t-48 27.5t-55.5 12.5q-27 0 -57.5 -13.5t-71.5 -46.5z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="891" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="1782" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="891" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="1782" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="594" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="445" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="297" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="297" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="222" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="356" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="99" />
|
||||||
|
<glyph unicode="‐" horiz-adv-x="700" d="M129 520l33 139h471l-35 -139h-469z" />
|
||||||
|
<glyph unicode="‑" horiz-adv-x="700" d="M129 520l33 139h471l-35 -139h-469z" />
|
||||||
|
<glyph unicode="‒" horiz-adv-x="700" d="M129 520l33 139h471l-35 -139h-469z" />
|
||||||
|
<glyph unicode="–" horiz-adv-x="1284" d="M231 520l33 139h826l-33 -139h-826z" />
|
||||||
|
<glyph unicode="—" horiz-adv-x="1595" d="M231 520l33 139h1137l-33 -139h-1137z" />
|
||||||
|
<glyph unicode="‘" horiz-adv-x="380" d="M221 1288q0 70 26.5 124t63.5 92t76 59.5t64 29.5l30 -71q-47 -23 -81.5 -63t-43.5 -93q6 2 19 2q31 0 48 -24.5t17 -57.5q0 -59 -29.5 -89t-80.5 -30q-53 0 -81 37t-28 84z" />
|
||||||
|
<glyph unicode="’" horiz-adv-x="382" d="M221 1094q47 25 82 63.5t45 93.5q-82 5 -82 97q0 25 11.5 44t28 31.5t35.5 19.5t38 7q61 0 82.5 -30.5t21.5 -88.5q0 -70 -26.5 -123t-63.5 -91t-75.5 -61.5t-63.5 -31.5z" />
|
||||||
|
<glyph unicode="‚" horiz-adv-x="387" d="M4 -153q47 25 82 63.5t45 93.5q-82 5 -82 97q0 25 11.5 44t28 31.5t35.5 19.5t38 7q61 0 82.5 -30.5t21.5 -88.5q0 -70 -26.5 -123t-63.5 -91t-75.5 -61.5t-63.5 -31.5z" />
|
||||||
|
<glyph unicode="“" horiz-adv-x="665" d="M221 1288q0 70 26.5 124t63.5 92t76 59.5t64 29.5l30 -71q-47 -23 -81.5 -63t-43.5 -93q6 2 19 2q31 0 48 -24.5t17 -57.5q0 -59 -29.5 -89t-80.5 -30q-53 0 -81 37t-28 84zM506 1288q0 70 26.5 124t63.5 92t76 59.5t64 29.5l30 -71q-47 -23 -81.5 -63t-43.5 -93 q6 2 19 2q31 0 48 -24.5t17 -57.5q0 -59 -29.5 -89t-80.5 -30q-53 0 -81 37t-28 84z" />
|
||||||
|
<glyph unicode="”" horiz-adv-x="665" d="M221 1094q47 25 82 63.5t45 93.5q-82 5 -82 97q0 25 11.5 44t28 31.5t35.5 19.5t38 7q61 0 82.5 -30.5t21.5 -88.5q0 -70 -26.5 -123t-63.5 -91t-75.5 -61.5t-63.5 -31.5zM504 1094q47 25 82 63.5t45 93.5q-82 5 -82 97q0 25 11.5 44t28 31.5t35.5 19.5t38 7 q61 0 82.5 -30.5t21.5 -88.5q0 -70 -26.5 -123t-63.5 -91t-75.5 -61.5t-63.5 -31.5z" />
|
||||||
|
<glyph unicode="„" horiz-adv-x="669" d="M4 -153q47 25 82 63.5t45 93.5q-82 5 -82 97q0 25 11.5 44t28 31.5t35.5 19.5t38 7q61 0 82.5 -30.5t21.5 -88.5q0 -70 -26.5 -123t-63.5 -91t-75.5 -61.5t-63.5 -31.5zM284 -153q47 25 82 63.5t45 93.5q-82 5 -82 97q0 25 11.5 44t28 31.5t35.5 19.5t38 7 q61 0 82.5 -30.5t21.5 -88.5q0 -70 -26.5 -123t-63.5 -91t-75.5 -61.5t-63.5 -31.5z" />
|
||||||
|
<glyph unicode="•" horiz-adv-x="925" d="M229 637q0 63 22.5 115.5t60.5 90.5t90.5 58.5t111.5 20.5t111.5 -19.5t90.5 -56.5t60.5 -89t22.5 -120t-22.5 -120t-60.5 -89t-90.5 -56.5t-111.5 -19.5t-111.5 19.5t-90.5 56.5t-60.5 89t-22.5 120z" />
|
||||||
|
<glyph unicode="…" horiz-adv-x="1476" d="M55 94q0 55 33 87t86 32t86 -31.5t33 -87.5q0 -53 -33 -86t-86 -33t-86 33t-33 86zM549 94q0 55 32.5 87t86.5 32q53 0 85.5 -31.5t32.5 -87.5q0 -53 -32.5 -86t-85.5 -33t-86 33t-33 86zM1044 94q0 55 33 87t86 32t86 -31.5t33 -87.5q0 -53 -32.5 -86t-86.5 -33 q-53 0 -86 33t-33 86z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="356" />
|
||||||
|
<glyph unicode="‹" horiz-adv-x="614" d="M115 530l409 471l90 -98l-252 -295l-114 -76l67 -79l140 -289l-113 -86z" />
|
||||||
|
<glyph unicode="›" horiz-adv-x="579" d="M78 166l254 297l117 84l-72 86l-139 291l116 77l226 -452l-410 -471z" />
|
||||||
|
<glyph unicode=" " horiz-adv-x="445" />
|
||||||
|
<glyph unicode="€" d="M12 520l64 131h145q6 31 13.5 74t15.5 74h-176l63 131h152q53 141 129 239.5t166 163t187 95t190 30.5q98 0 166.5 -16.5t117.5 -42.5l-71 -125q-78 45 -244 45q-55 0 -121 -22.5t-131.5 -69.5t-123.5 -120t-103 -177h565l-62 -131h-544q-10 -33 -16.5 -75t-10.5 -73h498 l-62 -131h-442l-2 -8q-2 -94 16.5 -165t58 -122t105.5 -80.5t164 -29.5q66 0 130 18.5t118 46.5l28 -123q-37 -25 -79 -40t-87 -24t-88 -13.5t-79 -4.5q-111 0 -195 38t-140.5 104.5t-85 158t-30.5 207.5l2 37h-201z" />
|
||||||
|
<glyph unicode="™" horiz-adv-x="1814" d="M184 1294v140h717v-140h-278v-598h-160v598h-279zM983 696v738h160l215 -344l57 -119h2l62 123l198 340h162v-738h-156v342l21 211h-8l-80 -174l-178 -287h-68l-182 285l-74 176h-8l27 -209v-344h-150z" />
|
||||||
|
<glyph unicode="" horiz-adv-x="1024" d="M0 0v1024h1024v-1024h-1024z" />
|
||||||
|
</font>
|
||||||
|
</defs></svg>
|
After Width: | Height: | Size: 67 KiB |
BIN
source/app/fonts/ttf/ptsans.ttf
Normal file
BIN
source/app/fonts/ttf/ptsansbold.ttf
Normal file
BIN
source/app/fonts/ttf/ptsansbolditalic.ttf
Normal file
BIN
source/app/fonts/ttf/ptsansitalic.ttf
Normal file
BIN
source/app/fonts/woff/ptsans.woff
Normal file
BIN
source/app/fonts/woff/ptsansbold.woff
Normal file
BIN
source/app/fonts/woff/ptsansbolditalic.woff
Normal file
BIN
source/app/fonts/woff/ptsansitalic.woff
Normal file
BIN
source/app/images/others/blank.gif
Normal file
After Width: | Height: | Size: 43 B |
BIN
source/app/images/others/default-avatar.png
Normal file
After Width: | Height: | Size: 1.4 KiB |
BIN
source/app/images/others/lock.png
Normal file
After Width: | Height: | Size: 95 B |
BIN
source/app/images/placeholders/jingle_video_local.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
source/app/images/sprites/animate.gif
Normal file
After Width: | Height: | Size: 1.3 KiB |
BIN
source/app/images/sprites/animate.png
Normal file
After Width: | Height: | Size: 6 KiB |
BIN
source/app/images/sprites/archives.png
Normal file
After Width: | Height: | Size: 1.7 KiB |
BIN
source/app/images/sprites/background.png
Normal file
After Width: | Height: | Size: 8.6 KiB |
BIN
source/app/images/sprites/browsers.png
Normal file
After Width: | Height: | Size: 10 KiB |
BIN
source/app/images/sprites/buttons.png
Normal file
After Width: | Height: | Size: 298 B |
BIN
source/app/images/sprites/home.png
Normal file
After Width: | Height: | Size: 29 KiB |
BIN
source/app/images/sprites/install.png
Normal file
After Width: | Height: | Size: 9.7 KiB |
BIN
source/app/images/sprites/jingle.png
Normal file
After Width: | Height: | Size: 2 KiB |
BIN
source/app/images/sprites/manager.png
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
source/app/images/sprites/me.png
Normal file
After Width: | Height: | Size: 5 KiB |
BIN
source/app/images/sprites/mini.gif
Normal file
After Width: | Height: | Size: 4 KiB |
BIN
source/app/images/sprites/mini.png
Normal file
After Width: | Height: | Size: 8.7 KiB |
BIN
source/app/images/sprites/mobile.png
Normal file
After Width: | Height: | Size: 2.4 KiB |
BIN
source/app/images/sprites/smileys.png
Normal file
After Width: | Height: | Size: 19 KiB |
BIN
source/app/images/sprites/talk.png
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
source/app/images/sprites/welcome.png
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
source/app/images/wait/wait-big.gif
Normal file
After Width: | Height: | Size: 1.9 KiB |
BIN
source/app/images/wait/wait-medium.png
Normal file
After Width: | Height: | Size: 294 B |
BIN
source/app/images/wait/wait-small.gif
Normal file
After Width: | Height: | Size: 688 B |
BIN
source/app/images/wait/wait-typing.gif
Normal file
After Width: | Height: | Size: 151 B |
160
source/app/javascripts/adhoc.js
Normal file
|
@ -0,0 +1,160 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the Ad-Hoc JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var AdHoc = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the adhoc popup
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.open = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Popup HTML content
|
||||||
|
var html =
|
||||||
|
'<div class="top">' + Common._e("Commands") + '</div>' +
|
||||||
|
|
||||||
|
'<div class="content">' +
|
||||||
|
'<div class="adhoc-head"></div>' +
|
||||||
|
|
||||||
|
'<div class="results adhoc-results"></div>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="bottom">' +
|
||||||
|
'<div class="wait wait-medium"></div>' +
|
||||||
|
|
||||||
|
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
// Create the popup
|
||||||
|
Popup.create('adhoc', html);
|
||||||
|
|
||||||
|
// Associate the events
|
||||||
|
self.launch();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('AdHoc.open', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the adhoc popup
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.close = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Destroy the popup
|
||||||
|
Popup.destroy('adhoc');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('AdHoc.close', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves an entity adhoc command
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.retrieve = function(xid) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Open the popup
|
||||||
|
self.open();
|
||||||
|
|
||||||
|
// Add a XID marker
|
||||||
|
$('#adhoc .adhoc-head').html('<b>' + Name.getBuddy(xid).htmlEnc() + '</b> (' + xid.htmlEnc() + ')');
|
||||||
|
|
||||||
|
// Get the highest entity resource
|
||||||
|
var highest = Presence.highestPriority(xid);
|
||||||
|
|
||||||
|
if(highest)
|
||||||
|
xid = highest;
|
||||||
|
|
||||||
|
// Start a new adhoc command
|
||||||
|
DataForm.go(xid, 'command', '', '', 'adhoc');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('AdHoc.retrieve', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Starts an adhoc command on the user server
|
||||||
|
* @public
|
||||||
|
* @param {string} server
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.server = function(server) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Open the popup
|
||||||
|
self.open();
|
||||||
|
|
||||||
|
// Add a XID marker
|
||||||
|
$('#adhoc .adhoc-head').html('<b>' + server.htmlEnc() + '</b>');
|
||||||
|
|
||||||
|
// Start a new adhoc command
|
||||||
|
DataForm.go(server, 'command', '', '', 'adhoc');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('AdHoc.server', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin launcher
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.launch = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Click event
|
||||||
|
$('#adhoc .bottom .finish').click(
|
||||||
|
self.close()
|
||||||
|
);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('AdHoc.launch', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
190
source/app/javascripts/anonymous.js
Normal file
|
@ -0,0 +1,190 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the anonymous mode JS script for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Authors: Valérian Saliou, LinkMauve
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Anonymous = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Connected to an anonymous session
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.connected = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Console.info('Jappix (anonymous) is now connected.');
|
||||||
|
|
||||||
|
// Connected marker
|
||||||
|
Connection.connected = true;
|
||||||
|
Connection.current_session = true;
|
||||||
|
Connection.reconnect_try = 0;
|
||||||
|
Connection.reconnect_timer = 0;
|
||||||
|
|
||||||
|
// Not resumed?
|
||||||
|
if(!Connection.resume) {
|
||||||
|
// Create the app
|
||||||
|
Talk.create();
|
||||||
|
|
||||||
|
// Send our first presence
|
||||||
|
Presence.sendFirst('');
|
||||||
|
|
||||||
|
// Set last activity stamp
|
||||||
|
DateUtils.last_activity = DateUtils.getTimeStamp();
|
||||||
|
|
||||||
|
// Create the new groupchat
|
||||||
|
Chat.checkCreate(Common.generateXID(ANONYMOUS_ROOM, 'groupchat'), 'groupchat');
|
||||||
|
|
||||||
|
// Remove some nasty elements for the anonymous mode
|
||||||
|
$('.tools-mucadmin, .tools-add').remove();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resumed
|
||||||
|
else {
|
||||||
|
// Send again our presence
|
||||||
|
Presence.sendActions();
|
||||||
|
|
||||||
|
// Change the title
|
||||||
|
Interface.updateTitle();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the waiting icon
|
||||||
|
Interface.removeGeneralWait();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Anonymous.connected', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disconnected from an anonymous session
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.disconnected = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Console.info('Jappix (anonymous) is now disconnected.');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Anonymous.disconnected', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logins to a anonymous account
|
||||||
|
* @public
|
||||||
|
* @param {string} server
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.login = function(server) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(Common.hasWebSocket()) {
|
||||||
|
// WebSocket supported & configured
|
||||||
|
con = new JSJaCWebSocketConnection({
|
||||||
|
httpbase: HOST_WEBSOCKET
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
|
||||||
|
|
||||||
|
// Check BOSH origin
|
||||||
|
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
|
||||||
|
|
||||||
|
// We create the new http-binding connection
|
||||||
|
con = new JSJaCHttpBindingConnection({
|
||||||
|
httpbase: httpbase
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// And we handle everything that happen
|
||||||
|
con.registerHandler('message', Message.handle);
|
||||||
|
con.registerHandler('presence', Presence.handle);
|
||||||
|
con.registerHandler('iq', IQ.handle);
|
||||||
|
con.registerHandler('onconnect', self.connected);
|
||||||
|
con.registerHandler('onerror', Errors.handle);
|
||||||
|
con.registerHandler('ondisconnect', self.disconnected);
|
||||||
|
|
||||||
|
// We set the anonymous connection parameters
|
||||||
|
oArgs = {};
|
||||||
|
oArgs.domain = server;
|
||||||
|
oArgs.authtype = 'saslanon';
|
||||||
|
oArgs.resource = JAPPIX_RESOURCE + ' Anonymous (' + (new Date()).getTime() + ')';
|
||||||
|
oArgs.secure = true;
|
||||||
|
oArgs.xmllang = XML_LANG;
|
||||||
|
|
||||||
|
// We connect !
|
||||||
|
con.connect(oArgs);
|
||||||
|
|
||||||
|
// Change the page title
|
||||||
|
Interface.title('wait');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Anonymous.login', e);
|
||||||
|
|
||||||
|
// Reset Jappix
|
||||||
|
self.disconnected();
|
||||||
|
|
||||||
|
// Open an unknown error
|
||||||
|
Board.openThisError(2);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin launcher
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.launch = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$(document).ready(function() {
|
||||||
|
Console.info('Anonymous mode detected, connecting...');
|
||||||
|
|
||||||
|
// We add the login wait div
|
||||||
|
Interface.showGeneralWait();
|
||||||
|
|
||||||
|
// Get the vars
|
||||||
|
if(XMPPLinks.links_var.r)
|
||||||
|
ANONYMOUS_ROOM = XMPPLinks.links_var.r;
|
||||||
|
if(XMPPLinks.links_var.n)
|
||||||
|
ANONYMOUS_NICK = XMPPLinks.links_var.n;
|
||||||
|
|
||||||
|
// Fire the login action
|
||||||
|
self.login(HOST_ANONYMOUS);
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Anonymous.launch', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
Anonymous.launch();
|
191
source/app/javascripts/audio.js
Normal file
|
@ -0,0 +1,191 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the audio JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Audio = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
self._timeout_stop = false;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether browser supports audio or not
|
||||||
|
* @private
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self._is_supported = function() {
|
||||||
|
|
||||||
|
is_supported = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9)) {
|
||||||
|
is_supported = false;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Audio._is_supported', e);
|
||||||
|
} finally {
|
||||||
|
return is_supported;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plays the given sound ID
|
||||||
|
* @public
|
||||||
|
* @param {string} name
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.play = function(name, repeat) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
repeat = (typeof repeat === 'boolean') ? repeat : false;
|
||||||
|
|
||||||
|
// Not supported?
|
||||||
|
if(!self._is_supported()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the sounds are enabled
|
||||||
|
if(DataStore.getDB(Connection.desktop_hash, 'options', 'sounds') === '1') {
|
||||||
|
// If the audio elements aren't yet in the DOM
|
||||||
|
if(!Common.exists('#audio')) {
|
||||||
|
$('body').append(
|
||||||
|
'<div id="audio">' +
|
||||||
|
'<audio id="new-chat" preload="auto" data-duration="2">' +
|
||||||
|
'<source src="' + './sounds/new-chat.mp3' + '" />' +
|
||||||
|
'<source src="' + './sounds/new-chat.oga' + '" />' +
|
||||||
|
'</audio>' +
|
||||||
|
|
||||||
|
'<audio id="receive-message" preload="auto" data-duration="2">' +
|
||||||
|
'<source src="' + './sounds/receive-message.mp3' + '" />' +
|
||||||
|
'<source src="' + './sounds/receive-message.oga' + '" />' +
|
||||||
|
'</audio>' +
|
||||||
|
|
||||||
|
'<audio id="notification" preload="auto" data-duration="2">' +
|
||||||
|
'<source src="' + './sounds/notification.mp3' + '" />' +
|
||||||
|
'<source src="' + './sounds/notification.oga' + '" />' +
|
||||||
|
'</audio>' +
|
||||||
|
|
||||||
|
'<audio id="incoming-call" preload="auto" data-duration="7">' +
|
||||||
|
'<source src="' + './sounds/incoming-call.mp3' + '" />' +
|
||||||
|
'<source src="' + './sounds/incoming-call.oga' + '" />' +
|
||||||
|
'</audio>' +
|
||||||
|
|
||||||
|
'<audio id="outgoing-call" preload="auto" data-duration="30">' +
|
||||||
|
'<source src="' + './sounds/outgoing-call.mp3' + '" />' +
|
||||||
|
'<source src="' + './sounds/outgoing-call.oga' + '" />' +
|
||||||
|
'</audio>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We play the target sound
|
||||||
|
var audio_raw_sel = $('#audio audio').filter('#' + name);
|
||||||
|
var audio_sel = audio_raw_sel[0];
|
||||||
|
|
||||||
|
if(audio_sel) {
|
||||||
|
// Fixes Chrome audio bug when Get API serves expired files (for development work purposes)
|
||||||
|
if(window.chrome && System.isDeveloper()) {
|
||||||
|
audio_sel.load();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must repeat sound?
|
||||||
|
if(repeat === true) {
|
||||||
|
// We hardcoded sound duration as it's a mess to add load event handlers to determine duration via Audio API...
|
||||||
|
var duration = parseInt((audio_raw_sel.attr('data-duration') || 0), 10);
|
||||||
|
|
||||||
|
self._timeout_stop = false;
|
||||||
|
|
||||||
|
audio_raw_sel.oneTime((duration + 's'), function() {
|
||||||
|
if(!self._timeout_stop) {
|
||||||
|
self.play(name, repeat);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
audio_sel.play();
|
||||||
|
|
||||||
|
Console.info('Played sound with name: ' + name + ' (' + (repeat ? 'repeatedly' : 'one time') + ')');
|
||||||
|
} else {
|
||||||
|
throw 'Sound does not exist: ' + name;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Audio.play', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stops the given sound ID
|
||||||
|
* @public
|
||||||
|
* @param {string} name
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.stop = function(name) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Not supported?
|
||||||
|
if(!self._is_supported()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
self._timeout_stop = true;
|
||||||
|
|
||||||
|
// Check the audio container exists before doing anything...
|
||||||
|
var audio_parent_sel = $('#audio');
|
||||||
|
var audio_raw_sel = audio_parent_sel.find('audio').filter('#' + name);
|
||||||
|
var audio_sel = audio_raw_sel[0];
|
||||||
|
|
||||||
|
if(audio_parent_sel.size()) {
|
||||||
|
audio_raw_sel.stopTime();
|
||||||
|
|
||||||
|
if(audio_sel) {
|
||||||
|
if(!audio_sel.paused) {
|
||||||
|
audio_sel.pause();
|
||||||
|
|
||||||
|
Console.info('Stopped sound with name: ' + name);
|
||||||
|
} else {
|
||||||
|
Console.info('Sound with name: ' + name + ' already stopped');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw 'Sound does not exist: ' + name;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Console.warn('Audio container does not exist, aborting as nothing likely to be playing! (already stopped)');
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Audio.stop', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
166
source/app/javascripts/autocompletion.js
Normal file
|
@ -0,0 +1,166 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the autocompletion tools JS script for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Autocompletion = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sort an array with insensitivity to the case
|
||||||
|
* @public
|
||||||
|
* @param {string} a
|
||||||
|
* @param {string} b
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.caseInsensitiveSort = function(a, b) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Put the two strings into lower case
|
||||||
|
a = a.toLowerCase();
|
||||||
|
b = b.toLowerCase();
|
||||||
|
|
||||||
|
// Process the sort
|
||||||
|
if(a > b)
|
||||||
|
return 1;
|
||||||
|
if(a < b)
|
||||||
|
return -1;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Autocompletion.caseInsensitiveSort', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an array with the autocompletion results
|
||||||
|
* @public
|
||||||
|
* @param {string} query
|
||||||
|
* @param {string} id
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.process = function(query, id) {
|
||||||
|
|
||||||
|
var results = [];
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Replace forbidden characters in regex
|
||||||
|
query = Common.escapeRegex(query);
|
||||||
|
|
||||||
|
// Search in the roster
|
||||||
|
$('#' + id + ' .user').each(function() {
|
||||||
|
var nick = $(this).find('.name').text();
|
||||||
|
var regex = new RegExp('(^)' + query, 'gi');
|
||||||
|
|
||||||
|
if(nick.match(regex))
|
||||||
|
results.push(nick);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort the array
|
||||||
|
results = results.sort(self.caseInsensitiveSort);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Autocompletion.process', e);
|
||||||
|
} finally {
|
||||||
|
return results;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the autocompletion tools
|
||||||
|
* @public
|
||||||
|
* @param {string} hash
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.reset = function(hash) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$('#' + hash + ' .message-area').removeAttr('data-autocompletion-pointer').removeAttr('data-autocompletion-query');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Autocompletion.reset', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Autocompletes the chat input nick
|
||||||
|
* @public
|
||||||
|
* @param {string} hash
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.create = function(hash) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize
|
||||||
|
var vSelector = $('#' + hash + ' .message-area');
|
||||||
|
var value = vSelector.val();
|
||||||
|
|
||||||
|
if(!value) {
|
||||||
|
self.reset(hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
var query = vSelector.attr('data-autocompletion-query');
|
||||||
|
|
||||||
|
// The autocompletion has not been yet launched
|
||||||
|
if(query === undefined) {
|
||||||
|
query = value;
|
||||||
|
vSelector.attr('data-autocompletion-query', query);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the pointer
|
||||||
|
var pointer = vSelector.attr('data-autocompletion-pointer');
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
if(pointer)
|
||||||
|
i = parseInt(pointer);
|
||||||
|
|
||||||
|
// We get the nickname
|
||||||
|
var nick = self.process(query, hash)[i];
|
||||||
|
|
||||||
|
// Shit, this is my nick!
|
||||||
|
if((nick !== undefined) && (nick.toLowerCase() == Name.getMUCNick(hash).toLowerCase())) {
|
||||||
|
// Increment
|
||||||
|
i++;
|
||||||
|
|
||||||
|
// Get the next nick
|
||||||
|
nick = self.process(query, hash)[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
// We quote the nick
|
||||||
|
if(nick !== undefined) {
|
||||||
|
// Increment
|
||||||
|
i++;
|
||||||
|
Utils.quoteMyNick(hash, nick);
|
||||||
|
|
||||||
|
// Put a pointer
|
||||||
|
vSelector.attr('data-autocompletion-pointer', i);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Autocompletion.create', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
282
source/app/javascripts/avatar.js
Normal file
|
@ -0,0 +1,282 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the avatar JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou, Maranda
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Avatar = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
self.pending = [];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Requests the avatar of a given user
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} mode
|
||||||
|
* @param {boolean} enabled
|
||||||
|
* @param {boolean} photo
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.get = function(xid, mode, enabled, photo) {
|
||||||
|
|
||||||
|
/* REF: http://xmpp.org/extensions/xep-0153.html */
|
||||||
|
|
||||||
|
try {
|
||||||
|
// No need to get the avatar, another process is yet running
|
||||||
|
if(Utils.existArrayValue(self.pending, xid))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Initialize: XML data is in one SQL entry, because some browser are sloooow with SQL requests
|
||||||
|
var xml = Common.XMLFromString(
|
||||||
|
DataStore.getPersistent('global', 'avatar', xid)
|
||||||
|
);
|
||||||
|
var forced = false;
|
||||||
|
|
||||||
|
// Retrieving forced?
|
||||||
|
if($(xml).find('forced').text() == 'true')
|
||||||
|
forced = true;
|
||||||
|
|
||||||
|
// No avatar in presence
|
||||||
|
if(!photo && !forced && enabled == 'true') {
|
||||||
|
// Pending marker
|
||||||
|
self.pending.push(xid);
|
||||||
|
|
||||||
|
// Reset the avatar
|
||||||
|
self.reset(xid, hex_md5(xid));
|
||||||
|
|
||||||
|
Console.warn('No avatar for: ' + xid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to catch the avatar
|
||||||
|
else {
|
||||||
|
// Define some stuffs
|
||||||
|
var type = $(xml).find('type').text();
|
||||||
|
var binval = $(xml).find('binval').text();
|
||||||
|
var checksum = $(xml).find('checksum').text();
|
||||||
|
var updated = false;
|
||||||
|
|
||||||
|
// Process the checksum of the avatar
|
||||||
|
if(checksum == photo || photo == 'forget' || forced)
|
||||||
|
updated = true;
|
||||||
|
|
||||||
|
// If the avatar is yet stored and a new retrieving is not needed
|
||||||
|
if(mode == 'cache' && type && binval && checksum && updated) {
|
||||||
|
// Pending marker
|
||||||
|
self.pending.push(xid);
|
||||||
|
|
||||||
|
// Display the cache avatar
|
||||||
|
self.display(xid, hex_md5(xid), type, binval);
|
||||||
|
|
||||||
|
Console.info('Read avatar from cache: ' + xid);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else if the request has not yet been fired, we get it
|
||||||
|
else if((!updated || mode == 'force' || photo == 'forget') && enabled != 'false') {
|
||||||
|
// Pending marker
|
||||||
|
self.pending.push(xid);
|
||||||
|
|
||||||
|
// Get the latest avatar
|
||||||
|
var iq = new JSJaCIQ();
|
||||||
|
iq.setType('get');
|
||||||
|
iq.setTo(xid);
|
||||||
|
|
||||||
|
iq.appendNode('vCard', {'xmlns': NS_VCARD});
|
||||||
|
|
||||||
|
con.send(iq, self.handle);
|
||||||
|
|
||||||
|
Console.info('Get avatar from server: ' + xid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Avatar.get', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the avatar
|
||||||
|
* @public
|
||||||
|
* @param {object} iq
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.handle = function(iq) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Extract the XML values
|
||||||
|
var handleXML = iq.getNode();
|
||||||
|
var handleFrom = Common.fullXID(Common.getStanzaFrom(iq));
|
||||||
|
|
||||||
|
// Is this me? Remove the resource!
|
||||||
|
if(Common.bareXID(handleFrom) == Common.getXID()) {
|
||||||
|
handleFrom = Common.bareXID(handleFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get some other values
|
||||||
|
var hash = hex_md5(handleFrom);
|
||||||
|
var find = $(handleXML).find('vCard');
|
||||||
|
var aChecksum = 'none';
|
||||||
|
var oChecksum = null;
|
||||||
|
|
||||||
|
// Read our own checksum
|
||||||
|
if(handleFrom == Common.getXID()) {
|
||||||
|
oChecksum = DataStore.getDB(Connection.desktop_hash, 'checksum', 1);
|
||||||
|
|
||||||
|
// Avoid the "null" value
|
||||||
|
if(!oChecksum)
|
||||||
|
oChecksum = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// vCard not empty?
|
||||||
|
if(find.size()) {
|
||||||
|
// We get our profile details
|
||||||
|
if(handleFrom == Common.getXID()) {
|
||||||
|
// Get the names
|
||||||
|
var names = Name.generateBuddy(iq);
|
||||||
|
|
||||||
|
// Write the values to the database
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'profile', 'name', names[0]);
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'profile', 'nick', names[1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We get the avatar
|
||||||
|
var aType = find.find('TYPE:first').text();
|
||||||
|
var aBinval = find.find('BINVAL:first').text();
|
||||||
|
|
||||||
|
// No binval?
|
||||||
|
if(!aBinval) {
|
||||||
|
aType = 'none';
|
||||||
|
aBinval = 'none';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enough data
|
||||||
|
else {
|
||||||
|
// No type?
|
||||||
|
if(!aType)
|
||||||
|
aType = 'image/png';
|
||||||
|
|
||||||
|
// Process the checksum
|
||||||
|
else
|
||||||
|
aChecksum = hex_sha1(Base64.decode(aBinval));
|
||||||
|
}
|
||||||
|
|
||||||
|
// We display the user avatar
|
||||||
|
self.display(handleFrom, hash, aType, aBinval);
|
||||||
|
|
||||||
|
// Store the avatar
|
||||||
|
DataStore.setPersistent('global', 'avatar', handleFrom, '<avatar><type>' + aType + '</type><binval>' + aBinval + '</binval><checksum>' + aChecksum + '</checksum><forced>false</forced></avatar>');
|
||||||
|
|
||||||
|
Console.info('Avatar retrieved from server: ' + handleFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// vCard is empty
|
||||||
|
else {
|
||||||
|
self.reset(handleFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We got a new checksum for us?
|
||||||
|
if(((oChecksum !== null) && (oChecksum != aChecksum)) || !Presence.first_sent) {
|
||||||
|
// Define a proper checksum
|
||||||
|
var pChecksum = aChecksum;
|
||||||
|
|
||||||
|
if(pChecksum == 'none')
|
||||||
|
pChecksum = '';
|
||||||
|
|
||||||
|
// Update our temp. checksum
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'checksum', 1, pChecksum);
|
||||||
|
|
||||||
|
// Send the stanza
|
||||||
|
if(!Presence.first_sent)
|
||||||
|
Storage.get(NS_OPTIONS);
|
||||||
|
else if(DataStore.hasPersistent())
|
||||||
|
Presence.sendActions(pChecksum);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Avatar.handle', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the avatar of an user
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} hash
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.reset = function(xid, hash) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Store the empty avatar
|
||||||
|
DataStore.setPersistent('global', 'avatar', xid, '<avatar><type>none</type><binval>none</binval><checksum>none</checksum><forced>false</forced></avatar>');
|
||||||
|
|
||||||
|
// Display the empty avatar
|
||||||
|
self.display(xid, hash, 'none', 'none');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Avatar.reset', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the avatar of an user
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} hash
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} binval
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.display = function(xid, hash, type, binval) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize the vars
|
||||||
|
var container = hash + ' .avatar-container';
|
||||||
|
var code = '<img class="avatar" src="';
|
||||||
|
|
||||||
|
// If the avatar exists
|
||||||
|
if((type != 'none') && (binval != 'none'))
|
||||||
|
code += 'data:' + type + ';base64,' + binval;
|
||||||
|
else
|
||||||
|
code += './images/others/default-avatar.png';
|
||||||
|
|
||||||
|
code += '" alt="" />';
|
||||||
|
|
||||||
|
// Replace with the new avatar (in the roster and in the chat)
|
||||||
|
$('.' + container).html(code);
|
||||||
|
|
||||||
|
// We can remove the pending marker
|
||||||
|
Utils.removeArrayValue(self.pending, xid);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Avatar.display', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
82
source/app/javascripts/base64.js
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
// License: PD
|
||||||
|
|
||||||
|
// This code was written by Tyler Akins and has been placed in the
|
||||||
|
// public domain. It would be nice if you left this header intact.
|
||||||
|
// Base64 code from Tyler Akins -- http://rumkin.com
|
||||||
|
|
||||||
|
var Base64 = (function () {
|
||||||
|
var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";
|
||||||
|
|
||||||
|
var obj = {
|
||||||
|
/**
|
||||||
|
* Encodes a string in base64
|
||||||
|
* @param {String} input The string to encode in base64.
|
||||||
|
*/
|
||||||
|
encode: function (input) {
|
||||||
|
var output = "";
|
||||||
|
var chr1, chr2, chr3;
|
||||||
|
var enc1, enc2, enc3, enc4;
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
do {
|
||||||
|
chr1 = input.charCodeAt(i++);
|
||||||
|
chr2 = input.charCodeAt(i++);
|
||||||
|
chr3 = input.charCodeAt(i++);
|
||||||
|
|
||||||
|
enc1 = chr1 >> 2;
|
||||||
|
enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
|
||||||
|
enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
|
||||||
|
enc4 = chr3 & 63;
|
||||||
|
|
||||||
|
if (isNaN(chr2)) {
|
||||||
|
enc3 = enc4 = 64;
|
||||||
|
} else if (isNaN(chr3)) {
|
||||||
|
enc4 = 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) +
|
||||||
|
keyStr.charAt(enc3) + keyStr.charAt(enc4);
|
||||||
|
} while (i < input.length);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decodes a base64 string.
|
||||||
|
* @param {String} input The string to decode.
|
||||||
|
*/
|
||||||
|
decode: function (input) {
|
||||||
|
var output = "";
|
||||||
|
var chr1, chr2, chr3;
|
||||||
|
var enc1, enc2, enc3, enc4;
|
||||||
|
var i = 0;
|
||||||
|
|
||||||
|
// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
|
||||||
|
input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
|
||||||
|
|
||||||
|
do {
|
||||||
|
enc1 = keyStr.indexOf(input.charAt(i++));
|
||||||
|
enc2 = keyStr.indexOf(input.charAt(i++));
|
||||||
|
enc3 = keyStr.indexOf(input.charAt(i++));
|
||||||
|
enc4 = keyStr.indexOf(input.charAt(i++));
|
||||||
|
|
||||||
|
chr1 = (enc1 << 2) | (enc2 >> 4);
|
||||||
|
chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
|
||||||
|
chr3 = ((enc3 & 3) << 6) | enc4;
|
||||||
|
|
||||||
|
output = output + String.fromCharCode(chr1);
|
||||||
|
|
||||||
|
if (enc3 != 64) {
|
||||||
|
output = output + String.fromCharCode(chr2);
|
||||||
|
}
|
||||||
|
if (enc4 != 64) {
|
||||||
|
output = output + String.fromCharCode(chr3);
|
||||||
|
}
|
||||||
|
} while (i < input.length);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
return obj;
|
||||||
|
})();
|
357
source/app/javascripts/board.js
Normal file
|
@ -0,0 +1,357 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the notification board JS script for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou, Maranda
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Board = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a board panel
|
||||||
|
* @public
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} id
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.create = function(type, id) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Text var
|
||||||
|
var text = '';
|
||||||
|
|
||||||
|
// Info
|
||||||
|
if(type == 'info') {
|
||||||
|
switch(id) {
|
||||||
|
// Password change
|
||||||
|
case 1:
|
||||||
|
text = Common._e("Your password has been changed, now you can connect to your account with your new login data.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Account deletion
|
||||||
|
case 2:
|
||||||
|
text = Common._e("Your XMPP account has been removed, bye!");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Account logout
|
||||||
|
case 3:
|
||||||
|
text = Common._e("You have been logged out of your XMPP account, have a nice day!");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Groupchat join
|
||||||
|
case 4:
|
||||||
|
text = Common._e("The room you tried to join doesn't seem to exist.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Groupchat removal
|
||||||
|
case 5:
|
||||||
|
text = Common._e("The groupchat has been removed.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Non-existant groupchat user
|
||||||
|
case 6:
|
||||||
|
text = Common._e("The user that you want to reach is not present in the room.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error
|
||||||
|
else {
|
||||||
|
switch(id) {
|
||||||
|
// Custom error
|
||||||
|
case 1:
|
||||||
|
text = '<b>' + Common._e("Error") + '</b> » <span></span>';
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Network error
|
||||||
|
case 2:
|
||||||
|
text = Common._e("Jappix has been interrupted by a network issue, a bug or bad login (check that you entered the right credentials), sorry for the inconvenience.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// List retrieving error
|
||||||
|
case 3:
|
||||||
|
text = Common._e("The element list on this server could not be obtained!");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Attaching error
|
||||||
|
case 4:
|
||||||
|
text = Common.printf(Common._e("An error occured while uploading your file: maybe it is too big (%s maximum) or forbidden!"), JAPPIX_MAX_UPLOAD);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No text?
|
||||||
|
if(!text)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Append the content
|
||||||
|
$('#board').append('<div class="one-board ' + type + '" data-id="' + id + '">' + text + '</div>');
|
||||||
|
|
||||||
|
// Events (click and auto-hide)
|
||||||
|
$('#board .one-board.' + type + '[data-id="' + id + '"]')
|
||||||
|
|
||||||
|
.click(function() {
|
||||||
|
self.closeThis(this);
|
||||||
|
})
|
||||||
|
|
||||||
|
.oneTime('5s', function() {
|
||||||
|
self.closeThis(this);
|
||||||
|
})
|
||||||
|
|
||||||
|
.slideDown();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Board.create', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Destroys the existing board notifications
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.destroy = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$('#board').empty();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Board.destroy', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Executes a given action on the notification board
|
||||||
|
* @public
|
||||||
|
* @param {type} name
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.action = function(id, type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// In a first, we destroy other boards
|
||||||
|
self.destroy();
|
||||||
|
|
||||||
|
// Then we display the board
|
||||||
|
self.create(type, id);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Board.action', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a given error ID
|
||||||
|
* @public
|
||||||
|
* @param {string} id
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.openThisError = function(id) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
self.action(id, 'error');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Board.openThisError', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens a given info ID
|
||||||
|
* @public
|
||||||
|
* @param {string} id
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.openThisInfo = function(id) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
self.action(id, 'info');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Board.openThisInfo', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes a given board
|
||||||
|
* @public
|
||||||
|
* @param {string} board
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.closeThis = function(board) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$(board).slideUp('normal', function() {
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Board.closeThis', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a quick board (HTML5 notification)
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} content
|
||||||
|
* @param {string} title
|
||||||
|
* @param {string} icon
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.quick = function(xid, type, content, title, icon) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Cannot process?
|
||||||
|
if(Common.isFocused() || !content || !window.webkitNotifications)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Default icon?
|
||||||
|
if(!icon) {
|
||||||
|
icon = './images/others/default-avatar.png';
|
||||||
|
|
||||||
|
// Avatar icon?
|
||||||
|
if(xid) {
|
||||||
|
var avatar_xml = Common.XMLFromString(
|
||||||
|
DataStore.getPersistent('global', 'avatar', xid)
|
||||||
|
);
|
||||||
|
var avatar_type = $(avatar_xml).find('type').text() || 'image/png';
|
||||||
|
var avatar_binval = $(avatar_xml).find('binval').text();
|
||||||
|
|
||||||
|
if(avatar_binval && avatar_type)
|
||||||
|
icon = 'data:' + avatar_type + ';base64,' + avatar_binval;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default title?
|
||||||
|
if(!title)
|
||||||
|
title = Common._e("New event!");
|
||||||
|
|
||||||
|
// Check for notification permission
|
||||||
|
if(window.webkitNotifications.checkPermission() === 0) {
|
||||||
|
// Create notification
|
||||||
|
var notification = window.webkitNotifications.createNotification(icon, title, content);
|
||||||
|
|
||||||
|
// Auto-hide after a while
|
||||||
|
notification.ondisplay = function(event) {
|
||||||
|
setTimeout(function() {
|
||||||
|
event.currentTarget.cancel();
|
||||||
|
}, 10000);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Click event
|
||||||
|
notification.onclick = function() {
|
||||||
|
// Click action?
|
||||||
|
switch(type) {
|
||||||
|
case 'chat':
|
||||||
|
Interface.switchChan(hex_md5(xid));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'groupchat':
|
||||||
|
Interface.switchChan(hex_md5(Common.bareXID(xid)));
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Focus on msg-me
|
||||||
|
window.focus();
|
||||||
|
|
||||||
|
// Remove notification
|
||||||
|
this.cancel();
|
||||||
|
};
|
||||||
|
|
||||||
|
// Show notification
|
||||||
|
notification.show();
|
||||||
|
|
||||||
|
return notification;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Board.quick', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asks for permission to show quick boards (HTML5 notification)
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.quickPermission = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(!window.webkitNotifications || (window.webkitNotifications.checkPermission() === 0))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Ask for permission
|
||||||
|
window.webkitNotifications.requestPermission();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Board.quickPermission', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin launcher
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.launch = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Fires quickPermission() on document click
|
||||||
|
$(document).click(function() {
|
||||||
|
// Ask for permission to use quick boards
|
||||||
|
if((typeof con != 'undefined') && con.connected())
|
||||||
|
self.quickPermission();
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Board.launch', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
Board.launch();
|
125
source/app/javascripts/browser-detect.js
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
/* BROWSER DETECT
|
||||||
|
* http://www.quirksmode.org/js/detect.html
|
||||||
|
* License: dual-licensed under MPLv2 and the original license
|
||||||
|
*/
|
||||||
|
|
||||||
|
var BrowserDetect = {
|
||||||
|
init: function () {
|
||||||
|
this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
|
||||||
|
this.version = this.searchVersion(navigator.userAgent)
|
||||||
|
|| this.searchVersion(navigator.appVersion)
|
||||||
|
|| "an unknown version";
|
||||||
|
this.OS = this.searchString(this.dataOS) || "an unknown OS";
|
||||||
|
},
|
||||||
|
|
||||||
|
searchString: function (data) {
|
||||||
|
for (var i=0;i<data.length;i++) {
|
||||||
|
var dataString = data[i].string;
|
||||||
|
var dataProp = data[i].prop;
|
||||||
|
this.versionSearchString = data[i].versionSearch || data[i].identity;
|
||||||
|
if (dataString) {
|
||||||
|
if (dataString.indexOf(data[i].subString) != -1)
|
||||||
|
return data[i].identity;
|
||||||
|
}
|
||||||
|
else if (dataProp)
|
||||||
|
return data[i].identity;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
searchVersion: function (dataString) {
|
||||||
|
var index = dataString.indexOf(this.versionSearchString);
|
||||||
|
if (index == -1) return;
|
||||||
|
return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
|
||||||
|
},
|
||||||
|
|
||||||
|
dataBrowser: [
|
||||||
|
{
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "Chrome",
|
||||||
|
identity: "Chrome"
|
||||||
|
},
|
||||||
|
{ string: navigator.userAgent,
|
||||||
|
subString: "OmniWeb",
|
||||||
|
versionSearch: "OmniWeb/",
|
||||||
|
identity: "OmniWeb"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.vendor,
|
||||||
|
subString: "Apple",
|
||||||
|
identity: "Safari",
|
||||||
|
versionSearch: "Version"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
prop: window.opera,
|
||||||
|
identity: "Opera"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.vendor,
|
||||||
|
subString: "iCab",
|
||||||
|
identity: "iCab"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.vendor,
|
||||||
|
subString: "KDE",
|
||||||
|
identity: "Konqueror"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "Firefox",
|
||||||
|
identity: "Firefox"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.vendor,
|
||||||
|
subString: "Camino",
|
||||||
|
identity: "Camino"
|
||||||
|
},
|
||||||
|
{ // for newer Netscapes (6+)
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "Netscape",
|
||||||
|
identity: "Netscape"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "MSIE",
|
||||||
|
identity: "Explorer",
|
||||||
|
versionSearch: "MSIE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "Gecko",
|
||||||
|
identity: "Mozilla",
|
||||||
|
versionSearch: "rv"
|
||||||
|
},
|
||||||
|
{ // for older Netscapes (4-)
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "Mozilla",
|
||||||
|
identity: "Netscape",
|
||||||
|
versionSearch: "Mozilla"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
|
||||||
|
dataOS : [
|
||||||
|
{
|
||||||
|
string: navigator.platform,
|
||||||
|
subString: "Win",
|
||||||
|
identity: "Windows"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.platform,
|
||||||
|
subString: "Mac",
|
||||||
|
identity: "Mac"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.userAgent,
|
||||||
|
subString: "iPhone",
|
||||||
|
identity: "iPhone/iPod"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
string: navigator.platform,
|
||||||
|
subString: "Linux",
|
||||||
|
identity: "Linux"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
};
|
||||||
|
|
||||||
|
BrowserDetect.init();
|
98
source/app/javascripts/bubble.js
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the bubble JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Bubble = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes all the opened bubbles
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.close = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Destroy all the elements
|
||||||
|
$('.bubble.hidable:visible').hide();
|
||||||
|
$('.bubble.removable').remove();
|
||||||
|
$('body').off('click');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Bubble.close', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Click function when a bubble is opened
|
||||||
|
* @public
|
||||||
|
* @param {object} selector
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.show = function(selector) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Hidable bubbles special things
|
||||||
|
if($(selector).is('.hidable')) {
|
||||||
|
// This bubble is yet displayed? So abort!
|
||||||
|
if($(selector).is(':visible'))
|
||||||
|
return self.close();
|
||||||
|
|
||||||
|
// Close all the bubbles
|
||||||
|
self.close();
|
||||||
|
|
||||||
|
// Show the requested bubble
|
||||||
|
$(selector).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Removable bubbles special things
|
||||||
|
else {
|
||||||
|
// This bubble is yet added? So abort!
|
||||||
|
if(Common.exists(selector))
|
||||||
|
return self.close();
|
||||||
|
|
||||||
|
// Close all the bubbles
|
||||||
|
self.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Creates a new click event to close the bubble
|
||||||
|
$('body').on('click', function(evt) {
|
||||||
|
var target = evt.target;
|
||||||
|
|
||||||
|
// If this is a click away from a bubble
|
||||||
|
if(!$(target).parents('.ibubble').size())
|
||||||
|
self.close();
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Bubble.show', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
541
source/app/javascripts/caps.js
Normal file
|
@ -0,0 +1,541 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the CAPS JS script for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou, Maranda
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Caps = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a stored Caps
|
||||||
|
* @public
|
||||||
|
* @param {string} caps
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.read = function(caps) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Common.XMLFromString(
|
||||||
|
DataStore.getPersistent('global', 'caps', caps)
|
||||||
|
);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Caps.read', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns an array of the Jappix disco#infos
|
||||||
|
* @public
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.myDiscoInfos = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var disco_base = [
|
||||||
|
NS_MUC,
|
||||||
|
NS_MUC_USER,
|
||||||
|
NS_MUC_ADMIN,
|
||||||
|
NS_MUC_OWNER,
|
||||||
|
NS_MUC_CONFIG,
|
||||||
|
NS_DISCO_INFO,
|
||||||
|
NS_DISCO_ITEMS,
|
||||||
|
NS_PUBSUB_RI,
|
||||||
|
NS_BOSH,
|
||||||
|
NS_CAPS,
|
||||||
|
NS_MOOD,
|
||||||
|
NS_ACTIVITY,
|
||||||
|
NS_TUNE,
|
||||||
|
NS_GEOLOC,
|
||||||
|
NS_NICK,
|
||||||
|
NS_URN_MBLOG,
|
||||||
|
NS_URN_INBOX,
|
||||||
|
NS_MOOD + NS_NOTIFY,
|
||||||
|
NS_ACTIVITY + NS_NOTIFY,
|
||||||
|
NS_TUNE + NS_NOTIFY,
|
||||||
|
NS_GEOLOC + NS_NOTIFY,
|
||||||
|
NS_URN_MBLOG + NS_NOTIFY,
|
||||||
|
NS_URN_INBOX + NS_NOTIFY,
|
||||||
|
NS_URN_DELAY,
|
||||||
|
NS_ROSTER,
|
||||||
|
NS_ROSTERX,
|
||||||
|
NS_HTTP_AUTH,
|
||||||
|
NS_CHATSTATES,
|
||||||
|
NS_XHTML_IM,
|
||||||
|
NS_URN_MAM,
|
||||||
|
NS_IPV6,
|
||||||
|
NS_LAST,
|
||||||
|
NS_PRIVATE,
|
||||||
|
NS_REGISTER,
|
||||||
|
NS_SEARCH,
|
||||||
|
NS_COMMANDS,
|
||||||
|
NS_VERSION,
|
||||||
|
NS_XDATA,
|
||||||
|
NS_VCARD,
|
||||||
|
NS_IETF_VCARD4,
|
||||||
|
NS_URN_ADATA,
|
||||||
|
NS_URN_AMETA,
|
||||||
|
NS_URN_TIME,
|
||||||
|
NS_URN_PING,
|
||||||
|
NS_URN_RECEIPTS,
|
||||||
|
NS_PRIVACY,
|
||||||
|
NS_IQOOB,
|
||||||
|
NS_XOOB,
|
||||||
|
NS_URN_CARBONS
|
||||||
|
];
|
||||||
|
|
||||||
|
var disco_jingle = JSJaCJingle_disco();
|
||||||
|
var disco_all = disco_base.concat(disco_jingle);
|
||||||
|
|
||||||
|
return disco_all;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Caps.myDiscoInfos', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the disco#infos of an entity
|
||||||
|
* @public
|
||||||
|
* @param {string} to
|
||||||
|
* @param {string} caps
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.getDiscoInfos = function(to, caps) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// No CAPS
|
||||||
|
if(!caps) {
|
||||||
|
Console.warn('No CAPS: ' + to);
|
||||||
|
|
||||||
|
self.displayDiscoInfos(to, '');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the stored disco infos
|
||||||
|
var xml = self.read(caps);
|
||||||
|
|
||||||
|
// Yet stored
|
||||||
|
if(xml) {
|
||||||
|
Console.info('CAPS from cache: ' + to);
|
||||||
|
|
||||||
|
self.displayDiscoInfos(to, xml);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.info('CAPS from the network: ' + to);
|
||||||
|
|
||||||
|
// Not stored: get the disco#infos
|
||||||
|
var iq = new JSJaCIQ();
|
||||||
|
|
||||||
|
iq.setTo(to);
|
||||||
|
iq.setType('get');
|
||||||
|
iq.setQuery(NS_DISCO_INFO);
|
||||||
|
|
||||||
|
con.send(iq, self.handleDiscoInfos);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Caps.getDiscoInfos', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the disco#infos of an entity
|
||||||
|
* @public
|
||||||
|
* @param {object} iq
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.handleDiscoInfos = function(iq) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(!iq || (iq.getType() == 'error'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// IQ received, get some values
|
||||||
|
var from = Common.fullXID(Common.getStanzaFrom(iq));
|
||||||
|
var query = iq.getQuery();
|
||||||
|
|
||||||
|
// Generate the CAPS-processing values
|
||||||
|
var identities = [];
|
||||||
|
var features = [];
|
||||||
|
var data_forms = [];
|
||||||
|
|
||||||
|
// Identity values
|
||||||
|
$(query).find('identity').each(function() {
|
||||||
|
var pCategory = $(this).attr('category');
|
||||||
|
var pType = $(this).attr('type');
|
||||||
|
var pLang = $(this).attr('xml:lang');
|
||||||
|
var pName = $(this).attr('name');
|
||||||
|
|
||||||
|
if(!pCategory)
|
||||||
|
pCategory = '';
|
||||||
|
if(!pType)
|
||||||
|
pType = '';
|
||||||
|
if(!pLang)
|
||||||
|
pLang = '';
|
||||||
|
if(!pName)
|
||||||
|
pName = '';
|
||||||
|
|
||||||
|
identities.push(pCategory + '/' + pType + '/' + pLang + '/' + pName);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Feature values
|
||||||
|
$(query).find('feature').each(function() {
|
||||||
|
var pVar = $(this).attr('var');
|
||||||
|
|
||||||
|
// Add the current value to the array
|
||||||
|
if(pVar)
|
||||||
|
features.push(pVar);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Data-form values
|
||||||
|
$(query).find('x[xmlns="' + NS_XDATA + '"]').each(function() {
|
||||||
|
// Initialize some stuffs
|
||||||
|
var pString = '';
|
||||||
|
var sortVar = [];
|
||||||
|
|
||||||
|
// Add the form type field
|
||||||
|
$(this).find('field[var="FORM_TYPE"] value').each(function() {
|
||||||
|
var cText = $(this).text();
|
||||||
|
|
||||||
|
if(cText)
|
||||||
|
pString += cText + '<';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add the var attributes into an array
|
||||||
|
$(this).find('field:not([var="FORM_TYPE"])').each(function() {
|
||||||
|
var cVar = $(this).attr('var');
|
||||||
|
|
||||||
|
if(cVar)
|
||||||
|
sortVar.push(cVar);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort the var attributes
|
||||||
|
sortVar = sortVar.sort();
|
||||||
|
|
||||||
|
// Loop this sorted var attributes
|
||||||
|
$.each(sortVar, function(i) {
|
||||||
|
// Initialize the value sorting
|
||||||
|
var sortVal = [];
|
||||||
|
|
||||||
|
// Append it to the string
|
||||||
|
pString += sortVar[i] + '<';
|
||||||
|
|
||||||
|
// Add each value to the array
|
||||||
|
$(this).find('field[var=' + sortVar[i] + '] value').each(function() {
|
||||||
|
sortVal.push($(this).text());
|
||||||
|
});
|
||||||
|
|
||||||
|
// Sort the values
|
||||||
|
sortVal = sortVal.sort();
|
||||||
|
|
||||||
|
// Append the values to the string
|
||||||
|
for(var j in sortVal) {
|
||||||
|
pString += sortVal[j] + '<';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Any string?
|
||||||
|
if(pString) {
|
||||||
|
// Remove the undesired double '<' from the string
|
||||||
|
if(pString.match(/(.+)(<)+$/))
|
||||||
|
pString = pString.substring(0, pString.length - 1);
|
||||||
|
|
||||||
|
// Add the current string to the array
|
||||||
|
data_forms.push(pString);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Process the CAPS
|
||||||
|
var caps = self.process(identities, features, data_forms);
|
||||||
|
|
||||||
|
// Get the XML string
|
||||||
|
var xml = Common.xmlToString(query);
|
||||||
|
|
||||||
|
// Store the disco infos
|
||||||
|
DataStore.setPersistent('global', 'caps', caps, xml);
|
||||||
|
|
||||||
|
// This is our server
|
||||||
|
if(from == Utils.getServer()) {
|
||||||
|
// Handle the features
|
||||||
|
Features.handle(xml);
|
||||||
|
|
||||||
|
Console.info('Got our server CAPS');
|
||||||
|
} else {
|
||||||
|
// Display the disco infos
|
||||||
|
self.displayDiscoInfos(from, xml);
|
||||||
|
|
||||||
|
Console.info('Got CAPS: ' + from);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Caps.handleDiscoInfos', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the disco#infos everywhere needed for an entity
|
||||||
|
* @public
|
||||||
|
* @param {string} from
|
||||||
|
* @param {string} xml
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.displayDiscoInfos = function(from, xml) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Generate the chat path
|
||||||
|
var xid = Common.bareXID(from);
|
||||||
|
|
||||||
|
// This comes from a private groupchat chat?
|
||||||
|
if(Utils.isPrivate(xid))
|
||||||
|
xid = from;
|
||||||
|
|
||||||
|
hash = hex_md5(xid);
|
||||||
|
|
||||||
|
// Display the supported features
|
||||||
|
var features = {};
|
||||||
|
|
||||||
|
$(xml).find('feature').each(function() {
|
||||||
|
var current = $(this).attr('var');
|
||||||
|
|
||||||
|
if(current) {
|
||||||
|
features[current] = 1;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Paths
|
||||||
|
var path = $('#' + hash);
|
||||||
|
var roster_path = $('#roster .buddy.' + hash);
|
||||||
|
var roster_jingle_path = roster_path.find('.buddy-infos .call-jingle');
|
||||||
|
|
||||||
|
var message_area = path.find('.message-area');
|
||||||
|
var style = path.find('.chat-tools-style');
|
||||||
|
var jingle_audio = path.find('.tools-jingle-audio');
|
||||||
|
var roster_jingle_audio = roster_jingle_path.find('a.audio');
|
||||||
|
var jingle_video = path.find('.tools-jingle-video');
|
||||||
|
var roster_jingle_video = roster_jingle_path.find('a.video');
|
||||||
|
var roster_jingle_separator = roster_jingle_path.find('span.separator');
|
||||||
|
var file = path.find('.chat-tools-file');
|
||||||
|
|
||||||
|
// Apply xHTML-IM
|
||||||
|
if(NS_XHTML_IM in features) {
|
||||||
|
style.show();
|
||||||
|
} else {
|
||||||
|
// Remove the tooltip elements
|
||||||
|
style.hide();
|
||||||
|
style.find('.bubble-style').remove();
|
||||||
|
|
||||||
|
// Reset the markers
|
||||||
|
message_area.removeAttr('style')
|
||||||
|
.removeAttr('data-font')
|
||||||
|
.removeAttr('data-fontsize')
|
||||||
|
.removeAttr('data-color')
|
||||||
|
.removeAttr('data-bold')
|
||||||
|
.removeAttr('data-italic')
|
||||||
|
.removeAttr('data-underline');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply Jingle
|
||||||
|
var jingle_local_supported = JSJAC_JINGLE_AVAILABLE;
|
||||||
|
var jingle_audio_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_AUDIO);
|
||||||
|
var jingle_video_xid = self.getFeatureResource(xid, NS_JINGLE_APPS_RTP_VIDEO);
|
||||||
|
|
||||||
|
if(jingle_audio_xid && jingle_local_supported) {
|
||||||
|
jingle_audio.show();
|
||||||
|
roster_jingle_audio.show();
|
||||||
|
} else {
|
||||||
|
jingle_audio.hide();
|
||||||
|
roster_jingle_audio.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(jingle_video_xid && jingle_local_supported) {
|
||||||
|
jingle_video.show();
|
||||||
|
roster_jingle_video.show();
|
||||||
|
} else {
|
||||||
|
jingle_video.hide();
|
||||||
|
roster_jingle_video.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if(jingle_audio_xid && jingle_video_xid && jingle_local_supported) {
|
||||||
|
roster_jingle_separator.show();
|
||||||
|
} else {
|
||||||
|
roster_jingle_separator.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
if((jingle_audio_xid || jingle_video_xid) && jingle_local_supported) {
|
||||||
|
roster_jingle_path.show();
|
||||||
|
} else {
|
||||||
|
roster_jingle_path.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply Out of Band Data
|
||||||
|
var iq_oob_xid = self.getFeatureResource(xid, NS_IQOOB);
|
||||||
|
|
||||||
|
if(iq_oob_xid || NS_XOOB in features) {
|
||||||
|
file.show();
|
||||||
|
|
||||||
|
// Set a marker
|
||||||
|
file.attr(
|
||||||
|
'data-oob',
|
||||||
|
iq_oob_xid ? 'iq' : 'x'
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
// Remove the tooltip elements
|
||||||
|
file.hide();
|
||||||
|
file.find('.bubble-style').remove();
|
||||||
|
|
||||||
|
// Reset the marker
|
||||||
|
file.removeAttr('data-oob');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply receipts
|
||||||
|
if(NS_URN_RECEIPTS in features) {
|
||||||
|
message_area.attr('data-receipts', 'true');
|
||||||
|
} else {
|
||||||
|
message_area.removeAttr('data-receipts');
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Caps.displayDiscoInfos', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the CAPS hash
|
||||||
|
* @public
|
||||||
|
* @param {object} cIdentities
|
||||||
|
* @param {object} cFeatures
|
||||||
|
* @param {object} cDataForms
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.process = function(cIdentities, cFeatures, cDataForms) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize
|
||||||
|
var cString = '';
|
||||||
|
|
||||||
|
// Sort the arrays
|
||||||
|
cIdentities = cIdentities.sort();
|
||||||
|
cFeatures = cFeatures.sort();
|
||||||
|
cDataForms = cDataForms.sort();
|
||||||
|
|
||||||
|
// Process the sorted identity string
|
||||||
|
for(var a in cIdentities) {
|
||||||
|
cString += cIdentities[a] + '<';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the sorted feature string
|
||||||
|
for(var b in cFeatures) {
|
||||||
|
cString += cFeatures[b] + '<';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the sorted data-form string
|
||||||
|
for(var c in cDataForms) {
|
||||||
|
cString += cDataForms[c] + '<';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Process the SHA-1 hash
|
||||||
|
var cHash = b64_sha1(cString);
|
||||||
|
|
||||||
|
return cHash;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Caps.process', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the Jappix CAPS hash
|
||||||
|
* @public
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.mine = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.process(
|
||||||
|
['client/web//Jappix'],
|
||||||
|
self.myDiscoInfos(),
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Caps.mine', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the user resource supporting given feature w/ highest priority
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} feature_ns
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.getFeatureResource = function(xid, feature_ns) {
|
||||||
|
|
||||||
|
var selected_xid = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(!feature_ns) {
|
||||||
|
throw 'No feature namespace given!';
|
||||||
|
}
|
||||||
|
|
||||||
|
var max_priority = null;
|
||||||
|
var cur_xid_full, cur_presence_sel, cur_caps, cur_features, cur_priority;
|
||||||
|
|
||||||
|
for(var cur_resource in Presence.resources(xid)) {
|
||||||
|
cur_xid_full = xid + '/' + cur_resource;
|
||||||
|
cur_presence_sel = $(Presence.readStanza(cur_xid_full));
|
||||||
|
|
||||||
|
cur_priority = parseInt((cur_presence_sel.find('priority').text() || 0), 10);
|
||||||
|
cur_caps = cur_presence_sel.find('caps').text();
|
||||||
|
|
||||||
|
if(cur_caps) {
|
||||||
|
cur_features = self.read(cur_caps);
|
||||||
|
|
||||||
|
if(cur_features && $(cur_features).find('feature[var="' + feature_ns + '"]').size() &&
|
||||||
|
(cur_priority >= max_priority || max_priority === null)) {
|
||||||
|
max_priority = cur_priority;
|
||||||
|
selected_xid = cur_xid_full;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Caps.getFeatureResource', e);
|
||||||
|
} finally {
|
||||||
|
return selected_xid;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
238
source/app/javascripts/carbons.js
Normal file
|
@ -0,0 +1,238 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the Message Carbons JS script for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Carbons = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures Message Carbons options
|
||||||
|
* @public
|
||||||
|
* @param {string} type
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self._configure = function(type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(!(type in {'enable': 1, 'disable': 1})) {
|
||||||
|
Console.error('Carbons._configure', 'Invalid type (must be either "enable" or "disable")'); return;
|
||||||
|
}
|
||||||
|
|
||||||
|
var iq = new JSJaCIQ();
|
||||||
|
iq.setType('set');
|
||||||
|
|
||||||
|
iq.appendNode(type, {'xmlns': NS_URN_CARBONS});
|
||||||
|
|
||||||
|
con.send(iq, function(iq) {
|
||||||
|
self._handleConfigure(iq, type);
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Carbons._configure', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Configures Message Carbons options
|
||||||
|
* @public
|
||||||
|
* @param {object} iq
|
||||||
|
* @param {string} type
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self._handleConfigure = function(iq, type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(iq.getType() === 'result') {
|
||||||
|
Console.log('Message Carbons successfully configured (type: ' + type + ')');
|
||||||
|
} else {
|
||||||
|
Console.error('Message Carbons could not be configured (type: ' + type + ')');
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Carbons._handleConfigure', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables Message Carbons for this session
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.enable = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
self._configure('enable');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Carbons.enable', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Disables Message Carbons for this session
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.disable = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
self._configure('disable');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Carbons.disable', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the server has Carbons support or not
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.has = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Features.enabledCarbons();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Carbons.has', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the forwarded message stanza
|
||||||
|
* @public
|
||||||
|
* @param {object} message
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self._getForwarded = function(message) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var forwarded_message = $(message.getNode()).find('forwarded[xmlns="' + NS_URN_FORWARD + '"]:first message:first');
|
||||||
|
|
||||||
|
if(forwarded_message[0]) {
|
||||||
|
return JSJaCPacket.wrapNode(forwarded_message[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Carbons._getForwarded', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a forwarded sent message
|
||||||
|
* @public
|
||||||
|
* @param {object} message
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.handleSent = function(message) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var forwarded_message = self._getForwarded(message);
|
||||||
|
|
||||||
|
if(forwarded_message !== null) {
|
||||||
|
var to = Common.bareXID(forwarded_message.getTo());
|
||||||
|
var hash = hex_md5(to);
|
||||||
|
var type = forwarded_message.getType();
|
||||||
|
|
||||||
|
// Display sent message
|
||||||
|
if(type === 'chat' || !type) {
|
||||||
|
// Chat opened? (no need to display sent messages if chat does not exist there...)
|
||||||
|
if(Chat.exists(hash)) {
|
||||||
|
// Get more data
|
||||||
|
var id = forwarded_message.getID();
|
||||||
|
var body = $.trim(forwarded_message.getBody());
|
||||||
|
var my_xid = Common.getXID();
|
||||||
|
|
||||||
|
// Generate the message body
|
||||||
|
var html_escape = (Message.generate(forwarded_message, body, hash) !== 'XHTML');
|
||||||
|
if(!html_escape) {
|
||||||
|
body = Filter.xhtml(forwarded_message.getNode());
|
||||||
|
}
|
||||||
|
|
||||||
|
if(body) {
|
||||||
|
// Display the message (finally!)
|
||||||
|
Message.display(
|
||||||
|
'chat',
|
||||||
|
my_xid,
|
||||||
|
hash,
|
||||||
|
Name.getBuddy(my_xid).htmlEnc(),
|
||||||
|
body,
|
||||||
|
DateUtils.getCompleteTime(),
|
||||||
|
DateUtils.getTimeStamp(),
|
||||||
|
'user-message',
|
||||||
|
html_escape,
|
||||||
|
'',
|
||||||
|
'me',
|
||||||
|
id
|
||||||
|
);
|
||||||
|
|
||||||
|
Console.debug('Got a sent message from another resource to: ' + (to || 'none'));
|
||||||
|
} else {
|
||||||
|
Console.debug('Got a sent message from another resource to: ' + (to || 'none') + ', was ignored because body empty');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Console.debug('Got a sent message from another resource to: ' + (to || 'none') + ', was ignored because chat not open');
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Console.warning('Got a sent message from another resource to: ' + (to || 'none') + ', was ignored because of type: ' + type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Carbons.handleSent', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles a forwarded received message
|
||||||
|
* @public
|
||||||
|
* @param {object} message
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.handleReceived = function(message) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var forwarded_message = self._getForwarded(message);
|
||||||
|
|
||||||
|
if(forwarded_message !== null) {
|
||||||
|
Console.debug('Got a received message from another resource from: ' + (forwarded_message.getFrom() || 'none'));
|
||||||
|
|
||||||
|
Message.handle(forwarded_message);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Carbons.handleReceived', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
505
source/app/javascripts/chat.js
Normal file
|
@ -0,0 +1,505 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the chat JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Authors: Valérian Saliou, Eric, Maranda
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Chat = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Correctly opens a new chat
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} nickname
|
||||||
|
* @param {string} password
|
||||||
|
* @param {string} title
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.checkCreate = function(xid, type, nickname, password, title) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// No XID?
|
||||||
|
if(!xid)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// We generate some stuffs
|
||||||
|
var hash = hex_md5(xid);
|
||||||
|
var name;
|
||||||
|
|
||||||
|
// Gets the name of the user/title of the room
|
||||||
|
if(title)
|
||||||
|
name = title;
|
||||||
|
|
||||||
|
else {
|
||||||
|
// Private groupchat chat
|
||||||
|
if(type == 'private')
|
||||||
|
name = Common.thisResource(xid);
|
||||||
|
|
||||||
|
// XMPP-ID
|
||||||
|
else if(xid.indexOf('@') != -1)
|
||||||
|
name = Name.getBuddy(xid);
|
||||||
|
|
||||||
|
// Gateway
|
||||||
|
else
|
||||||
|
name = xid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the target div does not exist
|
||||||
|
if(!Common.exists('#' + hash)) {
|
||||||
|
// We check the type of the chat to open
|
||||||
|
if((type == 'chat') || (type == 'private'))
|
||||||
|
self.create(hash, xid, name, type);
|
||||||
|
|
||||||
|
else if(type == 'groupchat') {
|
||||||
|
// Try to read the room stored configuration
|
||||||
|
if(!Utils.isAnonymous() && (!nickname || !password || !title)) {
|
||||||
|
// Catch the room data
|
||||||
|
var fData = $(Common.XMLFromString(DataStore.getDB(Connection.desktop_hash, 'favorites', xid)));
|
||||||
|
var fNick = fData.find('nick').text();
|
||||||
|
var fPwd = fData.find('password').text();
|
||||||
|
var fName = fData.find('name').text();
|
||||||
|
|
||||||
|
// Apply the room data
|
||||||
|
if(!nickname && fNick)
|
||||||
|
nickname = fNick;
|
||||||
|
if(!password && fPwd)
|
||||||
|
password = fPwd;
|
||||||
|
if(!title && fName)
|
||||||
|
name = fName;
|
||||||
|
}
|
||||||
|
|
||||||
|
Groupchat.create(hash, xid, name, nickname, password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch to the newly-created chat
|
||||||
|
Interface.switchChan(hash);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Chat.checkCreate', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the chat DOM elements
|
||||||
|
* @public
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} id
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} nick
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.generate = function(type, id, xid, nick) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Generate some stuffs
|
||||||
|
var path = '#' + id + ' .';
|
||||||
|
var escaped_xid = escape(xid);
|
||||||
|
|
||||||
|
// Special code
|
||||||
|
var specialAttributes, specialAvatar, specialName, specialCode, specialLink, specialDisabled, specialStyle, specialMAM;
|
||||||
|
|
||||||
|
// Groupchat special code
|
||||||
|
if(type == 'groupchat') {
|
||||||
|
specialAttributes = ' data-type="groupchat"';
|
||||||
|
specialAvatar = '';
|
||||||
|
specialName = '<p class="bc-infos"><b>' + Common._e("Subject") + '</b> <span class="muc-topic">' + Common._e("no subject defined for this room.") + '</span></p>';
|
||||||
|
specialCode = '<div class="content groupchat-content" id="chat-content-' + id + '"></div><div class="list"><div class="moderator role"><p class="title">' + Common._e("Moderators") + '</p></div><div class="participant role"><p class="title">' + Common._e("Participants") + '</p></div><div class="visitor role"><p class="title">' + Common._e("Visitors") + '</p></div><div class="none role"><p class="title">' + Common._e("Others") + '</p></div></div>';
|
||||||
|
specialLink = '<a href="#" class="tools-mucadmin tools-tooltip talk-images chat-tools-content" title="' + Common._e("Administration panel for this room") + '"></a>';
|
||||||
|
specialStyle = '';
|
||||||
|
|
||||||
|
// Is this a gateway?
|
||||||
|
if(xid.match(/%/))
|
||||||
|
specialDisabled = '';
|
||||||
|
else
|
||||||
|
specialDisabled = ' disabled=""';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chat (or other things?!) special code
|
||||||
|
else {
|
||||||
|
specialMAM = '<div class="wait-mam wait-small"></div>';
|
||||||
|
specialAttributes = ' data-type="chat"';
|
||||||
|
specialAvatar = '<div class="avatar-container"><img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" /></div>';
|
||||||
|
specialName = '<div class="bc-pep"></div><p class="bc-infos"><span class="unavailable show talk-images"></span></p>';
|
||||||
|
specialCode = '<div class="content" id="chat-content-' + id + '">' + specialMAM + '</div>';
|
||||||
|
specialLink = '<a href="#" class="tools-jingle-audio tools-tooltip talk-images chat-tools-content" title="' + Common._e("Call (audio only)") + '"></a>' +
|
||||||
|
'<a href="#" class="tools-jingle-video tools-tooltip talk-images chat-tools-content" title="' + Common._e("Call (video)") + '"></a>' +
|
||||||
|
'<a href="#" class="tools-infos tools-tooltip talk-images chat-tools-content" title="' + Common._e("Show user profile") + '"></a>';
|
||||||
|
specialStyle = ' style="display: none;"';
|
||||||
|
specialDisabled = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not a groupchat private chat, we can use the buddy add icon
|
||||||
|
if((type == 'chat') || (type == 'groupchat')) {
|
||||||
|
var addTitle;
|
||||||
|
|
||||||
|
if(type == 'chat')
|
||||||
|
addTitle = Common._e("Add this contact to your friends");
|
||||||
|
else
|
||||||
|
addTitle = Common._e("Add this groupchat to your favorites");
|
||||||
|
|
||||||
|
specialLink += '<a href="#" class="tools-add tools-tooltip talk-images chat-tools-content" title="' + addTitle + '"></a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
// IE DOM parsing bug fix
|
||||||
|
var specialStylePicker = '<div class="chat-tools-content chat-tools-style"' + specialStyle + '>' +
|
||||||
|
'<a href="#" class="tools-style tools-tooltip talk-images"></a>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9))
|
||||||
|
specialStylePicker = '';
|
||||||
|
|
||||||
|
// Append the chat HTML code
|
||||||
|
$('#page-engine').append(
|
||||||
|
'<div id="' + id + '" class="page-engine-chan chat one-counter"' + specialAttributes + ' data-xid="' + escaped_xid + '">' +
|
||||||
|
'<div class="top ' + id + '">' +
|
||||||
|
specialAvatar +
|
||||||
|
|
||||||
|
'<div class="name">' +
|
||||||
|
'<p class="bc-name bc-name-nick">' + nick.htmlEnc() + '</p>' +
|
||||||
|
specialName +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
specialCode +
|
||||||
|
|
||||||
|
'<div class="text">' +
|
||||||
|
'<div class="footer">' +
|
||||||
|
'<div class="chat-tools-content chat-tools-smileys">' +
|
||||||
|
'<a href="#" class="tools-smileys tools-tooltip talk-images"></a>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
specialStylePicker +
|
||||||
|
|
||||||
|
'<div class="chat-tools-content chat-tools-file">' +
|
||||||
|
'<a href="#" class="tools-file tools-tooltip talk-images"></a>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="chat-tools-content chat-tools-save">' +
|
||||||
|
'<a href="#" class="tools-save tools-tooltip talk-images"></a>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<a href="#" class="tools-clear tools-tooltip talk-images chat-tools-content" title="' + Common._e("Clean current chat") + '"></a>' +
|
||||||
|
|
||||||
|
specialLink +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="compose">' +
|
||||||
|
'<textarea class="message-area focusable" ' + specialDisabled + ' data-to="' + escaped_xid + '" /></textarea>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Click event: chat cleaner
|
||||||
|
$(path + 'tools-clear').click(function() {
|
||||||
|
self.clean(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Click event: call (audio)
|
||||||
|
$(path + 'tools-jingle-audio').click(function() {
|
||||||
|
Jingle.start(xid, 'audio');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Click event: call (video)
|
||||||
|
$(path + 'tools-jingle-video').click(function() {
|
||||||
|
Jingle.start(xid, 'video');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Click event: user-infos
|
||||||
|
$(path + 'tools-infos').click(function() {
|
||||||
|
UserInfos.open(xid);
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Chat.generate', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the chat switch elements
|
||||||
|
* @public
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} id
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} nick
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.generateSwitch = function(type, id, xid, nick) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Path to the element
|
||||||
|
var chat_switch = '#page-switch .';
|
||||||
|
|
||||||
|
// Special code
|
||||||
|
var specialClass = ' unavailable';
|
||||||
|
var show_close = true;
|
||||||
|
|
||||||
|
// Groupchat
|
||||||
|
if(type == 'groupchat') {
|
||||||
|
specialClass = ' groupchat-default';
|
||||||
|
|
||||||
|
if(Utils.isAnonymous() && (xid == Common.generateXID(ANONYMOUS_ROOM, 'groupchat')))
|
||||||
|
show_close = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate the HTML code
|
||||||
|
var html = '<div class="' + id + ' switcher chan" onclick="return Interface.switchChan(\'' + Utils.encodeOnclick(id) + '\')">' +
|
||||||
|
'<div class="icon talk-images' + specialClass + '"></div>' +
|
||||||
|
|
||||||
|
'<div class="name">' + nick.htmlEnc() + '</div>';
|
||||||
|
|
||||||
|
// Show the close button if not MUC and not anonymous
|
||||||
|
if(show_close)
|
||||||
|
html += '<div class="exit" title="' + Common._e("Close this tab") + '" onclick="return Interface.quitThisChat(\'' + Utils.encodeOnclick(xid) + '\', \'' + Utils.encodeOnclick(id) + '\', \'' + Utils.encodeOnclick(type) + '\');">x</div>';
|
||||||
|
|
||||||
|
// Close the HTML
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
// Append the HTML code
|
||||||
|
$(chat_switch + 'chans, ' + chat_switch + 'more-content').append(html);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Chat.generateSwitch', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans given the chat lines
|
||||||
|
* @public
|
||||||
|
* @param {string} chat
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.clean = function(chat) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Remove the messages
|
||||||
|
$('#page-engine #' + chat + ' .content .one-group').remove();
|
||||||
|
|
||||||
|
// Clear the history database
|
||||||
|
Message.removeLocalArchive(chat);
|
||||||
|
|
||||||
|
// Focus again
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
$('#page-engine #' + chat + ' .text .message-area').focus();
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Chat.clean', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether chat exists or not
|
||||||
|
* @public
|
||||||
|
* @param {string} hash
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.exists = function(hash) {
|
||||||
|
|
||||||
|
exists = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(hash) {
|
||||||
|
exists = Common.exists('#' + hash + '.page-engine-chan[data-type="chat"]');
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Chat.exists', e);
|
||||||
|
} finally {
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new chat
|
||||||
|
* @public
|
||||||
|
* @param {string} hash
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} nick
|
||||||
|
* @param {string} type
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.create = function(hash, xid, nick, type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Console.info('New chat: ' + xid);
|
||||||
|
|
||||||
|
// Create the chat content
|
||||||
|
self.generate(type, hash, xid, nick);
|
||||||
|
|
||||||
|
// Create the chat switcher
|
||||||
|
self.generateSwitch(type, hash, xid, nick);
|
||||||
|
|
||||||
|
// If the user is not in our roster
|
||||||
|
if(type == 'chat') {
|
||||||
|
// MAM? Get archives from there!
|
||||||
|
if(Features.enabledMAM()) {
|
||||||
|
MAM.getArchives({
|
||||||
|
'with': xid
|
||||||
|
}, {
|
||||||
|
'max': MAM.REQ_MAX,
|
||||||
|
'before': ''
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Restore the chat history
|
||||||
|
var chat_history = Message.readLocalArchive(hash);
|
||||||
|
|
||||||
|
if(chat_history) {
|
||||||
|
// Generate hashs
|
||||||
|
var my_hash = hex_md5(Common.getXID());
|
||||||
|
var friend_hash = hex_md5(xid);
|
||||||
|
|
||||||
|
// Add chat history HTML
|
||||||
|
$('#' + hash + ' .content').append(chat_history);
|
||||||
|
|
||||||
|
// Filter old groups & messages
|
||||||
|
$('#' + hash + ' .one-group[data-type="user-message"]').addClass('from-history').attr('data-type', 'old-message');
|
||||||
|
$('#' + hash + ' .user-message').removeClass('user-message').addClass('old-message');
|
||||||
|
|
||||||
|
// Regenerate user names
|
||||||
|
$('#' + hash + ' .one-group.' + my_hash + ' b.name').text(Name.getBuddy(Common.getXID()));
|
||||||
|
$('#' + hash + ' .one-group.' + friend_hash + ' b.name').text(Name.getBuddy(xid));
|
||||||
|
|
||||||
|
// Regenerate group dates
|
||||||
|
$('#' + hash + ' .one-group').each(function() {
|
||||||
|
var current_stamp = parseInt($(this).attr('data-stamp'));
|
||||||
|
$(this).find('span.date').text(DateUtils.relative(current_stamp));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Regenerate avatars
|
||||||
|
if(Common.exists('#' + hash + ' .one-group.' + my_hash + ' .avatar-container'))
|
||||||
|
Avatar.get(Common.getXID(), 'cache', 'true', 'forget');
|
||||||
|
if(Common.exists('#' + hash + ' .one-group.' + friend_hash + ' .avatar-container'))
|
||||||
|
Avatar.get(xid, 'cache', 'true', 'forget');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add button
|
||||||
|
if(!Roster.isFriend(xid))
|
||||||
|
$('#' + hash + ' .tools-add').click(function() {
|
||||||
|
// Hide the icon (to tell the user all is okay)
|
||||||
|
$(this).hide();
|
||||||
|
|
||||||
|
// Send the subscribe request
|
||||||
|
Roster.addThisContact(xid, nick);
|
||||||
|
}).show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// We catch the user's informations (like this avatar, vcard, and so on...)
|
||||||
|
UserInfos.get(hash, xid, nick, type);
|
||||||
|
|
||||||
|
// The icons-hover functions
|
||||||
|
Tooltip.icons(xid, hash);
|
||||||
|
|
||||||
|
// The event handlers
|
||||||
|
var inputDetect = $('#page-engine #' + hash + ' .message-area');
|
||||||
|
|
||||||
|
inputDetect.focus(function() {
|
||||||
|
// Clean notifications for this chat
|
||||||
|
Interface.chanCleanNotify(hash);
|
||||||
|
|
||||||
|
// Store focus on this chat!
|
||||||
|
Interface.chat_focus_hash = hash;
|
||||||
|
});
|
||||||
|
|
||||||
|
inputDetect.blur(function() {
|
||||||
|
// Reset storage about focus on this chat!
|
||||||
|
if(Interface.chat_focus_hash == hash)
|
||||||
|
Interface.chat_focus_hash = null;
|
||||||
|
});
|
||||||
|
|
||||||
|
inputDetect.keypress(function(e) {
|
||||||
|
// Enter key
|
||||||
|
if(e.keyCode == 13) {
|
||||||
|
// Add a new line
|
||||||
|
if(e.shiftKey || e.ctrlKey) {
|
||||||
|
inputDetect.val(inputDetect.val() + '\n');
|
||||||
|
} else {
|
||||||
|
// Send the message
|
||||||
|
Message.send(hash, 'chat');
|
||||||
|
|
||||||
|
// Reset the composing database entry
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Scroll in chat content
|
||||||
|
$('#page-engine #' + hash + ' .content').scroll(function() {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if(Features.enabledMAM() && !(xid in MAM.map_pending)) {
|
||||||
|
var has_state = xid in MAM.map_states;
|
||||||
|
var rsm_count = has_state ? MAM.map_states[xid].rsm.count : 1;
|
||||||
|
var rsm_before = has_state ? MAM.map_states[xid].rsm.first : '';
|
||||||
|
|
||||||
|
// Request more archives?
|
||||||
|
if(rsm_count > 0 && $(this).scrollTop() < MAM.SCROLL_THRESHOLD) {
|
||||||
|
var was_scroll_top = $(self).scrollTop() <= 32;
|
||||||
|
var wait_mam = $('#' + hash).find('.wait-mam');
|
||||||
|
wait_mam.show();
|
||||||
|
|
||||||
|
MAM.getArchives({
|
||||||
|
'with': xid
|
||||||
|
}, {
|
||||||
|
'max': MAM.REQ_MAX,
|
||||||
|
'before': rsm_before
|
||||||
|
}, function() {
|
||||||
|
var wait_mam_height = was_scroll_top ? 0 : wait_mam.height();
|
||||||
|
wait_mam.hide();
|
||||||
|
|
||||||
|
// Restore scroll?
|
||||||
|
if($(self).scrollTop() < MAM.SCROLL_THRESHOLD) {
|
||||||
|
var sel_mam_chunk = $(self).find('.mam-chunk:first');
|
||||||
|
|
||||||
|
var cont_padding_top = parseInt($(self).css('padding-top').replace(/[^-\d\.]/g, ''));
|
||||||
|
var cont_one_group_margin_bottom = parseInt(sel_mam_chunk.find('.one-group:last').css('margin-bottom').replace(/[^-\d\.]/g, ''));
|
||||||
|
var cont_mam_chunk_height = sel_mam_chunk.height();
|
||||||
|
|
||||||
|
$(self).scrollTop(wait_mam_height + cont_padding_top + cont_one_group_margin_bottom + cont_mam_chunk_height);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Chatstate events
|
||||||
|
ChatState.events(inputDetect, xid, hash, 'chat');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Chat.create', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
242
source/app/javascripts/chatstate.js
Normal file
|
@ -0,0 +1,242 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the chatstate JS script for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var ChatState = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a given chatstate to a given entity
|
||||||
|
* @public
|
||||||
|
* @param {string} state
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} hash
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.send = function(state, xid, hash) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var user_type = $('#' + hash).attr('data-type');
|
||||||
|
|
||||||
|
// If the friend client supports chatstates and is online
|
||||||
|
if((user_type == 'groupchat') || ((user_type == 'chat') && $('#' + hash + ' .message-area').attr('data-chatstates') && !Common.exists('#page-switch .' + hash + ' .unavailable'))) {
|
||||||
|
// Already sent?
|
||||||
|
if(DataStore.getDB(Connection.desktop_hash, 'currentchatstate', xid) == state)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Write the state
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'currentchatstate', xid, state);
|
||||||
|
|
||||||
|
// New message stanza
|
||||||
|
var aMsg = new JSJaCMessage();
|
||||||
|
aMsg.setTo(xid);
|
||||||
|
aMsg.setType(user_type);
|
||||||
|
|
||||||
|
// Append the chatstate node
|
||||||
|
aMsg.appendNode(state, {'xmlns': NS_CHATSTATES});
|
||||||
|
|
||||||
|
// Send this!
|
||||||
|
con.send(aMsg);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('ChatState.send', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a given chatstate in a given chat
|
||||||
|
* @public
|
||||||
|
* @param {string} state
|
||||||
|
* @param {string} hash
|
||||||
|
* @param {string} type
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.display = function(state, hash, type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Groupchat?
|
||||||
|
if(type == 'groupchat') {
|
||||||
|
self.reset(hash, type);
|
||||||
|
|
||||||
|
// "gone" state not allowed
|
||||||
|
if(state != 'gone')
|
||||||
|
$('#page-engine .page-engine-chan .user.' + hash).addClass(state);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Chat
|
||||||
|
else {
|
||||||
|
// We change the buddy name color in the page-switch
|
||||||
|
self.reset(hash, type);
|
||||||
|
$('#page-switch .' + hash + ' .name').addClass(state);
|
||||||
|
|
||||||
|
// We generate the chatstate text
|
||||||
|
var text = '';
|
||||||
|
|
||||||
|
switch(state) {
|
||||||
|
// Active
|
||||||
|
case 'active':
|
||||||
|
text = Common._e("Your friend is paying attention to the conversation.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Composing
|
||||||
|
case 'composing':
|
||||||
|
text = Common._e("Your friend is writing a message...");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Paused
|
||||||
|
case 'paused':
|
||||||
|
text = Common._e("Your friend stopped writing a message.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Inactive
|
||||||
|
case 'inactive':
|
||||||
|
text = Common._e("Your friend is doing something else.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Gone
|
||||||
|
case 'gone':
|
||||||
|
text = Common._e("Your friend closed the chat.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We reset the previous state
|
||||||
|
$('#' + hash + ' .chatstate').remove();
|
||||||
|
|
||||||
|
// We create the chatstate
|
||||||
|
$('#' + hash + ' .content').after('<div class="' + state + ' chatstate">' + text + '</div>');
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('ChatState.display', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the chatstate switcher marker
|
||||||
|
* @public
|
||||||
|
* @param {string} hash
|
||||||
|
* @param {string} type
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.reset = function(hash, type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Define the selector
|
||||||
|
var selector;
|
||||||
|
|
||||||
|
if(type == 'groupchat')
|
||||||
|
selector = $('#page-engine .page-engine-chan .user.' + hash);
|
||||||
|
else
|
||||||
|
selector = $('#page-switch .' + hash + ' .name');
|
||||||
|
|
||||||
|
// Reset!
|
||||||
|
selector.removeClass('active composing paused inactive gone');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('ChatState.reset', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the chatstate events
|
||||||
|
* @public
|
||||||
|
* @param {object} target
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} hash
|
||||||
|
* @param {string} type
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.events = function(target, xid, hash, type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
target.keyup(function(e) {
|
||||||
|
if(e.keyCode != 13) {
|
||||||
|
// Composing a message
|
||||||
|
if($(this).val() && (DataStore.getDB(Connection.desktop_hash, 'chatstate', xid) != 'on')) {
|
||||||
|
// We change the state detect input
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'on');
|
||||||
|
|
||||||
|
// We send the friend a "composing" chatstate
|
||||||
|
self.send('composing', xid, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Flushed the message which was being composed
|
||||||
|
else if(!$(this).val() && (DataStore.getDB(Connection.desktop_hash, 'chatstate', xid) == 'on')) {
|
||||||
|
// We change the state detect input
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
|
||||||
|
|
||||||
|
// We send the friend an "active" chatstate
|
||||||
|
self.send('active', xid, hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
target.change(function() {
|
||||||
|
// Reset the composing database entry
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'chatstate', xid, 'off');
|
||||||
|
});
|
||||||
|
|
||||||
|
target.focus(function() {
|
||||||
|
// Not needed
|
||||||
|
if(target.is(':disabled'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Something was written, user started writing again
|
||||||
|
if($(this).val())
|
||||||
|
self.send('composing', xid, hash);
|
||||||
|
|
||||||
|
// Chat only: Nothing in the input, user is active
|
||||||
|
else if(type == 'chat')
|
||||||
|
self.send('active', xid, hash);
|
||||||
|
});
|
||||||
|
|
||||||
|
target.blur(function() {
|
||||||
|
// Not needed
|
||||||
|
if(target.is(':disabled'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Something was written, user paused
|
||||||
|
if($(this).val())
|
||||||
|
self.send('paused', xid, hash);
|
||||||
|
|
||||||
|
// Chat only: Nothing in the input, user is inactive
|
||||||
|
else if(type == 'chat')
|
||||||
|
self.send('inactive', xid, hash);
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('ChatState.events', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
763
source/app/javascripts/common.js
Normal file
|
@ -0,0 +1,763 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the common JS script for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: dual-licensed under AGPL and MPLv2
|
||||||
|
Authors: Valérian Saliou, olivierm, regilero, Maranda
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Common = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if an element exists in the DOM
|
||||||
|
* @public
|
||||||
|
* @param {string} path
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.exists = function(path) {
|
||||||
|
|
||||||
|
var exists = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(jQuery(path).size() > 0) {
|
||||||
|
exists = true;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.exists', e);
|
||||||
|
} finally {
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if Jappix is connected
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.isConnected = function() {
|
||||||
|
|
||||||
|
connected = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if((typeof con != 'undefined') && con && con.connected()) {
|
||||||
|
connected = true;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.isConnected', e);
|
||||||
|
} finally {
|
||||||
|
return connected;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if Jappix is connected
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.hasWebSocket = function() {
|
||||||
|
|
||||||
|
has_websocket = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(HOST_WEBSOCKET && typeof window.WebSocket != 'undefined') {
|
||||||
|
has_websocket = true;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.hasWebSocket', e);
|
||||||
|
} finally {
|
||||||
|
return has_websocket;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if Jappix has focus
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.isFocused = function() {
|
||||||
|
|
||||||
|
has_focus = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(!document.hasFocus()) {
|
||||||
|
has_focus = false;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.isFocused', e);
|
||||||
|
} finally {
|
||||||
|
return has_focus;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the good XID
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} type
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.generateXID = function(xid, type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// XID needs to be transformed
|
||||||
|
// .. and made lowercase (uncertain though this is the right place...)
|
||||||
|
xid = xid.toLowerCase();
|
||||||
|
|
||||||
|
if(xid && (xid.indexOf('@') == -1)) {
|
||||||
|
// Groupchat
|
||||||
|
if(type == 'groupchat')
|
||||||
|
return xid + '@' + HOST_MUC;
|
||||||
|
|
||||||
|
// One-to-one chat
|
||||||
|
if(xid.indexOf('.') == -1)
|
||||||
|
return xid + '@' + HOST_MAIN;
|
||||||
|
|
||||||
|
// It might be a gateway?
|
||||||
|
return xid;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing special (yet bare XID)
|
||||||
|
return xid;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.generateXID', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the asked translated string
|
||||||
|
* @public
|
||||||
|
* @param {string} string
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self._e = function(string) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return string;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common._e', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replaces '%s' to a given value for a translated string
|
||||||
|
* @public
|
||||||
|
* @param {string} string
|
||||||
|
* @param {string} value
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.printf = function(string, value) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return string.replace('%s', value);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.printf', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the string after the last given char
|
||||||
|
* @public
|
||||||
|
* @param {string} given_char
|
||||||
|
* @param {string} str
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.strAfterLast = function(given_char, str) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(!given_char || !str)
|
||||||
|
return '';
|
||||||
|
|
||||||
|
var char_index = str.lastIndexOf(given_char);
|
||||||
|
var str_return = str;
|
||||||
|
|
||||||
|
if(char_index >= 0)
|
||||||
|
str_return = str.substr(char_index + 1);
|
||||||
|
|
||||||
|
return str_return;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.strAfterLast', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Properly explodes a string with a given character
|
||||||
|
* @public
|
||||||
|
* @param {string} toEx
|
||||||
|
* @param {string} toStr
|
||||||
|
* @param {number} i
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.explodeThis = function(toEx, toStr, i) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get the index of our char to explode
|
||||||
|
var index = toStr.indexOf(toEx);
|
||||||
|
|
||||||
|
// We split if necessary the string
|
||||||
|
if(index !== -1) {
|
||||||
|
if(i === 0)
|
||||||
|
toStr = toStr.substr(0, index);
|
||||||
|
else
|
||||||
|
toStr = toStr.substr(index + 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We return the value
|
||||||
|
return toStr;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.explodeThis', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cuts the resource of a XID
|
||||||
|
* @public
|
||||||
|
* @param {string} aXID
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.cutResource = function(aXID) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.explodeThis('/', aXID, 0);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.cutResource', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the resource of a XID
|
||||||
|
* @public
|
||||||
|
* @param {string} aXID
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.thisResource = function(aXID) {
|
||||||
|
|
||||||
|
resource = '';
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Any resource?
|
||||||
|
if(self.isFullXID(aXID)) {
|
||||||
|
resource = self.explodeThis('/', aXID, 1);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.thisResource', e);
|
||||||
|
} finally {
|
||||||
|
return resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether this XID is full or not
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.isFullXID = function(xid) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return xid.indexOf('/') !== -1;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.isFullXID', e);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* nodepreps an XMPP node
|
||||||
|
* @public
|
||||||
|
* @param {string} node
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.nodeprep = function(node) {
|
||||||
|
|
||||||
|
// Spec: http://tools.ietf.org/html/rfc6122#appendix-A
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(!node)
|
||||||
|
return node;
|
||||||
|
|
||||||
|
// Remove prohibited chars
|
||||||
|
var prohibited_chars = ['"', '&', '\'', '/', ':', '<', '>', '@'];
|
||||||
|
|
||||||
|
for(var j in prohibited_chars) {
|
||||||
|
node = node.replace(prohibited_chars[j], '');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lower case
|
||||||
|
node = node.toLowerCase();
|
||||||
|
|
||||||
|
return node;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.nodeprep', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Encodes quotes in a string
|
||||||
|
* @public
|
||||||
|
* @param {string} str
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.encodeQuotes = function(str) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (str + '').htmlEnc();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.encodeQuotes', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the bare XID from a XID
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.bareXID = function(xid) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Cut the resource
|
||||||
|
xid = self.cutResource(xid);
|
||||||
|
|
||||||
|
// Launch nodeprep
|
||||||
|
if(xid.indexOf('@') != -1)
|
||||||
|
xid = self.nodeprep(self.getXIDNick(xid)) + '@' + self.getXIDHost(xid);
|
||||||
|
|
||||||
|
return xid;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.bareXID', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the full XID from a XID
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.fullXID = function(xid) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Normalizes the XID
|
||||||
|
var full = self.bareXID(xid);
|
||||||
|
var resource = self.thisResource(xid);
|
||||||
|
|
||||||
|
// Any resource?
|
||||||
|
if(resource)
|
||||||
|
full += '/' + resource;
|
||||||
|
|
||||||
|
return full;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.fullXID', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the nick from a XID
|
||||||
|
* @public
|
||||||
|
* @param {string} aXID
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.getXIDNick = function(aXID) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Gateway nick?
|
||||||
|
if(aXID.match(/\\40/))
|
||||||
|
return self.explodeThis('\\40', aXID, 0);
|
||||||
|
|
||||||
|
return self.explodeThis('@', aXID, 0);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.getXIDNick', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the host from a XID
|
||||||
|
* @public
|
||||||
|
* @param {string} aXID
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.getXIDHost = function(aXID) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.explodeThis('@', aXID, 1);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.getXIDHost', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if we are RTL (Right-To-Left)
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.isRTL = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (self._e("default:LTR") == 'default:RTL');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.isRTL', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if anonymous mode is allowed
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.allowedAnonymous = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (ANONYMOUS == 'on');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.allowedAnonymous', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if host is locked
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.lockHost = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (LOCK_HOST == 'on');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.lockHost', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the full XID of the user
|
||||||
|
* @public
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.getXID = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Return the XID of the user
|
||||||
|
if(con.username && con.domain) {
|
||||||
|
return con.username + '@' + con.domain;
|
||||||
|
}
|
||||||
|
|
||||||
|
return '';
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.getXID', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the colors for a given user XID
|
||||||
|
* @public
|
||||||
|
* @param {type} xid
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.generateColor = function(xid) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var colors = new Array(
|
||||||
|
'ac0000',
|
||||||
|
'a66200',
|
||||||
|
'007703',
|
||||||
|
'00705f',
|
||||||
|
'00236b',
|
||||||
|
'4e005c'
|
||||||
|
);
|
||||||
|
|
||||||
|
var number = 0;
|
||||||
|
|
||||||
|
for(var i = 0; i < xid.length; i++) {
|
||||||
|
number += xid.charCodeAt(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
var color = '#' + colors[number % (colors.length)];
|
||||||
|
|
||||||
|
return color;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.generateColor', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the XID is a gateway
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.isGateway = function(xid) {
|
||||||
|
|
||||||
|
is_gateway = true;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(xid.indexOf('@') != -1) {
|
||||||
|
is_gateway = false;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.isGateway', e);
|
||||||
|
} finally {
|
||||||
|
return is_gateway;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the from attribute of a stanza (overrides some servers like Prosody missing from attributes)
|
||||||
|
* @public
|
||||||
|
* @param {object} stanza
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.getStanzaFrom = function(stanza) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var from = stanza.getFrom();
|
||||||
|
|
||||||
|
// No from, we assume this is our XID
|
||||||
|
if(!from)
|
||||||
|
from = self.getXID();
|
||||||
|
|
||||||
|
return from;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.getStanzaFrom', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a zero to a date when needed
|
||||||
|
* @public
|
||||||
|
* @param {number} i
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.padZero = function(i) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Negative number (without first 0)
|
||||||
|
if(i > -10 && i < 0)
|
||||||
|
return '-0' + (i * -1);
|
||||||
|
|
||||||
|
// Positive number (without first 0)
|
||||||
|
if(i < 10 && i >= 0)
|
||||||
|
return '0' + i;
|
||||||
|
|
||||||
|
// All is okay
|
||||||
|
return i;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.padZero', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Escapes a string for a regex usage
|
||||||
|
* @public
|
||||||
|
* @param {string} query
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.escapeRegex = function(query) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return query.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, '\\$&');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.escapeRegex', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a random array value
|
||||||
|
* @public
|
||||||
|
* @param {object} arr
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.randomArrayValue = function(arr) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return arr[Math.floor(Math.random() * arr.length)];
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.randomArrayValue', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns whether the browser is mobile or not
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.isMobile = function() {
|
||||||
|
|
||||||
|
is_mobile = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
is_mobile = /Android|iPhone|iPod|iPad|Windows Phone|BlackBerry|Bada|Maemo|Meego|webOS/i.test(navigator.userAgent);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.isMobile', e);
|
||||||
|
} finally {
|
||||||
|
return is_mobile;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a XML document to a string
|
||||||
|
* @public
|
||||||
|
* @param {object} xmlData
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.xmlToString = function(xmlData) {
|
||||||
|
|
||||||
|
xml_str = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// For Mozilla, Firefox, Opera, etc.
|
||||||
|
if(window.XMLSerializer) {
|
||||||
|
xml_str = (new XMLSerializer()).serializeToString(xmlData);
|
||||||
|
}
|
||||||
|
|
||||||
|
// For Internet Explorer
|
||||||
|
if(window.ActiveXObject) {
|
||||||
|
xml_str = xmlData.xml;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.xmlToString', e);
|
||||||
|
} finally {
|
||||||
|
return xml_str;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts a string to a XML document
|
||||||
|
* @public
|
||||||
|
* @param {string} sXML
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.XMLFromString = function(sXML) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// No data?
|
||||||
|
if(!sXML) {
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the XML tag
|
||||||
|
if(!sXML.match(/^<\?xml/i)) {
|
||||||
|
sXML = '<?xml version="1.0"?>' + sXML;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Parse it!
|
||||||
|
if(window.DOMParser) {
|
||||||
|
return (new DOMParser()).parseFromString(sXML, 'text/xml');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(window.ActiveXObject) {
|
||||||
|
var oXML = new ActiveXObject('Microsoft.XMLDOM');
|
||||||
|
oXML.loadXML(sXML);
|
||||||
|
|
||||||
|
return oXML;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.XMLFromString', e);
|
||||||
|
|
||||||
|
return '';
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watches for input value change (delays callback)
|
||||||
|
* @public
|
||||||
|
* @param {function} cb
|
||||||
|
* @return {function}
|
||||||
|
*/
|
||||||
|
self.typewatch = function(cb) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var timer = 0;
|
||||||
|
|
||||||
|
return function(callback, ms) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = setTimeout(callback, ms);
|
||||||
|
};
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Common.typewatch', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
var JappixCommon = Common;
|
926
source/app/javascripts/connection.js
Normal file
|
@ -0,0 +1,926 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the connection JS script for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Authors: Valérian Saliou, Maranda
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Connection = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
self.current_session = false;
|
||||||
|
self.desktop_hash = null;
|
||||||
|
self.connected = false;
|
||||||
|
self.reconnect_try = 0;
|
||||||
|
self.reconnect_timer = 0;
|
||||||
|
self.resume = false;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the user login
|
||||||
|
* @public
|
||||||
|
* @param {string} lNick
|
||||||
|
* @param {string} lServer
|
||||||
|
* @param {string} lPass
|
||||||
|
* @param {string} lResource
|
||||||
|
* @param {number} lPriority
|
||||||
|
* @param {boolean} lRemember
|
||||||
|
* @param {object} loginOpts
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.doLogin = function(lNick, lServer, lPass, lResource, lPriority, lRemember, loginOpts) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// get optionnal conn handlers
|
||||||
|
oExtend = loginOpts || {};
|
||||||
|
|
||||||
|
// We remove the not completed class to avoid problems
|
||||||
|
$('#home .loginer input').removeClass('please-complete');
|
||||||
|
|
||||||
|
// We add the login wait div
|
||||||
|
Interface.showGeneralWait();
|
||||||
|
|
||||||
|
if(Common.hasWebSocket()) {
|
||||||
|
// WebSocket supported & configured
|
||||||
|
con = new JSJaCWebSocketConnection({
|
||||||
|
httpbase: HOST_WEBSOCKET
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
|
||||||
|
|
||||||
|
// Check BOSH origin
|
||||||
|
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
|
||||||
|
|
||||||
|
// We create the new http-binding connection
|
||||||
|
con = new JSJaCHttpBindingConnection({
|
||||||
|
httpbase: httpbase
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// And we handle everything that happen
|
||||||
|
self.setupCon(con, oExtend);
|
||||||
|
|
||||||
|
// Generate a resource
|
||||||
|
var random_resource = DataStore.getDB(self.desktop_hash, 'session', 'resource');
|
||||||
|
|
||||||
|
if(!random_resource) {
|
||||||
|
random_resource = lResource + ' (' + (new Date()).getTime() + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
// We retrieve what the user typed in the login inputs
|
||||||
|
oArgs = {};
|
||||||
|
oArgs.domain = $.trim(lServer);
|
||||||
|
oArgs.username = $.trim(lNick);
|
||||||
|
oArgs.resource = random_resource;
|
||||||
|
oArgs.pass = lPass;
|
||||||
|
oArgs.secure = true;
|
||||||
|
oArgs.xmllang = XML_LANG;
|
||||||
|
|
||||||
|
self.desktop_hash = 'jd.' + hex_md5(oArgs.username + '@' + oArgs.domain);
|
||||||
|
|
||||||
|
// Store the resource (for reconnection)
|
||||||
|
DataStore.setDB(self.desktop_hash, 'session', 'resource', random_resource);
|
||||||
|
|
||||||
|
// Store session XML in temporary database
|
||||||
|
self.storeSession(lNick, lServer, lPass, lResource, lPriority, lRemember);
|
||||||
|
|
||||||
|
// We store the infos of the user into the data-base
|
||||||
|
DataStore.setDB(self.desktop_hash, 'priority', 1, lPriority);
|
||||||
|
|
||||||
|
// We connect !
|
||||||
|
con.connect(oArgs);
|
||||||
|
|
||||||
|
// Change the page title
|
||||||
|
Interface.title('wait');
|
||||||
|
|
||||||
|
Console.info('Jappix is connecting...');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.doLogin', e);
|
||||||
|
|
||||||
|
// Reset Jappix
|
||||||
|
Talk.destroy();
|
||||||
|
|
||||||
|
// Open an unknown error
|
||||||
|
Board.openThisError(2);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the user registration
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.handleRegistered = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Console.info('A new account has been registered.');
|
||||||
|
|
||||||
|
// We remove the waiting image
|
||||||
|
Interface.removeGeneralWait();
|
||||||
|
|
||||||
|
// Reset the title
|
||||||
|
Interface.title('home');
|
||||||
|
|
||||||
|
// We show the success information
|
||||||
|
$('#home .registerer .success').fadeIn('fast');
|
||||||
|
|
||||||
|
// We quit the session
|
||||||
|
if(Common.isConnected()) {
|
||||||
|
self.logout();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.handleRegistered', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the user registration
|
||||||
|
* @public
|
||||||
|
* @param {string} username
|
||||||
|
* @param {string} domain
|
||||||
|
* @param {string} pass
|
||||||
|
* @param {string} captcha
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.doRegister = function(username, domain, pass, captcha) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Console.info('Trying to register an account...');
|
||||||
|
|
||||||
|
// We change the registered information text
|
||||||
|
$('#home .homediv.registerer').append(
|
||||||
|
'<div class="info success">' +
|
||||||
|
Common._e("You have been registered, here is your XMPP address:") + ' <b>' + username.htmlEnc() + '@' + domain.htmlEnc() + '</b> - <a href="#">' + Common._e("Login") + '</a>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Login link
|
||||||
|
$('#home .homediv.registerer .success a').click(function() {
|
||||||
|
return self.doLogin(username, domain, pass, '', '10', false);
|
||||||
|
});
|
||||||
|
|
||||||
|
if((REGISTER_API == 'on') && (domain == HOST_MAIN) && captcha) {
|
||||||
|
// Show the waiting image
|
||||||
|
Interface.showGeneralWait();
|
||||||
|
|
||||||
|
// Change the page title
|
||||||
|
Interface.title('wait');
|
||||||
|
|
||||||
|
// Send request
|
||||||
|
$.post('./server/register.php', {username: username, domain: domain, password: pass, captcha: captcha}, function(data) {
|
||||||
|
// Error registering
|
||||||
|
Interface.removeGeneralWait();
|
||||||
|
Interface.title('home');
|
||||||
|
|
||||||
|
// In all case, update CAPTCHA
|
||||||
|
$('#home img.captcha_img').attr('src', './server/captcha.php?id=' + genID());
|
||||||
|
$('#home input.captcha').val('');
|
||||||
|
|
||||||
|
// Registration okay
|
||||||
|
if($(data).find('query status').text() == '1') {
|
||||||
|
self.handleRegistered();
|
||||||
|
} else {
|
||||||
|
// Show error message
|
||||||
|
var error_message = '';
|
||||||
|
|
||||||
|
switch($(data).find('query message').text()) {
|
||||||
|
case 'CAPTCHA Not Matching':
|
||||||
|
error_message = Common._e("The security code you entered is invalid. Please retry with another one.");
|
||||||
|
|
||||||
|
$('#home input.captcha').focus();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'Username Unavailable':
|
||||||
|
error_message = Common._e("The username you picked is not available. Please try another one.");
|
||||||
|
|
||||||
|
$('#home input.nick').focus();
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
error_message = Common._e("There was an error registering your account. Please retry.");
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(error_message)
|
||||||
|
Errors.show('', error_message, '');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
oArgs = {};
|
||||||
|
|
||||||
|
if(Common.hasWebSocket()) {
|
||||||
|
// WebSocket supported & configured
|
||||||
|
con = new JSJaCWebSocketConnection({
|
||||||
|
httpbase: HOST_WEBSOCKET
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
|
||||||
|
|
||||||
|
// Check BOSH origin
|
||||||
|
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
|
||||||
|
|
||||||
|
// We create the new http-binding connection
|
||||||
|
con = new JSJaCHttpBindingConnection({
|
||||||
|
httpbase: httpbase
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// We setup the connection !
|
||||||
|
con.registerHandler('onconnect', self.handleRegistered);
|
||||||
|
con.registerHandler('onerror', Errors.handle);
|
||||||
|
|
||||||
|
// We retrieve what the user typed in the register inputs
|
||||||
|
oArgs = {};
|
||||||
|
oArgs.domain = $.trim(domain);
|
||||||
|
oArgs.username = $.trim(username);
|
||||||
|
oArgs.resource = JAPPIX_RESOURCE + ' Register (' + (new Date()).getTime() + ')';
|
||||||
|
oArgs.pass = pass;
|
||||||
|
oArgs.register = true;
|
||||||
|
oArgs.secure = true;
|
||||||
|
oArgs.xmllang = XML_LANG;
|
||||||
|
|
||||||
|
con.connect(oArgs);
|
||||||
|
|
||||||
|
// Show the waiting image
|
||||||
|
Interface.showGeneralWait();
|
||||||
|
|
||||||
|
// Change the page title
|
||||||
|
Interface.title('wait');
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(e) {
|
||||||
|
// Logs errors
|
||||||
|
Console.error('doRegister', e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.doRegister', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Does the user anonymous login
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.doAnonymous = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Console.info('Trying to login anonymously...');
|
||||||
|
|
||||||
|
var aPath = '#home .anonymouser ';
|
||||||
|
var room = $(aPath + '.room').val();
|
||||||
|
var nick = $(aPath + '.nick').val();
|
||||||
|
|
||||||
|
// If the form is correctly completed
|
||||||
|
if(room && nick) {
|
||||||
|
// We remove the not completed class to avoid problems
|
||||||
|
$('#home .anonymouser input').removeClass('please-complete');
|
||||||
|
|
||||||
|
// Redirect the user to the anonymous room
|
||||||
|
window.location.href = JAPPIX_LOCATION + '?r=' + room + '&n=' + nick;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We check if the form is entirely completed
|
||||||
|
else {
|
||||||
|
$(aPath + 'input[type="text"]').each(function() {
|
||||||
|
var select = $(this);
|
||||||
|
|
||||||
|
if(!select.val())
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
select.addClass('please-complete').focus();
|
||||||
|
});
|
||||||
|
else
|
||||||
|
select.removeClass('please-complete');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.doAnonymous', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the user connected event
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.handleConnected = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Console.info('Jappix is now connected.');
|
||||||
|
|
||||||
|
// Connection markers
|
||||||
|
self.connected = true;
|
||||||
|
self.reconnect_try = 0;
|
||||||
|
self.reconnect_timer = 0;
|
||||||
|
|
||||||
|
// We hide the home page
|
||||||
|
$('#home').hide();
|
||||||
|
|
||||||
|
// Any suggest to do before triggering connected event?
|
||||||
|
Groupchat.suggestCheck();
|
||||||
|
|
||||||
|
// Remove the waiting item
|
||||||
|
Interface.removeGeneralWait();
|
||||||
|
|
||||||
|
// Init Jingle
|
||||||
|
Jingle.init();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.handleConnected', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Triggers the connected state
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.triggerConnected = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Not resumed?
|
||||||
|
if(!self.resume) {
|
||||||
|
// Remember the session?
|
||||||
|
if(DataStore.getDB(self.desktop_hash, 'remember', 'session'))
|
||||||
|
DataStore.setPersistent('global', 'session', 1, self.current_session);
|
||||||
|
|
||||||
|
// We show the chatting app.
|
||||||
|
Talk.create();
|
||||||
|
|
||||||
|
// We reset the homepage
|
||||||
|
Home.change('default');
|
||||||
|
|
||||||
|
// We get all the other things
|
||||||
|
self.getEverything();
|
||||||
|
|
||||||
|
// Set last activity stamp
|
||||||
|
DateUtils.last_activity = DateUtils.getTimeStamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Resumed
|
||||||
|
else {
|
||||||
|
// Send our presence
|
||||||
|
Presence.sendActions();
|
||||||
|
|
||||||
|
// Change the title
|
||||||
|
Interface.updateTitle();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.triggerConnected', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the user disconnected event
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.handleDisconnected = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Console.info('Jappix is now disconnected.');
|
||||||
|
|
||||||
|
// Normal disconnection
|
||||||
|
if(!self.current_session && !self.connected) {
|
||||||
|
Talk.destroy();
|
||||||
|
self.desktop_hash = null;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.handleDisconnected', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Setups the normal connection
|
||||||
|
* @public
|
||||||
|
* @param {object} con
|
||||||
|
* @param {object} oExtend
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.setupCon = function(con, oExtend) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Setup connection handlers
|
||||||
|
con.registerHandler('message', Message.handle);
|
||||||
|
con.registerHandler('presence', Presence.handle);
|
||||||
|
con.registerHandler('iq', IQ.handle);
|
||||||
|
con.registerHandler('onconnect', self.handleConnected);
|
||||||
|
con.registerHandler('onerror', Errors.handle);
|
||||||
|
con.registerHandler('ondisconnect', self.handleDisconnected);
|
||||||
|
|
||||||
|
// Extended handlers
|
||||||
|
oExtend = oExtend || {};
|
||||||
|
|
||||||
|
jQuery.each(oExtend, function(keywd,funct) {
|
||||||
|
con.registerHandler(keywd, funct);
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.setupCon', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logouts from the server
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.logout = function() {
|
||||||
|
|
||||||
|
logout_done = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(Common.isConnected()) {
|
||||||
|
Console.info('Jappix is disconnecting...');
|
||||||
|
|
||||||
|
// Disconnect from the XMPP server
|
||||||
|
con.disconnect();
|
||||||
|
|
||||||
|
logout_done = true;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.logout', e);
|
||||||
|
} finally {
|
||||||
|
return logout_done;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminates the user session
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.terminate = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(Common.isConnected()) {
|
||||||
|
// Clear temporary session storage
|
||||||
|
self.resetConMarkers();
|
||||||
|
|
||||||
|
// Show the waiting item (useful if BOSH is sloooow)
|
||||||
|
Interface.showGeneralWait();
|
||||||
|
|
||||||
|
// Change the page title
|
||||||
|
Interface.title('wait');
|
||||||
|
|
||||||
|
// Disconnect from the XMPP server
|
||||||
|
self.logout();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.terminate', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quits a session
|
||||||
|
* @public
|
||||||
|
* @param {type} name
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.quit = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(!Common.isConnected()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We show the waiting image
|
||||||
|
Interface.showGeneralWait();
|
||||||
|
|
||||||
|
// Change the page title
|
||||||
|
Interface.title('wait');
|
||||||
|
|
||||||
|
// We disconnect from the XMPP server
|
||||||
|
self.logout();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.quit', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the reconnect pane
|
||||||
|
* @public
|
||||||
|
* @param {string} mode
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.createReconnect = function(mode) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Console.error('This is not a normal disconnection, show the reconnect pane...');
|
||||||
|
|
||||||
|
// Reconnect pane not yet displayed?
|
||||||
|
if(!Common.exists('#reconnect')) {
|
||||||
|
// Blur the focused input/textarea/select
|
||||||
|
$('input, select, textarea').blur();
|
||||||
|
|
||||||
|
// Create the HTML code
|
||||||
|
var html = '<div id="reconnect" class="lock">' +
|
||||||
|
'<div class="pane">' +
|
||||||
|
Common._e("Due to a network issue, you were disconnected. What do you want to do now?");
|
||||||
|
|
||||||
|
// Can we cancel reconnection?
|
||||||
|
if(mode == 'normal')
|
||||||
|
html += '<a href="#" class="finish cancel">' + Common._e("Cancel") + '</a>';
|
||||||
|
|
||||||
|
html += '<a href="#" class="finish reconnect">' + Common._e("Reconnect") + '</a>' +
|
||||||
|
'</div></div>';
|
||||||
|
|
||||||
|
// Append the code
|
||||||
|
$('body').append(html);
|
||||||
|
|
||||||
|
// Click events
|
||||||
|
if(mode == 'normal')
|
||||||
|
$('#reconnect a.finish.cancel').click(function() {
|
||||||
|
return self.cancelReconnect();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#reconnect a.finish.reconnect').click(function() {
|
||||||
|
return self.acceptReconnect(mode);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Try to reconnect automatically after a while
|
||||||
|
if(self.reconnect_try < 5)
|
||||||
|
self.reconnect_timer = 5 + (5 * self.reconnect_try);
|
||||||
|
else
|
||||||
|
self.reconnect_timer = 120;
|
||||||
|
|
||||||
|
// Change the try number
|
||||||
|
self.reconnect_try++;
|
||||||
|
|
||||||
|
// Fire the event!
|
||||||
|
$('#reconnect a.finish.reconnect').everyTime('1s', function() {
|
||||||
|
// We can reconnect!
|
||||||
|
if(self.reconnect_timer === 0)
|
||||||
|
return self.acceptReconnect(mode);
|
||||||
|
|
||||||
|
// Button text
|
||||||
|
if(self.reconnect_timer <= 10)
|
||||||
|
$(this).text(Common._e("Reconnect") + ' (' + self.reconnect_timer + ')');
|
||||||
|
|
||||||
|
// Remove 1 second
|
||||||
|
self.reconnect_timer--;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Page title
|
||||||
|
Interface.updateTitle();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.createReconnect', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reconnects the user if he was disconnected (network issue)
|
||||||
|
* @public
|
||||||
|
* @param {string} mode
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.acceptReconnect = function(mode) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Console.info('Trying to reconnect the user...');
|
||||||
|
|
||||||
|
// Resume marker
|
||||||
|
self.resume = true;
|
||||||
|
|
||||||
|
// Show waiting item
|
||||||
|
Interface.showGeneralWait();
|
||||||
|
|
||||||
|
// Reset some various stuffs
|
||||||
|
var groupchats = '#page-engine .page-engine-chan[data-type="groupchat"]';
|
||||||
|
$(groupchats + ' .list .role').hide();
|
||||||
|
$(groupchats + ' .one-group, ' + groupchats + ' .list .user').remove();
|
||||||
|
$(groupchats).attr('data-initial', 'false');
|
||||||
|
|
||||||
|
// Stop the timer
|
||||||
|
$('#reconnect a.finish.reconnect').stopTime();
|
||||||
|
|
||||||
|
// Remove the reconnect pane
|
||||||
|
$('#reconnect').remove();
|
||||||
|
|
||||||
|
// Try to login again
|
||||||
|
if(mode == 'normal')
|
||||||
|
self.loginFromSession(Common.XMLFromString(self.current_session));
|
||||||
|
else if(mode == 'anonymous')
|
||||||
|
Anonymous.login(HOST_ANONYMOUS);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.acceptReconnect', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cancel the reconnection of user account (network issue)
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.cancelReconnect = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Console.info('User has canceled automatic reconnection...');
|
||||||
|
|
||||||
|
// Stop the timer
|
||||||
|
$('#reconnect a.finish.reconnect').stopTime();
|
||||||
|
|
||||||
|
// Remove the reconnect pane
|
||||||
|
$('#reconnect').remove();
|
||||||
|
|
||||||
|
// Destroy the talk page
|
||||||
|
Talk.destroy();
|
||||||
|
|
||||||
|
// Renitialize the previous session parameters
|
||||||
|
self.resetConMarkers();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.cancelReconnect', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clears session reminder database
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.clearLastSession = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Clear temporary storage
|
||||||
|
self.resetConMarkers();
|
||||||
|
|
||||||
|
// Clear persistent storage
|
||||||
|
if($(Common.XMLFromString(DataStore.getPersistent('global', 'session', 1))).find('stored').text() == 'true') {
|
||||||
|
DataStore.removePersistent('global', 'session', 1);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.clearLastSession', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the connection markers
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.resetConMarkers = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
self.current_session = false;
|
||||||
|
self.connected = false;
|
||||||
|
self.resume = false;
|
||||||
|
self.reconnect_try = 0;
|
||||||
|
self.reconnect_timer = 0;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.resetConMarkers', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Logins from a saved session
|
||||||
|
* @public
|
||||||
|
* @param {string} data
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.loginFromSession = function(data) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Select the data
|
||||||
|
var session = $(data);
|
||||||
|
|
||||||
|
// Fire the login event
|
||||||
|
self.doLogin(
|
||||||
|
session.find('username').text(),
|
||||||
|
session.find('domain').text(),
|
||||||
|
session.find('password').text(),
|
||||||
|
session.find('resource').text(),
|
||||||
|
session.find('priority').text(),
|
||||||
|
false
|
||||||
|
);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.loginFromSession', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quits a session normally
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.normalQuit = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Reset our database
|
||||||
|
self.clearLastSession();
|
||||||
|
|
||||||
|
// We quit the current session
|
||||||
|
self.quit();
|
||||||
|
|
||||||
|
// We show an info
|
||||||
|
Board.openThisInfo(3);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.normalQuit', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets all the users stuff
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.getEverything = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
Features.get();
|
||||||
|
Roster.get();
|
||||||
|
Privacy.list();
|
||||||
|
Storage.get(NS_ROSTERNOTES);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.getEverything', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates session data to store
|
||||||
|
* @public
|
||||||
|
* @param {string} lNick
|
||||||
|
* @param {string} lServer
|
||||||
|
* @param {string} lPass
|
||||||
|
* @param {string} lResource
|
||||||
|
* @param {number} lPriority
|
||||||
|
* @param {boolean} lRemember
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.storeSession = function(lNick, lServer, lPass, lResource, lPriority, lRemember) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Generate a session XML to be stored
|
||||||
|
session_xml = '<session><stored>true</stored><domain>' + lServer.htmlEnc() + '</domain><username>' + lNick.htmlEnc() + '</username><resource>' + lResource.htmlEnc() + '</resource><password>' + lPass.htmlEnc() + '</password><priority>' + lPriority.htmlEnc() + '</priority></session>';
|
||||||
|
|
||||||
|
// Save the session parameters (for reconnect if network issue)
|
||||||
|
self.current_session = session_xml;
|
||||||
|
|
||||||
|
// Remember me?
|
||||||
|
if(lRemember) {
|
||||||
|
DataStore.setDB(self.desktop_hash, 'remember', 'session', 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return session_xml;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.storeSession', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin launcher
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.launch = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$(document).ready(function() {
|
||||||
|
// Logouts when Jappix is closed
|
||||||
|
$(window).bind('beforeunload', Connection.terminate);
|
||||||
|
|
||||||
|
// Nothing to do when anonymous!
|
||||||
|
if(Utils.isAnonymous())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Connection params submitted in URL?
|
||||||
|
if(XMPPLinks.links_var.u && XMPPLinks.links_var.q) {
|
||||||
|
// Generate login data
|
||||||
|
var login_xid = Common.bareXID(Common.generateXID(XMPPLinks.links_var.u, 'chat'));
|
||||||
|
var login_nick = Common.getXIDNick(login_xid);
|
||||||
|
var login_server = Common.getXIDHost(login_xid);
|
||||||
|
var login_pwd = XMPPLinks.links_var.q;
|
||||||
|
var login_resource = JAPPIX_RESOURCE + ' (' + (new Date()).getTime() + ')';
|
||||||
|
var login_priority = '10';
|
||||||
|
var login_remember = 1;
|
||||||
|
|
||||||
|
// Must store session?
|
||||||
|
if(XMPPLinks.links_var.h && (XMPPLinks.links_var.h === '1')) {
|
||||||
|
// Store session
|
||||||
|
var session_xml = self.storeSession(login_nick, login_server, login_pwd, login_resource, login_priority, true);
|
||||||
|
DataStore.setPersistent('global', 'session', 1, session_xml);
|
||||||
|
|
||||||
|
// Redirect to a clean URL
|
||||||
|
document.location.href = './';
|
||||||
|
} else {
|
||||||
|
// Hide the homepage
|
||||||
|
$('#home').hide();
|
||||||
|
|
||||||
|
// Show the waiting icon
|
||||||
|
Interface.showGeneralWait();
|
||||||
|
|
||||||
|
// Proceed login
|
||||||
|
self.doLogin(login_nick, login_server, login_pwd, login_resource, login_priority, login_remember);
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try to resume a stored session, if not anonymous
|
||||||
|
var session = Common.XMLFromString(
|
||||||
|
DataStore.getPersistent('global', 'session', 1)
|
||||||
|
);
|
||||||
|
|
||||||
|
if($(session).find('stored').text() == 'true') {
|
||||||
|
// Hide the homepage
|
||||||
|
$('#home').hide();
|
||||||
|
|
||||||
|
// Show the waiting icon
|
||||||
|
Interface.showGeneralWait();
|
||||||
|
|
||||||
|
// Login!
|
||||||
|
self.loginFromSession(session);
|
||||||
|
|
||||||
|
Console.info('Saved session found, resuming it...');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not connected, maybe a XMPP link is submitted?
|
||||||
|
else if((parent.location.hash != '#OK') && XMPPLinks.links_var.x) {
|
||||||
|
Home.change('loginer');
|
||||||
|
|
||||||
|
Console.info('A XMPP link is set, switch to login page.');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Connection.launch', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
Connection.launch();
|
66
source/app/javascripts/console.js
Normal file
|
@ -0,0 +1,66 @@
|
||||||
|
// License: MIT
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Console.js
|
||||||
|
*
|
||||||
|
* An interface to native console methods
|
||||||
|
* Avoids issues when browser does not have native support for console
|
||||||
|
*
|
||||||
|
* @license OS
|
||||||
|
* @author Valérian Saliou <valerian@valeriansaliou.name>
|
||||||
|
* @url https://github.com/valeriansaliou/console.js
|
||||||
|
*/
|
||||||
|
|
||||||
|
var Console = (function () {
|
||||||
|
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
self._available = typeof(window.console) != 'undefined';
|
||||||
|
self._has = self._available && JappixSystem.isDeveloper();
|
||||||
|
self._console = self._available ? console : {};
|
||||||
|
|
||||||
|
|
||||||
|
/* Adapters */
|
||||||
|
self._adapter = function (level) {
|
||||||
|
if (!self._has) {
|
||||||
|
return function() {};
|
||||||
|
}
|
||||||
|
|
||||||
|
var adapter = null;
|
||||||
|
try {
|
||||||
|
switch (level) {
|
||||||
|
case 0:
|
||||||
|
adapter = console.warn; break;
|
||||||
|
case 1:
|
||||||
|
adapter = console.error; break;
|
||||||
|
case 2:
|
||||||
|
adapter = console.info; break;
|
||||||
|
case 3:
|
||||||
|
adapter = console.log; break;
|
||||||
|
case 4:
|
||||||
|
adapter = console.debug; break;
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
adapter = function() {};
|
||||||
|
}
|
||||||
|
|
||||||
|
return adapter.bind(self._console);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* Methods */
|
||||||
|
self.warn = self._adapter(0);
|
||||||
|
self.error = self._adapter(1);
|
||||||
|
self.info = self._adapter(2);
|
||||||
|
self.log = self._adapter(3);
|
||||||
|
self.debug = self._adapter(4);
|
||||||
|
|
||||||
|
|
||||||
|
/* Return class scope */
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
var JappixConsole = Console;
|
231
source/app/javascripts/constants.js
Normal file
|
@ -0,0 +1,231 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the constants JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: dual-licensed under AGPL and MPLv2
|
||||||
|
Authors: Stefan Strigler, Valérian Saliou, Kloadut, Maranda
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// XMPP XMLNS attributes
|
||||||
|
var NS_PROTOCOL = 'http://jabber.org/protocol/';
|
||||||
|
var NS_FEATURES = 'http://jabber.org/features/';
|
||||||
|
var NS_CLIENT = 'jabber:client';
|
||||||
|
var NS_IQ = 'jabber:iq:';
|
||||||
|
var NS_X = 'jabber:x:';
|
||||||
|
var NS_IETF = 'urn:ietf:params:xml:ns:';
|
||||||
|
var NS_IETF_XMPP = NS_IETF + 'xmpp-';
|
||||||
|
var NS_XMPP = 'urn:xmpp:';
|
||||||
|
|
||||||
|
var NS_STORAGE = 'storage:';
|
||||||
|
var NS_BOOKMARKS = NS_STORAGE + 'bookmarks';
|
||||||
|
var NS_ROSTERNOTES = NS_STORAGE + 'rosternotes';
|
||||||
|
|
||||||
|
var NS_JAPPIX = 'jappix:';
|
||||||
|
var NS_INBOX = NS_JAPPIX + 'inbox';
|
||||||
|
var NS_OPTIONS = NS_JAPPIX + 'options';
|
||||||
|
|
||||||
|
var NS_DISCO_ITEMS = NS_PROTOCOL + 'disco#items';
|
||||||
|
var NS_DISCO_INFO = NS_PROTOCOL + 'disco#info';
|
||||||
|
var NS_VCARD = 'vcard-temp';
|
||||||
|
var NS_VCARD_P = NS_VCARD + ':x:update';
|
||||||
|
var NS_IETF_VCARD4 = NS_IETF + 'vcard-4.0';
|
||||||
|
var NS_XMPP_VCARD4 = NS_XMPP + 'vcard4';
|
||||||
|
var NS_URN_ADATA = NS_XMPP + 'avatar:data';
|
||||||
|
var NS_URN_AMETA = NS_XMPP + 'avatar:metadata';
|
||||||
|
var NS_AUTH = NS_IQ + 'auth';
|
||||||
|
var NS_AUTH_ERROR = NS_IQ + 'auth:error';
|
||||||
|
var NS_REGISTER = NS_IQ + 'register';
|
||||||
|
var NS_SEARCH = NS_IQ + 'search';
|
||||||
|
var NS_ROSTER = NS_IQ + 'roster';
|
||||||
|
var NS_PRIVACY = NS_IQ + 'privacy';
|
||||||
|
var NS_PRIVATE = NS_IQ + 'private';
|
||||||
|
var NS_VERSION = NS_IQ + 'version';
|
||||||
|
var NS_TIME = NS_IQ + 'time';
|
||||||
|
var NS_LAST = NS_IQ + 'last';
|
||||||
|
var NS_IQDATA = NS_IQ + 'data';
|
||||||
|
var NS_XDATA = NS_X + 'data';
|
||||||
|
var NS_IQOOB = NS_IQ + 'oob';
|
||||||
|
var NS_XOOB = NS_X + 'oob';
|
||||||
|
var NS_DELAY = NS_X + 'delay';
|
||||||
|
var NS_EXPIRE = NS_X + 'expire';
|
||||||
|
var NS_EVENT = NS_X + 'event';
|
||||||
|
var NS_XCONFERENCE = NS_X + 'conference';
|
||||||
|
var NS_STATS = NS_PROTOCOL + 'stats';
|
||||||
|
var NS_MUC = NS_PROTOCOL + 'muc';
|
||||||
|
var NS_MUC_USER = NS_MUC + '#user';
|
||||||
|
var NS_MUC_ADMIN = NS_MUC + '#admin';
|
||||||
|
var NS_MUC_OWNER = NS_MUC + '#owner';
|
||||||
|
var NS_MUC_CONFIG = NS_MUC + '#roomconfig';
|
||||||
|
var NS_PUBSUB = NS_PROTOCOL + 'pubsub';
|
||||||
|
var NS_PUBSUB_EVENT = NS_PUBSUB + '#event';
|
||||||
|
var NS_PUBSUB_OWNER = NS_PUBSUB + '#owner';
|
||||||
|
var NS_PUBSUB_NMI = NS_PUBSUB + '#node-meta-info';
|
||||||
|
var NS_PUBSUB_NC = NS_PUBSUB + '#node_config';
|
||||||
|
var NS_PUBSUB_CN = NS_PUBSUB + '#config-node';
|
||||||
|
var NS_PUBSUB_RI = NS_PUBSUB + '#retrieve-items';
|
||||||
|
var NS_COMMANDS = NS_PROTOCOL + 'commands';
|
||||||
|
var NS_BOSH = NS_PROTOCOL + 'httpbind';
|
||||||
|
var NS_STREAM = 'http://etherx.jabber.org/streams';
|
||||||
|
var NS_URN_TIME = NS_XMPP + 'time';
|
||||||
|
var NS_URN_PING = NS_XMPP + 'ping';
|
||||||
|
var NS_URN_MBLOG = NS_XMPP + 'microblog:0';
|
||||||
|
var NS_URN_INBOX = NS_XMPP + 'inbox';
|
||||||
|
var NS_URN_FORWARD = NS_XMPP + 'forward:0';
|
||||||
|
var NS_URN_MAM = NS_XMPP + 'mam:tmp';
|
||||||
|
var NS_URN_DELAY = NS_XMPP + 'delay';
|
||||||
|
var NS_URN_RECEIPTS = NS_XMPP + 'receipts';
|
||||||
|
var NS_URN_CARBONS = NS_XMPP + 'carbons:2';
|
||||||
|
var NS_RSM = NS_PROTOCOL + 'rsm';
|
||||||
|
var NS_IPV6 = 'ipv6';
|
||||||
|
var NS_XHTML = 'http://www.w3.org/1999/xhtml';
|
||||||
|
var NS_XHTML_IM = NS_PROTOCOL + 'xhtml-im';
|
||||||
|
var NS_CHATSTATES = NS_PROTOCOL + 'chatstates';
|
||||||
|
var NS_HTTP_AUTH = NS_PROTOCOL + 'http-auth';
|
||||||
|
var NS_ROSTERX = NS_PROTOCOL + 'rosterx';
|
||||||
|
var NS_MOOD = NS_PROTOCOL + 'mood';
|
||||||
|
var NS_ACTIVITY = NS_PROTOCOL + 'activity';
|
||||||
|
var NS_TUNE = NS_PROTOCOL + 'tune';
|
||||||
|
var NS_GEOLOC = NS_PROTOCOL + 'geoloc';
|
||||||
|
var NS_NICK = NS_PROTOCOL + 'nick';
|
||||||
|
var NS_NOTIFY = '+notify';
|
||||||
|
var NS_CAPS = NS_PROTOCOL + 'caps';
|
||||||
|
var NS_ATOM = 'http://www.w3.org/2005/Atom';
|
||||||
|
|
||||||
|
var NS_STANZAS = NS_IETF_XMPP + 'stanzas';
|
||||||
|
var NS_STREAMS = NS_IETF_XMPP + 'streams';
|
||||||
|
|
||||||
|
var NS_TLS = NS_IETF_XMPP + 'tls';
|
||||||
|
var NS_SASL = NS_IETF_XMPP + 'sasl';
|
||||||
|
var NS_SESSION = NS_IETF_XMPP + 'session';
|
||||||
|
var NS_BIND = NS_IETF_XMPP + 'bind';
|
||||||
|
|
||||||
|
var NS_FEATURE_IQAUTH = NS_FEATURES + 'iq-auth';
|
||||||
|
var NS_FEATURE_IQREGISTER = NS_FEATURES + 'iq-register';
|
||||||
|
var NS_FEATURE_COMPRESS = NS_FEATURES + 'compress';
|
||||||
|
|
||||||
|
var NS_COMPRESS = NS_PROTOCOL + 'compress';
|
||||||
|
|
||||||
|
var NS_METRONOME_MAM_PURGE = 'http://metronome.im/protocol/mam-purge';
|
||||||
|
|
||||||
|
// Available locales
|
||||||
|
var LOCALES_AVAILABLE_ID = [];
|
||||||
|
var LOCALES_AVAILABLE_NAMES = [];
|
||||||
|
|
||||||
|
// XML lang
|
||||||
|
var XML_LANG = null;
|
||||||
|
|
||||||
|
// Jappix parameters
|
||||||
|
var JAPPIX_STATIC = null;
|
||||||
|
var JAPPIX_VERSION = null;
|
||||||
|
var JAPPIX_MAX_FILE_SIZE = null;
|
||||||
|
var JAPPIX_MAX_UPLOAD = null;
|
||||||
|
|
||||||
|
// Jappix main configuration
|
||||||
|
var SERVICE_NAME = null;
|
||||||
|
var SERVICE_DESC = null;
|
||||||
|
var OWNER_NAME = null;
|
||||||
|
var OWNER_WEBSITE = null;
|
||||||
|
var LEGAL = null;
|
||||||
|
var JAPPIX_RESOURCE = null;
|
||||||
|
var LOCK_HOST = null;
|
||||||
|
var ANONYMOUS = null;
|
||||||
|
var HTTP_AUTH = null;
|
||||||
|
var REGISTRATION = null;
|
||||||
|
var BOSH_PROXY = null;
|
||||||
|
var MANAGER_LINK = null;
|
||||||
|
var GROUPCHATS_JOIN = null;
|
||||||
|
var GROUPCHATS_SUGGEST = null;
|
||||||
|
var ENCRYPTION = null;
|
||||||
|
var HTTPS_STORAGE = null;
|
||||||
|
var HTTPS_FORCE = null;
|
||||||
|
var COMPRESSION = null;
|
||||||
|
var ADS_ENABLE = null;
|
||||||
|
var GADS_CLIENT = null;
|
||||||
|
var GADS_SLOT = null;
|
||||||
|
var MULTI_FILES = null;
|
||||||
|
var DEVELOPER = null;
|
||||||
|
var REGISTER_API = null;
|
||||||
|
|
||||||
|
// Jappix hosts configuration
|
||||||
|
var HOST_MAIN = null;
|
||||||
|
var HOST_MUC = null;
|
||||||
|
var HOST_PUBSUB = null;
|
||||||
|
var HOST_VJUD = null;
|
||||||
|
var HOST_ANONYMOUS = null;
|
||||||
|
var HOST_STUN = null;
|
||||||
|
var HOST_TURN = null;
|
||||||
|
var HOST_TURN_USERNAME = null;
|
||||||
|
var HOST_TURN_PASSWORD = null;
|
||||||
|
var HOST_BOSH = null;
|
||||||
|
var HOST_BOSH_MAIN = null;
|
||||||
|
var HOST_BOSH_MINI = null;
|
||||||
|
var HOST_WEBSOCKET = null;
|
||||||
|
var HOST_STATIC = null;
|
||||||
|
var HOST_UPLOAD = null;
|
||||||
|
|
||||||
|
// Anonymous mode
|
||||||
|
var ANONYMOUS_ROOM = null;
|
||||||
|
var ANONYMOUS_NICK = null;
|
||||||
|
|
||||||
|
// Node parameters
|
||||||
|
var JAPPIX_LOCATION = JappixSystem.location();
|
||||||
|
var JAPPIX_MINI_CSS = null;
|
||||||
|
var BOSH_SAME_ORIGIN = false;
|
||||||
|
|
||||||
|
// XMPP error stanzas
|
||||||
|
function STANZA_ERROR(code, type, cond) {
|
||||||
|
if(window == this) {
|
||||||
|
return new STANZA_ERROR(code, type, cond);
|
||||||
|
}
|
||||||
|
|
||||||
|
this.code = code;
|
||||||
|
this.type = type;
|
||||||
|
this.cond = cond;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ERR_BAD_REQUEST =
|
||||||
|
STANZA_ERROR('400', 'modify', 'bad-request');
|
||||||
|
var ERR_CONFLICT =
|
||||||
|
STANZA_ERROR('409', 'cancel', 'conflict');
|
||||||
|
var ERR_FEATURE_NOT_IMPLEMENTED =
|
||||||
|
STANZA_ERROR('501', 'cancel', 'feature-not-implemented');
|
||||||
|
var ERR_FORBIDDEN =
|
||||||
|
STANZA_ERROR('403', 'auth', 'forbidden');
|
||||||
|
var ERR_GONE =
|
||||||
|
STANZA_ERROR('302', 'modify', 'gone');
|
||||||
|
var ERR_INTERNAL_SERVER_ERROR =
|
||||||
|
STANZA_ERROR('500', 'wait', 'internal-server-error');
|
||||||
|
var ERR_ITEM_NOT_FOUND =
|
||||||
|
STANZA_ERROR('404', 'cancel', 'item-not-found');
|
||||||
|
var ERR_JID_MALFORMED =
|
||||||
|
STANZA_ERROR('400', 'modify', 'jid-malformed');
|
||||||
|
var ERR_NOT_ACCEPTABLE =
|
||||||
|
STANZA_ERROR('406', 'modify', 'not-acceptable');
|
||||||
|
var ERR_NOT_ALLOWED =
|
||||||
|
STANZA_ERROR('405', 'cancel', 'not-allowed');
|
||||||
|
var ERR_NOT_AUTHORIZED =
|
||||||
|
STANZA_ERROR('401', 'auth', 'not-authorized');
|
||||||
|
var ERR_PAYMENT_REQUIRED =
|
||||||
|
STANZA_ERROR('402', 'auth', 'payment-required');
|
||||||
|
var ERR_RECIPIENT_UNAVAILABLE =
|
||||||
|
STANZA_ERROR('404', 'wait', 'recipient-unavailable');
|
||||||
|
var ERR_REDIRECT =
|
||||||
|
STANZA_ERROR('302', 'modify', 'redirect');
|
||||||
|
var ERR_REGISTRATION_REQUIRED =
|
||||||
|
STANZA_ERROR('407', 'auth', 'registration-required');
|
||||||
|
var ERR_REMOTE_SERVER_NOT_FOUND =
|
||||||
|
STANZA_ERROR('404', 'cancel', 'remote-server-not-found');
|
||||||
|
var ERR_REMOTE_SERVER_TIMEOUT =
|
||||||
|
STANZA_ERROR('504', 'wait', 'remote-server-timeout');
|
||||||
|
var ERR_RESOURCE_CONSTRAINT =
|
||||||
|
STANZA_ERROR('500', 'wait', 'resource-constraint');
|
||||||
|
var ERR_SERVICE_UNAVAILABLE =
|
||||||
|
STANZA_ERROR('503', 'cancel', 'service-unavailable');
|
||||||
|
var ERR_SUBSCRIPTION_REQUIRED =
|
||||||
|
STANZA_ERROR('407', 'auth', 'subscription-required');
|
||||||
|
var ERR_UNEXPECTED_REQUEST =
|
||||||
|
STANZA_ERROR('400', 'wait', 'unexpected-request');
|
1160
source/app/javascripts/dataform.js
Normal file
502
source/app/javascripts/datastore.js
Normal file
|
@ -0,0 +1,502 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the temporary/persistent data store functions
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: dual-licensed under AGPL and MPLv2
|
||||||
|
Authors: Valérian Saliou, Maranda
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var DataStore = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
self._db_emulated = {};
|
||||||
|
self._persistent_emulated = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common: storage adapter
|
||||||
|
* @public
|
||||||
|
* @param {object} storage_native
|
||||||
|
* @param {object} storage_emulated
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self._adapter = function(storage_native, storage_emulated) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var legacy = !storage_native;
|
||||||
|
|
||||||
|
this.key = function(key) {
|
||||||
|
if(legacy) {
|
||||||
|
if(key >= this.length)
|
||||||
|
return null;
|
||||||
|
|
||||||
|
var c = 0;
|
||||||
|
|
||||||
|
for(var name in storage_emulated) {
|
||||||
|
if(c++ == key) return name;
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return storage_native.key(key);
|
||||||
|
};
|
||||||
|
|
||||||
|
this.getItem = function(key) {
|
||||||
|
if(legacy) {
|
||||||
|
if(storage_emulated[key] !== undefined)
|
||||||
|
return storage_emulated[key];
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} else {
|
||||||
|
return storage_native.getItem(key);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.setItem = function(key, data) {
|
||||||
|
if(legacy) {
|
||||||
|
if(!(key in storage_emulated))
|
||||||
|
this.length++;
|
||||||
|
|
||||||
|
storage_emulated[key] = (data + '');
|
||||||
|
} else {
|
||||||
|
storage_native.setItem(key, data);
|
||||||
|
this.length = storage_native.length;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.removeItem = function(key) {
|
||||||
|
if(legacy) {
|
||||||
|
if(key in storage_emulated) {
|
||||||
|
this.length--;
|
||||||
|
delete storage_emulated[key];
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
storage_native.removeItem(key);
|
||||||
|
this.length = storage_native.length;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.clear = function() {
|
||||||
|
if(legacy) {
|
||||||
|
this.length = 0;
|
||||||
|
storage_emulated = {};
|
||||||
|
} else {
|
||||||
|
storage_native.clear();
|
||||||
|
this.length = storage_native.length;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
this.length = legacy ? 0 : storage_native.length;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore._adapter', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary: sessionStorage class alias for direct access
|
||||||
|
*/
|
||||||
|
self.storageDB = new self._adapter(
|
||||||
|
(window.sessionStorage ? sessionStorage : null),
|
||||||
|
self._db_emulated
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent: localStorage class alias for direct access
|
||||||
|
*/
|
||||||
|
self.storagePersistent = new self._adapter(
|
||||||
|
(window.localStorage ? localStorage : null),
|
||||||
|
self._persistent_emulated
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary: returns whether it is available or not
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.hasDB = function() {
|
||||||
|
|
||||||
|
var has_db = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
self.storageDB.setItem('hasdb_check', 'ok');
|
||||||
|
self.storageDB.removeItem('hasdb_check');
|
||||||
|
|
||||||
|
has_db = true;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.hasDB', e);
|
||||||
|
} finally {
|
||||||
|
return has_db;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary: used to read a database entry
|
||||||
|
* @public
|
||||||
|
* @param {string} dbID
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} id
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.getDB = function(dbID, type, id) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
return self.storageDB.getItem(dbID + '_' + type + '_' + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(e) {
|
||||||
|
Console.error('Error while getting a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.getDB', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary: used to update a database entry
|
||||||
|
* @public
|
||||||
|
* @param {string} dbID
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} id
|
||||||
|
* @param {type} value
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.setDB = function(dbID, type, id, value) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
self.storageDB.setItem(dbID + '_' + type + '_' + id, value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(e) {
|
||||||
|
Console.error('Error while writing a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.setDB', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary: used to remove a database entry
|
||||||
|
* @public
|
||||||
|
* @param {string} dbID
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} id
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.removeDB = function(dbID, type, id) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
self.storageDB.removeItem(dbID + '_' + type + '_' + id);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(e) {
|
||||||
|
Console.error('Error while removing a temporary database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.removeDB', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary: used to check a database entry exists
|
||||||
|
* @public
|
||||||
|
* @param {string} dbID
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} id
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.existDB = function(dbID, type, id) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.getDB(dbID, type, id) !== null;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.existDB', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Temporary: used to clear all the database
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.resetDB = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
self.storageDB.clear();
|
||||||
|
|
||||||
|
Console.info('Temporary database cleared.');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(e) {
|
||||||
|
Console.error('Error while clearing temporary database', e);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.resetDB', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent: returns whether it is available or not
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.hasPersistent = function() {
|
||||||
|
|
||||||
|
var has_persistent = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Try to write something
|
||||||
|
self.storagePersistent.setItem('haspersistent_check', 'ok');
|
||||||
|
self.storagePersistent.removeItem('haspersistent_check');
|
||||||
|
|
||||||
|
has_persistent = true;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.hasPersistent', e);
|
||||||
|
} finally {
|
||||||
|
return has_persistent;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent: used to read a database entry
|
||||||
|
* @public
|
||||||
|
* @param {string} dbID
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} id
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.getPersistent = function(dbID, type, id) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
return self.storagePersistent.getItem(dbID + '_' + type + '_' + id);
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(e) {
|
||||||
|
Console.error('Error while getting a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.getPersistent', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent: used to update a database entry
|
||||||
|
* @public
|
||||||
|
* @param {string} dbID
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} id
|
||||||
|
* @param {string} value
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.setPersistent = function(dbID, type, id, value) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
self.storagePersistent.setItem(dbID + '_' + type + '_' + id, value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Database might be full
|
||||||
|
catch(e) {
|
||||||
|
Console.warn('Retrying: could not write a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
|
||||||
|
|
||||||
|
// Flush it!
|
||||||
|
self.flushPersistent();
|
||||||
|
|
||||||
|
// Set the item again
|
||||||
|
try {
|
||||||
|
self.storagePersistent.setItem(dbID + ' -> ' + type + '_' + id, value);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// New error!
|
||||||
|
catch(_e) {
|
||||||
|
Console.error('Aborted: error while writing a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', _e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.setPersistent', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent: used to remove a database entry
|
||||||
|
* @public
|
||||||
|
* @param {string} dbID
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} id
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.removePersistent = function(dbID, type, id) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
self.storagePersistent.removeItem(dbID + '_' + type + '_' + id);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(e) {
|
||||||
|
Console.error('Error while removing a persistent database entry (' + dbID + ' -> ' + type + ' -> ' + id + ')', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.removePersistent', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent: used to check a database entry exists
|
||||||
|
* @public
|
||||||
|
* @param {string} dbID
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} id
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.existPersistent = function(dbID, type, id) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.getPersistent(dbID, type, id) !== null;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.existPersistent', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent: used to clear all the database
|
||||||
|
* @public
|
||||||
|
* @param {type} name
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.resetPersistent = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
self.storagePersistent.clear();
|
||||||
|
|
||||||
|
Console.info('Persistent database cleared.');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(e) {
|
||||||
|
Console.error('Error while clearing persistent database', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.resetPersistent', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Persistent: used to flush the database
|
||||||
|
* @public
|
||||||
|
* @param {type} name
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.flushPersistent = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
try {
|
||||||
|
// Get the stored session entry
|
||||||
|
var session = self.getPersistent('global', 'session', 1);
|
||||||
|
|
||||||
|
// Reset the persistent database
|
||||||
|
self.resetPersistent();
|
||||||
|
|
||||||
|
// Restaure the stored session entry
|
||||||
|
if(session)
|
||||||
|
self.setPersistent('global', 'session', 1, session);
|
||||||
|
|
||||||
|
Console.info('Persistent database flushed.');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
catch(e) {
|
||||||
|
Console.error('Error while flushing persistent database', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DataStore.flushPersistent', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
var JappixDataStore = DataStore;
|
402
source/app/javascripts/date.js
Normal file
|
@ -0,0 +1,402 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the date related JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: dual-licensed under AGPL and MPLv2
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var DateUtils = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
self.last_activity = 0;
|
||||||
|
self.presence_last_activity = 0;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a stamp from a date
|
||||||
|
* @public
|
||||||
|
* @param {Date} date
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
self.extractStamp = function(date) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return Math.round(date.getTime() / 1000);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.extractStamp', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the time from a date
|
||||||
|
* @public
|
||||||
|
* @param {Date} date
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.extractTime = function(date) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return date.toLocaleTimeString();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.extractTime', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the actual date stamp
|
||||||
|
* @public
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
self.getTimeStamp = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.extractStamp(new Date());
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.getTimeStamp', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the last user activity in seconds
|
||||||
|
* @public
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
self.getLastActivity = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Last activity not yet initialized?
|
||||||
|
if(self.last_activity === 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return self.getTimeStamp() - self.last_activity;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.getLastActivity', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the last user available presence in seconds
|
||||||
|
* @public
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
self.getPresenceLast = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Last presence stamp not yet initialized?
|
||||||
|
if(self.presence_last_activity === 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return self.getTimeStamp() - self.presence_last_activity;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.getPresenceLast', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the time for XMPP
|
||||||
|
* @public
|
||||||
|
* @param {string} location
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.getXMPPTime = function(location) {
|
||||||
|
|
||||||
|
/* FROM : http://trac.jwchat.org/jsjac/browser/branches/jsjac_1.0/jsextras.js?rev=221 */
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize
|
||||||
|
var jInit = new Date();
|
||||||
|
var year, month, day, hours, minutes, seconds;
|
||||||
|
|
||||||
|
// Gets the UTC date
|
||||||
|
if(location == 'utc') {
|
||||||
|
year = jInit.getUTCFullYear();
|
||||||
|
month = jInit.getUTCMonth();
|
||||||
|
day = jInit.getUTCDate();
|
||||||
|
hours = jInit.getUTCHours();
|
||||||
|
minutes = jInit.getUTCMinutes();
|
||||||
|
seconds = jInit.getUTCSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Gets the local date
|
||||||
|
else {
|
||||||
|
year = jInit.getFullYear();
|
||||||
|
month = jInit.getMonth();
|
||||||
|
day = jInit.getDate();
|
||||||
|
hours = jInit.getHours();
|
||||||
|
minutes = jInit.getMinutes();
|
||||||
|
seconds = jInit.getSeconds();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generates the date string
|
||||||
|
var jDate = year + '-';
|
||||||
|
jDate += Common.padZero(month + 1) + '-';
|
||||||
|
jDate += Common.padZero(day) + 'T';
|
||||||
|
jDate += Common.padZero(hours) + ':';
|
||||||
|
jDate += Common.padZero(minutes) + ':';
|
||||||
|
jDate += Common.padZero(seconds) + 'Z';
|
||||||
|
|
||||||
|
// Returns the date string
|
||||||
|
return jDate;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.getXMPPTime', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates then human time
|
||||||
|
* @public
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.getCompleteTime = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var init = new Date();
|
||||||
|
var time = Common.padZero(init.getHours()) + ':';
|
||||||
|
time += Common.padZero(init.getMinutes()) + ':';
|
||||||
|
time += Common.padZero(init.getSeconds());
|
||||||
|
|
||||||
|
return time;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.getCompleteTime', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the TZO of a date
|
||||||
|
* @public
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.getTZO = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get the date
|
||||||
|
var date = new Date();
|
||||||
|
var offset = date.getTimezoneOffset();
|
||||||
|
|
||||||
|
// Default vars
|
||||||
|
var sign = '';
|
||||||
|
var hours = 0;
|
||||||
|
var minutes = 0;
|
||||||
|
|
||||||
|
// Process a neutral offset
|
||||||
|
if(offset < 0) {
|
||||||
|
offset = offset * -1;
|
||||||
|
sign = '+';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the values
|
||||||
|
var n_date = new Date(offset * 60 * 1000);
|
||||||
|
hours = n_date.getHours() - 1;
|
||||||
|
minutes = n_date.getMinutes();
|
||||||
|
|
||||||
|
// Process the TZO
|
||||||
|
tzo = sign + Common.padZero(hours) + ':' + Common.padZero(minutes);
|
||||||
|
|
||||||
|
// Return the processed value
|
||||||
|
return tzo;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.getTZO', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a date representing the difference of time between 2 timestamps
|
||||||
|
* @public
|
||||||
|
* @param {string} now_stamp
|
||||||
|
* @param {string} past_stamp
|
||||||
|
* @return {Date}
|
||||||
|
*/
|
||||||
|
self.difference = function(now_stamp, past_stamp) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return (new Date()).clearTime().addSeconds(
|
||||||
|
past_stamp > 0 ? now_stamp - past_stamp : 0
|
||||||
|
);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.difference', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a XMPP date (yyyy-mm-dd, hh-mm-ss) into an human-readable one
|
||||||
|
* @public
|
||||||
|
* @param {string} to_parse
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.parse = function(to_parse) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var date = Date.jab2date(to_parse);
|
||||||
|
var parsed = date.toLocaleDateString() + ' (' + date.toLocaleTimeString() + ')';
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.parse', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a XMPP date (yyyy-mm-dd) into an human-readable one
|
||||||
|
* @public
|
||||||
|
* @param {string} to_parse
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.parseDay = function(to_parse) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var date = Date.jab2date(to_parse);
|
||||||
|
var parsed = date.toLocaleDateString();
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.parseDay', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a XMPP date (hh-mm-ss) into an human-readable one
|
||||||
|
* @public
|
||||||
|
* @param {string} to_parse
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.parseTime = function(to_parse) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var date = Date.jab2date(to_parse);
|
||||||
|
var parsed = date.toLocaleTimeString();
|
||||||
|
|
||||||
|
return parsed;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.parseTime', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses a XMPP date stamp into a relative one
|
||||||
|
* @public
|
||||||
|
* @param {string} to_parse
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.relative = function(to_parse) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get the current date
|
||||||
|
var current_date = Date.jab2date(self.getXMPPTime('utc'));
|
||||||
|
var current_day = current_date.getDate();
|
||||||
|
var current_stamp = current_date.getTime();
|
||||||
|
|
||||||
|
// Parse the given date
|
||||||
|
var old_date = Date.jab2date(to_parse);
|
||||||
|
var old_day = old_date.getDate();
|
||||||
|
var old_stamp = old_date.getTime();
|
||||||
|
var old_time = old_date.toLocaleTimeString();
|
||||||
|
|
||||||
|
// Get the day number between the two dates
|
||||||
|
var days = Math.round((current_stamp - old_stamp) / 86400000);
|
||||||
|
|
||||||
|
// Invalid date?
|
||||||
|
if(isNaN(old_stamp) || isNaN(days))
|
||||||
|
return self.getCompleteTime();
|
||||||
|
|
||||||
|
// Is it today?
|
||||||
|
if(current_day == old_day)
|
||||||
|
return old_time;
|
||||||
|
|
||||||
|
// It is yesterday?
|
||||||
|
if(days <= 1)
|
||||||
|
return Common._e("Yesterday") + ' - ' + old_time;
|
||||||
|
|
||||||
|
// Is it less than a week ago?
|
||||||
|
if(days <= 7)
|
||||||
|
return Common.printf(Common._e("%s days ago"), days) + ' - ' + old_time;
|
||||||
|
|
||||||
|
// Another longer period
|
||||||
|
return old_date.toLocaleDateString() + ' - ' + old_time;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.relative', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads a message delay
|
||||||
|
* @public
|
||||||
|
* @param {string} node
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.readMessageDelay = function(node) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize
|
||||||
|
var delay, d_delay;
|
||||||
|
|
||||||
|
// Read the delay
|
||||||
|
d_delay = jQuery(node).find('delay[xmlns="' + NS_URN_DELAY + '"]:first').attr('stamp');
|
||||||
|
|
||||||
|
// New delay (valid XEP)
|
||||||
|
if(d_delay)
|
||||||
|
delay = d_delay;
|
||||||
|
|
||||||
|
// Old delay (obsolete XEP!)
|
||||||
|
else {
|
||||||
|
// Try to read the old-school delay
|
||||||
|
var x_delay = jQuery(node).find('x[xmlns="' + NS_DELAY + '"]:first').attr('stamp');
|
||||||
|
|
||||||
|
if(x_delay)
|
||||||
|
delay = x_delay.replace(/^(\w{4})(\w{2})(\w{2})T(\w{2}):(\w{2}):(\w{2})Z?(\S+)?/, '$1-$2-$3T$4:$5:$6Z$7');
|
||||||
|
}
|
||||||
|
|
||||||
|
return delay;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('DateUtils.readMessageDelay', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
var JappixDateUtils = DateUtils;
|
104
source/app/javascripts/datejs.js
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
/**
|
||||||
|
* Version: 1.0 Alpha-1
|
||||||
|
* Build Date: 13-Nov-2007
|
||||||
|
* Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
|
||||||
|
* License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
|
||||||
|
* Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
|
||||||
|
*/
|
||||||
|
Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
|
||||||
|
Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
||||||
|
return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
|
||||||
|
return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
|
||||||
|
return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
|
||||||
|
if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
|
||||||
|
var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
|
||||||
|
if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
|
||||||
|
if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
|
||||||
|
if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
|
||||||
|
if(x.month||x.months){this.addMonths(x.month||x.months);}
|
||||||
|
if(x.year||x.years){this.addYears(x.year||x.years);}
|
||||||
|
if(x.day||x.days){this.addDays(x.day||x.days);}
|
||||||
|
return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
|
||||||
|
return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
|
||||||
|
if(!x.second&&x.second!==0){x.second=-1;}
|
||||||
|
if(!x.minute&&x.minute!==0){x.minute=-1;}
|
||||||
|
if(!x.hour&&x.hour!==0){x.hour=-1;}
|
||||||
|
if(!x.day&&x.day!==0){x.day=-1;}
|
||||||
|
if(!x.month&&x.month!==0){x.month=-1;}
|
||||||
|
if(!x.year&&x.year!==0){x.year=-1;}
|
||||||
|
if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
|
||||||
|
if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
|
||||||
|
if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
|
||||||
|
if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
|
||||||
|
if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
|
||||||
|
if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
|
||||||
|
if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
|
||||||
|
if(x.timezone){this.setTimezone(x.timezone);}
|
||||||
|
if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
|
||||||
|
return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
|
||||||
|
var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
|
||||||
|
return w;};Date.prototype.isDST=function(){console.log('isDST');return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
|
||||||
|
Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
|
||||||
|
return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
|
||||||
|
var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
|
||||||
|
return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
|
||||||
|
var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
|
||||||
|
return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
|
||||||
|
(function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
|
||||||
|
break;}
|
||||||
|
return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
|
||||||
|
rx.push(r[0]);s=r[1];}
|
||||||
|
return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
|
||||||
|
return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
|
||||||
|
throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
|
||||||
|
return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
|
||||||
|
if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
|
||||||
|
try{r=(px[i].call(this,s));}catch(e){r=null;}
|
||||||
|
if(r){return r;}}
|
||||||
|
throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
|
||||||
|
try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
|
||||||
|
rx.push(r[0]);s=r[1];}
|
||||||
|
return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
|
||||||
|
return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
|
||||||
|
rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
|
||||||
|
s=q[1];}
|
||||||
|
if(!r){throw new $P.Exception(s);}
|
||||||
|
if(q){throw new $P.Exception(q[1]);}
|
||||||
|
if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
|
||||||
|
return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
|
||||||
|
rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
|
||||||
|
if(!last&&q[1].length===0){last=true;}
|
||||||
|
if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
|
||||||
|
p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
|
||||||
|
if(rx[1].length<best[1].length){best=rx;}
|
||||||
|
if(best[1].length===0){break;}}
|
||||||
|
if(best[0].length===0){return best;}
|
||||||
|
if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
|
||||||
|
best[1]=q[1];}
|
||||||
|
return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
|
||||||
|
return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
|
||||||
|
if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
|
||||||
|
var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
|
||||||
|
return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
|
||||||
|
this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
|
||||||
|
var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
|
||||||
|
return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
|
||||||
|
for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
|
||||||
|
if(this.now){return new Date();}
|
||||||
|
var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
|
||||||
|
if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
|
||||||
|
if(!this.unit){this.unit="day";}
|
||||||
|
if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
|
||||||
|
if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
|
||||||
|
this[this.unit+"s"]=this.value*orient;}
|
||||||
|
return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
|
||||||
|
if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
|
||||||
|
if(this.month&&!this.day){this.day=1;}
|
||||||
|
return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
|
||||||
|
fn=_C[keys]=_.any.apply(null,px);}
|
||||||
|
return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
|
||||||
|
return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
|
||||||
|
return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
|
||||||
|
try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
|
||||||
|
return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
|
||||||
|
return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
|
147
source/app/javascripts/directory.js
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the directory JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Directory = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the directory popup
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.open = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Popup HTML content
|
||||||
|
var html =
|
||||||
|
'<div class="top">' + Common._e("User directory") + '</div>' +
|
||||||
|
|
||||||
|
'<div class="content">' +
|
||||||
|
'<div class="directory-head">' +
|
||||||
|
'<div class="directory-server-text">' + Common._e("Server to query") + '</div>' +
|
||||||
|
|
||||||
|
'<input name="directory-server-input" class="directory-server-input" value="' + Common.encodeQuotes(HOST_VJUD) + '" />' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="results directory-results"></div>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="bottom">' +
|
||||||
|
'<div class="wait wait-medium"></div>' +
|
||||||
|
|
||||||
|
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
// Create the popup
|
||||||
|
Popup.create('directory', html);
|
||||||
|
|
||||||
|
// Associate the events
|
||||||
|
self.instance();
|
||||||
|
|
||||||
|
// Start a search!
|
||||||
|
self.start();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Directory.open', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quits the directory popup
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.close = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Destroy the popup
|
||||||
|
Popup.destroy('directory');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Directory.close', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launches a directory search
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.start = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get the server to query
|
||||||
|
var server = $('#directory .directory-server-input').val();
|
||||||
|
|
||||||
|
// Launch the search!
|
||||||
|
DataForm.go($('#directory .directory-server-input').val(), 'search', '', '', 'directory');
|
||||||
|
|
||||||
|
Console.log('Directory search launched: ' + server);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Directory.start', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin launcher
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.instance = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Click event
|
||||||
|
$('#directory .bottom .finish').click(self.close);
|
||||||
|
|
||||||
|
// Keyboard event
|
||||||
|
$('#directory .directory-server-input').keyup(function(e) {
|
||||||
|
if(e.keyCode == 13) {
|
||||||
|
// No value?
|
||||||
|
if(!$(this).val())
|
||||||
|
$(this).val(HOST_VJUD);
|
||||||
|
|
||||||
|
// Start the directory search
|
||||||
|
self.start();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Directory.instance', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
240
source/app/javascripts/discovery.js
Normal file
|
@ -0,0 +1,240 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the discovery JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Discovery = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the discovery popup
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.open = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Popup HTML content
|
||||||
|
var html =
|
||||||
|
'<div class="top">' + Common._e("Service discovery") + '</div>' +
|
||||||
|
|
||||||
|
'<div class="content">' +
|
||||||
|
'<div class="discovery-head">' +
|
||||||
|
'<div class="disco-server-text">' + Common._e("Server to query") + '</div>' +
|
||||||
|
|
||||||
|
'<input name="disco-server-input" class="disco-server-input" value="' + Common.encodeQuotes(HOST_MAIN) + '" />' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="results discovery-results">' +
|
||||||
|
'<div class="disco-category disco-account">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Accounts") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-auth">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Authentications") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-automation">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Automation") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-client">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Clients") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-collaboration">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Collaboration") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-component">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Components") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-conference">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Rooms") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-directory">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Directories") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-gateway">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Gateways") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-headline">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("News") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-hierarchy">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Hierarchy") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-proxy">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Proxies") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-pubsub">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Publication/Subscription") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-server">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Server") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-store">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Storage") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-others">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Others") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="disco-category disco-wait">' +
|
||||||
|
'<p class="disco-category-title">' + Common._e("Loading") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="bottom">' +
|
||||||
|
'<div class="wait wait-medium"></div>' +
|
||||||
|
|
||||||
|
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
// Create the popup
|
||||||
|
Popup.create('discovery', html);
|
||||||
|
|
||||||
|
// Associate the events
|
||||||
|
self.instance();
|
||||||
|
|
||||||
|
// We request a disco to the default server
|
||||||
|
self.start();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Discovery.open', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quits the discovery popup
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.close = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Destroy the popup
|
||||||
|
Popup.destroy('discovery');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Discovery.close', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Launches a discovery
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.start = function() {
|
||||||
|
|
||||||
|
/* REF: http://xmpp.org/extensions/xep-0030.html */
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We get the server to query
|
||||||
|
var discoServer = $('#discovery .disco-server-input').val();
|
||||||
|
|
||||||
|
// We launch the items query
|
||||||
|
DataForm.go(discoServer, 'browse', '', '', 'discovery');
|
||||||
|
|
||||||
|
Console.log('Service discovery launched: ' + discoServer);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Discovery.start', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans the discovery results
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.clean = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We remove the results
|
||||||
|
$('#discovery .discovery-oneresult, #discovery .oneinstructions, #discovery .onetitle, #discovery .no-results').remove();
|
||||||
|
|
||||||
|
// We clean the user info
|
||||||
|
$('#discovery .disco-server-info').text('');
|
||||||
|
|
||||||
|
// We hide the wait icon, the no result alert and the results
|
||||||
|
$('#discovery .wait, #discovery .disco-category').hide();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Discovery.clean', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin launcher
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.instance = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Click event
|
||||||
|
$('#discovery .bottom .finish').click(self.close);
|
||||||
|
|
||||||
|
// Keyboard event
|
||||||
|
$('#discovery .disco-server-input').keyup(function(e) {
|
||||||
|
if(e.keyCode == 13) {
|
||||||
|
// No value?
|
||||||
|
if(!$(this).val())
|
||||||
|
$(this).val(HOST_MAIN);
|
||||||
|
|
||||||
|
// Start the discovery
|
||||||
|
self.start();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Discovery.instance', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
206
source/app/javascripts/errors.js
Normal file
|
@ -0,0 +1,206 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the error functions for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Errors = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the given error output
|
||||||
|
* @public
|
||||||
|
* @param {string} condition
|
||||||
|
* @param {string} reason
|
||||||
|
* @param {string} type
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.show = function(condition, reason, type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Enough data to output the error
|
||||||
|
if(condition || reason) {
|
||||||
|
// Initialize the error text
|
||||||
|
var eText = '';
|
||||||
|
|
||||||
|
// Any error condition
|
||||||
|
if(condition)
|
||||||
|
eText += condition;
|
||||||
|
|
||||||
|
// Any error type
|
||||||
|
if(type && eText)
|
||||||
|
eText += ' (' + type + ')';
|
||||||
|
|
||||||
|
// Any error reason
|
||||||
|
if(reason) {
|
||||||
|
if(eText)
|
||||||
|
eText += ' - ';
|
||||||
|
|
||||||
|
eText += reason;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We reveal the error
|
||||||
|
Board.openThisError(1);
|
||||||
|
|
||||||
|
// Create the error text
|
||||||
|
$('#board .one-board.error[data-id="1"] span').text(eText);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not enough data to output the error: output a generic board
|
||||||
|
else {
|
||||||
|
Board.openThisError(2);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Errors.show', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the error from a packet and return true if any error
|
||||||
|
* @public
|
||||||
|
* @param {object} packet
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.handle = function(packet) {
|
||||||
|
|
||||||
|
/* REF: http://xmpp.org/extensions/xep-0086.html */
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize
|
||||||
|
var type, code, reason, condition;
|
||||||
|
var node = $(packet);
|
||||||
|
|
||||||
|
// First level error (connection error)
|
||||||
|
if(node.is('error')) {
|
||||||
|
// Get the value
|
||||||
|
code = node.attr('code');
|
||||||
|
|
||||||
|
// Specific error reason
|
||||||
|
switch(code) {
|
||||||
|
case '401':
|
||||||
|
reason = Common._e("Authorization failed");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '409':
|
||||||
|
reason = Common._e("Registration failed, please choose a different username");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '503':
|
||||||
|
reason = Common._e("Service unavailable");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case '500':
|
||||||
|
reason = Common._e("Internal server error, try later");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
reason = node.find('text').text();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the general wait item (security)
|
||||||
|
Interface.removeGeneralWait();
|
||||||
|
|
||||||
|
// Show reconnect pane
|
||||||
|
if(Connection.current_session && Connection.connected) {
|
||||||
|
// Anonymous?
|
||||||
|
if(Utils.isAnonymous())
|
||||||
|
Connection.createReconnect('anonymous');
|
||||||
|
else
|
||||||
|
Connection.createReconnect('normal');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the homepage (security)
|
||||||
|
else if(!Connection.current_session || !Connection.connected) {
|
||||||
|
$('#home').show();
|
||||||
|
Interface.title('home');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Still connected? (security)
|
||||||
|
if(Common.isConnected()) {
|
||||||
|
con.disconnect();
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.error('First level error received.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second level error (another error)
|
||||||
|
else if(node.find('error').size()) {
|
||||||
|
type = node.find('error').attr('type');
|
||||||
|
reason = node.find('error text').text();
|
||||||
|
condition = packet.getElementsByTagName('error').item(0).childNodes.item(0).nodeName.replace(/-/g, ' ');
|
||||||
|
|
||||||
|
Console.error('Second level error received.');
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show the error board
|
||||||
|
self.show(condition, reason, type);
|
||||||
|
|
||||||
|
// Return there's an error
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Errors.handle', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the error reply of a packet
|
||||||
|
* @public
|
||||||
|
* @param {object} packet
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.handleReply = function(packet) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.handle(packet.getNode());
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Errors.handleReply', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the error reply for a message
|
||||||
|
* @public
|
||||||
|
* @param {object} packet
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.handleMessage = function(packet) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(!self.handleReply(packet)) {
|
||||||
|
Message.handle(packet);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Errors.handleMessage', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
719
source/app/javascripts/favorites.js
Normal file
|
@ -0,0 +1,719 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the favorites JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Favorites = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the favorites popup
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.open = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Popup HTML content
|
||||||
|
var html =
|
||||||
|
'<div class="top">' + Common._e("Manage favorite rooms") + '</div>' +
|
||||||
|
|
||||||
|
'<div class="content">' +
|
||||||
|
'<div class="switch-fav">' +
|
||||||
|
'<div class="room-switcher room-list">' +
|
||||||
|
'<div class="icon list-icon talk-images"></div>' +
|
||||||
|
|
||||||
|
Common._e("Change favorites") +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="room-switcher room-search">' +
|
||||||
|
'<div class="icon search-icon talk-images"></div>' +
|
||||||
|
|
||||||
|
Common._e("Search a room") +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="static-fav">' +
|
||||||
|
'<div class="favorites-edit favorites-content">' +
|
||||||
|
'<div class="head fedit-head static-fav-head">' +
|
||||||
|
'<div class="head-text fedit-head-text">' + Common._e("Select a favorite") + '</div>' +
|
||||||
|
|
||||||
|
'<select name="fedit-head-select" class="head-select fedit-head-select"></select>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="results fedit-results static-fav-results">' +
|
||||||
|
'<div class="fedit-line">' +
|
||||||
|
'<label>' + Common._e("Name") + '</label>' +
|
||||||
|
|
||||||
|
'<input class="fedit-title" type="text" required="" />' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="fedit-line">' +
|
||||||
|
'<label>' + Common._e("Nickname") + '</label>' +
|
||||||
|
|
||||||
|
'<input class="fedit-nick" type="text" value="' + Name.getNick() + '" required="" />' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="fedit-line">' +
|
||||||
|
'<label>' + Common._e("Room") + '</label>' +
|
||||||
|
|
||||||
|
'<input class="fedit-chan" type="text" required="" />' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="fedit-line">' +
|
||||||
|
'<label>' + Common._e("Server") + '</label>' +
|
||||||
|
|
||||||
|
'<input class="fedit-server" type="text" value="' + HOST_MUC + '" required="" />' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="fedit-line">' +
|
||||||
|
'<label>' + Common._e("Password") + '</label>' +
|
||||||
|
|
||||||
|
'<input class="fedit-password" type="password" />' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="fedit-line">' +
|
||||||
|
'<label>' + Common._e("Automatic") + '</label>' +
|
||||||
|
|
||||||
|
'<input type="checkbox" class="fedit-autojoin" />' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="fedit-actions">' +
|
||||||
|
'<a href="#" class="fedit-terminate fedit-add add one-button talk-images">' + Common._e("Add") + '</a>' +
|
||||||
|
'<a href="#" class="fedit-terminate fedit-edit one-button talk-images">' + Common._e("Edit") + '</a>' +
|
||||||
|
'<a href="#" class="fedit-terminate fedit-remove remove one-button talk-images">' + Common._e("Remove") + '</a>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="favorites-search favorites-content">' +
|
||||||
|
'<div class="head fsearch-head static-fav-head">' +
|
||||||
|
'<div class="head-text fsearch-head-text">' + Common._e("Search a room on") + '</div>' +
|
||||||
|
|
||||||
|
'<input type="text" class="head-input fsearch-head-server" value="' + HOST_MUC + '" />' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="results fsearch-results static-fav-results">' +
|
||||||
|
'<p class="fsearch-noresults">' + Common._e("No room found on this server.") + '</p>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="bottom">' +
|
||||||
|
'<div class="wait wait-medium"></div>' +
|
||||||
|
|
||||||
|
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
// Create the popup
|
||||||
|
Popup.create('favorites', html);
|
||||||
|
|
||||||
|
// Load the favorites
|
||||||
|
self.load();
|
||||||
|
|
||||||
|
// Associate the events
|
||||||
|
self.instance();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.open', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resets the favorites elements
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.reset = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var path = '#favorites ';
|
||||||
|
|
||||||
|
$(path + '.wait, ' + path + '.fedit-terminate').hide();
|
||||||
|
$(path + '.fedit-add').show();
|
||||||
|
$(path + '.fsearch-oneresult').remove();
|
||||||
|
$(path + 'input').val('');
|
||||||
|
$(path + '.please-complete').removeClass('please-complete');
|
||||||
|
$(path + '.fedit-nick').val(Name.getNick());
|
||||||
|
$(path + '.fsearch-head-server, ' + path + '.fedit-server').val(HOST_MUC);
|
||||||
|
$(path + '.fedit-autojoin').removeAttr('checked');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.reset', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Quits the favorites popup
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.quit = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Destroy the popup
|
||||||
|
Popup.destroy('favorites');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.quit', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a room to the favorites
|
||||||
|
* @public
|
||||||
|
* @param {string} roomXID
|
||||||
|
* @param {string} roomName
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.addThis = function(roomXID, roomName) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Button path
|
||||||
|
var button = '#favorites .fsearch-results div[data-xid="' + escape(roomXID) + '"] a.one-button';
|
||||||
|
|
||||||
|
// Add a remove button instead of the add one
|
||||||
|
$(button + '.add').replaceWith('<a href="#" class="one-button remove talk-images">' + Common._e("Remove") + '</a>');
|
||||||
|
|
||||||
|
// Click event
|
||||||
|
$(button + '.remove').click(function() {
|
||||||
|
return self.removeThis(roomXID, roomName);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Hide the add button in the (opened?) groupchat
|
||||||
|
$('#' + hex_md5(roomXID) + ' .tools-add').hide();
|
||||||
|
|
||||||
|
// Add the database entry
|
||||||
|
self.display(roomXID, Common.explodeThis(' (', roomName, 0), Name.getNick(), '0', '');
|
||||||
|
|
||||||
|
// Publish the favorites
|
||||||
|
self.publish();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.addThis', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a room from the favorites
|
||||||
|
* @public
|
||||||
|
* @param {string} roomXID
|
||||||
|
* @param {string} roomName
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.removeThis = function(roomXID, roomName) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Button path
|
||||||
|
var button = '#favorites .fsearch-results div[data-xid="' + escape(roomXID) + '"] a.one-button';
|
||||||
|
|
||||||
|
// Add a remove button instead of the add one
|
||||||
|
$(button + '.remove').replaceWith('<a href="#" class="one-button add talk-images">' + Common._e("Add") + '</a>');
|
||||||
|
|
||||||
|
// Click event
|
||||||
|
$(button + '.add').click(function() {
|
||||||
|
return self.addThis(roomXID, roomName);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show the add button in the (opened?) groupchat
|
||||||
|
$('#' + hex_md5(roomXID) + ' .tools-add').show();
|
||||||
|
|
||||||
|
// Remove the favorite
|
||||||
|
self.remove(roomXID, true);
|
||||||
|
|
||||||
|
// Publish the favorites
|
||||||
|
self.publish();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.removeThis', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Edits a favorite
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.edit = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Path to favorites
|
||||||
|
var favorites = '#favorites .';
|
||||||
|
|
||||||
|
// Reset the favorites
|
||||||
|
self.reset();
|
||||||
|
|
||||||
|
// Show the edit/remove button, hide the others
|
||||||
|
$(favorites + 'fedit-terminate').hide();
|
||||||
|
$(favorites + 'fedit-edit').show();
|
||||||
|
$(favorites + 'fedit-remove').show();
|
||||||
|
|
||||||
|
// We retrieve the values
|
||||||
|
var xid = $(favorites + 'fedit-head-select').val();
|
||||||
|
var data = Common.XMLFromString(DataStore.getDB(Connection.desktop_hash, 'favorites', xid));
|
||||||
|
|
||||||
|
// If this is not the default room
|
||||||
|
if(xid != 'none') {
|
||||||
|
// We apply the values
|
||||||
|
$(favorites + 'fedit-title').val($(data).find('name').text());
|
||||||
|
$(favorites + 'fedit-nick').val($(data).find('nick').text());
|
||||||
|
$(favorites + 'fedit-chan').val(Common.getXIDNick(xid));
|
||||||
|
$(favorites + 'fedit-server').val(Common.getXIDHost(xid));
|
||||||
|
$(favorites + 'fedit-password').val($(data).find('password').text());
|
||||||
|
|
||||||
|
if($(data).find('autojoin').text() == 'true')
|
||||||
|
$(favorites + 'fedit-autojoin').attr('checked', true);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.edit', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Terminate a favorite editing
|
||||||
|
* @public
|
||||||
|
* @param {string} type
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.terminateThis = function(type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Path to favorites
|
||||||
|
var favorites = '#favorites ';
|
||||||
|
|
||||||
|
// We get the values of the current edited groupchat
|
||||||
|
var old_xid = $(favorites + '.fedit-head-select').val();
|
||||||
|
|
||||||
|
var title = $(favorites + '.fedit-title').val();
|
||||||
|
var nick = $(favorites + '.fedit-nick').val();
|
||||||
|
var room = $(favorites + '.fedit-chan').val();
|
||||||
|
var server = $(favorites + '.fedit-server').val();
|
||||||
|
var xid = room + '@' + server;
|
||||||
|
var password = $(favorites + '.fedit-password').val();
|
||||||
|
var autojoin = 'false';
|
||||||
|
|
||||||
|
if($(favorites + '.fedit-autojoin').filter(':checked').size())
|
||||||
|
autojoin = 'true';
|
||||||
|
|
||||||
|
// We check the missing values and send this if okay
|
||||||
|
if((type == 'add') || (type == 'edit')) {
|
||||||
|
if(title && nick && room && server) {
|
||||||
|
// Remove the edited room
|
||||||
|
if(type == 'edit')
|
||||||
|
self.remove(old_xid, true);
|
||||||
|
|
||||||
|
// Display the favorites
|
||||||
|
self.display(xid, title, nick, autojoin, password);
|
||||||
|
|
||||||
|
// Reset the inputs
|
||||||
|
self.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
$(favorites + 'input[required]').each(function() {
|
||||||
|
var select = $(this);
|
||||||
|
|
||||||
|
if(!select.val())
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
select.addClass('please-complete').focus();
|
||||||
|
});
|
||||||
|
else
|
||||||
|
select.removeClass('please-complete');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Must remove a favorite?
|
||||||
|
else if(type == 'remove') {
|
||||||
|
self.remove(old_xid, true);
|
||||||
|
|
||||||
|
// Reset the inputs
|
||||||
|
self.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Publish the new favorites
|
||||||
|
self.publish();
|
||||||
|
|
||||||
|
Console.info('Action on this bookmark: ' + room + '@' + server + ' / ' + type);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.terminateThis', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a favorite
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {boolean} database
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.remove = function(xid, database) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We remove the target favorite everywhere needed
|
||||||
|
$('.buddy-conf-groupchat-select option[value="' + xid + '"]').remove();
|
||||||
|
$('.fedit-head-select option[value="' + xid + '"]').remove();
|
||||||
|
|
||||||
|
// Must remove it from database?
|
||||||
|
if(database) {
|
||||||
|
DataStore.removeDB(Connection.desktop_hash, 'favorites', xid);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.remove', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a favorite to the XMPP server
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.publish = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var iq = new JSJaCIQ();
|
||||||
|
iq.setType('set');
|
||||||
|
|
||||||
|
var query = iq.setQuery(NS_PRIVATE);
|
||||||
|
var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_BOOKMARKS}));
|
||||||
|
|
||||||
|
// We generate the XML
|
||||||
|
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'favorites_(.+)');
|
||||||
|
|
||||||
|
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||||
|
// Get the pointer values
|
||||||
|
var current = DataStore.storageDB.key(i);
|
||||||
|
|
||||||
|
// If the pointer is on a stored favorite
|
||||||
|
if(current.match(db_regex)) {
|
||||||
|
var data = Common.XMLFromString(DataStore.storageDB.getItem(current));
|
||||||
|
var xid = $(data).find('xid').text();
|
||||||
|
var rName = $(data).find('name').text();
|
||||||
|
var nick = $(data).find('nick').text();
|
||||||
|
var password = $(data).find('password').text();
|
||||||
|
var autojoin = $(data).find('autojoin').text();
|
||||||
|
|
||||||
|
// We create the node for this groupchat
|
||||||
|
var item = storage.appendChild(iq.buildNode('conference', {'name': rName, 'jid': xid, 'autojoin': autojoin, xmlns: NS_BOOKMARKS}));
|
||||||
|
item.appendChild(iq.buildNode('nick', {xmlns: NS_BOOKMARKS}, nick));
|
||||||
|
|
||||||
|
if(password)
|
||||||
|
item.appendChild(iq.buildNode('password', {xmlns: NS_BOOKMARKS}, password));
|
||||||
|
|
||||||
|
Console.info('Bookmark sent: ' + xid);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
con.send(iq);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.publish', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a list of the MUC items on a given server
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.getGCList = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var path = '#favorites .';
|
||||||
|
var gcServer = $('.fsearch-head-server').val();
|
||||||
|
|
||||||
|
// We reset some things
|
||||||
|
$(path + 'fsearch-oneresult').remove();
|
||||||
|
$(path + 'fsearch-noresults').hide();
|
||||||
|
$(path + 'wait').show();
|
||||||
|
|
||||||
|
var iq = new JSJaCIQ();
|
||||||
|
iq.setType('get');
|
||||||
|
iq.setTo(gcServer);
|
||||||
|
|
||||||
|
iq.setQuery(NS_DISCO_ITEMS);
|
||||||
|
|
||||||
|
con.send(iq, self.handleGCList);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.getGCList', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the MUC items list
|
||||||
|
* @public
|
||||||
|
* @param {object} iq
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.handleGCList = function(iq) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var path = '#favorites .';
|
||||||
|
var from = Common.fullXID(Common.getStanzaFrom(iq));
|
||||||
|
|
||||||
|
if(!iq || (iq.getType() != 'result')) {
|
||||||
|
Board.openThisError(3);
|
||||||
|
|
||||||
|
$(path + 'wait').hide();
|
||||||
|
|
||||||
|
Console.error('Error while retrieving the rooms: ' + from);
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
var handleXML = iq.getQuery();
|
||||||
|
|
||||||
|
if($(handleXML).find('item').size()) {
|
||||||
|
// Initialize the HTML code
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
$(handleXML).find('item').each(function() {
|
||||||
|
var roomXID = $(this).attr('jid');
|
||||||
|
var roomName = $(this).attr('name');
|
||||||
|
|
||||||
|
if(roomXID && roomName) {
|
||||||
|
// Escaped values
|
||||||
|
var escaped_xid = Utils.encodeOnclick(roomXID);
|
||||||
|
var escaped_name = Utils.encodeOnclick(roomName);
|
||||||
|
|
||||||
|
// Initialize the room HTML
|
||||||
|
html += '<div class="oneresult fsearch-oneresult" data-xid="' + escape(roomXID) + '">' +
|
||||||
|
'<div class="room-name">' + roomName.htmlEnc() + '</div>' +
|
||||||
|
'<a href="#" class="one-button join talk-images" onclick="return Favorites.join(\'' + escaped_xid + '\');">' + Common._e("Join") + '</a>';
|
||||||
|
|
||||||
|
// This room is yet a favorite
|
||||||
|
if(DataStore.existDB('favorites', roomXID))
|
||||||
|
html += '<a href="#" class="one-button remove talk-images" onclick="return Favorites.removeThis(\'' + escaped_xid + '\', \'' + escaped_name + '\');">' + Common._e("Remove") + '</a>';
|
||||||
|
else
|
||||||
|
html += '<a href="#" class="one-button add talk-images" onclick="return Favorites.addThis(\'' + escaped_xid + '\', \'' + escaped_name + '\');">' + Common._e("Add") + '</a>';
|
||||||
|
|
||||||
|
// Close the room HTML
|
||||||
|
html += '</div>';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Append this code to the popup
|
||||||
|
$(path + 'fsearch-results').append(html);
|
||||||
|
}
|
||||||
|
|
||||||
|
else
|
||||||
|
$(path + 'fsearch-noresults').show();
|
||||||
|
|
||||||
|
Console.info('Rooms retrieved: ' + from);
|
||||||
|
}
|
||||||
|
|
||||||
|
$(path + 'wait').hide();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.handleGCList', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Joins a groupchat from favorites
|
||||||
|
* @public
|
||||||
|
* @param {string} room
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.join = function(room) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
self.quit();
|
||||||
|
Chat.checkCreate(room, 'groupchat', '', '', Common.getXIDNick(room));
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.join', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a given favorite
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} name
|
||||||
|
* @param {string} nick
|
||||||
|
* @param {boolean} autojoin
|
||||||
|
* @param {string} password
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.display = function(xid, name, nick, autojoin, password) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Generate the HTML code
|
||||||
|
var html = '<option value="' + Common.encodeQuotes(xid) + '">' + name.htmlEnc() + '</option>';
|
||||||
|
|
||||||
|
// Remove the existing favorite
|
||||||
|
self.remove(xid, false);
|
||||||
|
|
||||||
|
// We complete the select forms
|
||||||
|
$('#roster .gc-join-first-option, #favorites .fedit-head-select-first-option').after(html);
|
||||||
|
|
||||||
|
// We store the informations
|
||||||
|
var value = '<groupchat><xid>' + xid.htmlEnc() + '</xid><name>' + name.htmlEnc() + '</name><nick>' + nick.htmlEnc() + '</nick><autojoin>' + autojoin.htmlEnc() + '</autojoin><password>' + password.htmlEnc() + '</password></groupchat>';
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'favorites', xid, value);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.display', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the favorites for the popup
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.load = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize the HTML code
|
||||||
|
var html = '';
|
||||||
|
|
||||||
|
// Read the database
|
||||||
|
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'favorites_(.+)');
|
||||||
|
|
||||||
|
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||||
|
// Get the pointer values
|
||||||
|
var current = DataStore.storageDB.key(i);
|
||||||
|
|
||||||
|
// If the pointer is on a stored favorite
|
||||||
|
if(current.match(db_regex)) {
|
||||||
|
var data = Common.XMLFromString(DataStore.storageDB.getItem(current));
|
||||||
|
|
||||||
|
// Add the current favorite to the HTML code
|
||||||
|
html += '<option value="' + Common.encodeQuotes($(data).find('xid').text()) + '">' + $(data).find('name').text().htmlEnc() + '</option>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate specific HTML code
|
||||||
|
var favorites_bubble = '<option value="none" class="gc-join-first-option" selected="">' + Common._e("Select a favorite") + '</option>' + html;
|
||||||
|
var favorites_popup = '<option value="none" class="fedit-head-select-first-option" selected="">' + Common._e("Select a favorite") + '</option>' + html;
|
||||||
|
|
||||||
|
// Append the HTML code
|
||||||
|
$('#roster .buddy-conf-groupchat-select').html(favorites_bubble);
|
||||||
|
$('#favorites .fedit-head-select').html(favorites_popup);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.load', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin launcher
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.instance = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var path = '#favorites .';
|
||||||
|
|
||||||
|
// Keyboard events
|
||||||
|
$(path + 'fsearch-head-server').keyup(function(e) {
|
||||||
|
if(e.keyCode == 13) {
|
||||||
|
// No value?
|
||||||
|
if(!$(this).val())
|
||||||
|
$(this).val(HOST_MUC);
|
||||||
|
|
||||||
|
// Get the list
|
||||||
|
self.getGCList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(path + 'fedit-line input').keyup(function(e) {
|
||||||
|
if(e.keyCode == 13) {
|
||||||
|
// Edit a favorite
|
||||||
|
if($(path + 'fedit-edit').is(':visible'))
|
||||||
|
terminateThis('edit');
|
||||||
|
|
||||||
|
// Add a favorite
|
||||||
|
else
|
||||||
|
terminateThis('add');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Change events
|
||||||
|
$('.fedit-head-select').change(self.edit);
|
||||||
|
|
||||||
|
// Click events
|
||||||
|
$(path + 'room-switcher').click(function() {
|
||||||
|
$(path + 'favorites-content').hide();
|
||||||
|
self.reset();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(path + 'room-list').click(function() {
|
||||||
|
$(path + 'favorites-edit').show();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(path + 'room-search').click(function() {
|
||||||
|
$(path + 'favorites-search').show();
|
||||||
|
self.getGCList();
|
||||||
|
});
|
||||||
|
|
||||||
|
$(path + 'fedit-add').click(function() {
|
||||||
|
return terminateThis('add');
|
||||||
|
});
|
||||||
|
|
||||||
|
$(path + 'fedit-edit').click(function() {
|
||||||
|
return terminateThis('edit');
|
||||||
|
});
|
||||||
|
|
||||||
|
$(path + 'fedit-remove').click(function() {
|
||||||
|
return terminateThis('remove');
|
||||||
|
});
|
||||||
|
|
||||||
|
$(path + 'bottom .finish').click(function() {
|
||||||
|
return self.quit();
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Favorites.instance', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
370
source/app/javascripts/features.js
Normal file
|
@ -0,0 +1,370 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
This is the server features JS script for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou, Maranda
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Features = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the features of a server
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.get = function() {
|
||||||
|
|
||||||
|
/* REF: http://xmpp.org/extensions/xep-0030.html */
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get the main values
|
||||||
|
var to = Utils.getServer();
|
||||||
|
var caps = con.server_caps;
|
||||||
|
var xml = null;
|
||||||
|
|
||||||
|
// Try to get the stored data
|
||||||
|
if(caps) {
|
||||||
|
xml = Common.XMLFromString(
|
||||||
|
DataStore.getPersistent('global', 'caps', caps)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any stored data?
|
||||||
|
if(xml) {
|
||||||
|
self.handle(xml);
|
||||||
|
|
||||||
|
Console.log('Read server CAPS from cache.');
|
||||||
|
} else {
|
||||||
|
// Not stored (or no CAPS)!
|
||||||
|
var iq = new JSJaCIQ();
|
||||||
|
|
||||||
|
iq.setTo(to);
|
||||||
|
iq.setType('get');
|
||||||
|
iq.setQuery(NS_DISCO_INFO);
|
||||||
|
|
||||||
|
con.send(iq, Caps.handleDiscoInfos);
|
||||||
|
|
||||||
|
Console.log('Read server CAPS from network.');
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Features.get', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the features of a server
|
||||||
|
* @public
|
||||||
|
* @param {string} xml
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.handle = function(xml) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Selector
|
||||||
|
var selector = $(xml);
|
||||||
|
|
||||||
|
// Functions
|
||||||
|
var check_feature_fn = function(namespace) {
|
||||||
|
// This weird selector fixes an IE8 bug...
|
||||||
|
return (selector.find('feature').filter(function() {
|
||||||
|
return ($(this).attr('var') == namespace);
|
||||||
|
}).size() > 0 ? true : false);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Markers
|
||||||
|
var namespaces = [NS_PUBSUB, NS_PUBSUB_CN, NS_URN_MAM, NS_COMMANDS, NS_URN_CARBONS];
|
||||||
|
|
||||||
|
var cur_feature;
|
||||||
|
var features = {
|
||||||
|
// This weird selector fixes the same IE8 bug as above...
|
||||||
|
'pep': (selector.find('identity').filter(function() {
|
||||||
|
var this_sel = $(this);
|
||||||
|
return (this_sel.attr('category') == 'pubsub' && this_sel.attr('type') == 'pep');
|
||||||
|
}).size() && true)
|
||||||
|
};
|
||||||
|
|
||||||
|
$.each(namespaces, function(n, namespace) {
|
||||||
|
features[namespace] = check_feature_fn(namespace);
|
||||||
|
|
||||||
|
if(features[namespace] === true) {
|
||||||
|
self.enable(namespace);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Enable the pep elements if available
|
||||||
|
if(features.pep === true) {
|
||||||
|
// Update our database
|
||||||
|
self.enable('pep');
|
||||||
|
|
||||||
|
// Get the PEP nodes to initiate
|
||||||
|
Microblog.getInit();
|
||||||
|
PEP.getInitGeoloc();
|
||||||
|
|
||||||
|
// Get the notifications
|
||||||
|
Notification.get();
|
||||||
|
|
||||||
|
// Geolocate the user
|
||||||
|
PEP.geolocate();
|
||||||
|
|
||||||
|
// Enable microblogging send tools
|
||||||
|
Microblog.wait('sync');
|
||||||
|
$('.postit.attach').css('display', 'block');
|
||||||
|
|
||||||
|
Console.info('XMPP server supports PEP.');
|
||||||
|
} else {
|
||||||
|
Microblog.wait('unsync');
|
||||||
|
|
||||||
|
Console.warn('XMPP server does not support PEP.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hide the private life fieldset if nothing to show
|
||||||
|
if(features.pep === false && features[NS_URN_MAM] === false) {
|
||||||
|
$('#options fieldset.privacy').hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the features
|
||||||
|
self.apply('talk');
|
||||||
|
|
||||||
|
// Process the roster height
|
||||||
|
if(features.pep === true) {
|
||||||
|
Roster.adapt();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable Message Carbons?
|
||||||
|
if(features[NS_URN_CARBONS] === true) {
|
||||||
|
Carbons.enable();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Features.handle', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The function to apply the features to an element
|
||||||
|
* @public
|
||||||
|
* @param {string} id
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.apply = function(id) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Path to the elements
|
||||||
|
var path = '#' + id + ' .';
|
||||||
|
|
||||||
|
// PEP features
|
||||||
|
if(self.enabledPEP()) {
|
||||||
|
$(path + 'pep-hidable').show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PubSub features
|
||||||
|
if(self.enabledPubSub()) {
|
||||||
|
$(path + 'pubsub-hidable').show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// PubSub Config-Node features
|
||||||
|
if(self.enabledPubSubCN()) {
|
||||||
|
$(path + 'pubsub-hidable-cn').show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// MAM features
|
||||||
|
if(self.enabledMAM()) {
|
||||||
|
$(path + 'mam-hidable').show();
|
||||||
|
$(path + 'mam-showable').hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
// MAM Purge
|
||||||
|
if(self.enabledMAMPurge()) {
|
||||||
|
$(path + 'mam-purge-hidable').show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Commands features
|
||||||
|
if(self.enabledCommands()) {
|
||||||
|
$(path + 'commands-hidable').show();
|
||||||
|
}
|
||||||
|
|
||||||
|
// XMPP links (browser feature)
|
||||||
|
if(navigator.registerProtocolHandler) {
|
||||||
|
$(path + 'xmpplinks-hidable').show();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Features.apply', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enables a feature
|
||||||
|
* @public
|
||||||
|
* @param {string} feature
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.enable = function(feature) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'feature', feature, 'true');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Features.enable', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if a feature is enabled
|
||||||
|
* @public
|
||||||
|
* @param {string} feature
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.isEnabled = function(feature) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return DataStore.getDB(Connection.desktop_hash, 'feature', feature) === 'true';
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Features.isEnabled', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the XMPP server PEP support
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.enabledPEP = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.isEnabled('pep');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Features.enabledPEP', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the XMPP server PubSub support
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.enabledPubSub = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.isEnabled(NS_PUBSUB);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Features.enabledPubSub', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the XMPP server PubSub Config-Node support
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.enabledPubSubCN = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.isEnabled(NS_PUBSUB_CN);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Features.enabledPubSubCN', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the XMPP server MAM support
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.enabledMAM = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.isEnabled(NS_URN_MAM);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Features.enabledMAM', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns Metronome MAM Purge support
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.enabledMAMPurge = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(self.isEnabled(NS_URN_MAM)) {
|
||||||
|
return self.isEnabled(NS_METRONOME_MAM_PURGE);
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Features.enabledMAMPurge', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the XMPP server Carbons support
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.enabledCarbons = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.isEnabled(NS_URN_CARBONS);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Features.enabledCarbons', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the XMPP server commands support
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.enabledCommands = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return self.isEnabled(NS_COMMANDS);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Features.enabledCommands', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
250
source/app/javascripts/filter.js
Normal file
|
@ -0,0 +1,250 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the filtering JS script for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Authors: Valérian Saliou, Maranda
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Filter = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a given emoticon HTML code
|
||||||
|
* @public
|
||||||
|
* @param {string} image
|
||||||
|
* @param {string} text
|
||||||
|
* @param {string} after
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.emoteImage = function(image, text, after) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return ' <img class="emoticon emoticon-' + image + ' smileys-images" alt="' + Common.encodeQuotes(text) + '" src="' + './images/others/blank.gif' + '" /> ' + after;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Filter.emoteImage', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters a given message
|
||||||
|
* @public
|
||||||
|
* @param {string} neutralMessage
|
||||||
|
* @param {string} nick
|
||||||
|
* @param {string} html_escape
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.message = function(neutralMessage, nick, html_escape) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var filteredMessage = neutralMessage;
|
||||||
|
|
||||||
|
// We encode the HTML special chars
|
||||||
|
if(html_escape)
|
||||||
|
filteredMessage = filteredMessage.htmlEnc();
|
||||||
|
|
||||||
|
// /me command
|
||||||
|
filteredMessage = filteredMessage.replace(/((^)|((.+)(>)))(\/me )([^<]+)/, nick + ' $7')
|
||||||
|
|
||||||
|
// We replace the smilies text into images
|
||||||
|
.replace(/(:-?@)($|\s|<)/gi, self.emoteImage('angry', '$1', '$2'))
|
||||||
|
.replace(/(:-?\[)($|\s|<)/gi, self.emoteImage('bat', '$1', '$2'))
|
||||||
|
.replace(/(\(B\))($|\s|<)/g, self.emoteImage('beer', '$1', '$2'))
|
||||||
|
.replace(/((:-?D)|(XD))($|\s|<)/gi, self.emoteImage('biggrin', '$1', '$4'))
|
||||||
|
.replace(/(:-?\$)($|\s|<)/gi, self.emoteImage('blush', '$1', '$2'))
|
||||||
|
.replace(/(\(Z\))($|\s|<)/g, self.emoteImage('boy', '$1', '$2'))
|
||||||
|
.replace(/(\(W\))($|\s|<)/g, self.emoteImage('brflower', '$1', '$2'))
|
||||||
|
.replace(/((<\/3)|(\(U\)))($|\s|<)/g, self.emoteImage('brheart', '$1', '$4'))
|
||||||
|
.replace(/(\(C\))($|\s|<)/g, self.emoteImage('coffee', '$1', '$2'))
|
||||||
|
.replace(/((8-\))|(\(H\)))($|\s|<)/g, self.emoteImage('coolglasses', '$1', '$4'))
|
||||||
|
.replace(/(:'-?\()($|\s|<)/gi, self.emoteImage('cry', '$1', '$2'))
|
||||||
|
.replace(/(\(%\))($|\s|<)/g, self.emoteImage('cuffs', '$1', '$2'))
|
||||||
|
.replace(/(\]:-?>)($|\s|<)/gi, self.emoteImage('devil', '$1', '$2'))
|
||||||
|
.replace(/(\(D\))($|\s|<)/g, self.emoteImage('drink', '$1', '$2'))
|
||||||
|
.replace(/(@}->--)($|\s|<)/gi, self.emoteImage('flower', '$1', '$2'))
|
||||||
|
.replace(/((:-?\/)|(:-?S))($|\s|<)/gi, self.emoteImage('frowning', '$1', '$4'))
|
||||||
|
.replace(/(\(X\))($|\s|<)/g, self.emoteImage('girl', '$1', '$2'))
|
||||||
|
.replace(/((<3)|(\(L\)))($|\s|<)/g, self.emoteImage('heart', '$1', '$4'))
|
||||||
|
.replace(/(\(}\))($|\s|<)/g, self.emoteImage('hugleft', '$1', '$2'))
|
||||||
|
.replace(/(\({\))($|\s|<)/g, self.emoteImage('hugright', '$1', '$2'))
|
||||||
|
.replace(/(:-?{})($|\s|<)/gi, self.emoteImage('kiss', '$1', '$2'))
|
||||||
|
.replace(/(\(I\))($|\s|<)/g, self.emoteImage('lamp', '$1', '$2'))
|
||||||
|
.replace(/(:-?3)($|\s|<)/gi, self.emoteImage('lion', '$1', '$2'))
|
||||||
|
.replace(/(\(E\))($|\s|<)/g, self.emoteImage('mail', '$1', '$2'))
|
||||||
|
.replace(/(\(S\))($|\s|<)/g, self.emoteImage('moon', '$1', '$2'))
|
||||||
|
.replace(/(\(8\))($|\s|<)/g, self.emoteImage('music', '$1', '$2'))
|
||||||
|
.replace(/((=-?O)|(:-?O))($|\s|<)/gi, self.emoteImage('oh', '$1', '$4'))
|
||||||
|
.replace(/(\(T\))($|\s|<)/g, self.emoteImage('phone', '$1', '$2'))
|
||||||
|
.replace(/(\(P\))($|\s|<)/g, self.emoteImage('photo', '$1', '$2'))
|
||||||
|
.replace(/(:-?!)($|\s|<)/gi, self.emoteImage('puke', '$1', '$2'))
|
||||||
|
.replace(/(\(@\))($|\s|<)/g, self.emoteImage('pussy', '$1', '$2'))
|
||||||
|
.replace(/(\(R\))($|\s|<)/g, self.emoteImage('rainbow', '$1', '$2'))
|
||||||
|
.replace(/(:-?\))($|\s|<)/gi, self.emoteImage('smile', '$1', '$2'))
|
||||||
|
.replace(/(\(\*\))($|\s|<)/g, self.emoteImage('star', '$1', '$2'))
|
||||||
|
.replace(/(:-?\|)($|\s|<)/gi, self.emoteImage('stare', '$1', '$2'))
|
||||||
|
.replace(/(\(N\))($|\s|<)/g, self.emoteImage('thumbdown', '$1', '$2'))
|
||||||
|
.replace(/(\(Y\))($|\s|<)/g, self.emoteImage('thumbup', '$1', '$2'))
|
||||||
|
.replace(/(:-?P)($|\s|<)/gi, self.emoteImage('tongue', '$1', '$2'))
|
||||||
|
.replace(/(:-?\()($|\s|<)/gi, self.emoteImage('unhappy', '$1', '$2'))
|
||||||
|
.replace(/(;-?\))($|\s|<)/gi, self.emoteImage('wink', '$1', '$2'))
|
||||||
|
|
||||||
|
// Text in bold
|
||||||
|
.replace(/(^|\s|>|\()((\*)([^<>'"\*]+)(\*))($|\s|<|\))/gi, '$1<b>$2</b>$6')
|
||||||
|
|
||||||
|
// Italic text
|
||||||
|
.replace(/(^|\s|>|\()((\/)([^<>'"\/]+)(\/))($|\s|<|\))/gi, '$1<em>$2</em>$6')
|
||||||
|
|
||||||
|
// Underlined text
|
||||||
|
.replace(/(^|\s|>|\()((_)([^<>'"_]+)(_))($|\s|<|\))/gi, '$1<span style="text-decoration: underline;">$2</span>$6');
|
||||||
|
|
||||||
|
// Add the links
|
||||||
|
if(html_escape) {
|
||||||
|
filteredMessage = Links.apply(filteredMessage, 'desktop');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Filter integratebox links
|
||||||
|
filteredMessage = IntegrateBox.filter(filteredMessage);
|
||||||
|
|
||||||
|
return filteredMessage;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Filter.message', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters a xHTML message to be displayed in Jappix
|
||||||
|
* @public
|
||||||
|
* @param {string} code
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.xhtml = function(code) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Allowed elements array
|
||||||
|
var elements = new Array(
|
||||||
|
'a',
|
||||||
|
'abbr',
|
||||||
|
'acronym',
|
||||||
|
'address',
|
||||||
|
'blockquote',
|
||||||
|
'body',
|
||||||
|
'br',
|
||||||
|
'cite',
|
||||||
|
'code',
|
||||||
|
'dd',
|
||||||
|
'dfn',
|
||||||
|
'div',
|
||||||
|
'dt',
|
||||||
|
'em',
|
||||||
|
'h1',
|
||||||
|
'h2',
|
||||||
|
'h3',
|
||||||
|
'h4',
|
||||||
|
'h5',
|
||||||
|
'h6',
|
||||||
|
'head',
|
||||||
|
'html',
|
||||||
|
'kbd',
|
||||||
|
'li',
|
||||||
|
'ol',
|
||||||
|
'p',
|
||||||
|
'pre',
|
||||||
|
'q',
|
||||||
|
'samp',
|
||||||
|
'span',
|
||||||
|
'strong',
|
||||||
|
'title',
|
||||||
|
'ul',
|
||||||
|
'var'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Allowed attributes array
|
||||||
|
var attributes = new Array(
|
||||||
|
'accesskey',
|
||||||
|
'alt',
|
||||||
|
'charset',
|
||||||
|
'cite',
|
||||||
|
'class',
|
||||||
|
'height',
|
||||||
|
'href',
|
||||||
|
'hreflang',
|
||||||
|
'id',
|
||||||
|
'longdesc',
|
||||||
|
'profile',
|
||||||
|
'rel',
|
||||||
|
'rev',
|
||||||
|
'src',
|
||||||
|
'style',
|
||||||
|
'tabindex',
|
||||||
|
'title',
|
||||||
|
'type',
|
||||||
|
'uri',
|
||||||
|
'version',
|
||||||
|
'width',
|
||||||
|
'xml:lang',
|
||||||
|
'xmlns'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check if Filter for XHTML-IM images is enabled
|
||||||
|
if(DataStore.getDB(Connection.desktop_hash, 'options', 'no-xhtml-images') != '1') {
|
||||||
|
elements.push("img");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove forbidden elements
|
||||||
|
$(code).find('html body *').each(function() {
|
||||||
|
// This element is not authorized
|
||||||
|
if(!Utils.existArrayValue(elements, (this).nodeName.toLowerCase()))
|
||||||
|
$(this).remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove forbidden attributes
|
||||||
|
$(code).find('html body *').each(function() {
|
||||||
|
// Put a pointer on this element (jQuery way & normal way)
|
||||||
|
var cSelector = $(this);
|
||||||
|
var cElement = (this);
|
||||||
|
|
||||||
|
// Loop the attributes of the current element
|
||||||
|
$(cElement.attributes).each(function(index) {
|
||||||
|
// Read the current attribute
|
||||||
|
var cAttr = cElement.attributes[index];
|
||||||
|
var cName = cAttr.name;
|
||||||
|
var cVal = cAttr.value;
|
||||||
|
|
||||||
|
// This attribute is not authorized, or contains JS code
|
||||||
|
if(!Utils.existArrayValue(attributes, cName.toLowerCase()) || ((cVal.toLowerCase()).match(/(^|"|')javascript:/)))
|
||||||
|
cSelector.removeAttr(cName);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Filter some other elements
|
||||||
|
$(code).find('a').attr('target', '_blank');
|
||||||
|
|
||||||
|
return $(code).find('html body').html();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Filter.xhtml', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
680
source/app/javascripts/groupchat.js
Normal file
|
@ -0,0 +1,680 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the groupchat JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Authors: Valérian Saliou, Maranda, Eric
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Groupchat = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
var JOIN_SUGGEST = [];
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays the MUC admin elements
|
||||||
|
* @public
|
||||||
|
* @param {string} affiliation
|
||||||
|
* @param {string} id
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {number} statuscode
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.openAdmin = function(affiliation, id, xid, statuscode) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We must be in the "login" mode
|
||||||
|
if(Utils.isAnonymous())
|
||||||
|
return;
|
||||||
|
|
||||||
|
// We check if the user is a room owner or administrator to give him privileges
|
||||||
|
if(affiliation == 'owner' || affiliation == 'admin')
|
||||||
|
$('#' + id + ' .tools-mucadmin').show();
|
||||||
|
|
||||||
|
// We check if the room hasn't been yet created
|
||||||
|
if(statuscode == 201)
|
||||||
|
Board.openThisInfo(4);
|
||||||
|
|
||||||
|
// We add the click event
|
||||||
|
$('#' + id + ' .tools-mucadmin').click(function() {
|
||||||
|
MUCAdmin.open(xid, affiliation);
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.openAdmin', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initializes a connection with a MUC groupchat
|
||||||
|
* @public
|
||||||
|
* @param {string} room
|
||||||
|
* @param {string} nickname
|
||||||
|
* @param {string} password
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.getMUC = function(room, nickname, password) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Room hash
|
||||||
|
var hash = hex_md5(room);
|
||||||
|
|
||||||
|
// Reset the elements
|
||||||
|
$('#' + hash + ' .muc-ask').remove();
|
||||||
|
$('#' + hash + ' .compose').show();
|
||||||
|
|
||||||
|
// No nickname?
|
||||||
|
if(!nickname) {
|
||||||
|
// Get some values
|
||||||
|
if(!Utils.isAnonymous())
|
||||||
|
nickname = Name.getNick();
|
||||||
|
else
|
||||||
|
nickname = ANONYMOUS_NICK;
|
||||||
|
|
||||||
|
// If the nickname could not be retrieved, ask it
|
||||||
|
if(!nickname)
|
||||||
|
self.generateMUCAsk('nickname', room, hash, nickname, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Got our nickname?
|
||||||
|
if(nickname) {
|
||||||
|
// Get our general presence
|
||||||
|
var show = DataStore.getDB(Connection.desktop_hash, 'presence-show', 1);
|
||||||
|
var status = DataStore.getDB(Connection.desktop_hash, 'options', 'presence-status');
|
||||||
|
|
||||||
|
// Set my nick
|
||||||
|
$('#' + hash).attr('data-nick', escape(nickname));
|
||||||
|
|
||||||
|
// Send the appropriate presence
|
||||||
|
Presence.send(room + '/' + nickname, '', show, status, '', true, password, self.handleMUC);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.getMUC', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles the MUC main elements
|
||||||
|
* @public
|
||||||
|
* @param {object} presence
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.handleMUC = function(presence) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We get the xml content
|
||||||
|
var xml = presence.getNode();
|
||||||
|
var from = Common.fullXID(Common.getStanzaFrom(presence));
|
||||||
|
var room = Common.bareXID(from);
|
||||||
|
var nickname = Common.thisResource(from);
|
||||||
|
var hash = hex_md5(room);
|
||||||
|
|
||||||
|
// No ID: must fix M-Link bug
|
||||||
|
if(presence.getID() === null) {
|
||||||
|
presence.setID(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.info('First MUC presence: ' + from);
|
||||||
|
|
||||||
|
// Catch the errors
|
||||||
|
if(!Errors.handle(xml)) {
|
||||||
|
// Define some stuffs
|
||||||
|
var muc_user = $(xml).find('x[xmlns="' + NS_MUC_USER + '"]');
|
||||||
|
var affiliation = muc_user.find('item').attr('affiliation');
|
||||||
|
var statuscode = parseInt(muc_user.find('status').attr('code'));
|
||||||
|
|
||||||
|
// Handle my presence
|
||||||
|
Presence.handle(presence);
|
||||||
|
|
||||||
|
// Check if I am a room owner
|
||||||
|
self.openAdmin(affiliation, hash, room, statuscode);
|
||||||
|
|
||||||
|
// Tell the MUC we can notify the incoming presences
|
||||||
|
$(document).oneTime('15s', function() {
|
||||||
|
$('#' + hash).attr('data-initial', 'true');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Enable the chatting input
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
$('#' + hash + ' .message-area').removeAttr('disabled').focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// A password is required
|
||||||
|
else if($(xml).find('error[type="auth"] not-authorized').size()) {
|
||||||
|
self.generateMUCAsk('password', room, hash, nickname);
|
||||||
|
}
|
||||||
|
|
||||||
|
// There's a nickname conflict
|
||||||
|
else if($(xml).find('error[type="cancel"] conflict').size()) {
|
||||||
|
self.generateMUCAsk('nickname', room, hash);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.handleMUC', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a correct MUC asker
|
||||||
|
* @public
|
||||||
|
* @param {string} type
|
||||||
|
* @param {string} room
|
||||||
|
* @param {string} hash
|
||||||
|
* @param {string} nickname
|
||||||
|
* @param {string} password
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.generateMUCAsk = function(type, room, hash, nickname, password) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Generate the path to the elements
|
||||||
|
var path_to = '#' + hash + ' .muc-ask';
|
||||||
|
|
||||||
|
// Define the label text
|
||||||
|
var label_text;
|
||||||
|
|
||||||
|
switch(type) {
|
||||||
|
case 'nickname':
|
||||||
|
label_text = Common._e("Nickname");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'password':
|
||||||
|
label_text = Common._e("Password");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create the HTML markup
|
||||||
|
$('#' + hash + ' .compose').hide();
|
||||||
|
|
||||||
|
$('#' + hash).append(
|
||||||
|
'<div class="muc-ask text">' +
|
||||||
|
'<label>' + label_text + '</label>' +
|
||||||
|
'<input class="focusable" type="text" />' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
// When a key is pressed in the input
|
||||||
|
$(path_to + ' input').keyup(function(e) {
|
||||||
|
var value_input = $(this).val();
|
||||||
|
|
||||||
|
// Enter key pressed
|
||||||
|
if(e.keyCode == 13) {
|
||||||
|
// $.trim() fixes #304
|
||||||
|
if(type == 'nickname' && $.trim(value_input)) {
|
||||||
|
nickname = $.trim(value_input);
|
||||||
|
return self.getMUC(room, nickname, password);
|
||||||
|
}
|
||||||
|
|
||||||
|
if(type == 'password' && value_input) {
|
||||||
|
password = value_input;
|
||||||
|
return self.getMUC(room, nickname, password);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Focus on the input
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
$(path_to + ' input').focus();
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.generateMUCAsk', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new groupchat
|
||||||
|
* @public
|
||||||
|
* @param {string} hash
|
||||||
|
* @param {string} room
|
||||||
|
* @param {string} chan
|
||||||
|
* @param {string} nickname
|
||||||
|
* @param {string} password
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.create = function(hash, room, chan, nickname, password) {
|
||||||
|
|
||||||
|
/* REF: http://xmpp.org/extensions/xep-0045.html */
|
||||||
|
|
||||||
|
try {
|
||||||
|
Console.info('New groupchat: ' + room);
|
||||||
|
|
||||||
|
// Create the chat content
|
||||||
|
Chat.generate('groupchat', hash, room, chan);
|
||||||
|
|
||||||
|
// Create the chat switcher
|
||||||
|
Chat.generateSwitch('groupchat', hash, room, chan);
|
||||||
|
|
||||||
|
// The icons-hover functions
|
||||||
|
Tooltip.icons(room, hash);
|
||||||
|
|
||||||
|
// Click event on the add tool
|
||||||
|
$('#' + hash + ' .tools-add').click(function() {
|
||||||
|
// Hide the icon (to tell the user all is okay)
|
||||||
|
$(this).hide();
|
||||||
|
|
||||||
|
// Add the groupchat to the user favorites
|
||||||
|
Favorites.addThis(room, chan);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Must show the add button?
|
||||||
|
if(!DataStore.existDB('favorites', room))
|
||||||
|
$('#' + hash + ' .tools-add').show();
|
||||||
|
|
||||||
|
// The event handlers
|
||||||
|
var inputDetect = $('#' + hash + ' .message-area');
|
||||||
|
|
||||||
|
// Focus event
|
||||||
|
inputDetect.focus(function() {
|
||||||
|
// Clean notifications for this chat
|
||||||
|
Interface.chanCleanNotify(hash);
|
||||||
|
|
||||||
|
// Store focus on this chat!
|
||||||
|
Interface.chat_focus_hash = hash;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Blur event
|
||||||
|
inputDetect.blur(function() {
|
||||||
|
// Reset storage about focus on this chat!
|
||||||
|
if(Interface.chat_focus_hash == hash)
|
||||||
|
Interface.chat_focus_hash = null;
|
||||||
|
|
||||||
|
// Reset autocompletion
|
||||||
|
Autocompletion.reset(hash);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Lock to the input
|
||||||
|
inputDetect.keydown(function(e) {
|
||||||
|
// Enter key
|
||||||
|
if(e.keyCode == 13) {
|
||||||
|
// If shift key (without any others modifiers) was pressed, add a new line
|
||||||
|
if(e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey)
|
||||||
|
inputDetect.val(inputDetect.val() + '\n');
|
||||||
|
|
||||||
|
// Send the message
|
||||||
|
else {
|
||||||
|
Message.send(hash, 'groupchat');
|
||||||
|
|
||||||
|
// Reset the composing database entry
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'chatstate', room, 'off');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tabulation key (without any modifiers)
|
||||||
|
else if(!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey && e.keyCode == 9) {
|
||||||
|
Autocompletion.create(hash);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the autocompleter
|
||||||
|
else {
|
||||||
|
Autocompletion.reset(hash);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Chatstate events
|
||||||
|
ChatState.events(inputDetect, room, hash, 'groupchat');
|
||||||
|
|
||||||
|
// Get the current muc informations and content
|
||||||
|
self.getMUC(room, nickname, password);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.create', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a groupchat to join array
|
||||||
|
* @public
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.arrayJoin = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Values array
|
||||||
|
var muc_arr = [GROUPCHATS_JOIN];
|
||||||
|
var new_arr = [];
|
||||||
|
|
||||||
|
// Try to split it
|
||||||
|
if(GROUPCHATS_JOIN.indexOf(',') != -1)
|
||||||
|
muc_arr = GROUPCHATS_JOIN.split(',');
|
||||||
|
|
||||||
|
for(var i in muc_arr) {
|
||||||
|
// Get the current value
|
||||||
|
var muc_current = $.trim(muc_arr[i]);
|
||||||
|
|
||||||
|
// No current value?
|
||||||
|
if(!muc_current)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Filter the current value
|
||||||
|
muc_current = Common.generateXID(muc_current, 'groupchat');
|
||||||
|
|
||||||
|
// Add the current value
|
||||||
|
if(!Utils.existArrayValue(new_arr, muc_current))
|
||||||
|
new_arr.push(muc_current);
|
||||||
|
}
|
||||||
|
|
||||||
|
return new_arr;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.arrayJoin', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Joins the defined groupchats
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.joinConf = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Nothing to join?
|
||||||
|
if(!JOIN_SUGGEST)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Join the chats
|
||||||
|
if(JOIN_SUGGEST.length) {
|
||||||
|
for(var g in JOIN_SUGGEST) {
|
||||||
|
Chat.checkCreate(JOIN_SUGGEST[g], 'groupchat');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.joinConf', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks suggest utility
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.suggestCheck = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var groupchat_arr = self.arrayJoin();
|
||||||
|
|
||||||
|
// Must suggest the user?
|
||||||
|
if((GROUPCHATS_SUGGEST == 'on') && groupchat_arr.length) {
|
||||||
|
if(Common.exists('#suggest'))
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Create HTML code
|
||||||
|
var html = '<div id="suggest" class="removable">';
|
||||||
|
html += '<div class="title">' + Common._e("Suggested chatrooms") + '</div>';
|
||||||
|
|
||||||
|
html += '<div class="content">';
|
||||||
|
for(var g in groupchat_arr) {
|
||||||
|
html += '<a class="one" href="#" data-xid="' + Common.encodeQuotes(groupchat_arr[g]) + '">';
|
||||||
|
html += '<span class="icon talk-images"></span>';
|
||||||
|
html += '<span class="name">' + Utils.capitaliseFirstLetter(Common.getXIDNick(groupchat_arr[g]).htmlEnc()) + '</span>';
|
||||||
|
html += '<span class="state talk-images"></span>';
|
||||||
|
html += '<span class="clear"></span>';
|
||||||
|
html += '</a>';
|
||||||
|
}
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
html += '<div class="bottom">';
|
||||||
|
html += '<a class="next continue disabled" href="#">' + Common._e("Continue") + '</a>';
|
||||||
|
html += '<a class="next skip" href="#">' + Common._e("Skip") + '</a>';
|
||||||
|
html += '</div>';
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
// Append HTML code
|
||||||
|
$('body').append(html);
|
||||||
|
|
||||||
|
// Click events
|
||||||
|
$('#suggest .content a.one').click(function() {
|
||||||
|
// Add/remove the active class
|
||||||
|
$(this).toggleClass('active');
|
||||||
|
|
||||||
|
// We require at least one room to be chosen
|
||||||
|
if(Common.exists('#suggest .content a.one.active'))
|
||||||
|
$('#suggest a.next').removeClass('disabled');
|
||||||
|
else
|
||||||
|
$('#suggest a.next').addClass('disabled');
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
$('#suggest a.next').click(function() {
|
||||||
|
// Disabled?
|
||||||
|
if($(this).hasClass('disabled')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store groupchats to join?
|
||||||
|
if($(this).is('.continue')) {
|
||||||
|
$('#suggest .content a.one.active').each(function() {
|
||||||
|
JOIN_SUGGEST.push($(this).attr('data-xid'));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch to talk UI
|
||||||
|
$('#suggest').remove();
|
||||||
|
Connection.triggerConnected();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
JOIN_SUGGEST = groupchat_arr;
|
||||||
|
|
||||||
|
Connection.triggerConnected();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.suggestCheck', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Bans a user from given room
|
||||||
|
* @public
|
||||||
|
* @param {string} room_xid
|
||||||
|
* @param {string} ban_xid
|
||||||
|
* @param {string} reason
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.banUser = function(room_xid, ban_xid, reason) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We check if the user exists
|
||||||
|
if(!ban_xid) {
|
||||||
|
Board.openThisInfo(6);
|
||||||
|
|
||||||
|
Console.warning('Could not ban user with XID: ' + ban_xid + ' from room: ' + room_xid);
|
||||||
|
} else {
|
||||||
|
// We generate the ban IQ
|
||||||
|
var iq = new JSJaCIQ();
|
||||||
|
iq.setTo(room_xid);
|
||||||
|
iq.setType('set');
|
||||||
|
|
||||||
|
var iqQuery = iq.setQuery(NS_MUC_ADMIN);
|
||||||
|
var item = iqQuery.appendChild(iq.buildNode('item', {'affiliation': 'outcast', 'jid': ban_xid, 'xmlns': NS_MUC_ADMIN}));
|
||||||
|
|
||||||
|
if(reason) {
|
||||||
|
item.appendChild(iq.buildNode('reason', {'xmlns': NS_MUC_ADMIN}, reason));
|
||||||
|
}
|
||||||
|
|
||||||
|
con.send(iq, Errors.handleReply);
|
||||||
|
|
||||||
|
Console.log('Banned user with XID: ' + ban_xid + ' from room: ' + room_xid);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.banUser', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Kicks a user from given room
|
||||||
|
* @public
|
||||||
|
* @param {string} room_xid
|
||||||
|
* @param {string} kick_xid
|
||||||
|
* @param {string} nick
|
||||||
|
* @param {string} reason
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.kickUser = function(room_xid, kick_xid, nick, reason) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We check if the user exists
|
||||||
|
if(!room_xid) {
|
||||||
|
Board.openThisInfo(6);
|
||||||
|
|
||||||
|
Console.warning('Could not kick user "' + nick + '" from room: ' + room_xid);
|
||||||
|
} else {
|
||||||
|
// We generate the kick IQ
|
||||||
|
var iq = new JSJaCIQ();
|
||||||
|
iq.setTo(room_xid);
|
||||||
|
iq.setType('set');
|
||||||
|
|
||||||
|
var iqQuery = iq.setQuery(NS_MUC_ADMIN);
|
||||||
|
var item = iqQuery.appendChild(iq.buildNode('item', {'nick': nick, 'role': 'none', 'xmlns': NS_MUC_ADMIN}));
|
||||||
|
|
||||||
|
if(reason) {
|
||||||
|
item.appendChild(iq.buildNode('reason', {'xmlns': NS_MUC_ADMIN}, reason));
|
||||||
|
}
|
||||||
|
|
||||||
|
con.send(iq, Errors.handleReply);
|
||||||
|
|
||||||
|
Console.info('Kicked user "' + nick + '" from room: ' + room_xid);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.kickUser', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Promotes an user as groupchat moderator
|
||||||
|
* @public
|
||||||
|
* @param {string} muc_xid
|
||||||
|
* @param {string} user_xid
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.promoteModerator = function(muc_xid, user_xid) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
MUCAdmin.setAffiliation(muc_xid, user_xid, 'admin');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.promoteModerator', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Demotes an user as being groupchat moderator
|
||||||
|
* @public
|
||||||
|
* @param {string} muc_xid
|
||||||
|
* @param {string} user_xid
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.demoteModerator = function(muc_xid, user_xid) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
MUCAdmin.setAffiliation(muc_xid, user_xid, 'none');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.demoteModerator', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns user affiliation in groupchat
|
||||||
|
* @public
|
||||||
|
* @param {string} muc_xid
|
||||||
|
* @param {string} nick
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.affiliationUser = function(muc_xid, nick) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initial data
|
||||||
|
var affiliations = ['none', 'member', 'admin', 'owner'];
|
||||||
|
var affiliation = {
|
||||||
|
code: 0,
|
||||||
|
name: affiliations[0]
|
||||||
|
};
|
||||||
|
|
||||||
|
// Get user data
|
||||||
|
var user_sel = $('#' + hex_md5(muc_xid) + ' .list .user[data-nick="' + escape(nick) + '"]');
|
||||||
|
|
||||||
|
if(user_sel.size()) {
|
||||||
|
var user_affiliation = user_sel.attr('data-affiliation');
|
||||||
|
|
||||||
|
if(user_affiliation && Utils.existArrayValue(affiliations, user_affiliation)) {
|
||||||
|
affiliation.code = Utils.indexArrayValue(affiliations, user_affiliation);
|
||||||
|
affiliation.name = user_affiliation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return affiliation;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.affiliationUser', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns our affiliation in groupchat
|
||||||
|
* @public
|
||||||
|
* @param {string} muc_xid
|
||||||
|
* @return {object}
|
||||||
|
*/
|
||||||
|
self.affiliationMe = function(muc_xid) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get my nick
|
||||||
|
var my_nick = unescape($('#' + hex_md5(muc_xid)).attr('data-nick') || '');
|
||||||
|
|
||||||
|
// Return my affiliation
|
||||||
|
return self.affiliationUser(muc_xid, my_nick);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Groupchat.affiliationMe', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
476
source/app/javascripts/home.js
Normal file
|
@ -0,0 +1,476 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the homepage JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Authors: Valérian Saliou, LinkMauve
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Home = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows the user to switch the difference home page elements
|
||||||
|
* @public
|
||||||
|
* @param {string} div
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.change = function(div) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Path to
|
||||||
|
var home = '#home .';
|
||||||
|
var right = home + 'right ';
|
||||||
|
var current = right + '.homediv.' + div;
|
||||||
|
|
||||||
|
// We switch the div
|
||||||
|
$(right + '.homediv, ' + right + '.top').hide();
|
||||||
|
$(right + '.' + div).show();
|
||||||
|
|
||||||
|
// We reset the homedivs
|
||||||
|
$(home + 'homediv:not(.default), ' + home + 'top:not(.default)').remove();
|
||||||
|
|
||||||
|
// Get the HTML code to display
|
||||||
|
var disable_form = '';
|
||||||
|
var lock_host = '';
|
||||||
|
var code = '';
|
||||||
|
|
||||||
|
// Apply the previous link
|
||||||
|
switch(div) {
|
||||||
|
case 'loginer':
|
||||||
|
case 'anonymouser':
|
||||||
|
case 'registerer':
|
||||||
|
if(!Common.exists(right + '.top.sub')) {
|
||||||
|
// Append the HTML code for previous link
|
||||||
|
$(right + '.top.default').after('<h1 class="top sub loginer anonymouser registerer">« <a href="#" class="previous">' + Common._e("Previous") + '</a></h1>');
|
||||||
|
|
||||||
|
// Click event on previous link
|
||||||
|
$(home + 'top.sub a.previous').click(function() {
|
||||||
|
return self.change('default');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the form
|
||||||
|
switch(div) {
|
||||||
|
// Login tool
|
||||||
|
case 'loginer':
|
||||||
|
lock_host = Utils.disableInput(LOCK_HOST, 'on');
|
||||||
|
code = '<p>' + Common.printf(Common._e("Login to your existing XMPP account. You can also use the %s to join a groupchat."), '<a href="#" class="to-anonymous">' + Common._e("anonymous mode") + '</a>') + '</p>' +
|
||||||
|
|
||||||
|
'<form action="#" method="post">' +
|
||||||
|
'<fieldset>' +
|
||||||
|
'<legend>' + Common._e("Required") + '</legend>' +
|
||||||
|
|
||||||
|
'<label for="lnick">' + Common._e("Address") + '</label>' +
|
||||||
|
'<input type="text" class="nick" id="lnick" pattern="[^@/]+" required="" /><span class="jid">@</span><input type="text" class="server" id="lserver" value="' + HOST_MAIN + '" ' + lock_host + ' pattern="[^@/]+" required="" />' +
|
||||||
|
'<label for="lpassword">' + Common._e("Password") + '</label>' +
|
||||||
|
'<input type="password" class="password" id="lpassword" required="" />' +
|
||||||
|
'<label for="lremember">' + Common._e("Remember me") + '</label>' +
|
||||||
|
'<input type="checkbox" class="remember" id="lremember" />' +
|
||||||
|
'</fieldset>' +
|
||||||
|
|
||||||
|
'<a href="#" class="advanced home-images">' + Common._e("Advanced") + '</a>' +
|
||||||
|
|
||||||
|
'<fieldset class="advanced">' +
|
||||||
|
'<legend>' + Common._e("Advanced") + '</legend>' +
|
||||||
|
|
||||||
|
'<label for="lresource">' + Common._e("Resource") + '</label>' +
|
||||||
|
'<input type="text" class="resource" id="lresource" value="' + JAPPIX_RESOURCE + '" />' +
|
||||||
|
'<label for="lpriority">' + Common._e("Priority") + '</label>' +
|
||||||
|
'<select class="priority" id="lpriority">' +
|
||||||
|
'<option value="1">' + Common._e("Low") + '</option>' +
|
||||||
|
'<option value="10" selected="">' + Common._e("Medium") + '</option>' +
|
||||||
|
'<option value="100">' + Common._e("High") + '</option>' +
|
||||||
|
'</select>' +
|
||||||
|
'</fieldset>' +
|
||||||
|
|
||||||
|
'<div class="submit">' +
|
||||||
|
'<input type="submit" value="' + Common._e("Here we go!") + '" />' +
|
||||||
|
|
||||||
|
'<div class="clear"></div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</form>';
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Anonymous login tool
|
||||||
|
case 'anonymouser':
|
||||||
|
disable_form = Utils.disableInput(ANONYMOUS, 'off');
|
||||||
|
code = '<p>' + Common.printf(Common._e("Enter the groupchat you want to join and the nick you want to have. You can also go back to the %s."), '<a href="#" class="to-home">' + Common._e("login page") + '</a>') + '</p>';
|
||||||
|
|
||||||
|
if(LEGAL)
|
||||||
|
code += '<p>' + Common.printf(Common._e("By using our service, you accept %s."), '<b><a href="' + Common.encodeQuotes(LEGAL) + '" target="_blank">' + Common._e("our terms of use") + '</a></b>') + '</p>';
|
||||||
|
|
||||||
|
code += '<form action="#" method="post">' +
|
||||||
|
'<fieldset>' +
|
||||||
|
'<legend>' + Common._e("Required") + '</legend>' +
|
||||||
|
|
||||||
|
'<label>' + Common._e("Room") + '</label>' +
|
||||||
|
'<input type="text" class="room"' + disable_form + ' pattern="[^/]+" required="" />' +
|
||||||
|
|
||||||
|
'<label>' + Common._e("Nickname") + '</label>' +
|
||||||
|
'<input type="text" class="nick"' + disable_form + ' required="" />' +
|
||||||
|
'</fieldset>' +
|
||||||
|
|
||||||
|
'<input type="submit" value="' + Common._e("Here we go!") + '"' + disable_form + ' />' +
|
||||||
|
'</form>' +
|
||||||
|
|
||||||
|
'<div class="info report">' +
|
||||||
|
Common._e("Share this link with your friends:") + ' <span></span>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Register tool
|
||||||
|
case 'registerer':
|
||||||
|
disable_form = Utils.disableInput(REGISTRATION, 'off');
|
||||||
|
|
||||||
|
if(!disable_form)
|
||||||
|
lock_host = Utils.disableInput(LOCK_HOST, 'on');
|
||||||
|
|
||||||
|
code = '<p>' + Common._e("Register a new XMPP account to join your friends on your own social cloud. That's simple!") + '</p>';
|
||||||
|
|
||||||
|
if(LEGAL)
|
||||||
|
code += '<p>' + Common.printf(Common._e("By using our service, you accept %s."), '<b><a href="' + Common.encodeQuotes(LEGAL) + '" target="_blank">' + Common._e("our terms of use") + '</a></b>') + '</p>';
|
||||||
|
|
||||||
|
code += '<form action="#" method="post">' +
|
||||||
|
'<fieldset>' +
|
||||||
|
'<legend>' + Common._e("Required") + '</legend>' +
|
||||||
|
|
||||||
|
'<label for="rnick">' + Common._e("Address") + '</label>' +
|
||||||
|
'<input type="text" class="nick" id="rnick" ' + disable_form + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Username") + '" /><span class="jid">@</span><input type="text" class="server" id="rserver" value="' + HOST_MAIN + '" ' + disable_form + lock_host + ' pattern="[^@/]+" required="" placeholder="' + Common._e("Server") + '" />' +
|
||||||
|
'<label for="rpassword">' + Common._e("Password") + '</label>' +
|
||||||
|
'<input type="password" class="password" id="rpassword" ' + disable_form + ' required="" placeholder="' + Common._e("Enter password") + '" /><input type="password" class="spassword" id="spassword" ' + disable_form + ' required="" placeholder="' + Common._e("Once again...") + '" />';
|
||||||
|
|
||||||
|
if(REGISTER_API == 'on')
|
||||||
|
code += '<div class="captcha_grp">' +
|
||||||
|
'<label for="captcha">' + Common._e("Code") + '</label><input type="text" class="captcha" id="captcha" ' + disable_form + ' maxlength="6" pattern="[a-zA-Z0-9]{6}" required="" placeholder="' + Common._e("Security code") + '" /><img class="captcha_img" src="./server/captcha.php?id=' + genID() + '" alt="" />' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
code += '</fieldset>' +
|
||||||
|
|
||||||
|
'<input type="submit" value="' + Common._e("Here we go!") + '" ' + disable_form + '/>' +
|
||||||
|
'</form>';
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Form disabled?
|
||||||
|
if(disable_form)
|
||||||
|
code += '<div class="info fail">' +
|
||||||
|
Common._e("This tool has been disabled!") +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
// Create this HTML code
|
||||||
|
if(code && !Common.exists(current)) {
|
||||||
|
// Append it!
|
||||||
|
$(right + '.homediv.default').after('<div class="' + div + ' homediv">' + code + '</div>');
|
||||||
|
|
||||||
|
// Create the attached events
|
||||||
|
switch(div) {
|
||||||
|
// Login tool
|
||||||
|
case 'loginer':
|
||||||
|
$(current + ' a.to-anonymous').click(function() {
|
||||||
|
return self.change('anonymouser');
|
||||||
|
});
|
||||||
|
|
||||||
|
$(current + ' a.advanced').click(self.showAdvanced);
|
||||||
|
$(current + ' form').submit(self.loginForm);
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Anonymous login tool
|
||||||
|
case 'anonymouser':
|
||||||
|
$(current + ' a.to-home').click(function() {
|
||||||
|
return self.change('loginer');
|
||||||
|
});
|
||||||
|
|
||||||
|
$(current + ' form').submit(Connection.doAnonymous);
|
||||||
|
|
||||||
|
// Keyup event on anonymous join's room input
|
||||||
|
$(current + ' input.room').keyup(function() {
|
||||||
|
var value = $(this).val();
|
||||||
|
var report = current + ' .report';
|
||||||
|
var span = report + ' span';
|
||||||
|
|
||||||
|
if(!value) {
|
||||||
|
$(report).hide();
|
||||||
|
$(span).text('');
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
$(report).show();
|
||||||
|
$(span).text(JAPPIX_LOCATION + '?r=' + value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Register tool
|
||||||
|
case 'registerer':
|
||||||
|
// Server input change
|
||||||
|
$('#home input.server').keyup(function(e) {
|
||||||
|
if($.trim($(this).val()) == HOST_MAIN) {
|
||||||
|
$('#home .captcha_grp').show();
|
||||||
|
$('#home input.captcha').removeAttr('disabled');
|
||||||
|
} else {
|
||||||
|
$('#home .captcha_grp').hide();
|
||||||
|
$('#home input.captcha').attr('disabled', true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Register input placeholder
|
||||||
|
// FIXME: breaks IE compatibility
|
||||||
|
//$('#home input[placeholder]').placeholder();
|
||||||
|
|
||||||
|
// Register form submit
|
||||||
|
$(current + ' form').submit(self.registerForm);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We focus on the first input
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
$(right + 'input:visible:first').focus();
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Home.change', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allows the user to display the advanced login options
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.showAdvanced = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Hide the link
|
||||||
|
$('#home a.advanced').hide();
|
||||||
|
|
||||||
|
// Show the fieldset
|
||||||
|
$('#home fieldset.advanced').show();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Home.showAdvanced', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the login form values
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.loginForm = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We get the values
|
||||||
|
var lPath = '#home .loginer ';
|
||||||
|
var lServer = $(lPath + '.server').val();
|
||||||
|
var lNick = Common.nodeprep($(lPath + '.nick').val());
|
||||||
|
var lPass = $(lPath + '.password').val();
|
||||||
|
var lResource = $(lPath + '.resource').val();
|
||||||
|
var lPriority = $(lPath + '.priority').val();
|
||||||
|
var lRemember = $(lPath + '.remember').filter(':checked').size();
|
||||||
|
|
||||||
|
// Enough values?
|
||||||
|
if(lServer && lNick && lPass && lResource && lPriority) {
|
||||||
|
Connection.doLogin(lNick, lServer, lPass, lResource, lPriority, lRemember);
|
||||||
|
} else {
|
||||||
|
$(lPath + 'input[type="text"], ' + lPath + 'input[type="password"]').each(function() {
|
||||||
|
var select = $(this);
|
||||||
|
|
||||||
|
if(!select.val())
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
select.addClass('please-complete').focus();
|
||||||
|
});
|
||||||
|
else
|
||||||
|
select.removeClass('please-complete');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Home.loginForm', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the register form values
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.registerForm = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var rPath = '#home .registerer ';
|
||||||
|
|
||||||
|
// Remove the success info
|
||||||
|
$(rPath + '.success').remove();
|
||||||
|
|
||||||
|
// Get the values
|
||||||
|
var username = Common.nodeprep($(rPath + '.nick').val());
|
||||||
|
var domain = $(rPath + '.server').val();
|
||||||
|
var pass = $(rPath + '.password').val();
|
||||||
|
var spass = $(rPath + '.spassword').val();
|
||||||
|
var captcha = $(rPath + '.captcha').val();
|
||||||
|
|
||||||
|
// Enough values?
|
||||||
|
if(domain && username && pass && spass && (pass == spass) && !((REGISTER_API == 'on') && (domain == HOST_MAIN) && !captcha)) {
|
||||||
|
// We remove the not completed class to avoid problems
|
||||||
|
$('#home .registerer input').removeClass('please-complete');
|
||||||
|
|
||||||
|
// Fire the register event!
|
||||||
|
Connection.doRegister(username, domain, pass, captcha);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Something is missing?
|
||||||
|
else {
|
||||||
|
$(rPath + 'input[type="text"], ' + rPath + 'input[type="password"]').each(function() {
|
||||||
|
var select = $(this);
|
||||||
|
|
||||||
|
if(!select.val() || (select.is('#spassword') && pass && (pass != spass)))
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
select.addClass('please-complete').focus();
|
||||||
|
});
|
||||||
|
else
|
||||||
|
select.removeClass('please-complete');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Home.registerForm', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin launcher
|
||||||
|
* @public
|
||||||
|
* @param {type} name
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.launch = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$(document).ready(function() {
|
||||||
|
// Define the vars
|
||||||
|
var home = '#home ';
|
||||||
|
var button = home + 'button';
|
||||||
|
var corp = home + '.corporation';
|
||||||
|
var aboutus = home + '.aboutus';
|
||||||
|
var locale = home + '.locale';
|
||||||
|
|
||||||
|
// Removes the <noscript /> elements to lighten the DOM
|
||||||
|
$('noscript').remove();
|
||||||
|
|
||||||
|
// Allows the user to switch the home page
|
||||||
|
$(button).click(function() {
|
||||||
|
// Login button
|
||||||
|
if($(this).is('.login'))
|
||||||
|
return self.change('loginer');
|
||||||
|
|
||||||
|
// Register button
|
||||||
|
else
|
||||||
|
return self.change('registerer');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Allows the user to view the corporation & about infobox
|
||||||
|
$(corp + ', ' + aboutus).hover(function() {
|
||||||
|
$(this).addClass('hovered');
|
||||||
|
}, function() {
|
||||||
|
$(this).removeClass('hovered');
|
||||||
|
});
|
||||||
|
|
||||||
|
// Allows the user to switch the language
|
||||||
|
$(locale).hover(function() {
|
||||||
|
// Initialize the HTML code
|
||||||
|
var keepget = $(locale).attr('data-keepget');
|
||||||
|
var html = '<div class="list">';
|
||||||
|
|
||||||
|
// Generate each locale HTML code
|
||||||
|
for(var i in LOCALES_AVAILABLE_ID) {
|
||||||
|
html += '<a href="./?l=' + LOCALES_AVAILABLE_ID[i] + keepget + '">' + LOCALES_AVAILABLE_NAMES[i].htmlEnc() + '</a>';
|
||||||
|
}
|
||||||
|
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
// Append the HTML code
|
||||||
|
$(locale).append(html);
|
||||||
|
}, function() {
|
||||||
|
$(locale + ' .list').remove();
|
||||||
|
});
|
||||||
|
|
||||||
|
// Disables the browser HTTP-requests stopper
|
||||||
|
$(document).keydown(function(e) {
|
||||||
|
if((e.keyCode == 27) && !System.isDeveloper())
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Warns for an obsolete browser
|
||||||
|
if(Utils.isObsolete()) {
|
||||||
|
// Add the code
|
||||||
|
$(locale).after(
|
||||||
|
'<div class="obsolete">' +
|
||||||
|
'<p>' + Common._e("Your browser is out of date!") + '</p>' +
|
||||||
|
|
||||||
|
'<a class="firefox browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Mozilla Firefox') + '" href="http://www.mozilla.com/firefox/"></a>' +
|
||||||
|
'<a class="chrome browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Google Chrome') + '" href="http://www.google.com/chrome"></a>' +
|
||||||
|
'<a class="safari browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Safari') + '" href="http://www.apple.com/safari/"></a>' +
|
||||||
|
'<a class="opera browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Opera') + '" href="http://www.opera.com/"></a>' +
|
||||||
|
'<a class="ie browsers-images" title="' + Common.printf(Common._e("Last %s version is better!"), 'Internet Explorer') + '" href="http://www.microsoft.com/hk/windows/internet-explorer/"></a>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Display it later
|
||||||
|
$(home + '.obsolete').oneTime('1s', function() {
|
||||||
|
$(this).slideDown();
|
||||||
|
});
|
||||||
|
|
||||||
|
Console.warn('Jappix does not support this browser!');
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.log('Welcome to Jappix! Happy coding in developer mode!');
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Home.launch', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
Home.launch();
|
118
source/app/javascripts/httpauth.js
Normal file
|
@ -0,0 +1,118 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the http-auth JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou, Kload
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var HTTPAuth = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Login to a HTTP session
|
||||||
|
* @public
|
||||||
|
* @param {string} lNick
|
||||||
|
* @param {string} lPass
|
||||||
|
* @param {string} lServer
|
||||||
|
* @param {number} lPriority
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.go = function(lNick, lPass, lServer, lPriority) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We add the login wait div
|
||||||
|
Interface.showGeneralWait();
|
||||||
|
|
||||||
|
oArgs = {};
|
||||||
|
|
||||||
|
if(Common.hasWebSocket()) {
|
||||||
|
// WebSocket supported & configured
|
||||||
|
con = new JSJaCWebSocketConnection({
|
||||||
|
httpbase: HOST_WEBSOCKET
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
var httpbase = (HOST_BOSH_MAIN || HOST_BOSH);
|
||||||
|
|
||||||
|
// Check BOSH origin
|
||||||
|
BOSH_SAME_ORIGIN = Origin.isSame(httpbase);
|
||||||
|
|
||||||
|
// We create the new http-binding connection
|
||||||
|
con = new JSJaCHttpBindingConnection({
|
||||||
|
httpbase: httpbase
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// And we handle everything that happen
|
||||||
|
self.setupCon(con);
|
||||||
|
|
||||||
|
// Generate a resource
|
||||||
|
var random_resource = DataStore.getDB(Connection.desktop_hash, 'session', 'resource');
|
||||||
|
|
||||||
|
if(!random_resource) {
|
||||||
|
random_resource = JAPPIX_RESOURCE + ' (' + (new Date()).getTime() + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Generate a priority
|
||||||
|
lPriority = lPriority ? lPriority : 10;
|
||||||
|
|
||||||
|
// We retrieve what the user typed in the login inputs
|
||||||
|
oArgs = {};
|
||||||
|
oArgs.domain = $.trim(lServer);
|
||||||
|
oArgs.username = $.trim(lNick);
|
||||||
|
oArgs.resource = random_resource;
|
||||||
|
oArgs.pass = lPass;
|
||||||
|
oArgs.secure = true;
|
||||||
|
oArgs.xmllang = XML_LANG;
|
||||||
|
|
||||||
|
// Store the resource (for reconnection)
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'session', 'resource', random_resource);
|
||||||
|
|
||||||
|
// Generate a session XML to be stored
|
||||||
|
session_xml = '<session><stored>true</stored><domain>' + lServer.htmlEnc() + '</domain><username>' + lNick.htmlEnc() + '</username><resource>' + random_resource + '</resource><password>' + lPass.htmlEnc() + '</password><priority>' + (lPriority + '').htmlEnc() + '</priority></session>';
|
||||||
|
|
||||||
|
// Save the session parameters (for reconnect if network issue)
|
||||||
|
Connection.current_session = session_xml;
|
||||||
|
|
||||||
|
// We store the infos of the user into the data-base
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'priority', 1, 10);
|
||||||
|
|
||||||
|
// We connect !
|
||||||
|
con.connect(oArgs);
|
||||||
|
|
||||||
|
// Change the page title
|
||||||
|
Interface.title('wait');
|
||||||
|
|
||||||
|
Console.info('Jappix is connecting...');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('HTTPAuth.go', e);
|
||||||
|
|
||||||
|
// Reset Jappix
|
||||||
|
Talk.destroy();
|
||||||
|
|
||||||
|
// Open an unknown error
|
||||||
|
Board.openThisError(2);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
70
source/app/javascripts/httpreply.js
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the http-reply JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var HTTPReply = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replies to a HTTP request
|
||||||
|
* @public
|
||||||
|
* @param {string} value
|
||||||
|
* @param {object} xml
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.go = function(value, xml) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We parse the xml content
|
||||||
|
var from = Common.fullXID(Common.getStanzaFrom(xml));
|
||||||
|
var confirm = $(xml.getNode()).find('confirm');
|
||||||
|
var xmlns = confirm.attr('xmlns');
|
||||||
|
var id = confirm.attr('id');
|
||||||
|
var method = confirm.attr('method');
|
||||||
|
var url = confirm.attr('url');
|
||||||
|
|
||||||
|
// We generate the reply message
|
||||||
|
var aMsg = new JSJaCMessage();
|
||||||
|
aMsg.setTo(from);
|
||||||
|
|
||||||
|
// If "no"
|
||||||
|
if(value == 'no') {
|
||||||
|
aMsg.setType('error');
|
||||||
|
aMsg.appendNode('error', {'code': '401', 'type': 'auth'});
|
||||||
|
}
|
||||||
|
|
||||||
|
// We set the confirm node
|
||||||
|
aMsg.appendNode('confirm', {'xmlns': xmlns, 'url': url, 'id': id, 'method': method});
|
||||||
|
|
||||||
|
// We send the message
|
||||||
|
con.send(aMsg, Errors.handleReply);
|
||||||
|
|
||||||
|
Console.info('Replying HTTP auth request: ' + from);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('HTTPReply.go', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
985
source/app/javascripts/inbox.js
Normal file
|
@ -0,0 +1,985 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the inbox JS script for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Inbox = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the inbox popup
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.open = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Popup HTML content
|
||||||
|
var html =
|
||||||
|
'<div class="top">' + Common._e("Your inbox") + '</div>' +
|
||||||
|
|
||||||
|
'<div class="content">' +
|
||||||
|
'<div class="head inbox-head">' +
|
||||||
|
'<div class="head-text inbox-head-text">' + Common._e("Available actions") + '</div>' +
|
||||||
|
|
||||||
|
'<div class="head-actions inbox-head-actions">' +
|
||||||
|
'<a href="#" class="a-delete-messages">' + Common._e("Clean") + '</a>' +
|
||||||
|
'<a href="#" class="a-new-message">' + Common._e("New") + '</a>' +
|
||||||
|
'<a href="#" class="a-show-messages">' + Common._e("Received") + '</a>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="inbox-results">' +
|
||||||
|
'<p class="inbox-noresults">' + Common._e("Your inbox is empty.") + '</p>' +
|
||||||
|
|
||||||
|
'<div class="inbox"></div>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="inbox-new">' +
|
||||||
|
'<div class="inbox-new-to inbox-new-block search">' +
|
||||||
|
'<p class="inbox-new-text">' + Common._e("To") + '</p>' +
|
||||||
|
|
||||||
|
'<input name="inbox-new-to-input" class="inbox-new-input inbox-new-to-input" type="text" required="" />' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="inbox-new-topic inbox-new-block">' +
|
||||||
|
'<p class="inbox-new-text">' + Common._e("Subject") + '</p>' +
|
||||||
|
|
||||||
|
'<input name="inbox-new-subject-input" class="inbox-new-input inbox-new-subject-input" type="text" required="" />' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="inbox-new-body inbox-new-block">' +
|
||||||
|
'<p class="inbox-new-text">' + Common._e("Content") + '</p>' +
|
||||||
|
|
||||||
|
'<textarea class="inbox-new-textarea" rows="8" cols="60" required=""></textarea>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<form class="inbox-new-file inbox-new-block" action="./server/file-share.php" method="post" enctype="multipart/form-data">' +
|
||||||
|
'<p class="inbox-new-text">' + Common._e("File") + '</p>' +
|
||||||
|
|
||||||
|
Interface.generateFileShare() +
|
||||||
|
'</form>' +
|
||||||
|
|
||||||
|
'<div class="inbox-new-send inbox-new-block">' +
|
||||||
|
'<a href="#" class="send one-button talk-images">' + Common._e("Send message") + '</a>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="bottom">' +
|
||||||
|
'<div class="wait wait-medium"></div>' +
|
||||||
|
|
||||||
|
'<a href="#" class="finish">' + Common._e("Close") + '</a>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
// Create the popup
|
||||||
|
Popup.create('inbox', html);
|
||||||
|
|
||||||
|
// Associate the events
|
||||||
|
self.instance();
|
||||||
|
|
||||||
|
// Load the messages
|
||||||
|
self.load();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.open', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the inbox popup
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.close = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Destroy the popup
|
||||||
|
Popup.destroy('inbox');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.close', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the message compose tool
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.composeMessage = function(xid) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Open things
|
||||||
|
self.open();
|
||||||
|
self.newMessage();
|
||||||
|
|
||||||
|
// Apply XID
|
||||||
|
$('#inbox .inbox-new-to-input').val(xid);
|
||||||
|
|
||||||
|
// Focus to the next item
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
$('#inbox .inbox-new-subject-input').focus();
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.composeMessage', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores the inbox
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.store = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var iq = new JSJaCIQ();
|
||||||
|
iq.setType('set');
|
||||||
|
var query = iq.setQuery(NS_PRIVATE);
|
||||||
|
var storage = query.appendChild(iq.buildNode('storage', {'xmlns': NS_INBOX}));
|
||||||
|
|
||||||
|
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)'));
|
||||||
|
|
||||||
|
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||||
|
// Get the pointer values
|
||||||
|
var current = DataStore.storageDB.key(i);
|
||||||
|
|
||||||
|
// If the pointer is on a stored message
|
||||||
|
if(current.match(db_regex)) {
|
||||||
|
// Get the values
|
||||||
|
var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current)));
|
||||||
|
|
||||||
|
// Create the storage node
|
||||||
|
storage.appendChild(iq.buildNode('message', {
|
||||||
|
'id': value.find('id').text().revertHtmlEnc(),
|
||||||
|
'from': value.find('from').text().revertHtmlEnc(),
|
||||||
|
'subject': value.find('subject').text().revertHtmlEnc(),
|
||||||
|
'status': value.find('status').text().revertHtmlEnc(),
|
||||||
|
'date': value.find('date').text().revertHtmlEnc(),
|
||||||
|
'xmlns': NS_INBOX
|
||||||
|
},
|
||||||
|
|
||||||
|
value.find('content').text().revertHtmlEnc()
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
con.send(iq);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.store', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new normal message
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.newMessage = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Init
|
||||||
|
var mPath = '#inbox .';
|
||||||
|
|
||||||
|
// Reset the previous buddy search
|
||||||
|
Search.resetBuddy('#inbox .inbox-new-to');
|
||||||
|
|
||||||
|
// We switch the divs
|
||||||
|
$(mPath + 'inbox-results, #inbox .a-new-message, #inbox .a-delete-messages').hide();
|
||||||
|
$(mPath + 'inbox-new, #inbox .a-show-messages').show();
|
||||||
|
|
||||||
|
// We focus on the first input
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
$(mPath + 'inbox-new-to-input').focus();
|
||||||
|
});
|
||||||
|
|
||||||
|
// We reset some stuffs
|
||||||
|
self.cleanNewMessage();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.newMessage', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans the inbox
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.cleanNewMessage = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Init
|
||||||
|
var mPath = '#inbox .';
|
||||||
|
|
||||||
|
// We reset the forms
|
||||||
|
$(mPath + 'inbox-new-block:not(form) input, ' + mPath + 'inbox-new textarea').val('').removeClass('please-complete');
|
||||||
|
$(mPath + 'inbox-new-file a').remove();
|
||||||
|
$(mPath + 'inbox-new-file input').show();
|
||||||
|
|
||||||
|
// We close an eventual opened message
|
||||||
|
$(mPath + 'message-content').remove();
|
||||||
|
$(mPath + 'one-message').removeClass('message-reading');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.cleanNewMessage', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a normal message
|
||||||
|
* @public
|
||||||
|
* @param {string} to
|
||||||
|
* @param {string} subject
|
||||||
|
* @param {string} body
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.sendMessage = function(to, subject, body) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We send the message
|
||||||
|
var mess = new JSJaCMessage();
|
||||||
|
|
||||||
|
// Main attributes
|
||||||
|
mess.setTo(to);
|
||||||
|
mess.setSubject(subject);
|
||||||
|
mess.setType('normal');
|
||||||
|
|
||||||
|
// Any file to attach?
|
||||||
|
var attached = '#inbox .inbox-new-file a.file';
|
||||||
|
|
||||||
|
if(Common.exists(attached)) {
|
||||||
|
body += '\n' +
|
||||||
|
'\n' +
|
||||||
|
$(attached).attr('data-attachedtitle') + ' - ' + $(attached).attr('data-attachedhref');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set body
|
||||||
|
mess.setBody(body);
|
||||||
|
|
||||||
|
con.send(mess, Errors.handleReply);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.sendMessage', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Performs the normal message sender checks
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.checkMessage = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We get some informations
|
||||||
|
var mPath = '#inbox ';
|
||||||
|
var to = $(mPath + '.inbox-new-to-input').val();
|
||||||
|
var body = $(mPath + '.inbox-new-textarea').val();
|
||||||
|
var subject = $(mPath + '.inbox-new-subject-input').val();
|
||||||
|
|
||||||
|
if(to && body && subject) {
|
||||||
|
// New array of XID
|
||||||
|
var xid = new Array(to);
|
||||||
|
|
||||||
|
// More than one XID
|
||||||
|
if(to.indexOf(',') != -1) {
|
||||||
|
xid = to.split(',');
|
||||||
|
}
|
||||||
|
|
||||||
|
for(var i in xid) {
|
||||||
|
var current = xid[i];
|
||||||
|
|
||||||
|
// No current value?
|
||||||
|
if(!current || current.match(/^(\s+)$/))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// Edit the XID if needed
|
||||||
|
current = current.replace(/ /g, '');
|
||||||
|
current = Common.generateXID(current, 'chat');
|
||||||
|
|
||||||
|
// We send the message
|
||||||
|
self.sendMessage(current, subject, body);
|
||||||
|
|
||||||
|
// We clean the inputs
|
||||||
|
self.cleanNewMessage();
|
||||||
|
|
||||||
|
Console.info('Inbox message sent: ' + current);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Close the inbox
|
||||||
|
self.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
else {
|
||||||
|
$(mPath + 'input[type="text"], ' + mPath + 'textarea').each(function() {
|
||||||
|
var current = this;
|
||||||
|
|
||||||
|
if(!$(current).val()) {
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
$(current).addClass('please-complete').focus();
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
$(current).removeClass('please-complete');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.checkMessage', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows the inbox messages
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.showMessage = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Init
|
||||||
|
var mPath = '#inbox .';
|
||||||
|
|
||||||
|
// We switch the divs
|
||||||
|
$(mPath + 'inbox-new').hide();
|
||||||
|
$(mPath + 'inbox-results').show();
|
||||||
|
|
||||||
|
// We show a new link in the menu
|
||||||
|
$(mPath + 'a-show-messages').hide();
|
||||||
|
$(mPath + 'a-delete-messages').show();
|
||||||
|
$(mPath + 'a-new-message').show();
|
||||||
|
|
||||||
|
// We reset some stuffs
|
||||||
|
self.cleanNewMessage();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.showMessage', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Displays a normal message
|
||||||
|
* @public
|
||||||
|
* @param {string} from
|
||||||
|
* @param {string} subject
|
||||||
|
* @param {string} content
|
||||||
|
* @param {string} status
|
||||||
|
* @param {string} id
|
||||||
|
* @param {string} date
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.displayMessage = function(from, subject, content, status, id, date) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Generate some paths
|
||||||
|
var inbox = '#inbox .';
|
||||||
|
var one_message = inbox + 'one-message.' + id;
|
||||||
|
|
||||||
|
// Message yet displayed!
|
||||||
|
if(Common.exists(one_message)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the nearest element
|
||||||
|
var stamp = DateUtils.extractStamp(Date.jab2date(date));
|
||||||
|
var nearest = Search.sortElementByStamp(stamp, '#inbox .one-message');
|
||||||
|
|
||||||
|
// Get the buddy name
|
||||||
|
var name = Name.getBuddy(from).htmlEnc();
|
||||||
|
|
||||||
|
// We generate the html code
|
||||||
|
var nContent = '<div class="one-message message-' + status + ' ' + id + ' ' + hex_md5(from) + '" data-stamp="' + stamp + '">' +
|
||||||
|
'<div class="message-head">' +
|
||||||
|
'<div class="avatar-container">' +
|
||||||
|
'<img class="avatar" src="' + './images/others/default-avatar.png' + '" alt="" />' +
|
||||||
|
'</div>' +
|
||||||
|
|
||||||
|
'<div class="message-jid">' + name + '</div>' +
|
||||||
|
'<div class="message-subject">' + subject.htmlEnc() + '</div>' +
|
||||||
|
|
||||||
|
'<div class="message-truncated">' + Utils.truncate(Utils.noLines(content), 90).htmlEnc() + '</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
// Display the message
|
||||||
|
if(nearest === 0) {
|
||||||
|
$(inbox + 'inbox-results .inbox').append(nContent);
|
||||||
|
} else {
|
||||||
|
$('#inbox .one-message[data-stamp="' + nearest + '"]:first').before(nContent);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Click events
|
||||||
|
$(one_message + ' .message-head').click(function() {
|
||||||
|
if(!Common.exists(one_message + ' .message-content'))
|
||||||
|
self.revealMessage(id, from, subject, content, name, date, status);
|
||||||
|
else
|
||||||
|
self.hideMessage(id);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get the user avatar
|
||||||
|
Avatar.get(from, 'cache', 'true', 'forget');
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.displayMessage', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Stores an inbox message
|
||||||
|
* @public
|
||||||
|
* @param {string} from
|
||||||
|
* @param {string} subject
|
||||||
|
* @param {string} content
|
||||||
|
* @param {string} status
|
||||||
|
* @param {string} id
|
||||||
|
* @param {string} date
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.storeMessage = function(from, subject, content, status, id, date) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize the XML data
|
||||||
|
var xml = '<message><id>' + id.htmlEnc().htmlEnc() + '</id><date>' + date.htmlEnc().htmlEnc() + '</date><from>' + from.htmlEnc().htmlEnc() + '</from><subject>' + subject.htmlEnc().htmlEnc() + '</subject><status>' + status.htmlEnc().htmlEnc() + '</status><content>' + content.htmlEnc().htmlEnc() + '</content>';
|
||||||
|
|
||||||
|
// End the XML data
|
||||||
|
xml += '</message>';
|
||||||
|
|
||||||
|
// Store this message!
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'inbox', id, xml);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.storeMessage', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes a given normal message
|
||||||
|
* @public
|
||||||
|
* @param {string} id
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.deleteMessage = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Remove the message from the inbox
|
||||||
|
$('#inbox .one-message.' + id).remove();
|
||||||
|
|
||||||
|
// Remove the message from the database
|
||||||
|
DataStore.removeDB(Connection.desktop_hash, 'inbox', id);
|
||||||
|
|
||||||
|
// Check the unread messages
|
||||||
|
self.checkMessages();
|
||||||
|
|
||||||
|
// Store the new inbox
|
||||||
|
self.store();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.deleteMessage', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes all the inbox messages
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.purge = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Remove all the messages from the database
|
||||||
|
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)'));
|
||||||
|
|
||||||
|
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||||
|
// Get the pointer values
|
||||||
|
var current = DataStore.storageDB.key(i);
|
||||||
|
|
||||||
|
// If the pointer is on a stored message
|
||||||
|
if(current.match(db_regex)) {
|
||||||
|
DataStore.removeDB(Connection.desktop_hash, 'inbox', RegExp.$1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prevent the database lag
|
||||||
|
$(document).oneTime(100, function() {
|
||||||
|
// Store the new inbox
|
||||||
|
self.store();
|
||||||
|
|
||||||
|
// Remove all the messages from the inbox
|
||||||
|
$('#inbox .one-message').remove();
|
||||||
|
|
||||||
|
// Reload the inbox
|
||||||
|
self.load();
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.purge', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if there are new messages to be notified
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.checkMessages = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Selectors
|
||||||
|
var inbox_link = '#top-content a.inbox-hidable';
|
||||||
|
var no_results = '#inbox .inbox-noresults';
|
||||||
|
|
||||||
|
// Marker
|
||||||
|
var has_messages = false;
|
||||||
|
|
||||||
|
// Read the number of unread messages
|
||||||
|
var unread = 0;
|
||||||
|
|
||||||
|
// Read the local inbox database
|
||||||
|
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)'));
|
||||||
|
|
||||||
|
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||||
|
// Database pointer
|
||||||
|
var current = DataStore.storageDB.key(i);
|
||||||
|
|
||||||
|
// Check inbox messages
|
||||||
|
if(current.match(db_regex)) {
|
||||||
|
// Read the current status
|
||||||
|
var status = $(Common.XMLFromString(DataStore.storageDB.getItem(current))).find('status').text();
|
||||||
|
|
||||||
|
// Found an unread message
|
||||||
|
if(status == 'unread') {
|
||||||
|
unread++;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the marker
|
||||||
|
has_messages = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No message?
|
||||||
|
if(!has_messages) {
|
||||||
|
$(no_results).show();
|
||||||
|
} else {
|
||||||
|
$(no_results).hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset notifications
|
||||||
|
$(inbox_link + ' .notify').remove();
|
||||||
|
|
||||||
|
// Any unread message?
|
||||||
|
if(unread) {
|
||||||
|
// Notify the user
|
||||||
|
$(inbox_link).prepend('<div class="notify one-counter" data-counter="' + unread + '">' + unread + '</div>');
|
||||||
|
|
||||||
|
// Update the title
|
||||||
|
Interface.updateTitle();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Anyway, update the title
|
||||||
|
Interface.updateTitle();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.checkMessages', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reveal a normal message content
|
||||||
|
* @public
|
||||||
|
* @param {string} id
|
||||||
|
* @param {string} from
|
||||||
|
* @param {string} subject
|
||||||
|
* @param {string} content
|
||||||
|
* @param {string} name
|
||||||
|
* @param {string} date
|
||||||
|
* @param {string} status
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.revealMessage = function(id, from, subject, content, name, date, status) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Message path
|
||||||
|
var all_message = '#inbox .one-message';
|
||||||
|
var one_message = all_message + '.' + id;
|
||||||
|
var one_content = one_message + ' .message-content';
|
||||||
|
|
||||||
|
// We reset all the other messages
|
||||||
|
$(all_message + ' .message-content').remove();
|
||||||
|
$(all_message).removeClass('message-reading');
|
||||||
|
|
||||||
|
// Message content
|
||||||
|
var html =
|
||||||
|
'<div class="message-content">' +
|
||||||
|
'<div class="message-body">' + Filter.message(content, name, true) + '</div>' +
|
||||||
|
|
||||||
|
'<div class="message-meta">' +
|
||||||
|
'<span class="date">' + DateUtils.parse(date) + '</span>' +
|
||||||
|
|
||||||
|
'<a href="#" class="reply one-button talk-images">' + Common._e("Reply") + '</a>' +
|
||||||
|
'<a href="#" class="remove one-button talk-images">' + Common._e("Delete") + '</a>' +
|
||||||
|
|
||||||
|
'<div class="clear">' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
// Message content
|
||||||
|
html += '</div>';
|
||||||
|
|
||||||
|
$(one_message).append(html).addClass('message-reading');
|
||||||
|
|
||||||
|
// Click events
|
||||||
|
$(one_content + ' a.reply').click(function() {
|
||||||
|
return self.replyMessage(id, from, subject, content);
|
||||||
|
});
|
||||||
|
|
||||||
|
$(one_content + ' a.remove').click(function() {
|
||||||
|
return self.deleteMessage(id);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Unread message
|
||||||
|
if(status == 'unread') {
|
||||||
|
// Update our database
|
||||||
|
var xml = DataStore.getDB(Connection.desktop_hash, 'inbox', id).replace(/<status>unread<\/status>/i,'<status>read</status>');
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'inbox', id, xml);
|
||||||
|
|
||||||
|
// Remove the unread class
|
||||||
|
$(one_message).removeClass('message-unread');
|
||||||
|
|
||||||
|
// Send it to the server!
|
||||||
|
self.store();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check the unread messages
|
||||||
|
self.checkMessages();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.revealMessage', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Hides a normal message content
|
||||||
|
* @public
|
||||||
|
* @param {string} id
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.hideMessage = function(id) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Define the paths
|
||||||
|
var inbox = '#inbox .';
|
||||||
|
var one_message = inbox + 'one-message.' + id;
|
||||||
|
|
||||||
|
// Reset this message
|
||||||
|
$(one_message).removeClass('message-reading');
|
||||||
|
$(one_message + ' .message-content').remove();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.hideMessage', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Replies to a given normal message
|
||||||
|
* @public
|
||||||
|
* @param {type} name
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.replyMessage = function(id, from, subject, body) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We switch to the writing div
|
||||||
|
self.newMessage();
|
||||||
|
|
||||||
|
// Inbox path
|
||||||
|
var inbox = '#inbox .';
|
||||||
|
|
||||||
|
// Generate the body
|
||||||
|
body = '\n' + '____________' + '\n\n' + Utils.truncate(body, 120);
|
||||||
|
|
||||||
|
// We apply the generated values to the form
|
||||||
|
$(inbox + 'inbox-new-to-input').val(from);
|
||||||
|
$(inbox + 'inbox-new-subject-input').val(subject);
|
||||||
|
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
$(inbox + 'inbox-new-textarea').val(body).focus().selectRange(1, 0);
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.replyMessage', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the inbox messages
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.load = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Read the local database
|
||||||
|
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'inbox' + ('_(.+)'));
|
||||||
|
|
||||||
|
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||||
|
// Get the pointer values
|
||||||
|
var current = DataStore.storageDB.key(i);
|
||||||
|
|
||||||
|
// If the pointer is on a stored message
|
||||||
|
if(current.match(db_regex)) {
|
||||||
|
// Get the current value
|
||||||
|
var value = $(Common.XMLFromString(DataStore.storageDB.getItem(current)));
|
||||||
|
|
||||||
|
// Display the current message
|
||||||
|
self.displayMessage(
|
||||||
|
value.find('from').text().revertHtmlEnc(),
|
||||||
|
value.find('subject').text().revertHtmlEnc(),
|
||||||
|
value.find('content').text().revertHtmlEnc(),
|
||||||
|
value.find('status').text().revertHtmlEnc(),
|
||||||
|
value.find('id').text().revertHtmlEnc(),
|
||||||
|
value.find('date').text().revertHtmlEnc()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check new messages
|
||||||
|
self.checkMessages();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.load', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Wait event for file attaching
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.waitAttach = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$('#inbox .wait').show();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.waitAttach', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Success event for file attaching
|
||||||
|
* @public
|
||||||
|
* @param {string} responseXML
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.handleAttach = function(responseXML) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Data selector
|
||||||
|
var dData = $(responseXML).find('jappix');
|
||||||
|
|
||||||
|
// Process the returned data
|
||||||
|
if(dData.find('error').size()) {
|
||||||
|
Board.openThisError(4);
|
||||||
|
|
||||||
|
Console.error('Error while attaching the file', dData.find('error').text());
|
||||||
|
} else {
|
||||||
|
// Get the file values
|
||||||
|
var fName = dData.find('title').text();
|
||||||
|
var fType = dData.find('type').text();
|
||||||
|
var fURL = dData.find('href').text();
|
||||||
|
|
||||||
|
// Hide the attach link, show the unattach one
|
||||||
|
$('#inbox .inbox-new-file input').hide();
|
||||||
|
$('#inbox .inbox-new-file').append('<a class="file ' + Common.encodeQuotes(Utils.fileCategory(Common.explodeThis('/', fType, 1))) + ' talk-images" href="' + Common.encodeQuotes(fURL) + '" target="_blank">' + fName.htmlEnc() + '</a><a href="#" class="remove one-button talk-images">' + Common._e("Remove") + '</a>');
|
||||||
|
|
||||||
|
// Set values to the file link
|
||||||
|
$('#inbox .inbox-new-file a.file').attr('data-attachedtitle', fName)
|
||||||
|
.attr('data-attachedhref', fURL);
|
||||||
|
|
||||||
|
// Click events
|
||||||
|
$('#inbox .inbox-new-file a.remove').click(function() {
|
||||||
|
$('#inbox .inbox-new-file a').remove();
|
||||||
|
$('#inbox .inbox-new-file input').show();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
Console.info('File attached.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the attach bubble
|
||||||
|
$('#inbox .inbox-new-file input[type="file"]').val('');
|
||||||
|
$('#inbox .wait').hide();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.handleAttach', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin launcher
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.instance = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Define the pats
|
||||||
|
var inbox = '#inbox .';
|
||||||
|
|
||||||
|
// Define the buddy search vars
|
||||||
|
var destination = inbox + 'inbox-new-to';
|
||||||
|
var dHovered = destination + ' ul li.hovered:first';
|
||||||
|
|
||||||
|
// Send the message when enter pressend
|
||||||
|
$(inbox + 'inbox-new input').keyup(function(e) {
|
||||||
|
if(e.keyCode == 13) {
|
||||||
|
if(Common.exists(dHovered))
|
||||||
|
Search.addBuddy(destination, $(dHovered).attr('data-xid'));
|
||||||
|
else
|
||||||
|
self.checkMessage();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Buddy search
|
||||||
|
$(inbox + 'inbox-new-to-input').keyup(function(e) {
|
||||||
|
if(e.keyCode != 13) {
|
||||||
|
// New buddy search
|
||||||
|
if((e.keyCode != 40) && (e.keyCode != 38)) {
|
||||||
|
Search.createBuddy(destination);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Navigating with keyboard in the results
|
||||||
|
Search.arrowsBuddy(e, destination);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Buddy search lost focus
|
||||||
|
.blur(function() {
|
||||||
|
if(!$(destination + ' ul').attr('mouse-hover')) {
|
||||||
|
Search.resetBuddy(destination);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
// Buddy search got focus
|
||||||
|
.focus(function() {
|
||||||
|
var value = $(this).val();
|
||||||
|
|
||||||
|
// Add a comma at the end
|
||||||
|
if(value && !value.match(/^(.+)((,)(\s)?)$/)) {
|
||||||
|
$(this).val(value + ', ');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Click events
|
||||||
|
$(inbox + 'a-delete-messages').click(self.purge);
|
||||||
|
$(inbox + 'a-new-message').click(self.newMessage);
|
||||||
|
$(inbox + 'a-show-messages').click(self.showMessage);
|
||||||
|
$(inbox + 'inbox-new-send a').click(self.checkMessage);
|
||||||
|
|
||||||
|
$(inbox + 'bottom .finish').click(function() {
|
||||||
|
return self.close();
|
||||||
|
});
|
||||||
|
|
||||||
|
// File upload
|
||||||
|
var attach_options = {
|
||||||
|
dataType: 'xml',
|
||||||
|
beforeSubmit: self.waitAttach,
|
||||||
|
success: self.handleAttach
|
||||||
|
};
|
||||||
|
|
||||||
|
// Upload form submit event
|
||||||
|
$('#inbox .inbox-new-file').submit(function() {
|
||||||
|
if($('#inbox .wait').is(':hidden') && $('#inbox .inbox-new-file input[type="file"]').val()) {
|
||||||
|
$(this).ajaxSubmit(attach_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Upload input change event
|
||||||
|
$('#inbox .inbox-new-file input[type="file"]').change(function() {
|
||||||
|
if($('#inbox .wait').is(':hidden') && $(this).val()) {
|
||||||
|
$('#inbox .inbox-new-file').ajaxSubmit(attach_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Inbox.instance', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
469
source/app/javascripts/integratebox.js
Normal file
|
@ -0,0 +1,469 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the integratebox JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var IntegrateBox = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Opens the integratebox popup
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.open = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Popup HTML content
|
||||||
|
var html =
|
||||||
|
'<div class="top">' + Common._e("Media viewer") + '</div>' +
|
||||||
|
|
||||||
|
'<div class="content"></div>' +
|
||||||
|
|
||||||
|
'<div class="bottom">' +
|
||||||
|
'<div class="wait wait-medium"></div>' +
|
||||||
|
|
||||||
|
'<a href="#" class="finish close">' + Common._e("Close") + '</a>' +
|
||||||
|
'<a href="#" class="finish next disabled" title="' + Common._e("Next") + '">></a>' +
|
||||||
|
'<a href="#" class="finish previous disabled" title="' + Common._e("Previous") + '"><</a>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
// Create the popup
|
||||||
|
Popup.create('integratebox', html);
|
||||||
|
|
||||||
|
// Associate the events
|
||||||
|
self.instance();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('IntegrateBox.open', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the integratebox popup
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.close = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Destroy the popup
|
||||||
|
Popup.destroy('integratebox');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('IntegrateBox.close', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the integratebox HTML code
|
||||||
|
* @public
|
||||||
|
* @param {string} serv
|
||||||
|
* @param {string} url
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.code = function(serv, url) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
var code = '';
|
||||||
|
|
||||||
|
// Protocol to use
|
||||||
|
var protocol = Utils.isHTTPS() ? 'https' : 'http';
|
||||||
|
|
||||||
|
// Legacy browser
|
||||||
|
var legacy = false;
|
||||||
|
|
||||||
|
if((BrowserDetect.browser == 'Explorer') && (BrowserDetect.version < 9)) {
|
||||||
|
legacy = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Switch to get the good DOM code
|
||||||
|
switch(serv) {
|
||||||
|
case 'youtube':
|
||||||
|
if(legacy) {
|
||||||
|
code = '<object width="640" height="385"><param name="movie" value="http://www.youtube.com/v/' + url + '&autoplay=1"></param><embed src="http://www.youtube.com/v/' + Common.encodeQuotes(url) + '&autoplay=1" type="application/x-shockwave-flash" width="640" height="385"></embed></object>';
|
||||||
|
} else {
|
||||||
|
code = '<object width="640" height="385" data="' + Common.encodeQuotes(protocol) + '://www.youtube.com/embed/' + Common.encodeQuotes(url) + '?autoplay=1" type="text/html"><a href="http://www.youtube.com/watch?v=' + Common.encodeQuotes(url) + '" target="_blank">http://www.youtube.com/watch?v=' + Common.encodeQuotes(url) + '</a></object>';
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'dailymotion':
|
||||||
|
code = '<object width="640" height="385"><param name="movie" value="http://www.dailymotion.com/swf/video/' + url + '&autoplay=1"></param><param name="allowFullScreen" value="false"></param><embed type="application/x-shockwave-flash" src="http://www.dailymotion.com/swf/video/' + Common.encodeQuotes(url) + '&autoplay=1" width="640" height="385" allowfullscreen="true" allowscriptaccess="always"></embed></object>';
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'vimeo':
|
||||||
|
code = '<object width="640" height="385"><param name="allowfullscreen" value="true" /><param name="movie" value="http://vimeo.com/moogaloop.swf?clip_id=' + Common.encodeQuotes(url) + '&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1&autoplay=1" /><embed src="http://vimeo.com/moogaloop.swf?clip_id=' + Common.encodeQuotes(url) + '&server=vimeo.com&show_title=1&show_byline=1&show_portrait=0&color=&fullscreen=1&autoplay=1" type="application/x-shockwave-flash" allowfullscreen="true" allowscriptaccess="always" width="640" height="385"></embed></object>';
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'theora':
|
||||||
|
case 'video':
|
||||||
|
code = '<video width="640" height="385" src="' + Common.encodeQuotes(url) + '" controls autoplay><a href="' + Common.encodeQuotes(url) + '" target="_blank">' + Common.encodeQuotes(url) + '</a></video>';
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'vorbis':
|
||||||
|
case 'audio':
|
||||||
|
code = '<audio src="' + Common.encodeQuotes(url) + '" controls autoplay><a href="' + Common.encodeQuotes(url) + '" target="_blank">' + Common.encodeQuotes(url) + '</a></audio>';
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'image':
|
||||||
|
code = '<a href="' + Common.encodeQuotes(url) + '" target="_blank"><img alt="" src="' + Common.encodeQuotes(url) + '" /></a>';
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return code;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('IntegrateBox.code', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Applies a given integratebox element
|
||||||
|
* @public
|
||||||
|
* @param {string} url
|
||||||
|
* @param {string} service
|
||||||
|
* @param {string} url_list
|
||||||
|
* @param {string} services_list
|
||||||
|
* @param {string} comments_e_list
|
||||||
|
* @param {string} comments_n_list
|
||||||
|
* @param {string} width_style
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.apply = function(url, service, url_list, services_list, comments_e_list, comments_n_list, width_style) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Close the integratebox
|
||||||
|
self.close();
|
||||||
|
|
||||||
|
// Media integration not wanted?
|
||||||
|
if(DataStore.getDB(Connection.desktop_hash, 'options', 'integratemedias') == '0')
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Apply the HTML code
|
||||||
|
var dom_code = self.code(service, url);
|
||||||
|
|
||||||
|
// Any code: apply it!
|
||||||
|
if(dom_code) {
|
||||||
|
// We show the integratebox
|
||||||
|
self.open();
|
||||||
|
|
||||||
|
// We add the code to the DOM
|
||||||
|
$('#integratebox .content').prepend('<div class="one-media">' + dom_code + '</div>');
|
||||||
|
|
||||||
|
// Image waiting icon
|
||||||
|
if(service == 'image') {
|
||||||
|
var waitItem = $('#integratebox .wait');
|
||||||
|
|
||||||
|
// Show it while it is loading
|
||||||
|
waitItem.show();
|
||||||
|
|
||||||
|
// Hide it when it is loaded
|
||||||
|
$('#integratebox img').load(function() {
|
||||||
|
waitItem.hide();
|
||||||
|
|
||||||
|
// Center the image vertically
|
||||||
|
$(this).oneTime(10, function() {
|
||||||
|
$(this).css('margin-top', (($('#integratebox .content').height() - $(this).height()) / 2));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Large style?
|
||||||
|
var comments_id = genID();
|
||||||
|
|
||||||
|
if(width_style == 'large') {
|
||||||
|
// Make the popup large
|
||||||
|
$('#integratebox .popup').addClass('large');
|
||||||
|
|
||||||
|
// Add the right content
|
||||||
|
$('#integratebox .content').after(
|
||||||
|
'<div class="comments" data-id="' + Common.encodeQuotes(comments_id) + '">' +
|
||||||
|
'<div class="comments-content">' +
|
||||||
|
'<div class="one-comment loading"><span class="icon talk-images"></span>' + Common._e("Loading comments...") + '</div>' +
|
||||||
|
'</div>' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Previous and next items?
|
||||||
|
var url_array = Utils.stringToArray(url_list);
|
||||||
|
var services_array = Utils.stringToArray(services_list);
|
||||||
|
var comments_e_array = Utils.stringToArray(comments_e_list);
|
||||||
|
var comments_n_array = Utils.stringToArray(comments_n_list);
|
||||||
|
var index = Utils.indexArrayValue(url_array, url);
|
||||||
|
|
||||||
|
// Any comments?
|
||||||
|
if(Common.exists('#integratebox .comments')) {
|
||||||
|
if(comments_e_array[index] && comments_n_array[index]) {
|
||||||
|
Microblog.getComments(comments_e_array[index], comments_n_array[index], comments_id);
|
||||||
|
} else {
|
||||||
|
$('#integratebox .comments .comments-content').html('<div class="one-comment loading"><span class="icon talk-images"></span>' + Common._e("Comments locked!") + '</div>');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the previous values
|
||||||
|
var previous_url = url_array[index - 1];
|
||||||
|
var previous_services = services_array[index - 1];
|
||||||
|
|
||||||
|
// Get the next values
|
||||||
|
var next_url = url_array[index + 1];
|
||||||
|
var next_services = services_array[index + 1];
|
||||||
|
|
||||||
|
// Enable/disable buttons
|
||||||
|
if(previous_url && previous_services) {
|
||||||
|
$('#integratebox .bottom .finish.previous').removeClass('disabled');
|
||||||
|
} else {
|
||||||
|
$('#integratebox .bottom .finish.previous').addClass('disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
if(next_url && next_services) {
|
||||||
|
$('#integratebox .bottom .finish.next').removeClass('disabled');
|
||||||
|
} else {
|
||||||
|
$('#integratebox .bottom .finish.next').addClass('disabled');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Click events
|
||||||
|
$('#integratebox .bottom .finish.previous, #integratebox .bottom .finish.next').click(function() {
|
||||||
|
// Not acceptable?
|
||||||
|
if($(this).is('.disabled')) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply the event!
|
||||||
|
if($(this).is('.previous')) {
|
||||||
|
self.apply(previous_url, previous_services, url_list, services_list, comments_e_list, comments_n_list, width_style);
|
||||||
|
} else {
|
||||||
|
self.apply(next_url, next_services, url_list, services_list, comments_e_list, comments_n_list, width_style);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
if(width_style == 'large')
|
||||||
|
$('#integratebox .content a:has(img)').click(function() {
|
||||||
|
if(next_url && next_services) {
|
||||||
|
self.apply(next_url, next_services, url_list, services_list, comments_e_list, comments_n_list, width_style);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Nothing: return true to be able to open the URL in a new tab
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('IntegrateBox.apply', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks whether the file ext can use integratebox or not
|
||||||
|
* @public
|
||||||
|
* @param {string} ext
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.can = function(ext) {
|
||||||
|
|
||||||
|
can_use = false;
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Can use?
|
||||||
|
if(ext && ((ext == 'jpg') || (ext == 'jpeg') || (ext == 'png') || (ext == 'gif') || (ext == 'ogg') || (ext == 'oga') || (ext == 'ogv'))) {
|
||||||
|
can_use = true;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('IntegrateBox.can', e);
|
||||||
|
} finally {
|
||||||
|
return can_use;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters a string to apply the integratebox links
|
||||||
|
* @public
|
||||||
|
* @param {string} data
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
self.filter = function(data) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Encapsulates the string into two <div /> elements
|
||||||
|
var xml = $('<div><div>' + data + '</div></div>').contents();
|
||||||
|
|
||||||
|
// Loop the <a /> elements
|
||||||
|
$(xml).find('a').each(function() {
|
||||||
|
// Initialize this element
|
||||||
|
var href = $(this).attr('href');
|
||||||
|
var to, url, service, event;
|
||||||
|
|
||||||
|
// XMPP ID
|
||||||
|
if(href.match(/^xmpp:(.+)/i)) {
|
||||||
|
to = RegExp.$1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// YouTube video box
|
||||||
|
else if(href.match(/(\w{3,5})(:)(\S+)((\.youtube\.com\/watch(\?v|\?\S+v|\#\!v|\#\!\S+v)\=)|(youtu\.be\/))([^& ]+)((&\S)|(&\S)|\s|$)/gim)) {
|
||||||
|
url = RegExp.$8;
|
||||||
|
service = 'youtube';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Dailymotion video box
|
||||||
|
else if(href.match(/(\w{3,5})(:)(\S+)\.dailymotion\.com\/video\/([\w\-]+)((\#[\w\-]+)|\s|$)/gim)) {
|
||||||
|
url = RegExp.$4;
|
||||||
|
service = 'dailymotion';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vimeo video box
|
||||||
|
else if(href.match(/((\w{3,5})(:)(\S+)(vimeo|www\.vimeo)\.com\/([\w\-]+))/gim)) {
|
||||||
|
url = RegExp.$6;
|
||||||
|
service = 'vimeo';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Theora video box
|
||||||
|
else if(href.match(/((\w{3,5})(:)(\S+)(\.)(ogv|ogg))/gim)) {
|
||||||
|
url = RegExp.$1;
|
||||||
|
service = 'theora';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Vorbis audio box
|
||||||
|
else if(href.match(/((\w{3,5})(:)(\S+)(\.oga))/gim)) {
|
||||||
|
url = RegExp.$1;
|
||||||
|
service = 'vorbis';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Image box
|
||||||
|
else if(href.match(/((\w{3,5})(:)(\S+)(\.)(jpg|jpeg|png|gif|tif|bmp))/gim)) {
|
||||||
|
url = RegExp.$1;
|
||||||
|
service = 'image';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Define the good event
|
||||||
|
if(to) {
|
||||||
|
event = 'XMPPLinks.go(\'' + Utils.encodeOnclick(to) + '\')';
|
||||||
|
} else if(url && service) {
|
||||||
|
event = 'IntegrateBox.apply(\'' + Utils.encodeOnclick(url) + '\', \'' + Utils.encodeOnclick(service) + '\')';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any click event to apply?
|
||||||
|
if(event) {
|
||||||
|
// Regenerate the link element (for onclick)
|
||||||
|
var new_a = '<a';
|
||||||
|
var element_a = (this);
|
||||||
|
|
||||||
|
// Attributes
|
||||||
|
$(element_a.attributes).each(function(index) {
|
||||||
|
// Read the current attribute
|
||||||
|
var current_attr = element_a.attributes[index];
|
||||||
|
|
||||||
|
// Apply the current attribute
|
||||||
|
new_a += ' ' + Common.encodeQuotes(current_attr.name) + '="' + Common.encodeQuotes(current_attr.value) + '"';
|
||||||
|
});
|
||||||
|
|
||||||
|
// Add onclick attribute
|
||||||
|
new_a += ' onclick="return ' + event + ';"';
|
||||||
|
|
||||||
|
// Value
|
||||||
|
new_a += '>' + $(this).html() + '</a>';
|
||||||
|
|
||||||
|
// Replace it!
|
||||||
|
$(this).replaceWith(new_a);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Regenerate the HTML code (include string into a div to be readable)
|
||||||
|
var string = $(xml).html();
|
||||||
|
|
||||||
|
return string;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('IntegrateBox.filter', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instance launcher
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.instance = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Click event
|
||||||
|
$('#integratebox .bottom .finish.close').click(self.close);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('IntegrateBox.instance', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin launcher
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.launch = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$(document).keyup(function(e) {
|
||||||
|
// Previous item?
|
||||||
|
if((Common.exists('#integratebox .bottom .finish.previous:not(.disabled)')) && (e.keyCode == 37)) {
|
||||||
|
$('#integratebox .bottom .finish.previous').click();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next item?
|
||||||
|
if((Common.exists('#integratebox .bottom .finish.next:not(.disabled)')) && (e.keyCode == 39)) {
|
||||||
|
$('#integratebox .bottom .finish.next').click();
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('IntegrateBox.launch', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
IntegrateBox.launch();
|
703
source/app/javascripts/interface.js
Normal file
|
@ -0,0 +1,703 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the interface JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var Interface = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/* Variables */
|
||||||
|
self.chat_focus_hash = null;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the title of the document
|
||||||
|
* @public
|
||||||
|
* @param {string} new_title
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.title = function(title_type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Anonymous mode?
|
||||||
|
var head_name = Name.get();
|
||||||
|
|
||||||
|
if(Utils.isAnonymous()) {
|
||||||
|
head_name = ANONYMOUS_ROOM + ' (' + Common._e("anonymous mode") + ')';
|
||||||
|
}
|
||||||
|
|
||||||
|
// We change the title to give essential informations
|
||||||
|
switch(title_type) {
|
||||||
|
case 'home':
|
||||||
|
document.title = SERVICE_NAME + ' • ' + SERVICE_DESC;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'talk':
|
||||||
|
document.title = SERVICE_NAME + ' • ' + head_name;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'new':
|
||||||
|
document.title = '[' + self.pendingEvents() + '] ' + SERVICE_NAME + ' • ' + head_name;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 'wait':
|
||||||
|
document.title = SERVICE_NAME + ' • ' + Common._e("Please wait...");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.title', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a general-wait item
|
||||||
|
* @public
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.showGeneralWait = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Item exists?
|
||||||
|
if(Common.exists('#general-wait'))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Generate the HTML code
|
||||||
|
var html =
|
||||||
|
'<div id="general-wait" class="removable">' +
|
||||||
|
'<div class="general-wait-content wait-big"></div>' +
|
||||||
|
'</div>';
|
||||||
|
|
||||||
|
// Append the HTML code
|
||||||
|
$('body').append(html);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.showGeneralWait', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes the general-wait item
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.removeGeneralWait = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$('#general-wait').remove();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.removeGeneralWait', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a file upload valid form content
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.generateFileShare = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
return '<input type="hidden" name="MAX_FILE_SIZE" value="' + Common.encodeQuotes(JAPPIX_MAX_FILE_SIZE) + '">' +
|
||||||
|
'<input type="hidden" name="user" value="' + Common.encodeQuotes(Common.getXID()) + '" />' +
|
||||||
|
'<input type="hidden" name="location" value="' + Common.encodeQuotes(Utils.generateURL(JAPPIX_LOCATION)) + '" />' +
|
||||||
|
'<input type="hidden" name="id" value="' + (new Date()).getTime() + '" />' +
|
||||||
|
'<input type="file" name="file" required="" />' +
|
||||||
|
'<input type="submit" value="' + Common._e("Send") + '" />';
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.generateFileShare', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Switches to the given chan
|
||||||
|
* @public
|
||||||
|
* @param {string} id
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.switchChan = function(id) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(Common.exists('#' + id)) {
|
||||||
|
// We show the page-engine content
|
||||||
|
$('.page-engine-chan').hide();
|
||||||
|
$('#' + id).show();
|
||||||
|
|
||||||
|
// We edit the tab switcher
|
||||||
|
$('#page-switch .switcher').removeClass('activechan').addClass('chan');
|
||||||
|
$('#page-switch .' + id).addClass('activechan').removeClass('chan');
|
||||||
|
|
||||||
|
// Scroll down to the last message
|
||||||
|
if(id != 'channel') {
|
||||||
|
self.autoScroll(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Manage input focus
|
||||||
|
self.inputFocus();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.switchChan', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the complete chat switcher
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.loadChatSwitch = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Path
|
||||||
|
var more_content = '#page-switch .more-content';
|
||||||
|
|
||||||
|
// Yet displayed?
|
||||||
|
if(Common.exists(more_content))
|
||||||
|
return Bubble.close();
|
||||||
|
|
||||||
|
// Add the bubble
|
||||||
|
Bubble.show(more_content);
|
||||||
|
|
||||||
|
// Append the content
|
||||||
|
$('#page-switch .more').append(
|
||||||
|
'<div class="more-content bubble removable">' +
|
||||||
|
$('#page-switch .chans').html() +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.loadChatSwitch', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Loads the groupchat joiner
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.loadJoinGroupchat = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Path
|
||||||
|
var join_content = '#page-switch .join-content';
|
||||||
|
var join_sel = $('#page-switch .join');
|
||||||
|
|
||||||
|
// Yet displayed?
|
||||||
|
if(Common.exists(join_content))
|
||||||
|
return Bubble.close();
|
||||||
|
|
||||||
|
// Add the bubble
|
||||||
|
Bubble.show(join_content);
|
||||||
|
|
||||||
|
// Append the content
|
||||||
|
join_sel.append(
|
||||||
|
'<div class="join-content bubble removable">' +
|
||||||
|
'<input type="text" class="join-groupchat-xid" required="" placeholder="' + Common._e("Groupchat name") + '" />' +
|
||||||
|
'</div>'
|
||||||
|
);
|
||||||
|
|
||||||
|
var input_sel = join_sel.find('input.join-groupchat-xid');
|
||||||
|
|
||||||
|
input_sel.keyup(function(e) {
|
||||||
|
// Enter: continue
|
||||||
|
if(e.keyCode == 13) {
|
||||||
|
var this_sel = $(this);
|
||||||
|
var xid = $.trim(this_sel.val());
|
||||||
|
|
||||||
|
if(xid) {
|
||||||
|
// Generate a correct XID
|
||||||
|
xid = Common.generateXID(xid, 'groupchat');
|
||||||
|
|
||||||
|
Bubble.close();
|
||||||
|
Chat.checkCreate(xid, 'groupchat');
|
||||||
|
} else {
|
||||||
|
this_sel.addClass('please-complete');
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
input_sel.focus();
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.loadJoinGroupchat', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Puts the selected smiley in the good page-engine input
|
||||||
|
* @public
|
||||||
|
* @param {string} smiley
|
||||||
|
* @param {string} hash
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.insertSmiley = function(smiley, hash) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We define the variables
|
||||||
|
var selector = $('#' + hash + ' .message-area');
|
||||||
|
var oValue = selector.val();
|
||||||
|
|
||||||
|
// Any old value?
|
||||||
|
if(oValue && !oValue.match(/^(.+)(\s)+$/)) {
|
||||||
|
oValue += ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
var nValue = oValue + smiley + ' ';
|
||||||
|
|
||||||
|
// Put the new value and focus on it
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
selector.val(nValue).focus();
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.insertSmiley', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deletes all the associated elements of the chat we want to remove
|
||||||
|
* @public
|
||||||
|
* @param {string} hash
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.deleteThisChat = function(hash) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$('#' + hash + ', #page-switch .' + hash).remove();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.deleteThisChat', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes the given chat
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} hash
|
||||||
|
* @param {string} type
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.quitThisChat = function(xid, hash, type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
if(type == 'groupchat') {
|
||||||
|
// Send our unavailable presence
|
||||||
|
Presence.send(xid + '/' + Name.getMUCNick(hash), 'unavailable');
|
||||||
|
|
||||||
|
// Remove all presence database entries for this groupchat
|
||||||
|
var db_regex = new RegExp(('^' + Connection.desktop_hash + '_') + 'presence' + ('_(.+)'));
|
||||||
|
|
||||||
|
for(var i = 0; i < DataStore.storageDB.length; i++) {
|
||||||
|
// Get the pointer values
|
||||||
|
var current = DataStore.storageDB.key(i);
|
||||||
|
|
||||||
|
if(current.match(db_regex)) {
|
||||||
|
var cXID = RegExp.$1;
|
||||||
|
|
||||||
|
// If the pointer is on a presence from this groupchat
|
||||||
|
if(Common.bareXID(cXID) == xid) {
|
||||||
|
// Generate the hash for the current XID
|
||||||
|
var cHash = hex_md5(cXID);
|
||||||
|
|
||||||
|
// Disable the message textarea
|
||||||
|
$('#' + cHash + ' .message-area').attr('disabled', true);
|
||||||
|
|
||||||
|
// Remove the presence for this XID
|
||||||
|
DataStore.removeDB(Connection.desktop_hash, 'presence-stanza', cXID);
|
||||||
|
DataStore.removeDB(Connection.desktop_hash, 'presence-resources', cXID);
|
||||||
|
Presence.funnel(cXID, cHash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ChatState.send('gone', xid, hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear MAM storage for this chat
|
||||||
|
if(xid in MAM.map_states) {
|
||||||
|
delete MAM.map_states[xid];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the chat ID which is before
|
||||||
|
var previous = $('#' + hash).prev().attr('id');
|
||||||
|
|
||||||
|
// Remove the chat
|
||||||
|
self.deleteThisChat(hash);
|
||||||
|
|
||||||
|
// Reset the switcher
|
||||||
|
if(!Common.exists('#page-switch .switcher.activechan')) {
|
||||||
|
self.switchChan(previous);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Reset the notifications
|
||||||
|
self.chanCleanNotify(hash);
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.quitThisChat', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates the chat logs
|
||||||
|
* @public
|
||||||
|
* @param {string} xid
|
||||||
|
* @param {string} hash
|
||||||
|
* @return {boolean}
|
||||||
|
*/
|
||||||
|
self.generateChatLog = function(xid, hash) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Get the main values
|
||||||
|
var path = '#' + hash + ' .';
|
||||||
|
var content = $(path + 'content').clone().contents();
|
||||||
|
var avatar = $(path + 'top .avatar-container:first').html();
|
||||||
|
var nick = $(path + 'top .bc-name').text();
|
||||||
|
var date = DateUtils.getXMPPTime('local');
|
||||||
|
var type = $('#' + hash).attr('data-type');
|
||||||
|
var direction = $('html').attr('dir') || 'ltr';
|
||||||
|
|
||||||
|
// Filter the content smileys
|
||||||
|
$(content).find('img.emoticon').each(function() {
|
||||||
|
$(this).replaceWith($(this).attr('alt'));
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove the useless attributes
|
||||||
|
$(content).removeAttr('data-type').removeAttr('data-stamp');
|
||||||
|
|
||||||
|
// Remove the content avatars
|
||||||
|
$(content).find('.avatar-container').remove();
|
||||||
|
|
||||||
|
// Remove the content click events
|
||||||
|
$(content).find('a').removeAttr('onclick');
|
||||||
|
|
||||||
|
// Extract the content HTML code
|
||||||
|
content = $(content).parent().html();
|
||||||
|
|
||||||
|
// No avatar?
|
||||||
|
if(!avatar || !avatar.match(/data:/))
|
||||||
|
avatar = 'none';
|
||||||
|
|
||||||
|
// POST the values to the server
|
||||||
|
$.post('./server/generate-chat.php', { 'content': content, 'xid': xid, 'nick': nick, 'avatar': avatar, 'date': date, 'type': type, 'direction': direction }, function(data) {
|
||||||
|
// Handled!
|
||||||
|
$(path + 'tooltip-waitlog').replaceWith('<a class="tooltip-actionlog" href="./server/download-chat.php?id=' + data + '" target="_blank">' + Common._e("Download file!") + '</a>');
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.generateChatLog', e);
|
||||||
|
} finally {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notifies the user from a new incoming message
|
||||||
|
* @public
|
||||||
|
* @param {string} hash
|
||||||
|
* @param {string} type
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.messageNotify = function(hash, type) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Initialize the vars
|
||||||
|
var chat_switch = '#page-switch .';
|
||||||
|
var tested = chat_switch + hash;
|
||||||
|
var active = $(tested).hasClass('activechan');
|
||||||
|
|
||||||
|
// We notify the user if he has not the focus on the chat
|
||||||
|
if(!active || !Common.isFocused() || (self.chat_focus_hash != hash)) {
|
||||||
|
if(!active) {
|
||||||
|
if(type == 'personal')
|
||||||
|
$(tested + ', ' + chat_switch + 'more-button').addClass('chan-newmessage');
|
||||||
|
else if(type == 'unread')
|
||||||
|
$(tested).addClass('chan-unread');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Count the number of pending messages
|
||||||
|
var pending = 1;
|
||||||
|
|
||||||
|
if(Common.exists('#' + hash + '[data-counter]'))
|
||||||
|
pending = parseInt($('#' + hash).attr('data-counter')) + 1;
|
||||||
|
|
||||||
|
$('#' + hash).attr('data-counter', pending);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Update the page title
|
||||||
|
self.updateTitle();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.messageNotify', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the number of pending events
|
||||||
|
* @public
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
self.pendingEvents = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Count the number of notifications
|
||||||
|
var number = 0;
|
||||||
|
|
||||||
|
$('.one-counter[data-counter]').each(function() {
|
||||||
|
number = number + parseInt($(this).attr('data-counter'));
|
||||||
|
});
|
||||||
|
|
||||||
|
return number;
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.pendingEvents', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the page title
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.updateTitle = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Any pending events?
|
||||||
|
if(Common.exists('.one-counter[data-counter]'))
|
||||||
|
self.title('new');
|
||||||
|
else
|
||||||
|
self.title('talk');
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.updateTitle', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cleans the given chat notifications
|
||||||
|
* @public
|
||||||
|
* @param {string} hash
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.chanCleanNotify = function(hash) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// We remove the class that tell the user of a new message
|
||||||
|
var chat_switch = '#page-switch .';
|
||||||
|
$(chat_switch + hash).removeClass('chan-newmessage chan-unread');
|
||||||
|
|
||||||
|
// We reset the global notifications if no more unread messages
|
||||||
|
if(!$(chat_switch + 'chans .chan-newmessage').size())
|
||||||
|
$(chat_switch + 'more-button').removeClass('chan-newmessage');
|
||||||
|
|
||||||
|
// We reset the chat counter
|
||||||
|
$('#' + hash).removeAttr('data-counter');
|
||||||
|
|
||||||
|
// Update the page title
|
||||||
|
self.updateTitle();
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.chanCleanNotify', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scrolls to the last chat message
|
||||||
|
* @public
|
||||||
|
* @param {string} hash
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.autoScroll = function(hash) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Avoid a JS error
|
||||||
|
if(Common.exists('#' + hash)) {
|
||||||
|
var container = document.getElementById('chat-content-' + hash);
|
||||||
|
|
||||||
|
// Scroll down!
|
||||||
|
container.scrollTop = container.scrollHeight;
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.autoScroll', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows all the buddies in the roster
|
||||||
|
* @public
|
||||||
|
* @param {string} from
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.showAllBuddies = function(from) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Put a marker
|
||||||
|
Roster.blist_all = true;
|
||||||
|
|
||||||
|
// We switch the two modes
|
||||||
|
$('.buddy-conf-more-display-unavailable').hide();
|
||||||
|
$('.buddy-conf-more-display-available').show();
|
||||||
|
|
||||||
|
// Security: reset all the groups toggle event
|
||||||
|
$('#roster .group-buddies').show();
|
||||||
|
$('#roster .group span').text('-');
|
||||||
|
|
||||||
|
// We show the disconnected buddies
|
||||||
|
$('.hidden-buddy').show();
|
||||||
|
|
||||||
|
// We show all the groups
|
||||||
|
$('#roster .one-group').show();
|
||||||
|
|
||||||
|
if(Search.search_filtered)
|
||||||
|
Search.funnelFilterBuddy();
|
||||||
|
|
||||||
|
// Store this in the options
|
||||||
|
if((from == 'roster') && Options.loaded()) {
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '1');
|
||||||
|
Options.store();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.showAllBuddies', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Shows only the online buddies in the roster
|
||||||
|
* @public
|
||||||
|
* @param {string} from
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.showOnlineBuddies = function(from) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Remove the marker
|
||||||
|
Roster.blist_all = false;
|
||||||
|
|
||||||
|
// We switch the two modes
|
||||||
|
$('.buddy-conf-more-display-available').hide();
|
||||||
|
$('.buddy-conf-more-display-unavailable').show();
|
||||||
|
|
||||||
|
// Security: reset all the groups toggle event
|
||||||
|
$('#roster .group-buddies').show();
|
||||||
|
$('#roster .group span').text('-');
|
||||||
|
|
||||||
|
// We hide the disconnected buddies
|
||||||
|
$('.hidden-buddy').hide();
|
||||||
|
|
||||||
|
// We check the groups to hide
|
||||||
|
Roster.updateGroups();
|
||||||
|
|
||||||
|
if(Search.search_filtered) {
|
||||||
|
Search.funnelFilterBuddy();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Store this in the options
|
||||||
|
if((from == 'roster') && Options.loaded()) {
|
||||||
|
DataStore.setDB(Connection.desktop_hash, 'options', 'roster-showall', '0');
|
||||||
|
Options.store();
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.showOnlineBuddies', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Focuses on the right input
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.inputFocus = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// No popup shown
|
||||||
|
if(!Common.exists('.popup')) {
|
||||||
|
$(document).oneTime(10, function() {
|
||||||
|
$('.focusable:visible:first').focus();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.inputFocus', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Plugin launcher
|
||||||
|
* @public
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.launch = function() {
|
||||||
|
|
||||||
|
try {
|
||||||
|
$(document).ready(function() {
|
||||||
|
// Focus on the first visible input
|
||||||
|
$(window).focus(self.inputFocus);
|
||||||
|
});
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('Interface.launch', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
||||||
|
|
||||||
|
Interface.launch();
|
354
source/app/javascripts/ios.js
Normal file
|
@ -0,0 +1,354 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
This is the iOS add to home JS script for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Camaran
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Add to Homescreen v2.0.8 ~ Copyright (c) 2013 Matteo Spinelli, http://cubiq.org
|
||||||
|
* Released under MIT license, http://cubiq.org/license
|
||||||
|
*/
|
||||||
|
var addToHome = (function (w) {
|
||||||
|
var nav = w.navigator,
|
||||||
|
isIDevice = 'platform' in nav && (/iphone|ipod|ipad/gi).test(nav.platform),
|
||||||
|
isIPad,
|
||||||
|
isRetina,
|
||||||
|
isSafari,
|
||||||
|
isStandalone,
|
||||||
|
OSVersion,
|
||||||
|
startX = 0,
|
||||||
|
startY = 0,
|
||||||
|
lastVisit = 0,
|
||||||
|
isExpired,
|
||||||
|
isSessionActive,
|
||||||
|
isReturningVisitor,
|
||||||
|
balloon,
|
||||||
|
overrideChecks,
|
||||||
|
|
||||||
|
positionInterval,
|
||||||
|
closeTimeout,
|
||||||
|
|
||||||
|
options = {
|
||||||
|
autostart: true, // Automatically open the balloon
|
||||||
|
returningVisitor: false, // Show the balloon to returning visitors only (setting this to true is highly recommended)
|
||||||
|
animationIn: 'drop', // drop || bubble || fade
|
||||||
|
animationOut: 'fade', // drop || bubble || fade
|
||||||
|
startDelay: 2000, // 2 seconds from page load before the balloon appears
|
||||||
|
lifespan: 15000, // 15 seconds before it is automatically destroyed
|
||||||
|
bottomOffset: 14, // Distance of the balloon from bottom
|
||||||
|
expire: 0, // Minutes to wait before showing the popup again (0 = always displayed)
|
||||||
|
message: '', // Customize your message or force a language ('' = automatic)
|
||||||
|
touchIcon: false, // Display the touch icon
|
||||||
|
arrow: true, // Display the balloon arrow
|
||||||
|
hookOnLoad: true, // Should we hook to onload event? (really advanced usage)
|
||||||
|
closeButton: true, // Let the user close the balloon
|
||||||
|
iterations: 100 // Internal/debug use
|
||||||
|
},
|
||||||
|
|
||||||
|
intl = {
|
||||||
|
ar: '<span dir="rtl">قم بتثبيت هذا التطبيق على <span dir="ltr">%device:</span>انقر<span dir="ltr">%icon</span> ،<strong>ثم اضفه الى الشاشة الرئيسية.</strong></span>',
|
||||||
|
ca_es: 'Per instal·lar aquesta aplicació al vostre %device premeu %icon i llavors <strong>Afegir a pantalla d\'inici</strong>.',
|
||||||
|
cs_cz: 'Pro instalaci aplikace na Váš %device, stiskněte %icon a v nabídce <strong>Přidat na plochu</strong>.',
|
||||||
|
da_dk: 'Tilføj denne side til din %device: tryk på %icon og derefter <strong>Føj til hjemmeskærm</strong>.',
|
||||||
|
de_de: 'Installieren Sie diese App auf Ihrem %device: %icon antippen und dann <strong>Zum Home-Bildschirm</strong>.',
|
||||||
|
el_gr: 'Εγκαταστήσετε αυτήν την Εφαρμογή στήν συσκευή σας %device: %icon μετά πατάτε <strong>Προσθήκη σε Αφετηρία</strong>.',
|
||||||
|
en_us: 'Install this web app on your %device: tap %icon and then <strong>Add to Home Screen</strong>.',
|
||||||
|
es_es: 'Para instalar esta app en su %device, pulse %icon y seleccione <strong>Añadir a pantalla de inicio</strong>.',
|
||||||
|
fi_fi: 'Asenna tämä web-sovellus laitteeseesi %device: paina %icon ja sen jälkeen valitse <strong>Lisää Koti-valikkoon</strong>.',
|
||||||
|
fr_fr: 'Ajoutez cette application sur votre %device en cliquant sur %icon, puis <strong>Ajouter à l\'écran d\'accueil</strong>.',
|
||||||
|
he_il: '<span dir="rtl">התקן אפליקציה זו על ה-%device שלך: הקש %icon ואז <strong>הוסף למסך הבית</strong>.</span>',
|
||||||
|
hr_hr: 'Instaliraj ovu aplikaciju na svoj %device: klikni na %icon i odaberi <strong>Dodaj u početni zaslon</strong>.',
|
||||||
|
hu_hu: 'Telepítse ezt a web-alkalmazást az Ön %device-jára: nyomjon a %icon-ra majd a <strong>Főképernyőhöz adás</strong> gombra.',
|
||||||
|
it_it: 'Installa questa applicazione sul tuo %device: premi su %icon e poi <strong>Aggiungi a Home</strong>.',
|
||||||
|
ja_jp: 'このウェブアプリをあなたの%deviceにインストールするには%iconをタップして<strong>ホーム画面に追加</strong>を選んでください。',
|
||||||
|
ko_kr: '%device에 웹앱을 설치하려면 %icon을 터치 후 "홈화면에 추가"를 선택하세요',
|
||||||
|
nb_no: 'Installer denne appen på din %device: trykk på %icon og deretter <strong>Legg til på Hjem-skjerm</strong>',
|
||||||
|
nl_nl: 'Installeer deze webapp op uw %device: tik %icon en dan <strong>Voeg toe aan beginscherm</strong>.',
|
||||||
|
pl_pl: 'Aby zainstalować tę aplikacje na %device: naciśnij %icon a następnie <strong>Dodaj jako ikonę</strong>.',
|
||||||
|
pt_br: 'Instale este aplicativo em seu %device: aperte %icon e selecione <strong>Adicionar à Tela Inicio</strong>.',
|
||||||
|
pt_pt: 'Para instalar esta aplicação no seu %device, prima o %icon e depois em <strong>Adicionar ao ecrã principal</strong>.',
|
||||||
|
ru_ru: 'Установите это веб-приложение на ваш %device: нажмите %icon, затем <strong>Добавить в «Домой»</strong>.',
|
||||||
|
sv_se: 'Lägg till denna webbapplikation på din %device: tryck på %icon och därefter <strong>Lägg till på hemskärmen</strong>.',
|
||||||
|
th_th: 'ติดตั้งเว็บแอพฯ นี้บน %device ของคุณ: แตะ %icon และ <strong>เพิ่มที่หน้าจอโฮม</strong>',
|
||||||
|
tr_tr: 'Bu uygulamayı %device\'a eklemek için %icon simgesine sonrasında <strong>Ana Ekrana Ekle</strong> düğmesine basın.',
|
||||||
|
uk_ua: 'Встановіть цей веб сайт на Ваш %device: натисніть %icon, а потім <strong>На початковий екран</strong>.',
|
||||||
|
zh_cn: '您可以将此应用程式安装到您的 %device 上。请按 %icon 然后点选<strong>添加至主屏幕</strong>。',
|
||||||
|
zh_tw: '您可以將此應用程式安裝到您的 %device 上。請按 %icon 然後點選<strong>加入主畫面螢幕</strong>。'
|
||||||
|
};
|
||||||
|
|
||||||
|
function init () {
|
||||||
|
// Preliminary check, all further checks are performed on iDevices only
|
||||||
|
if ( !isIDevice ) return;
|
||||||
|
|
||||||
|
var now = Date.now(),
|
||||||
|
i;
|
||||||
|
|
||||||
|
// Merge local with global options
|
||||||
|
if ( w.addToHomeConfig ) {
|
||||||
|
for ( i in w.addToHomeConfig ) {
|
||||||
|
options[i] = w.addToHomeConfig[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !options.autostart ) options.hookOnLoad = false;
|
||||||
|
|
||||||
|
isIPad = (/ipad/gi).test(nav.platform);
|
||||||
|
isRetina = w.devicePixelRatio && w.devicePixelRatio > 1;
|
||||||
|
isSafari = (/Safari/i).test(nav.appVersion) && !(/CriOS/i).test(nav.appVersion);
|
||||||
|
isStandalone = nav.standalone;
|
||||||
|
OSVersion = nav.appVersion.match(/OS (\d+_\d+)/i);
|
||||||
|
OSVersion = OSVersion && OSVersion[1] ? +OSVersion[1].replace('_', '.') : 0;
|
||||||
|
|
||||||
|
lastVisit = +w.localStorage.getItem('addToHome');
|
||||||
|
|
||||||
|
isSessionActive = w.sessionStorage.getItem('addToHomeSession');
|
||||||
|
isReturningVisitor = options.returningVisitor ? lastVisit && lastVisit + 28*24*60*60*1000 > now : true;
|
||||||
|
|
||||||
|
if ( !lastVisit ) lastVisit = now;
|
||||||
|
|
||||||
|
// If it is expired we need to reissue a new balloon
|
||||||
|
isExpired = isReturningVisitor && lastVisit <= now;
|
||||||
|
|
||||||
|
if ( options.hookOnLoad ) w.addEventListener('load', loaded, false);
|
||||||
|
else if ( !options.hookOnLoad && options.autostart ) loaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loaded () {
|
||||||
|
w.removeEventListener('load', loaded, false);
|
||||||
|
|
||||||
|
if ( !isReturningVisitor ) w.localStorage.setItem('addToHome', Date.now());
|
||||||
|
else if ( options.expire && isExpired ) w.localStorage.setItem('addToHome', Date.now() + options.expire * 60000);
|
||||||
|
|
||||||
|
if ( !overrideChecks && ( !isSafari || !isExpired || isSessionActive || isStandalone || !isReturningVisitor ) ) return;
|
||||||
|
|
||||||
|
var touchIcon = '',
|
||||||
|
platform = nav.platform.split(' ')[0],
|
||||||
|
language = nav.language.replace('-', '_');
|
||||||
|
|
||||||
|
balloon = document.createElement('div');
|
||||||
|
balloon.id = 'addToHomeScreen';
|
||||||
|
balloon.style.cssText += 'left:-9999px;-webkit-transition-property:-webkit-transform,opacity;-webkit-transition-duration:0;-webkit-transform:translate3d(0,0,0);position:' + (OSVersion < 5 ? 'absolute' : 'fixed');
|
||||||
|
|
||||||
|
// Localize message
|
||||||
|
if ( options.message in intl ) { // You may force a language despite the user's locale
|
||||||
|
language = options.message;
|
||||||
|
options.message = '';
|
||||||
|
}
|
||||||
|
if ( options.message === '' ) { // We look for a suitable language (defaulted to en_us)
|
||||||
|
options.message = language in intl ? intl[language] : intl['en_us'];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( options.touchIcon ) {
|
||||||
|
touchIcon = isRetina ?
|
||||||
|
document.querySelector('head link[rel^=apple-touch-icon][sizes="114x114"],head link[rel^=apple-touch-icon][sizes="144x144"],head link[rel^=apple-touch-icon]') :
|
||||||
|
document.querySelector('head link[rel^=apple-touch-icon][sizes="57x57"],head link[rel^=apple-touch-icon]');
|
||||||
|
|
||||||
|
if ( touchIcon ) {
|
||||||
|
touchIcon = '<span style="background-image:url(' + touchIcon.href + ')" class="addToHomeTouchIcon"></span>';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
balloon.className = (isIPad ? 'addToHomeIpad' : 'addToHomeIphone') + (touchIcon ? ' addToHomeWide' : '');
|
||||||
|
balloon.innerHTML = touchIcon +
|
||||||
|
options.message.replace('%device', platform).replace('%icon', OSVersion >= 4.2 ? '<span class="addToHomeShare' + (OSVersion >= 7 ? ' addToHomeShareOS7' : '') + '"></span>' : '<span class="addToHomePlus">+</span>') +
|
||||||
|
(options.arrow ? '<span class="addToHomeArrow"></span>' : '') +
|
||||||
|
(options.closeButton ? '<span class="addToHomeClose">\u00D7</span>' : '');
|
||||||
|
|
||||||
|
document.body.appendChild(balloon);
|
||||||
|
|
||||||
|
// Add the close action
|
||||||
|
if ( options.closeButton ) balloon.addEventListener('click', clicked, false);
|
||||||
|
|
||||||
|
if ( !isIPad && OSVersion >= 6 ) window.addEventListener('orientationchange', orientationCheck, false);
|
||||||
|
|
||||||
|
setTimeout(show, options.startDelay);
|
||||||
|
}
|
||||||
|
|
||||||
|
function show () {
|
||||||
|
var duration,
|
||||||
|
iPadXShift = 208;
|
||||||
|
|
||||||
|
// Set the initial position
|
||||||
|
if ( isIPad ) {
|
||||||
|
if ( OSVersion < 5 ) {
|
||||||
|
startY = w.scrollY;
|
||||||
|
startX = w.scrollX;
|
||||||
|
} else if ( OSVersion < 6 ) {
|
||||||
|
iPadXShift = 160;
|
||||||
|
}
|
||||||
|
|
||||||
|
balloon.style.top = startY + options.bottomOffset + 'px';
|
||||||
|
balloon.style.left = startX + iPadXShift - Math.round(balloon.offsetWidth / 2) + 'px';
|
||||||
|
|
||||||
|
switch ( options.animationIn ) {
|
||||||
|
case 'drop':
|
||||||
|
duration = '0.6s';
|
||||||
|
balloon.style.webkitTransform = 'translate3d(0,' + -(w.scrollY + options.bottomOffset + balloon.offsetHeight) + 'px,0)';
|
||||||
|
break;
|
||||||
|
case 'bubble':
|
||||||
|
duration = '0.6s';
|
||||||
|
balloon.style.opacity = '0';
|
||||||
|
balloon.style.webkitTransform = 'translate3d(0,' + (startY + 50) + 'px,0)';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
duration = '1s';
|
||||||
|
balloon.style.opacity = '0';
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
startY = w.innerHeight + w.scrollY;
|
||||||
|
|
||||||
|
if ( OSVersion < 5 ) {
|
||||||
|
startX = Math.round((w.innerWidth - balloon.offsetWidth) / 2) + w.scrollX;
|
||||||
|
balloon.style.left = startX + 'px';
|
||||||
|
balloon.style.top = startY - balloon.offsetHeight - options.bottomOffset + 'px';
|
||||||
|
} else {
|
||||||
|
balloon.style.left = '50%';
|
||||||
|
balloon.style.marginLeft = -Math.round(balloon.offsetWidth / 2) - ( w.orientation%180 && OSVersion >= 6 ? 40 : 0 ) + 'px';
|
||||||
|
balloon.style.bottom = options.bottomOffset + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (options.animationIn) {
|
||||||
|
case 'drop':
|
||||||
|
duration = '1s';
|
||||||
|
balloon.style.webkitTransform = 'translate3d(0,' + -(startY + options.bottomOffset) + 'px,0)';
|
||||||
|
break;
|
||||||
|
case 'bubble':
|
||||||
|
duration = '0.6s';
|
||||||
|
balloon.style.webkitTransform = 'translate3d(0,' + (balloon.offsetHeight + options.bottomOffset + 50) + 'px,0)';
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
duration = '1s';
|
||||||
|
balloon.style.opacity = '0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
balloon.offsetHeight; // repaint trick
|
||||||
|
balloon.style.webkitTransitionDuration = duration;
|
||||||
|
balloon.style.opacity = '1';
|
||||||
|
balloon.style.webkitTransform = 'translate3d(0,0,0)';
|
||||||
|
balloon.addEventListener('webkitTransitionEnd', transitionEnd, false);
|
||||||
|
|
||||||
|
closeTimeout = setTimeout(close, options.lifespan);
|
||||||
|
}
|
||||||
|
|
||||||
|
function manualShow (override) {
|
||||||
|
if ( !isIDevice || balloon ) return;
|
||||||
|
|
||||||
|
overrideChecks = override;
|
||||||
|
loaded();
|
||||||
|
}
|
||||||
|
|
||||||
|
function close () {
|
||||||
|
clearInterval( positionInterval );
|
||||||
|
clearTimeout( closeTimeout );
|
||||||
|
closeTimeout = null;
|
||||||
|
|
||||||
|
// check if the popup is displayed and prevent errors
|
||||||
|
if ( !balloon ) return;
|
||||||
|
|
||||||
|
var posY = 0,
|
||||||
|
posX = 0,
|
||||||
|
opacity = '1',
|
||||||
|
duration = '0';
|
||||||
|
|
||||||
|
if ( options.closeButton ) balloon.removeEventListener('click', clicked, false);
|
||||||
|
if ( !isIPad && OSVersion >= 6 ) window.removeEventListener('orientationchange', orientationCheck, false);
|
||||||
|
|
||||||
|
if ( OSVersion < 5 ) {
|
||||||
|
posY = isIPad ? w.scrollY - startY : w.scrollY + w.innerHeight - startY;
|
||||||
|
posX = isIPad ? w.scrollX - startX : w.scrollX + Math.round((w.innerWidth - balloon.offsetWidth)/2) - startX;
|
||||||
|
}
|
||||||
|
|
||||||
|
balloon.style.webkitTransitionProperty = '-webkit-transform,opacity';
|
||||||
|
|
||||||
|
switch ( options.animationOut ) {
|
||||||
|
case 'drop':
|
||||||
|
if ( isIPad ) {
|
||||||
|
duration = '0.4s';
|
||||||
|
opacity = '0';
|
||||||
|
posY += 50;
|
||||||
|
} else {
|
||||||
|
duration = '0.6s';
|
||||||
|
posY += balloon.offsetHeight + options.bottomOffset + 50;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'bubble':
|
||||||
|
if ( isIPad ) {
|
||||||
|
duration = '0.8s';
|
||||||
|
posY -= balloon.offsetHeight + options.bottomOffset + 50;
|
||||||
|
} else {
|
||||||
|
duration = '0.4s';
|
||||||
|
opacity = '0';
|
||||||
|
posY -= 50;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
duration = '0.8s';
|
||||||
|
opacity = '0';
|
||||||
|
}
|
||||||
|
|
||||||
|
balloon.addEventListener('webkitTransitionEnd', transitionEnd, false);
|
||||||
|
balloon.style.opacity = opacity;
|
||||||
|
balloon.style.webkitTransitionDuration = duration;
|
||||||
|
balloon.style.webkitTransform = 'translate3d(' + posX + 'px,' + posY + 'px,0)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function clicked () {
|
||||||
|
w.sessionStorage.setItem('addToHomeSession', '1');
|
||||||
|
isSessionActive = true;
|
||||||
|
close();
|
||||||
|
}
|
||||||
|
|
||||||
|
function transitionEnd () {
|
||||||
|
balloon.removeEventListener('webkitTransitionEnd', transitionEnd, false);
|
||||||
|
|
||||||
|
balloon.style.webkitTransitionProperty = '-webkit-transform';
|
||||||
|
balloon.style.webkitTransitionDuration = '0.2s';
|
||||||
|
|
||||||
|
// We reached the end!
|
||||||
|
if ( !closeTimeout ) {
|
||||||
|
balloon.parentNode.removeChild(balloon);
|
||||||
|
balloon = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// On iOS 4 we start checking the element position
|
||||||
|
if ( OSVersion < 5 && closeTimeout ) positionInterval = setInterval(setPosition, options.iterations);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPosition () {
|
||||||
|
var matrix = new WebKitCSSMatrix(w.getComputedStyle(balloon, null).webkitTransform),
|
||||||
|
posY = isIPad ? w.scrollY - startY : w.scrollY + w.innerHeight - startY,
|
||||||
|
posX = isIPad ? w.scrollX - startX : w.scrollX + Math.round((w.innerWidth - balloon.offsetWidth) / 2) - startX;
|
||||||
|
|
||||||
|
// Screen didn't move
|
||||||
|
if ( posY == matrix.m42 && posX == matrix.m41 ) return;
|
||||||
|
|
||||||
|
balloon.style.webkitTransform = 'translate3d(' + posX + 'px,' + posY + 'px,0)';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear local and session storages (this is useful primarily in development)
|
||||||
|
function reset () {
|
||||||
|
w.localStorage.removeItem('addToHome');
|
||||||
|
w.sessionStorage.removeItem('addToHomeSession');
|
||||||
|
}
|
||||||
|
|
||||||
|
function orientationCheck () {
|
||||||
|
balloon.style.marginLeft = -Math.round(balloon.offsetWidth / 2) - ( w.orientation%180 && OSVersion >= 6 ? 40 : 0 ) + 'px';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bootstrap!
|
||||||
|
init();
|
||||||
|
|
||||||
|
return {
|
||||||
|
show: manualShow,
|
||||||
|
close: close,
|
||||||
|
reset: reset
|
||||||
|
};
|
||||||
|
})(window);
|
237
source/app/javascripts/iq.js
Normal file
|
@ -0,0 +1,237 @@
|
||||||
|
/*
|
||||||
|
|
||||||
|
Jappix - An open social platform
|
||||||
|
These are the IQ JS scripts for Jappix
|
||||||
|
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
License: AGPL
|
||||||
|
Author: Valérian Saliou
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
// Bundle
|
||||||
|
var IQ = (function () {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Alias of this
|
||||||
|
* @private
|
||||||
|
*/
|
||||||
|
var self = {};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles an incoming IQ packet
|
||||||
|
* @public
|
||||||
|
* @param {object} iq
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
self.handle = function(iq) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Gets the IQ content
|
||||||
|
var iqNode = iq.getNode();
|
||||||
|
var iqFrom = Common.fullXID(Common.getStanzaFrom(iq));
|
||||||
|
var iqID = iq.getID();
|
||||||
|
var iqQueryXMLNS = iq.getQueryXMLNS();
|
||||||
|
var iqQuery = iq.getQuery();
|
||||||
|
var iqType = iq.getType();
|
||||||
|
|
||||||
|
// Handle Jingle packet?
|
||||||
|
JSJaCJingle_route(iq);
|
||||||
|
|
||||||
|
// Build the response
|
||||||
|
var iqResponse = new JSJaCIQ();
|
||||||
|
|
||||||
|
iqResponse.setID(iqID);
|
||||||
|
iqResponse.setTo(iqFrom);
|
||||||
|
iqResponse.setType('result');
|
||||||
|
|
||||||
|
// OOB request
|
||||||
|
if((iqQueryXMLNS == NS_IQOOB) && (iqType == 'set')) {
|
||||||
|
/* REF: http://xmpp.org/extensions/xep-0066.html */
|
||||||
|
|
||||||
|
OOB.handle(iqFrom, iqID, 'iq', iqNode);
|
||||||
|
|
||||||
|
Console.log('Received IQ OOB request: ' + iqFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// OOB reply
|
||||||
|
else if(DataStore.getDB(Connection.desktop_hash, 'send/url', iqID)) {
|
||||||
|
// Get the values
|
||||||
|
var oob_url = DataStore.getDB(Connection.desktop_hash, 'send/url', iqID);
|
||||||
|
var oob_desc = DataStore.getDB(Connection.desktop_hash, 'send/desc', iqID);
|
||||||
|
var notif_id = hex_md5(oob_url + oob_desc + iqType + iqFrom + iqID);
|
||||||
|
|
||||||
|
if($(iqNode).find('error').size()) {
|
||||||
|
// Error?
|
||||||
|
if($(iqNode).find('error not-acceptable').size()) {
|
||||||
|
// Rejected?
|
||||||
|
Notification.create('send_reject', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||||
|
} else {
|
||||||
|
// Failed?
|
||||||
|
Notification.create('send_fail', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the file
|
||||||
|
$.get(oob_url + '&action=remove');
|
||||||
|
} else if(iqType == 'result') {
|
||||||
|
// Success?
|
||||||
|
Notification.create('send_accept', iqFrom, [iqFrom, oob_url, 'iq', iqID, iqNode], oob_desc, notif_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Software version query
|
||||||
|
else if((iqQueryXMLNS == NS_VERSION) && (iqType == 'get')) {
|
||||||
|
/* REF: http://xmpp.org/extensions/xep-0092.html */
|
||||||
|
|
||||||
|
iqQuery = iqResponse.setQuery(NS_VERSION);
|
||||||
|
|
||||||
|
iqQuery.appendChild(iqResponse.buildNode('name', {'xmlns': NS_VERSION}, 'Jappix'));
|
||||||
|
iqQuery.appendChild(iqResponse.buildNode('version', {'xmlns': NS_VERSION}, JAPPIX_VERSION));
|
||||||
|
iqQuery.appendChild(iqResponse.buildNode('os', {'xmlns': NS_VERSION}, BrowserDetect.OS));
|
||||||
|
|
||||||
|
con.send(iqResponse);
|
||||||
|
|
||||||
|
Console.log('Received software version query: ' + iqFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Last activity query
|
||||||
|
else if((iqQueryXMLNS == NS_LAST) && (iqType == 'get')) {
|
||||||
|
/* REF: http://xmpp.org/extensions/xep-0012.html */
|
||||||
|
|
||||||
|
iqQuery = iqResponse.setQuery(NS_LAST);
|
||||||
|
iqQuery.setAttribute('seconds', DateUtils.getLastActivity());
|
||||||
|
|
||||||
|
con.send(iqResponse);
|
||||||
|
|
||||||
|
Console.log('Received last activity query: ' + iqFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Privacy lists push
|
||||||
|
else if((iqQueryXMLNS == NS_PRIVACY) && (iqType == 'set')) {
|
||||||
|
// REF : http://xmpp.org/extensions/xep-0016.html
|
||||||
|
|
||||||
|
// Roster push
|
||||||
|
con.send(iqResponse);
|
||||||
|
|
||||||
|
// Get the lists
|
||||||
|
$(iqQuery).find('list').each(function() {
|
||||||
|
Privacy.get($(this).attr('name'));
|
||||||
|
});
|
||||||
|
|
||||||
|
Console.log('Received privacy lists push: ' + iqFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roster push
|
||||||
|
else if((iqQueryXMLNS == NS_ROSTER) && (iqType == 'set')) {
|
||||||
|
// REF : http://xmpp.org/extensions/xep-0092.html
|
||||||
|
|
||||||
|
// Roster push
|
||||||
|
con.send(iqResponse);
|
||||||
|
|
||||||
|
// Get the values
|
||||||
|
$(iqQuery).find('item').each(function() {
|
||||||
|
Roster.parse($(this), 'presence');
|
||||||
|
});
|
||||||
|
|
||||||
|
Console.log('Received roster push: ' + iqFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Roster Item Exchange query
|
||||||
|
else if($(iqNode).find('x[xmlns="' + NS_ROSTERX + '"]').size()) {
|
||||||
|
// Open a new notification
|
||||||
|
Notification.create('rosterx', iqFrom, [iqNode], '');
|
||||||
|
|
||||||
|
Console.log('Roster Item Exchange from: ' + iqFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Disco info query
|
||||||
|
else if((iqQueryXMLNS == NS_DISCO_INFO) && (iqType == 'get')) {
|
||||||
|
/* REF: http://xmpp.org/extensions/xep-0030.html */
|
||||||
|
|
||||||
|
iqQuery = iqResponse.setQuery(NS_DISCO_INFO);
|
||||||
|
|
||||||
|
// We set the name of the client
|
||||||
|
iqQuery.appendChild(iqResponse.buildNode('identity', {
|
||||||
|
'category': 'client',
|
||||||
|
'type': 'web',
|
||||||
|
'name': 'Jappix',
|
||||||
|
'xmlns': NS_DISCO_INFO
|
||||||
|
}));
|
||||||
|
|
||||||
|
// We set all the supported features
|
||||||
|
var disco_infos = Caps.myDiscoInfos();
|
||||||
|
|
||||||
|
$.each(disco_infos, function(i, disco_info) {
|
||||||
|
iqQuery.appendChild(iqResponse.buildNode('feature', {'var': disco_info, 'xmlns': NS_DISCO_INFO}));
|
||||||
|
});
|
||||||
|
|
||||||
|
con.send(iqResponse);
|
||||||
|
|
||||||
|
Console.log('Received disco#infos query: ' + iqFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// User time query
|
||||||
|
else if($(iqNode).find('time').size() && (iqType == 'get')) {
|
||||||
|
/* REF: http://xmpp.org/extensions/xep-0202.html */
|
||||||
|
|
||||||
|
var iqTime = iqResponse.appendNode('time', {'xmlns': NS_URN_TIME});
|
||||||
|
iqTime.appendChild(iqResponse.buildNode('tzo', {'xmlns': NS_URN_TIME}, DateUtils.getTZO()));
|
||||||
|
iqTime.appendChild(iqResponse.buildNode('utc', {'xmlns': NS_URN_TIME}, DateUtils.getXMPPTime('utc')));
|
||||||
|
|
||||||
|
con.send(iqResponse);
|
||||||
|
|
||||||
|
Console.log('Received local time query: ' + iqFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ping
|
||||||
|
else if($(iqNode).find('ping').size() && (iqType == 'get')) {
|
||||||
|
/* REF: http://xmpp.org/extensions/xep-0199.html */
|
||||||
|
|
||||||
|
con.send(iqResponse);
|
||||||
|
|
||||||
|
Console.log('Received a ping: ' + iqFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jingle
|
||||||
|
else if($(iqNode).find('jingle').size()) {
|
||||||
|
/* REF: http://xmpp.org/extensions/xep-0166.html */
|
||||||
|
|
||||||
|
// Handled via JSJaCJingle_route() (see above)
|
||||||
|
|
||||||
|
Console.log('Received a Jingle packet: ' + iqFrom);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Not implemented
|
||||||
|
else if(!$(iqNode).find('error').size() && ((iqType == 'get') || (iqType == 'set'))) {
|
||||||
|
// Change IQ type
|
||||||
|
iqResponse.setType('error');
|
||||||
|
|
||||||
|
// Append stanza content
|
||||||
|
for(var c = 0; c < iqNode.childNodes.length; c++) {
|
||||||
|
iqResponse.getNode().appendChild(iqNode.childNodes.item(c).cloneNode(true));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Append error content
|
||||||
|
var iqError = iqResponse.appendNode('error', {'xmlns': NS_CLIENT, 'code': '501', 'type': 'cancel'});
|
||||||
|
iqError.appendChild(iqResponse.buildNode('feature-not-implemented', {'xmlns': NS_STANZAS}));
|
||||||
|
iqError.appendChild(iqResponse.buildNode('text', {'xmlns': NS_STANZAS}, Common._e("The feature requested is not implemented by the recipient or server and therefore cannot be processed.")));
|
||||||
|
|
||||||
|
con.send(iqResponse);
|
||||||
|
|
||||||
|
Console.log('Received an unsupported IQ query from: ' + iqFrom);
|
||||||
|
}
|
||||||
|
} catch(e) {
|
||||||
|
Console.error('IQ.handle', e);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return class scope
|
||||||
|
*/
|
||||||
|
return self;
|
||||||
|
|
||||||
|
})();
|
1638
source/app/javascripts/jingle.js
Normal file
1278
source/app/javascripts/jquery.form.js
Normal file
10337
source/app/javascripts/jquery.js
vendored
Normal file
201
source/app/javascripts/jquery.json.js
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
// License: MIT
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jQuery JSON plugin 2.4.0
|
||||||
|
*
|
||||||
|
* @author Brantley Harris, 2009-2011
|
||||||
|
* @author Timo Tijhof, 2011-2012
|
||||||
|
* @source This plugin is heavily influenced by MochiKit's serializeJSON, which is
|
||||||
|
* copyrighted 2005 by Bob Ippolito.
|
||||||
|
* @source Brantley Harris wrote this plugin. It is based somewhat on the JSON.org
|
||||||
|
* website's http://www.json.org/json2.js, which proclaims:
|
||||||
|
* "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that
|
||||||
|
* I uphold.
|
||||||
|
* @license MIT License <http://www.opensource.org/licenses/mit-license.php>
|
||||||
|
*/
|
||||||
|
(function ($) {
|
||||||
|
'use strict';
|
||||||
|
|
||||||
|
var escape = /["\\\x00-\x1f\x7f-\x9f]/g,
|
||||||
|
meta = {
|
||||||
|
'\b': '\\b',
|
||||||
|
'\t': '\\t',
|
||||||
|
'\n': '\\n',
|
||||||
|
'\f': '\\f',
|
||||||
|
'\r': '\\r',
|
||||||
|
'"' : '\\"',
|
||||||
|
'\\': '\\\\'
|
||||||
|
},
|
||||||
|
hasOwn = Object.prototype.hasOwnProperty;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jQuery.toJSON
|
||||||
|
* Converts the given argument into a JSON representation.
|
||||||
|
*
|
||||||
|
* @param o {Mixed} The json-serializable *thing* to be converted
|
||||||
|
*
|
||||||
|
* If an object has a toJSON prototype, that will be used to get the representation.
|
||||||
|
* Non-integer/string keys are skipped in the object, as are keys that point to a
|
||||||
|
* function.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$.toJSON = typeof JSON === 'object' && JSON.stringify ? JSON.stringify : function (o) {
|
||||||
|
if (o === null) {
|
||||||
|
return 'null';
|
||||||
|
}
|
||||||
|
|
||||||
|
var pairs, k, name, val,
|
||||||
|
type = $.type(o);
|
||||||
|
|
||||||
|
if (type === 'undefined') {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Also covers instantiated Number and Boolean objects,
|
||||||
|
// which are typeof 'object' but thanks to $.type, we
|
||||||
|
// catch them here. I don't know whether it is right
|
||||||
|
// or wrong that instantiated primitives are not
|
||||||
|
// exported to JSON as an {"object":..}.
|
||||||
|
// We choose this path because that's what the browsers did.
|
||||||
|
if (type === 'number' || type === 'boolean') {
|
||||||
|
return String(o);
|
||||||
|
}
|
||||||
|
if (type === 'string') {
|
||||||
|
return $.quoteString(o);
|
||||||
|
}
|
||||||
|
if (typeof o.toJSON === 'function') {
|
||||||
|
return $.toJSON(o.toJSON());
|
||||||
|
}
|
||||||
|
if (type === 'date') {
|
||||||
|
var month = o.getUTCMonth() + 1,
|
||||||
|
day = o.getUTCDate(),
|
||||||
|
year = o.getUTCFullYear(),
|
||||||
|
hours = o.getUTCHours(),
|
||||||
|
minutes = o.getUTCMinutes(),
|
||||||
|
seconds = o.getUTCSeconds(),
|
||||||
|
milli = o.getUTCMilliseconds();
|
||||||
|
|
||||||
|
if (month < 10) {
|
||||||
|
month = '0' + month;
|
||||||
|
}
|
||||||
|
if (day < 10) {
|
||||||
|
day = '0' + day;
|
||||||
|
}
|
||||||
|
if (hours < 10) {
|
||||||
|
hours = '0' + hours;
|
||||||
|
}
|
||||||
|
if (minutes < 10) {
|
||||||
|
minutes = '0' + minutes;
|
||||||
|
}
|
||||||
|
if (seconds < 10) {
|
||||||
|
seconds = '0' + seconds;
|
||||||
|
}
|
||||||
|
if (milli < 100) {
|
||||||
|
milli = '0' + milli;
|
||||||
|
}
|
||||||
|
if (milli < 10) {
|
||||||
|
milli = '0' + milli;
|
||||||
|
}
|
||||||
|
return '"' + year + '-' + month + '-' + day + 'T' +
|
||||||
|
hours + ':' + minutes + ':' + seconds +
|
||||||
|
'.' + milli + 'Z"';
|
||||||
|
}
|
||||||
|
|
||||||
|
pairs = [];
|
||||||
|
|
||||||
|
if ($.isArray(o)) {
|
||||||
|
for (k = 0; k < o.length; k++) {
|
||||||
|
pairs.push($.toJSON(o[k]) || 'null');
|
||||||
|
}
|
||||||
|
return '[' + pairs.join(',') + ']';
|
||||||
|
}
|
||||||
|
|
||||||
|
// Any other object (plain object, RegExp, ..)
|
||||||
|
// Need to do typeof instead of $.type, because we also
|
||||||
|
// want to catch non-plain objects.
|
||||||
|
if (typeof o === 'object') {
|
||||||
|
for (k in o) {
|
||||||
|
// Only include own properties,
|
||||||
|
// Filter out inherited prototypes
|
||||||
|
if (hasOwn.call(o, k)) {
|
||||||
|
// Keys must be numerical or string. Skip others
|
||||||
|
type = typeof k;
|
||||||
|
if (type === 'number') {
|
||||||
|
name = '"' + k + '"';
|
||||||
|
} else if (type === 'string') {
|
||||||
|
name = $.quoteString(k);
|
||||||
|
} else {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
type = typeof o[k];
|
||||||
|
|
||||||
|
// Invalid values like these return undefined
|
||||||
|
// from toJSON, however those object members
|
||||||
|
// shouldn't be included in the JSON string at all.
|
||||||
|
if (type !== 'function' && type !== 'undefined') {
|
||||||
|
val = $.toJSON(o[k]);
|
||||||
|
pairs.push(name + ':' + val);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return '{' + pairs.join(',') + '}';
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jQuery.evalJSON
|
||||||
|
* Evaluates a given json string.
|
||||||
|
*
|
||||||
|
* @param str {String}
|
||||||
|
*/
|
||||||
|
$.evalJSON = typeof JSON === 'object' && JSON.parse ? JSON.parse : function (str) {
|
||||||
|
/*jshint evil: true */
|
||||||
|
return eval('(' + str + ')');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jQuery.secureEvalJSON
|
||||||
|
* Evals JSON in a way that is *more* secure.
|
||||||
|
*
|
||||||
|
* @param str {String}
|
||||||
|
*/
|
||||||
|
$.secureEvalJSON = typeof JSON === 'object' && JSON.parse ? JSON.parse : function (str) {
|
||||||
|
var filtered =
|
||||||
|
str
|
||||||
|
.replace(/\\["\\\/bfnrtu]/g, '@')
|
||||||
|
.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
|
||||||
|
.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
|
||||||
|
|
||||||
|
if (/^[\],:{}\s]*$/.test(filtered)) {
|
||||||
|
/*jshint evil: true */
|
||||||
|
return eval('(' + str + ')');
|
||||||
|
}
|
||||||
|
throw new SyntaxError('Error parsing JSON, source is not valid.');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* jQuery.quoteString
|
||||||
|
* Returns a string-repr of a string, escaping quotes intelligently.
|
||||||
|
* Mostly a support function for toJSON.
|
||||||
|
* Examples:
|
||||||
|
* >>> jQuery.quoteString('apple')
|
||||||
|
* "apple"
|
||||||
|
*
|
||||||
|
* >>> jQuery.quoteString('"Where are we going?", she asked.')
|
||||||
|
* "\"Where are we going?\", she asked."
|
||||||
|
*/
|
||||||
|
$.quoteString = function (str) {
|
||||||
|
if (str.match(escape)) {
|
||||||
|
return '"' + str.replace(escape, function (a) {
|
||||||
|
var c = meta[a];
|
||||||
|
if (typeof c === 'string') {
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
c = a.charCodeAt();
|
||||||
|
return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
|
||||||
|
}) + '"';
|
||||||
|
}
|
||||||
|
return '"' + str + '"';
|
||||||
|
};
|
||||||
|
|
||||||
|
}(jQuery));
|
157
source/app/javascripts/jquery.placeholder.js
Normal file
|
@ -0,0 +1,157 @@
|
||||||
|
/*! http://mths.be/placeholder v2.0.7 by @mathias */
|
||||||
|
;(function(window, document, $) {
|
||||||
|
|
||||||
|
var isInputSupported = 'placeholder' in document.createElement('input'),
|
||||||
|
isTextareaSupported = 'placeholder' in document.createElement('textarea'),
|
||||||
|
prototype = $.fn,
|
||||||
|
valHooks = $.valHooks,
|
||||||
|
hooks,
|
||||||
|
placeholder;
|
||||||
|
|
||||||
|
if (isInputSupported && isTextareaSupported) {
|
||||||
|
|
||||||
|
placeholder = prototype.placeholder = function() {
|
||||||
|
return this;
|
||||||
|
};
|
||||||
|
|
||||||
|
placeholder.input = placeholder.textarea = true;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
placeholder = prototype.placeholder = function() {
|
||||||
|
var $this = this;
|
||||||
|
$this
|
||||||
|
.filter((isInputSupported ? 'textarea' : ':input') + '[placeholder]')
|
||||||
|
.not('.placeholder')
|
||||||
|
.bind({
|
||||||
|
'focus.placeholder': clearPlaceholder,
|
||||||
|
'blur.placeholder': setPlaceholder
|
||||||
|
})
|
||||||
|
.data('placeholder-enabled', true)
|
||||||
|
.trigger('blur.placeholder');
|
||||||
|
return $this;
|
||||||
|
};
|
||||||
|
|
||||||
|
placeholder.input = isInputSupported;
|
||||||
|
placeholder.textarea = isTextareaSupported;
|
||||||
|
|
||||||
|
hooks = {
|
||||||
|
'get': function(element) {
|
||||||
|
var $element = $(element);
|
||||||
|
return $element.data('placeholder-enabled') && $element.hasClass('placeholder') ? '' : element.value;
|
||||||
|
},
|
||||||
|
'set': function(element, value) {
|
||||||
|
var $element = $(element);
|
||||||
|
if (!$element.data('placeholder-enabled')) {
|
||||||
|
return element.value = value;
|
||||||
|
}
|
||||||
|
if (value == '') {
|
||||||
|
element.value = value;
|
||||||
|
// Issue #56: Setting the placeholder causes problems if the element continues to have focus.
|
||||||
|
if (element != document.activeElement) {
|
||||||
|
// We can't use `triggerHandler` here because of dummy text/password inputs :(
|
||||||
|
setPlaceholder.call(element);
|
||||||
|
}
|
||||||
|
} else if ($element.hasClass('placeholder')) {
|
||||||
|
clearPlaceholder.call(element, true, value) || (element.value = value);
|
||||||
|
} else {
|
||||||
|
element.value = value;
|
||||||
|
}
|
||||||
|
// `set` can not return `undefined`; see http://jsapi.info/jquery/1.7.1/val#L2363
|
||||||
|
return $element;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
isInputSupported || (valHooks.input = hooks);
|
||||||
|
isTextareaSupported || (valHooks.textarea = hooks);
|
||||||
|
|
||||||
|
$(function() {
|
||||||
|
// Look for forms
|
||||||
|
$(document).delegate('form', 'submit.placeholder', function() {
|
||||||
|
// Clear the placeholder values so they don't get submitted
|
||||||
|
var $inputs = $('.placeholder', this).each(clearPlaceholder);
|
||||||
|
setTimeout(function() {
|
||||||
|
$inputs.each(setPlaceholder);
|
||||||
|
}, 10);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Clear placeholder values upon page reload
|
||||||
|
$(window).bind('beforeunload.placeholder', function() {
|
||||||
|
$('.placeholder').each(function() {
|
||||||
|
this.value = '';
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
function args(elem) {
|
||||||
|
// Return an object of element attributes
|
||||||
|
var newAttrs = {},
|
||||||
|
rinlinejQuery = /^jQuery\d+$/;
|
||||||
|
$.each(elem.attributes, function(i, attr) {
|
||||||
|
if (attr.specified && !rinlinejQuery.test(attr.name)) {
|
||||||
|
newAttrs[attr.name] = attr.value;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return newAttrs;
|
||||||
|
}
|
||||||
|
|
||||||
|
function clearPlaceholder(event, value) {
|
||||||
|
var input = this,
|
||||||
|
$input = $(input);
|
||||||
|
if (input.value == $input.attr('placeholder') && $input.hasClass('placeholder')) {
|
||||||
|
if ($input.data('placeholder-password')) {
|
||||||
|
$input = $input.hide().next().show().attr('id', $input.removeAttr('id').data('placeholder-id'));
|
||||||
|
// If `clearPlaceholder` was called from `$.valHooks.input.set`
|
||||||
|
if (event === true) {
|
||||||
|
return $input[0].value = value;
|
||||||
|
}
|
||||||
|
$input.focus();
|
||||||
|
} else {
|
||||||
|
input.value = '';
|
||||||
|
$input.removeClass('placeholder');
|
||||||
|
input == document.activeElement && input.select();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setPlaceholder() {
|
||||||
|
var $replacement,
|
||||||
|
input = this,
|
||||||
|
$input = $(input),
|
||||||
|
$origInput = $input,
|
||||||
|
id = this.id;
|
||||||
|
if (input.value == '') {
|
||||||
|
if (input.type == 'password') {
|
||||||
|
if (!$input.data('placeholder-textinput')) {
|
||||||
|
try {
|
||||||
|
$replacement = $input.clone().attr({ 'type': 'text' });
|
||||||
|
} catch(e) {
|
||||||
|
$replacement = $('<input>').attr($.extend(args(this), { 'type': 'text' }));
|
||||||
|
}
|
||||||
|
$replacement
|
||||||
|
.removeAttr('name')
|
||||||
|
.data({
|
||||||
|
'placeholder-password': true,
|
||||||
|
'placeholder-id': id
|
||||||
|
})
|
||||||
|
.bind('focus.placeholder', clearPlaceholder);
|
||||||
|
$input
|
||||||
|
.data({
|
||||||
|
'placeholder-textinput': $replacement,
|
||||||
|
'placeholder-id': id
|
||||||
|
})
|
||||||
|
.before($replacement);
|
||||||
|
}
|
||||||
|
$input = $input.removeAttr('id').hide().prev().attr('id', id).show();
|
||||||
|
// Note: `$input[0] != input` now!
|
||||||
|
}
|
||||||
|
$input.addClass('placeholder');
|
||||||
|
$input[0].value = $input.attr('placeholder');
|
||||||
|
} else {
|
||||||
|
$input.removeClass('placeholder');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}(this, document, jQuery));
|