Add files via upload
parent
e19debbced
commit
ae0c6b3e1b
|
@ -0,0 +1,160 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Debug entry point</title>
|
||||
<meta charset='utf-8'>
|
||||
<link rel="shortcut icon" href="system/settings/img/576/ico_settings_blue.png"/>
|
||||
<!--<link rel="stylesheet" href="http://yui.yahooapis.com/pure/0.2.1/pure-min.css">-->
|
||||
|
||||
<style type="text/css">
|
||||
* { padding:0; margin:0; font-family:Verdana,sans-serif; }
|
||||
|
||||
html, body { height: 100%; background:#000; color:#fff; font-size:20px }
|
||||
|
||||
/* table cell spacing/padding reset */
|
||||
table { border:0; border-collapse:collapse }
|
||||
table td { padding:0 }
|
||||
|
||||
/* meta-classes */
|
||||
.maxh { height:100% }
|
||||
.maxw { width:100% }
|
||||
a { text-decoration:none }
|
||||
|
||||
.header { height:20px; background-color:#222; border-bottom:1px solid #333; padding:10px }
|
||||
.footer { height:5px; background-color:#111; border-top:1px solid #333; }
|
||||
|
||||
.list { margin: 0 auto; cursor:default; border:2px solid #333; }
|
||||
.list .text, .list .link { padding:5px 15px; border:1px solid #222; }
|
||||
.list .link { width:80px; text-align:center }
|
||||
.list .text { text-align:left }
|
||||
.list .text { padding-left:100px }
|
||||
|
||||
.list .text.home { background:url('system/img/1280/loader/home.png') 15px center no-repeat }
|
||||
.list .text.sett { background:url('system/img/1280/loader/settings.png') 15px center no-repeat }
|
||||
.list .text.vkb { background:url('public/img/1280/menu/icons/def.png') 0 center no-repeat }
|
||||
.list .text.load { background:url('system/img/1280/loader/net.png') 15px center no-repeat }
|
||||
.list .text.dlman { background:url('public/img/1280/menu/icons/dm.png') 0 4px no-repeat }
|
||||
.list .text.pvr { background:url('public/img/1280/menu/icons/pvr.png') 0 5px no-repeat }
|
||||
.list .text.web { background:url('public/img/1280/menu/icons/web.png') 0 5px no-repeat }
|
||||
.list .text.favs { background:url('public/img/1280/menu/icons/favs.png') 0 5px no-repeat }
|
||||
.list .text.help { background:url('public/img/1280/menu/icons/manual.png') 0px 10px no-repeat }
|
||||
.list tr { height:80px }
|
||||
.list tr:hover { background-color:#111; }
|
||||
.list .link:hover { background-color:#8b7f0c; color:#000; font-weight:bold; cursor:pointer }
|
||||
|
||||
table.options td.name { font-size:14px; color:grey }
|
||||
table.options td.data { padding:0 20px 0 5px; }
|
||||
table.options td.data input[type="text"] { border:none; margin:0; padding:0 5px; height:25px }
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
function openUrl ( url, width, height ) {
|
||||
window.open(
|
||||
url + (url.indexOf('?') === -1 ? '?' : '&') + 'width=' + width + '&height=' + height,
|
||||
'_blank',
|
||||
'menubar=0,location=0,resizable=0,scrollbars=0,status=0,titlebar=0,left=0,top=0,width=' + width + ',height=' + height
|
||||
);
|
||||
}
|
||||
|
||||
var fldServerAddress, fldSessionName;
|
||||
window.onload = function () {
|
||||
fldServerAddress = document.getElementById('fldServerAddress');
|
||||
fldSessionName = document.getElementById('fldSessionName');
|
||||
|
||||
fldServerAddress.value = localStorage.getItem('DEBUG_SERVER');
|
||||
fldSessionName.value = localStorage.getItem('DEBUG_NAME');
|
||||
|
||||
fldServerAddress.onchange = function(){
|
||||
localStorage.setItem('DEBUG_SERVER', this.value);
|
||||
};
|
||||
fldSessionName.onchange = function(){
|
||||
localStorage.setItem('DEBUG_NAME', this.value);
|
||||
};
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<table class="maxh maxw">
|
||||
<tr>
|
||||
<td class="header">
|
||||
<table class="options">
|
||||
<tr>
|
||||
<td class="name">Proxy server address:</td>
|
||||
<td class="data"><input type="text" style="width:150px;vertical-align:top" id="fldServerAddress"></td>
|
||||
|
||||
<td class="name">Session name:</td>
|
||||
<td class="data"><input type="text" style="width:100px;vertical-align:top" id="fldSessionName"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<table class="list">
|
||||
<tr>
|
||||
<td class="text home">Service page</td>
|
||||
<td class="link" onclick="openUrl('services.html', 1920, 1080)">1080p</td>
|
||||
<td class="link" onclick="openUrl('services.html', 1280, 720)">720p</td>
|
||||
<td class="link" onclick="openUrl('services.html', 720, 576)">PAL</td>
|
||||
<td class="link" onclick="openUrl('services.html', 720, 480)">NTSC</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text sett">System settings</td>
|
||||
<td class="link" onclick="openUrl('system/settings/index.html', 1920, 1080)">1080p</td>
|
||||
<td class="link" onclick="openUrl('system/settings/index.html', 1280, 720)">720p</td>
|
||||
<td class="link" onclick="openUrl('system/settings/index.html', 720, 576)">PAL</td>
|
||||
<td class="link" onclick="openUrl('system/settings/index.html', 720, 480)">NTSC</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text load">Portal loader</td>
|
||||
<td class="link" onclick="openUrl('system/pages/loader/index.html', 1920, 1080)">1080p</td>
|
||||
<td class="link" onclick="openUrl('system/pages/loader/index.html', 1280, 720)">720p</td>
|
||||
<td class="link" onclick="openUrl('system/pages/loader/index.html', 720, 576)">PAL</td>
|
||||
<td class="link" onclick="openUrl('system/pages/loader/index.html', 720, 480)">NTSC</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text dlman">Download manager</td>
|
||||
<td class="link" onclick="openUrl('public/app/dlman/index.html', 1920, 1080)">1080p</td>
|
||||
<td class="link" onclick="openUrl('public/app/dlman/index.html', 1280, 720)">720p</td>
|
||||
<td class="link" onclick="openUrl('public/app/dlman/index.html', 720, 576)">PAL</td>
|
||||
<td class="link" onclick="openUrl('public/app/dlman/index.html', 720, 480)">NTSC</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text pvr">Record manager</td>
|
||||
<td class="link" onclick="openUrl('public/app/pvr/index.html', 1920, 1080)">1080p</td>
|
||||
<td class="link" onclick="openUrl('public/app/pvr/index.html', 1280, 720)">720p</td>
|
||||
<td class="link" onclick="openUrl('public/app/pvr/index.html', 720, 576)">PAL</td>
|
||||
<td class="link" onclick="openUrl('public/app/pvr/index.html', 720, 480)">NTSC</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text web">Internet browser</td>
|
||||
<td class="link" onclick="openUrl('public/app/ibman/index.html?mode=2', 1920, 1080)">1080p</td>
|
||||
<td class="link" onclick="openUrl('public/app/ibman/index.html?mode=2', 1280, 720)">720p</td>
|
||||
<td class="link" onclick="openUrl('public/app/ibman/index.html?mode=2', 720, 576)">PAL</td>
|
||||
<td class="link" onclick="openUrl('public/app/ibman/index.html?mode=2', 720, 480)">NTSC</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text favs">Internet bookmarks</td>
|
||||
<td class="link" onclick="openUrl('public/app/ibman/index.html?mode=1', 1920, 1080)">1080p</td>
|
||||
<td class="link" onclick="openUrl('public/app/ibman/index.html?mode=1', 1280, 720)">720p</td>
|
||||
<td class="link" onclick="openUrl('public/app/ibman/index.html?mode=1', 720, 576)">PAL</td>
|
||||
<td class="link" onclick="openUrl('public/app/ibman/index.html?mode=1', 720, 480)">NTSC</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="text help">Help</td>
|
||||
<td class="link" onclick="openUrl('public/app/help/index.html', 1920, 1080)">1080p</td>
|
||||
<td class="link" onclick="openUrl('public/app/help/index.html', 1280, 720)">720p</td>
|
||||
<td class="link" onclick="openUrl('public/app/help/index.html', 720, 576)">PAL</td>
|
||||
<td class="link" onclick="openUrl('public/app/help/index.html', 720, 480)">NTSC</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
<!--<tr>
|
||||
<td class="footer">
|
||||
footer
|
||||
</td>
|
||||
</tr>-->
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,31 @@
|
|||
//All global events
|
||||
|
||||
//Reload given window
|
||||
"window.reload"
|
||||
|
||||
//Load given URL (has 1 param {String} - new window URL)
|
||||
"window.load"
|
||||
|
||||
// Player end playing some file
|
||||
"player.end"
|
||||
|
||||
// Play file. (has 1 param {String} - file url)
|
||||
"player.play"
|
||||
|
||||
// usb device has been mounted
|
||||
"broadcast.storage.mount"
|
||||
|
||||
// accessControl state has been change
|
||||
"broadcast.accessControl"
|
||||
|
||||
// usb device has been unmounted
|
||||
"broadcast.storage.unmount"
|
||||
|
||||
// sent (wake up) device to (from) standby mode
|
||||
"portal.standbyMode"
|
||||
|
||||
// reload environment variables
|
||||
"environment.reload"
|
||||
|
||||
// reset player resolution data according to new video mode
|
||||
"video.mode.reload"
|
|
@ -0,0 +1,708 @@
|
|||
History
|
||||
=======
|
||||
|
||||
## 2020.08.14 ##
|
||||
|
||||
* enable bluetooth support only for specific devices
|
||||
* force disable bluetooth and clear env for unsupported devices
|
||||
|
||||
|
||||
## 2020.07.21 ##
|
||||
|
||||
* delete Magic Cast application
|
||||
|
||||
|
||||
## 2020.07.03 ##
|
||||
|
||||
* fix update resolution on HDMI connect event
|
||||
* fix review warnings
|
||||
|
||||
|
||||
## 2020.06.25 ##
|
||||
|
||||
* add IM4411WV model support
|
||||
* add IM4410WV model support
|
||||
|
||||
|
||||
## 2020.06.04 ##
|
||||
|
||||
* remove overlapping of bookmarks modal by autocomplete
|
||||
* fix logic of changing F3 footer button
|
||||
* initialize Widevine for IPTV playlists if allowed
|
||||
* fix handle focus on items in Explorer
|
||||
* remove selection from added items inside Favorites
|
||||
* add support for whole cyrillic letters range in URL validation
|
||||
|
||||
|
||||
## 2020.05.07 ##
|
||||
|
||||
* add implementation for external page loading delay
|
||||
* select view as uniq to prevent loosing text
|
||||
* add check condition for setting delay
|
||||
* encode input fragment only for search mode
|
||||
|
||||
|
||||
## 2020.04.23 ##
|
||||
|
||||
* switch by default to the highest qulity for HLS
|
||||
|
||||
|
||||
## 2020.04.21 ##
|
||||
|
||||
* fix obtain "addresses" property for mount config
|
||||
|
||||
|
||||
## 2020.04.14 ##
|
||||
|
||||
* add SRT as stream protocol in URL validator, refactor
|
||||
|
||||
|
||||
## 2020.04.10 ##
|
||||
|
||||
* add basic support for Widevine DRM playlists
|
||||
* fix manual mounting of SMB share
|
||||
|
||||
|
||||
## 2020.03.26 ##
|
||||
|
||||
* encode URL spaces and pluses (+) in appropriate way
|
||||
* remove unescaping of explicit URL encoding symbols
|
||||
|
||||
|
||||
## 2020.03.11 ##
|
||||
|
||||
* fix reaction when error occured during slideshow
|
||||
|
||||
|
||||
## 2020.03.04 ##
|
||||
|
||||
* switch to HTTPS for update lists
|
||||
|
||||
|
||||
## 2020.01.23 ##
|
||||
|
||||
* add IM4411V model support
|
||||
* fix demo page loading by preventing parse wrong font files
|
||||
|
||||
|
||||
## 2019.10.31 ##
|
||||
|
||||
* fix help generator
|
||||
* add sorting by number in m3u parser
|
||||
|
||||
|
||||
## 2019.10.18 ##
|
||||
|
||||
* add device reload after user data cleared
|
||||
* fix server part of help-generator for php 7 version
|
||||
* fix background after removing all channels
|
||||
|
||||
|
||||
## 2019.10.11 ##
|
||||
|
||||
* fix timeshift start error modal
|
||||
|
||||
|
||||
## 2019.10.09 ##
|
||||
|
||||
* skip privacy policy not only in loader but in portal too
|
||||
|
||||
|
||||
## 2019.09.26 ##
|
||||
|
||||
* fix hiding modal behavior to prevent from show webinput results
|
||||
* prevent of showing webinput result box on exit from menu by Exit button
|
||||
* fix mounting share by domain name, remove IP validation
|
||||
* improve code quality
|
||||
|
||||
|
||||
## 2019.09.03 ##
|
||||
|
||||
* fix review warnings
|
||||
* fix checkbox styles for 576 and 480 resolution
|
||||
|
||||
|
||||
## 2019.08.19 ##
|
||||
|
||||
* fix teletext in 4k resolution
|
||||
|
||||
|
||||
## 2019.08.14 ##
|
||||
|
||||
* fix initial mute state after reload portal
|
||||
* add 4k resolution for MAG422
|
||||
|
||||
|
||||
## 2019.08.06 ##
|
||||
|
||||
* portals loader: add privacy policy reset
|
||||
* fix focus item in IPTV Channels after empty list
|
||||
|
||||
|
||||
## 2019.07.25 ##
|
||||
|
||||
* fix update list url for IM2101VO
|
||||
|
||||
|
||||
## 2019.07.05 ##
|
||||
|
||||
* fix init volume setting change
|
||||
|
||||
|
||||
## 2019.07.04 ##
|
||||
|
||||
* portals loader: remove HEAD request from portal availability check and use only GET request (some clients have strangely configured servers)
|
||||
|
||||
|
||||
## 2019.07.01 ##
|
||||
|
||||
* player: fix jscs
|
||||
* player: don't show error message for same file twice
|
||||
* player: exit from player after error message for bad images in non-slideshow mode
|
||||
* player: show error message for bad images
|
||||
|
||||
|
||||
## 2019.06.12 ##
|
||||
|
||||
* loader: fix embedded portal loading in multiportal mode
|
||||
* loader: fix jscs
|
||||
|
||||
|
||||
## 2019.06.10 ##
|
||||
|
||||
* loader: fix jscs
|
||||
* loader: remove exit button from privacy policy
|
||||
* loader: add checks for different ajax errors, fix abort function in ajax
|
||||
* loader: fix interface
|
||||
|
||||
|
||||
## 2019.06.05 ##
|
||||
|
||||
* loader: add new exit button
|
||||
* fix teletext option setup for low resolutions instead of low video modes
|
||||
* help: add privacy policy agreement
|
||||
* help generator: update to php 7
|
||||
* fix player teletext settings saving
|
||||
* fix navigation in player teletext settings
|
||||
|
||||
|
||||
## 2019.05.30 ##
|
||||
|
||||
* remove tif format support from mag322
|
||||
* loader: fix long names problems
|
||||
|
||||
|
||||
## 2019.05.17 ##
|
||||
|
||||
* fix loader
|
||||
|
||||
|
||||
## 2019.05.08 ##
|
||||
|
||||
* remove tif format for mag322
|
||||
* loader page rework and optimizations
|
||||
|
||||
|
||||
## 2019.04.25 ##
|
||||
|
||||
* fix list vertical align in DVB channels
|
||||
|
||||
|
||||
## 2019.04.18 ##
|
||||
|
||||
* add IM2101VO model support
|
||||
* remove .raw format support for mag322
|
||||
|
||||
|
||||
## 2019.04.11 ##
|
||||
|
||||
* add IM4411 model support
|
||||
|
||||
|
||||
## 2019.03.27 ##
|
||||
|
||||
* add IM4412 model support
|
||||
* add IM2101VI model support
|
||||
|
||||
|
||||
## 2019.03.25 ##
|
||||
|
||||
* remove some user data from speedtest and traceroute reports for aura
|
||||
|
||||
|
||||
## 2019.02.13 ##
|
||||
|
||||
* fix advanced settings in access control
|
||||
* add 4k resolution for MAG420
|
||||
* fix wifi manual settings
|
||||
* fix set subtitles black color
|
||||
* fix load manual wifi settings
|
||||
|
||||
|
||||
## 2019.02.07 ##
|
||||
|
||||
* fix weather in master settings
|
||||
|
||||
|
||||
## 2019.01.28 ##
|
||||
|
||||
* fix text in popup which appears for blocked portals
|
||||
|
||||
|
||||
## 2019.01.22 ##
|
||||
|
||||
* fix name overlap in update modal
|
||||
* add 'utf-16be' and 'utf-16le' subtitles encoding
|
||||
* fix fast load in loader
|
||||
* fix access control in loader
|
||||
|
||||
|
||||
## 2019.01.02 ##
|
||||
|
||||
* fix update start
|
||||
|
||||
|
||||
## 2018.12.27 ##
|
||||
|
||||
* update exit_wraper_bg.png from 2x2 to 100x100 size
|
||||
* fix event handler in update modal
|
||||
|
||||
|
||||
## 2018.12.10 ##
|
||||
|
||||
* support difference between mag254 and mag322 wifi event status implementation
|
||||
* add mag420 model support
|
||||
|
||||
|
||||
## 2018.12.05 ##
|
||||
|
||||
* correct updateList for MAG422
|
||||
|
||||
|
||||
## 2018.11.30 ##
|
||||
|
||||
* fix UPnPRendererClear error
|
||||
* change keydown listener to keypress in tattelecom code
|
||||
* update dvb scanning modals
|
||||
|
||||
|
||||
## 2018.11.15 ##
|
||||
|
||||
* fix focused out of array
|
||||
* fix code style
|
||||
|
||||
|
||||
## 2018.11.07 ##
|
||||
|
||||
* add mag422, remove PPPoE for mag422, mag424, mag425 from system settings
|
||||
|
||||
|
||||
## 2018.10.30 ##
|
||||
|
||||
* fix error handler for playlist update request
|
||||
* remove forcing enabling service button
|
||||
* hide unsupported settings for IM2100V, IM2100VI (resolution and network settings)
|
||||
|
||||
|
||||
## 2018.09.18 ##
|
||||
|
||||
* add contact data to warning text at "url is blocked" page
|
||||
* add IM2100VI model support
|
||||
|
||||
|
||||
## 2018.09.07 ##
|
||||
|
||||
* add check for async work of bluetooth API function at mag424 (stbBluetooth.enable)
|
||||
* fix channels list loading
|
||||
* fix start play object without url in player
|
||||
|
||||
|
||||
## 2018.08.23 ##
|
||||
|
||||
* fix event propagation
|
||||
|
||||
|
||||
## 2018.08.21 ##
|
||||
|
||||
* update manual
|
||||
* update localization
|
||||
* fix empty audio_initial_volume state
|
||||
|
||||
|
||||
## 2018.08.13 ##
|
||||
|
||||
* fix change position
|
||||
|
||||
|
||||
## 2018.08.07 ##
|
||||
|
||||
* fix localization
|
||||
|
||||
|
||||
## 2018.07.30 ##
|
||||
|
||||
* fix saving zero volume
|
||||
* fix localization
|
||||
|
||||
|
||||
## 2018.07.19 ##
|
||||
|
||||
* disable stbUPnPRenderer and clear code
|
||||
|
||||
|
||||
## 2018.07.11 ##
|
||||
|
||||
* fix current image date check in update
|
||||
|
||||
|
||||
## 2018.06.01 ##
|
||||
|
||||
* increase portal loading delay in multiportal mode to fix slow wifi start
|
||||
|
||||
|
||||
## 2018.05.24 ##
|
||||
|
||||
* add IM2100V model support
|
||||
* remove games from portal
|
||||
* remove games section from manual
|
||||
|
||||
|
||||
## 2018.05.17 ##
|
||||
|
||||
* fix update check: remove influence of device local time zone
|
||||
|
||||
|
||||
## 2018.05.07 ##
|
||||
|
||||
* fix incorrectly encoded urls in API event
|
||||
|
||||
|
||||
## 2018.04.27 ##
|
||||
|
||||
* add IM2101 device support
|
||||
* fix navigation in favorite, fix style in DVB Channels
|
||||
|
||||
|
||||
## 2018.04.24 ##
|
||||
|
||||
* remove DVB settings for IM2102
|
||||
* fix navigation in DVB channels
|
||||
* fix DVB channels item style
|
||||
|
||||
|
||||
## 2018.04.13 ##
|
||||
|
||||
* fix access control settings
|
||||
|
||||
|
||||
## 2018.04.12 ##
|
||||
|
||||
* add modal window with info on url blocking
|
||||
|
||||
|
||||
## 2018.04.10 ##
|
||||
|
||||
* add IM2102 device support
|
||||
|
||||
|
||||
## 2018.04.03 ##
|
||||
|
||||
* add IM2100 device support
|
||||
* change title LED brightness (standby) in settings
|
||||
* add stbUPnP.deinit in system settings
|
||||
|
||||
|
||||
## 2018.03.26 ##
|
||||
|
||||
* add MAG424 device support
|
||||
* fix checkbox style in settings
|
||||
* correct configs for MAG424/425/351/352
|
||||
|
||||
|
||||
## 2018.02.19 ##
|
||||
|
||||
* add new timezone codes
|
||||
* always check environment variables portal1 and portal2 for possible operator changes (and apply them)
|
||||
* change statistic server url
|
||||
* optimise auto update requests
|
||||
* disable 1920x1080 graphic resolution for AuraHD4
|
||||
|
||||
|
||||
## 2018.02.16 ##
|
||||
|
||||
* fix translation
|
||||
* fix opening Home Media resources after UPnP failure
|
||||
* fix retrieving search data from Google for autocomplete
|
||||
* improve saving algorithm in timeshift
|
||||
* don't show auto power down if timeshift is active
|
||||
* renew environment variables values after correction by operator
|
||||
|
||||
|
||||
## 2018.01.24 ##
|
||||
|
||||
* remove 1080p resolution selection in settings for mag322
|
||||
|
||||
|
||||
## 2018.01.19 ##
|
||||
|
||||
* request timeout for retrieving the help archive has been increased
|
||||
* fix video settings
|
||||
* fix wifi keys generation page
|
||||
|
||||
|
||||
## 2018.01.09 ##
|
||||
|
||||
* fix mounting share by hand
|
||||
* remove DVB setting for AuraHD4
|
||||
|
||||
|
||||
## 2017.12.26 ##
|
||||
|
||||
* fix wrong url for auto update on MAG276
|
||||
* remove misspelling from auto update url in auraHD4
|
||||
* comment cleanup trash download tasks for unmounted storages (cleanup triggers by unmount event)
|
||||
* cleanup trash download tasks for unmounted storages (cleanup triggers by unmount event)
|
||||
|
||||
|
||||
## 2017.12.18 ##
|
||||
|
||||
* fix value parsing for auto update condition variable
|
||||
|
||||
|
||||
## 2017.11.29 ##
|
||||
|
||||
* add missing codec image to cache list
|
||||
* fix item focusing in media browser on player event
|
||||
* fix missing environment variables for sending headers on update
|
||||
* optimize player and explorer pages switching
|
||||
|
||||
## 2017.11.27 ##
|
||||
|
||||
* add new headers (X-Portal1 and X-Portal2) in update list request
|
||||
* fix save resolution in settings
|
||||
* don't send update check request after update modal window exit
|
||||
|
||||
|
||||
## 2017.11.20 ##
|
||||
|
||||
* add new headers in update list request
|
||||
* disable password field for NFS mounting
|
||||
* change logo for AuraHD 4
|
||||
|
||||
|
||||
## 2017.11.17 ##
|
||||
|
||||
* add AC3+ audio type
|
||||
* fix interface error in download app on quick multiple tasks creation
|
||||
* add speed test for mag35*
|
||||
|
||||
|
||||
## 2017.11.07 ##
|
||||
|
||||
* remove PPPoE for AuraHD*
|
||||
* update updateList url for MAG256 and MAG351
|
||||
|
||||
|
||||
## 2017.10.30 ##
|
||||
|
||||
* fix reload portal after change settings
|
||||
|
||||
|
||||
## 2017.10.13 ##
|
||||
|
||||
* add untune dvb input in DVB channels
|
||||
* fix focus item in Media Browser
|
||||
* correct supported files types list for mag322
|
||||
|
||||
|
||||
## 2017.09.28 ##
|
||||
|
||||
* add AuraHD4 device config and logo
|
||||
* fix pause icon in download manager
|
||||
* fix reload portal after change settings
|
||||
* fix teletext settings
|
||||
* add logo for mag425
|
||||
|
||||
|
||||
## 2017.09.14 ##
|
||||
|
||||
* fix reboot device after reset settings
|
||||
* fix problem with chapters list in player for DVD content
|
||||
* fix reload portal message after reset settings
|
||||
* add mag324c and mag325c logo images
|
||||
|
||||
|
||||
## 2017.09.04 ##
|
||||
|
||||
* add mag324c and mag325c logo images
|
||||
|
||||
|
||||
## 2017.08.28 ##
|
||||
|
||||
* fix wifi, internet and network states
|
||||
* update localizations
|
||||
* add .wtv extension to supported files
|
||||
|
||||
|
||||
## 2017.08.17 ##
|
||||
|
||||
* fix mag349 config
|
||||
* change format wifi_off from boolean to number
|
||||
* update registers types in config for mag3** series
|
||||
* fix wifi state change
|
||||
|
||||
|
||||
## 2017.08.11 ##
|
||||
|
||||
* add wifi disable button and state change hook
|
||||
* fix enable wifi button state
|
||||
|
||||
|
||||
## 2017.08.09 ##
|
||||
|
||||
* fix ts time save
|
||||
* add to settings information about rootFS version
|
||||
* fix update url for mag324c
|
||||
* remove 'No ip' settings for MAG322, MAG324C
|
||||
|
||||
|
||||
## 2017.07.28 ##
|
||||
|
||||
* fix editing iptv channels, remove unc option from SMB mount
|
||||
|
||||
|
||||
## 2017.07.26 ##
|
||||
|
||||
* remove PPPoE from network settings on MAG324C
|
||||
|
||||
|
||||
## 2017.07.25 ##
|
||||
|
||||
* fix adding channels to IPTV playlist
|
||||
* checking API version for set appropriate method signatures on open samba host
|
||||
* fix unc address syntax on cifs mount
|
||||
|
||||
|
||||
## 2017.07.24 ##
|
||||
|
||||
* add hash info to build metadata
|
||||
* add MAG324C model support
|
||||
* protect parsing AJAX request for update list result
|
||||
* remove PPPoE from settings for MAG322
|
||||
|
||||
|
||||
## 2017.07.14 ##
|
||||
|
||||
* add auth for SMB servers and rework error handling
|
||||
* fix tv url parsing
|
||||
* hide password and fix mounting share by hand
|
||||
* fix manual mounting in SAMBA browser
|
||||
* store auth data of successful connections to SMB servers
|
||||
* open SAMBA server even if it's password protected
|
||||
|
||||
|
||||
## 2017.06.23 ##
|
||||
|
||||
* hide info panel on bluetooth disable
|
||||
* realize opening shares with multiple IPs
|
||||
|
||||
|
||||
## 2017.06.14 ##
|
||||
|
||||
* add mac to auto update list request as query param
|
||||
|
||||
|
||||
## 2017.05.22 ##
|
||||
|
||||
* add warning message in case of NAND bank damage
|
||||
* show actual NAND number in settings (with emergency status info)
|
||||
|
||||
|
||||
## 2017.05.15 ##
|
||||
|
||||
* add MAGic Cast menu item
|
||||
* fix bluetooth adapter disabling when some device is connected
|
||||
* fix .m3u parser
|
||||
* fix audio playing info panel state in player
|
||||
|
||||
|
||||
## 2017.04.26 ##
|
||||
|
||||
* add "wtv" video file format support
|
||||
|
||||
|
||||
## 2017.04.25 ##
|
||||
|
||||
* fix playback on video mode change
|
||||
* fix empty Bluetooth device list handlers
|
||||
|
||||
|
||||
## 2017.04.14 ##
|
||||
|
||||
* set dynamic range compression for DolbyDigital audio on player initialization
|
||||
* remove "Dynamic range compression" option from settings
|
||||
* restrict "Operating mode" audio setting to "RF Mode" and "Line Mode" only
|
||||
|
||||
|
||||
## 2017.04.12 ##
|
||||
|
||||
* update codec icons in player
|
||||
|
||||
|
||||
## 2017.04.05 ##
|
||||
|
||||
* correct manual localization
|
||||
|
||||
|
||||
## 2017.03.31 ##
|
||||
|
||||
* fix selected chapter after change position in DVD or ISO files
|
||||
* fix #6534, read cue and m3u playlists equally
|
||||
* remove dead code (variable STB_MODE_STANDBY) and fix multiple net status function call
|
||||
* add flag IPTV_PLAYBACK_ON_START to start first channel in full screen
|
||||
|
||||
|
||||
## 2017.03.29 ##
|
||||
|
||||
fix usb unmount when something is playing
|
||||
|
||||
|
||||
## 2017.03.28 ##
|
||||
|
||||
* save bluetooth enabled state in environment
|
||||
* remove unused device characteristics
|
||||
|
||||
|
||||
## 2017.03.27 ##
|
||||
|
||||
* fix player preview position
|
||||
* bluetooth: sort devices by paired and active
|
||||
* fix bug with partially transparent overlay
|
||||
* fix localization
|
||||
|
||||
|
||||
## 2017.03.16 ##
|
||||
|
||||
* add device config to json generator
|
||||
* add devices logos
|
||||
* add bluetooth translations
|
||||
* rework bluetooth api
|
||||
* add MAG323 model support
|
||||
* fix image preview
|
||||
* fix subtitles and teletext subtitles
|
||||
* add rotate image in player menu
|
||||
* fix localisation
|
||||
|
||||
|
||||
## 2017.03.01 ##
|
||||
|
||||
* Add MAG324/MAG325 device support
|
||||
* Add img format #11116
|
||||
* Solve #11048
|
||||
|
||||
|
||||
## 2017.02.22 ##
|
||||
|
||||
* hide gSTB error message until we get localisation for it
|
||||
* title field shouldn't rewrite lang field and if title field available use it instead of localised type text
|
||||
* upgrade error page ping
|
|
@ -0,0 +1,14 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||
<title>new MAG 200-250</title>
|
||||
|
||||
<script type="text/javascript">
|
||||
window.location = 'system/pages/loader/index.html';
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,32 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* Customization rules for manual tune
|
||||
* @author Stanislav Kalashnik <sk@infomir.eu>
|
||||
* @namespace
|
||||
*/
|
||||
var RULES = {
|
||||
|
||||
'Playback' : true,
|
||||
|
||||
'Interface' : true,
|
||||
|
||||
'SoftwareAutoUpdate': true,
|
||||
|
||||
'TimeShift' : true,
|
||||
|
||||
'SpeedTest' : true,
|
||||
|
||||
'Traceroute' : true,
|
||||
|
||||
'SystemSettings' : true,
|
||||
|
||||
'SetupWizard' : true,
|
||||
|
||||
'DVB' : true,
|
||||
|
||||
'accessControl' : true,
|
||||
|
||||
'teletext' : true
|
||||
|
||||
};
|
|
@ -0,0 +1,795 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>STB Service page</title>
|
||||
<meta charset='utf-8'>
|
||||
|
||||
<script>
|
||||
var PATH_BASE = '';
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="system/init.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
(function () {
|
||||
var time = (new Date).getTime();
|
||||
// conditional css loading
|
||||
document.write('<link rel="stylesheet" href="system/' + WINDOW_HEIGHT + '.css?_=' + time + '">');
|
||||
document.write('<link rel="stylesheet" href="public/portal/' + WINDOW_HEIGHT + '.css?_=' + time + '">');
|
||||
})();
|
||||
</script>
|
||||
|
||||
<script type="text/javascript" src="rules.js"></script>
|
||||
|
||||
<script type="text/javascript" src="system/config.js"></script>
|
||||
<script type="text/javascript" src="system/wm.js"></script>
|
||||
<script type="text/javascript" src="system/keys.js"></script>
|
||||
<script type="text/javascript" src="system/gettext.js"></script>
|
||||
<script type="text/javascript" src="system/tools.js"></script>
|
||||
<script type="text/javascript" src="system/cbase.js"></script>
|
||||
<script type="text/javascript" src="system/update.js"></script>
|
||||
<script type="text/javascript" src="system/cprogressbar.js"></script>
|
||||
<script type="text/javascript" src="system/cpage.js"></script>
|
||||
<script type="text/javascript" src="system/cslist.js"></script>
|
||||
<script type="text/javascript" src="system/clist.js"></script>
|
||||
<script type="text/javascript" src="system/vscrollbar.js"></script>
|
||||
<script type="text/javascript" src="system/vlist.js"></script>
|
||||
<script type="text/javascript" src="system/cgmenu.js"></script>
|
||||
<script type="text/javascript" src="system/cmodal.js"></script>
|
||||
<script type="text/javascript" src="system/cbpanel.js"></script>
|
||||
<script type="text/javascript" src="system/cbcrumb.js"></script>
|
||||
<script type="text/javascript" src="system/csbar.js"></script>
|
||||
<script type="text/javascript" src="system/buffer.js"></script>
|
||||
<script type="text/javascript" src="system/ccheckbox.js"></script>
|
||||
<script type="text/javascript" src="system/cinput.js"></script>
|
||||
<script type="text/javascript" src="system/cselect.js"></script>
|
||||
<script type="text/javascript" src="system/clog.js"></script>
|
||||
<script type="text/javascript" src="system/cupdatemodal.js"></script>
|
||||
<script type="text/javascript" src="system/cmap.js"></script>
|
||||
<script type="text/javascript" src="system/timezones.js"></script>
|
||||
<script type="text/javascript" src="system/keyboard/js/config.js"></script>
|
||||
<script type="text/javascript" src="system/access.control/main.js"></script>
|
||||
<script type="text/javascript" src="system/emiter.js"></script>
|
||||
<script type="text/javascript" src="system/wamp.js"></script>
|
||||
|
||||
<script type="text/javascript" src="public/portal/types.js"></script>
|
||||
<script type="text/javascript" src="public/portal/vars.js"></script>
|
||||
<script type="text/javascript" src="system/variables/check.js"></script>
|
||||
<script type="text/javascript" src="public/portal/services.js"></script>
|
||||
<script type="text/javascript" src="public/portal/speedtest.js"></script>
|
||||
<script type="text/javascript" src="public/portal/menu.js"></script>
|
||||
|
||||
<script type="text/javascript" src="public/config.js"></script>
|
||||
|
||||
<script type="text/javascript" src="public/portal/media/browsers/file.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/browsers/upnp.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/cflist.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/tvlist.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/dvblist.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/epggrid.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/dvbepg.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/exlporer.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/iptv.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/dvbtv.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/modals.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/main.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/player.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/playlist.js"></script>
|
||||
<script type="text/javascript" src="public/portal/media/upnpRender.js"></script>
|
||||
|
||||
<!--<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?v=3.exp&sensor=false&libraries=places,weather&scale=2&language=en"></script>-->
|
||||
|
||||
<style type="text/css">
|
||||
html, body { overflow:hidden; background:transparent; color:#fff; margin:0; padding:0; -webkit-user-select:none; font-family:Ubuntu,sans-serif; }
|
||||
|
||||
/* table cell spacing/padding reset */
|
||||
table { border:0; border-collapse:collapse; border-spacing:0; }
|
||||
table td { padding:0 }
|
||||
|
||||
/* meta-classes */
|
||||
.maxh { height:100% }
|
||||
.maxw { width:100% }
|
||||
a { text-decoration:none }
|
||||
|
||||
/* scroll bars */
|
||||
::-webkit-scrollbar-track { background:#2a2c2f }
|
||||
::-webkit-scrollbar-thumb { background:#ffc20e }
|
||||
|
||||
.page#pageServiceMenu .header { position:absolute; top:0; background:none; z-index:7 }
|
||||
|
||||
#cursorGround { z-index:1 }
|
||||
#cursor { z-index:1 }
|
||||
#ground { z-index:2 }
|
||||
#weatherSettings { z-index:3 }
|
||||
|
||||
.page#pageMediaPlayer #slideContainer {
|
||||
position: absolute;
|
||||
/*background-color: black;*/
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
top: 0;
|
||||
left: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.page#pageMediaPlayer #slideContainer .fix {
|
||||
width: 0;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.page#pageMediaPlayer .animationContainer {
|
||||
margin: 0 auto;
|
||||
width: 500px;
|
||||
height: 162px;
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
overflow: hidden;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.page#pageMediaPlayer .slide{
|
||||
position: absolute;
|
||||
-webkit-animation-name: play;
|
||||
-webkit-animation-iteration-count: infinite;
|
||||
-webkit-animation-duration: 0.8s;
|
||||
opacity: 0;
|
||||
/*opacity:1;*/
|
||||
}
|
||||
|
||||
@-webkit-keyframes play{
|
||||
/*from{opacity: 1;}*/
|
||||
0% { opacity: 0; }
|
||||
10% { opacity: 1; }
|
||||
40% { opacity: 1; }
|
||||
100% { opacity: 0; }
|
||||
/*to{opacity: 1;}*/
|
||||
}
|
||||
|
||||
.page#pageMediaPlayer .animationPlay4 { -webkit-animation-delay: 0s; }
|
||||
.page#pageMediaPlayer .animationPlay3 { -webkit-animation-delay: 0.2s; }
|
||||
.page#pageMediaPlayer .animationPlay2 { -webkit-animation-delay: 0.4s; }
|
||||
.page#pageMediaPlayer .animationPlay1 { -webkit-animation-delay: 0.6s; }
|
||||
|
||||
/*
|
||||
fix resizing bug after showing table, Bug #2281, link - http://192.168.1.220:3000/issues/2281
|
||||
looks like a browser bug
|
||||
*/
|
||||
.page#pageMediaPlayer .cgmenu-main table {table-layout: fixed;}
|
||||
</style>
|
||||
</head>
|
||||
<body id="body">
|
||||
|
||||
<div id="loading" style="width:100%; height:100%; background-color:transparent; position:absolute; top:0; left:0; z-index:2010; display:block; cursor:none">
|
||||
<span style="position:absolute; color:#ccc; font-family:Ubuntu,sans-serif; font-size:36px; width:100%; text-align:center; top:50%; cursor:none">Loading...</span>
|
||||
</div>
|
||||
|
||||
<!-- Master Settings -->
|
||||
<div id="pageMasterSettings" style="display: none;">
|
||||
<div id="pageMasterSettings_header"></div>
|
||||
<div id="pageMasterSettings_main" class=""></div>
|
||||
<div id="pageMasterSettings_footer"></div>
|
||||
<!-- google map -->
|
||||
<div id="masterSettingsMapCanvas" class="mapCanvas"></div>
|
||||
<!-- end google map -->
|
||||
</div>
|
||||
<!-- end Master Settings -->
|
||||
|
||||
<!-- Weather Settings -->
|
||||
<div id="weatherSettings" style="display:none" class="page">
|
||||
<!-- main container -->
|
||||
<table cellpadding="0" cellspacing="0" border="0" style="width:100%; height:100%; background-color:transparent" class="body">
|
||||
<!-- page body top panel -->
|
||||
<tr class="header">
|
||||
<td colspan="3" class="crop">
|
||||
<table class="maxw" cellpadding="0" class="maxw" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<!-- Breadcrumb component -->
|
||||
<td class="cbcrumb"></td>
|
||||
<!-- Search bar component -->
|
||||
<td class="csbar">
|
||||
<input type="text" id="place"/>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!--<tr class="map" style="display:none">-->
|
||||
<!--<td colspan="3">-->
|
||||
<!--<div class="canvas"></div>-->
|
||||
<!--</td>-->
|
||||
<!--</tr>-->
|
||||
|
||||
<tr class="content">
|
||||
<td colspan="2" class="today">
|
||||
<!-- today -->
|
||||
<table id="wsbody_today" cellpadding="0" cellspacing="0" border="0">
|
||||
<tr class="row_title">
|
||||
<td colspan="2" align="left">
|
||||
<div class="day" id="forecast_day_0_day"></div>
|
||||
<div class="date" id="forecast_day_0_date"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row_image">
|
||||
<td colspan="2" class="image" align="center" style="vertical-align:middle">
|
||||
<div id="forecast_day_0_img"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row_descr">
|
||||
<td colspan="2">
|
||||
<div class="descr" id="forecast_day_0_cond"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row_data">
|
||||
<td>
|
||||
<div class="weather_details day_temp" id="forecast_day_0_to">0</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="weather_details humidity" id="forecast_day_0_hum">0%</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row_data" align="left">
|
||||
<td>
|
||||
<div class="weather_details night_temp" id="forecast_day_0_from">0</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="weather_details wind" id="forecast_day_0_wind"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="row_footer">
|
||||
<td colspan="2"> </td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- end today -->
|
||||
</td>
|
||||
<td class="weather_list">
|
||||
<!-- list of the next 3 days -->
|
||||
<table id="wsbody_wlist" cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td align="left">
|
||||
<div class="day" id="forecast_day_1_day"></div>
|
||||
<div class="date" id="forecast_day_1_date"></div>
|
||||
</td>
|
||||
<td class="image">
|
||||
<div id="forecast_day_1_img"></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="descr" id="forecast_day_1_cond">0</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="day_temp" id="forecast_day_1_to">0</div>
|
||||
<div class="night_temp" id="forecast_day_1_from">0</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<div class="day" id="forecast_day_2_day"></div>
|
||||
<div class="date" id="forecast_day_2_date"></div>
|
||||
</td>
|
||||
<td class="image">
|
||||
<div id="forecast_day_2_img"></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="descr" id="forecast_day_2_cond">0</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="day_temp" id="forecast_day_2_to">0</div>
|
||||
<div class="night_temp" id="forecast_day_2_from">0</div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="left">
|
||||
<div class="day" id="forecast_day_3_day"></div>
|
||||
<div class="date" id="forecast_day_3_date"></div>
|
||||
</td>
|
||||
<td class="image">
|
||||
<div id="forecast_day_3_img"></div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="descr" id="forecast_day_3_cond">0</div>
|
||||
</td>
|
||||
<td>
|
||||
<div class="day_temp" id="forecast_day_3_to">0</div>
|
||||
<div class="night_temp" id="forecast_day_3_from">0</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- end list of the next 3 days -->
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<tr class="footer">
|
||||
<td class="crop exit">
|
||||
<div class="cbpanel-main"></div>
|
||||
<!--<div onclick="weather.weatherSettingsExit()">Exit</div>-->
|
||||
</td>
|
||||
<td class="crop main" colspan="2">
|
||||
<!-- control buttons block -->
|
||||
<div class="cbpanel-main"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<!-- end main container -->
|
||||
|
||||
<!-- autocompleter list -->
|
||||
<div class="suggests" id="suggests" style="display:none">
|
||||
<ul>
|
||||
<li id="s0"></li>
|
||||
<li id="s1"></li>
|
||||
<li id="s2"></li>
|
||||
<li id="s3"></li>
|
||||
<li id="s4"></li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- end autocompleter list -->
|
||||
|
||||
<!-- google map -->
|
||||
<div id="mapCanvas" class="mapCanvas"></div>
|
||||
<!-- end google map -->
|
||||
</div>
|
||||
<!-- end Weather Settings -->
|
||||
|
||||
<!-- Service Menu -->
|
||||
<div class="page" id="pageServiceMenu">
|
||||
<div class="bg"></div>
|
||||
<div class="header">
|
||||
<div id="statuses">
|
||||
<div id="network_status"></div>
|
||||
<div id="wifi_status"></div>
|
||||
<div id="lan_status"></div>
|
||||
</div>
|
||||
<div id="screenClockHours_main" class="date_time" style="text-align:center">
|
||||
<div class="time" id="screenClockMinutes_main"></div>
|
||||
<div id="screenClockDate_main" class="date"></div>
|
||||
</div>
|
||||
<div id="face" style="text-align:right"></div>
|
||||
<div id="weather_condition" class="weather_default" style="text-align:right"></div>
|
||||
</div>
|
||||
<div id="switch_desktop" onclick="app.switch_page()">
|
||||
<div id="cur_desktop" class="_0"></div>
|
||||
</div>
|
||||
<div id="cursorGround" class="ground0">
|
||||
<div id="cursor"></div>
|
||||
</div>
|
||||
<div id="ground" class="ground0"></div>
|
||||
</div>
|
||||
<!-- end Service Menu -->
|
||||
|
||||
<!-- Settings -->
|
||||
<div class="page" id="pageSettings">
|
||||
<table class="body">
|
||||
<!-- page body top panel -->
|
||||
<tr class="header">
|
||||
<td colspan="2" class="crop">
|
||||
<table class="maxw">
|
||||
<tr>
|
||||
<!-- Breadcrumb component -->
|
||||
<td class="cbcrumb"></td>
|
||||
<!-- Search bar component -->
|
||||
<td class="csbar"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
<!-- page body main content block -->
|
||||
<tr class="content">
|
||||
<td colspan="2" class="crop">
|
||||
<!-- FileList component -->
|
||||
<div class="cslist-main maxw"></div>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- page body bottom panel -->
|
||||
<tr class="footer">
|
||||
<td class="crop exit">
|
||||
<div class="cbpanel-main"></div>
|
||||
<!--<div onclick="SettingsPage.pressExit()">Exit</div>-->
|
||||
</td>
|
||||
<td class="crop main">
|
||||
<!-- control buttons block -->
|
||||
<div class="cbpanel-main"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!-- end Settings -->
|
||||
|
||||
<!-- IPTV -->
|
||||
<div class="page" id="pageTVChannels">
|
||||
<!-- side menu hidden body -->
|
||||
<div class="cgmenu-main"></div>
|
||||
|
||||
<!-- main page body -->
|
||||
<table class="body">
|
||||
<!-- page body top panel -->
|
||||
<tr class="header">
|
||||
<td colspan="2" class="crop">
|
||||
<table class="maxw">
|
||||
<tr>
|
||||
<!-- Breadcrumb component -->
|
||||
<td class="cbcrumb"></td>
|
||||
<!-- Search bar component -->
|
||||
<td class="csbar"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td class="crop tray"></td>
|
||||
</tr>
|
||||
|
||||
<tr class="content" style="background-image: url(system/img/backgrounds/bg_black_70.png);">
|
||||
<td colspan="3" class="crop">
|
||||
<table class="maxw">
|
||||
<tr>
|
||||
<td class="main">
|
||||
<!-- FileList component -->
|
||||
<div class="cslist-main"></div>
|
||||
</td>
|
||||
<td class="content_right">
|
||||
<div class="content">
|
||||
<div class="title"><div class="info_icon"></div><div class="infoTitle"></div></div>
|
||||
<div class="prog_name URL" style="word-break: break-all;word-wrap: break-word;"></div>
|
||||
<div class="prog_name pvrStatus" style="word-break: break-all;word-wrap: break-word; display: none;">
|
||||
<div class="pvrText" style="float:left;"></div>
|
||||
<div class="pvrStatusImg done"></div>
|
||||
<div class="pvrStatusImg wait"></div>
|
||||
<div class="pvrStatusImg write"></div>
|
||||
<div class="pvrStatusImg error"></div>
|
||||
</div>
|
||||
<div class="prog_name epgNow"></div>
|
||||
<div class="prog_name epgNext"></div>
|
||||
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- page body bottom panel -->
|
||||
<tr class="footer">
|
||||
<td class="crop exit">
|
||||
<div class="cbpanel-main"></div>
|
||||
<!--<div onclick="IPTVChannels.actionExit()">Exit</div>-->
|
||||
</td>
|
||||
<td class="crop main" colspan="2">
|
||||
<!-- control buttons block -->
|
||||
<div class="cbpanel-main"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="channelNumber" style="display: none;"></div>
|
||||
</div>
|
||||
<!-- end IPTV -->
|
||||
|
||||
<!-- DVBTV -->
|
||||
<div class="page" id="pageDVBChannels">
|
||||
<!-- side menu hidden body -->
|
||||
<div class="cgmenu-main"></div>
|
||||
<div class="scanInProgress maxw maxh" style="display: none;">
|
||||
<div class="connection">
|
||||
<div class="percent percentScan">100%</div>
|
||||
<div class="loader"></div>
|
||||
</div>
|
||||
<div class="desc">
|
||||
<table width="100%" border="0" cellspacing="0" cellpadding="0">
|
||||
<tr>
|
||||
<td class="titleFreqScan" style="text-align: right;width: 50%;"></td>
|
||||
<td class="titleFreqScanText" style="text-align: left;width: 50%;"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="titleTotalScan" style="text-align: right"></td>
|
||||
<td class="titleTotalScanText" style="text-align: left"></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="titleLastScan" style="text-align: right"></td>
|
||||
<td class="titleLastScanText" style="text-align: left"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<!-- main page body -->
|
||||
<table class="body">
|
||||
<!-- page body top panel -->
|
||||
<tr class="header">
|
||||
<td colspan="2" class="crop">
|
||||
<table class="maxw">
|
||||
<tr>
|
||||
<!-- Breadcrumb component -->
|
||||
<td class="cbcrumb"></td>
|
||||
<!-- Search bar component -->
|
||||
<td class="csbar"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td class="crop tray"></td>
|
||||
</tr>
|
||||
|
||||
<!-- page body main content block -->
|
||||
<tr class="content" style="background-image: url(system/img/backgrounds/bg_black_70.png);">
|
||||
<td colspan="3" class="crop">
|
||||
<table class="maxw">
|
||||
<tr>
|
||||
<td class="main">
|
||||
<!-- FileList component -->
|
||||
<div class="clist-main"></div>
|
||||
</td>
|
||||
<td class="content_right">
|
||||
<div class="content">
|
||||
<div class="title"><div class="info_icon"></div><div class="infoTitle"></div></div>
|
||||
<div class="prog_name epgNow"></div>
|
||||
<div class="prog_name epgNext"></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- page body bottom panel -->
|
||||
<tr class="footer">
|
||||
<td class="crop exit">
|
||||
<div class="cbpanel-main"></div>
|
||||
</td>
|
||||
<td class="crop main" colspan="2">
|
||||
<!-- control buttons block -->
|
||||
<div class="cbpanel-main"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="channelNumber" style="display: none;"></div>
|
||||
</div>
|
||||
|
||||
<!--DVB EPG PAGE-->
|
||||
<div class="page" id="pageDVBEpg">
|
||||
<!-- main page body -->
|
||||
<table class="body">
|
||||
<!-- page body top panel -->
|
||||
<tr class="header">
|
||||
<td colspan="2" class="crop">
|
||||
<table class="maxw">
|
||||
<tr>
|
||||
<!-- Breadcrumb component -->
|
||||
<td class="cbcrumb"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- page body main content block -->
|
||||
<tr class="content" style="background-image: url(system/img/backgrounds/bg_black_70.png);">
|
||||
<td colspan="3" class="crop">
|
||||
<table class="maxw">
|
||||
<tr>
|
||||
<td colspan="2" class="timeblocks">
|
||||
<!--<div class="mainblock"></div>-->
|
||||
</td>
|
||||
<td>
|
||||
<div class="clock"></div>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td valign="top" class="clist-main" colspan="3"><div class="timeline"></div></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td colspan="2">
|
||||
<div class="current_prog"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- page body bottom panel -->
|
||||
<tr class="footer">
|
||||
<td class="crop exit">
|
||||
<div class="cbpanel-main"></div>
|
||||
<!--<div onclick="DVBEpg.actionExit()">Exit</div>-->
|
||||
</td>
|
||||
<td class="crop main" colspan="2">
|
||||
<!-- control buttons block -->
|
||||
<div class="cbpanel-main"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
<div class="channelNumber" style="display: none;"></div>
|
||||
</div>
|
||||
<!-- end DVBTV -->
|
||||
|
||||
<!-- Media Browser -->
|
||||
<div class="page" id="pageMediaBrowser">
|
||||
<!-- side menu hidden body -->
|
||||
<div class="cgmenu-main"></div>
|
||||
|
||||
<!-- main page body -->
|
||||
<table class="body">
|
||||
<!-- page body top panel -->
|
||||
<tr class="header">
|
||||
<td colspan="2" class="crop">
|
||||
<table class="maxw">
|
||||
<tr>
|
||||
<!-- Breadcrumb component -->
|
||||
<td class="cbcrumb"></td>
|
||||
<!-- Search bar component -->
|
||||
<td class="csbar"></td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td class="crop tray"></td>
|
||||
</tr>
|
||||
|
||||
<!-- page body main content block -->
|
||||
<tr class="content">
|
||||
<td colspan="3" class="crop">
|
||||
<table class="maxw">
|
||||
<tr>
|
||||
<td class="main">
|
||||
<!-- FileList component -->
|
||||
<div class="vlist-main"></div>
|
||||
<div class="vscroll"></div>
|
||||
</td>
|
||||
<td class="sbar">
|
||||
<!-- SideBar component -->
|
||||
<table class="maxh maxw">
|
||||
<tr>
|
||||
<td class="view">
|
||||
<!-- main preview block -->
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="info">
|
||||
<div class="block all">
|
||||
<span class="title">Records:</span> <span class="value">0</span>
|
||||
</div>
|
||||
<div class="block sel">
|
||||
<span class="title">Selected:</span> <span class="value">0</span>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- page body bottom panel -->
|
||||
<tr class="footer">
|
||||
<td class="crop exit">
|
||||
<div class="cbpanel-main"></div>
|
||||
<!--<div onclick="MediaBrowser.actionBack()">Exit</div>-->
|
||||
</td>
|
||||
<td class="crop main" colspan="2">
|
||||
<!-- control buttons block -->
|
||||
<div class="cbpanel-main"></div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!-- end Media Browser -->
|
||||
|
||||
<!-- Tools Pan -->
|
||||
<div id="toolsPan">
|
||||
<table cellpadding="0" cellspacing="0" width="100%" border="0" class="fixed">
|
||||
<tr>
|
||||
<td id="media_HeaderContainer" valign="top">
|
||||
<!--<div id="mediaHeader_DualMonoIco" class="mediaHeaderIco"></div>-->
|
||||
<!--<div id="mediaHeader_PauseIco" class="mediaHeaderIco"></div>-->
|
||||
<div id="mediaHeader_Aspect" class="mediaHeaderIco">
|
||||
<div class="aspect_icon"></div>
|
||||
<span></span>
|
||||
</div>
|
||||
</td>
|
||||
|
||||
<td class="volumeContainer">
|
||||
<div id="mute" style="visibility:hidden"></div>
|
||||
<div id="volumeForm" style="visibility:hidden">
|
||||
<div id="volume_bar">
|
||||
<img src="" class="alignLeft" id="volumeLeft" alt="" style="float:left">
|
||||
|
||||
<div id="volume_right"></div>
|
||||
</div>
|
||||
<div id="volume_num"></div>
|
||||
</div>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
<!-- end Tools Pan -->
|
||||
|
||||
<!-- MediaPlayer -->
|
||||
<div class="page" id="pageMediaPlayer">
|
||||
<div id="slideContainer" style="display:none;">
|
||||
<div class="animationContainer">
|
||||
<img class='slide animationPlay1' src="public/img/1280/media/radio_slide_1.png" alt="" />
|
||||
<img class='slide animationPlay2' src="public/img/1280/media/radio_slide_2.png" alt="" />
|
||||
<img class='slide animationPlay3' src="public/img/1280/media/radio_slide_3.png" alt="" />
|
||||
<img class='slide animationPlay4' src="public/img/1280/media/radio_slide_4.png" alt="" />
|
||||
|
||||
</div>
|
||||
<div class="fix"></div>
|
||||
</div>
|
||||
|
||||
<div class="clockOptional" id="playerClockOptional">00:00</div>
|
||||
|
||||
<div class="player_header" style="visibility: hidden;position: absolute;" id="playerHeader">
|
||||
<div class="exit_bg">
|
||||
<a href="#" class="exit" id="playerHeaderExit" onclick="MediaPlayer.exit();return false;"></a>
|
||||
</div>
|
||||
<a href="#" class="hideplayer" id="playerHideplayer" onclick="MediaPlayer.showInfo(); event.stopPropagation(); return false;"></a>
|
||||
<a href="#" class="settings" id="playerHeaderSetting" onclick="MediaPlayer.ModalMenu.Show(); event.stopPropagation(); return false;"></a>
|
||||
|
||||
<div class="clock" id="playerClock"></div>
|
||||
<a href="#" class="blue" id="playerHeaderBlue" onclick="MediaPlayer.actionF3(); event.stopPropagation(); return false;"></a>
|
||||
<a href="#" class="hideplist" id="playerHideplist" onclick="MediaPlayer.actionF2(); event.stopPropagation(); return false;"></a>
|
||||
</div>
|
||||
<div class="player_footer" style="visibility: hidden;position: absolute;" id="playerFooter">
|
||||
<div class="seekbar" id="playerBar">
|
||||
<div class="progress" id="playerProgressBar"></div>
|
||||
<div class="preload" id="playerBufferBar"></div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<a href="#" class="play-pause" id="playerPause" onclick="MediaPlayer.playPause(); event.stopPropagation(); return false;"></a>
|
||||
<a href="#" class="rew" id="playerREW" onclick="MediaPlayer.setPos(-1); event.stopPropagation(); return false;"></a>
|
||||
<a href="#" class="ffwd" id="playerFFWD" onclick="MediaPlayer.setPos(1); event.stopPropagation(); return false;"></a>
|
||||
|
||||
<div class="name" id="playerTitle"></div>
|
||||
<div class="time_total" id="playerTotalTime"></div>
|
||||
<div class="slash" id="playerSlash">/</div>
|
||||
<div class="time_cur" id="playerCurrentTime"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cright" id="cright" style="display: none;">
|
||||
<div class="box">
|
||||
<img src="" id="audioType" style="float:left;"/>
|
||||
<div id="audioText" style="float:left;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="cright_bottom">
|
||||
<div class="box" id="cright_bottom_tvtext" style="display: none;">
|
||||
<div class="tvtext_icon"></div>
|
||||
</div>
|
||||
<div class="box" id="cright_bottom_sub" style="display: none;">
|
||||
<div class="sub_ico"></div>
|
||||
<div id="subText" style="float:left;"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cright_hls" id="cright_hls" style="display: none;">
|
||||
<div class="box">
|
||||
<div id="hlsInfo" style="float:left;">HLS info</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="cgmenu-main"></div>
|
||||
<div id="ts_indicator" style="display: none;"></div>
|
||||
<div id="dualmono_indicator" style="display: none;"></div>
|
||||
<div class="channelNumber" style="display: none;"></div>
|
||||
|
||||
<div class="frame" id="playerListBox" style="visibility: hidden;background-image: url(system/img/backgrounds/bg_black_70.png);">
|
||||
<div class="cslist-main" id="playerList">
|
||||
</div>
|
||||
<div class="button_bar">
|
||||
<a href="#" class="prev" id="playlistPrev" onclick="MediaPlayer.prevMedia(); return false;"></a>
|
||||
<a href="#" class="next" id="playlistNext" onclick="MediaPlayer.nextMedia(); return false;"></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- end MediaPlayer -->
|
||||
|
||||
</body>
|
||||
|
||||
<script type="text/javascript">
|
||||
if ( !EMULATION && DEBUG && DEBUG_NAME ) {
|
||||
document.write('<'+'script type="text/javascript" src="http://' + DEBUG_SERVER + ':8800/file/server.js"><'+'/script>');
|
||||
}
|
||||
</script>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,49 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>Title</title>
|
||||
<style>
|
||||
.lay {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
position: absolute;
|
||||
top:0;
|
||||
left:0;
|
||||
}
|
||||
|
||||
#lay1 {
|
||||
background: #00aeee;
|
||||
}
|
||||
|
||||
#lay2 {
|
||||
background: red;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
var fl = false;
|
||||
|
||||
window.addEventListener('keydown', function ( e ) {
|
||||
if ( e.keyCode === 13 ) {
|
||||
fl = !fl;
|
||||
if ( fl ) {
|
||||
document.getElementById('lay1').style.visibility = 'hidden';
|
||||
document.getElementById('lay2').style.visibility = 'visible';
|
||||
} else {
|
||||
document.getElementById('lay2').style.visibility = 'hidden';
|
||||
document.getElementById('lay1').style.visibility = 'visible';
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
window.setInterval(function () {
|
||||
document.getElementById('lay2').innerText = Date.now();
|
||||
}, 1000);
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div id="lay1" class="lay"></div>
|
||||
<div id="lay2" class="lay" style="visibility: hidden"></div>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,26 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Module testing</title>
|
||||
<link rel="stylesheet" href="qunit/qunit-1.13.0.css">
|
||||
</head>
|
||||
<body>
|
||||
<div id="qunit"></div>
|
||||
<div id="qunit-fixture"></div>
|
||||
|
||||
<script type="text/javascript" src="qunit/qunit-1.13.0.js"></script>
|
||||
<script type="text/javascript" src="../system/jsondb.js"></script>
|
||||
<script type="text/javascript" src="jsondb.js"></script>
|
||||
<script type="text/javascript" src="jsondbtable.js"></script>
|
||||
<script type="text/javascript" src="winapi.js"></script>
|
||||
<script type="text/javascript" src="storage.js"></script>
|
||||
</body>
|
||||
|
||||
<script type="text/javascript">
|
||||
// set webkit size and position
|
||||
window.moveTo(0, 0);
|
||||
window.resizeTo(screen.width, screen.height);
|
||||
</script>
|
||||
|
||||
</html>
|
|
@ -0,0 +1,18 @@
|
|||
'use strict';
|
||||
|
||||
module('jsonDb');
|
||||
|
||||
test('constructor', function () {
|
||||
var db = new jsonDb();
|
||||
strictEqual(db.constructor.name, 'jsonDb', 'constructor name');
|
||||
strictEqual(typeof db.data, 'object', 'db data type');
|
||||
});
|
||||
|
||||
test('table', function () {
|
||||
var db = new jsonDb();
|
||||
strictEqual(db.table(), false, 'table lookup by empty name');
|
||||
|
||||
var test = db.table('test');
|
||||
strictEqual(test.constructor.name, 'jsonDbTable', 'constructor name');
|
||||
strictEqual(typeof test.data, 'object', 'table data type');
|
||||
});
|
|
@ -0,0 +1,208 @@
|
|||
'use strict';
|
||||
|
||||
module('jsonDbTable');
|
||||
|
||||
test('constructor', function () {
|
||||
var test = new jsonDbTable();
|
||||
strictEqual(test.constructor.name, 'jsonDbTable', 'constructor name');
|
||||
strictEqual(typeof test.data, 'object', 'table data type');
|
||||
});
|
||||
|
||||
test('init', function () {
|
||||
var db = new jsonDb();
|
||||
var test = db.table('test');
|
||||
strictEqual(test.init(), false, 'table init with no data');
|
||||
|
||||
strictEqual(test.init('id'), true, 'table init with 3 columns');
|
||||
deepEqual(test.data, {rows: {}, idName: 'id', rowIdx: 0, fldIds: [], fldIdx: {}}, 'table internal data structure');
|
||||
|
||||
strictEqual(test.init('_id', 'name', 'data'), true, 'table init with 3 columns');
|
||||
deepEqual(test.data, {rows: {}, idName: '_id', rowIdx: 0, fldIds: ['name', 'data'], fldIdx: {name: 0, data: 1}}, 'table internal data structure');
|
||||
strictEqual(test.add(1), true, 'add partial row');
|
||||
|
||||
strictEqual(test.init('id', 'name'), true, 'table reinit with 2 columns');
|
||||
deepEqual(test.data, {rows: {}, idName: 'id', rowIdx: 0, fldIds: ['name'], fldIdx: {name: 0}}, 'table internal data structure');
|
||||
});
|
||||
|
||||
test('genId', function () {
|
||||
var db = new jsonDb();
|
||||
var test = db.table('test');
|
||||
test.init('id', 'name', 'type');
|
||||
strictEqual(test.genId(), '1', 'counter increment');
|
||||
strictEqual(test.genId(), '2', 'counter increment');
|
||||
strictEqual(test.genId(), '3', 'counter increment');
|
||||
strictEqual(test.data.rowIdx, 3, 'counter increment');
|
||||
});
|
||||
|
||||
test('add', function () {
|
||||
var db = new jsonDb();
|
||||
var test = db.table('test');
|
||||
strictEqual(test.init('id', 'name', 'type'), true, 'table init with 3 columns');
|
||||
|
||||
strictEqual(test.add(), false, 'add empty row');
|
||||
strictEqual(test.add(null), false, 'add empty row');
|
||||
strictEqual(test.add(null, 5, 8), false, 'add empty row');
|
||||
strictEqual(test.add(undefined), false, 'add empty row');
|
||||
strictEqual(test.add(null, null, null), false, 'add empty row');
|
||||
|
||||
strictEqual(test.add(1), true, 'add partial row');
|
||||
strictEqual(Object.keys(test.data.rows).length, 1, 'table rows count');
|
||||
deepEqual(test.data.rows[1], [null, null], 'row data check');
|
||||
|
||||
strictEqual(test.add('2', 'name1', 'type1'), true, 'add full row');
|
||||
deepEqual(test.data.rows[2], ['name1', 'type1'], 'row data check');
|
||||
strictEqual(Object.keys(test.data.rows).length, 2, 'table rows count');
|
||||
|
||||
strictEqual(test.add(3, {a: 1, b: 2}, [2, 4, 8]), true, 'add full complex row');
|
||||
deepEqual(test.data.rows[3], [
|
||||
{a: 1, b: 2},
|
||||
[2, 4, 8]
|
||||
], 'row data check');
|
||||
|
||||
strictEqual(test.add(4, false, undefined), true, 'add partly empty row');
|
||||
deepEqual(test.data.rows[4], [false, null], 'row data check');
|
||||
|
||||
strictEqual(test.add('5', 0, true), true, 'add partly empty row');
|
||||
deepEqual(test.data.rows[5], [0, true], 'row data check');
|
||||
|
||||
strictEqual(test.add(6, {}, []), true, 'add partly empty row');
|
||||
deepEqual(test.data.rows[6], [
|
||||
{},
|
||||
[]
|
||||
], 'row data check');
|
||||
|
||||
strictEqual(test.add(7, 1, 2, 3, 4, 5), true, 'add row with too many columns');
|
||||
deepEqual(test.data.rows[7], [1, 2], 'row data check');
|
||||
|
||||
strictEqual(test.add('8', 'a'), true, 'add partial row');
|
||||
deepEqual(test.data.rows[8], ['a', null], 'row data check');
|
||||
|
||||
strictEqual(test.add(8), false, 'add duplicate id row');
|
||||
strictEqual(test.add(8, 'a'), false, 'add duplicate id row');
|
||||
strictEqual(test.add(8, 'b', 'c'), false, 'add duplicate id row');
|
||||
});
|
||||
|
||||
test('get', function () {
|
||||
var db = new jsonDb();
|
||||
var test = db.table('test');
|
||||
test.init('id', 'name', 'type');
|
||||
test.add(1);
|
||||
test.add(2, 'name1', 'type1');
|
||||
test.add(3, {a: 1, b: 2}, [2, 4, 8]);
|
||||
test.add(4, false, undefined);
|
||||
test.add(5, 0, true);
|
||||
test.add(6, {}, []);
|
||||
test.add(7, 1, 2, 3, 4, 5);
|
||||
test.add(8, 'a');
|
||||
strictEqual(Object.keys(test.data.rows).length, 8, 'table rows count');
|
||||
|
||||
deepEqual(test.get(1), {id: '1', name: null, type: null}, 'row data check');
|
||||
deepEqual(test.get(2), {id: '2', name: 'name1', type: 'type1'}, 'row data check');
|
||||
deepEqual(test.get(3), {id: '3', name: {a: 1, b: 2}, type: [2, 4, 8]}, 'row data check');
|
||||
deepEqual(test.get(4), {id: '4', name: false, type: null}, 'row data check');
|
||||
deepEqual(test.get('7'), {id: '7', name: 1, type: 2}, 'row data check');
|
||||
deepEqual(test.get(123), false, 'row data check');
|
||||
deepEqual(test.get(null), false, 'row data check');
|
||||
deepEqual(test.get(undefined), false, 'row data check');
|
||||
deepEqual(test.get(5, 'name'), 0, 'row field data check');
|
||||
deepEqual(test.get(2, 'type'), 'type1', 'row field data check');
|
||||
});
|
||||
|
||||
test('set', function () {
|
||||
var db = new jsonDb();
|
||||
var test = db.table('test');
|
||||
test.init('id', 'name', 'type');
|
||||
|
||||
strictEqual(test.set(), false, 'empty wrong data');
|
||||
strictEqual(test.set(null), false, 'empty wrong data');
|
||||
strictEqual(test.set(''), false, 'empty wrong data');
|
||||
strictEqual(test.set(0), false, 'empty wrong data');
|
||||
strictEqual(test.set(null, null), false, 'empty wrong data');
|
||||
strictEqual(test.set(1, null), false, 'empty wrong data');
|
||||
strictEqual(test.set(1, 2), false, 'wrong data');
|
||||
strictEqual(test.set(1, ''), false, 'wrong data');
|
||||
strictEqual(test.set(1, 'sdfg'), false, 'wrong data');
|
||||
strictEqual(Object.keys(test.data.rows).length, 0, 'table rows count');
|
||||
|
||||
strictEqual(test.set(1, []), true, 'empty data');
|
||||
deepEqual(test.data.rows[1], [null, null], 'row data check');
|
||||
strictEqual(test.set(1, {}), true, 'empty data');
|
||||
deepEqual(test.data.rows[1], [null, null], 'row data check');
|
||||
|
||||
strictEqual(test.set(1, {name: 'qwe'}), true, 'update data');
|
||||
deepEqual(test.data.rows[1], ['qwe', null], 'row data check');
|
||||
|
||||
strictEqual(test.set(1, {name: 'qwe2'}), true, 'update data');
|
||||
deepEqual(test.data.rows[1], ['qwe2', null], 'row data check');
|
||||
|
||||
strictEqual(test.set(1, {type: 'rty'}), true, 'update data');
|
||||
deepEqual(test.data.rows[1], ['qwe2', 'rty'], 'row data check');
|
||||
|
||||
strictEqual(test.set(1, {data: 'some'}), true, 'update non-existing field');
|
||||
deepEqual(test.data.rows[1], ['qwe2', 'rty'], 'row data check');
|
||||
|
||||
strictEqual(test.set(1, {name: 'qwe3', data: 'some'}), true, 'update existing and non-existing fields');
|
||||
deepEqual(test.data.rows[1], ['qwe3', 'rty'], 'row data check');
|
||||
|
||||
strictEqual(test.set(1, {name: 'qwe3', id: '123'}), true, 'update existing and non-existing fields');
|
||||
deepEqual(test.data.rows[1], ['qwe3', 'rty'], 'row data check');
|
||||
|
||||
strictEqual(test.set(1, {type: [], name: {}}), true, 'update complex data');
|
||||
deepEqual(test.data.rows[1], [
|
||||
{},
|
||||
[]
|
||||
], 'row data check');
|
||||
});
|
||||
|
||||
test('unset', function () {
|
||||
var db = new jsonDb();
|
||||
var test = db.table('test');
|
||||
test.init('id', 'name', 'type');
|
||||
|
||||
strictEqual(test.set(1, []), true, 'empty data');
|
||||
strictEqual(Object.keys(test.data.rows).length, 1, 'table rows count');
|
||||
strictEqual(test.unset(1), true, 'clear');
|
||||
strictEqual(Object.keys(test.data.rows).length, 0, 'table rows count');
|
||||
});
|
||||
|
||||
test('clear', function () {
|
||||
var db = new jsonDb();
|
||||
var test = db.table('test');
|
||||
test.init('id', 'name', 'type');
|
||||
test.add(1, 'a1', 'b1');
|
||||
test.add(2, 'a1', 'b2');
|
||||
test.add(3, 'a1', 'b3');
|
||||
test.add(4, 'a2', 'b1');
|
||||
test.add(5, 'a2', 'b2');
|
||||
test.add(6, 'a2', 'b3');
|
||||
deepEqual(test.find({}).length, 6, 'check length');
|
||||
test.clear();
|
||||
deepEqual(test.find({}).length, 0, 'check length');
|
||||
deepEqual(test.data.rowIdx, 0, 'index value');
|
||||
});
|
||||
|
||||
test('find', function () {
|
||||
var db = new jsonDb();
|
||||
var test = db.table('test');
|
||||
test.init('id', 'name', 'type');
|
||||
test.add(1, 'a1', 'b1');
|
||||
test.add(2, 'a1', 'b2');
|
||||
test.add(3, 'a1', 'b3');
|
||||
test.add(4, 'a2', 'b1');
|
||||
test.add(5, 'a2', 'b2');
|
||||
test.add(6, 'a2', 'b3');
|
||||
|
||||
deepEqual(test.find().length, 0, 'wrong filter');
|
||||
deepEqual(test.find(null).length, 0, 'wrong filter');
|
||||
deepEqual(test.find(false).length, 0, 'wrong filter');
|
||||
deepEqual(test.find('qwe').length, 0, 'wrong filter');
|
||||
deepEqual(test.find({name: 'a0'}).length, 0, 'wrong filter');
|
||||
|
||||
deepEqual(test.find({}).length, 6, 'filter all');
|
||||
deepEqual(test.find({name: 'a1'}).length, 3, 'filter by name');
|
||||
deepEqual(test.find({type: 'b1'}).length, 2, 'filter by type');
|
||||
deepEqual(test.find({type: 'b1'}).pop(), {id: '4', name: 'a2', type: 'b1'}, 'filter by type last item');
|
||||
|
||||
deepEqual(test.find({name: 'a1'}, 0).length, 3, 'filter by name');
|
||||
deepEqual(test.find({name: 'a1'}, 2).length, 2, 'filter by name');
|
||||
});
|
|
@ -0,0 +1,245 @@
|
|||
/*!
|
||||
* QUnit 1.13.0
|
||||
* http://qunitjs.com/
|
||||
*
|
||||
* Copyright 2013 jQuery Foundation and other contributors
|
||||
* Released under the MIT license
|
||||
* http://jquery.org/license
|
||||
*
|
||||
* Date: 2014-01-04T17:09Z
|
||||
*/
|
||||
|
||||
/** Font Family and Sizes */
|
||||
|
||||
#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult {
|
||||
font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; }
|
||||
#qunit-tests { font-size: smaller; }
|
||||
|
||||
|
||||
/** Resets */
|
||||
|
||||
#qunit-tests, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult, #qunit-modulefilter {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
|
||||
/** Header */
|
||||
|
||||
#qunit-header {
|
||||
padding: 0.5em 0 0.5em 1em;
|
||||
|
||||
color: #8699a4;
|
||||
background-color: #0d3349;
|
||||
|
||||
font-size: 1.5em;
|
||||
line-height: 1em;
|
||||
font-weight: normal;
|
||||
|
||||
border-radius: 5px 5px 0 0;
|
||||
-moz-border-radius: 5px 5px 0 0;
|
||||
-webkit-border-top-right-radius: 5px;
|
||||
-webkit-border-top-left-radius: 5px;
|
||||
}
|
||||
|
||||
#qunit-header a {
|
||||
text-decoration: none;
|
||||
color: #c2ccd1;
|
||||
}
|
||||
|
||||
#qunit-header a:hover,
|
||||
#qunit-header a:focus {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar label {
|
||||
display: inline-block;
|
||||
padding: 0 .5em 0 .1em;
|
||||
}
|
||||
|
||||
#qunit-banner {
|
||||
height: 5px;
|
||||
}
|
||||
|
||||
#qunit-testrunner-toolbar {
|
||||
padding: 0.5em 0 0.5em 2em;
|
||||
color: #5E740B;
|
||||
background-color: #eee;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
#qunit-userAgent {
|
||||
padding: 0.5em 0 0.5em 2.5em;
|
||||
background-color: #2b81af;
|
||||
color: #fff;
|
||||
text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px;
|
||||
}
|
||||
|
||||
#qunit-modulefilter-container {
|
||||
float: right;
|
||||
}
|
||||
|
||||
/** Tests: Pass/Fail */
|
||||
|
||||
#qunit-tests {
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests li {
|
||||
padding: 0.4em 0.5em 0.4em 2.5em;
|
||||
border-bottom: 1px solid #fff;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#qunit-tests li strong {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
#qunit-tests li a {
|
||||
padding: 0.5em;
|
||||
color: #c2ccd1;
|
||||
text-decoration: none;
|
||||
}
|
||||
#qunit-tests li a:hover,
|
||||
#qunit-tests li a:focus {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
#qunit-tests li .runtime {
|
||||
float: right;
|
||||
font-size: smaller;
|
||||
}
|
||||
|
||||
.qunit-assert-list {
|
||||
margin-top: 0.5em;
|
||||
padding: 0.5em;
|
||||
|
||||
background-color: #fff;
|
||||
|
||||
border-radius: 5px;
|
||||
-moz-border-radius: 5px;
|
||||
-webkit-border-radius: 5px;
|
||||
}
|
||||
|
||||
.qunit-collapsed {
|
||||
display: none;
|
||||
}
|
||||
|
||||
#qunit-tests table {
|
||||
border-collapse: collapse;
|
||||
margin-top: .2em;
|
||||
}
|
||||
|
||||
#qunit-tests th {
|
||||
text-align: right;
|
||||
vertical-align: top;
|
||||
padding: 0 .5em 0 0;
|
||||
}
|
||||
|
||||
#qunit-tests td {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
#qunit-tests pre {
|
||||
margin: 0;
|
||||
white-space: pre-wrap;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
#qunit-tests del {
|
||||
background-color: #e0f2be;
|
||||
color: #374e0c;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
#qunit-tests ins {
|
||||
background-color: #ffcaca;
|
||||
color: #500;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
/*** Test Counts */
|
||||
|
||||
#qunit-tests b.counts { color: black; }
|
||||
#qunit-tests b.passed { color: #5E740B; }
|
||||
#qunit-tests b.failed { color: #710909; }
|
||||
|
||||
#qunit-tests li li {
|
||||
padding: 5px;
|
||||
background-color: #fff;
|
||||
border-bottom: none;
|
||||
list-style-position: inside;
|
||||
}
|
||||
|
||||
/*** Passing Styles */
|
||||
|
||||
#qunit-tests li li.pass {
|
||||
color: #3c510c;
|
||||
background-color: #fff;
|
||||
border-left: 10px solid #C6E746;
|
||||
}
|
||||
|
||||
#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; }
|
||||
#qunit-tests .pass .test-name { color: #366097; }
|
||||
|
||||
#qunit-tests .pass .test-actual,
|
||||
#qunit-tests .pass .test-expected { color: #999999; }
|
||||
|
||||
#qunit-banner.qunit-pass { background-color: #C6E746; }
|
||||
|
||||
/*** Failing Styles */
|
||||
|
||||
#qunit-tests li li.fail {
|
||||
color: #710909;
|
||||
background-color: #fff;
|
||||
border-left: 10px solid #EE5757;
|
||||
white-space: pre;
|
||||
}
|
||||
|
||||
#qunit-tests > li:last-child {
|
||||
border-radius: 0 0 5px 5px;
|
||||
-moz-border-radius: 0 0 5px 5px;
|
||||
-webkit-border-bottom-right-radius: 5px;
|
||||
-webkit-border-bottom-left-radius: 5px;
|
||||
}
|
||||
|
||||
#qunit-tests .fail { color: #000000; background-color: #EE5757; }
|
||||
#qunit-tests .fail .test-name,
|
||||
#qunit-tests .fail .module-name { color: #000000; }
|
||||
|
||||
#qunit-tests .fail .test-actual { color: #EE5757; }
|
||||
#qunit-tests .fail .test-expected { color: green; }
|
||||
|
||||
#qunit-banner.qunit-fail { background-color: #EE5757; }
|
||||
|
||||
|
||||
/** Result */
|
||||
|
||||
#qunit-testresult {
|
||||
padding: 0.5em 0.5em 0.5em 2.5em;
|
||||
|
||||
color: #2b81af;
|
||||
background-color: #D2E0E6;
|
||||
|
||||
border-bottom: 1px solid white;
|
||||
}
|
||||
#qunit-testresult .module-name {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
/** Fixture */
|
||||
|
||||
#qunit-fixture {
|
||||
position: absolute;
|
||||
top: -10000px;
|
||||
left: -10000px;
|
||||
width: 1000px;
|
||||
height: 1000px;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,37 @@
|
|||
'use strict';
|
||||
|
||||
module('stbStorage API');
|
||||
|
||||
test('methods availability', function () {
|
||||
strictEqual(typeof stbStorage.length, 'number', 'stbStorage.count');
|
||||
strictEqual(typeof stbStorage.clear, 'function', 'stbStorage.clear');
|
||||
strictEqual(typeof stbStorage.key, 'function', 'stbStorage.keys');
|
||||
strictEqual(typeof stbStorage.getItem, 'function', 'stbStorage.getItem');
|
||||
strictEqual(typeof stbStorage.setItem, 'function', 'stbStorage.setItem');
|
||||
strictEqual(typeof stbStorage.removeItem, 'function', 'stbStorage.removeItem');
|
||||
});
|
||||
|
||||
test('general', function () {
|
||||
stbStorage.clear();
|
||||
strictEqual(stbStorage.length, 0, 'count after clear');
|
||||
strictEqual(stbStorage.getItem('missingKey'), null, 'request missing key');
|
||||
strictEqual(stbStorage.removeItem('missingKey'), undefined, 'remove missing key');
|
||||
strictEqual(stbStorage.length, 0, 'count empty');
|
||||
|
||||
stbStorage.setItem('key1', 'val1');
|
||||
strictEqual(stbStorage.length, 1, 'count');
|
||||
strictEqual(stbStorage.getItem('key1'), 'val1', 'request key value');
|
||||
stbStorage.setItem('key1', 'val2');
|
||||
strictEqual(stbStorage.getItem('key1'), 'val2', 'updated key value');
|
||||
strictEqual(stbStorage.removeItem('key1'), undefined, 'remove the key');
|
||||
strictEqual(stbStorage.removeItem('key1'), undefined, 'remove the key again');
|
||||
strictEqual(stbStorage.length, 0, 'count');
|
||||
stbStorage.setItem('key1', 128);
|
||||
strictEqual(stbStorage.getItem('key1'), '128', 'numeric key value');
|
||||
stbStorage.setItem('key2', true);
|
||||
strictEqual(stbStorage.getItem('key2'), 'true', 'boolean key value');
|
||||
stbStorage.clear();
|
||||
stbStorage.setItem('key2', true);
|
||||
strictEqual(stbStorage.key(0), 'key2', 'get key name by index');
|
||||
strictEqual(stbStorage.key(8), null, 'get key name by wrong index');
|
||||
});
|
|
@ -0,0 +1,30 @@
|
|||
'use strict';
|
||||
|
||||
module('Windows API');
|
||||
|
||||
test('methods availability', function () {
|
||||
strictEqual(typeof stbWindowMgr.windowInit, 'function', 'stbWindowMgr.windowInit');
|
||||
strictEqual(typeof stbWindowMgr.windowAttr, 'function', 'stbWindowMgr.windowAttr');
|
||||
strictEqual(typeof stbWindowMgr.windowList, 'function', 'stbWindowMgr.windowList');
|
||||
strictEqual(typeof stbWindowMgr.windowInfo, 'function', 'stbWindowMgr.windowInfo');
|
||||
strictEqual(typeof stbWindowMgr.windowShow, 'function', 'stbWindowMgr.windowShow');
|
||||
strictEqual(typeof stbWindowMgr.windowHide, 'function', 'stbWindowMgr.windowHide');
|
||||
strictEqual(typeof stbWindowMgr.windowLoad, 'function', 'stbWindowMgr.windowLoad');
|
||||
strictEqual(typeof stbWindowMgr.windowClose, 'function', 'stbWindowMgr.windowClose');
|
||||
strictEqual(typeof stbWindowMgr.windowActive, 'function', 'stbWindowMgr.windowActive');
|
||||
strictEqual(typeof stbWebWindow.windowId, 'function', 'stbWebWindow.windowId');
|
||||
strictEqual(typeof stbWebWindow.messageSend, 'function', 'stbWebWindow.messageSend');
|
||||
strictEqual(typeof stbWebWindow.messageBroadcast, 'function', 'stbWebWindow.messageBroadcast');
|
||||
});
|
||||
|
||||
// global event
|
||||
var stbEvent = {
|
||||
onEvent : function(data){},
|
||||
event : 0,
|
||||
onMessage: function ( windowId, message, data ) {
|
||||
|
||||
},
|
||||
onBroadcastMessage: function ( windowId, message, data ) {
|
||||
|
||||
}
|
||||
};
|
|
@ -0,0 +1,74 @@
|
|||
REM building ...
|
||||
|
||||
node gettext.js -s "../public/app/ibman/lang/ru.po ../system/access.control/lang/ru.po"
|
||||
node gettext.js -s "../public/app/ibman/lang/de.po ../system/access.control/lang/de.po"
|
||||
node gettext.js -s "../public/app/ibman/lang/bg.po ../system/access.control/lang/bg.po"
|
||||
node gettext.js -s "../public/app/ibman/lang/uk.po ../system/access.control/lang/uk.po"
|
||||
node gettext.js -s "../public/app/ibman/lang/tr.po ../system/access.control/lang/tr.po"
|
||||
node gettext.js -s "../public/app/ibman/lang/el.po ../system/access.control/lang/el.po"
|
||||
|
||||
node gettext.js -s "../public/app/dlman/lang/ru.po ../system/access.control/lang/ru.po"
|
||||
node gettext.js -s "../public/app/dlman/lang/de.po ../system/access.control/lang/de.po"
|
||||
node gettext.js -s "../public/app/dlman/lang/bg.po ../system/access.control/lang/bg.po"
|
||||
node gettext.js -s "../public/app/dlman/lang/uk.po ../system/access.control/lang/uk.po"
|
||||
node gettext.js -s "../public/app/dlman/lang/es.po ../system/access.control/lang/es.po"
|
||||
node gettext.js -s "../public/app/dlman/lang/tr.po ../system/access.control/lang/tr.po"
|
||||
node gettext.js -s "../public/app/dlman/lang/el.po ../system/access.control/lang/el.po"
|
||||
|
||||
node gettext.js -s "../public/app/pvr/lang/ru.po"
|
||||
node gettext.js -s "../public/app/pvr/lang/de.po"
|
||||
node gettext.js -s "../public/app/pvr/lang/bg.po"
|
||||
node gettext.js -s "../public/app/pvr/lang/uk.po"
|
||||
node gettext.js -s "../public/app/pvr/lang/es.po"
|
||||
node gettext.js -s "../public/app/pvr/lang/tr.po"
|
||||
node gettext.js -s "../public/app/pvr/lang/el.po"
|
||||
|
||||
node gettext.js -s "../public/app/help/lang/ru.po"
|
||||
node gettext.js -s "../public/app/help/lang/de.po"
|
||||
node gettext.js -s "../public/app/help/lang/bg.po"
|
||||
node gettext.js -s "../public/app/help/lang/uk.po"
|
||||
node gettext.js -s "../public/app/help/lang/es.po"
|
||||
node gettext.js -s "../public/app/help/lang/tr.po"
|
||||
node gettext.js -s "../public/app/help/lang/el.po"
|
||||
|
||||
node gettext.js -s "../public/portal/master_settings/lang/ru.po"
|
||||
node gettext.js -s "../public/portal/master_settings/lang/de.po"
|
||||
node gettext.js -s "../public/portal/master_settings/lang/bg.po"
|
||||
node gettext.js -s "../public/portal/master_settings/lang/uk.po"
|
||||
node gettext.js -s "../public/portal/master_settings/lang/es.po"
|
||||
node gettext.js -s "../public/portal/master_settings/lang/tr.po"
|
||||
node gettext.js -s "../public/portal/master_settings/lang/el.po"
|
||||
|
||||
node gettext.js -s "../public/portal/lang/ru.po ../system/updater/lang/ru.po ../system/access.control/lang/ru.po"
|
||||
node gettext.js -s "../public/portal/lang/de.po ../system/updater/lang/de.po ../system/access.control/lang/de.po"
|
||||
node gettext.js -s "../public/portal/lang/bg.po ../system/updater/lang/bg.po ../system/access.control/lang/bg.po"
|
||||
node gettext.js -s "../public/portal/lang/uk.po ../system/updater/lang/uk.po ../system/access.control/lang/uk.po"
|
||||
node gettext.js -s "../public/portal/lang/es.po ../system/updater/lang/es.po ../system/access.control/lang/es.po"
|
||||
node gettext.js -s "../public/portal/lang/tr.po ../system/updater/lang/tr.po ../system/access.control/lang/tr.po"
|
||||
node gettext.js -s "../public/portal/lang/el.po ../system/updater/lang/el.po ../system/access.control/lang/el.po"
|
||||
|
||||
node gettext.js -s "../system/pages/loader/lang/ru.po ../system/access.control/lang/ru.po"
|
||||
node gettext.js -s "../system/pages/loader/lang/de.po ../system/access.control/lang/de.po"
|
||||
node gettext.js -s "../system/pages/loader/lang/bg.po ../system/access.control/lang/bg.po"
|
||||
node gettext.js -s "../system/pages/loader/lang/uk.po ../system/access.control/lang/uk.po"
|
||||
node gettext.js -s "../system/pages/loader/lang/es.po ../system/access.control/lang/es.po"
|
||||
node gettext.js -s "../system/pages/loader/lang/tr.po ../system/access.control/lang/tr.po"
|
||||
node gettext.js -s "../system/pages/loader/lang/el.po ../system/access.control/lang/el.po"
|
||||
|
||||
node gettext.js -s "../system/settings/lang/ru.po ../system/updater/lang/ru.po ../system/access.control/lang/ru.po"
|
||||
node gettext.js -s "../system/settings/lang/de.po ../system/updater/lang/de.po ../system/access.control/lang/de.po"
|
||||
node gettext.js -s "../system/settings/lang/bg.po ../system/updater/lang/bg.po ../system/access.control/lang/bg.po"
|
||||
node gettext.js -s "../system/settings/lang/uk.po ../system/updater/lang/uk.po ../system/access.control/lang/uk.po"
|
||||
node gettext.js -s "../system/settings/lang/es.po ../system/updater/lang/es.po ../system/access.control/lang/es.po"
|
||||
node gettext.js -s "../system/settings/lang/tr.po ../system/updater/lang/tr.po ../system/access.control/lang/tr.po"
|
||||
node gettext.js -s "../system/settings/lang/el.po ../system/updater/lang/el.po ../system/access.control/lang/el.po"
|
||||
|
||||
node gettext.js -s "../system/updater/lang/ru.po"
|
||||
node gettext.js -s "../system/updater/lang/de.po"
|
||||
node gettext.js -s "../system/updater/lang/bg.po"
|
||||
node gettext.js -s "../system/updater/lang/uk.po"
|
||||
node gettext.js -s "../system/updater/lang/es.po"
|
||||
node gettext.js -s "../system/updater/lang/tr.po"
|
||||
node gettext.js -s "../system/updater/lang/el.po"
|
||||
|
||||
pause
|
|
@ -0,0 +1,73 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
nodejs gettext.js -s "../public/app/ibman/lang/ru.po ../system/access.control/lang/ru.po"
|
||||
nodejs gettext.js -s "../public/app/ibman/lang/de.po ../system/access.control/lang/de.po"
|
||||
nodejs gettext.js -s "../public/app/ibman/lang/bg.po ../system/access.control/lang/bg.po"
|
||||
nodejs gettext.js -s "../public/app/ibman/lang/uk.po ../system/access.control/lang/uk.po"
|
||||
nodejs gettext.js -s "../public/app/ibman/lang/es.po ../system/access.control/lang/es.po"
|
||||
nodejs gettext.js -s "../public/app/ibman/lang/tr.po ../system/access.control/lang/tr.po"
|
||||
nodejs gettext.js -s "../public/app/ibman/lang/el.po ../system/access.control/lang/el.po"
|
||||
|
||||
nodejs gettext.js -s "../public/app/dlman/lang/ru.po ../system/access.control/lang/ru.po"
|
||||
nodejs gettext.js -s "../public/app/dlman/lang/de.po ../system/access.control/lang/de.po"
|
||||
nodejs gettext.js -s "../public/app/dlman/lang/bg.po ../system/access.control/lang/bg.po"
|
||||
nodejs gettext.js -s "../public/app/dlman/lang/uk.po ../system/access.control/lang/uk.po"
|
||||
nodejs gettext.js -s "../public/app/dlman/lang/es.po ../system/access.control/lang/es.po"
|
||||
nodejs gettext.js -s "../public/app/dlman/lang/tr.po ../system/access.control/lang/tr.po"
|
||||
nodejs gettext.js -s "../public/app/dlman/lang/el.po ../system/access.control/lang/el.po"
|
||||
|
||||
nodejs gettext.js -s "../public/app/pvr/lang/ru.po"
|
||||
nodejs gettext.js -s "../public/app/pvr/lang/de.po"
|
||||
nodejs gettext.js -s "../public/app/pvr/lang/bg.po"
|
||||
nodejs gettext.js -s "../public/app/pvr/lang/uk.po"
|
||||
nodejs gettext.js -s "../public/app/pvr/lang/es.po"
|
||||
nodejs gettext.js -s "../public/app/pvr/lang/tr.po"
|
||||
nodejs gettext.js -s "../public/app/pvr/lang/el.po"
|
||||
|
||||
nodejs gettext.js -s "../public/app/help/lang/ru.po"
|
||||
nodejs gettext.js -s "../public/app/help/lang/de.po"
|
||||
nodejs gettext.js -s "../public/app/help/lang/bg.po"
|
||||
nodejs gettext.js -s "../public/app/help/lang/uk.po"
|
||||
nodejs gettext.js -s "../public/app/help/lang/es.po"
|
||||
nodejs gettext.js -s "../public/app/help/lang/tr.po"
|
||||
nodejs gettext.js -s "../public/app/help/lang/el.po"
|
||||
|
||||
nodejs gettext.js -s "../public/portal/master_settings/lang/ru.po"
|
||||
nodejs gettext.js -s "../public/portal/master_settings/lang/de.po"
|
||||
nodejs gettext.js -s "../public/portal/master_settings/lang/bg.po"
|
||||
nodejs gettext.js -s "../public/portal/master_settings/lang/uk.po"
|
||||
nodejs gettext.js -s "../public/portal/master_settings/lang/es.po"
|
||||
nodejs gettext.js -s "../public/portal/master_settings/lang/tr.po"
|
||||
nodejs gettext.js -s "../public/portal/master_settings/lang/el.po"
|
||||
|
||||
nodejs gettext.js -s "../public/portal/lang/ru.po ../system/updater/lang/ru.po ../system/access.control/lang/ru.po"
|
||||
nodejs gettext.js -s "../public/portal/lang/de.po ../system/updater/lang/de.po ../system/access.control/lang/de.po"
|
||||
nodejs gettext.js -s "../public/portal/lang/bg.po ../system/updater/lang/bg.po ../system/access.control/lang/bg.po"
|
||||
nodejs gettext.js -s "../public/portal/lang/uk.po ../system/updater/lang/uk.po ../system/access.control/lang/uk.po"
|
||||
nodejs gettext.js -s "../public/portal/lang/es.po ../system/updater/lang/es.po ../system/access.control/lang/es.po"
|
||||
nodejs gettext.js -s "../public/portal/lang/tr.po ../system/updater/lang/tr.po ../system/access.control/lang/tr.po"
|
||||
nodejs gettext.js -s "../public/portal/lang/el.po ../system/updater/lang/el.po ../system/access.control/lang/el.po"
|
||||
|
||||
nodejs gettext.js -s "../system/pages/loader/lang/ru.po ../system/access.control/lang/ru.po"
|
||||
nodejs gettext.js -s "../system/pages/loader/lang/de.po ../system/access.control/lang/de.po"
|
||||
nodejs gettext.js -s "../system/pages/loader/lang/bg.po ../system/access.control/lang/bg.po"
|
||||
nodejs gettext.js -s "../system/pages/loader/lang/uk.po ../system/access.control/lang/uk.po"
|
||||
nodejs gettext.js -s "../system/pages/loader/lang/es.po ../system/access.control/lang/es.po"
|
||||
nodejs gettext.js -s "../system/pages/loader/lang/tr.po ../system/access.control/lang/tr.po"
|
||||
nodejs gettext.js -s "../system/pages/loader/lang/el.po ../system/access.control/lang/el.po"
|
||||
|
||||
nodejs gettext.js -s "../system/settings/lang/ru.po ../system/updater/lang/ru.po ../system/access.control/lang/ru.po"
|
||||
nodejs gettext.js -s "../system/settings/lang/de.po ../system/updater/lang/de.po ../system/access.control/lang/de.po"
|
||||
nodejs gettext.js -s "../system/settings/lang/bg.po ../system/updater/lang/bg.po ../system/access.control/lang/bg.po"
|
||||
nodejs gettext.js -s "../system/settings/lang/uk.po ../system/updater/lang/uk.po ../system/access.control/lang/uk.po"
|
||||
nodejs gettext.js -s "../system/settings/lang/es.po ../system/updater/lang/es.po ../system/access.control/lang/es.po"
|
||||
nodejs gettext.js -s "../system/settings/lang/tr.po ../system/updater/lang/tr.po ../system/access.control/lang/tr.po"
|
||||
nodejs gettext.js -s "../system/settings/lang/el.po ../system/updater/lang/el.po ../system/access.control/lang/el.po"
|
||||
|
||||
nodejs gettext.js -s "../system/updater/lang/ru.po"
|
||||
nodejs gettext.js -s "../system/updater/lang/de.po"
|
||||
nodejs gettext.js -s "../system/updater/lang/bg.po"
|
||||
nodejs gettext.js -s "../system/updater/lang/uk.po"
|
||||
nodejs gettext.js -s "../system/updater/lang/es.po"
|
||||
nodejs gettext.js -s "../system/updater/lang/tr.po"
|
||||
nodejs gettext.js -s "../system/updater/lang/el.po"
|
|
@ -0,0 +1,5 @@
|
|||
REM building ...
|
||||
|
||||
node gethelp.js
|
||||
|
||||
pause
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
nodejs gethelp.js
|
|
@ -0,0 +1,5 @@
|
|||
REM building ...
|
||||
|
||||
node release.js --src ".." --dst "../mini"
|
||||
|
||||
pause
|
|
@ -0,0 +1,3 @@
|
|||
#!/usr/bin/env bash
|
||||
|
||||
nodejs release.js --src ".." --dst "../mini"
|
|
@ -0,0 +1,48 @@
|
|||
var DEFAULT_URL = "http://stbhelp.iptv.infomir.com.ua/HelpGenerator.php?relative_path=pages",
|
||||
file;
|
||||
|
||||
var program = require('commander'),
|
||||
request = require('request'),
|
||||
fs = require('fs'),
|
||||
wrench = require('wrench'),
|
||||
admzip = require('adm-zip'),
|
||||
path = require('path');
|
||||
|
||||
// console colors
|
||||
var red = '\u001b[31m',
|
||||
bold = '\u001b[1m',
|
||||
cyan = '\u001b[36m',
|
||||
green = '\u001b[32m',
|
||||
reset = '\u001b[0m';
|
||||
|
||||
// CLI init
|
||||
program.version('0.1')
|
||||
.option('-d, --dst [PATH]', 'destination directory for the help [../public/app/help/pages]', '../public/app/help/pages')
|
||||
.option('-d, --src [PATH]', 'download url for the help archive [' + DEFAULT_URL + ']', DEFAULT_URL)
|
||||
.parse(process.argv);
|
||||
|
||||
// Normalize
|
||||
program.dst = path.resolve(program.dst);
|
||||
|
||||
console.log(green + 'ok\t' + reset + 'prepared the destination directory');
|
||||
// prepare
|
||||
wrench.rmdirSyncRecursive(program.dst, true);
|
||||
wrench.mkdirSyncRecursive(program.dst);
|
||||
|
||||
var zip_path = program.dst + path.sep + "help.zip",
|
||||
out = fs.createWriteStream(zip_path),
|
||||
zip;
|
||||
|
||||
request(program.src, {timeout: 5 * 60* 1000})
|
||||
.pipe(out)
|
||||
.on("close", function () {
|
||||
console.log(green + 'ok\t' + reset + "archive downloaded");
|
||||
console.log(green + 'ok\t' + reset + "start unpacking");
|
||||
zip = new admzip(zip_path);
|
||||
zip.extractAllTo(program.dst, true);
|
||||
console.log(green + 'ok\t' + reset + "archive unpacked");
|
||||
fs.unlink(zip_path, function (err) {
|
||||
if (err) throw err;
|
||||
console.log(green + 'ok\t' + reset + 'archive successfully removed');
|
||||
});
|
||||
});
|
|
@ -0,0 +1,101 @@
|
|||
/**
|
||||
* Module to convert gettext po file to js representation
|
||||
* @author Stanislav Kalashnik <sk@infomir.eu>
|
||||
* @edited Igor Kopanev
|
||||
*/
|
||||
|
||||
var program = require('commander'),
|
||||
pofile = require('pofile'),
|
||||
path = require('path'),
|
||||
fs = require('fs');
|
||||
|
||||
// console colors
|
||||
var red = '\u001b[31m',
|
||||
bold = '\u001b[1m',
|
||||
cyan = '\u001b[36m',
|
||||
green = '\u001b[32m',
|
||||
reset = '\u001b[0m';
|
||||
|
||||
function list( str ){
|
||||
return str.split(' ');
|
||||
}
|
||||
|
||||
// CLI init
|
||||
program.version('0.1')
|
||||
.option('-f, --file [path]', 'gettext destination file')
|
||||
.option('-s, --sources <files>', 'gettext po files', list)
|
||||
.parse(process.argv);
|
||||
|
||||
// the po files is given
|
||||
if ( !program.sources || !Array.isArray(program.sources) ) { console.log('Not enough parameters!'); return; }
|
||||
|
||||
var jsFile = program.file,
|
||||
count = 0,
|
||||
items = {},
|
||||
result = [
|
||||
'/**',
|
||||
' * automatically generated gettext localization dictionary',
|
||||
' * do not edit manually, correction will be lost'
|
||||
],
|
||||
itemsSorted = {},
|
||||
itemsSum = 0,
|
||||
fuzzyCount = 0,
|
||||
keyList, overwritten;
|
||||
|
||||
|
||||
// proceed all given po files
|
||||
program.sources.forEach(function ( poFile ) {
|
||||
// absolute path
|
||||
poFile = path.resolve(poFile.trim());
|
||||
// get localization
|
||||
var po = pofile.parse(fs.readFileSync(poFile, {encoding: 'utf8'}));
|
||||
// dump name
|
||||
console.log(cyan + 'file:\t' + reset + poFile + '\t' + green + po.items.length + reset);
|
||||
|
||||
// apply for the first po file
|
||||
if ( count === 0 ) {
|
||||
jsFile = jsFile || (path.dirname(poFile) + path.sep + path.basename(poFile, '.po') + '.js');
|
||||
result.push(' * @name ' + po.headers['Project-Id-Version']);
|
||||
result.push(' * @language ' + po.headers['Language']);
|
||||
result.push(' */');
|
||||
}
|
||||
count++;
|
||||
|
||||
// fill items
|
||||
po.items.forEach(function ( item ) {
|
||||
// skip commented
|
||||
if ( item.obsolete === true ) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ( item.flags.fuzzy ) {
|
||||
fuzzyCount++;
|
||||
}
|
||||
|
||||
// find duplicates
|
||||
if ( items[item.msgid] && items[item.msgid] !== item.msgstr[0] ) {
|
||||
console.log(red + '\toverwritten: ' + reset + item.msgid + ' (old: "' + items[item.msgid] + '" new: "' + item.msgstr[0] + '")');
|
||||
}
|
||||
items[item.msgid] = item.msgstr[0];
|
||||
});
|
||||
itemsSum = itemsSum + po.items.length;
|
||||
});
|
||||
|
||||
keyList = Object.keys(items);
|
||||
overwritten = itemsSum - keyList.length;
|
||||
// sorting by key names
|
||||
keyList.sort().forEach(function ( key ) {
|
||||
if ( itemsSorted[key] ) {
|
||||
console.log('\toverwritten:' + key);
|
||||
}
|
||||
if ( items[key] && items[key].length > 0 ) {
|
||||
itemsSorted[key] = items[key];
|
||||
}
|
||||
});
|
||||
result.push('gettext.load(' + JSON.stringify(itemsSorted, null, 4) + ');');
|
||||
|
||||
// and save
|
||||
console.log(cyan + 'build:\t' + reset + bold + jsFile + '\t' + green + keyList.length + reset + (fuzzyCount ? red : green) + '\tfuzzy:' + fuzzyCount + reset + (overwritten ? ' (total overwritten: ' + overwritten + ')' : '') + '\n');
|
||||
|
||||
// store js file
|
||||
fs.writeFileSync(jsFile, result.join('\n'), {encoding:'utf8'});
|
|
@ -0,0 +1,220 @@
|
|||
<?php
|
||||
|
||||
define("TEMP_DIR", './tmp');
|
||||
//define("DEFAULT_URL", 'http://stbhelp.iptv.infomir.com.ua/');
|
||||
|
||||
require_once 'inc/init.php';
|
||||
require_once DOKU_INC . 'inc/parser/parser.php';
|
||||
require_once DOKU_INC . 'inc/parser/xhtml.php';
|
||||
|
||||
function dump ( $data, $label ) {
|
||||
$data = print_r($data, true);
|
||||
file_put_contents(TEMP_DIR . '/build.log', ($label ? $label."\n":'') . $data . "\n", FILE_APPEND);
|
||||
}
|
||||
|
||||
function delTree($dir) {
|
||||
$files = array_diff(scandir($dir), array('.','..'));
|
||||
foreach ($files as $file) {
|
||||
(is_dir("$dir/$file")) ? delTree("$dir/$file") : unlink("$dir/$file");
|
||||
}
|
||||
return rmdir($dir);
|
||||
}
|
||||
|
||||
function Zip($source, $destination)
|
||||
{
|
||||
if (!extension_loaded('zip') || !file_exists($source)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$zip = new ZipArchive();
|
||||
if (!$zip->open($destination, ZIPARCHIVE::CREATE)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$source = str_replace('\\', '/', realpath($source));
|
||||
|
||||
if (is_dir($source) === true)
|
||||
{
|
||||
$files = new RecursiveIteratorIterator(new RecursiveDirectoryIterator($source), RecursiveIteratorIterator::SELF_FIRST);
|
||||
|
||||
foreach ($files as $file)
|
||||
{
|
||||
$file = str_replace('\\', '/', $file);
|
||||
|
||||
// Ignore "." and ".." folders
|
||||
if( in_array(substr($file, strrpos($file, '/')+1), array('.', '..')) )
|
||||
continue;
|
||||
|
||||
$file = realpath($file);
|
||||
|
||||
if (is_dir($file) === true)
|
||||
{
|
||||
$zip->addEmptyDir(str_replace($source . '/', '', $file . '/'));
|
||||
}
|
||||
else if (is_file($file) === true)
|
||||
{
|
||||
$zip->addFromString(str_replace($source . '/', '', $file), file_get_contents($file));
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (is_file($source) === true)
|
||||
{
|
||||
$zip->addFromString(basename($source), file_get_contents($source));
|
||||
}
|
||||
|
||||
return $zip->close();
|
||||
}
|
||||
|
||||
class HelpGenerator{
|
||||
function __construct($config){
|
||||
$this->config = $config;
|
||||
$this->help_dir = TEMP_DIR."/help";
|
||||
$this->pages_dir = $this->config['savedir']."/pages";
|
||||
}
|
||||
|
||||
function parseFile($dir, $name){
|
||||
$pages = array();
|
||||
if (is_dir($dir.'/'.$name) && is_file($file = $dir.'/'.$name.'.txt')){
|
||||
if ($file = fopen($file,'r')){
|
||||
while(!feof($file)) {
|
||||
$line = fgets($file);
|
||||
//if ($res = preg_match_all('/\|\s*\[\[.+\]\]\s*\|\s*\[\[.+:(\w+)\s*\|\s*(.*)\s*\]\]\s*\|\s*(.+)\s*\|/', $line, $media)){
|
||||
if ($res = preg_match_all('/\|.*{{.+}}.*\|\s*\[\[.+:(\w+)\s*\|\s*(.*)\s*\]\]\s*\|\s*(.+)\s*\|/', $line, $media)){
|
||||
$page = array(
|
||||
"key" => trim($media[1][0]),
|
||||
"title" => trim($media[2][0]),
|
||||
"annotation" => trim($media[3][0])
|
||||
);
|
||||
if (is_dir($dir.'/'.$name.'/'.$page["key"])){
|
||||
$page['data'] = $this->parseFile($dir.'/'.$name, $page["key"]);
|
||||
}
|
||||
$pages[] = $page;
|
||||
}
|
||||
}
|
||||
fclose($file);
|
||||
}
|
||||
}
|
||||
return $pages;
|
||||
}
|
||||
|
||||
function renderFile($file){
|
||||
$this->parser = new Doku_Parser();
|
||||
$this->parser->Handler = new Doku_Handler();
|
||||
|
||||
$this->parser->addMode('listblock',new Doku_Parser_Mode_ListBlock());
|
||||
$this->parser->addMode('preformatted',new Doku_Parser_Mode_Preformatted());
|
||||
$this->parser->addMode('notoc',new Doku_Parser_Mode_NoToc());
|
||||
$this->parser->addMode('header',new Doku_Parser_Mode_Header());
|
||||
$this->parser->addMode('table',new Doku_Parser_Mode_Table());
|
||||
|
||||
$formats = array (
|
||||
'strong', 'emphasis', 'underline', 'monospace',
|
||||
'subscript', 'superscript', 'deleted',
|
||||
);
|
||||
|
||||
foreach ( $formats as $format ) {
|
||||
$this->parser->addMode($format,new Doku_Parser_Mode_Formatting($format));
|
||||
}
|
||||
|
||||
$this->parser->addMode('linebreak',new Doku_Parser_Mode_Linebreak());
|
||||
$this->parser->addMode('footnote',new Doku_Parser_Mode_Footnote());
|
||||
$this->parser->addMode('hr',new Doku_Parser_Mode_HR());
|
||||
|
||||
$this->parser->addMode('internallink',new Doku_Parser_Mode_InternalLink());
|
||||
$this->parser->addMode('externallink',new Doku_Parser_Mode_ExternalLink());
|
||||
|
||||
$this->parser->addMode('unformatted',new Doku_Parser_Mode_Unformatted());
|
||||
$this->parser->addMode('code',new Doku_Parser_Mode_Code());
|
||||
$this->parser->addMode('file',new Doku_Parser_Mode_File());
|
||||
$this->parser->addMode('quote',new Doku_Parser_Mode_Quote());
|
||||
|
||||
$this->parser->addMode('multiplyentity',new Doku_Parser_Mode_MultiplyEntity());
|
||||
$this->parser->addMode('quotes',new Doku_Parser_Mode_Quotes());
|
||||
$this->parser->addMode('media',new Doku_Parser_Mode_Media());
|
||||
$this->parser->addMode('eol',new Doku_Parser_Mode_Eol());
|
||||
$doc = file_get_contents($file);
|
||||
$instructions = $this->parser->parse($doc);
|
||||
$Renderer = new Doku_Renderer_XHTML();
|
||||
foreach ( $instructions as $instruction ) {
|
||||
call_user_func_array(array($Renderer, $instruction[0]),$instruction[1]);
|
||||
}
|
||||
return $Renderer->doc;
|
||||
}
|
||||
|
||||
function updateImages($html, $path){
|
||||
$level = substr_count($path, "/");
|
||||
if ($_GET['relative_path']){
|
||||
$client_path = $_GET['relative_path'].'/'.$path.'/';
|
||||
}
|
||||
for ($i=0, $relative = ""; $i < $level; $i++) {
|
||||
$relative .= "../";
|
||||
}
|
||||
|
||||
//if ($res = preg_match_all('/<img.*src=[\'"]{1}([^\'"]*[:|=]([^\'"]*))[\'"]{1}.*\/>?/i', $html, $media)){
|
||||
if ($res = preg_match_all('/<img[^>]*src=[\'"]{1}([^\'"]*[:|=]([^\'"]*))[\'"]{1}[^>]*\/>?/i', $html, $media)){
|
||||
foreach ($media[1] as $key => $src) {
|
||||
$image_url = $relative.'images/'.$media[2][$key];
|
||||
$html = str_replace($src, $client_path.$image_url, $html);
|
||||
// print("getBaseURL = ".getBaseURL().$src."\n");
|
||||
// print("HTTP_HOST = "."http://".$_SERVER['HTTP_HOST'].$src."\n");
|
||||
// print(DEFAULT_URL.$src);
|
||||
// dump("http://".$_SERVER['HTTP_HOST'].$src, "HOST:");
|
||||
file_put_contents($this->help_dir.'/'.$path.'/'.$image_url, file_get_contents("http://".$_SERVER['HTTP_HOST'].$src));
|
||||
// file_put_contents($this->help_dir.'/'.$path.'/'.$image_url, file_get_contents(DEFAULT_URL.$src));
|
||||
}
|
||||
}
|
||||
return $html;
|
||||
}
|
||||
|
||||
function generatePart($pages, $path, $relative){
|
||||
foreach ($pages as $page) {
|
||||
$part = $relative ? $relative.'/'.$page['key'] : $page['key'];
|
||||
if ($page['data']){
|
||||
mkdir($this->help_dir.'/'.$path.'/'.$part, 0777, true);
|
||||
$this->generatePart($page['data'], $path, $part);
|
||||
}else{
|
||||
$html = $this->renderFile($this->pages_dir.'/'.$path.'/'.$this->config['start'].'/'.$part.'.txt');
|
||||
$html = $this->updateImages($html, $path.'/'.$relative);
|
||||
file_put_contents($this->help_dir.'/'.$path.'/'.$part.'.html', $html);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function prepareTmp(){
|
||||
delTree(TEMP_DIR);
|
||||
mkdir($this->help_dir, 0777, true);
|
||||
}
|
||||
|
||||
function generate(){
|
||||
$languages = explode(" ", $this->config['plugin']['translation']['translations']);
|
||||
//dump($languages);
|
||||
$pages = array();
|
||||
foreach ($languages as $language) {
|
||||
if (is_dir($directory = $this->pages_dir.'/'.$language)){
|
||||
//dump($language);
|
||||
$pages = $this->parseFile($directory, $this->config['start']);
|
||||
//dump($pages);
|
||||
mkdir($this->help_dir.'/'.$language.'/images', 0777, true);
|
||||
$this->generatePart($pages, $language, '');
|
||||
file_put_contents($this->help_dir.'/'.$language.'/pages.json', json_encode($pages));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createArchive($zip){
|
||||
Zip($this->help_dir, $zip);
|
||||
}
|
||||
|
||||
function redirectToZip($zip){
|
||||
header("HTTP/1.1 200 OK");
|
||||
header("Location: $zip");
|
||||
}
|
||||
}
|
||||
|
||||
$Generator = new HelpGenerator($conf);
|
||||
$Generator->prepareTmp();
|
||||
$Generator->generate();
|
||||
|
||||
$zip = TEMP_DIR.'/help.zip';
|
||||
$Generator->createArchive($zip);
|
||||
$Generator->redirectToZip($zip);
|
|
@ -0,0 +1,96 @@
|
|||
<?php
|
||||
/* Ace editor plugin for Dokuwiki
|
||||
* Copyright © 2011, 2012 Institut Obert de Catalunya
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* as published by the Free Software Foundation; either version 2
|
||||
* of the License, or (at your option) any later version.
|
||||
*
|
||||
* Ths program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
||||
*/
|
||||
|
||||
if (!defined('DOKU_INC')) die();
|
||||
|
||||
require_once DOKU_INC.'lib/plugins/action.php';
|
||||
|
||||
class action_plugin_aceeditor extends DokuWiki_Action_Plugin {
|
||||
|
||||
public function register(Doku_Event_Handler $controller){
|
||||
$controller->register_hook('DOKUWIKI_STARTED', 'AFTER',
|
||||
$this, 'handle_dokuwiki_started');
|
||||
$controller->register_hook('TPL_METAHEADER_OUTPUT', 'BEFORE',
|
||||
$this, 'handle_tpl_metaheader_output');
|
||||
}
|
||||
|
||||
public function handle_dokuwiki_started(Doku_Event $event, $param) {
|
||||
global $INFO, $JSINFO;
|
||||
$wraplimit = trim($this->getConf('wraplimit'));
|
||||
$xmltags = $this->getConf('xmltags');
|
||||
$xmltags = ($xmltags ? explode(',', $xmltags) : array());
|
||||
$JSINFO['plugin_aceeditor'] = array(
|
||||
'default' => $this->getConf('default'),
|
||||
'highlight' => $this->getConf('highlight'),
|
||||
'wraplimit' => $wraplimit ? (int) $wraplimit : null,
|
||||
'colortheme' => $this->getConf('colortheme'),
|
||||
'latex' => $this->getConf('latex'),
|
||||
'markdown' => $this->getConf('markdown'),
|
||||
'mdpage' => substr($INFO['id'], -3) == '.md',
|
||||
'xmltags' => $xmltags,
|
||||
);
|
||||
}
|
||||
|
||||
public function handle_tpl_metaheader_output(Doku_Event $event, $param) {
|
||||
global $ACT;
|
||||
|
||||
if (!in_array($ACT, array('edit', 'create', 'source', 'preview',
|
||||
'locked', 'draft', 'recover'))) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!$this->has_jquery() and $this->getConf('loadjquery')) {
|
||||
$jqueryurl = '//ajax.googleapis.com/ajax/libs/jquery/1.8.1/jquery.min.js';
|
||||
$this->link_script($event, $jqueryurl);
|
||||
$this->include_script($event, '$.noConflict();');
|
||||
}
|
||||
|
||||
if (file_exists(DOKU_INC.'lib/plugins/aceeditor/build.js')) {
|
||||
$this->link_script($event, DOKU_BASE.'lib/plugins/aceeditor/build.js');
|
||||
} else {
|
||||
$this->link_script($event, DOKU_BASE.'lib/plugins/aceeditor/vendor/require.js');
|
||||
$this->link_script($event, DOKU_BASE.'lib/plugins/aceeditor/scripts/init.js');
|
||||
}
|
||||
|
||||
// Workaround for conflict with syntaxhighlighter3 plugin
|
||||
$this->include_script($event, 'window.require = undefined;');
|
||||
}
|
||||
|
||||
public function has_jquery() {
|
||||
$version = getVersionData();
|
||||
$date = str_replace('-', '', $version['date']);
|
||||
return (int) $date > 20110525;
|
||||
}
|
||||
|
||||
private function include_script($event, $code) {
|
||||
$event->data['script'][] = array(
|
||||
'type' => 'text/javascript',
|
||||
'charset' => 'utf-8',
|
||||
'_data' => $code,
|
||||
);
|
||||
}
|
||||
|
||||
private function link_script($event, $url) {
|
||||
$event->data['script'][] = array(
|
||||
'type' => 'text/javascript',
|
||||
'charset' => 'utf-8',
|
||||
'src' => $url,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
Файл ложится в корневую директорию Dokuwiki.
|
||||
|
||||
Требует установленый языковой плагин в Dokuwiki.
|
||||
Требует права на запись в папку Dokuwiki так как создает в ней временную директорию для своих нужд.
|
||||
|
||||
Для работы генератора достаточно обратиться к нему по http и в ответ он отдаст архив с готовыой справкой.
|
||||
|
||||
Так же необходимо добавить обозначение нового языка в поле "Список поддерживаемых языков "
|
||||
http://stbhelp.iptv.infomir.com.ua/doku.php?id=start&do=admin&page=config
|
||||
|
||||
Рядом с этой папкой должна появиться новая для нового языка
|
||||
79.142.197.72
|
||||
/var/www/stbhelp.iptv.infomir.com.ua/data/pages/ru
|
|
@ -0,0 +1 @@
|
|||
node http.server.js
|
|
@ -0,0 +1,14 @@
|
|||
/**
|
||||
* HTTP static file server
|
||||
* @author Stanislav Kalashnik <sk@infomir.eu>
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
var files = new (require('node-static')).Server(require('path').join(__dirname, '/..'));
|
||||
|
||||
require('http').createServer(function (request, response) {
|
||||
request.addListener('end', function () {
|
||||
files.serve(request, response);
|
||||
}).resume();
|
||||
}).listen(8080);
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
*
|
||||
* @author Aleynikov Boris <aleynikov.boris@gmail.com>.
|
||||
*/
|
||||
|
||||
var path = require('path'),
|
||||
fs = require('fs'),
|
||||
configPath = path.join(process.cwd(), '..', 'public', 'config.js'),
|
||||
|
||||
//
|
||||
configuration = {},
|
||||
PATH_IMG_PUBLIC ='',
|
||||
PATH_SYSTEM = ''
|
||||
;
|
||||
|
||||
Array.prototype.shuffle = function () {
|
||||
var n = this.length,
|
||||
i, tmp;
|
||||
while ( n-- ) {
|
||||
i = Math.floor(n * Math.random());
|
||||
tmp = this[i];
|
||||
this[i] = this[n];
|
||||
this[n] = tmp;
|
||||
|
||||
}
|
||||
return this;
|
||||
};
|
||||
|
||||
function extend (target, source, override) {
|
||||
var _target = (override === false ? extend({}, target) : target || {});
|
||||
for (var prop in source) {
|
||||
if ( typeof _target[prop] === 'object' && typeof source[prop] === 'object' && !Array.isArray(_target[prop]) && !Array.isArray(source[prop]) ) {
|
||||
_target[prop] = extend(_target[prop], source[prop], override);
|
||||
} else {
|
||||
_target[prop] = source[prop];
|
||||
}
|
||||
}
|
||||
return _target;
|
||||
}
|
||||
|
||||
function getCurrentLanguage () {
|
||||
return 'en';
|
||||
}
|
||||
|
||||
fs.readFile(configPath, 'utf8', function ( error, data ) {
|
||||
var copy,
|
||||
idx = data.indexOf('var menu = {'),
|
||||
codeText = data.slice(idx);
|
||||
|
||||
idx = codeText.indexOf('config = extend(config, models[gSTB.GetDeviceModelExt()]);');
|
||||
|
||||
codeText = codeText.slice(0, idx);
|
||||
|
||||
|
||||
eval(codeText);
|
||||
|
||||
|
||||
for ( model in models ) {
|
||||
copy = JSON.parse(JSON.stringify(config));
|
||||
models[model] = extend(copy, models[model]);
|
||||
console.log(model + ' ' + models[model].logoImagePath);
|
||||
}
|
||||
|
||||
fs.writeFileSync('models.json', JSON.stringify(models, null, 4));
|
||||
console.log('Write to models.json');
|
||||
|
||||
|
||||
|
||||
});
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"name": "portal-tools",
|
||||
"version": "0.1.0",
|
||||
"description": "command-line utils for the stb portal management",
|
||||
"keywords": [
|
||||
"stb",
|
||||
"portal",
|
||||
"command",
|
||||
"utils"
|
||||
],
|
||||
"author": "Stanislav Kalashnik <sk@infomir.eu>",
|
||||
"repository": {},
|
||||
"scripts": {
|
||||
"test": "echo \"no test specified\""
|
||||
},
|
||||
"readme": "",
|
||||
"dependencies": {
|
||||
"adm-zip": "0.4.x",
|
||||
"cheerio": "0.12.0",
|
||||
"commander": "2.6.*",
|
||||
"pofile": "0.2.*",
|
||||
"node-static": "0.7.x",
|
||||
"request": "2.51.x",
|
||||
"uglify-js": "2.4.x",
|
||||
"wrench": "1.5.x",
|
||||
"clean-css": "2.2.x"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,14 @@
|
|||
gettext.js - NodeJS скрипт генерации js файлов на основании gettext po файлов
|
||||
пример вызова:
|
||||
node gettext.js -f "../public/app/dlman/lang/ru.po"
|
||||
получение справки:
|
||||
node gettext.js --help
|
||||
|
||||
build.gettext.cmd - скрипт автоматической генерации js файлов на основании gettext po файлов для всего проекта
|
||||
вызывается без параметров
|
||||
|
||||
release.js - NodeJS скрипт сборки релиза с вычленением всех зависимостей и склейки в общий файл для каждого html файла
|
||||
пример вызова (пути по умолчанию):
|
||||
node release.js
|
||||
пример вызова (пути в явном виде):
|
||||
node release.js -s "../../current_portal_path" -d "../../new_minified_version"
|
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* Module to prepare minimized and compressed version of page dependence files
|
||||
* @author Stanislav Kalashnik <sk@infomir.eu>
|
||||
*/
|
||||
|
||||
//'use strict';
|
||||
|
||||
var program = require('commander'),
|
||||
cheerio = require('cheerio'),
|
||||
wrench = require('wrench'),
|
||||
uglify = require('uglify-js'),
|
||||
path = require('path'),
|
||||
cleanCss = new (require('clean-css'))({noAdvanced:true, noRebase:true}),
|
||||
fs = require('fs'),
|
||||
exec = require('child_process').execSync,
|
||||
gitHash = fs.existsSync(path.join(__dirname, '..', '.git')) && exec('git rev-parse HEAD').toString().trim();
|
||||
|
||||
// console colors
|
||||
var red = '\u001b[31m',
|
||||
bold = '\u001b[1m',
|
||||
cyan = '\u001b[36m',
|
||||
green = '\u001b[32m',
|
||||
reset = '\u001b[0m';
|
||||
|
||||
// all used js files
|
||||
var jsUsedList = {};
|
||||
|
||||
// CLI init
|
||||
program.version('0.1')
|
||||
.option('-s, --src [PATH]', 'source directory with files to proceed [..]', '..')
|
||||
.option('-d, --dst [PATH]', 'destination directory for the result build [../mini]', '..' + path.sep + 'mini')
|
||||
.parse(process.argv);
|
||||
|
||||
// the po file is given
|
||||
if ( !program.src || typeof program.src !== 'string' ||
|
||||
!program.dst || typeof program.dst !== 'string' ) { console.log('Not enough parameters!'); return; }
|
||||
|
||||
// normalize
|
||||
program.src = path.resolve(program.src);
|
||||
program.dst = path.resolve(program.dst);
|
||||
// report
|
||||
console.log(cyan + 'src:\t' + reset + bold + program.src + reset);
|
||||
console.log(cyan + 'dst:\t' + reset + bold + program.dst + reset + "\n");
|
||||
|
||||
// prepare
|
||||
wrench.rmdirSyncRecursive(program.dst, true);
|
||||
wrench.mkdirSyncRecursive(program.dst);
|
||||
// report
|
||||
console.log(green + 'ok\t' + reset + 'prepared the destination directory');
|
||||
|
||||
// dirs
|
||||
wrench.copyDirSyncRecursive(program.src + path.sep + 'public', program.dst + path.sep + 'public');
|
||||
wrench.copyDirSyncRecursive(program.src + path.sep + 'system', program.dst + path.sep + 'system');
|
||||
// files
|
||||
fs.writeFileSync(program.dst + path.sep + 'index.html', fs.readFileSync(program.src + path.sep + 'index.html', {encoding:'utf8'}), {encoding:'utf8'});
|
||||
fs.writeFileSync(program.dst + path.sep + 'services.html', fs.readFileSync(program.src + path.sep + 'services.html', {encoding:'utf8'}), {encoding:'utf8'});
|
||||
fs.writeFileSync(program.dst + path.sep + 'rules.js', fs.readFileSync(program.src + path.sep + 'rules.js', {encoding:'utf8'}), {encoding:'utf8'});
|
||||
// report
|
||||
console.log(green + 'ok\t' + reset + 'cloned the source directory to the destination');/**/
|
||||
console.log(green + 'ok\t' + reset + 'cleaning gettext localization files');
|
||||
|
||||
// remove all po files
|
||||
walk(program.dst, '.po').forEach(function(item){
|
||||
fs.unlinkSync(item);
|
||||
});
|
||||
|
||||
// recursively read directories contents
|
||||
// and get all html files
|
||||
walk(program.dst, '.html').forEach(function(item){
|
||||
var htmlFile = fs.readFileSync(item, {encoding:'utf8'});
|
||||
var jsName = path.dirname(item) + path.sep + path.basename(item, '.html') + '.min.js';
|
||||
var jsData = [];
|
||||
var scripts = [];
|
||||
// screen resolution correction
|
||||
htmlFile = htmlFile.replace(/WINDOW_HEIGHT/g, 'screen.height');
|
||||
htmlFile = htmlFile.replace(/WINDOW_WIDTH/g, 'screen.width');
|
||||
// parse
|
||||
var $ = cheerio.load(htmlFile, {ignoreWhitespace:false, xmlMode:false});
|
||||
// find and remove scripts
|
||||
$('script').each(function(){
|
||||
// only in case of include
|
||||
if ( $(this).attr('src') !== undefined && $(this).attr('src') !== 'rules.js' ) {
|
||||
var src = path.normalize(path.dirname(item) + path.sep + $(this).attr('src'));
|
||||
jsUsedList[src] = true;
|
||||
scripts.push(src);
|
||||
$(this).remove();
|
||||
}
|
||||
});
|
||||
// report
|
||||
console.log(green + 'ok\t' + reset + 'processed: ' + bold + path.relative(program.dst, item) + reset);
|
||||
// add one general
|
||||
if ( scripts.length > 0 ) {
|
||||
scripts.forEach(function(script){
|
||||
console.log('\t\tscript: ' + path.relative(program.dst, script));
|
||||
jsData.push(fs.readFileSync(script, {encoding:'utf8'}).trim());
|
||||
});
|
||||
$('head').append('\n\t<script type="text/javascript" src="' + path.basename(item, '.html') + '.min.js' + '"></script>\n');
|
||||
fs.writeFileSync(jsName, uglify.minify(jsData.join('\n\n\n'), {fromString:true, mangle:false}).code, {encoding:'utf8'});
|
||||
}
|
||||
htmlFile = $.html();
|
||||
// resave
|
||||
fs.writeFileSync(item, htmlFile, {encoding:'utf8'});
|
||||
});
|
||||
|
||||
// clear all used js files
|
||||
for ( var name in jsUsedList ) if ( jsUsedList.hasOwnProperty(name) ) fs.unlinkSync(name);
|
||||
// gstb
|
||||
fs.unlinkSync(program.dst + path.sep + 'system' + path.sep + 'gstb.js');
|
||||
console.log(green + 'ok\t' + reset + 'cleared all used js files');
|
||||
|
||||
console.log(green + 'ok\t' + reset + 'prepare to compile language files');
|
||||
// recursively read directories contents
|
||||
// and get all js files to minimize
|
||||
walk(program.dst, '.js').forEach(function(item){
|
||||
if ( item.indexOf('.min.js') === -1 && item.indexOf('rules.js') === -1 ) {
|
||||
fs.writeFileSync(
|
||||
item,
|
||||
uglify.minify(fs.readFileSync(item, {encoding:'utf8'}), {fromString:true, mangle:false}).code,
|
||||
{encoding:'utf8'}
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
console.log(green + 'ok\t' + reset + 'prepare to minify css files');
|
||||
// minify css files
|
||||
walk(program.dst, '.css').forEach(function(item){
|
||||
fs.writeFileSync(
|
||||
item,
|
||||
cleanCss.minify(fs.readFileSync(item, {encoding:'utf8'})),
|
||||
{encoding:'utf8'}
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
// save build info
|
||||
fs.writeFileSync(program.dst + path.sep + 'info.json', JSON.stringify({
|
||||
time: (new Date()).toUTCString(),
|
||||
hash: gitHash
|
||||
}, null, '\t'), {encoding:'utf8'});
|
||||
|
||||
|
||||
function walk ( dir, ext ) {
|
||||
var results = [];
|
||||
var list = fs.readdirSync(dir);
|
||||
list.forEach(function ( file ) {
|
||||
file = dir + path.sep + file;
|
||||
var stat = fs.statSync(file);
|
||||
if ( stat && stat.isDirectory() ) results = results.concat(walk(file, ext));
|
||||
else if ( path.extname(file) === ext ) results.push(file);
|
||||
});
|
||||
return results;
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
/**
|
||||
* STB Proxy desktop browser (client) part
|
||||
* @constructor
|
||||
* @author Stanislav Kalashnik <sk@infomir.eu>
|
||||
*/
|
||||
function proxyClient () {
|
||||
|
||||
/**
|
||||
* proxy instance configuration
|
||||
* @namespace
|
||||
*/
|
||||
var config = {
|
||||
/** node.js server address */
|
||||
host : '127.0.0.1',
|
||||
|
||||
/** http server port */
|
||||
port : 8800,
|
||||
|
||||
/** session name */
|
||||
name : 'anonymous',
|
||||
|
||||
/** cached url for posting requests */
|
||||
urlPost : null,
|
||||
|
||||
/** cached url for info collecting */
|
||||
urlInfo : null
|
||||
};
|
||||
|
||||
// single ajax object for performance
|
||||
var xhr = new XMLHttpRequest();
|
||||
|
||||
/**
|
||||
* Prepares the connection
|
||||
* @param {Object} options set of initialization parameters (host, port, name, urlPost, urlInfo)
|
||||
*/
|
||||
this.init = function ( options ) {
|
||||
// validate and iterate input
|
||||
if ( options ) for ( var name in options ) {
|
||||
// rewrite defaults
|
||||
if ( options.hasOwnProperty(name) ) config[name] = options[name];
|
||||
}
|
||||
// cache final request urls
|
||||
config.urlPost = 'http://' + config.host + ':' + config.port + '/' + config.name;
|
||||
config.urlInfo = 'http://' + config.host + ':' + config.port + '/info/' + config.name;
|
||||
};
|
||||
|
||||
/**
|
||||
* Sends a sync request to the STB device from the desktop browser
|
||||
* @param {Object} data JSON data to send
|
||||
* @return {*} execution result from the STB
|
||||
*/
|
||||
this.send = function ( data ) {
|
||||
// mandatory init check
|
||||
if ( !config.urlPost ) return false;
|
||||
// prepare
|
||||
var time = +new Date(),
|
||||
response;
|
||||
// make request
|
||||
xhr.open('post', config.urlPost, false);
|
||||
xhr.setRequestHeader('Content-Type', 'application/json; charset=utf-8');
|
||||
xhr.send(JSON.stringify(data));
|
||||
// proceed the result
|
||||
try {
|
||||
response = JSON.parse(xhr.responseText);
|
||||
} catch ( e ) {
|
||||
response = {error:e};
|
||||
}
|
||||
// detailed report
|
||||
console.groupCollapsed('%c%s\t%c%d/%d ms',
|
||||
'color:' + (response.error ? 'red' : 'green'), data.method || data.code || 'unhandled STB call',
|
||||
'color:#aaa;font-weight:normal', response.time || 0, +new Date() - time);
|
||||
console.log(data);
|
||||
console.log(response.error || response.data);
|
||||
console.groupEnd();
|
||||
// ready
|
||||
return response.data;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper to send a line of js code to eval on the STB device
|
||||
* @param {string} code javascript source code to execute on the device
|
||||
* @return {*} execution result from the STB
|
||||
*/
|
||||
this.eval = function ( code ) {
|
||||
return this.send({type:'eval', code:code});
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapper to send one function of js code with arguments to eval on the STB device
|
||||
* @param {string} method javascript function name (like "gSTB.Debug")
|
||||
* @param {Array} params list of the function arguments
|
||||
* @return {*} execution result from the STB
|
||||
*/
|
||||
this.call = function ( method, params ) {
|
||||
return this.send({type:'call', method:method, params:params});
|
||||
};
|
||||
|
||||
/**
|
||||
* Gets the detailed info about the current connection
|
||||
* @return {{active:Boolean, count:Number}|{active:Boolean}|Boolean}
|
||||
*/
|
||||
this.info = function () {
|
||||
// mandatory init check
|
||||
if ( !config.urlInfo ) return false;
|
||||
// make request
|
||||
xhr.open('get', config.urlInfo, false);
|
||||
xhr.send();
|
||||
return JSON.parse(xhr.responseText || false);
|
||||
};
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
/**
|
||||
* STB Proxy device (server) side
|
||||
* @constructor
|
||||
* @author Stanislav Kalashnik <sk@infomir.eu>
|
||||
*/
|
||||
function ProxyServer () {
|
||||
|
||||
/**
|
||||
* proxy instance configuration
|
||||
* @namespace
|
||||
*/
|
||||
var config = {
|
||||
/** node.js server address */
|
||||
host : '127.0.0.1',
|
||||
|
||||
/** websocket server port */
|
||||
port : 8900,
|
||||
|
||||
/** session name */
|
||||
name : 'anonymous'
|
||||
};
|
||||
|
||||
/**
|
||||
* Prepares the connection
|
||||
* @param {Object} options set of initialization parameters (host, port, name)
|
||||
*/
|
||||
this.init = function ( options ) {
|
||||
// validate and iterate input
|
||||
if ( options ) for ( var name in options ) {
|
||||
// rewrite defaults
|
||||
if ( options.hasOwnProperty(name) ) config[name] = options[name];
|
||||
}
|
||||
|
||||
// establish the connection
|
||||
config.socket = new WebSocket('ws://' + config.host + ':' + config.port + '/' + config.name);
|
||||
|
||||
// event hook
|
||||
config.socket.onopen = function(){
|
||||
console.log('socket.onopen', config.name);
|
||||
};
|
||||
|
||||
// event hook
|
||||
config.socket.onclose = function(){
|
||||
console.log('socket.onclose', config.name);
|
||||
};
|
||||
|
||||
// message from a desktop browser
|
||||
config.socket.onmessage = function ( message ) {
|
||||
console.log('socket.onmessage', config.name);
|
||||
// prepare
|
||||
var result = {time:+new Date()},
|
||||
request;
|
||||
// proceed the message
|
||||
try {
|
||||
request = JSON.parse(message.data || false);
|
||||
// valid incoming request
|
||||
if ( request && ['call', 'eval'].indexOf(request.type) !== -1 ) {
|
||||
// exec types
|
||||
if ( request.type === 'call' ) {
|
||||
result.data = eval(request.method).apply(window, request.params);
|
||||
} else if ( request.type === 'eval' ) {
|
||||
result.data = eval(request.code);
|
||||
}
|
||||
} else {
|
||||
result.error = 'invalid incoming request';
|
||||
}
|
||||
} catch ( e ) {
|
||||
console.log(e);
|
||||
result.error = e;
|
||||
}
|
||||
// time taken
|
||||
result.time = +new Date() - result.time;
|
||||
// wrap and send back
|
||||
config.socket.send(JSON.stringify(result));
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Finish the connection
|
||||
*/
|
||||
this.close = function () {
|
||||
config.socket.close();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Debug entry point</title>
|
||||
<meta charset='utf-8'>
|
||||
<link rel="shortcut icon" href="https://www.iconfinder.com/icons/3693/download/png/64"/>
|
||||
|
||||
<style type="text/css">
|
||||
html, body { height: 100%; background:#000; color:#fff; margin:0; padding:0; font-family:Verdana,sans-serif; font-size:20px }
|
||||
|
||||
/* table cell spacing/padding reset */
|
||||
table { border:0; border-collapse:collapse }
|
||||
table td { padding:0 }
|
||||
|
||||
/* meta-classes */
|
||||
.maxh { height:100% }
|
||||
.maxw { width:100% }
|
||||
a { text-decoration:none }
|
||||
</style>
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<table class="maxh maxw">
|
||||
<tr>
|
||||
<td>
|
||||
<!--header-->
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>
|
||||
<!--footer-->
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,96 @@
|
|||
/**
|
||||
* STB Proxy server node.js part
|
||||
* handles all requests between desktop browser (client) and server (stb device)
|
||||
* @author Stanislav Kalashnik <sk@infomir.eu>
|
||||
*/
|
||||
|
||||
// globals
|
||||
var WebSocketServer = require('ws').Server,
|
||||
wsPool = require('./wspool.js'),
|
||||
http = require('http'),
|
||||
fs = require('fs');
|
||||
|
||||
// connection ports
|
||||
var portHttp = 8800, // http server
|
||||
portWss = 8900; // websocket server
|
||||
|
||||
// files allowed to be served
|
||||
var fileList = ['client.js', 'server.js'];
|
||||
|
||||
|
||||
// WebSocket server creation
|
||||
wss = new WebSocketServer({port:portWss});
|
||||
wss.on('connection', function(socket) {
|
||||
// new awaiting instance of WebSocket in the pool
|
||||
wsPool.add(socket.upgradeReq.url.slice(1), socket);
|
||||
});
|
||||
console.log('port %d accepts WebSocket connections', portWss);
|
||||
|
||||
|
||||
// simple http listener
|
||||
http.createServer(function(request, response){
|
||||
console.log('http\t%s\t%s', request.method, request.url);
|
||||
// prepare request query
|
||||
var query = request.url.slice(1).split('/');
|
||||
|
||||
switch ( request.method ) {
|
||||
|
||||
// simple serve info/file requests
|
||||
case 'GET':
|
||||
// first param holds the command name
|
||||
switch ( query[0] ) {
|
||||
// serving files
|
||||
case 'file':
|
||||
// one of the allowed files
|
||||
if ( fileList.indexOf(query[1]) !== -1 ) {
|
||||
response.writeHead(200, {'Content-Type':'application/javascript; charset=utf-8'});
|
||||
response.end(fs.readFileSync(query[1]));
|
||||
}
|
||||
break;
|
||||
// get connection info
|
||||
case 'info':
|
||||
//var wsItem = wsList.get(query[1]);
|
||||
response.writeHead(200, {'Content-Type':'application/json; charset=utf-8'});
|
||||
response.end(JSON.stringify(wsPool.info(query[1])));
|
||||
break;
|
||||
// show help page
|
||||
default:
|
||||
// not valid url or root
|
||||
response.writeHead(200, {'Content-Type':'text/html; charset=utf-8'});
|
||||
response.end(fs.readFileSync('start.html'));
|
||||
}
|
||||
break;
|
||||
|
||||
// security info call
|
||||
case 'OPTIONS':
|
||||
//TODO: investigate why doesn't work
|
||||
response.writeHead(200, {
|
||||
'Access-Control-Allow-Origin' : '*',
|
||||
'Access-Control-Allow-Credentials' : 'true',
|
||||
'Access-Control-Allow-Methods' : 'POST, GET, OPTIONS',
|
||||
'Access-Control-Allow-Headers' : 'content-type',
|
||||
'Access-Control-Max-Age' : 1800
|
||||
});
|
||||
response.end();
|
||||
break;
|
||||
|
||||
// accept connections from desktop clients
|
||||
case 'POST':
|
||||
var post = '';
|
||||
// append all chunks
|
||||
request.on('data', function(data){ post += data; });
|
||||
// everything is ready to send to the STB
|
||||
request.on('end', function(){
|
||||
// make a call
|
||||
if ( !wsPool.send(query[0], post, response) ) {
|
||||
// no available connections so close
|
||||
response.end(JSON.stringify({error:'no connections'}));
|
||||
}
|
||||
});
|
||||
break;
|
||||
|
||||
default:
|
||||
response.end('wrong request!');
|
||||
}
|
||||
}).listen(portHttp);
|
||||
console.log('port %d accepts HTTP connections\n', portHttp);
|
|
@ -0,0 +1,20 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>client.a</title>
|
||||
<script type="text/javascript" src="http://192.168.1.71:8800/file/client.js"></script>
|
||||
<script type="text/javascript">
|
||||
var name = document.title,
|
||||
proxy = new proxyClient();
|
||||
|
||||
window.onload = function(){
|
||||
document.body.innerHTML = name;
|
||||
|
||||
proxy.init({name:'a', host:'192.168.1.71'});
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,20 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>client.b</title>
|
||||
<script type="text/javascript" src="http://192.168.1.71:8800/file/client.js"></script>
|
||||
<script type="text/javascript">
|
||||
var name = document.title,
|
||||
proxy = new proxyClient();
|
||||
|
||||
window.onload = function(){
|
||||
document.body.innerHTML = name;
|
||||
|
||||
proxy.init({name:'b', host:'192.168.1.71'});
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,20 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>server.a</title>
|
||||
<script type="text/javascript" src="http://192.168.1.71:8800/file/server.js"></script>
|
||||
<script type="text/javascript">
|
||||
var name = document.title,
|
||||
proxy = new proxyServer();
|
||||
|
||||
window.onload = function(){
|
||||
document.body.innerHTML = name;
|
||||
|
||||
proxy.init({name:'a', host:'192.168.1.71'});
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,20 @@
|
|||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>server.b</title>
|
||||
<script type="text/javascript" src="http://192.168.1.71:8800/file/server.js"></script>
|
||||
<script type="text/javascript">
|
||||
var name = document.title,
|
||||
proxy = new proxyServer();
|
||||
|
||||
window.onload = function(){
|
||||
document.body.innerHTML = name;
|
||||
|
||||
proxy.init({name:'b', host:'192.168.1.71'});
|
||||
};
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,109 @@
|
|||
/**
|
||||
* WebSocket pool
|
||||
* wraps all the work with ws instances
|
||||
* @author Stanislav Kalashnik <sk@infomir.eu>
|
||||
*/
|
||||
|
||||
// named WebSocket list
|
||||
var pool = {};
|
||||
|
||||
// exports the wrapper object
|
||||
module.exports = {
|
||||
|
||||
/**
|
||||
* New WebSocket creation
|
||||
* @param {string} name unique identifier for session
|
||||
* @param {Object} socket websocket resource
|
||||
* @return {boolean} true if was deleted successfully
|
||||
*/
|
||||
add : function ( name, socket ) {
|
||||
var self = this;
|
||||
// check input
|
||||
if ( name && socket ) {
|
||||
console.log('ws\tINIT\t[%s]\tconnection', name);
|
||||
|
||||
// main data structure
|
||||
pool[name] = {
|
||||
socket : socket,
|
||||
time : Math.round(+new Date()/1000),
|
||||
count : 0,
|
||||
active : true
|
||||
};
|
||||
|
||||
// disable link on close
|
||||
pool[name].socket.on('close', function() {
|
||||
self.remove(name);
|
||||
});
|
||||
|
||||
// await for an answer
|
||||
pool[name].socket.on('message', function(message) {
|
||||
// has link to talk back
|
||||
if ( pool[name].response ) {
|
||||
console.log('ws\tGET\t[%s]\tmessage\t%s', name, message);
|
||||
pool[name].response.end(message);
|
||||
}
|
||||
});
|
||||
return true;
|
||||
}
|
||||
// failure
|
||||
console.log('ws\tINIT\t[%s]\tfail to connect (wrong name or link)', name);
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Clear resources on WebSocket deletion
|
||||
* @param {string} name session name
|
||||
* @return {boolean} true if was deleted successfully
|
||||
*/
|
||||
remove : function ( name ) {
|
||||
// valid connection
|
||||
if ( name in pool ) {
|
||||
console.log('ws\tEXIT\t[%s]\tclose', name);
|
||||
return delete pool[name];
|
||||
}
|
||||
// failure
|
||||
console.log('ws\tDEL\t[%s]\tfail to remove (invalid connection)', name);
|
||||
return false;
|
||||
},
|
||||
|
||||
/**
|
||||
* Detailed information of the named WebSocket instance
|
||||
* @param {string} name session name
|
||||
* @return {{active:Boolean, count:Number}|{active:Boolean}}
|
||||
*/
|
||||
info : function ( name ) {
|
||||
// valid connection
|
||||
if ( name in pool ) {
|
||||
return {
|
||||
active : pool[name].active,
|
||||
count : pool[name].count
|
||||
};
|
||||
}
|
||||
// failure
|
||||
return {active:false};
|
||||
},
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {string} name session name
|
||||
* @param {string} data post data from browser to STB server
|
||||
* @param {ServerResponse} response link to HTTP response object to send back data
|
||||
* @return {boolean} true if was send successfully
|
||||
*/
|
||||
send : function ( name, data, response ) {
|
||||
// valid connection
|
||||
if ( name in pool && pool[name].active ) {
|
||||
console.log('ws\tSEND\t[%s]\tmessage\t%s', name, data);
|
||||
// store link to talk back when ready
|
||||
pool[name].response = response;
|
||||
// actual post
|
||||
pool[name].socket.send(data);
|
||||
pool[name].count++;
|
||||
return true;
|
||||
}
|
||||
// failure
|
||||
console.log('ws\tSEND\t[%s]\tfail to send (invalid connection)', name);
|
||||
return false;
|
||||
}
|
||||
|
||||
};
|
Loading…
Reference in New Issue