1消息传输协议使用了Google Protobuf,效率更高

2客户端示例基于Android Studio
3删除了flash sdk,将不再维护flash sdk
4 netty版本升级最新版,以及文档修改
This commit is contained in:
夏军 2017-03-17 15:37:44 +08:00
parent 42059835ae
commit 6248ccd569
1409 changed files with 32684 additions and 14910 deletions

View File

@ -1,42 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<actionScriptProperties analytics="false" mainApplicationPath="CIMBridge.as" projectUUID="03408a4e-ab34-4064-b20b-a105b4fb81be" version="11">
<compiler additionalCompilerArguments="-locale en_US" advancedTelemetry="false" autoRSLOrdering="true" copyDependentFiles="true" fteInMXComponents="false" generateAccessible="false" htmlExpressInstall="true" htmlGenerate="true" htmlHistoryManagement="true" htmlPlayerVersionCheck="true" includeNetmonSwc="false" outputFolderPath="bin-debug" removeUnusedRSL="true" sourceFolderPath="src" strict="true" targetPlayerVersion="0.0.0" useApolloConfig="false" useDebugRSLSwfs="true" useFlashSDK="true" verifyDigests="true" warn="true">
<compilerSourcePath/>
<libraryPath defaultLinkType="0">
<libraryPathEntry kind="4" path="">
<excludedEntries>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_charts.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="1" linkType="1" path="${PROJECT_FRAMEWORKS}/locale/{locale}"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/advancedgrids.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_air.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/charts.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/framework.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/mx/mx.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/netmon.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/sparkskins.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/rpc.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/datavisualization.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/qtp_air.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/videoPlayer.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/spark_dmv.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_dmv.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/flash-integration.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_flashflexkit.swc" useDefaultLinkType="false"/>
<libraryPathEntry kind="3" linkType="1" path="${PROJECT_FRAMEWORKS}/libs/automation_agent.swc" useDefaultLinkType="false"/>
</excludedEntries>
</libraryPathEntry>
<libraryPathEntry kind="3" linkType="1" path="libs/as3corelib.swc" useDefaultLinkType="false"/>
</libraryPath>
<sourceAttachmentPath/>
</compiler>
<applications>
<application path="CIMBridge.as"/>
</applications>
<modules/>
<workers/>
<buildCSSFiles/>
<flashCatalyst validateFlashCatalystCompatibility="false"/>
</actionScriptProperties>

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>CIMFlashBridge</name>
<comment></comment>
<projects>
</projects>
<buildSpec>
<buildCommand>
<name>com.adobe.flexbuilder.project.flexbuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>com.adobe.flexbuilder.project.actionscriptnature</nature>
</natures>
</projectDescription>

View File

@ -1,3 +0,0 @@
#Mon Sep 22 14:10:44 CST 2014
eclipse.preferences.version=1
encoding/<project>=utf-8

View File

@ -1,108 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- saved from url=(0014)about:internet -->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<!--
Smart developers always View Source.
This application was built using Adobe Flex, an open source framework
for building rich Internet applications that get delivered via the
Flash Player or to desktops via Adobe AIR.
Learn more about Flex at http://flex.org
// -->
<head>
<title></title>
<meta name="google" value="notranslate" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- Include CSS to eliminate any default margins/padding and set the height of the html element and
the body element to 100%, because Firefox, or any Gecko based browser, interprets percentage as
the percentage of the height of its parent container, which has to be set explicitly. Fix for
Firefox 3.6 focus border issues. Initially, don't display flashContent div so it won't show
if JavaScript disabled.
-->
<style type="text/css" media="screen">
html, body { height:100%; }
body { margin:0; padding:0; overflow:auto; text-align:center;
background-color: #ffffff; }
object:focus { outline:none; }
#flashContent { display:none; }
</style>
<!-- Enable Browser History by replacing useBrowserHistory tokens with two hyphens -->
<!-- BEGIN Browser History required section -->
<link rel="stylesheet" type="text/css" href="history/history.css" />
<script type="text/javascript" src="history/history.js"></script>
<!-- END Browser History required section -->
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript">
// For version detection, set to min. required Flash Player version, or 0 (or 0.0.0), for no version detection.
var swfVersionStr = "11.4.0";
// To use express install, set to playerProductInstall.swf, otherwise the empty string.
var xiSwfUrlStr = "playerProductInstall.swf";
var flashvars = {};
var params = {};
params.quality = "high";
params.bgcolor = "#ffffff";
params.allowscriptaccess = "sameDomain";
params.allowfullscreen = "true";
var attributes = {};
attributes.id = "CIMBridge";
attributes.name = "CIMBridge";
attributes.align = "middle";
swfobject.embedSWF(
"CIMBridge.swf", "flashContent",
"100%", "100%",
swfVersionStr, xiSwfUrlStr,
flashvars, params, attributes);
// JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
swfobject.createCSS("#flashContent", "display:block;text-align:left;");
</script>
</head>
<body>
<!-- SWFObject's dynamic embed method replaces this alternative HTML content with Flash content when enough
JavaScript and Flash plug-in support is available. The div is initially hidden so that it doesn't show
when JavaScript is disabled.
-->
<div id="flashContent">
<p>
To view this page ensure that Adobe Flash Player version
11.4.0 or greater is installed.
</p>
<script type="text/javascript">
var pageHost = ((document.location.protocol == "https:") ? "https://" : "http://");
document.write("<a href='http://www.adobe.com/go/getflashplayer'><img src='"
+ pageHost + "www.adobe.com/images/shared/download_buttons/get_flash_player.gif' alt='Get Adobe Flash player' /></a>" );
</script>
</div>
<noscript>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%" id="CIMBridge">
<param name="movie" value="CIMBridge.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="true" />
<!--[if !IE]>-->
<object type="application/x-shockwave-flash" data="CIMBridge.swf" width="100%" height="100%">
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="true" />
<!--<![endif]-->
<!--[if gte IE 6]>-->
<p>
Either scripts and active content are not permitted to run or Adobe Flash Player version
11.4.0 or greater is not installed.
</p>
<!--<![endif]-->
<a href="http://www.adobe.com/go/getflashplayer">
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash Player" />
</a>
<!--[if !IE]>-->
</object>
<!--<![endif]-->
</object>
</noscript>
</body>
</html>

View File

@ -1,108 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- saved from url=(0014)about:internet -->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<!--
Smart developers always View Source.
This application was built using Adobe Flex, an open source framework
for building rich Internet applications that get delivered via the
Flash Player or to desktops via Adobe AIR.
Learn more about Flex at http://flex.org
// -->
<head>
<title></title>
<meta name="google" value="notranslate" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- Include CSS to eliminate any default margins/padding and set the height of the html element and
the body element to 100%, because Firefox, or any Gecko based browser, interprets percentage as
the percentage of the height of its parent container, which has to be set explicitly. Fix for
Firefox 3.6 focus border issues. Initially, don't display flashContent div so it won't show
if JavaScript disabled.
-->
<style type="text/css" media="screen">
html, body { height:100%; }
body { margin:0; padding:0; overflow:auto; text-align:center;
background-color: #ffffff; }
object:focus { outline:none; }
#flashContent { display:none; }
</style>
<!-- Enable Browser History by replacing useBrowserHistory tokens with two hyphens -->
<!-- BEGIN Browser History required section -->
<link rel="stylesheet" type="text/css" href="history/history.css" />
<script type="text/javascript" src="history/history.js"></script>
<!-- END Browser History required section -->
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript">
// For version detection, set to min. required Flash Player version, or 0 (or 0.0.0), for no version detection.
var swfVersionStr = "11.4.0";
// To use express install, set to playerProductInstall.swf, otherwise the empty string.
var xiSwfUrlStr = "playerProductInstall.swf";
var flashvars = {};
var params = {};
params.quality = "high";
params.bgcolor = "#ffffff";
params.allowscriptaccess = "sameDomain";
params.allowfullscreen = "true";
var attributes = {};
attributes.id = "cim";
attributes.name = "cim";
attributes.align = "middle";
swfobject.embedSWF(
"cim.swf", "flashContent",
"100%", "100%",
swfVersionStr, xiSwfUrlStr,
flashvars, params, attributes);
// JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
swfobject.createCSS("#flashContent", "display:block;text-align:left;");
</script>
</head>
<body>
<!-- SWFObject's dynamic embed method replaces this alternative HTML content with Flash content when enough
JavaScript and Flash plug-in support is available. The div is initially hidden so that it doesn't show
when JavaScript is disabled.
-->
<div id="flashContent">
<p>
To view this page ensure that Adobe Flash Player version
11.4.0 or greater is installed.
</p>
<script type="text/javascript">
var pageHost = ((document.location.protocol == "https:") ? "https://" : "http://");
document.write("<a href='http://www.adobe.com/go/getflashplayer'><img src='"
+ pageHost + "www.adobe.com/images/shared/download_buttons/get_flash_player.gif' alt='Get Adobe Flash player' /></a>" );
</script>
</div>
<noscript>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%" id="cim">
<param name="movie" value="cim.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="true" />
<!--[if !IE]>-->
<object type="application/x-shockwave-flash" data="cim.swf" width="100%" height="100%">
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="true" />
<!--<![endif]-->
<!--[if gte IE 6]>-->
<p>
Either scripts and active content are not permitted to run or Adobe Flash Player version
11.4.0 or greater is not installed.
</p>
<!--<![endif]-->
<a href="http://www.adobe.com/go/getflashplayer">
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash Player" />
</a>
<!--[if !IE]>-->
</object>
<!--<![endif]-->
</object>
</noscript>
</body>
</html>

Binary file not shown.

View File

@ -1,6 +0,0 @@
/* This CSS stylesheet defines styles used by required elements in a flex application page that supports browser history */
#ie_historyFrame { width: 0px; height: 0px; display:none }
#firefox_anchorDiv { width: 0px; height: 0px; display:none }
#safari_formDiv { width: 0px; height: 0px; display:none }
#safari_rememberDiv { width: 0px; height: 0px; display:none }

View File

@ -1,678 +0,0 @@
BrowserHistoryUtils = {
addEvent: function(elm, evType, fn, useCapture) {
useCapture = useCapture || false;
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
}
else if (elm.attachEvent) {
var r = elm.attachEvent('on' + evType, fn);
return r;
}
else {
elm['on' + evType] = fn;
}
}
}
BrowserHistory = (function() {
// type of browser
var browser = {
ie: false,
ie8: false,
firefox: false,
safari: false,
opera: false,
version: -1
};
// Default app state URL to use when no fragment ID present
var defaultHash = '';
// Last-known app state URL
var currentHref = document.location.href;
// Initial URL (used only by IE)
var initialHref = document.location.href;
// Initial URL (used only by IE)
var initialHash = document.location.hash;
// History frame source URL prefix (used only by IE)
var historyFrameSourcePrefix = 'history/historyFrame.html?';
// History maintenance (used only by Safari)
var currentHistoryLength = -1;
// Flag to denote the existence of onhashchange
var browserHasHashChange = false;
var historyHash = [];
var initialState = createState(initialHref, initialHref + '#' + initialHash, initialHash);
var backStack = [];
var forwardStack = [];
var currentObjectId = null;
//UserAgent detection
var useragent = navigator.userAgent.toLowerCase();
if (useragent.indexOf("opera") != -1) {
browser.opera = true;
} else if (useragent.indexOf("msie") != -1) {
browser.ie = true;
browser.version = parseFloat(useragent.substring(useragent.indexOf('msie') + 4));
if (browser.version == 8)
{
browser.ie = false;
browser.ie8 = true;
}
} else if (useragent.indexOf("safari") != -1) {
browser.safari = true;
browser.version = parseFloat(useragent.substring(useragent.indexOf('safari') + 7));
} else if (useragent.indexOf("gecko") != -1) {
browser.firefox = true;
}
if (browser.ie == true && browser.version == 7) {
window["_ie_firstload"] = false;
}
function hashChangeHandler()
{
currentHref = document.location.href;
var flexAppUrl = getHash();
//ADR: to fix multiple
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
var pl = getPlayers();
for (var i = 0; i < pl.length; i++) {
pl[i].browserURLChange(flexAppUrl);
}
} else {
getPlayer().browserURLChange(flexAppUrl);
}
}
// Accessor functions for obtaining specific elements of the page.
function getHistoryFrame()
{
return document.getElementById('ie_historyFrame');
}
function getFormElement()
{
return document.getElementById('safari_formDiv');
}
function getRememberElement()
{
return document.getElementById("safari_remember_field");
}
// Get the Flash player object for performing ExternalInterface callbacks.
// Updated for changes to SWFObject2.
function getPlayer(id) {
var i;
if (id && document.getElementById(id)) {
var r = document.getElementById(id);
if (typeof r.SetVariable != "undefined") {
return r;
}
else {
var o = r.getElementsByTagName("object");
var e = r.getElementsByTagName("embed");
for (i = 0; i < o.length; i++) {
if (typeof o[i].browserURLChange != "undefined")
return o[i];
}
for (i = 0; i < e.length; i++) {
if (typeof e[i].browserURLChange != "undefined")
return e[i];
}
}
}
else {
var o = document.getElementsByTagName("object");
var e = document.getElementsByTagName("embed");
for (i = 0; i < e.length; i++) {
if (typeof e[i].browserURLChange != "undefined")
{
return e[i];
}
}
for (i = 0; i < o.length; i++) {
if (typeof o[i].browserURLChange != "undefined")
{
return o[i];
}
}
}
return undefined;
}
function getPlayers() {
var i;
var players = [];
if (players.length == 0) {
var tmp = document.getElementsByTagName('object');
for (i = 0; i < tmp.length; i++)
{
if (typeof tmp[i].browserURLChange != "undefined")
players.push(tmp[i]);
}
}
if (players.length == 0 || players[0].object == null) {
var tmp = document.getElementsByTagName('embed');
for (i = 0; i < tmp.length; i++)
{
if (typeof tmp[i].browserURLChange != "undefined")
players.push(tmp[i]);
}
}
return players;
}
function getIframeHash() {
var doc = getHistoryFrame().contentWindow.document;
var hash = String(doc.location.search);
if (hash.length == 1 && hash.charAt(0) == "?") {
hash = "";
}
else if (hash.length >= 2 && hash.charAt(0) == "?") {
hash = hash.substring(1);
}
return hash;
}
/* Get the current location hash excluding the '#' symbol. */
function getHash() {
// It would be nice if we could use document.location.hash here,
// but it's faulty sometimes.
var idx = document.location.href.indexOf('#');
return (idx >= 0) ? document.location.href.substr(idx+1) : '';
}
/* Get the current location hash excluding the '#' symbol. */
function setHash(hash) {
// It would be nice if we could use document.location.hash here,
// but it's faulty sometimes.
if (hash == '') hash = '#'
document.location.hash = hash;
}
function createState(baseUrl, newUrl, flexAppUrl) {
return { 'baseUrl': baseUrl, 'newUrl': newUrl, 'flexAppUrl': flexAppUrl, 'title': null };
}
/* Add a history entry to the browser.
* baseUrl: the portion of the location prior to the '#'
* newUrl: the entire new URL, including '#' and following fragment
* flexAppUrl: the portion of the location following the '#' only
*/
function addHistoryEntry(baseUrl, newUrl, flexAppUrl) {
//delete all the history entries
forwardStack = [];
if (browser.ie) {
//Check to see if we are being asked to do a navigate for the first
//history entry, and if so ignore, because it's coming from the creation
//of the history iframe
if (flexAppUrl == defaultHash && document.location.href == initialHref && window['_ie_firstload']) {
currentHref = initialHref;
return;
}
if ((!flexAppUrl || flexAppUrl == defaultHash) && window['_ie_firstload']) {
newUrl = baseUrl + '#' + defaultHash;
flexAppUrl = defaultHash;
} else {
// for IE, tell the history frame to go somewhere without a '#'
// in order to get this entry into the browser history.
getHistoryFrame().src = historyFrameSourcePrefix + flexAppUrl;
}
setHash(flexAppUrl);
} else {
//ADR
if (backStack.length == 0 && initialState.flexAppUrl == flexAppUrl) {
initialState = createState(baseUrl, newUrl, flexAppUrl);
} else if(backStack.length > 0 && backStack[backStack.length - 1].flexAppUrl == flexAppUrl) {
backStack[backStack.length - 1] = createState(baseUrl, newUrl, flexAppUrl);
}
if (browser.safari && !browserHasHashChange) {
// for Safari, submit a form whose action points to the desired URL
if (browser.version <= 419.3) {
var file = window.location.pathname.toString();
file = file.substring(file.lastIndexOf("/")+1);
getFormElement().innerHTML = '<form name="historyForm" action="'+file+'#' + flexAppUrl + '" method="GET"></form>';
//get the current elements and add them to the form
var qs = window.location.search.substring(1);
var qs_arr = qs.split("&");
for (var i = 0; i < qs_arr.length; i++) {
var tmp = qs_arr[i].split("=");
var elem = document.createElement("input");
elem.type = "hidden";
elem.name = tmp[0];
elem.value = tmp[1];
document.forms.historyForm.appendChild(elem);
}
document.forms.historyForm.submit();
} else {
top.location.hash = flexAppUrl;
}
// We also have to maintain the history by hand for Safari
historyHash[history.length] = flexAppUrl;
_storeStates();
} else {
// Otherwise, just tell the browser to go there
setHash(flexAppUrl);
}
}
backStack.push(createState(baseUrl, newUrl, flexAppUrl));
}
function _storeStates() {
if (browser.safari) {
getRememberElement().value = historyHash.join(",");
}
}
function handleBackButton() {
//The "current" page is always at the top of the history stack.
var current = backStack.pop();
if (!current) { return; }
var last = backStack[backStack.length - 1];
if (!last && backStack.length == 0){
last = initialState;
}
forwardStack.push(current);
}
function handleForwardButton() {
//summary: private method. Do not call this directly.
var last = forwardStack.pop();
if (!last) { return; }
backStack.push(last);
}
function handleArbitraryUrl() {
//delete all the history entries
forwardStack = [];
}
/* Called periodically to poll to see if we need to detect navigation that has occurred */
function checkForUrlChange() {
if (browser.ie) {
if (currentHref != document.location.href && currentHref + '#' != document.location.href) {
//This occurs when the user has navigated to a specific URL
//within the app, and didn't use browser back/forward
//IE seems to have a bug where it stops updating the URL it
//shows the end-user at this point, but programatically it
//appears to be correct. Do a full app reload to get around
//this issue.
if (browser.version < 7) {
currentHref = document.location.href;
document.location.reload();
} else {
if (getHash() != getIframeHash()) {
// this.iframe.src = this.blankURL + hash;
var sourceToSet = historyFrameSourcePrefix + getHash();
getHistoryFrame().src = sourceToSet;
currentHref = document.location.href;
}
}
}
}
if (browser.safari && !browserHasHashChange) {
// For Safari, we have to check to see if history.length changed.
if (currentHistoryLength >= 0 && history.length != currentHistoryLength) {
//alert("did change: " + history.length + ", " + historyHash.length + "|" + historyHash[history.length] + "|>" + historyHash.join("|"));
var flexAppUrl = getHash();
if (browser.version < 528.16 /* Anything earlier than Safari 4.0 */)
{
// If it did change and we're running Safari 3.x or earlier,
// then we have to look the old state up in our hand-maintained
// array since document.location.hash won't have changed,
// then call back into BrowserManager.
currentHistoryLength = history.length;
flexAppUrl = historyHash[currentHistoryLength];
}
//ADR: to fix multiple
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
var pl = getPlayers();
for (var i = 0; i < pl.length; i++) {
pl[i].browserURLChange(flexAppUrl);
}
} else {
getPlayer().browserURLChange(flexAppUrl);
}
_storeStates();
}
}
if (browser.firefox && !browserHasHashChange) {
if (currentHref != document.location.href) {
var bsl = backStack.length;
var urlActions = {
back: false,
forward: false,
set: false
}
if ((window.location.hash == initialHash || window.location.href == initialHref) && (bsl == 1)) {
urlActions.back = true;
// FIXME: could this ever be a forward button?
// we can't clear it because we still need to check for forwards. Ugg.
// clearInterval(this.locationTimer);
handleBackButton();
}
// first check to see if we could have gone forward. We always halt on
// a no-hash item.
if (forwardStack.length > 0) {
if (forwardStack[forwardStack.length-1].flexAppUrl == getHash()) {
urlActions.forward = true;
handleForwardButton();
}
}
// ok, that didn't work, try someplace back in the history stack
if ((bsl >= 2) && (backStack[bsl - 2])) {
if (backStack[bsl - 2].flexAppUrl == getHash()) {
urlActions.back = true;
handleBackButton();
}
}
if (!urlActions.back && !urlActions.forward) {
var foundInStacks = {
back: -1,
forward: -1
}
for (var i = 0; i < backStack.length; i++) {
if (backStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
arbitraryUrl = true;
foundInStacks.back = i;
}
}
for (var i = 0; i < forwardStack.length; i++) {
if (forwardStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
arbitraryUrl = true;
foundInStacks.forward = i;
}
}
handleArbitraryUrl();
}
// Firefox changed; do a callback into BrowserManager to tell it.
currentHref = document.location.href;
var flexAppUrl = getHash();
//ADR: to fix multiple
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
var pl = getPlayers();
for (var i = 0; i < pl.length; i++) {
pl[i].browserURLChange(flexAppUrl);
}
} else {
getPlayer().browserURLChange(flexAppUrl);
}
}
}
}
var _initialize = function () {
browserHasHashChange = ("onhashchange" in document.body);
if (browser.ie)
{
var scripts = document.getElementsByTagName('script');
for (var i = 0, s; s = scripts[i]; i++) {
if (s.src.indexOf("history.js") > -1) {
var iframe_location = (new String(s.src)).replace("history.js", "historyFrame.html");
}
}
historyFrameSourcePrefix = iframe_location + "?";
var src = historyFrameSourcePrefix;
var iframe = document.createElement("iframe");
iframe.id = 'ie_historyFrame';
iframe.name = 'ie_historyFrame';
iframe.src = 'javascript:false;';
try {
document.body.appendChild(iframe);
} catch(e) {
setTimeout(function() {
document.body.appendChild(iframe);
}, 0);
}
}
if (browser.safari && !browserHasHashChange)
{
var rememberDiv = document.createElement("div");
rememberDiv.id = 'safari_rememberDiv';
document.body.appendChild(rememberDiv);
rememberDiv.innerHTML = '<input type="text" id="safari_remember_field" style="width: 500px;">';
var formDiv = document.createElement("div");
formDiv.id = 'safari_formDiv';
document.body.appendChild(formDiv);
var reloader_content = document.createElement('div');
reloader_content.id = 'safarireloader';
var scripts = document.getElementsByTagName('script');
for (var i = 0, s; s = scripts[i]; i++) {
if (s.src.indexOf("history.js") > -1) {
html = (new String(s.src)).replace(".js", ".html");
}
}
reloader_content.innerHTML = '<iframe id="safarireloader-iframe" src="about:blank" frameborder="no" scrolling="no"></iframe>';
document.body.appendChild(reloader_content);
reloader_content.style.position = 'absolute';
reloader_content.style.left = reloader_content.style.top = '-9999px';
iframe = reloader_content.getElementsByTagName('iframe')[0];
if (document.getElementById("safari_remember_field").value != "" ) {
historyHash = document.getElementById("safari_remember_field").value.split(",");
}
}
if (browserHasHashChange)
document.body.onhashchange = hashChangeHandler;
}
return {
historyHash: historyHash,
backStack: function() { return backStack; },
forwardStack: function() { return forwardStack },
getPlayer: getPlayer,
initialize: function(src) {
_initialize(src);
},
setURL: function(url) {
document.location.href = url;
},
getURL: function() {
return document.location.href;
},
getTitle: function() {
return document.title;
},
setTitle: function(title) {
try {
backStack[backStack.length - 1].title = title;
} catch(e) { }
//if on safari, set the title to be the empty string.
if (browser.safari) {
if (title == "") {
try {
var tmp = window.location.href.toString();
title = tmp.substring((tmp.lastIndexOf("/")+1), tmp.lastIndexOf("#"));
} catch(e) {
title = "";
}
}
}
document.title = title;
},
setDefaultURL: function(def)
{
defaultHash = def;
def = getHash();
//trailing ? is important else an extra frame gets added to the history
//when navigating back to the first page. Alternatively could check
//in history frame navigation to compare # and ?.
if (browser.ie)
{
window['_ie_firstload'] = true;
var sourceToSet = historyFrameSourcePrefix + def;
var func = function() {
getHistoryFrame().src = sourceToSet;
window.location.replace("#" + def);
setInterval(checkForUrlChange, 50);
}
try {
func();
} catch(e) {
window.setTimeout(function() { func(); }, 0);
}
}
if (browser.safari)
{
currentHistoryLength = history.length;
if (historyHash.length == 0) {
historyHash[currentHistoryLength] = def;
var newloc = "#" + def;
window.location.replace(newloc);
} else {
//alert(historyHash[historyHash.length-1]);
}
setInterval(checkForUrlChange, 50);
}
if (browser.firefox || browser.opera)
{
var reg = new RegExp("#" + def + "$");
if (window.location.toString().match(reg)) {
} else {
var newloc ="#" + def;
window.location.replace(newloc);
}
setInterval(checkForUrlChange, 50);
}
},
/* Set the current browser URL; called from inside BrowserManager to propagate
* the application state out to the container.
*/
setBrowserURL: function(flexAppUrl, objectId) {
if (browser.ie && typeof objectId != "undefined") {
currentObjectId = objectId;
}
//fromIframe = fromIframe || false;
//fromFlex = fromFlex || false;
//alert("setBrowserURL: " + flexAppUrl);
//flexAppUrl = (flexAppUrl == "") ? defaultHash : flexAppUrl ;
var pos = document.location.href.indexOf('#');
var baseUrl = pos != -1 ? document.location.href.substr(0, pos) : document.location.href;
var newUrl = baseUrl + '#' + flexAppUrl;
if (document.location.href != newUrl && document.location.href + '#' != newUrl) {
currentHref = newUrl;
addHistoryEntry(baseUrl, newUrl, flexAppUrl);
currentHistoryLength = history.length;
}
},
browserURLChange: function(flexAppUrl) {
var objectId = null;
if (browser.ie && currentObjectId != null) {
objectId = currentObjectId;
}
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
var pl = getPlayers();
for (var i = 0; i < pl.length; i++) {
try {
pl[i].browserURLChange(flexAppUrl);
} catch(e) { }
}
} else {
try {
getPlayer(objectId).browserURLChange(flexAppUrl);
} catch(e) { }
}
currentObjectId = null;
},
getUserAgent: function() {
return navigator.userAgent;
},
getPlatform: function() {
return navigator.platform;
}
}
})();
// Initialization
// Automated unit testing and other diagnostics
function setURL(url)
{
document.location.href = url;
}
function backButton()
{
history.back();
}
function forwardButton()
{
history.forward();
}
function goForwardOrBackInHistory(step)
{
history.go(step);
}
//BrowserHistoryUtils.addEvent(window, "load", function() { BrowserHistory.initialize(); });
(function(i) {
var u =navigator.userAgent;var e=/*@cc_on!@*/false;
var st = setTimeout;
if(/webkit/i.test(u)){
st(function(){
var dr=document.readyState;
if(dr=="loaded"||dr=="complete"){i()}
else{st(arguments.callee,10);}},10);
} else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){
document.addEventListener("DOMContentLoaded",i,false);
} else if(e){
(function(){
var t=document.createElement('doc:rdy');
try{t.doScroll('left');
i();t=null;
}catch(e){st(arguments.callee,0);}})();
} else{
window.onload=i;
}
})( function() {BrowserHistory.initialize();} );

View File

@ -1,29 +0,0 @@
<html>
<head>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="-1">
</head>
<body>
<script>
function processUrl()
{
var pos = url.indexOf("?");
url = pos != -1 ? url.substr(pos + 1) : "";
if (!parent._ie_firstload) {
parent.BrowserHistory.setBrowserURL(url);
try {
parent.BrowserHistory.browserURLChange(url);
} catch(e) { }
} else {
parent._ie_firstload = false;
}
}
var url = document.location.href;
processUrl();
document.write(encodeURIComponent(url));
</script>
Hidden frame for Browser History support.
</body>
</html>

View File

@ -1,777 +0,0 @@
/*! SWFObject v2.2 <http://code.google.com/p/swfobject/>
is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
var swfobject = function() {
var UNDEF = "undefined",
OBJECT = "object",
SHOCKWAVE_FLASH = "Shockwave Flash",
SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
FLASH_MIME_TYPE = "application/x-shockwave-flash",
EXPRESS_INSTALL_ID = "SWFObjectExprInst",
ON_READY_STATE_CHANGE = "onreadystatechange",
win = window,
doc = document,
nav = navigator,
plugin = false,
domLoadFnArr = [main],
regObjArr = [],
objIdArr = [],
listenersArr = [],
storedAltContent,
storedAltContentId,
storedCallbackFn,
storedCallbackObj,
isDomLoaded = false,
isExpressInstallActive = false,
dynamicStylesheet,
dynamicStylesheetMedia,
autoHideShow = true,
/* Centralized function for browser feature detection
- User agent string detection is only used when no good alternative is possible
- Is executed directly for optimal performance
*/
ua = function() {
var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
u = nav.userAgent.toLowerCase(),
p = nav.platform.toLowerCase(),
windows = p ? /win/.test(p) : /win/.test(u),
mac = p ? /mac/.test(p) : /mac/.test(u),
webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
playerVersion = [0,0,0],
d = null;
if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
d = nav.plugins[SHOCKWAVE_FLASH].description;
if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
plugin = true;
ie = false; // cascaded feature detection for Internet Explorer
d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
}
}
else if (typeof win.ActiveXObject != UNDEF) {
try {
var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
if (a) { // a will return null when ActiveX is disabled
d = a.GetVariable("$version");
if (d) {
ie = true; // cascaded feature detection for Internet Explorer
d = d.split(" ")[1].split(",");
playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
}
}
}
catch(e) {}
}
return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
}(),
/* Cross-browser onDomLoad
- Will fire an event as soon as the DOM of a web page is loaded
- Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/
- Regular onload serves as fallback
*/
onDomLoad = function() {
if (!ua.w3) { return; }
if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically
callDomLoadFunctions();
}
if (!isDomLoaded) {
if (typeof doc.addEventListener != UNDEF) {
doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
}
if (ua.ie && ua.win) {
doc.attachEvent(ON_READY_STATE_CHANGE, function() {
if (doc.readyState == "complete") {
doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
callDomLoadFunctions();
}
});
if (win == top) { // if not inside an iframe
(function(){
if (isDomLoaded) { return; }
try {
doc.documentElement.doScroll("left");
}
catch(e) {
setTimeout(arguments.callee, 0);
return;
}
callDomLoadFunctions();
})();
}
}
if (ua.wk) {
(function(){
if (isDomLoaded) { return; }
if (!/loaded|complete/.test(doc.readyState)) {
setTimeout(arguments.callee, 0);
return;
}
callDomLoadFunctions();
})();
}
addLoadEvent(callDomLoadFunctions);
}
}();
function callDomLoadFunctions() {
if (isDomLoaded) { return; }
try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early
var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
t.parentNode.removeChild(t);
}
catch (e) { return; }
isDomLoaded = true;
var dl = domLoadFnArr.length;
for (var i = 0; i < dl; i++) {
domLoadFnArr[i]();
}
}
function addDomLoadEvent(fn) {
if (isDomLoaded) {
fn();
}
else {
domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
}
}
/* Cross-browser onload
- Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
- Will fire an event as soon as a web page including all of its assets are loaded
*/
function addLoadEvent(fn) {
if (typeof win.addEventListener != UNDEF) {
win.addEventListener("load", fn, false);
}
else if (typeof doc.addEventListener != UNDEF) {
doc.addEventListener("load", fn, false);
}
else if (typeof win.attachEvent != UNDEF) {
addListener(win, "onload", fn);
}
else if (typeof win.onload == "function") {
var fnOld = win.onload;
win.onload = function() {
fnOld();
fn();
};
}
else {
win.onload = fn;
}
}
/* Main function
- Will preferably execute onDomLoad, otherwise onload (as a fallback)
*/
function main() {
if (plugin) {
testPlayerVersion();
}
else {
matchVersions();
}
}
/* Detect the Flash Player version for non-Internet Explorer browsers
- Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:
a. Both release and build numbers can be detected
b. Avoid wrong descriptions by corrupt installers provided by Adobe
c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports
- Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available
*/
function testPlayerVersion() {
var b = doc.getElementsByTagName("body")[0];
var o = createElement(OBJECT);
o.setAttribute("type", FLASH_MIME_TYPE);
var t = b.appendChild(o);
if (t) {
var counter = 0;
(function(){
if (typeof t.GetVariable != UNDEF) {
var d = t.GetVariable("$version");
if (d) {
d = d.split(" ")[1].split(",");
ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
}
}
else if (counter < 10) {
counter++;
setTimeout(arguments.callee, 10);
return;
}
b.removeChild(o);
t = null;
matchVersions();
})();
}
else {
matchVersions();
}
}
/* Perform Flash Player and SWF version matching; static publishing only
*/
function matchVersions() {
var rl = regObjArr.length;
if (rl > 0) {
for (var i = 0; i < rl; i++) { // for each registered object element
var id = regObjArr[i].id;
var cb = regObjArr[i].callbackFn;
var cbObj = {success:false, id:id};
if (ua.pv[0] > 0) {
var obj = getElementById(id);
if (obj) {
if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match!
setVisibility(id, true);
if (cb) {
cbObj.success = true;
cbObj.ref = getObjectById(id);
cb(cbObj);
}
}
else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported
var att = {};
att.data = regObjArr[i].expressInstall;
att.width = obj.getAttribute("width") || "0";
att.height = obj.getAttribute("height") || "0";
if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
// parse HTML object param element's name-value pairs
var par = {};
var p = obj.getElementsByTagName("param");
var pl = p.length;
for (var j = 0; j < pl; j++) {
if (p[j].getAttribute("name").toLowerCase() != "movie") {
par[p[j].getAttribute("name")] = p[j].getAttribute("value");
}
}
showExpressInstall(att, par, id, cb);
}
else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF
displayAltContent(obj);
if (cb) { cb(cbObj); }
}
}
}
else { // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content)
setVisibility(id, true);
if (cb) {
var o = getObjectById(id); // test whether there is an HTML object element or not
if (o && typeof o.SetVariable != UNDEF) {
cbObj.success = true;
cbObj.ref = o;
}
cb(cbObj);
}
}
}
}
}
function getObjectById(objectIdStr) {
var r = null;
var o = getElementById(objectIdStr);
if (o && o.nodeName == "OBJECT") {
if (typeof o.SetVariable != UNDEF) {
r = o;
}
else {
var n = o.getElementsByTagName(OBJECT)[0];
if (n) {
r = n;
}
}
}
return r;
}
/* Requirements for Adobe Express Install
- only one instance can be active at a time
- fp 6.0.65 or higher
- Win/Mac OS only
- no Webkit engines older than version 312
*/
function canExpressInstall() {
return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
}
/* Show the Adobe Express Install dialog
- Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75
*/
function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
isExpressInstallActive = true;
storedCallbackFn = callbackFn || null;
storedCallbackObj = {success:false, id:replaceElemIdStr};
var obj = getElementById(replaceElemIdStr);
if (obj) {
if (obj.nodeName == "OBJECT") { // static publishing
storedAltContent = abstractAltContent(obj);
storedAltContentId = null;
}
else { // dynamic publishing
storedAltContent = obj;
storedAltContentId = replaceElemIdStr;
}
att.id = EXPRESS_INSTALL_ID;
if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }
if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }
doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
fv = "MMredirectURL=" + encodeURI(window.location).toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
if (typeof par.flashvars != UNDEF) {
par.flashvars += "&" + fv;
}
else {
par.flashvars = fv;
}
// IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
if (ua.ie && ua.win && obj.readyState != 4) {
var newObj = createElement("div");
replaceElemIdStr += "SWFObjectNew";
newObj.setAttribute("id", replaceElemIdStr);
obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf
obj.style.display = "none";
(function(){
if (obj.readyState == 4) {
obj.parentNode.removeChild(obj);
}
else {
setTimeout(arguments.callee, 10);
}
})();
}
createSWF(att, par, replaceElemIdStr);
}
}
/* Functions to abstract and display alternative content
*/
function displayAltContent(obj) {
if (ua.ie && ua.win && obj.readyState != 4) {
// IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
var el = createElement("div");
obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content
el.parentNode.replaceChild(abstractAltContent(obj), el);
obj.style.display = "none";
(function(){
if (obj.readyState == 4) {
obj.parentNode.removeChild(obj);
}
else {
setTimeout(arguments.callee, 10);
}
})();
}
else {
obj.parentNode.replaceChild(abstractAltContent(obj), obj);
}
}
function abstractAltContent(obj) {
var ac = createElement("div");
if (ua.win && ua.ie) {
ac.innerHTML = obj.innerHTML;
}
else {
var nestedObj = obj.getElementsByTagName(OBJECT)[0];
if (nestedObj) {
var c = nestedObj.childNodes;
if (c) {
var cl = c.length;
for (var i = 0; i < cl; i++) {
if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
ac.appendChild(c[i].cloneNode(true));
}
}
}
}
}
return ac;
}
/* Cross-browser dynamic SWF creation
*/
function createSWF(attObj, parObj, id) {
var r, el = getElementById(id);
if (ua.wk && ua.wk < 312) { return r; }
if (el) {
if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
attObj.id = id;
}
if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML
var att = "";
for (var i in attObj) {
if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries
if (i.toLowerCase() == "data") {
parObj.movie = attObj[i];
}
else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
att += ' class="' + attObj[i] + '"';
}
else if (i.toLowerCase() != "classid") {
att += ' ' + i + '="' + attObj[i] + '"';
}
}
}
var par = "";
for (var j in parObj) {
if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries
par += '<param name="' + j + '" value="' + parObj[j] + '" />';
}
}
el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)
r = getElementById(attObj.id);
}
else { // well-behaving browsers
var o = createElement(OBJECT);
o.setAttribute("type", FLASH_MIME_TYPE);
for (var m in attObj) {
if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries
if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
o.setAttribute("class", attObj[m]);
}
else if (m.toLowerCase() != "classid") { // filter out IE specific attribute
o.setAttribute(m, attObj[m]);
}
}
}
for (var n in parObj) {
if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element
createObjParam(o, n, parObj[n]);
}
}
el.parentNode.replaceChild(o, el);
r = o;
}
}
return r;
}
function createObjParam(el, pName, pValue) {
var p = createElement("param");
p.setAttribute("name", pName);
p.setAttribute("value", pValue);
el.appendChild(p);
}
/* Cross-browser SWF removal
- Especially needed to safely and completely remove a SWF in Internet Explorer
*/
function removeSWF(id) {
var obj = getElementById(id);
if (obj && obj.nodeName == "OBJECT") {
if (ua.ie && ua.win) {
obj.style.display = "none";
(function(){
if (obj.readyState == 4) {
removeObjectInIE(id);
}
else {
setTimeout(arguments.callee, 10);
}
})();
}
else {
obj.parentNode.removeChild(obj);
}
}
}
function removeObjectInIE(id) {
var obj = getElementById(id);
if (obj) {
for (var i in obj) {
if (typeof obj[i] == "function") {
obj[i] = null;
}
}
obj.parentNode.removeChild(obj);
}
}
/* Functions to optimize JavaScript compression
*/
function getElementById(id) {
var el = null;
try {
el = doc.getElementById(id);
}
catch (e) {}
return el;
}
function createElement(el) {
return doc.createElement(el);
}
/* Updated attachEvent function for Internet Explorer
- Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
*/
function addListener(target, eventType, fn) {
target.attachEvent(eventType, fn);
listenersArr[listenersArr.length] = [target, eventType, fn];
}
/* Flash Player and SWF content version matching
*/
function hasPlayerVersion(rv) {
var pv = ua.pv, v = rv.split(".");
v[0] = parseInt(v[0], 10);
v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
v[2] = parseInt(v[2], 10) || 0;
return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
}
/* Cross-browser dynamic CSS creation
- Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php
*/
function createCSS(sel, decl, media, newStyle) {
if (ua.ie && ua.mac) { return; }
var h = doc.getElementsByTagName("head")[0];
if (!h) { return; } // to also support badly authored HTML pages that lack a head element
var m = (media && typeof media == "string") ? media : "screen";
if (newStyle) {
dynamicStylesheet = null;
dynamicStylesheetMedia = null;
}
if (!dynamicStylesheet || dynamicStylesheetMedia != m) {
// create dynamic stylesheet + get a global reference to it
var s = createElement("style");
s.setAttribute("type", "text/css");
s.setAttribute("media", m);
dynamicStylesheet = h.appendChild(s);
if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
}
dynamicStylesheetMedia = m;
}
// add style rule
if (ua.ie && ua.win) {
if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
dynamicStylesheet.addRule(sel, decl);
}
}
else {
if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
}
}
}
function setVisibility(id, isVisible) {
if (!autoHideShow) { return; }
var v = isVisible ? "visible" : "hidden";
if (isDomLoaded && getElementById(id)) {
getElementById(id).style.visibility = v;
}
else {
createCSS("#" + id, "visibility:" + v);
}
}
/* Filter to avoid XSS attacks
*/
function urlEncodeIfNecessary(s) {
var regex = /[\\\"<>\.;]/;
var hasBadChars = regex.exec(s) != null;
return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
}
/* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
*/
var cleanup = function() {
if (ua.ie && ua.win) {
window.attachEvent("onunload", function() {
// remove listeners to avoid memory leaks
var ll = listenersArr.length;
for (var i = 0; i < ll; i++) {
listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
}
// cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
var il = objIdArr.length;
for (var j = 0; j < il; j++) {
removeSWF(objIdArr[j]);
}
// cleanup library's main closures to avoid memory leaks
for (var k in ua) {
ua[k] = null;
}
ua = null;
for (var l in swfobject) {
swfobject[l] = null;
}
swfobject = null;
});
}
}();
return {
/* Public API
- Reference: http://code.google.com/p/swfobject/wiki/documentation
*/
registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
if (ua.w3 && objectIdStr && swfVersionStr) {
var regObj = {};
regObj.id = objectIdStr;
regObj.swfVersion = swfVersionStr;
regObj.expressInstall = xiSwfUrlStr;
regObj.callbackFn = callbackFn;
regObjArr[regObjArr.length] = regObj;
setVisibility(objectIdStr, false);
}
else if (callbackFn) {
callbackFn({success:false, id:objectIdStr});
}
},
getObjectById: function(objectIdStr) {
if (ua.w3) {
return getObjectById(objectIdStr);
}
},
embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
var callbackObj = {success:false, id:replaceElemIdStr};
if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
setVisibility(replaceElemIdStr, false);
addDomLoadEvent(function() {
widthStr += ""; // auto-convert to string
heightStr += "";
var att = {};
if (attObj && typeof attObj === OBJECT) {
for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs
att[i] = attObj[i];
}
}
att.data = swfUrlStr;
att.width = widthStr;
att.height = heightStr;
var par = {};
if (parObj && typeof parObj === OBJECT) {
for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs
par[j] = parObj[j];
}
}
if (flashvarsObj && typeof flashvarsObj === OBJECT) {
for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs
if (typeof par.flashvars != UNDEF) {
par.flashvars += "&" + k + "=" + flashvarsObj[k];
}
else {
par.flashvars = k + "=" + flashvarsObj[k];
}
}
}
if (hasPlayerVersion(swfVersionStr)) { // create SWF
var obj = createSWF(att, par, replaceElemIdStr);
if (att.id == replaceElemIdStr) {
setVisibility(replaceElemIdStr, true);
}
callbackObj.success = true;
callbackObj.ref = obj;
}
else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install
att.data = xiSwfUrlStr;
showExpressInstall(att, par, replaceElemIdStr, callbackFn);
return;
}
else { // show alternative content
setVisibility(replaceElemIdStr, true);
}
if (callbackFn) { callbackFn(callbackObj); }
});
}
else if (callbackFn) { callbackFn(callbackObj); }
},
switchOffAutoHideShow: function() {
autoHideShow = false;
},
ua: ua,
getFlashPlayerVersion: function() {
return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
},
hasFlashPlayerVersion: hasPlayerVersion,
createSWF: function(attObj, parObj, replaceElemIdStr) {
if (ua.w3) {
return createSWF(attObj, parObj, replaceElemIdStr);
}
else {
return undefined;
}
},
showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
if (ua.w3 && canExpressInstall()) {
showExpressInstall(att, par, replaceElemIdStr, callbackFn);
}
},
removeSWF: function(objElemIdStr) {
if (ua.w3) {
removeSWF(objElemIdStr);
}
},
createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
if (ua.w3) {
createCSS(selStr, declStr, mediaStr, newStyleBoolean);
}
},
addDomLoadEvent: addDomLoadEvent,
addLoadEvent: addLoadEvent,
getQueryParamValue: function(param) {
var q = doc.location.search || doc.location.hash;
if (q) {
if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark
if (param == null) {
return urlEncodeIfNecessary(q);
}
var pairs = q.split("&");
for (var i = 0; i < pairs.length; i++) {
if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
}
}
}
return "";
},
// For internal usage only
expressInstallCallback: function() {
if (isExpressInstallActive) {
var obj = getElementById(EXPRESS_INSTALL_ID);
if (obj && storedAltContent) {
obj.parentNode.replaceChild(storedAltContent, obj);
if (storedAltContentId) {
setVisibility(storedAltContentId, true);
if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
}
if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
}
isExpressInstallActive = false;
}
}
};
}();

View File

@ -1,108 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- saved from url=(0014)about:internet -->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<!--
Smart developers always View Source.
This application was built using Adobe Flex, an open source framework
for building rich Internet applications that get delivered via the
Flash Player or to desktops via Adobe AIR.
Learn more about Flex at http://flex.org
// -->
<head>
<title></title>
<meta name="google" value="notranslate" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- Include CSS to eliminate any default margins/padding and set the height of the html element and
the body element to 100%, because Firefox, or any Gecko based browser, interprets percentage as
the percentage of the height of its parent container, which has to be set explicitly. Fix for
Firefox 3.6 focus border issues. Initially, don't display flashContent div so it won't show
if JavaScript disabled.
-->
<style type="text/css" media="screen">
html, body { height:100%; }
body { margin:0; padding:0; overflow:auto; text-align:center;
background-color: #ffffff; }
object:focus { outline:none; }
#flashContent { display:none; }
</style>
<!-- Enable Browser History by replacing useBrowserHistory tokens with two hyphens -->
<!-- BEGIN Browser History required section -->
<link rel="stylesheet" type="text/css" href="history/history.css" />
<script type="text/javascript" src="history/history.js"></script>
<!-- END Browser History required section -->
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript">
// For version detection, set to min. required Flash Player version, or 0 (or 0.0.0), for no version detection.
var swfVersionStr = "11.4.0";
// To use express install, set to playerProductInstall.swf, otherwise the empty string.
var xiSwfUrlStr = "playerProductInstall.swf";
var flashvars = {};
var params = {};
params.quality = "high";
params.bgcolor = "#ffffff";
params.allowscriptaccess = "sameDomain";
params.allowfullscreen = "true";
var attributes = {};
attributes.id = "CIMBridge";
attributes.name = "CIMBridge";
attributes.align = "middle";
swfobject.embedSWF(
"CIMBridge.swf", "flashContent",
"100%", "100%",
swfVersionStr, xiSwfUrlStr,
flashvars, params, attributes);
// JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
swfobject.createCSS("#flashContent", "display:block;text-align:left;");
</script>
</head>
<body>
<!-- SWFObject's dynamic embed method replaces this alternative HTML content with Flash content when enough
JavaScript and Flash plug-in support is available. The div is initially hidden so that it doesn't show
when JavaScript is disabled.
-->
<div id="flashContent">
<p>
To view this page ensure that Adobe Flash Player version
11.4.0 or greater is installed.
</p>
<script type="text/javascript">
var pageHost = ((document.location.protocol == "https:") ? "https://" : "http://");
document.write("<a href='http://www.adobe.com/go/getflashplayer'><img src='"
+ pageHost + "www.adobe.com/images/shared/download_buttons/get_flash_player.gif' alt='Get Adobe Flash player' /></a>" );
</script>
</div>
<noscript>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="100%" height="100%" id="CIMBridge">
<param name="movie" value="CIMBridge.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="true" />
<!--[if !IE]>-->
<object type="application/x-shockwave-flash" data="CIMBridge.swf" width="100%" height="100%">
<param name="quality" value="high" />
<param name="bgcolor" value="#ffffff" />
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="true" />
<!--<![endif]-->
<!--[if gte IE 6]>-->
<p>
Either scripts and active content are not permitted to run or Adobe Flash Player version
11.4.0 or greater is not installed.
</p>
<!--<![endif]-->
<a href="http://www.adobe.com/go/getflashplayer">
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash Player" />
</a>
<!--[if !IE]>-->
</object>
<!--<![endif]-->
</object>
</noscript>
</body>
</html>

View File

@ -1,6 +0,0 @@
/* This CSS stylesheet defines styles used by required elements in a flex application page that supports browser history */
#ie_historyFrame { width: 0px; height: 0px; display:none }
#firefox_anchorDiv { width: 0px; height: 0px; display:none }
#safari_formDiv { width: 0px; height: 0px; display:none }
#safari_rememberDiv { width: 0px; height: 0px; display:none }

View File

@ -1,678 +0,0 @@
BrowserHistoryUtils = {
addEvent: function(elm, evType, fn, useCapture) {
useCapture = useCapture || false;
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
}
else if (elm.attachEvent) {
var r = elm.attachEvent('on' + evType, fn);
return r;
}
else {
elm['on' + evType] = fn;
}
}
}
BrowserHistory = (function() {
// type of browser
var browser = {
ie: false,
ie8: false,
firefox: false,
safari: false,
opera: false,
version: -1
};
// Default app state URL to use when no fragment ID present
var defaultHash = '';
// Last-known app state URL
var currentHref = document.location.href;
// Initial URL (used only by IE)
var initialHref = document.location.href;
// Initial URL (used only by IE)
var initialHash = document.location.hash;
// History frame source URL prefix (used only by IE)
var historyFrameSourcePrefix = 'history/historyFrame.html?';
// History maintenance (used only by Safari)
var currentHistoryLength = -1;
// Flag to denote the existence of onhashchange
var browserHasHashChange = false;
var historyHash = [];
var initialState = createState(initialHref, initialHref + '#' + initialHash, initialHash);
var backStack = [];
var forwardStack = [];
var currentObjectId = null;
//UserAgent detection
var useragent = navigator.userAgent.toLowerCase();
if (useragent.indexOf("opera") != -1) {
browser.opera = true;
} else if (useragent.indexOf("msie") != -1) {
browser.ie = true;
browser.version = parseFloat(useragent.substring(useragent.indexOf('msie') + 4));
if (browser.version == 8)
{
browser.ie = false;
browser.ie8 = true;
}
} else if (useragent.indexOf("safari") != -1) {
browser.safari = true;
browser.version = parseFloat(useragent.substring(useragent.indexOf('safari') + 7));
} else if (useragent.indexOf("gecko") != -1) {
browser.firefox = true;
}
if (browser.ie == true && browser.version == 7) {
window["_ie_firstload"] = false;
}
function hashChangeHandler()
{
currentHref = document.location.href;
var flexAppUrl = getHash();
//ADR: to fix multiple
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
var pl = getPlayers();
for (var i = 0; i < pl.length; i++) {
pl[i].browserURLChange(flexAppUrl);
}
} else {
getPlayer().browserURLChange(flexAppUrl);
}
}
// Accessor functions for obtaining specific elements of the page.
function getHistoryFrame()
{
return document.getElementById('ie_historyFrame');
}
function getFormElement()
{
return document.getElementById('safari_formDiv');
}
function getRememberElement()
{
return document.getElementById("safari_remember_field");
}
// Get the Flash player object for performing ExternalInterface callbacks.
// Updated for changes to SWFObject2.
function getPlayer(id) {
var i;
if (id && document.getElementById(id)) {
var r = document.getElementById(id);
if (typeof r.SetVariable != "undefined") {
return r;
}
else {
var o = r.getElementsByTagName("object");
var e = r.getElementsByTagName("embed");
for (i = 0; i < o.length; i++) {
if (typeof o[i].browserURLChange != "undefined")
return o[i];
}
for (i = 0; i < e.length; i++) {
if (typeof e[i].browserURLChange != "undefined")
return e[i];
}
}
}
else {
var o = document.getElementsByTagName("object");
var e = document.getElementsByTagName("embed");
for (i = 0; i < e.length; i++) {
if (typeof e[i].browserURLChange != "undefined")
{
return e[i];
}
}
for (i = 0; i < o.length; i++) {
if (typeof o[i].browserURLChange != "undefined")
{
return o[i];
}
}
}
return undefined;
}
function getPlayers() {
var i;
var players = [];
if (players.length == 0) {
var tmp = document.getElementsByTagName('object');
for (i = 0; i < tmp.length; i++)
{
if (typeof tmp[i].browserURLChange != "undefined")
players.push(tmp[i]);
}
}
if (players.length == 0 || players[0].object == null) {
var tmp = document.getElementsByTagName('embed');
for (i = 0; i < tmp.length; i++)
{
if (typeof tmp[i].browserURLChange != "undefined")
players.push(tmp[i]);
}
}
return players;
}
function getIframeHash() {
var doc = getHistoryFrame().contentWindow.document;
var hash = String(doc.location.search);
if (hash.length == 1 && hash.charAt(0) == "?") {
hash = "";
}
else if (hash.length >= 2 && hash.charAt(0) == "?") {
hash = hash.substring(1);
}
return hash;
}
/* Get the current location hash excluding the '#' symbol. */
function getHash() {
// It would be nice if we could use document.location.hash here,
// but it's faulty sometimes.
var idx = document.location.href.indexOf('#');
return (idx >= 0) ? document.location.href.substr(idx+1) : '';
}
/* Get the current location hash excluding the '#' symbol. */
function setHash(hash) {
// It would be nice if we could use document.location.hash here,
// but it's faulty sometimes.
if (hash == '') hash = '#'
document.location.hash = hash;
}
function createState(baseUrl, newUrl, flexAppUrl) {
return { 'baseUrl': baseUrl, 'newUrl': newUrl, 'flexAppUrl': flexAppUrl, 'title': null };
}
/* Add a history entry to the browser.
* baseUrl: the portion of the location prior to the '#'
* newUrl: the entire new URL, including '#' and following fragment
* flexAppUrl: the portion of the location following the '#' only
*/
function addHistoryEntry(baseUrl, newUrl, flexAppUrl) {
//delete all the history entries
forwardStack = [];
if (browser.ie) {
//Check to see if we are being asked to do a navigate for the first
//history entry, and if so ignore, because it's coming from the creation
//of the history iframe
if (flexAppUrl == defaultHash && document.location.href == initialHref && window['_ie_firstload']) {
currentHref = initialHref;
return;
}
if ((!flexAppUrl || flexAppUrl == defaultHash) && window['_ie_firstload']) {
newUrl = baseUrl + '#' + defaultHash;
flexAppUrl = defaultHash;
} else {
// for IE, tell the history frame to go somewhere without a '#'
// in order to get this entry into the browser history.
getHistoryFrame().src = historyFrameSourcePrefix + flexAppUrl;
}
setHash(flexAppUrl);
} else {
//ADR
if (backStack.length == 0 && initialState.flexAppUrl == flexAppUrl) {
initialState = createState(baseUrl, newUrl, flexAppUrl);
} else if(backStack.length > 0 && backStack[backStack.length - 1].flexAppUrl == flexAppUrl) {
backStack[backStack.length - 1] = createState(baseUrl, newUrl, flexAppUrl);
}
if (browser.safari && !browserHasHashChange) {
// for Safari, submit a form whose action points to the desired URL
if (browser.version <= 419.3) {
var file = window.location.pathname.toString();
file = file.substring(file.lastIndexOf("/")+1);
getFormElement().innerHTML = '<form name="historyForm" action="'+file+'#' + flexAppUrl + '" method="GET"></form>';
//get the current elements and add them to the form
var qs = window.location.search.substring(1);
var qs_arr = qs.split("&");
for (var i = 0; i < qs_arr.length; i++) {
var tmp = qs_arr[i].split("=");
var elem = document.createElement("input");
elem.type = "hidden";
elem.name = tmp[0];
elem.value = tmp[1];
document.forms.historyForm.appendChild(elem);
}
document.forms.historyForm.submit();
} else {
top.location.hash = flexAppUrl;
}
// We also have to maintain the history by hand for Safari
historyHash[history.length] = flexAppUrl;
_storeStates();
} else {
// Otherwise, just tell the browser to go there
setHash(flexAppUrl);
}
}
backStack.push(createState(baseUrl, newUrl, flexAppUrl));
}
function _storeStates() {
if (browser.safari) {
getRememberElement().value = historyHash.join(",");
}
}
function handleBackButton() {
//The "current" page is always at the top of the history stack.
var current = backStack.pop();
if (!current) { return; }
var last = backStack[backStack.length - 1];
if (!last && backStack.length == 0){
last = initialState;
}
forwardStack.push(current);
}
function handleForwardButton() {
//summary: private method. Do not call this directly.
var last = forwardStack.pop();
if (!last) { return; }
backStack.push(last);
}
function handleArbitraryUrl() {
//delete all the history entries
forwardStack = [];
}
/* Called periodically to poll to see if we need to detect navigation that has occurred */
function checkForUrlChange() {
if (browser.ie) {
if (currentHref != document.location.href && currentHref + '#' != document.location.href) {
//This occurs when the user has navigated to a specific URL
//within the app, and didn't use browser back/forward
//IE seems to have a bug where it stops updating the URL it
//shows the end-user at this point, but programatically it
//appears to be correct. Do a full app reload to get around
//this issue.
if (browser.version < 7) {
currentHref = document.location.href;
document.location.reload();
} else {
if (getHash() != getIframeHash()) {
// this.iframe.src = this.blankURL + hash;
var sourceToSet = historyFrameSourcePrefix + getHash();
getHistoryFrame().src = sourceToSet;
currentHref = document.location.href;
}
}
}
}
if (browser.safari && !browserHasHashChange) {
// For Safari, we have to check to see if history.length changed.
if (currentHistoryLength >= 0 && history.length != currentHistoryLength) {
//alert("did change: " + history.length + ", " + historyHash.length + "|" + historyHash[history.length] + "|>" + historyHash.join("|"));
var flexAppUrl = getHash();
if (browser.version < 528.16 /* Anything earlier than Safari 4.0 */)
{
// If it did change and we're running Safari 3.x or earlier,
// then we have to look the old state up in our hand-maintained
// array since document.location.hash won't have changed,
// then call back into BrowserManager.
currentHistoryLength = history.length;
flexAppUrl = historyHash[currentHistoryLength];
}
//ADR: to fix multiple
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
var pl = getPlayers();
for (var i = 0; i < pl.length; i++) {
pl[i].browserURLChange(flexAppUrl);
}
} else {
getPlayer().browserURLChange(flexAppUrl);
}
_storeStates();
}
}
if (browser.firefox && !browserHasHashChange) {
if (currentHref != document.location.href) {
var bsl = backStack.length;
var urlActions = {
back: false,
forward: false,
set: false
}
if ((window.location.hash == initialHash || window.location.href == initialHref) && (bsl == 1)) {
urlActions.back = true;
// FIXME: could this ever be a forward button?
// we can't clear it because we still need to check for forwards. Ugg.
// clearInterval(this.locationTimer);
handleBackButton();
}
// first check to see if we could have gone forward. We always halt on
// a no-hash item.
if (forwardStack.length > 0) {
if (forwardStack[forwardStack.length-1].flexAppUrl == getHash()) {
urlActions.forward = true;
handleForwardButton();
}
}
// ok, that didn't work, try someplace back in the history stack
if ((bsl >= 2) && (backStack[bsl - 2])) {
if (backStack[bsl - 2].flexAppUrl == getHash()) {
urlActions.back = true;
handleBackButton();
}
}
if (!urlActions.back && !urlActions.forward) {
var foundInStacks = {
back: -1,
forward: -1
}
for (var i = 0; i < backStack.length; i++) {
if (backStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
arbitraryUrl = true;
foundInStacks.back = i;
}
}
for (var i = 0; i < forwardStack.length; i++) {
if (forwardStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
arbitraryUrl = true;
foundInStacks.forward = i;
}
}
handleArbitraryUrl();
}
// Firefox changed; do a callback into BrowserManager to tell it.
currentHref = document.location.href;
var flexAppUrl = getHash();
//ADR: to fix multiple
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
var pl = getPlayers();
for (var i = 0; i < pl.length; i++) {
pl[i].browserURLChange(flexAppUrl);
}
} else {
getPlayer().browserURLChange(flexAppUrl);
}
}
}
}
var _initialize = function () {
browserHasHashChange = ("onhashchange" in document.body);
if (browser.ie)
{
var scripts = document.getElementsByTagName('script');
for (var i = 0, s; s = scripts[i]; i++) {
if (s.src.indexOf("history.js") > -1) {
var iframe_location = (new String(s.src)).replace("history.js", "historyFrame.html");
}
}
historyFrameSourcePrefix = iframe_location + "?";
var src = historyFrameSourcePrefix;
var iframe = document.createElement("iframe");
iframe.id = 'ie_historyFrame';
iframe.name = 'ie_historyFrame';
iframe.src = 'javascript:false;';
try {
document.body.appendChild(iframe);
} catch(e) {
setTimeout(function() {
document.body.appendChild(iframe);
}, 0);
}
}
if (browser.safari && !browserHasHashChange)
{
var rememberDiv = document.createElement("div");
rememberDiv.id = 'safari_rememberDiv';
document.body.appendChild(rememberDiv);
rememberDiv.innerHTML = '<input type="text" id="safari_remember_field" style="width: 500px;">';
var formDiv = document.createElement("div");
formDiv.id = 'safari_formDiv';
document.body.appendChild(formDiv);
var reloader_content = document.createElement('div');
reloader_content.id = 'safarireloader';
var scripts = document.getElementsByTagName('script');
for (var i = 0, s; s = scripts[i]; i++) {
if (s.src.indexOf("history.js") > -1) {
html = (new String(s.src)).replace(".js", ".html");
}
}
reloader_content.innerHTML = '<iframe id="safarireloader-iframe" src="about:blank" frameborder="no" scrolling="no"></iframe>';
document.body.appendChild(reloader_content);
reloader_content.style.position = 'absolute';
reloader_content.style.left = reloader_content.style.top = '-9999px';
iframe = reloader_content.getElementsByTagName('iframe')[0];
if (document.getElementById("safari_remember_field").value != "" ) {
historyHash = document.getElementById("safari_remember_field").value.split(",");
}
}
if (browserHasHashChange)
document.body.onhashchange = hashChangeHandler;
}
return {
historyHash: historyHash,
backStack: function() { return backStack; },
forwardStack: function() { return forwardStack },
getPlayer: getPlayer,
initialize: function(src) {
_initialize(src);
},
setURL: function(url) {
document.location.href = url;
},
getURL: function() {
return document.location.href;
},
getTitle: function() {
return document.title;
},
setTitle: function(title) {
try {
backStack[backStack.length - 1].title = title;
} catch(e) { }
//if on safari, set the title to be the empty string.
if (browser.safari) {
if (title == "") {
try {
var tmp = window.location.href.toString();
title = tmp.substring((tmp.lastIndexOf("/")+1), tmp.lastIndexOf("#"));
} catch(e) {
title = "";
}
}
}
document.title = title;
},
setDefaultURL: function(def)
{
defaultHash = def;
def = getHash();
//trailing ? is important else an extra frame gets added to the history
//when navigating back to the first page. Alternatively could check
//in history frame navigation to compare # and ?.
if (browser.ie)
{
window['_ie_firstload'] = true;
var sourceToSet = historyFrameSourcePrefix + def;
var func = function() {
getHistoryFrame().src = sourceToSet;
window.location.replace("#" + def);
setInterval(checkForUrlChange, 50);
}
try {
func();
} catch(e) {
window.setTimeout(function() { func(); }, 0);
}
}
if (browser.safari)
{
currentHistoryLength = history.length;
if (historyHash.length == 0) {
historyHash[currentHistoryLength] = def;
var newloc = "#" + def;
window.location.replace(newloc);
} else {
//alert(historyHash[historyHash.length-1]);
}
setInterval(checkForUrlChange, 50);
}
if (browser.firefox || browser.opera)
{
var reg = new RegExp("#" + def + "$");
if (window.location.toString().match(reg)) {
} else {
var newloc ="#" + def;
window.location.replace(newloc);
}
setInterval(checkForUrlChange, 50);
}
},
/* Set the current browser URL; called from inside BrowserManager to propagate
* the application state out to the container.
*/
setBrowserURL: function(flexAppUrl, objectId) {
if (browser.ie && typeof objectId != "undefined") {
currentObjectId = objectId;
}
//fromIframe = fromIframe || false;
//fromFlex = fromFlex || false;
//alert("setBrowserURL: " + flexAppUrl);
//flexAppUrl = (flexAppUrl == "") ? defaultHash : flexAppUrl ;
var pos = document.location.href.indexOf('#');
var baseUrl = pos != -1 ? document.location.href.substr(0, pos) : document.location.href;
var newUrl = baseUrl + '#' + flexAppUrl;
if (document.location.href != newUrl && document.location.href + '#' != newUrl) {
currentHref = newUrl;
addHistoryEntry(baseUrl, newUrl, flexAppUrl);
currentHistoryLength = history.length;
}
},
browserURLChange: function(flexAppUrl) {
var objectId = null;
if (browser.ie && currentObjectId != null) {
objectId = currentObjectId;
}
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
var pl = getPlayers();
for (var i = 0; i < pl.length; i++) {
try {
pl[i].browserURLChange(flexAppUrl);
} catch(e) { }
}
} else {
try {
getPlayer(objectId).browserURLChange(flexAppUrl);
} catch(e) { }
}
currentObjectId = null;
},
getUserAgent: function() {
return navigator.userAgent;
},
getPlatform: function() {
return navigator.platform;
}
}
})();
// Initialization
// Automated unit testing and other diagnostics
function setURL(url)
{
document.location.href = url;
}
function backButton()
{
history.back();
}
function forwardButton()
{
history.forward();
}
function goForwardOrBackInHistory(step)
{
history.go(step);
}
//BrowserHistoryUtils.addEvent(window, "load", function() { BrowserHistory.initialize(); });
(function(i) {
var u =navigator.userAgent;var e=/*@cc_on!@*/false;
var st = setTimeout;
if(/webkit/i.test(u)){
st(function(){
var dr=document.readyState;
if(dr=="loaded"||dr=="complete"){i()}
else{st(arguments.callee,10);}},10);
} else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){
document.addEventListener("DOMContentLoaded",i,false);
} else if(e){
(function(){
var t=document.createElement('doc:rdy');
try{t.doScroll('left');
i();t=null;
}catch(e){st(arguments.callee,0);}})();
} else{
window.onload=i;
}
})( function() {BrowserHistory.initialize();} );

View File

@ -1,29 +0,0 @@
<html>
<head>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="-1">
</head>
<body>
<script>
function processUrl()
{
var pos = url.indexOf("?");
url = pos != -1 ? url.substr(pos + 1) : "";
if (!parent._ie_firstload) {
parent.BrowserHistory.setBrowserURL(url);
try {
parent.BrowserHistory.browserURLChange(url);
} catch(e) { }
} else {
parent._ie_firstload = false;
}
}
var url = document.location.href;
processUrl();
document.write(encodeURIComponent(url));
</script>
Hidden frame for Browser History support.
</body>
</html>

View File

@ -1,777 +0,0 @@
/*! SWFObject v2.2 <http://code.google.com/p/swfobject/>
is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
var swfobject = function() {
var UNDEF = "undefined",
OBJECT = "object",
SHOCKWAVE_FLASH = "Shockwave Flash",
SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
FLASH_MIME_TYPE = "application/x-shockwave-flash",
EXPRESS_INSTALL_ID = "SWFObjectExprInst",
ON_READY_STATE_CHANGE = "onreadystatechange",
win = window,
doc = document,
nav = navigator,
plugin = false,
domLoadFnArr = [main],
regObjArr = [],
objIdArr = [],
listenersArr = [],
storedAltContent,
storedAltContentId,
storedCallbackFn,
storedCallbackObj,
isDomLoaded = false,
isExpressInstallActive = false,
dynamicStylesheet,
dynamicStylesheetMedia,
autoHideShow = true,
/* Centralized function for browser feature detection
- User agent string detection is only used when no good alternative is possible
- Is executed directly for optimal performance
*/
ua = function() {
var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
u = nav.userAgent.toLowerCase(),
p = nav.platform.toLowerCase(),
windows = p ? /win/.test(p) : /win/.test(u),
mac = p ? /mac/.test(p) : /mac/.test(u),
webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
playerVersion = [0,0,0],
d = null;
if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
d = nav.plugins[SHOCKWAVE_FLASH].description;
if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
plugin = true;
ie = false; // cascaded feature detection for Internet Explorer
d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
}
}
else if (typeof win.ActiveXObject != UNDEF) {
try {
var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
if (a) { // a will return null when ActiveX is disabled
d = a.GetVariable("$version");
if (d) {
ie = true; // cascaded feature detection for Internet Explorer
d = d.split(" ")[1].split(",");
playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
}
}
}
catch(e) {}
}
return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
}(),
/* Cross-browser onDomLoad
- Will fire an event as soon as the DOM of a web page is loaded
- Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/
- Regular onload serves as fallback
*/
onDomLoad = function() {
if (!ua.w3) { return; }
if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically
callDomLoadFunctions();
}
if (!isDomLoaded) {
if (typeof doc.addEventListener != UNDEF) {
doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
}
if (ua.ie && ua.win) {
doc.attachEvent(ON_READY_STATE_CHANGE, function() {
if (doc.readyState == "complete") {
doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
callDomLoadFunctions();
}
});
if (win == top) { // if not inside an iframe
(function(){
if (isDomLoaded) { return; }
try {
doc.documentElement.doScroll("left");
}
catch(e) {
setTimeout(arguments.callee, 0);
return;
}
callDomLoadFunctions();
})();
}
}
if (ua.wk) {
(function(){
if (isDomLoaded) { return; }
if (!/loaded|complete/.test(doc.readyState)) {
setTimeout(arguments.callee, 0);
return;
}
callDomLoadFunctions();
})();
}
addLoadEvent(callDomLoadFunctions);
}
}();
function callDomLoadFunctions() {
if (isDomLoaded) { return; }
try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early
var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
t.parentNode.removeChild(t);
}
catch (e) { return; }
isDomLoaded = true;
var dl = domLoadFnArr.length;
for (var i = 0; i < dl; i++) {
domLoadFnArr[i]();
}
}
function addDomLoadEvent(fn) {
if (isDomLoaded) {
fn();
}
else {
domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
}
}
/* Cross-browser onload
- Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
- Will fire an event as soon as a web page including all of its assets are loaded
*/
function addLoadEvent(fn) {
if (typeof win.addEventListener != UNDEF) {
win.addEventListener("load", fn, false);
}
else if (typeof doc.addEventListener != UNDEF) {
doc.addEventListener("load", fn, false);
}
else if (typeof win.attachEvent != UNDEF) {
addListener(win, "onload", fn);
}
else if (typeof win.onload == "function") {
var fnOld = win.onload;
win.onload = function() {
fnOld();
fn();
};
}
else {
win.onload = fn;
}
}
/* Main function
- Will preferably execute onDomLoad, otherwise onload (as a fallback)
*/
function main() {
if (plugin) {
testPlayerVersion();
}
else {
matchVersions();
}
}
/* Detect the Flash Player version for non-Internet Explorer browsers
- Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:
a. Both release and build numbers can be detected
b. Avoid wrong descriptions by corrupt installers provided by Adobe
c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports
- Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available
*/
function testPlayerVersion() {
var b = doc.getElementsByTagName("body")[0];
var o = createElement(OBJECT);
o.setAttribute("type", FLASH_MIME_TYPE);
var t = b.appendChild(o);
if (t) {
var counter = 0;
(function(){
if (typeof t.GetVariable != UNDEF) {
var d = t.GetVariable("$version");
if (d) {
d = d.split(" ")[1].split(",");
ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
}
}
else if (counter < 10) {
counter++;
setTimeout(arguments.callee, 10);
return;
}
b.removeChild(o);
t = null;
matchVersions();
})();
}
else {
matchVersions();
}
}
/* Perform Flash Player and SWF version matching; static publishing only
*/
function matchVersions() {
var rl = regObjArr.length;
if (rl > 0) {
for (var i = 0; i < rl; i++) { // for each registered object element
var id = regObjArr[i].id;
var cb = regObjArr[i].callbackFn;
var cbObj = {success:false, id:id};
if (ua.pv[0] > 0) {
var obj = getElementById(id);
if (obj) {
if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match!
setVisibility(id, true);
if (cb) {
cbObj.success = true;
cbObj.ref = getObjectById(id);
cb(cbObj);
}
}
else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported
var att = {};
att.data = regObjArr[i].expressInstall;
att.width = obj.getAttribute("width") || "0";
att.height = obj.getAttribute("height") || "0";
if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
// parse HTML object param element's name-value pairs
var par = {};
var p = obj.getElementsByTagName("param");
var pl = p.length;
for (var j = 0; j < pl; j++) {
if (p[j].getAttribute("name").toLowerCase() != "movie") {
par[p[j].getAttribute("name")] = p[j].getAttribute("value");
}
}
showExpressInstall(att, par, id, cb);
}
else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF
displayAltContent(obj);
if (cb) { cb(cbObj); }
}
}
}
else { // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content)
setVisibility(id, true);
if (cb) {
var o = getObjectById(id); // test whether there is an HTML object element or not
if (o && typeof o.SetVariable != UNDEF) {
cbObj.success = true;
cbObj.ref = o;
}
cb(cbObj);
}
}
}
}
}
function getObjectById(objectIdStr) {
var r = null;
var o = getElementById(objectIdStr);
if (o && o.nodeName == "OBJECT") {
if (typeof o.SetVariable != UNDEF) {
r = o;
}
else {
var n = o.getElementsByTagName(OBJECT)[0];
if (n) {
r = n;
}
}
}
return r;
}
/* Requirements for Adobe Express Install
- only one instance can be active at a time
- fp 6.0.65 or higher
- Win/Mac OS only
- no Webkit engines older than version 312
*/
function canExpressInstall() {
return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
}
/* Show the Adobe Express Install dialog
- Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75
*/
function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
isExpressInstallActive = true;
storedCallbackFn = callbackFn || null;
storedCallbackObj = {success:false, id:replaceElemIdStr};
var obj = getElementById(replaceElemIdStr);
if (obj) {
if (obj.nodeName == "OBJECT") { // static publishing
storedAltContent = abstractAltContent(obj);
storedAltContentId = null;
}
else { // dynamic publishing
storedAltContent = obj;
storedAltContentId = replaceElemIdStr;
}
att.id = EXPRESS_INSTALL_ID;
if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }
if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }
doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
fv = "MMredirectURL=" + encodeURI(window.location).toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
if (typeof par.flashvars != UNDEF) {
par.flashvars += "&" + fv;
}
else {
par.flashvars = fv;
}
// IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
if (ua.ie && ua.win && obj.readyState != 4) {
var newObj = createElement("div");
replaceElemIdStr += "SWFObjectNew";
newObj.setAttribute("id", replaceElemIdStr);
obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf
obj.style.display = "none";
(function(){
if (obj.readyState == 4) {
obj.parentNode.removeChild(obj);
}
else {
setTimeout(arguments.callee, 10);
}
})();
}
createSWF(att, par, replaceElemIdStr);
}
}
/* Functions to abstract and display alternative content
*/
function displayAltContent(obj) {
if (ua.ie && ua.win && obj.readyState != 4) {
// IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
var el = createElement("div");
obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content
el.parentNode.replaceChild(abstractAltContent(obj), el);
obj.style.display = "none";
(function(){
if (obj.readyState == 4) {
obj.parentNode.removeChild(obj);
}
else {
setTimeout(arguments.callee, 10);
}
})();
}
else {
obj.parentNode.replaceChild(abstractAltContent(obj), obj);
}
}
function abstractAltContent(obj) {
var ac = createElement("div");
if (ua.win && ua.ie) {
ac.innerHTML = obj.innerHTML;
}
else {
var nestedObj = obj.getElementsByTagName(OBJECT)[0];
if (nestedObj) {
var c = nestedObj.childNodes;
if (c) {
var cl = c.length;
for (var i = 0; i < cl; i++) {
if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
ac.appendChild(c[i].cloneNode(true));
}
}
}
}
}
return ac;
}
/* Cross-browser dynamic SWF creation
*/
function createSWF(attObj, parObj, id) {
var r, el = getElementById(id);
if (ua.wk && ua.wk < 312) { return r; }
if (el) {
if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
attObj.id = id;
}
if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML
var att = "";
for (var i in attObj) {
if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries
if (i.toLowerCase() == "data") {
parObj.movie = attObj[i];
}
else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
att += ' class="' + attObj[i] + '"';
}
else if (i.toLowerCase() != "classid") {
att += ' ' + i + '="' + attObj[i] + '"';
}
}
}
var par = "";
for (var j in parObj) {
if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries
par += '<param name="' + j + '" value="' + parObj[j] + '" />';
}
}
el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)
r = getElementById(attObj.id);
}
else { // well-behaving browsers
var o = createElement(OBJECT);
o.setAttribute("type", FLASH_MIME_TYPE);
for (var m in attObj) {
if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries
if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
o.setAttribute("class", attObj[m]);
}
else if (m.toLowerCase() != "classid") { // filter out IE specific attribute
o.setAttribute(m, attObj[m]);
}
}
}
for (var n in parObj) {
if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element
createObjParam(o, n, parObj[n]);
}
}
el.parentNode.replaceChild(o, el);
r = o;
}
}
return r;
}
function createObjParam(el, pName, pValue) {
var p = createElement("param");
p.setAttribute("name", pName);
p.setAttribute("value", pValue);
el.appendChild(p);
}
/* Cross-browser SWF removal
- Especially needed to safely and completely remove a SWF in Internet Explorer
*/
function removeSWF(id) {
var obj = getElementById(id);
if (obj && obj.nodeName == "OBJECT") {
if (ua.ie && ua.win) {
obj.style.display = "none";
(function(){
if (obj.readyState == 4) {
removeObjectInIE(id);
}
else {
setTimeout(arguments.callee, 10);
}
})();
}
else {
obj.parentNode.removeChild(obj);
}
}
}
function removeObjectInIE(id) {
var obj = getElementById(id);
if (obj) {
for (var i in obj) {
if (typeof obj[i] == "function") {
obj[i] = null;
}
}
obj.parentNode.removeChild(obj);
}
}
/* Functions to optimize JavaScript compression
*/
function getElementById(id) {
var el = null;
try {
el = doc.getElementById(id);
}
catch (e) {}
return el;
}
function createElement(el) {
return doc.createElement(el);
}
/* Updated attachEvent function for Internet Explorer
- Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
*/
function addListener(target, eventType, fn) {
target.attachEvent(eventType, fn);
listenersArr[listenersArr.length] = [target, eventType, fn];
}
/* Flash Player and SWF content version matching
*/
function hasPlayerVersion(rv) {
var pv = ua.pv, v = rv.split(".");
v[0] = parseInt(v[0], 10);
v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
v[2] = parseInt(v[2], 10) || 0;
return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
}
/* Cross-browser dynamic CSS creation
- Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php
*/
function createCSS(sel, decl, media, newStyle) {
if (ua.ie && ua.mac) { return; }
var h = doc.getElementsByTagName("head")[0];
if (!h) { return; } // to also support badly authored HTML pages that lack a head element
var m = (media && typeof media == "string") ? media : "screen";
if (newStyle) {
dynamicStylesheet = null;
dynamicStylesheetMedia = null;
}
if (!dynamicStylesheet || dynamicStylesheetMedia != m) {
// create dynamic stylesheet + get a global reference to it
var s = createElement("style");
s.setAttribute("type", "text/css");
s.setAttribute("media", m);
dynamicStylesheet = h.appendChild(s);
if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
}
dynamicStylesheetMedia = m;
}
// add style rule
if (ua.ie && ua.win) {
if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
dynamicStylesheet.addRule(sel, decl);
}
}
else {
if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
}
}
}
function setVisibility(id, isVisible) {
if (!autoHideShow) { return; }
var v = isVisible ? "visible" : "hidden";
if (isDomLoaded && getElementById(id)) {
getElementById(id).style.visibility = v;
}
else {
createCSS("#" + id, "visibility:" + v);
}
}
/* Filter to avoid XSS attacks
*/
function urlEncodeIfNecessary(s) {
var regex = /[\\\"<>\.;]/;
var hasBadChars = regex.exec(s) != null;
return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
}
/* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
*/
var cleanup = function() {
if (ua.ie && ua.win) {
window.attachEvent("onunload", function() {
// remove listeners to avoid memory leaks
var ll = listenersArr.length;
for (var i = 0; i < ll; i++) {
listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
}
// cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
var il = objIdArr.length;
for (var j = 0; j < il; j++) {
removeSWF(objIdArr[j]);
}
// cleanup library's main closures to avoid memory leaks
for (var k in ua) {
ua[k] = null;
}
ua = null;
for (var l in swfobject) {
swfobject[l] = null;
}
swfobject = null;
});
}
}();
return {
/* Public API
- Reference: http://code.google.com/p/swfobject/wiki/documentation
*/
registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
if (ua.w3 && objectIdStr && swfVersionStr) {
var regObj = {};
regObj.id = objectIdStr;
regObj.swfVersion = swfVersionStr;
regObj.expressInstall = xiSwfUrlStr;
regObj.callbackFn = callbackFn;
regObjArr[regObjArr.length] = regObj;
setVisibility(objectIdStr, false);
}
else if (callbackFn) {
callbackFn({success:false, id:objectIdStr});
}
},
getObjectById: function(objectIdStr) {
if (ua.w3) {
return getObjectById(objectIdStr);
}
},
embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
var callbackObj = {success:false, id:replaceElemIdStr};
if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
setVisibility(replaceElemIdStr, false);
addDomLoadEvent(function() {
widthStr += ""; // auto-convert to string
heightStr += "";
var att = {};
if (attObj && typeof attObj === OBJECT) {
for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs
att[i] = attObj[i];
}
}
att.data = swfUrlStr;
att.width = widthStr;
att.height = heightStr;
var par = {};
if (parObj && typeof parObj === OBJECT) {
for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs
par[j] = parObj[j];
}
}
if (flashvarsObj && typeof flashvarsObj === OBJECT) {
for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs
if (typeof par.flashvars != UNDEF) {
par.flashvars += "&" + k + "=" + flashvarsObj[k];
}
else {
par.flashvars = k + "=" + flashvarsObj[k];
}
}
}
if (hasPlayerVersion(swfVersionStr)) { // create SWF
var obj = createSWF(att, par, replaceElemIdStr);
if (att.id == replaceElemIdStr) {
setVisibility(replaceElemIdStr, true);
}
callbackObj.success = true;
callbackObj.ref = obj;
}
else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install
att.data = xiSwfUrlStr;
showExpressInstall(att, par, replaceElemIdStr, callbackFn);
return;
}
else { // show alternative content
setVisibility(replaceElemIdStr, true);
}
if (callbackFn) { callbackFn(callbackObj); }
});
}
else if (callbackFn) { callbackFn(callbackObj); }
},
switchOffAutoHideShow: function() {
autoHideShow = false;
},
ua: ua,
getFlashPlayerVersion: function() {
return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
},
hasFlashPlayerVersion: hasPlayerVersion,
createSWF: function(attObj, parObj, replaceElemIdStr) {
if (ua.w3) {
return createSWF(attObj, parObj, replaceElemIdStr);
}
else {
return undefined;
}
},
showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
if (ua.w3 && canExpressInstall()) {
showExpressInstall(att, par, replaceElemIdStr, callbackFn);
}
},
removeSWF: function(objElemIdStr) {
if (ua.w3) {
removeSWF(objElemIdStr);
}
},
createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
if (ua.w3) {
createCSS(selStr, declStr, mediaStr, newStyleBoolean);
}
},
addDomLoadEvent: addDomLoadEvent,
addLoadEvent: addLoadEvent,
getQueryParamValue: function(param) {
var q = doc.location.search || doc.location.hash;
if (q) {
if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark
if (param == null) {
return urlEncodeIfNecessary(q);
}
var pairs = q.split("&");
for (var i = 0; i < pairs.length; i++) {
if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
}
}
}
return "";
},
// For internal usage only
expressInstallCallback: function() {
if (isExpressInstallActive) {
var obj = getElementById(EXPRESS_INSTALL_ID);
if (obj && storedAltContent) {
obj.parentNode.replaceChild(storedAltContent, obj);
if (storedAltContentId) {
setVisibility(storedAltContentId, true);
if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
}
if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
}
isExpressInstallActive = false;
}
}
};
}();

View File

@ -1,6 +0,0 @@
/* This CSS stylesheet defines styles used by required elements in a flex application page that supports browser history */
#ie_historyFrame { width: 0px; height: 0px; display:none }
#firefox_anchorDiv { width: 0px; height: 0px; display:none }
#safari_formDiv { width: 0px; height: 0px; display:none }
#safari_rememberDiv { width: 0px; height: 0px; display:none }

View File

@ -1,678 +0,0 @@
BrowserHistoryUtils = {
addEvent: function(elm, evType, fn, useCapture) {
useCapture = useCapture || false;
if (elm.addEventListener) {
elm.addEventListener(evType, fn, useCapture);
return true;
}
else if (elm.attachEvent) {
var r = elm.attachEvent('on' + evType, fn);
return r;
}
else {
elm['on' + evType] = fn;
}
}
}
BrowserHistory = (function() {
// type of browser
var browser = {
ie: false,
ie8: false,
firefox: false,
safari: false,
opera: false,
version: -1
};
// Default app state URL to use when no fragment ID present
var defaultHash = '';
// Last-known app state URL
var currentHref = document.location.href;
// Initial URL (used only by IE)
var initialHref = document.location.href;
// Initial URL (used only by IE)
var initialHash = document.location.hash;
// History frame source URL prefix (used only by IE)
var historyFrameSourcePrefix = 'history/historyFrame.html?';
// History maintenance (used only by Safari)
var currentHistoryLength = -1;
// Flag to denote the existence of onhashchange
var browserHasHashChange = false;
var historyHash = [];
var initialState = createState(initialHref, initialHref + '#' + initialHash, initialHash);
var backStack = [];
var forwardStack = [];
var currentObjectId = null;
//UserAgent detection
var useragent = navigator.userAgent.toLowerCase();
if (useragent.indexOf("opera") != -1) {
browser.opera = true;
} else if (useragent.indexOf("msie") != -1) {
browser.ie = true;
browser.version = parseFloat(useragent.substring(useragent.indexOf('msie') + 4));
if (browser.version == 8)
{
browser.ie = false;
browser.ie8 = true;
}
} else if (useragent.indexOf("safari") != -1) {
browser.safari = true;
browser.version = parseFloat(useragent.substring(useragent.indexOf('safari') + 7));
} else if (useragent.indexOf("gecko") != -1) {
browser.firefox = true;
}
if (browser.ie == true && browser.version == 7) {
window["_ie_firstload"] = false;
}
function hashChangeHandler()
{
currentHref = document.location.href;
var flexAppUrl = getHash();
//ADR: to fix multiple
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
var pl = getPlayers();
for (var i = 0; i < pl.length; i++) {
pl[i].browserURLChange(flexAppUrl);
}
} else {
getPlayer().browserURLChange(flexAppUrl);
}
}
// Accessor functions for obtaining specific elements of the page.
function getHistoryFrame()
{
return document.getElementById('ie_historyFrame');
}
function getFormElement()
{
return document.getElementById('safari_formDiv');
}
function getRememberElement()
{
return document.getElementById("safari_remember_field");
}
// Get the Flash player object for performing ExternalInterface callbacks.
// Updated for changes to SWFObject2.
function getPlayer(id) {
var i;
if (id && document.getElementById(id)) {
var r = document.getElementById(id);
if (typeof r.SetVariable != "undefined") {
return r;
}
else {
var o = r.getElementsByTagName("object");
var e = r.getElementsByTagName("embed");
for (i = 0; i < o.length; i++) {
if (typeof o[i].browserURLChange != "undefined")
return o[i];
}
for (i = 0; i < e.length; i++) {
if (typeof e[i].browserURLChange != "undefined")
return e[i];
}
}
}
else {
var o = document.getElementsByTagName("object");
var e = document.getElementsByTagName("embed");
for (i = 0; i < e.length; i++) {
if (typeof e[i].browserURLChange != "undefined")
{
return e[i];
}
}
for (i = 0; i < o.length; i++) {
if (typeof o[i].browserURLChange != "undefined")
{
return o[i];
}
}
}
return undefined;
}
function getPlayers() {
var i;
var players = [];
if (players.length == 0) {
var tmp = document.getElementsByTagName('object');
for (i = 0; i < tmp.length; i++)
{
if (typeof tmp[i].browserURLChange != "undefined")
players.push(tmp[i]);
}
}
if (players.length == 0 || players[0].object == null) {
var tmp = document.getElementsByTagName('embed');
for (i = 0; i < tmp.length; i++)
{
if (typeof tmp[i].browserURLChange != "undefined")
players.push(tmp[i]);
}
}
return players;
}
function getIframeHash() {
var doc = getHistoryFrame().contentWindow.document;
var hash = String(doc.location.search);
if (hash.length == 1 && hash.charAt(0) == "?") {
hash = "";
}
else if (hash.length >= 2 && hash.charAt(0) == "?") {
hash = hash.substring(1);
}
return hash;
}
/* Get the current location hash excluding the '#' symbol. */
function getHash() {
// It would be nice if we could use document.location.hash here,
// but it's faulty sometimes.
var idx = document.location.href.indexOf('#');
return (idx >= 0) ? document.location.href.substr(idx+1) : '';
}
/* Get the current location hash excluding the '#' symbol. */
function setHash(hash) {
// It would be nice if we could use document.location.hash here,
// but it's faulty sometimes.
if (hash == '') hash = '#'
document.location.hash = hash;
}
function createState(baseUrl, newUrl, flexAppUrl) {
return { 'baseUrl': baseUrl, 'newUrl': newUrl, 'flexAppUrl': flexAppUrl, 'title': null };
}
/* Add a history entry to the browser.
* baseUrl: the portion of the location prior to the '#'
* newUrl: the entire new URL, including '#' and following fragment
* flexAppUrl: the portion of the location following the '#' only
*/
function addHistoryEntry(baseUrl, newUrl, flexAppUrl) {
//delete all the history entries
forwardStack = [];
if (browser.ie) {
//Check to see if we are being asked to do a navigate for the first
//history entry, and if so ignore, because it's coming from the creation
//of the history iframe
if (flexAppUrl == defaultHash && document.location.href == initialHref && window['_ie_firstload']) {
currentHref = initialHref;
return;
}
if ((!flexAppUrl || flexAppUrl == defaultHash) && window['_ie_firstload']) {
newUrl = baseUrl + '#' + defaultHash;
flexAppUrl = defaultHash;
} else {
// for IE, tell the history frame to go somewhere without a '#'
// in order to get this entry into the browser history.
getHistoryFrame().src = historyFrameSourcePrefix + flexAppUrl;
}
setHash(flexAppUrl);
} else {
//ADR
if (backStack.length == 0 && initialState.flexAppUrl == flexAppUrl) {
initialState = createState(baseUrl, newUrl, flexAppUrl);
} else if(backStack.length > 0 && backStack[backStack.length - 1].flexAppUrl == flexAppUrl) {
backStack[backStack.length - 1] = createState(baseUrl, newUrl, flexAppUrl);
}
if (browser.safari && !browserHasHashChange) {
// for Safari, submit a form whose action points to the desired URL
if (browser.version <= 419.3) {
var file = window.location.pathname.toString();
file = file.substring(file.lastIndexOf("/")+1);
getFormElement().innerHTML = '<form name="historyForm" action="'+file+'#' + flexAppUrl + '" method="GET"></form>';
//get the current elements and add them to the form
var qs = window.location.search.substring(1);
var qs_arr = qs.split("&");
for (var i = 0; i < qs_arr.length; i++) {
var tmp = qs_arr[i].split("=");
var elem = document.createElement("input");
elem.type = "hidden";
elem.name = tmp[0];
elem.value = tmp[1];
document.forms.historyForm.appendChild(elem);
}
document.forms.historyForm.submit();
} else {
top.location.hash = flexAppUrl;
}
// We also have to maintain the history by hand for Safari
historyHash[history.length] = flexAppUrl;
_storeStates();
} else {
// Otherwise, just tell the browser to go there
setHash(flexAppUrl);
}
}
backStack.push(createState(baseUrl, newUrl, flexAppUrl));
}
function _storeStates() {
if (browser.safari) {
getRememberElement().value = historyHash.join(",");
}
}
function handleBackButton() {
//The "current" page is always at the top of the history stack.
var current = backStack.pop();
if (!current) { return; }
var last = backStack[backStack.length - 1];
if (!last && backStack.length == 0){
last = initialState;
}
forwardStack.push(current);
}
function handleForwardButton() {
//summary: private method. Do not call this directly.
var last = forwardStack.pop();
if (!last) { return; }
backStack.push(last);
}
function handleArbitraryUrl() {
//delete all the history entries
forwardStack = [];
}
/* Called periodically to poll to see if we need to detect navigation that has occurred */
function checkForUrlChange() {
if (browser.ie) {
if (currentHref != document.location.href && currentHref + '#' != document.location.href) {
//This occurs when the user has navigated to a specific URL
//within the app, and didn't use browser back/forward
//IE seems to have a bug where it stops updating the URL it
//shows the end-user at this point, but programatically it
//appears to be correct. Do a full app reload to get around
//this issue.
if (browser.version < 7) {
currentHref = document.location.href;
document.location.reload();
} else {
if (getHash() != getIframeHash()) {
// this.iframe.src = this.blankURL + hash;
var sourceToSet = historyFrameSourcePrefix + getHash();
getHistoryFrame().src = sourceToSet;
currentHref = document.location.href;
}
}
}
}
if (browser.safari && !browserHasHashChange) {
// For Safari, we have to check to see if history.length changed.
if (currentHistoryLength >= 0 && history.length != currentHistoryLength) {
//alert("did change: " + history.length + ", " + historyHash.length + "|" + historyHash[history.length] + "|>" + historyHash.join("|"));
var flexAppUrl = getHash();
if (browser.version < 528.16 /* Anything earlier than Safari 4.0 */)
{
// If it did change and we're running Safari 3.x or earlier,
// then we have to look the old state up in our hand-maintained
// array since document.location.hash won't have changed,
// then call back into BrowserManager.
currentHistoryLength = history.length;
flexAppUrl = historyHash[currentHistoryLength];
}
//ADR: to fix multiple
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
var pl = getPlayers();
for (var i = 0; i < pl.length; i++) {
pl[i].browserURLChange(flexAppUrl);
}
} else {
getPlayer().browserURLChange(flexAppUrl);
}
_storeStates();
}
}
if (browser.firefox && !browserHasHashChange) {
if (currentHref != document.location.href) {
var bsl = backStack.length;
var urlActions = {
back: false,
forward: false,
set: false
}
if ((window.location.hash == initialHash || window.location.href == initialHref) && (bsl == 1)) {
urlActions.back = true;
// FIXME: could this ever be a forward button?
// we can't clear it because we still need to check for forwards. Ugg.
// clearInterval(this.locationTimer);
handleBackButton();
}
// first check to see if we could have gone forward. We always halt on
// a no-hash item.
if (forwardStack.length > 0) {
if (forwardStack[forwardStack.length-1].flexAppUrl == getHash()) {
urlActions.forward = true;
handleForwardButton();
}
}
// ok, that didn't work, try someplace back in the history stack
if ((bsl >= 2) && (backStack[bsl - 2])) {
if (backStack[bsl - 2].flexAppUrl == getHash()) {
urlActions.back = true;
handleBackButton();
}
}
if (!urlActions.back && !urlActions.forward) {
var foundInStacks = {
back: -1,
forward: -1
}
for (var i = 0; i < backStack.length; i++) {
if (backStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
arbitraryUrl = true;
foundInStacks.back = i;
}
}
for (var i = 0; i < forwardStack.length; i++) {
if (forwardStack[i].flexAppUrl == getHash() && i != (bsl - 2)) {
arbitraryUrl = true;
foundInStacks.forward = i;
}
}
handleArbitraryUrl();
}
// Firefox changed; do a callback into BrowserManager to tell it.
currentHref = document.location.href;
var flexAppUrl = getHash();
//ADR: to fix multiple
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
var pl = getPlayers();
for (var i = 0; i < pl.length; i++) {
pl[i].browserURLChange(flexAppUrl);
}
} else {
getPlayer().browserURLChange(flexAppUrl);
}
}
}
}
var _initialize = function () {
browserHasHashChange = ("onhashchange" in document.body);
if (browser.ie)
{
var scripts = document.getElementsByTagName('script');
for (var i = 0, s; s = scripts[i]; i++) {
if (s.src.indexOf("history.js") > -1) {
var iframe_location = (new String(s.src)).replace("history.js", "historyFrame.html");
}
}
historyFrameSourcePrefix = iframe_location + "?";
var src = historyFrameSourcePrefix;
var iframe = document.createElement("iframe");
iframe.id = 'ie_historyFrame';
iframe.name = 'ie_historyFrame';
iframe.src = 'javascript:false;';
try {
document.body.appendChild(iframe);
} catch(e) {
setTimeout(function() {
document.body.appendChild(iframe);
}, 0);
}
}
if (browser.safari && !browserHasHashChange)
{
var rememberDiv = document.createElement("div");
rememberDiv.id = 'safari_rememberDiv';
document.body.appendChild(rememberDiv);
rememberDiv.innerHTML = '<input type="text" id="safari_remember_field" style="width: 500px;">';
var formDiv = document.createElement("div");
formDiv.id = 'safari_formDiv';
document.body.appendChild(formDiv);
var reloader_content = document.createElement('div');
reloader_content.id = 'safarireloader';
var scripts = document.getElementsByTagName('script');
for (var i = 0, s; s = scripts[i]; i++) {
if (s.src.indexOf("history.js") > -1) {
html = (new String(s.src)).replace(".js", ".html");
}
}
reloader_content.innerHTML = '<iframe id="safarireloader-iframe" src="about:blank" frameborder="no" scrolling="no"></iframe>';
document.body.appendChild(reloader_content);
reloader_content.style.position = 'absolute';
reloader_content.style.left = reloader_content.style.top = '-9999px';
iframe = reloader_content.getElementsByTagName('iframe')[0];
if (document.getElementById("safari_remember_field").value != "" ) {
historyHash = document.getElementById("safari_remember_field").value.split(",");
}
}
if (browserHasHashChange)
document.body.onhashchange = hashChangeHandler;
}
return {
historyHash: historyHash,
backStack: function() { return backStack; },
forwardStack: function() { return forwardStack },
getPlayer: getPlayer,
initialize: function(src) {
_initialize(src);
},
setURL: function(url) {
document.location.href = url;
},
getURL: function() {
return document.location.href;
},
getTitle: function() {
return document.title;
},
setTitle: function(title) {
try {
backStack[backStack.length - 1].title = title;
} catch(e) { }
//if on safari, set the title to be the empty string.
if (browser.safari) {
if (title == "") {
try {
var tmp = window.location.href.toString();
title = tmp.substring((tmp.lastIndexOf("/")+1), tmp.lastIndexOf("#"));
} catch(e) {
title = "";
}
}
}
document.title = title;
},
setDefaultURL: function(def)
{
defaultHash = def;
def = getHash();
//trailing ? is important else an extra frame gets added to the history
//when navigating back to the first page. Alternatively could check
//in history frame navigation to compare # and ?.
if (browser.ie)
{
window['_ie_firstload'] = true;
var sourceToSet = historyFrameSourcePrefix + def;
var func = function() {
getHistoryFrame().src = sourceToSet;
window.location.replace("#" + def);
setInterval(checkForUrlChange, 50);
}
try {
func();
} catch(e) {
window.setTimeout(function() { func(); }, 0);
}
}
if (browser.safari)
{
currentHistoryLength = history.length;
if (historyHash.length == 0) {
historyHash[currentHistoryLength] = def;
var newloc = "#" + def;
window.location.replace(newloc);
} else {
//alert(historyHash[historyHash.length-1]);
}
setInterval(checkForUrlChange, 50);
}
if (browser.firefox || browser.opera)
{
var reg = new RegExp("#" + def + "$");
if (window.location.toString().match(reg)) {
} else {
var newloc ="#" + def;
window.location.replace(newloc);
}
setInterval(checkForUrlChange, 50);
}
},
/* Set the current browser URL; called from inside BrowserManager to propagate
* the application state out to the container.
*/
setBrowserURL: function(flexAppUrl, objectId) {
if (browser.ie && typeof objectId != "undefined") {
currentObjectId = objectId;
}
//fromIframe = fromIframe || false;
//fromFlex = fromFlex || false;
//alert("setBrowserURL: " + flexAppUrl);
//flexAppUrl = (flexAppUrl == "") ? defaultHash : flexAppUrl ;
var pos = document.location.href.indexOf('#');
var baseUrl = pos != -1 ? document.location.href.substr(0, pos) : document.location.href;
var newUrl = baseUrl + '#' + flexAppUrl;
if (document.location.href != newUrl && document.location.href + '#' != newUrl) {
currentHref = newUrl;
addHistoryEntry(baseUrl, newUrl, flexAppUrl);
currentHistoryLength = history.length;
}
},
browserURLChange: function(flexAppUrl) {
var objectId = null;
if (browser.ie && currentObjectId != null) {
objectId = currentObjectId;
}
if (typeof BrowserHistory_multiple != "undefined" && BrowserHistory_multiple == true) {
var pl = getPlayers();
for (var i = 0; i < pl.length; i++) {
try {
pl[i].browserURLChange(flexAppUrl);
} catch(e) { }
}
} else {
try {
getPlayer(objectId).browserURLChange(flexAppUrl);
} catch(e) { }
}
currentObjectId = null;
},
getUserAgent: function() {
return navigator.userAgent;
},
getPlatform: function() {
return navigator.platform;
}
}
})();
// Initialization
// Automated unit testing and other diagnostics
function setURL(url)
{
document.location.href = url;
}
function backButton()
{
history.back();
}
function forwardButton()
{
history.forward();
}
function goForwardOrBackInHistory(step)
{
history.go(step);
}
//BrowserHistoryUtils.addEvent(window, "load", function() { BrowserHistory.initialize(); });
(function(i) {
var u =navigator.userAgent;var e=/*@cc_on!@*/false;
var st = setTimeout;
if(/webkit/i.test(u)){
st(function(){
var dr=document.readyState;
if(dr=="loaded"||dr=="complete"){i()}
else{st(arguments.callee,10);}},10);
} else if((/mozilla/i.test(u)&&!/(compati)/.test(u)) || (/opera/i.test(u))){
document.addEventListener("DOMContentLoaded",i,false);
} else if(e){
(function(){
var t=document.createElement('doc:rdy');
try{t.doScroll('left');
i();t=null;
}catch(e){st(arguments.callee,0);}})();
} else{
window.onload=i;
}
})( function() {BrowserHistory.initialize();} );

View File

@ -1,29 +0,0 @@
<html>
<head>
<META HTTP-EQUIV="Pragma" CONTENT="no-cache">
<META HTTP-EQUIV="Expires" CONTENT="-1">
</head>
<body>
<script>
function processUrl()
{
var pos = url.indexOf("?");
url = pos != -1 ? url.substr(pos + 1) : "";
if (!parent._ie_firstload) {
parent.BrowserHistory.setBrowserURL(url);
try {
parent.BrowserHistory.browserURLChange(url);
} catch(e) { }
} else {
parent._ie_firstload = false;
}
}
var url = document.location.href;
processUrl();
document.write(encodeURIComponent(url));
</script>
Hidden frame for Browser History support.
</body>
</html>

View File

@ -1,108 +0,0 @@
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<!-- saved from url=(0014)about:internet -->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<!--
Smart developers always View Source.
This application was built using Adobe Flex, an open source framework
for building rich Internet applications that get delivered via the
Flash Player or to desktops via Adobe AIR.
Learn more about Flex at http://flex.org
// -->
<head>
<title>${title}</title>
<meta name="google" value="notranslate" />
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<!-- Include CSS to eliminate any default margins/padding and set the height of the html element and
the body element to 100%, because Firefox, or any Gecko based browser, interprets percentage as
the percentage of the height of its parent container, which has to be set explicitly. Fix for
Firefox 3.6 focus border issues. Initially, don't display flashContent div so it won't show
if JavaScript disabled.
-->
<style type="text/css" media="screen">
html, body { height:100%; }
body { margin:0; padding:0; overflow:auto; text-align:center;
background-color: ${bgcolor}; }
object:focus { outline:none; }
#flashContent { display:none; }
</style>
<!-- Enable Browser History by replacing useBrowserHistory tokens with two hyphens -->
<!-- BEGIN Browser History required section ${useBrowserHistory}>
<link rel="stylesheet" type="text/css" href="history/history.css" />
<script type="text/javascript" src="history/history.js"></script>
<!${useBrowserHistory} END Browser History required section -->
<script type="text/javascript" src="swfobject.js"></script>
<script type="text/javascript">
// For version detection, set to min. required Flash Player version, or 0 (or 0.0.0), for no version detection.
var swfVersionStr = "${version_major}.${version_minor}.${version_revision}";
// To use express install, set to playerProductInstall.swf, otherwise the empty string.
var xiSwfUrlStr = "${expressInstallSwf}";
var flashvars = {};
var params = {};
params.quality = "high";
params.bgcolor = "${bgcolor}";
params.allowscriptaccess = "sameDomain";
params.allowfullscreen = "true";
var attributes = {};
attributes.id = "${application}";
attributes.name = "${application}";
attributes.align = "middle";
swfobject.embedSWF(
"${swf}.swf", "flashContent",
"${width}", "${height}",
swfVersionStr, xiSwfUrlStr,
flashvars, params, attributes);
// JavaScript enabled so display the flashContent div in case it is not replaced with a swf object.
swfobject.createCSS("#flashContent", "display:block;text-align:left;");
</script>
</head>
<body>
<!-- SWFObject's dynamic embed method replaces this alternative HTML content with Flash content when enough
JavaScript and Flash plug-in support is available. The div is initially hidden so that it doesn't show
when JavaScript is disabled.
-->
<div id="flashContent">
<p>
To view this page ensure that Adobe Flash Player version
${version_major}.${version_minor}.${version_revision} or greater is installed.
</p>
<script type="text/javascript">
var pageHost = ((document.location.protocol == "https:") ? "https://" : "http://");
document.write("<a href='http://www.adobe.com/go/getflashplayer'><img src='"
+ pageHost + "www.adobe.com/images/shared/download_buttons/get_flash_player.gif' alt='Get Adobe Flash player' /></a>" );
</script>
</div>
<noscript>
<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="${width}" height="${height}" id="${application}">
<param name="movie" value="${swf}.swf" />
<param name="quality" value="high" />
<param name="bgcolor" value="${bgcolor}" />
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="true" />
<!--[if !IE]>-->
<object type="application/x-shockwave-flash" data="${swf}.swf" width="${width}" height="${height}">
<param name="quality" value="high" />
<param name="bgcolor" value="${bgcolor}" />
<param name="allowScriptAccess" value="sameDomain" />
<param name="allowFullScreen" value="true" />
<!--<![endif]-->
<!--[if gte IE 6]>-->
<p>
Either scripts and active content are not permitted to run or Adobe Flash Player version
${version_major}.${version_minor}.${version_revision} or greater is not installed.
</p>
<!--<![endif]-->
<a href="http://www.adobe.com/go/getflashplayer">
<img src="http://www.adobe.com/images/shared/download_buttons/get_flash_player.gif" alt="Get Adobe Flash Player" />
</a>
<!--[if !IE]>-->
</object>
<!--<![endif]-->
</object>
</noscript>
</body>
</html>

View File

@ -1,777 +0,0 @@
/*! SWFObject v2.2 <http://code.google.com/p/swfobject/>
is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
*/
var swfobject = function() {
var UNDEF = "undefined",
OBJECT = "object",
SHOCKWAVE_FLASH = "Shockwave Flash",
SHOCKWAVE_FLASH_AX = "ShockwaveFlash.ShockwaveFlash",
FLASH_MIME_TYPE = "application/x-shockwave-flash",
EXPRESS_INSTALL_ID = "SWFObjectExprInst",
ON_READY_STATE_CHANGE = "onreadystatechange",
win = window,
doc = document,
nav = navigator,
plugin = false,
domLoadFnArr = [main],
regObjArr = [],
objIdArr = [],
listenersArr = [],
storedAltContent,
storedAltContentId,
storedCallbackFn,
storedCallbackObj,
isDomLoaded = false,
isExpressInstallActive = false,
dynamicStylesheet,
dynamicStylesheetMedia,
autoHideShow = true,
/* Centralized function for browser feature detection
- User agent string detection is only used when no good alternative is possible
- Is executed directly for optimal performance
*/
ua = function() {
var w3cdom = typeof doc.getElementById != UNDEF && typeof doc.getElementsByTagName != UNDEF && typeof doc.createElement != UNDEF,
u = nav.userAgent.toLowerCase(),
p = nav.platform.toLowerCase(),
windows = p ? /win/.test(p) : /win/.test(u),
mac = p ? /mac/.test(p) : /mac/.test(u),
webkit = /webkit/.test(u) ? parseFloat(u.replace(/^.*webkit\/(\d+(\.\d+)?).*$/, "$1")) : false, // returns either the webkit version or false if not webkit
ie = !+"\v1", // feature detection based on Andrea Giammarchi's solution: http://webreflection.blogspot.com/2009/01/32-bytes-to-know-if-your-browser-is-ie.html
playerVersion = [0,0,0],
d = null;
if (typeof nav.plugins != UNDEF && typeof nav.plugins[SHOCKWAVE_FLASH] == OBJECT) {
d = nav.plugins[SHOCKWAVE_FLASH].description;
if (d && !(typeof nav.mimeTypes != UNDEF && nav.mimeTypes[FLASH_MIME_TYPE] && !nav.mimeTypes[FLASH_MIME_TYPE].enabledPlugin)) { // navigator.mimeTypes["application/x-shockwave-flash"].enabledPlugin indicates whether plug-ins are enabled or disabled in Safari 3+
plugin = true;
ie = false; // cascaded feature detection for Internet Explorer
d = d.replace(/^.*\s+(\S+\s+\S+$)/, "$1");
playerVersion[0] = parseInt(d.replace(/^(.*)\..*$/, "$1"), 10);
playerVersion[1] = parseInt(d.replace(/^.*\.(.*)\s.*$/, "$1"), 10);
playerVersion[2] = /[a-zA-Z]/.test(d) ? parseInt(d.replace(/^.*[a-zA-Z]+(.*)$/, "$1"), 10) : 0;
}
}
else if (typeof win.ActiveXObject != UNDEF) {
try {
var a = new ActiveXObject(SHOCKWAVE_FLASH_AX);
if (a) { // a will return null when ActiveX is disabled
d = a.GetVariable("$version");
if (d) {
ie = true; // cascaded feature detection for Internet Explorer
d = d.split(" ")[1].split(",");
playerVersion = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
}
}
}
catch(e) {}
}
return { w3:w3cdom, pv:playerVersion, wk:webkit, ie:ie, win:windows, mac:mac };
}(),
/* Cross-browser onDomLoad
- Will fire an event as soon as the DOM of a web page is loaded
- Internet Explorer workaround based on Diego Perini's solution: http://javascript.nwbox.com/IEContentLoaded/
- Regular onload serves as fallback
*/
onDomLoad = function() {
if (!ua.w3) { return; }
if ((typeof doc.readyState != UNDEF && doc.readyState == "complete") || (typeof doc.readyState == UNDEF && (doc.getElementsByTagName("body")[0] || doc.body))) { // function is fired after onload, e.g. when script is inserted dynamically
callDomLoadFunctions();
}
if (!isDomLoaded) {
if (typeof doc.addEventListener != UNDEF) {
doc.addEventListener("DOMContentLoaded", callDomLoadFunctions, false);
}
if (ua.ie && ua.win) {
doc.attachEvent(ON_READY_STATE_CHANGE, function() {
if (doc.readyState == "complete") {
doc.detachEvent(ON_READY_STATE_CHANGE, arguments.callee);
callDomLoadFunctions();
}
});
if (win == top) { // if not inside an iframe
(function(){
if (isDomLoaded) { return; }
try {
doc.documentElement.doScroll("left");
}
catch(e) {
setTimeout(arguments.callee, 0);
return;
}
callDomLoadFunctions();
})();
}
}
if (ua.wk) {
(function(){
if (isDomLoaded) { return; }
if (!/loaded|complete/.test(doc.readyState)) {
setTimeout(arguments.callee, 0);
return;
}
callDomLoadFunctions();
})();
}
addLoadEvent(callDomLoadFunctions);
}
}();
function callDomLoadFunctions() {
if (isDomLoaded) { return; }
try { // test if we can really add/remove elements to/from the DOM; we don't want to fire it too early
var t = doc.getElementsByTagName("body")[0].appendChild(createElement("span"));
t.parentNode.removeChild(t);
}
catch (e) { return; }
isDomLoaded = true;
var dl = domLoadFnArr.length;
for (var i = 0; i < dl; i++) {
domLoadFnArr[i]();
}
}
function addDomLoadEvent(fn) {
if (isDomLoaded) {
fn();
}
else {
domLoadFnArr[domLoadFnArr.length] = fn; // Array.push() is only available in IE5.5+
}
}
/* Cross-browser onload
- Based on James Edwards' solution: http://brothercake.com/site/resources/scripts/onload/
- Will fire an event as soon as a web page including all of its assets are loaded
*/
function addLoadEvent(fn) {
if (typeof win.addEventListener != UNDEF) {
win.addEventListener("load", fn, false);
}
else if (typeof doc.addEventListener != UNDEF) {
doc.addEventListener("load", fn, false);
}
else if (typeof win.attachEvent != UNDEF) {
addListener(win, "onload", fn);
}
else if (typeof win.onload == "function") {
var fnOld = win.onload;
win.onload = function() {
fnOld();
fn();
};
}
else {
win.onload = fn;
}
}
/* Main function
- Will preferably execute onDomLoad, otherwise onload (as a fallback)
*/
function main() {
if (plugin) {
testPlayerVersion();
}
else {
matchVersions();
}
}
/* Detect the Flash Player version for non-Internet Explorer browsers
- Detecting the plug-in version via the object element is more precise than using the plugins collection item's description:
a. Both release and build numbers can be detected
b. Avoid wrong descriptions by corrupt installers provided by Adobe
c. Avoid wrong descriptions by multiple Flash Player entries in the plugin Array, caused by incorrect browser imports
- Disadvantage of this method is that it depends on the availability of the DOM, while the plugins collection is immediately available
*/
function testPlayerVersion() {
var b = doc.getElementsByTagName("body")[0];
var o = createElement(OBJECT);
o.setAttribute("type", FLASH_MIME_TYPE);
var t = b.appendChild(o);
if (t) {
var counter = 0;
(function(){
if (typeof t.GetVariable != UNDEF) {
var d = t.GetVariable("$version");
if (d) {
d = d.split(" ")[1].split(",");
ua.pv = [parseInt(d[0], 10), parseInt(d[1], 10), parseInt(d[2], 10)];
}
}
else if (counter < 10) {
counter++;
setTimeout(arguments.callee, 10);
return;
}
b.removeChild(o);
t = null;
matchVersions();
})();
}
else {
matchVersions();
}
}
/* Perform Flash Player and SWF version matching; static publishing only
*/
function matchVersions() {
var rl = regObjArr.length;
if (rl > 0) {
for (var i = 0; i < rl; i++) { // for each registered object element
var id = regObjArr[i].id;
var cb = regObjArr[i].callbackFn;
var cbObj = {success:false, id:id};
if (ua.pv[0] > 0) {
var obj = getElementById(id);
if (obj) {
if (hasPlayerVersion(regObjArr[i].swfVersion) && !(ua.wk && ua.wk < 312)) { // Flash Player version >= published SWF version: Houston, we have a match!
setVisibility(id, true);
if (cb) {
cbObj.success = true;
cbObj.ref = getObjectById(id);
cb(cbObj);
}
}
else if (regObjArr[i].expressInstall && canExpressInstall()) { // show the Adobe Express Install dialog if set by the web page author and if supported
var att = {};
att.data = regObjArr[i].expressInstall;
att.width = obj.getAttribute("width") || "0";
att.height = obj.getAttribute("height") || "0";
if (obj.getAttribute("class")) { att.styleclass = obj.getAttribute("class"); }
if (obj.getAttribute("align")) { att.align = obj.getAttribute("align"); }
// parse HTML object param element's name-value pairs
var par = {};
var p = obj.getElementsByTagName("param");
var pl = p.length;
for (var j = 0; j < pl; j++) {
if (p[j].getAttribute("name").toLowerCase() != "movie") {
par[p[j].getAttribute("name")] = p[j].getAttribute("value");
}
}
showExpressInstall(att, par, id, cb);
}
else { // Flash Player and SWF version mismatch or an older Webkit engine that ignores the HTML object element's nested param elements: display alternative content instead of SWF
displayAltContent(obj);
if (cb) { cb(cbObj); }
}
}
}
else { // if no Flash Player is installed or the fp version cannot be detected we let the HTML object element do its job (either show a SWF or alternative content)
setVisibility(id, true);
if (cb) {
var o = getObjectById(id); // test whether there is an HTML object element or not
if (o && typeof o.SetVariable != UNDEF) {
cbObj.success = true;
cbObj.ref = o;
}
cb(cbObj);
}
}
}
}
}
function getObjectById(objectIdStr) {
var r = null;
var o = getElementById(objectIdStr);
if (o && o.nodeName == "OBJECT") {
if (typeof o.SetVariable != UNDEF) {
r = o;
}
else {
var n = o.getElementsByTagName(OBJECT)[0];
if (n) {
r = n;
}
}
}
return r;
}
/* Requirements for Adobe Express Install
- only one instance can be active at a time
- fp 6.0.65 or higher
- Win/Mac OS only
- no Webkit engines older than version 312
*/
function canExpressInstall() {
return !isExpressInstallActive && hasPlayerVersion("6.0.65") && (ua.win || ua.mac) && !(ua.wk && ua.wk < 312);
}
/* Show the Adobe Express Install dialog
- Reference: http://www.adobe.com/cfusion/knowledgebase/index.cfm?id=6a253b75
*/
function showExpressInstall(att, par, replaceElemIdStr, callbackFn) {
isExpressInstallActive = true;
storedCallbackFn = callbackFn || null;
storedCallbackObj = {success:false, id:replaceElemIdStr};
var obj = getElementById(replaceElemIdStr);
if (obj) {
if (obj.nodeName == "OBJECT") { // static publishing
storedAltContent = abstractAltContent(obj);
storedAltContentId = null;
}
else { // dynamic publishing
storedAltContent = obj;
storedAltContentId = replaceElemIdStr;
}
att.id = EXPRESS_INSTALL_ID;
if (typeof att.width == UNDEF || (!/%$/.test(att.width) && parseInt(att.width, 10) < 310)) { att.width = "310"; }
if (typeof att.height == UNDEF || (!/%$/.test(att.height) && parseInt(att.height, 10) < 137)) { att.height = "137"; }
doc.title = doc.title.slice(0, 47) + " - Flash Player Installation";
var pt = ua.ie && ua.win ? "ActiveX" : "PlugIn",
fv = "MMredirectURL=" + encodeURI(window.location).toString().replace(/&/g,"%26") + "&MMplayerType=" + pt + "&MMdoctitle=" + doc.title;
if (typeof par.flashvars != UNDEF) {
par.flashvars += "&" + fv;
}
else {
par.flashvars = fv;
}
// IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
if (ua.ie && ua.win && obj.readyState != 4) {
var newObj = createElement("div");
replaceElemIdStr += "SWFObjectNew";
newObj.setAttribute("id", replaceElemIdStr);
obj.parentNode.insertBefore(newObj, obj); // insert placeholder div that will be replaced by the object element that loads expressinstall.swf
obj.style.display = "none";
(function(){
if (obj.readyState == 4) {
obj.parentNode.removeChild(obj);
}
else {
setTimeout(arguments.callee, 10);
}
})();
}
createSWF(att, par, replaceElemIdStr);
}
}
/* Functions to abstract and display alternative content
*/
function displayAltContent(obj) {
if (ua.ie && ua.win && obj.readyState != 4) {
// IE only: when a SWF is loading (AND: not available in cache) wait for the readyState of the object element to become 4 before removing it,
// because you cannot properly cancel a loading SWF file without breaking browser load references, also obj.onreadystatechange doesn't work
var el = createElement("div");
obj.parentNode.insertBefore(el, obj); // insert placeholder div that will be replaced by the alternative content
el.parentNode.replaceChild(abstractAltContent(obj), el);
obj.style.display = "none";
(function(){
if (obj.readyState == 4) {
obj.parentNode.removeChild(obj);
}
else {
setTimeout(arguments.callee, 10);
}
})();
}
else {
obj.parentNode.replaceChild(abstractAltContent(obj), obj);
}
}
function abstractAltContent(obj) {
var ac = createElement("div");
if (ua.win && ua.ie) {
ac.innerHTML = obj.innerHTML;
}
else {
var nestedObj = obj.getElementsByTagName(OBJECT)[0];
if (nestedObj) {
var c = nestedObj.childNodes;
if (c) {
var cl = c.length;
for (var i = 0; i < cl; i++) {
if (!(c[i].nodeType == 1 && c[i].nodeName == "PARAM") && !(c[i].nodeType == 8)) {
ac.appendChild(c[i].cloneNode(true));
}
}
}
}
}
return ac;
}
/* Cross-browser dynamic SWF creation
*/
function createSWF(attObj, parObj, id) {
var r, el = getElementById(id);
if (ua.wk && ua.wk < 312) { return r; }
if (el) {
if (typeof attObj.id == UNDEF) { // if no 'id' is defined for the object element, it will inherit the 'id' from the alternative content
attObj.id = id;
}
if (ua.ie && ua.win) { // Internet Explorer + the HTML object element + W3C DOM methods do not combine: fall back to outerHTML
var att = "";
for (var i in attObj) {
if (attObj[i] != Object.prototype[i]) { // filter out prototype additions from other potential libraries
if (i.toLowerCase() == "data") {
parObj.movie = attObj[i];
}
else if (i.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
att += ' class="' + attObj[i] + '"';
}
else if (i.toLowerCase() != "classid") {
att += ' ' + i + '="' + attObj[i] + '"';
}
}
}
var par = "";
for (var j in parObj) {
if (parObj[j] != Object.prototype[j]) { // filter out prototype additions from other potential libraries
par += '<param name="' + j + '" value="' + parObj[j] + '" />';
}
}
el.outerHTML = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"' + att + '>' + par + '</object>';
objIdArr[objIdArr.length] = attObj.id; // stored to fix object 'leaks' on unload (dynamic publishing only)
r = getElementById(attObj.id);
}
else { // well-behaving browsers
var o = createElement(OBJECT);
o.setAttribute("type", FLASH_MIME_TYPE);
for (var m in attObj) {
if (attObj[m] != Object.prototype[m]) { // filter out prototype additions from other potential libraries
if (m.toLowerCase() == "styleclass") { // 'class' is an ECMA4 reserved keyword
o.setAttribute("class", attObj[m]);
}
else if (m.toLowerCase() != "classid") { // filter out IE specific attribute
o.setAttribute(m, attObj[m]);
}
}
}
for (var n in parObj) {
if (parObj[n] != Object.prototype[n] && n.toLowerCase() != "movie") { // filter out prototype additions from other potential libraries and IE specific param element
createObjParam(o, n, parObj[n]);
}
}
el.parentNode.replaceChild(o, el);
r = o;
}
}
return r;
}
function createObjParam(el, pName, pValue) {
var p = createElement("param");
p.setAttribute("name", pName);
p.setAttribute("value", pValue);
el.appendChild(p);
}
/* Cross-browser SWF removal
- Especially needed to safely and completely remove a SWF in Internet Explorer
*/
function removeSWF(id) {
var obj = getElementById(id);
if (obj && obj.nodeName == "OBJECT") {
if (ua.ie && ua.win) {
obj.style.display = "none";
(function(){
if (obj.readyState == 4) {
removeObjectInIE(id);
}
else {
setTimeout(arguments.callee, 10);
}
})();
}
else {
obj.parentNode.removeChild(obj);
}
}
}
function removeObjectInIE(id) {
var obj = getElementById(id);
if (obj) {
for (var i in obj) {
if (typeof obj[i] == "function") {
obj[i] = null;
}
}
obj.parentNode.removeChild(obj);
}
}
/* Functions to optimize JavaScript compression
*/
function getElementById(id) {
var el = null;
try {
el = doc.getElementById(id);
}
catch (e) {}
return el;
}
function createElement(el) {
return doc.createElement(el);
}
/* Updated attachEvent function for Internet Explorer
- Stores attachEvent information in an Array, so on unload the detachEvent functions can be called to avoid memory leaks
*/
function addListener(target, eventType, fn) {
target.attachEvent(eventType, fn);
listenersArr[listenersArr.length] = [target, eventType, fn];
}
/* Flash Player and SWF content version matching
*/
function hasPlayerVersion(rv) {
var pv = ua.pv, v = rv.split(".");
v[0] = parseInt(v[0], 10);
v[1] = parseInt(v[1], 10) || 0; // supports short notation, e.g. "9" instead of "9.0.0"
v[2] = parseInt(v[2], 10) || 0;
return (pv[0] > v[0] || (pv[0] == v[0] && pv[1] > v[1]) || (pv[0] == v[0] && pv[1] == v[1] && pv[2] >= v[2])) ? true : false;
}
/* Cross-browser dynamic CSS creation
- Based on Bobby van der Sluis' solution: http://www.bobbyvandersluis.com/articles/dynamicCSS.php
*/
function createCSS(sel, decl, media, newStyle) {
if (ua.ie && ua.mac) { return; }
var h = doc.getElementsByTagName("head")[0];
if (!h) { return; } // to also support badly authored HTML pages that lack a head element
var m = (media && typeof media == "string") ? media : "screen";
if (newStyle) {
dynamicStylesheet = null;
dynamicStylesheetMedia = null;
}
if (!dynamicStylesheet || dynamicStylesheetMedia != m) {
// create dynamic stylesheet + get a global reference to it
var s = createElement("style");
s.setAttribute("type", "text/css");
s.setAttribute("media", m);
dynamicStylesheet = h.appendChild(s);
if (ua.ie && ua.win && typeof doc.styleSheets != UNDEF && doc.styleSheets.length > 0) {
dynamicStylesheet = doc.styleSheets[doc.styleSheets.length - 1];
}
dynamicStylesheetMedia = m;
}
// add style rule
if (ua.ie && ua.win) {
if (dynamicStylesheet && typeof dynamicStylesheet.addRule == OBJECT) {
dynamicStylesheet.addRule(sel, decl);
}
}
else {
if (dynamicStylesheet && typeof doc.createTextNode != UNDEF) {
dynamicStylesheet.appendChild(doc.createTextNode(sel + " {" + decl + "}"));
}
}
}
function setVisibility(id, isVisible) {
if (!autoHideShow) { return; }
var v = isVisible ? "visible" : "hidden";
if (isDomLoaded && getElementById(id)) {
getElementById(id).style.visibility = v;
}
else {
createCSS("#" + id, "visibility:" + v);
}
}
/* Filter to avoid XSS attacks
*/
function urlEncodeIfNecessary(s) {
var regex = /[\\\"<>\.;]/;
var hasBadChars = regex.exec(s) != null;
return hasBadChars && typeof encodeURIComponent != UNDEF ? encodeURIComponent(s) : s;
}
/* Release memory to avoid memory leaks caused by closures, fix hanging audio/video threads and force open sockets/NetConnections to disconnect (Internet Explorer only)
*/
var cleanup = function() {
if (ua.ie && ua.win) {
window.attachEvent("onunload", function() {
// remove listeners to avoid memory leaks
var ll = listenersArr.length;
for (var i = 0; i < ll; i++) {
listenersArr[i][0].detachEvent(listenersArr[i][1], listenersArr[i][2]);
}
// cleanup dynamically embedded objects to fix audio/video threads and force open sockets and NetConnections to disconnect
var il = objIdArr.length;
for (var j = 0; j < il; j++) {
removeSWF(objIdArr[j]);
}
// cleanup library's main closures to avoid memory leaks
for (var k in ua) {
ua[k] = null;
}
ua = null;
for (var l in swfobject) {
swfobject[l] = null;
}
swfobject = null;
});
}
}();
return {
/* Public API
- Reference: http://code.google.com/p/swfobject/wiki/documentation
*/
registerObject: function(objectIdStr, swfVersionStr, xiSwfUrlStr, callbackFn) {
if (ua.w3 && objectIdStr && swfVersionStr) {
var regObj = {};
regObj.id = objectIdStr;
regObj.swfVersion = swfVersionStr;
regObj.expressInstall = xiSwfUrlStr;
regObj.callbackFn = callbackFn;
regObjArr[regObjArr.length] = regObj;
setVisibility(objectIdStr, false);
}
else if (callbackFn) {
callbackFn({success:false, id:objectIdStr});
}
},
getObjectById: function(objectIdStr) {
if (ua.w3) {
return getObjectById(objectIdStr);
}
},
embedSWF: function(swfUrlStr, replaceElemIdStr, widthStr, heightStr, swfVersionStr, xiSwfUrlStr, flashvarsObj, parObj, attObj, callbackFn) {
var callbackObj = {success:false, id:replaceElemIdStr};
if (ua.w3 && !(ua.wk && ua.wk < 312) && swfUrlStr && replaceElemIdStr && widthStr && heightStr && swfVersionStr) {
setVisibility(replaceElemIdStr, false);
addDomLoadEvent(function() {
widthStr += ""; // auto-convert to string
heightStr += "";
var att = {};
if (attObj && typeof attObj === OBJECT) {
for (var i in attObj) { // copy object to avoid the use of references, because web authors often reuse attObj for multiple SWFs
att[i] = attObj[i];
}
}
att.data = swfUrlStr;
att.width = widthStr;
att.height = heightStr;
var par = {};
if (parObj && typeof parObj === OBJECT) {
for (var j in parObj) { // copy object to avoid the use of references, because web authors often reuse parObj for multiple SWFs
par[j] = parObj[j];
}
}
if (flashvarsObj && typeof flashvarsObj === OBJECT) {
for (var k in flashvarsObj) { // copy object to avoid the use of references, because web authors often reuse flashvarsObj for multiple SWFs
if (typeof par.flashvars != UNDEF) {
par.flashvars += "&" + k + "=" + flashvarsObj[k];
}
else {
par.flashvars = k + "=" + flashvarsObj[k];
}
}
}
if (hasPlayerVersion(swfVersionStr)) { // create SWF
var obj = createSWF(att, par, replaceElemIdStr);
if (att.id == replaceElemIdStr) {
setVisibility(replaceElemIdStr, true);
}
callbackObj.success = true;
callbackObj.ref = obj;
}
else if (xiSwfUrlStr && canExpressInstall()) { // show Adobe Express Install
att.data = xiSwfUrlStr;
showExpressInstall(att, par, replaceElemIdStr, callbackFn);
return;
}
else { // show alternative content
setVisibility(replaceElemIdStr, true);
}
if (callbackFn) { callbackFn(callbackObj); }
});
}
else if (callbackFn) { callbackFn(callbackObj); }
},
switchOffAutoHideShow: function() {
autoHideShow = false;
},
ua: ua,
getFlashPlayerVersion: function() {
return { major:ua.pv[0], minor:ua.pv[1], release:ua.pv[2] };
},
hasFlashPlayerVersion: hasPlayerVersion,
createSWF: function(attObj, parObj, replaceElemIdStr) {
if (ua.w3) {
return createSWF(attObj, parObj, replaceElemIdStr);
}
else {
return undefined;
}
},
showExpressInstall: function(att, par, replaceElemIdStr, callbackFn) {
if (ua.w3 && canExpressInstall()) {
showExpressInstall(att, par, replaceElemIdStr, callbackFn);
}
},
removeSWF: function(objElemIdStr) {
if (ua.w3) {
removeSWF(objElemIdStr);
}
},
createCSS: function(selStr, declStr, mediaStr, newStyleBoolean) {
if (ua.w3) {
createCSS(selStr, declStr, mediaStr, newStyleBoolean);
}
},
addDomLoadEvent: addDomLoadEvent,
addLoadEvent: addLoadEvent,
getQueryParamValue: function(param) {
var q = doc.location.search || doc.location.hash;
if (q) {
if (/\?/.test(q)) { q = q.split("?")[1]; } // strip question mark
if (param == null) {
return urlEncodeIfNecessary(q);
}
var pairs = q.split("&");
for (var i = 0; i < pairs.length; i++) {
if (pairs[i].substring(0, pairs[i].indexOf("=")) == param) {
return urlEncodeIfNecessary(pairs[i].substring((pairs[i].indexOf("=") + 1)));
}
}
}
return "";
},
// For internal usage only
expressInstallCallback: function() {
if (isExpressInstallActive) {
var obj = getElementById(EXPRESS_INSTALL_ID);
if (obj && storedAltContent) {
obj.parentNode.replaceChild(storedAltContent, obj);
if (storedAltContentId) {
setVisibility(storedAltContentId, true);
if (ua.ie && ua.win) { storedAltContent.style.display = "block"; }
}
if (storedCallbackFn) { storedCallbackFn(storedCallbackObj); }
}
isExpressInstallActive = false;
}
}
};
}();

Binary file not shown.

View File

@ -1,218 +0,0 @@
package
{
import flash.display.Sprite;
import flash.events.Event;
import flash.events.IOErrorEvent;
import flash.events.ProgressEvent;
import flash.events.TimerEvent;
import flash.external.ExternalInterface;
import flash.media.Sound;
import flash.net.Socket;
import flash.net.URLRequest;
import flash.system.Security;
import flash.utils.Timer;
public class CIMBridge extends Sprite
{
internal var CIM_HOST:String = "127.0.0.1";
internal var CIM_PORT:Number = 23456;
internal const TIME_OUT :Number =10000;
internal const RE_CONNECT_TIME :Number = 20000;
internal var socket:Socket = new Socket();
internal var froceOffline :Boolean = false;
internal const MESSAGE_SEPARATE :String = '\b';
/**
*
*/
internal const CMD_HEARTBEAT_REQUEST:String="S_H_RQ";
/**
*
*/
internal const CMD_HEARTBEAT_RESPONSE:String ="C_H_RS";
internal var mBuffer :String = '';
public function CIMBridge()
{
ExternalInterface.addCallback("connect",connect);
ExternalInterface.addCallback("bindAccount",bindAccount);
ExternalInterface.addCallback("getOfflineMessage",getOfflineMessage);
ExternalInterface.addCallback("logout",logout);
ExternalInterface.addCallback("playSound",playSound);
ExternalInterface.call("flashBridgeCreated");
}
public function connect(host:String,port:Number):void
{
CIM_HOST = host;
CIM_PORT = port;
var policyfile:String="xmlsocket://"+CIM_HOST+":"+CIM_PORT;
Security.loadPolicyFile(policyfile);//
socket.timeout = TIME_OUT;
socket.addEventListener(Event.CONNECT,sessionCreated);//
socket.addEventListener(Event.CLOSE,sessionClosed);//
socket.addEventListener(IOErrorEvent.IO_ERROR,sessionFailed);//
socket.addEventListener(ProgressEvent.SOCKET_DATA,messageReceived); //
socket.connect(CIM_HOST,CIM_PORT);//
var timer:Timer = new Timer(TIME_OUT, 1);
timer.addEventListener(TimerEvent.TIMER, function():void{
if(socket.connected == false){
sessionFailed(new IOErrorEvent(""));
}
});
timer.start();
}
public function bindAccount(account:String,deviceId:String):void
{
var xml:String="<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
xml+="<sent>";
xml+="<key>client_bind</key>";
xml+="<data>";
xml+="<account>"+account+"</account>";
xml+="<deviceId>"+deviceId+"</deviceId>";
xml+="<channel>browse</channel>";
xml+="<device>Flash</device>";
xml+="<version>2.0.0</version>";
xml+="<osVersion>"+flash.system.Capabilities.os+"</osVersion>";
xml+="</data>";
xml+="</sent>";
send(xml);
}
public function getOfflineMessage(account:String):void
{
var xml:String="<?xml version=\"1.0\" encoding=\"UTF-8\"?>";
xml+="<sent>";
xml+="<key>client_get_offline_message</key>";
xml+="<data>";
xml+="<account>"+account+"</account>";
xml+="</data>";
xml+="</sent>";
send(xml);
}
public function logout():void
{
socket.close();
}
private function sessionCreated(event:Event):void
{
ExternalInterface.call("sessionCreated");
froceOffline = false;
}
private function sessionClosed(event:Event):void
{
ExternalInterface.call("sessionClosed");
if(!froceOffline)
{
reconnection();
}
}
private function sessionFailed(event:Event):void
{
//20
ExternalInterface.call("sessionFailed");
reconnection();
}
private function reconnection():void{
var timer:Timer = new Timer(RE_CONNECT_TIME + Math.random() * 10, 1);
timer.addEventListener(TimerEvent.TIMER, function():void{
connect(CIM_HOST,CIM_PORT);
});
timer.start();
}
internal function handleMessage(message:String):void{
if(message.toUpperCase() == CMD_HEARTBEAT_REQUEST)
{
send(CMD_HEARTBEAT_RESPONSE);
return;
}
var xml:XML=XML(message);
if(xml.name()=="reply"){
ExternalInterface.call("onReplyReceived",ReplyBody.mappingToJSON(xml));
}
if(xml.name()=="message"){
if(xml["type"]=="999")
{
froceOffline = true;
}
ExternalInterface.call("onMessageReceived",Message.mappingToJSON(xml));
}
}
/**接受服务器信息*/
internal function messageReceived(event:ProgressEvent):void
{
mBuffer+=socket.readMultiByte(socket.bytesAvailable,"UTF-8");;
if(mBuffer.charAt(mBuffer.length-1)!=MESSAGE_SEPARATE){
return ;
}else
{
var array:Array = mBuffer.split(MESSAGE_SEPARATE);
for each(var message:String in array) {
handleMessage(message);
}
mBuffer = "";
}
}
/**发送数据到服务器*/
internal function send(msg:String):void
{
//ByteArray来存放数据
socket.writeUTFBytes(msg+MESSAGE_SEPARATE);
//flush方法发送信息
socket.flush();
}
public function playSound(name:String):void
{
internal var _sound:Sound = new Sound(new URLRequest(name));
_sound.play(1);
}
}
}

View File

@ -1,77 +0,0 @@
package
{
import com.adobe.serialization.json.JSON;
public class Message
{
/**
*
*/
public var mid:String;
/**
*
*/
public var type:String;
/**
*
*/
public var title:String;
/**
* type content format text,json ,xml数据格式
*/
public var content:String = "";
/**
*
*/
public var sender:String;
/**
*
*/
public var receiver:String;
/**
* url
*/
public var file:String;
/**
*
*/
public var fileType:String;
/**
* content
*/
public var format:String = "txt";
public var timestamp:Number;
public static function mappingToJSON(xml:XML):Object
{
var message:Message = new Message();
message.mid = xml["mid"];
message.type = xml["type"];
message.title = xml["title"];
message.sender = xml["sender"];
message.receiver = xml["receiver"];
message.file = xml["file"];
message.fileType = xml["fileType"];
message.timestamp = xml["timestamp"];
message.content =xml["content"];
return com.adobe.serialization.json.JSON.encode(message).toString();
}
}
}

View File

@ -1,31 +0,0 @@
package
{
import com.adobe.serialization.json.JSON;
public class ReplyBody
{
public var key:String;
public var code:String;
public var message:String;
public var data:Object = new Object();
public var timestamp:Number;
public static function mappingToJSON(xml:XML):String
{
var body:ReplyBody = new ReplyBody();
body.key = xml["key"];
body.code = xml["code"];
body.timestamp = xml["timestamp"];
var list:XMLList = xml.elements("data").children();
for each(var item:XML in list) {
body.data[item.name().toString()] =item.toString();
}
return com.adobe.serialization.json.JSON.encode(body);
}
}
}

Binary file not shown.

View File

@ -1,7 +1,7 @@
#说明
此开源版本为基础功能版本只有消息推送的基础功能netty版本,和mina版本结构和功能完全一致大家可以选择自己喜欢的或者合适的版本学习或者使用!
#侣信专业版1.6.5版本发布
#侣信专业版1.7.0版本发布
#[http://farsunset.com](http://farsunset.com)

View File

@ -2,7 +2,9 @@
<classpath>
<classpathentry kind="src" path="src"/>
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
<classpathentry kind="lib" path="/cim-server/WebRoot/WEB-INF/lib/mina-core-2.0.13.jar"/>
<classpathentry kind="lib" path="C:/dev/android-sdk-windows/platforms/android-22/android.jar"/>
<classpathentry kind="lib" path="libs/log4j-1.2.17.jar"/>
<classpathentry kind="lib" path="D:/Program Files (x86)/dev/android-sdk-windos/platforms/android-21/android.jar"/>
<classpathentry kind="lib" path="libs/mina-core-2.0.16.jar"/>
<classpathentry kind="lib" path="libs/protobuf-java-3.2.0.jar"/>
<classpathentry kind="output" path="bin"/>
</classpath>

View File

@ -0,0 +1,12 @@
eclipse.preferences.version=1
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
org.eclipse.jdt.core.compiler.codegen.methodParameters=do not generate
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
org.eclipse.jdt.core.compiler.compliance=1.7
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
org.eclipse.jdt.core.compiler.debug.localVariable=generate
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
org.eclipse.jdt.core.compiler.source=1.7

Binary file not shown.

Binary file not shown.

View File

@ -1,11 +1,27 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
@ -14,15 +30,17 @@ import android.database.sqlite.SQLiteOpenHelper;
class CIMCacheToolkit extends SQLiteOpenHelper {
private static final String DATABASE_NAME = "CIM_CONFIG_INFO.db";
private static final int DATABASE_VERSION = 20160416;
private static final int DATABASE_VERSION = 20160406;
private static final String TABLE_NAME = "T_CIM_CONFIG";
private static CIMCacheToolkit toolkit;
private static final String TABLE_SQL = "CREATE TABLE IF NOT EXISTS "+TABLE_NAME+" (KEY VARCHAR(64) PRIMARY KEY,VALUE TEXT)";
private static final String TABLE_SQL = "CREATE TABLE IF NOT EXISTS T_CIM_CONFIG (KEY VARCHAR(64) PRIMARY KEY,VALUE TEXT)";
private static final String DELETE_SQL = "DELETE FROM "+TABLE_NAME+" WHERE KEY = ?";
private static final String DELETE_SQL = "DELETE FROM T_CIM_CONFIG WHERE KEY = ?";
private static final String QUERY_SQL = "SELECT VALUE FROM "+TABLE_NAME+" WHERE KEY = ?";
private static final String SAVE_SQL = "INSERT INTO T_CIM_CONFIG (KEY,VALUE) VALUES(?,?)";
private static final String QUERY_SQL = "SELECT VALUE FROM T_CIM_CONFIG WHERE KEY = ?";
private SQLiteDatabase mSQLiteDatabase;
public static final String CIM_CONFIG_INFO = "CIM_CONFIG_INFO";
@ -37,16 +55,15 @@ class CIMCacheToolkit extends SQLiteOpenHelper {
public static final String KEY_CIM_SERVIER_PORT = "KEY_CIM_SERVIER_PORT";
public static final String KEY_CIM_CONNECTION_STATE = "KEY_CIM_CONNECTION_STATE";
private static CIMCacheToolkit toolkit;
private SQLiteDatabase mSQLiteDatabase;
public synchronized static CIMCacheToolkit getInstance(Context context){
if (toolkit==null){
toolkit = new CIMCacheToolkit(context);
}
return toolkit;
if(toolkit==null){
toolkit = new CIMCacheToolkit(context);
}
return toolkit;
}
@ -59,7 +76,6 @@ class CIMCacheToolkit extends SQLiteOpenHelper {
}
public synchronized void remove(String key)
{
getSQLiteDatabase().execSQL(DELETE_SQL,new String[]{key});
@ -68,8 +84,15 @@ class CIMCacheToolkit extends SQLiteOpenHelper {
public synchronized void putString(String key,String value)
{
getSQLiteDatabase().execSQL(DELETE_SQL,new String[]{key});
getSQLiteDatabase().execSQL(SAVE_SQL, new String[]{key, value});
ContentValues values = new ContentValues();
values.put("VALUE", value);
int result = getSQLiteDatabase().updateWithOnConflict(TABLE_NAME, values, "KEY=?",new String[]{key},SQLiteDatabase.CONFLICT_FAIL);
if(result<=0){
values.put("KEY", key);
getSQLiteDatabase().insert(TABLE_NAME, null, values);
}
}
@ -77,14 +100,15 @@ class CIMCacheToolkit extends SQLiteOpenHelper {
{
String value = null;
Cursor cursor = getSQLiteDatabase().rawQuery(QUERY_SQL, new String[]{key});
if (cursor!=null&&cursor.moveToFirst())
if (cursor!=null)
{
value = cursor.getString(0);
if(cursor.moveToFirst()){
value = cursor.getString(0);
}
cursor.close();
}
return value;
}
@ -123,6 +147,8 @@ class CIMCacheToolkit extends SQLiteOpenHelper {
try{toolkit.close();}catch(Exception e){}
}
toolkit = null;
}

View File

@ -1,15 +1,30 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android;
import java.net.InetSocketAddress;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;
import org.apache.mina.core.future.ConnectFuture;
import org.apache.mina.core.future.WriteFuture;
@ -19,6 +34,7 @@ import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolCodecFilter;
import org.apache.mina.filter.keepalive.KeepAliveFilter;
import org.apache.mina.filter.keepalive.KeepAliveMessageFactory;
import org.apache.mina.filter.keepalive.KeepAliveRequestTimeoutHandler;
import org.apache.mina.transport.socket.nio.NioSocketConnector;
import android.content.Context;
import android.content.Intent;
@ -27,10 +43,11 @@ import android.net.NetworkInfo;
import android.util.Log;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.exception.CIMSessionDisableException;
import com.farsunset.cim.sdk.android.exception.NetWorkDisableException;
import com.farsunset.cim.sdk.android.exception.WriteToClosedSessionException;
import com.farsunset.cim.sdk.android.exception.SessionDisconnectedException;
import com.farsunset.cim.sdk.android.exception.NetworkDisconnectedException;
import com.farsunset.cim.sdk.android.filter.ClientMessageCodecFactory;
import com.farsunset.cim.sdk.android.model.HeartbeatRequest;
import com.farsunset.cim.sdk.android.model.HeartbeatResponse;
import com.farsunset.cim.sdk.android.model.Message;
import com.farsunset.cim.sdk.android.model.ReplyBody;
import com.farsunset.cim.sdk.android.model.SentBody;
@ -40,65 +57,44 @@ import com.farsunset.cim.sdk.android.model.SentBody;
*
* @author 3979434@qq.com
*/
class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFactory{
class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFactory {
final static String TAG = CIMConnectorManager.class.getSimpleName();
private NioSocketConnector connector;
private ConnectFuture connectFuture;
private final String TAG = CIMConnectorManager.class.getSimpleName();
private final int READ_BUFFER_SIZE = 2048;//bit
private final int CONNECT_TIMEOUT = 10 * 1000;//
private final int WRITE_TIMEOUT = 10 * 1000;//
Context context;
private final int BOTH_IDLE_TIME = 120;//
private final int HEARBEAT_TIME_OUT = 330 * 1000;// 收到服务端心跳请求超时时间 毫秒
private final int READ_IDLE_TIME = 120;//
private final int HEARBEAT_TIME_OUT = (READ_IDLE_TIME + 20) * 1000;// 收到服务端心跳请求超时时间 毫秒
private final String KEY_LAST_HEART_TIME = "KEY_LAST_HEART_TIME" ;
private NioSocketConnector connector;
private ConnectFuture connectFuture;
private ExecutorService executor = Executors.newFixedThreadPool(1);
private Context context;
static CIMConnectorManager manager;
private static CIMConnectorManager manager;
// 消息广播action
public static final String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED";
// 发送sendbody失败广播
public static final String ACTION_SENT_FAILED = "com.farsunset.cim.SENT_FAILED";
// 发送sendbody成功广播
public static final String ACTION_SENT_SUCCESSED = "com.farsunset.cim.SENT_SUCCESSED";
// 链接意外关闭广播
public static final String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED";
// 链接失败广播
public static final String ACTION_CONNECTION_FAILED = "com.farsunset.cim.CONNECTION_FAILED";
// 链接成功广播
public static final String ACTION_CONNECTION_SUCCESSED = "com.farsunset.cim.CONNECTION_SUCCESSED";
// 发送sendbody成功后获得replaybody回应广播
public static final String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED";
// 网络变化广播
public static final String ACTION_NETWORK_CHANGED = "android.net.conn.CONNECTIVITY_CHANGE";
// 未知异常
public static final String ACTION_UNCAUGHT_EXCEPTION = "com.farsunset.cim.UNCAUGHT_EXCEPTION";
//重试连接
public final static String ACTION_CONNECTION_RECOVERY = "com.farsunset.cim.CONNECTION_RECOVERY";
private ExecutorService executor;
private CIMConnectorManager(Context ctx) {
private CIMConnectorManager(Context ctx) {
context = ctx;
executor = Executors.newCachedThreadPool();
connector = new NioSocketConnector();
connector.setConnectTimeoutMillis(10 * 1000);
connector.setConnectTimeoutMillis(CONNECT_TIMEOUT);
connector.getSessionConfig().setTcpNoDelay(true);
connector.getSessionConfig().setBothIdleTime(BOTH_IDLE_TIME);
connector.getSessionConfig().setReadBufferSize(2048);
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ClientMessageCodecFactory()));
connector.getSessionConfig().setKeepAlive(true);
connector.getSessionConfig().setReadBufferSize(READ_BUFFER_SIZE);
KeepAliveFilter keepAliveaHandler = new KeepAliveFilter(this, IdleStatus.BOTH_IDLE);
KeepAliveFilter keepAliveaHandler = new KeepAliveFilter(this);
keepAliveaHandler.setRequestInterval(READ_IDLE_TIME);
keepAliveaHandler.setRequestTimeoutHandler(KeepAliveRequestTimeoutHandler.NOOP);
keepAliveaHandler.setForwardEvent(true);
connector.getFilterChain().addLast("heartbeat", keepAliveaHandler);
connector.setHandler(this);
connector.getFilterChain().addLast("codec", new ProtocolCodecFilter(new ClientMessageCodecFactory()));
connector.getFilterChain().addLast("heartbeat", keepAliveaHandler);
connector.setHandler(this);
}
@ -110,118 +106,103 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFa
}
private synchronized void syncConnection(final String cimServerHost,final int cimServerPort) {
private synchronized void syncConnection(final String host,final int port) {
if(isConnected()){
return ;
}
try {
if(isConnected()){
return ;
}
Log.i(TAG, "****************CIM正在连接服务器 "+host+":"+port+"......");
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_CIM_CONNECTION_STATE, false);
InetSocketAddress remoteSocketAddress = new InetSocketAddress(cimServerHost, cimServerPort);
InetSocketAddress remoteSocketAddress = new InetSocketAddress(host, port);
connectFuture = connector.connect(remoteSocketAddress);
connectFuture.awaitUninterruptibly();
connectFuture.getSession();
} catch (Exception e) {
long interval = CIMConstant.RECONN_INTERVAL_TIME - (5*1000 - new Random().nextInt(15*1000));
Intent intent = new Intent();
intent.setAction(ACTION_CONNECTION_FAILED);
intent.putExtra("exception", e);
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED);
intent.putExtra(Exception.class.getName(), e);
intent.putExtra("interval", interval);
context.sendBroadcast(intent);
Log.e(TAG, "******************CIM连接服务器失败 "+cimServerHost+":"+cimServerPort);
}
Log.e(TAG, "****************CIM连接服务器失败 "+host+":"+port+"......将在"+interval/1000+"秒后重新尝试连接");
}
}
public void connect(final String cimServerHost, final int cimServerPort) {
public void connect(final String host, final int port) {
if (!netWorkAvailable(context)) {
if (!isNetworkConnected(context)) {
Intent intent = new Intent();
intent.setAction(ACTION_CONNECTION_FAILED);
intent.putExtra("exception", new NetWorkDisableException());
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED);
intent.putExtra(Exception.class.getName(), new NetworkDisconnectedException());
context.sendBroadcast(intent);
return;
}
Future<?> future = executor.submit(new Runnable() {
@Override
public void run() {
syncConnection(cimServerHost, cimServerPort);
}
});
try {
if(future.get()!=null)
executor.execute(new Runnable() {
public void run()
{
connect(cimServerHost,cimServerPort);
}
} catch (Exception e) {
connect(cimServerHost,cimServerPort);
e.printStackTrace();
}
syncConnection(host, port);
}
});
}
public void send(final SentBody body) {
public synchronized void send(SentBody body) {
executor.execute(new Runnable() {
@Override
public void run() {
IoSession session = getCurrentSession();
if(session!=null && session.isConnected())
{
WriteFuture wf = session.write(body);
// 消息发送超时 10秒
wf.awaitUninterruptibly(10, TimeUnit.SECONDS);
if (!wf.isWritten()) {
Intent intent = new Intent();
intent.setAction(ACTION_SENT_FAILED);
intent.putExtra("exception", new WriteToClosedSessionException());
intent.putExtra("sentBody", body);
context.sendBroadcast(intent);
}
}else
{
Intent intent = new Intent();
intent.setAction(ACTION_SENT_FAILED);
intent.putExtra("exception", new CIMSessionDisableException());
intent.putExtra("sentBody", body);
context.sendBroadcast(intent);
}
}
});
boolean isSuccessed = false;
Throwable exception = new SessionDisconnectedException();
IoSession session = getCurrentSession();
if(session!=null && session.isConnected())
{
WriteFuture wf = session.write(body);
// 消息发送超时 5秒
wf.awaitUninterruptibly(WRITE_TIMEOUT);
isSuccessed = wf.isWritten();
exception = wf.getException();
}
if(!isSuccessed){
Intent intent = new Intent();
intent.setAction(CIMConstant.IntentAction.ACTION_SENT_FAILED);
intent.putExtra(Exception.class.getName(),exception);
intent.putExtra(SentBody.class.getName(), body);
context.sendBroadcast(intent);
}
}
public void destroy() {
IoSession session = getCurrentSession();
if (session != null) {
session.closeNow();
session.removeAttribute("account");
}
if (connector != null && !connector.isDisposed()) {
connector.dispose();
}
CIMCacheToolkit.destroy();
manager = null;
}
public boolean isConnected() {
IoSession session = getCurrentSession();
if (session == null ) {
return false;
}
return session.isConnected() ;
return session != null ;
}
@ -237,50 +218,46 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFa
public IoSession getCurrentSession()
{
if(connector.getManagedSessionCount()>0)
Map<Long,IoSession> sessions = connector.getManagedSessions();
for(Long key:sessions.keySet())
{
for(Long key:connector.getManagedSessions().keySet())
{
return connector.getManagedSessions().get(key);
IoSession session = sessions.get(key);
if(session.isConnected()){
return session;
}
}
return null;
}
@Override
public void sessionCreated(IoSession session) throws Exception {
Log.i(TAG, "******************CIM连接服务器成功:"+session.getLocalAddress());
Log.i(TAG, "****************CIM连接服务器成功:"+session.getLocalAddress()+" NID:"+session.getId());
setLastHeartbeatTime(session);
Intent intent = new Intent();
intent.setAction(ACTION_CONNECTION_SUCCESSED);
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED);
context.sendBroadcast(intent);
}
@Override
public void sessionOpened(IoSession session) throws Exception {
session.getConfig().setBothIdleTime(180);
}
public void sessionClosed(IoSession session) {
@Override
public void sessionClosed(IoSession session) throws Exception {
Log.e(TAG, "******************CIM与服务器断开连接:"+session.getLocalAddress());
Log.e(TAG, "****************CIM与服务器断开连接:"+session.getLocalAddress()+" NID:"+session.getId());
Intent intent = new Intent();
intent.setAction(ACTION_CONNECTION_CLOSED);
intent.setAction(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED);
context.sendBroadcast(intent);
}
@Override
public void sessionIdle(IoSession session, IdleStatus status)throws Exception {
Log.d(TAG, "******************CIM与服务器连接空闲:"+session.getLocalAddress() + " isActive:" + session.isActive()+ " isConnected:" + session.isConnected());
public void sessionIdle(IoSession session, IdleStatus status) {
Log.d(TAG, "****************CIM "+status.toString().toUpperCase()+":"+session.getLocalAddress() +" NID:"+session.getId()+ " isConnected:" + session.isConnected());
/**
* 用于解决wifi情况下偶而路由器与服务器断开连接时客户端并没及时收到关闭事件
@ -291,52 +268,57 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFa
if(System.currentTimeMillis() - lastHeartbeatTime >= HEARBEAT_TIME_OUT)
{
session.closeNow();
Log.e(TAG, "****************CIM心跳超时 ,即将重新连接......"+" NID:"+session.getId());
}
}
@Override
public void exceptionCaught(IoSession session, Throwable cause)
throws Exception {
public void exceptionCaught(IoSession session, Throwable cause) {
Log.e(TAG, "****************CIM连接出现未知异常:"+session.getLocalAddress()+" NID:"+session.getId());
if(cause!=null && cause.getMessage()!=null){
Log.e(TAG, cause.getMessage());
}
Intent intent = new Intent();
intent.setAction(ACTION_UNCAUGHT_EXCEPTION);
intent.putExtra("exception", cause);
intent.setAction(CIMConstant.IntentAction.ACTION_UNCAUGHT_EXCEPTION);
intent.putExtra(Exception.class.getName(), cause);
context.sendBroadcast(intent);
}
@Override
public void messageReceived(IoSession session, Object obj)
throws Exception {
public void messageReceived(IoSession session, Object obj){
if (obj instanceof Message) {
Intent intent = new Intent();
intent.setAction(ACTION_MESSAGE_RECEIVED);
intent.putExtra("message", (Message) obj);
intent.setAction(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED);
intent.putExtra(Message.class.getName(), (Message) obj);
context.sendBroadcast(intent);
}
if (obj instanceof ReplyBody) {
Intent intent = new Intent();
intent.setAction(ACTION_REPLY_RECEIVED);
intent.putExtra("replyBody", (ReplyBody) obj);
intent.setAction(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED);
intent.putExtra(ReplyBody.class.getName(), (ReplyBody) obj);
context.sendBroadcast(intent);
}
}
@Override
public void messageSent(IoSession session, Object message) throws Exception {
public void messageSent(IoSession session, Object message) {
if(message instanceof SentBody)
{
Intent intent = new Intent();
intent.setAction(ACTION_SENT_SUCCESSED);
intent.putExtra("sentBody", (SentBody) message);
intent.setAction(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED);
intent.putExtra(SentBody.class.getName(), (SentBody) message);
context.sendBroadcast(intent);
}
}
private void setLastHeartbeatTime(IoSession session)
{
session.setAttribute(KEY_LAST_HEART_TIME, System.currentTimeMillis());
@ -345,14 +327,14 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFa
private long getLastHeartbeatTime(IoSession session)
{
long time = 0;
Object value ;
if((value = session.getAttribute(KEY_LAST_HEART_TIME)) !=null){
Object value = session.getAttribute(KEY_LAST_HEART_TIME);
if(value !=null){
time = Long.parseLong(value.toString());
}
return time;
}
public static boolean netWorkAvailable(Context context) {
public static boolean isNetworkConnected(Context context) {
try {
ConnectivityManager nw = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo networkInfo = nw.getActiveNetworkInfo();
@ -362,14 +344,15 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFa
return false;
}
@Override
public Object getRequest(IoSession arg0) {
return null;
}
@Override
public Object getResponse(IoSession arg0, Object arg1) {
return CIMConstant.CMD_HEARTBEAT_RESPONSE;
public Object getResponse(IoSession session, Object arg1) {
return HeartbeatResponse.getInstance();
}
@Override
@ -377,12 +360,11 @@ class CIMConnectorManager extends IoHandlerAdapter implements KeepAliveMessageFa
setLastHeartbeatTime(session);
return CIMConstant.CMD_HEARTBEAT_REQUEST.equalsIgnoreCase(data.toString());
return data instanceof HeartbeatRequest;
}
@Override
public boolean isResponse(IoSession arg0, Object arg1) {
return false;
}
}
}

View File

@ -1,14 +1,30 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.exception.CIMSessionDisableException;
import com.farsunset.cim.sdk.android.exception.SessionDisconnectedException;
import com.farsunset.cim.sdk.android.model.Message;
import com.farsunset.cim.sdk.android.model.ReplyBody;
import com.farsunset.cim.sdk.android.model.SentBody;
@ -18,28 +34,24 @@ import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Handler;
/**
* 消息入口所有消息都会经过这里
*/
public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver implements CIMEventListener {
public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver{
public Context context;
protected Context context;
@Override
public void onReceive(Context ctx, Intent it) {
public void onReceive(Context ctx, Intent intent) {
context = ctx;
/*
* 操作事件广播用于提高service存活率
*/
if(it.getAction().equals(Intent.ACTION_USER_PRESENT)
||it.getAction().equals(Intent.ACTION_POWER_CONNECTED)
||it.getAction().equals(Intent.ACTION_POWER_DISCONNECTED)
)
if(intent.getAction().equals(Intent.ACTION_USER_PRESENT)
||intent.getAction().equals(Intent.ACTION_POWER_CONNECTED)
||intent.getAction().equals(Intent.ACTION_POWER_DISCONNECTED))
{
startPushService();
}
@ -48,17 +60,16 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver impl
/*
* 设备网络状态变化事件
*/
if(it.getAction().equals(CIMConnectorManager.ACTION_NETWORK_CHANGED))
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_NETWORK_CHANGED))
{
ConnectivityManager connectivityManager = (ConnectivityManager)context.getSystemService(Context.CONNECTIVITY_SERVICE);
android.net.NetworkInfo info = connectivityManager.getActiveNetworkInfo();
onDevicesNetworkChanged(info);
onDevicesNetworkChanged(connectivityManager.getActiveNetworkInfo());
}
/*
* cim断开服务器事件
*/
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_CLOSED))
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_CLOSED))
{
onInnerConnectionClosed();
}
@ -66,15 +77,16 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver impl
/*
* cim连接服务器失败事件
*/
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_FAILED))
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_FAILED))
{
onInnerConnectionFailed((Exception) it.getSerializableExtra("exception"));
long interval = intent.getLongExtra("interval", CIMConstant.RECONN_INTERVAL_TIME);
onConnectionFailed((Exception) intent.getSerializableExtra(Exception.class.getName()),interval);
}
/*
* cim连接服务器成功事件
*/
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_SUCCESSED))
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_SUCCESSED))
{
onInnerConnectionSuccessed();
}
@ -82,94 +94,84 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver impl
/*
* 收到推送消息事件
*/
if(it.getAction().equals(CIMConnectorManager.ACTION_MESSAGE_RECEIVED))
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_MESSAGE_RECEIVED))
{
onInnerMessageReceived((Message)it.getSerializableExtra("message"));
onInnerMessageReceived((Message)intent.getSerializableExtra(Message.class.getName()),intent);
}
/*
* 获取收到replybody成功事件
*/
if(it.getAction().equals(CIMConnectorManager.ACTION_REPLY_RECEIVED))
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_REPLY_RECEIVED))
{
onReplyReceived((ReplyBody)it.getSerializableExtra("replyBody"));
onReplyReceived((ReplyBody)intent.getSerializableExtra(ReplyBody.class.getName()));
}
/*
* 获取sendbody发送失败事件
*/
if(it.getAction().equals(CIMConnectorManager.ACTION_SENT_FAILED))
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_FAILED))
{
onSentFailed((Exception) it.getSerializableExtra("exception"),(SentBody)it.getSerializableExtra("sentBody"));
Exception exception = (Exception) intent.getSerializableExtra(Exception.class.getName());
SentBody sentBody = (SentBody)intent.getSerializableExtra(SentBody.class.getName());
onSentFailed(exception,sentBody);
}
/*
* 获取sendbody发送成功事件
*/
if(it.getAction().equals(CIMConnectorManager.ACTION_SENT_SUCCESSED))
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_SENT_SUCCESSED))
{
onSentSucceed((SentBody)it.getSerializableExtra("sentBody"));
onSentSucceed((SentBody)intent.getSerializableExtra(SentBody.class.getName()));
}
/*
* 获取cim数据传输异常事件
*/
if(it.getAction().equals(CIMConnectorManager.ACTION_UNCAUGHT_EXCEPTION))
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_UNCAUGHT_EXCEPTION))
{
onUncaughtException((Exception)it.getSerializableExtra("exception"));
onUncaughtException((Exception)intent.getSerializableExtra(Exception.class.getName()));
}
/*
* 重新连接如果断开的话
*/
if(it.getAction().equals(CIMConnectorManager.ACTION_CONNECTION_RECOVERY))
if(intent.getAction().equals(CIMConstant.IntentAction.ACTION_CONNECTION_RECOVERY))
{
CIMPushManager.connect(context);
CIMPushManager.connect(context,0);
}
}
private void startPushService()
{
private void startPushService(){
Intent intent = new Intent(context, CIMPushService.class);
intent.setAction(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE);
context.startService(intent);
}
private void onInnerConnectionClosed(){
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_CIM_CONNECTION_STATE, false);
if(CIMConnectorManager.netWorkAvailable(context))
if(CIMConnectorManager.isNetworkConnected(context))
{
CIMPushManager.connect(context);
CIMPushManager.connect(context,0);
}
onConnectionClosed();
}
Handler connectionHandler = new Handler(){
@Override
public void handleMessage(android.os.Message message){
CIMPushManager.connect(context);
}
};
private void onInnerConnectionFailed(Exception e){
private void onConnectionFailed(Exception e,long reinterval){
if(CIMConnectorManager.netWorkAvailable(context))
if(CIMConnectorManager.isNetworkConnected(context))
{
connectionHandler.sendEmptyMessageDelayed(0, CIMConstant.RECONN_INTERVAL_TIME);
onConnectionFailed();
CIMPushManager.connect(context,reinterval);
}
onConnectionFailed(e);
}
private void onInnerConnectionSuccessed(){
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_CIM_CONNECTION_STATE, true);
@ -179,34 +181,36 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver impl
private void onUncaughtException(Throwable arg0) {}
private void onDevicesNetworkChanged(NetworkInfo info) {
if(info !=null)
{
CIMPushManager.connect(context);
CIMPushManager.connect(context,0);
}
onNetworkChanged(info);
}
private void onInnerMessageReceived(com.farsunset.cim.sdk.android.model.Message message)
{
if(CIMConstant.MessageType.TYPE_999.equals(message.getType()))
private void onInnerMessageReceived(com.farsunset.cim.sdk.android.model.Message message, Intent intent){
if(isForceOfflineMessage(message.getAction()))
{
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_MANUAL_STOP,true);
CIMPushManager.stop(context);
}
onMessageReceived(message);
onMessageReceived(message,intent);
}
private void onSentFailed(Exception e, SentBody body){
private boolean isForceOfflineMessage(String action)
{
return CIMConstant.MessageAction.ACTION_999.equals(action) || CIMConstant.MessageAction.ACTION_444.equals(action);
}
private void onSentFailed(Exception e, SentBody body){
//与服务端端开链接重新连接
if(e instanceof CIMSessionDisableException)
if(e instanceof SessionDisconnectedException)
{
CIMPushManager.connect(context);
CIMPushManager.connect(context,0);
}else
{
//发送失败 重新发送
@ -215,13 +219,32 @@ public abstract class CIMEventBroadcastReceiver extends BroadcastReceiver impl
}
private void onSentSucceed(SentBody body){}
@Override
public abstract void onMessageReceived(Message message);
@Override
public abstract void onReplyReceived(ReplyBody body);
public abstract void onNetworkChanged(NetworkInfo info);
public abstract void onConnectionFailed(Exception e);
public abstract void onMessageReceived(com.farsunset.cim.sdk.android.model.Message message,Intent intent);
public void onNetworkChanged(NetworkInfo info) {
CIMListenerManager.notifyOnNetworkChanged(info);
}
public void onConnectionSuccessed(boolean hasAutoBind) {
CIMListenerManager.notifyOnConnectionSuccessed(hasAutoBind);
}
public void onConnectionClosed() {
CIMListenerManager.notifyOnConnectionClosed();
}
public void onConnectionFailed() {
CIMListenerManager.notifyOnConnectionFailed();
}
public void onReplyReceived(ReplyBody body) {
CIMListenerManager.notifyOnReplyReceived(body);
}
public void onSentSucceed(SentBody body){
CIMListenerManager.notifyOnSentSucceed(body);
}
}

View File

@ -1,15 +1,31 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android;
import android.net.NetworkInfo;
import com.farsunset.cim.sdk.android.model.Message;
import com.farsunset.cim.sdk.android.model.ReplyBody;
import com.farsunset.cim.sdk.android.model.SentBody;
/**
*CIM 主要事件接口
@ -22,36 +38,49 @@ public interface CIMEventListener
* 当收到服务端推送过来的消息时调用
* @param message
*/
public abstract void onMessageReceived(Message message);
void onMessageReceived(Message message);
/**
* 当调用CIMPushManager.sendRequest()向服务端发送请求获得相应时调用
* @param replybody
*/
public abstract void onReplyReceived(ReplyBody replybody);
void onReplyReceived(ReplyBody replybody);
/**
* 当调用CIMPushManager.sendRequest()向服务端发送请求成功时
* @param body
*/
void onSentSuccessed(SentBody body);
/**
* 当手机网络发生变化时调用
* @param networkinfo
*/
public abstract void onNetworkChanged(NetworkInfo networkinfo);
void onNetworkChanged(NetworkInfo networkinfo);
/**
* 当连接服务器成功时回调
* @param hasAutoBind : true 已经自动绑定账号到服务器了不需要再手动调用bindAccount
*/
public abstract void onConnectionSuccessed(boolean hasAutoBind);
void onConnectionSuccessed(boolean hasAutoBind);
/**
* 当断开服务器连接的时候回调
*/
public abstract void onConnectionClosed();
/**
* 当服务器连接失败的时候回调
*
*/
public abstract void onConnectionFailed(Exception e);
void onConnectionClosed();
/**
* 当连接服务器失败的时候回调
*
*/
void onConnectionFailed();
/**
* 监听器在容器里面的排序值越大则越先接收
*/
int getEventDispatchOrder();
}

View File

@ -1,22 +1,33 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.model.Message;
import com.farsunset.cim.sdk.android.model.ReplyBody;
import com.farsunset.cim.sdk.android.model.SentBody;
import android.app.Activity;
import android.content.Context;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.net.NetworkInfo;
import android.util.Log;
@ -27,15 +38,13 @@ import android.util.Log;
public class CIMListenerManager {
private static ArrayList<CIMEventListener> cimListeners = new ArrayList<CIMEventListener>();
private static CIMMessageReceiveComparator comparator = new CIMMessageReceiveComparator();
public static void registerMessageListener(CIMEventListener listener,Context mcontext) {
public static void registerMessageListener(CIMEventListener listener) {
if (!cimListeners.contains(listener)) {
cimListeners.add(listener);
// 按照接收顺序倒序
Collections.sort(cimListeners, new CIMMessageReceiveComparator(mcontext));
Collections.sort(cimListeners,comparator);
}
}
@ -73,6 +82,12 @@ public class CIMListenerManager {
}
}
public static void notifyOnConnectionFailed() {
for (CIMEventListener listener : cimListeners) {
listener.onConnectionFailed();
}
}
public static void notifyOnReplyReceived(ReplyBody body) {
for (CIMEventListener listener : cimListeners) {
@ -80,11 +95,12 @@ public class CIMListenerManager {
}
}
public static void notifyOnConnectionFailed(Exception e) {
public static void notifyOnSentSucceed(SentBody body) {
for (CIMEventListener listener : cimListeners) {
listener.onConnectionFailed(e);
listener.onSentSuccessed(body);
}
}
public static void destory() {
cimListeners.clear();
@ -99,47 +115,17 @@ public class CIMListenerManager {
/**
* 消息接收activity的接收顺序排序CIM_RECEIVE_ORDER倒序
*/
static class CIMMessageReceiveComparator implements Comparator<CIMEventListener>{
private static class CIMMessageReceiveComparator implements Comparator<CIMEventListener>{
Context mcontext;
public CIMMessageReceiveComparator(Context ctx)
{
mcontext = ctx;
}
@Override
public int compare(CIMEventListener arg1, CIMEventListener arg2) {
Integer order1 = CIMConstant.CIM_DEFAULT_MESSAGE_ORDER;
Integer order2 = CIMConstant.CIM_DEFAULT_MESSAGE_ORDER;
ActivityInfo info;
if (arg1 instanceof Activity ) {
try {
info = mcontext.getPackageManager() .getActivityInfo(((Activity)(arg1)).getComponentName(), PackageManager.GET_META_DATA);
if(info.metaData!=null)
{
order1 = info.metaData.getInt("CIM_RECEIVE_ORDER");
}
} catch (Exception e) {}
}
if (arg1 instanceof Activity ) {
try {
info = mcontext.getPackageManager() .getActivityInfo(((Activity)(arg2)).getComponentName(), PackageManager.GET_META_DATA);
if(info.metaData!=null)
{
order2 = info.metaData.getInt("CIM_RECEIVE_ORDER");
}
} catch (Exception e) {}
}
return order2.compareTo(order1);
int order1 = arg1.getEventDispatchOrder();
int order2 = arg2.getEventDispatchOrder();
return order2 - order1 ;
}
}
}
}

View File

@ -1,9 +1,24 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android;
import java.util.UUID;
@ -33,27 +48,20 @@ public class CIMPushManager {
static String KEY_SEND_BODY ="KEY_SEND_BODY";
static String KEY_CIM_CONNECTION_STATUS ="KEY_CIM_CONNECTION_STATUS";
//被销毁的destroy()
public static final int STATE_DESTROYED = 0x0000DE;
//被销停止的 stop()
public static final int STATE_STOPED = 0x0000EE;
public static final int STATE_NORMAL = 0x000000;
/**
* 初始化,连接服务端在程序启动页或者 在Application里调用
* @param context
* @param ip
* @param port
*/
public static void connect(Context context,String host,int port){
public static void connect(Context context,String host,int port){
connect(context,host,port,false);
connect(context,host,port,false,0);
}
}
private static void connect(Context context,String ip,int port,boolean autoBind){
private static void connect(Context context,String ip,int port,boolean autoBind,long delayedTime){
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED, false);
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_MANUAL_STOP, false);
@ -69,12 +77,13 @@ private static void connect(Context context,String ip,int port,boolean autoBind
Intent serviceIntent = new Intent(context, CIMPushService.class);
serviceIntent.putExtra(CIMCacheToolkit.KEY_CIM_SERVIER_HOST, ip);
serviceIntent.putExtra(CIMCacheToolkit.KEY_CIM_SERVIER_PORT, port);
serviceIntent.putExtra(CIMPushService.KEY_DELAYED_TIME, delayedTime);
serviceIntent.setAction(ACTION_CREATE_CIM_CONNECTION);
context.startService(serviceIntent);
}
}
protected static void connect(Context context){
protected static void connect(Context context,long delayedTime){
boolean isManualStop = CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_MANUAL_STOP);
boolean isManualDestory = CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED);
@ -87,9 +96,9 @@ private static void connect(Context context,String ip,int port,boolean autoBind
String host = CIMCacheToolkit.getInstance(context).getString( CIMCacheToolkit.KEY_CIM_SERVIER_HOST);
int port =CIMCacheToolkit.getInstance(context).getInt( CIMCacheToolkit.KEY_CIM_SERVIER_PORT);
connect(context,host,port,true);
connect(context,host,port,true,delayedTime);
}
}
/**
@ -104,6 +113,7 @@ private static void connect(Context context,String ip,int port,boolean autoBind
{
return ;
}
sendBindRequest(context,account);
}
@ -132,8 +142,7 @@ private static void connect(Context context,String ip,int port,boolean autoBind
String account = CIMCacheToolkit.getInstance(context).getString(CIMCacheToolkit.KEY_ACCOUNT);
boolean isManualDestory = CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED);
boolean isManualStoped = CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_MANUAL_STOP);
if( isManualStoped || account==null || account.trim().length()==0 || isManualDestory )
if( account==null || account.trim().length()==0 || isManualDestory )
{
return false;
}
@ -195,7 +204,7 @@ private static void connect(Context context,String ip,int port,boolean autoBind
CIMCacheToolkit.getInstance(context).putBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED, true);
CIMCacheToolkit.getInstance(context).remove(CIMCacheToolkit.KEY_ACCOUNT);
CIMCacheToolkit.getInstance(context).putString(CIMCacheToolkit.KEY_ACCOUNT, null);
Intent serviceIntent = new Intent(context, CIMPushService.class);
serviceIntent.setAction(ACTION_DESTORY);
@ -205,9 +214,8 @@ private static void connect(Context context,String ip,int port,boolean autoBind
/**
* 重新恢复接收推送重新连接服务端并登录当前账号如果aotuBind == true
* 重新恢复接收推送重新连接服务端并登录当前账号
* @param context
* @param aotuBind
*/
public static void resume(Context context){
@ -223,19 +231,7 @@ private static void connect(Context context,String ip,int port,boolean autoBind
return CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_CIM_CONNECTION_STATE);
}
public static int getState(Context context){
boolean isManualDestory = CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_CIM_DESTROYED);
if(isManualDestory){
return STATE_DESTROYED;
}
boolean isManualStop = CIMCacheToolkit.getInstance(context).getBoolean(CIMCacheToolkit.KEY_MANUAL_STOP);
if(isManualStop){
return STATE_STOPED;
}
return STATE_NORMAL;
}
private static String getVersionName(Context context) {
String versionName = null;
@ -246,5 +242,5 @@ private static void connect(Context context,String ip,int port,boolean autoBind
}
return versionName;
}
}
}

View File

@ -1,54 +1,88 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android;
import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.os.Message;
import android.util.Log;
import com.farsunset.cim.sdk.android.model.SentBody;
/**
* 与服务端连接服务
* @author 3979434
*
*/
public class CIMPushService extends Service {
final static String TAG = CIMPushService.class.getSimpleName();
protected final static int DEF_CIM_PORT = 28888;
CIMConnectorManager manager;
WakeLock wakeLock;
private final String TAG = CIMPushService.class.getSimpleName();
public final static String KEY_DELAYED_TIME ="KEY_DELAYED_TIME";
private CIMConnectorManager manager;
@Override
public void onCreate()
{
manager = CIMConnectorManager.getManager(this.getApplicationContext());
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, CIMPushService.class.getName());
}
Handler connectionHandler = new Handler(){
@Override
public void handleMessage(android.os.Message message){
connectionHandler.removeMessages(0);
String host = message.getData().getString(CIMCacheToolkit.KEY_CIM_SERVIER_HOST);
int port = message.getData().getInt(CIMCacheToolkit.KEY_CIM_SERVIER_PORT,0);
manager.connect(host, port);
}
};
@Override
public int onStartCommand(Intent intent,int flags, int startId) {
if(intent==null)
{
return START_STICKY;
}
intent = (intent == null ? new Intent(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE) : intent);
String action = intent.getAction();
if(CIMPushManager.ACTION_CREATE_CIM_CONNECTION.equals(action))
{
String host = CIMCacheToolkit.getInstance(this).getString(CIMCacheToolkit.KEY_CIM_SERVIER_HOST);
int port =CIMCacheToolkit.getInstance(this).getInt(CIMCacheToolkit.KEY_CIM_SERVIER_PORT);
manager.connect(host,port);
long delayMillis = intent.getLongExtra(KEY_DELAYED_TIME,0);
if( delayMillis > 0){
Message msg = connectionHandler.obtainMessage();
msg.what = 0;
msg.setData(intent.getExtras());
connectionHandler.sendMessageDelayed(msg, delayMillis);
}else
{
String host = intent.getStringExtra(CIMCacheToolkit.KEY_CIM_SERVIER_HOST);
int port = intent.getIntExtra(CIMCacheToolkit.KEY_CIM_SERVIER_PORT,0);
manager.connect(host,port);
}
}
if(CIMPushManager.ACTION_SEND_REQUEST_BODY.equals(action))
@ -65,7 +99,6 @@ import com.farsunset.cim.sdk.android.model.SentBody;
{
manager.destroy();
this.stopSelf();
android.os.Process.killProcess(android.os.Process.myPid());
}
if(CIMPushManager.ACTION_ACTIVATE_PUSH_SERVICE.equals(action) )
@ -73,42 +106,23 @@ import com.farsunset.cim.sdk.android.model.SentBody;
if(!manager.isConnected()){
boolean isManualStop = CIMCacheToolkit.getInstance(this).getBoolean(CIMCacheToolkit.KEY_MANUAL_STOP);
Log.i(TAG, "CIM.isConnected() == false, isManualStop == " + isManualStop);
CIMPushManager.connect(this);
Log.w(TAG, "manager.isConnected() == false, isManualStop == " + isManualStop);
CIMPushManager.connect(this,0);
}else
{
Log.i(TAG, "CIM.isConnected() == true");
Log.i(TAG, "manager.isConnected() == true");
}
}
try{
if(!wakeLock.isHeld())
{
this.wakeLock.acquire();
}
}catch(Exception e){}
return START_STICKY;
}
public void onDestroy()
{
super.onDestroy();
if(wakeLock.isHeld())
{
this.wakeLock.release();
wakeLock = null;
}
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
}

View File

@ -1,9 +1,24 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.constant;
/**
@ -11,57 +26,90 @@ package com.farsunset.cim.sdk.android.constant;
*/
public interface CIMConstant {
long RECONN_INTERVAL_TIME= 30 * 1000;
public static String UTF8="UTF-8";
public static byte MESSAGE_SEPARATE='\b';
public static long RECONN_INTERVAL_TIME= 30 * 1000;
public static int CIM_DEFAULT_MESSAGE_ORDER=1;
public static class ReturnCode{
//消息头长度为3个字节第一个字节为消息类型第二第三字节 转换int后为消息长度
int DATA_HEADER_LENGTH = 3;
public static interface ReturnCode{
public static String CODE_404 ="404";
String CODE_404 ="404";
public static String CODE_403 ="403";
String CODE_403 ="403";
public static String CODE_405 ="405";
String CODE_405 ="405";
public static String CODE_200 ="200";
String CODE_200 ="200";
public static String CODE_206 ="206";
String CODE_206 ="206";
public static String CODE_500 ="500";
String CODE_500 ="500";
}
/**
* 服务端心跳请求命令 cmd_server_hb_request
*/
public static final String CMD_HEARTBEAT_REQUEST="S_H_RQ";
/**
* 客户端心跳响应命令 cmd_client_hb_response
*/
public static final String CMD_HEARTBEAT_RESPONSE ="C_H_RS";
public static class RequestKey{
public static interface ProtobufType{
byte C_H_RS = 0;
byte S_H_RQ = 1;
byte MESSAGE = 2;
byte SENTBODY = 3;
byte REPLYBODY = 4;
}
public static interface RequestKey{
public static String CLIENT_BIND ="client_bind";
String CLIENT_BIND ="client_bind";
public static String CLIENT_OFFLINE_MESSAGE ="client_get_offline_message";
String CLIENT_LOGOUT ="client_logout";
@Deprecated
String CLIENT_PULL_MESSAGE ="client_pull_message";
}
public static class MessageType{
public static interface MessageAction{
//用户会 踢出下线消息类型
public static String TYPE_999 ="999";
}
//被其他设备登录挤下线消息
String ACTION_999 ="999";
//被系统禁用消息
String ACTION_444 ="444";
}
}
public static interface IntentAction{
// 消息广播action
String ACTION_MESSAGE_RECEIVED = "com.farsunset.cim.MESSAGE_RECEIVED";
// 发送sendbody失败广播
String ACTION_SENT_FAILED = "com.farsunset.cim.SENT_FAILED";
// 发送sendbody成功广播
String ACTION_SENT_SUCCESSED = "com.farsunset.cim.SENT_SUCCESSED";
// 链接意外关闭广播
String ACTION_CONNECTION_CLOSED = "com.farsunset.cim.CONNECTION_CLOSED";
// 链接失败广播
String ACTION_CONNECTION_FAILED = "com.farsunset.cim.CONNECTION_FAILED";
// 链接成功广播
String ACTION_CONNECTION_SUCCESSED = "com.farsunset.cim.CONNECTION_SUCCESSED";
// 发送sendbody成功后获得replaybody回应广播
String ACTION_REPLY_RECEIVED = "com.farsunset.cim.REPLY_RECEIVED";
// 网络变化广播
String ACTION_NETWORK_CHANGED = "android.net.conn.CONNECTIVITY_CHANGE";
// 未知异常
String ACTION_UNCAUGHT_EXCEPTION = "com.farsunset.cim.UNCAUGHT_EXCEPTION";
//重试连接
String ACTION_CONNECTION_RECOVERY = "com.farsunset.cim.CONNECTION_RECOVERY";
}
}

View File

@ -1,21 +0,0 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
package com.farsunset.cim.sdk.android.exception;
public class CIMSessionDisableException extends Exception {
private static final long serialVersionUID = 1L;
public CIMSessionDisableException() {
super();
}
public CIMSessionDisableException(String s) {
super(s);
}
}

View File

@ -1,21 +0,0 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
package com.farsunset.cim.sdk.android.exception;
public class NetWorkDisableException extends Exception {
private static final long serialVersionUID = 1L;
public NetWorkDisableException() {
super();
}
public NetWorkDisableException(String s) {
super(s);
}
}

View File

@ -0,0 +1,36 @@
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.exception;
public class NetworkDisconnectedException extends Exception {
private static final long serialVersionUID = 1L;
public NetworkDisconnectedException() {
super();
}
public NetworkDisconnectedException(String s) {
super(s);
}
}

View File

@ -0,0 +1,36 @@
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.exception;
public class SessionDisconnectedException extends Exception {
private static final long serialVersionUID = 1L;
public SessionDisconnectedException() {
super();
}
public SessionDisconnectedException(String s) {
super(s);
}
}

View File

@ -1,23 +0,0 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
package com.farsunset.cim.sdk.android.exception;
import java.io.Serializable;
public class WriteToClosedSessionException extends Exception implements Serializable {
private static final long serialVersionUID = 1L;
public WriteToClosedSessionException() {
super();
}
public WriteToClosedSessionException(String s) {
super(s);
}
}

View File

@ -1,9 +1,24 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.filter;
import org.apache.mina.core.session.IoSession;
@ -12,33 +27,28 @@ import org.apache.mina.filter.codec.ProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolEncoder;
/**
* android客户端端消息 编码解码器 可以在
* 关于消息加密与加密 可在 encoder时进行消息加密在ServerMessageCodecFactory的 decoder时对消息解密
* android客户端端消息 编码解码器
*/
public class ClientMessageCodecFactory implements ProtocolCodecFactory {
/**
* 消息编码器
*/
private final ClientMessageEncoder encoder;
/**
* 消息解码器
*/
private final ClientMessageDecoder decoder;
/**
* Constructor.
*/
public ClientMessageCodecFactory() {
encoder = new ClientMessageEncoder();
decoder = new ClientMessageDecoder();
}
/**
* Returns a new (or reusable) instance of ProtocolEncoder.
*/
public ProtocolEncoder getEncoder(IoSession session) throws Exception {
return encoder;
}
/**
* Returns a new (or reusable) instance of ProtocolDecoder.
*/
public ProtocolDecoder getDecoder(IoSession session) throws Exception {
return decoder;
}

View File

@ -1,29 +1,40 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.filter;
import java.io.ByteArrayInputStream;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.CumulativeProtocolDecoder;
import org.apache.mina.filter.codec.ProtocolDecoderOutput;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import android.util.Log;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.model.HeartbeatRequest;
import com.farsunset.cim.sdk.android.model.Message;
import com.farsunset.cim.sdk.android.model.ReplyBody;
import com.farsunset.cim.sdk.android.model.proto.MessageProto;
import com.farsunset.cim.sdk.android.model.proto.ReplyBodyProto;
import com.google.protobuf.InvalidProtocolBufferException;
/**
* 客户端消息解码
*/
@ -33,141 +44,100 @@ public class ClientMessageDecoder extends CumulativeProtocolDecoder {
@Override
public boolean doDecode(IoSession iosession, IoBuffer iobuffer,ProtocolDecoderOutput out) throws Exception {
boolean complete = false;
IoBuffer tBuffer = IoBuffer.allocate(320).setAutoExpand(true);
iobuffer.mark();
while (iobuffer.hasRemaining()) {
byte b = iobuffer.get();
/**
* CIMConstant.MESSAGE_SEPARATE 为消息界限
* 当一次收到多个消息时以此分隔解析多个消息
*/
if (b == CIMConstant.MESSAGE_SEPARATE) {
public boolean doDecode(IoSession iosession, IoBuffer iobuffer,
ProtocolDecoderOutput out) throws Exception {
complete = true;
break;
} else {
tBuffer.put(b);
}
}
if (complete) {
tBuffer.flip();
byte[] bytes = new byte[tBuffer.limit()];
tBuffer.get(bytes);
String message = new String(bytes, CIMConstant.UTF8);
tBuffer.clear();
try
{
Object msg = mappingMessageObject(message);
out.write(msg);
}catch(Exception e)
{
e.printStackTrace();
}
}else
{
iobuffer.reset();//如果消息没有接收完整对buffer进行重置下次继续读取
}
return complete;
}
private Object mappingMessageObject(String message) throws Exception {
Log.i(TAG,message.toString());
if(CIMConstant.CMD_HEARTBEAT_REQUEST.equalsIgnoreCase(message))
{
return message;
}
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document doc = (Document) builder.parse(new ByteArrayInputStream(message.getBytes(CIMConstant.UTF8)));
/**
* 消息头3位
*/
if(iobuffer.remaining() < CIMConstant.DATA_HEADER_LENGTH){
return false;
}
iobuffer.mark();
byte conetnType = iobuffer.get();
byte lv =iobuffer.get();//int 低位
byte hv =iobuffer.get();//int 高位
int conetnLength = getContentLength(lv,hv);
//如果消息体没有接收完整则重置读取等待下一次重新读取
if(conetnLength > iobuffer.remaining()){
iobuffer.reset();
return false;
}
byte[] dataBytes = new byte[conetnLength];
iobuffer.get(dataBytes, 0, conetnLength);
String name = doc.getDocumentElement().getTagName();
if (name.equals("reply")) {
ReplyBody reply = new ReplyBody();
reply.setKey(doc.getElementsByTagName("key").item(0).getTextContent());
reply.setCode(doc.getElementsByTagName("code").item(0).getTextContent());
NodeList items = doc.getElementsByTagName("data").item(0).getChildNodes();
for (int i = 0; i < items.getLength(); i++) {
Node node = items.item(i);
reply.put(node.getNodeName(), node.getTextContent());
}
return reply;
}
if (name.equals("message")) {
Message body = new Message();
NodeList nodeList = doc.getElementsByTagName("message").item(0).getChildNodes();
int count = nodeList.getLength();
for(int i = 0;i < count; i++){
Node node = nodeList.item(i);
if(node.getNodeName().equals("mid"))
{
body.setMid(node.getTextContent());
}
if(node.getNodeName().equals("type"))
{
body.setType(node.getTextContent());
}
if(node.getNodeName().equals("content"))
{
body.setContent(node.getTextContent());
}
if(node.getNodeName().equals("file"))
{
body.setFile(node.getTextContent());
}
if(node.getNodeName().equals("fileType"))
{
body.setFileType(node.getTextContent());
}
if(node.getNodeName().equals("title"))
{
body.setTitle(node.getTextContent());
}
if(node.getNodeName().equals("sender"))
{
body.setSender(node.getTextContent());
}
if(node.getNodeName().equals("receiver"))
{
body.setReceiver(node.getTextContent());
}
if(node.getNodeName().equals("format"))
{
body.setFormat(node.getTextContent());
}
if(node.getNodeName().equals("timestamp"))
{
body.setTimestamp(Long.valueOf(node.getTextContent()));
}
}
return body;
}
return null;
Object message = mappingMessageObject(dataBytes,conetnType);
if(message!=null){
out.write(message);
}
return true;
}
private Object mappingMessageObject(byte[] bytes,byte type) throws InvalidProtocolBufferException {
if(CIMConstant.ProtobufType.S_H_RQ == type)
{
HeartbeatRequest request = HeartbeatRequest.getInstance();
Log.i(TAG,request.toString());
return request;
}
if(CIMConstant.ProtobufType.REPLYBODY == type)
{
ReplyBodyProto.Model bodyProto = ReplyBodyProto.Model.parseFrom(bytes);
ReplyBody body = new ReplyBody();
body.setKey(bodyProto.getKey());
body.setTimestamp(bodyProto.getTimestamp());
body.putAll(bodyProto.getDataMap());
body.setCode(bodyProto.getCode());
body.setMessage(bodyProto.getMessage());
Log.i(TAG,body.toString());
return body;
}
if(CIMConstant.ProtobufType.MESSAGE == type)
{
MessageProto.Model bodyProto = MessageProto.Model.parseFrom(bytes);
Message message = new Message();
message.setMid(bodyProto.getMid());
message.setAction(bodyProto.getAction());
message.setContent(bodyProto.getContent());
message.setSender(bodyProto.getSender());
message.setReceiver(bodyProto.getReceiver());
message.setTitle(bodyProto.getTitle());
message.setExtra(bodyProto.getExtra());
message.setTimestamp(bodyProto.getTimestamp());
message.setFormat(bodyProto.getFormat());
Log.i(TAG,message.toString());
return message;
}
return null;
}
/**
* 解析消息体长度
* @param type
* @param length
* @return
*/
private int getContentLength(byte lv,byte hv){
int l = (lv & 0xff);
int h = (hv & 0xff);
return (l| (h <<= 8));
}
}

View File

@ -1,40 +1,73 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.filter;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.session.IoSession;
import org.apache.mina.filter.codec.ProtocolEncoderAdapter;
import org.apache.mina.filter.codec.ProtocolEncoderOutput;
import android.util.Log;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.model.Protobufable;
/**
* 客户端消息发送前进行编码,可在此加密消息
* 客户端消息发送前进行编码
*/
public class ClientMessageEncoder extends ProtocolEncoderAdapter {
final static String TAG = ClientMessageEncoder.class.getSimpleName();
@Override
public void encode(IoSession iosession, Object message, ProtocolEncoderOutput out) throws Exception {
public void encode(IoSession iosession, Object object, ProtocolEncoderOutput out) throws Exception {
IoBuffer buff = IoBuffer.allocate(320).setAutoExpand(true);
buff.put(message.toString().getBytes(CIMConstant.UTF8));
buff.put(CIMConstant.MESSAGE_SEPARATE);
buff.flip();
out.write(buff);
//打印出收到的消息
Log.i(TAG,message.toString());
if(object instanceof Protobufable){
Protobufable data = (Protobufable) object;
byte[] byteArray = data.getByteArray();
IoBuffer buff = IoBuffer.allocate(byteArray.length + CIMConstant.DATA_HEADER_LENGTH).setAutoExpand(true);
buff.put(createHeader(data.getType(),byteArray.length));
buff.put(byteArray);
buff.flip();
out.write(buff);
//打印出收到的消息
Log.i(TAG,data.toString());
}
}
/**
* 消息体最大为65535
* @param type
* @param length
* @return
*/
private byte[] createHeader(byte type,int length){
byte[] header = new byte[CIMConstant.DATA_HEADER_LENGTH];
header[0] = type;
header[1] = (byte) (length & 0xff);
header[2] = (byte) ((length >> 8) & 0xff);
return header;
}
}

View File

@ -0,0 +1,62 @@
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.model;
import java.io.Serializable;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
/**
* 服务端心跳请求
*
*/
public class HeartbeatRequest implements Serializable,Protobufable {
private static final long serialVersionUID = 1L;
private static final String TAG = "SERVER_HEARTBEAT_REQUEST";
private static final String CMD_HEARTBEAT_RESPONSE = "SR";
private static HeartbeatRequest object = new HeartbeatRequest();
private HeartbeatRequest(){
}
public static HeartbeatRequest getInstance() {
return object;
}
@Override
public byte[] getByteArray() {
return CMD_HEARTBEAT_RESPONSE.getBytes();
}
public String toString(){
return TAG;
}
@Override
public byte getType() {
return CIMConstant.ProtobufType.S_H_RQ;
}
}

View File

@ -0,0 +1,59 @@
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.model;
import java.io.Serializable;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
/**
* 客户端心跳响应
*/
public class HeartbeatResponse implements Serializable,Protobufable {
private static final long serialVersionUID = 1L;
private static final String TAG = "CLIENT_HEARTBEAT_RESPONSE";
private static final String CMD_HEARTBEAT_RESPONSE = "CR";
private static HeartbeatResponse object = new HeartbeatResponse();
private HeartbeatResponse(){
}
public static HeartbeatResponse getInstance() {
return object;
}
@Override
public byte[] getByteArray() {
return CMD_HEARTBEAT_RESPONSE.getBytes();
}
public String toString(){
return TAG;
}
@Override
public byte getType() {
return CIMConstant.ProtobufType.C_H_RS;
}
}

View File

@ -1,12 +1,28 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.model;
import java.io.Serializable;
/**
* 消息对象
*/
@ -24,13 +40,13 @@ public class Message implements Serializable {
/**
* 消息类型用户自定义消息类别
*/
private String type;
private String action;
/**
* 消息标题
*/
private String title;
/**
* 消息类容type 组合为任何类型消息content 根据 format 可表示为 text,json ,xml数据格式
* 消息类容action 组合为任何类型消息content 根据 format 可表示为 text,json ,xml数据格式
*/
private String content;
@ -43,21 +59,18 @@ public class Message implements Serializable {
*/
private String receiver;
/**
* 文件 url
*/
private String file;
/**
* 文件类型
*/
private String fileType;
/**
* content 内容格式
*/
private String format = "txt";
private String format;
/**
* 附加内容 内容
*/
private String extra;
private long timestamp;
@ -73,14 +86,14 @@ public class Message implements Serializable {
this.timestamp = timestamp;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
public String getAction() {
return action;
}
public void setAction(String action) {
this.action = action;
}
public String getTitle() {
return title;
}
@ -113,22 +126,7 @@ public class Message implements Serializable {
this.receiver = receiver;
}
public String getFile() {
return file;
}
public void setFile(String file) {
this.file = file;
}
public String getFileType() {
return fileType;
}
public void setFileType(String fileType) {
this.fileType = fileType;
}
public String getFormat() {
return format;
}
@ -137,56 +135,30 @@ public class Message implements Serializable {
this.format = format;
}
public String getExtra() {
return extra;
}
public void setExtra(String extra) {
this.extra = extra;
}
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
buffer.append("<message>");
buffer.append("<mid>").append(mid).append("</mid>");
if (isNotEmpty(type)) {
buffer.append("<type>").append(type).append("</type>");
}
if (isNotEmpty(title)) {
buffer.append("<title>").append(title).append("</title>");
}
if (isNotEmpty(content)) {
buffer.append("<content><![CDATA[").append(content).append("]]></content>");
}
if (isNotEmpty(file)) {
buffer.append("<file>").append(file).append("</file>");
}
if (isNotEmpty(fileType)) {
buffer.append("<fileType>").append(fileType).append("</fileType>");
}
if (isNotEmpty(sender)) {
buffer.append("<sender>").append(sender).append("</sender>");
}
if (isNotEmpty(receiver)) {
buffer.append("<receiver>").append(receiver).append("</receiver>");
}
if (isNotEmpty(format)) {
buffer.append("<format>").append(format).append("</format>");
}
if (timestamp > 0) {
buffer.append("<timestamp>").append(timestamp).append("</timestamp>");
}
buffer.append("</message>");
buffer.append("#Message#").append("\n");
buffer.append("mid:").append(mid).append("\n");
buffer.append("action:").append(action).append("\n");
buffer.append("title:").append(title).append("\n");
buffer.append("content:").append(content).append("\n");
buffer.append("extra:").append(extra).append("\n");
buffer.append("sender:").append(sender).append("\n");
buffer.append("receiver:").append(receiver).append("\n");
buffer.append("format:").append(format).append("\n");
buffer.append("timestamp:").append(timestamp);
return buffer.toString();
}
public String toXmlString() {
return toString();
}
public String getMid() {
return mid;
@ -197,8 +169,8 @@ public class Message implements Serializable {
}
public boolean isNotEmpty(String txt) {
return txt != null && !txt.isEmpty();
return txt != null && txt.trim().length()!=0;
}
}

View File

@ -0,0 +1,31 @@
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.model;
/**
* 需要向另一端发送的结构体
*/
public interface Protobufable {
byte[] getByteArray();
byte getType();
}

View File

@ -1,13 +1,30 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.model;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
/**
* 请求应答对象
*
@ -64,7 +81,9 @@ public class ReplyBody implements Serializable {
}
public void put(String k, String v) {
data.put(k, v);
if(v!=null && k!=null){
data.put(k, v);
}
}
public String get(String k) {
@ -83,8 +102,12 @@ public class ReplyBody implements Serializable {
this.message = message;
}
public HashMap<String, String> getData() {
return data;
public void putAll(Map<String, String> map) {
data.putAll(map);
}
public Set<String> getKeySet() {
return data.keySet();
}
public String getCode() {
@ -98,27 +121,22 @@ public class ReplyBody implements Serializable {
public String toString()
{
StringBuffer buffer = new StringBuffer();
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
buffer.append("<reply>");
buffer.append("<key>").append(this.getKey()).append("</key>");
buffer.append("<timestamp>").append(timestamp).append("</timestamp>");
buffer.append("<code>").append(code).append("</code>");
buffer.append("<data>");
for(String key:this.getData().keySet())
{
buffer.append("<"+key+">").append(this.get(key)).append("</"+key+">");
buffer.append("#ReplyBody#").append("\n");
buffer.append("key:").append(this.getKey()).append("\n");
buffer.append("timestamp:").append(timestamp).append("\n");
buffer.append("code:").append(code).append("\n");
if(!data.isEmpty()){
buffer.append("data{").append("\n");
for(String key:getKeySet())
{
buffer.append(key).append(":").append(this.get(key)).append("\n");
}
buffer.append("}");
}
buffer.append("</data>");
buffer.append("</reply>");
return buffer.toString();
}
public String toXmlString()
{
return toString();
}
}

View File

@ -1,30 +1,48 @@
/**
* probject:cim-android-sdk
* @version 2.1.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.model;
import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import com.farsunset.cim.sdk.android.constant.CIMConstant;
import com.farsunset.cim.sdk.android.model.proto.SentBodyProto;
/**
* java |android 客户端请求结构
*
*/
public class SentBody implements Serializable {
public class SentBody implements Serializable,Protobufable {
private static final long serialVersionUID = 1L;
private String key;
private HashMap<String, String> data;
private HashMap<String, String> data = new HashMap<String, String>();;
private long timestamp;
public SentBody() {
data = new HashMap<String, String>();
timestamp = System.currentTimeMillis();
}
@ -49,36 +67,54 @@ public class SentBody implements Serializable {
}
public void put(String k, String v) {
data.put(k, v);
if(v!=null && k!=null){
data.put(k, v);
}
}
public void putAll(Map<String, String> map) {
data.putAll(map);
}
public Set<String> getKeySet() {
return data.keySet();
}
public void remove(String k) {
data.remove(k);
}
public HashMap<String, String> getData() {
return data;
}
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
buffer.append("<sent>");
buffer.append("<key>").append(key).append("</key>");
buffer.append("<timestamp>").append(timestamp).append("</timestamp>");
buffer.append("<data>");
for (String key : data.keySet()) {
buffer.append("<" + key + ">").append(data.get(key)).append(
"</" + key + ">");
buffer.append("#SentBody#").append("\n");;
buffer.append("key:").append(key).append("\n");
buffer.append("timestamp:").append(timestamp).append("\n");
if(!data.isEmpty()){
buffer.append("data{").append("\n");
for(String key:getKeySet())
{
buffer.append(key).append(":").append(this.get(key)).append("\n");
}
buffer.append("}");
}
buffer.append("</data>");
buffer.append("</sent>");
return buffer.toString();
}
public String toXmlString() {
return toString();
@Override
public byte[] getByteArray() {
SentBodyProto.Model.Builder builder = SentBodyProto.Model.newBuilder();
builder.setKey(key);
builder.setTimestamp(timestamp);
if(!data.isEmpty()){
builder.putAllData(data);
}
return builder.build().toByteArray();
}
@Override
public byte getType() {
return CIMConstant.ProtobufType.SENTBODY;
}
}

View File

@ -0,0 +1,15 @@
syntax = "proto3";
package com.farsunset.cim.sdk.android.model.proto;
option java_outer_classname="MessageProto";
message Model {
string mid = 1;
string action = 2;
string content = 3;
string sender = 4;
string receiver = 5;
string extra = 6;
string title = 7;
string format = 8;
int64 timestamp = 9;
}

View File

@ -0,0 +1,13 @@
syntax = "proto3";
package com.farsunset.cim.sdk.android.model.proto;
option java_outer_classname="ReplyBodyProto";
message Model {
string key = 1;
string code = 2;
string message = 3;
int64 timestamp =4;
map<string,string> data =5;
}

View File

@ -0,0 +1,11 @@
syntax = "proto3";
package com.farsunset.cim.sdk.android.model.proto;
option java_outer_classname="SentBodyProto";
message Model {
string key = 1;
int64 timestamp =2;
map<string,string> data =3;
}

View File

@ -0,0 +1,967 @@
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.cim.sdk.android.model.proto;
public final class SentBodyProto {
private SentBodyProto() {}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistryLite registry) {
}
public static void registerAllExtensions(
com.google.protobuf.ExtensionRegistry registry) {
registerAllExtensions(
(com.google.protobuf.ExtensionRegistryLite) registry);
}
public interface ModelOrBuilder extends
// @@protoc_insertion_point(interface_extends:com.farsunset.cim.sdk.android.model.proto.Model)
com.google.protobuf.MessageOrBuilder {
/**
* <code>string key = 1;</code>
*/
java.lang.String getKey();
/**
* <code>string key = 1;</code>
*/
com.google.protobuf.ByteString
getKeyBytes();
/**
* <code>int64 timestamp = 2;</code>
*/
long getTimestamp();
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
int getDataCount();
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
boolean containsData(
java.lang.String key);
/**
* Use {@link #getDataMap()} instead.
*/
@java.lang.Deprecated
java.util.Map<java.lang.String, java.lang.String>
getData();
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
java.util.Map<java.lang.String, java.lang.String>
getDataMap();
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
java.lang.String getDataOrDefault(
java.lang.String key,
java.lang.String defaultValue);
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
java.lang.String getDataOrThrow(
java.lang.String key);
}
/**
* Protobuf type {@code com.farsunset.cim.sdk.android.model.proto.Model}
*/
public static final class Model extends
com.google.protobuf.GeneratedMessageV3 implements
// @@protoc_insertion_point(message_implements:com.farsunset.cim.sdk.android.model.proto.Model)
ModelOrBuilder {
// Use Model.newBuilder() to construct.
private Model(com.google.protobuf.GeneratedMessageV3.Builder<?> builder) {
super(builder);
}
private Model() {
key_ = "";
timestamp_ = 0L;
}
@java.lang.Override
public final com.google.protobuf.UnknownFieldSet
getUnknownFields() {
return com.google.protobuf.UnknownFieldSet.getDefaultInstance();
}
private Model(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
this();
int mutable_bitField0_ = 0;
try {
boolean done = false;
while (!done) {
int tag = input.readTag();
switch (tag) {
case 0:
done = true;
break;
default: {
if (!input.skipField(tag)) {
done = true;
}
break;
}
case 10: {
java.lang.String s = input.readStringRequireUtf8();
key_ = s;
break;
}
case 16: {
timestamp_ = input.readInt64();
break;
}
case 26: {
if (!((mutable_bitField0_ & 0x00000004) == 0x00000004)) {
data_ = com.google.protobuf.MapField.newMapField(
DataDefaultEntryHolder.defaultEntry);
mutable_bitField0_ |= 0x00000004;
}
com.google.protobuf.MapEntry<java.lang.String, java.lang.String>
data__ = input.readMessage(
DataDefaultEntryHolder.defaultEntry.getParserForType(), extensionRegistry);
data_.getMutableMap().put(
data__.getKey(), data__.getValue());
break;
}
}
}
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
throw e.setUnfinishedMessage(this);
} catch (java.io.IOException e) {
throw new com.google.protobuf.InvalidProtocolBufferException(
e).setUnfinishedMessage(this);
} finally {
makeExtensionsImmutable();
}
}
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return com.farsunset.cim.sdk.android.model.proto.SentBodyProto.internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor;
}
@SuppressWarnings({"rawtypes"})
protected com.google.protobuf.MapField internalGetMapField(
int number) {
switch (number) {
case 3:
return internalGetData();
default:
throw new RuntimeException(
"Invalid map field number: " + number);
}
}
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internalGetFieldAccessorTable() {
return com.farsunset.cim.sdk.android.model.proto.SentBodyProto.internal_static_com_farsunset_cim_sdk_android_model_proto_Model_fieldAccessorTable
.ensureFieldAccessorsInitialized(
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.class, com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.Builder.class);
}
private int bitField0_;
public static final int KEY_FIELD_NUMBER = 1;
private volatile java.lang.Object key_;
/**
* <code>string key = 1;</code>
*/
public java.lang.String getKey() {
java.lang.Object ref = key_;
if (ref instanceof java.lang.String) {
return (java.lang.String) ref;
} else {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
key_ = s;
return s;
}
}
/**
* <code>string key = 1;</code>
*/
public com.google.protobuf.ByteString
getKeyBytes() {
java.lang.Object ref = key_;
if (ref instanceof java.lang.String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
key_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
public static final int TIMESTAMP_FIELD_NUMBER = 2;
private long timestamp_;
/**
* <code>int64 timestamp = 2;</code>
*/
public long getTimestamp() {
return timestamp_;
}
public static final int DATA_FIELD_NUMBER = 3;
private static final class DataDefaultEntryHolder {
static final com.google.protobuf.MapEntry<
java.lang.String, java.lang.String> defaultEntry =
com.google.protobuf.MapEntry
.<java.lang.String, java.lang.String>newDefaultInstance(
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.internal_static_com_farsunset_cim_sdk_android_model_proto_Model_DataEntry_descriptor,
com.google.protobuf.WireFormat.FieldType.STRING,
"",
com.google.protobuf.WireFormat.FieldType.STRING,
"");
}
private com.google.protobuf.MapField<
java.lang.String, java.lang.String> data_;
private com.google.protobuf.MapField<java.lang.String, java.lang.String>
internalGetData() {
if (data_ == null) {
return com.google.protobuf.MapField.emptyMapField(
DataDefaultEntryHolder.defaultEntry);
}
return data_;
}
public int getDataCount() {
return internalGetData().getMap().size();
}
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
public boolean containsData(
java.lang.String key) {
if (key == null) { throw new java.lang.NullPointerException(); }
return internalGetData().getMap().containsKey(key);
}
/**
* Use {@link #getDataMap()} instead.
*/
@java.lang.Deprecated
public java.util.Map<java.lang.String, java.lang.String> getData() {
return getDataMap();
}
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
public java.util.Map<java.lang.String, java.lang.String> getDataMap() {
return internalGetData().getMap();
}
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
public java.lang.String getDataOrDefault(
java.lang.String key,
java.lang.String defaultValue) {
if (key == null) { throw new java.lang.NullPointerException(); }
java.util.Map<java.lang.String, java.lang.String> map =
internalGetData().getMap();
return map.containsKey(key) ? map.get(key) : defaultValue;
}
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
public java.lang.String getDataOrThrow(
java.lang.String key) {
if (key == null) { throw new java.lang.NullPointerException(); }
java.util.Map<java.lang.String, java.lang.String> map =
internalGetData().getMap();
if (!map.containsKey(key)) {
throw new java.lang.IllegalArgumentException();
}
return map.get(key);
}
private byte memoizedIsInitialized = -1;
public final boolean isInitialized() {
byte isInitialized = memoizedIsInitialized;
if (isInitialized == 1) return true;
if (isInitialized == 0) return false;
memoizedIsInitialized = 1;
return true;
}
public void writeTo(com.google.protobuf.CodedOutputStream output)
throws java.io.IOException {
if (!getKeyBytes().isEmpty()) {
com.google.protobuf.GeneratedMessageV3.writeString(output, 1, key_);
}
if (timestamp_ != 0L) {
output.writeInt64(2, timestamp_);
}
com.google.protobuf.GeneratedMessageV3
.serializeStringMapTo(
output,
internalGetData(),
DataDefaultEntryHolder.defaultEntry,
3);
}
public int getSerializedSize() {
int size = memoizedSize;
if (size != -1) return size;
size = 0;
if (!getKeyBytes().isEmpty()) {
size += com.google.protobuf.GeneratedMessageV3.computeStringSize(1, key_);
}
if (timestamp_ != 0L) {
size += com.google.protobuf.CodedOutputStream
.computeInt64Size(2, timestamp_);
}
for (java.util.Map.Entry<java.lang.String, java.lang.String> entry
: internalGetData().getMap().entrySet()) {
com.google.protobuf.MapEntry<java.lang.String, java.lang.String>
data__ = DataDefaultEntryHolder.defaultEntry.newBuilderForType()
.setKey(entry.getKey())
.setValue(entry.getValue())
.build();
size += com.google.protobuf.CodedOutputStream
.computeMessageSize(3, data__);
}
memoizedSize = size;
return size;
}
private static final long serialVersionUID = 0L;
@java.lang.Override
public boolean equals(final java.lang.Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model)) {
return super.equals(obj);
}
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model other = (com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model) obj;
boolean result = true;
result = result && getKey()
.equals(other.getKey());
result = result && (getTimestamp()
== other.getTimestamp());
result = result && internalGetData().equals(
other.internalGetData());
return result;
}
@java.lang.Override
public int hashCode() {
if (memoizedHashCode != 0) {
return memoizedHashCode;
}
int hash = 41;
hash = (19 * hash) + getDescriptor().hashCode();
hash = (37 * hash) + KEY_FIELD_NUMBER;
hash = (53 * hash) + getKey().hashCode();
hash = (37 * hash) + TIMESTAMP_FIELD_NUMBER;
hash = (53 * hash) + com.google.protobuf.Internal.hashLong(
getTimestamp());
if (!internalGetData().getMap().isEmpty()) {
hash = (37 * hash) + DATA_FIELD_NUMBER;
hash = (53 * hash) + internalGetData().hashCode();
}
hash = (29 * hash) + unknownFields.hashCode();
memoizedHashCode = hash;
return hash;
}
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(
com.google.protobuf.ByteString data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(
com.google.protobuf.ByteString data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(byte[] data)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data);
}
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(
byte[] data,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return PARSER.parseFrom(data, extensionRegistry);
}
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseDelimitedFrom(java.io.InputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input);
}
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseDelimitedFrom(
java.io.InputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseDelimitedWithIOException(PARSER, input, extensionRegistry);
}
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(
com.google.protobuf.CodedInputStream input)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input);
}
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parseFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
return com.google.protobuf.GeneratedMessageV3
.parseWithIOException(PARSER, input, extensionRegistry);
}
public Builder newBuilderForType() { return newBuilder(); }
public static Builder newBuilder() {
return DEFAULT_INSTANCE.toBuilder();
}
public static Builder newBuilder(com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model prototype) {
return DEFAULT_INSTANCE.toBuilder().mergeFrom(prototype);
}
public Builder toBuilder() {
return this == DEFAULT_INSTANCE
? new Builder() : new Builder().mergeFrom(this);
}
@java.lang.Override
protected Builder newBuilderForType(
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
Builder builder = new Builder(parent);
return builder;
}
/**
* Protobuf type {@code com.farsunset.cim.sdk.android.model.proto.Model}
*/
public static final class Builder extends
com.google.protobuf.GeneratedMessageV3.Builder<Builder> implements
// @@protoc_insertion_point(builder_implements:com.farsunset.cim.sdk.android.model.proto.Model)
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.ModelOrBuilder {
public static final com.google.protobuf.Descriptors.Descriptor
getDescriptor() {
return com.farsunset.cim.sdk.android.model.proto.SentBodyProto.internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor;
}
@SuppressWarnings({"rawtypes"})
protected com.google.protobuf.MapField internalGetMapField(
int number) {
switch (number) {
case 3:
return internalGetData();
default:
throw new RuntimeException(
"Invalid map field number: " + number);
}
}
@SuppressWarnings({"rawtypes"})
protected com.google.protobuf.MapField internalGetMutableMapField(
int number) {
switch (number) {
case 3:
return internalGetMutableData();
default:
throw new RuntimeException(
"Invalid map field number: " + number);
}
}
protected com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internalGetFieldAccessorTable() {
return com.farsunset.cim.sdk.android.model.proto.SentBodyProto.internal_static_com_farsunset_cim_sdk_android_model_proto_Model_fieldAccessorTable
.ensureFieldAccessorsInitialized(
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.class, com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.Builder.class);
}
// Construct using com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.newBuilder()
private Builder() {
maybeForceBuilderInitialization();
}
private Builder(
com.google.protobuf.GeneratedMessageV3.BuilderParent parent) {
super(parent);
maybeForceBuilderInitialization();
}
private void maybeForceBuilderInitialization() {
if (com.google.protobuf.GeneratedMessageV3
.alwaysUseFieldBuilders) {
}
}
public Builder clear() {
super.clear();
key_ = "";
timestamp_ = 0L;
internalGetMutableData().clear();
return this;
}
public com.google.protobuf.Descriptors.Descriptor
getDescriptorForType() {
return com.farsunset.cim.sdk.android.model.proto.SentBodyProto.internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor;
}
public com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model getDefaultInstanceForType() {
return com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.getDefaultInstance();
}
public com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model build() {
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model result = buildPartial();
if (!result.isInitialized()) {
throw newUninitializedMessageException(result);
}
return result;
}
public com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model buildPartial() {
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model result = new com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model(this);
int from_bitField0_ = bitField0_;
int to_bitField0_ = 0;
result.key_ = key_;
result.timestamp_ = timestamp_;
result.data_ = internalGetData();
result.data_.makeImmutable();
result.bitField0_ = to_bitField0_;
onBuilt();
return result;
}
public Builder clone() {
return (Builder) super.clone();
}
public Builder setField(
com.google.protobuf.Descriptors.FieldDescriptor field,
Object value) {
return (Builder) super.setField(field, value);
}
public Builder clearField(
com.google.protobuf.Descriptors.FieldDescriptor field) {
return (Builder) super.clearField(field);
}
public Builder clearOneof(
com.google.protobuf.Descriptors.OneofDescriptor oneof) {
return (Builder) super.clearOneof(oneof);
}
public Builder setRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
int index, Object value) {
return (Builder) super.setRepeatedField(field, index, value);
}
public Builder addRepeatedField(
com.google.protobuf.Descriptors.FieldDescriptor field,
Object value) {
return (Builder) super.addRepeatedField(field, value);
}
public Builder mergeFrom(com.google.protobuf.Message other) {
if (other instanceof com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model) {
return mergeFrom((com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model)other);
} else {
super.mergeFrom(other);
return this;
}
}
public Builder mergeFrom(com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model other) {
if (other == com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model.getDefaultInstance()) return this;
if (!other.getKey().isEmpty()) {
key_ = other.key_;
onChanged();
}
if (other.getTimestamp() != 0L) {
setTimestamp(other.getTimestamp());
}
internalGetMutableData().mergeFrom(
other.internalGetData());
onChanged();
return this;
}
public final boolean isInitialized() {
return true;
}
public Builder mergeFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws java.io.IOException {
com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model parsedMessage = null;
try {
parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry);
} catch (com.google.protobuf.InvalidProtocolBufferException e) {
parsedMessage = (com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model) e.getUnfinishedMessage();
throw e.unwrapIOException();
} finally {
if (parsedMessage != null) {
mergeFrom(parsedMessage);
}
}
return this;
}
private int bitField0_;
private java.lang.Object key_ = "";
/**
* <code>string key = 1;</code>
*/
public java.lang.String getKey() {
java.lang.Object ref = key_;
if (!(ref instanceof java.lang.String)) {
com.google.protobuf.ByteString bs =
(com.google.protobuf.ByteString) ref;
java.lang.String s = bs.toStringUtf8();
key_ = s;
return s;
} else {
return (java.lang.String) ref;
}
}
/**
* <code>string key = 1;</code>
*/
public com.google.protobuf.ByteString
getKeyBytes() {
java.lang.Object ref = key_;
if (ref instanceof String) {
com.google.protobuf.ByteString b =
com.google.protobuf.ByteString.copyFromUtf8(
(java.lang.String) ref);
key_ = b;
return b;
} else {
return (com.google.protobuf.ByteString) ref;
}
}
/**
* <code>string key = 1;</code>
*/
public Builder setKey(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
key_ = value;
onChanged();
return this;
}
/**
* <code>string key = 1;</code>
*/
public Builder clearKey() {
key_ = getDefaultInstance().getKey();
onChanged();
return this;
}
/**
* <code>string key = 1;</code>
*/
public Builder setKeyBytes(
com.google.protobuf.ByteString value) {
if (value == null) {
throw new NullPointerException();
}
checkByteStringIsUtf8(value);
key_ = value;
onChanged();
return this;
}
private long timestamp_ ;
/**
* <code>int64 timestamp = 2;</code>
*/
public long getTimestamp() {
return timestamp_;
}
/**
* <code>int64 timestamp = 2;</code>
*/
public Builder setTimestamp(long value) {
timestamp_ = value;
onChanged();
return this;
}
/**
* <code>int64 timestamp = 2;</code>
*/
public Builder clearTimestamp() {
timestamp_ = 0L;
onChanged();
return this;
}
private com.google.protobuf.MapField<
java.lang.String, java.lang.String> data_;
private com.google.protobuf.MapField<java.lang.String, java.lang.String>
internalGetData() {
if (data_ == null) {
return com.google.protobuf.MapField.emptyMapField(
DataDefaultEntryHolder.defaultEntry);
}
return data_;
}
private com.google.protobuf.MapField<java.lang.String, java.lang.String>
internalGetMutableData() {
onChanged();;
if (data_ == null) {
data_ = com.google.protobuf.MapField.newMapField(
DataDefaultEntryHolder.defaultEntry);
}
if (!data_.isMutable()) {
data_ = data_.copy();
}
return data_;
}
public int getDataCount() {
return internalGetData().getMap().size();
}
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
public boolean containsData(
java.lang.String key) {
if (key == null) { throw new java.lang.NullPointerException(); }
return internalGetData().getMap().containsKey(key);
}
/**
* Use {@link #getDataMap()} instead.
*/
@java.lang.Deprecated
public java.util.Map<java.lang.String, java.lang.String> getData() {
return getDataMap();
}
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
public java.util.Map<java.lang.String, java.lang.String> getDataMap() {
return internalGetData().getMap();
}
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
public java.lang.String getDataOrDefault(
java.lang.String key,
java.lang.String defaultValue) {
if (key == null) { throw new java.lang.NullPointerException(); }
java.util.Map<java.lang.String, java.lang.String> map =
internalGetData().getMap();
return map.containsKey(key) ? map.get(key) : defaultValue;
}
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
public java.lang.String getDataOrThrow(
java.lang.String key) {
if (key == null) { throw new java.lang.NullPointerException(); }
java.util.Map<java.lang.String, java.lang.String> map =
internalGetData().getMap();
if (!map.containsKey(key)) {
throw new java.lang.IllegalArgumentException();
}
return map.get(key);
}
public Builder clearData() {
internalGetMutableData().getMutableMap()
.clear();
return this;
}
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
public Builder removeData(
java.lang.String key) {
if (key == null) { throw new java.lang.NullPointerException(); }
internalGetMutableData().getMutableMap()
.remove(key);
return this;
}
/**
* Use alternate mutation accessors instead.
*/
@java.lang.Deprecated
public java.util.Map<java.lang.String, java.lang.String>
getMutableData() {
return internalGetMutableData().getMutableMap();
}
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
public Builder putData(
java.lang.String key,
java.lang.String value) {
if (key == null) { throw new java.lang.NullPointerException(); }
if (value == null) { throw new java.lang.NullPointerException(); }
internalGetMutableData().getMutableMap()
.put(key, value);
return this;
}
/**
* <code>map&lt;string, string&gt; data = 3;</code>
*/
public Builder putAllData(
java.util.Map<java.lang.String, java.lang.String> values) {
internalGetMutableData().getMutableMap()
.putAll(values);
return this;
}
public final Builder setUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return this;
}
public final Builder mergeUnknownFields(
final com.google.protobuf.UnknownFieldSet unknownFields) {
return this;
}
// @@protoc_insertion_point(builder_scope:com.farsunset.cim.sdk.android.model.proto.Model)
}
// @@protoc_insertion_point(class_scope:com.farsunset.cim.sdk.android.model.proto.Model)
private static final com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model DEFAULT_INSTANCE;
static {
DEFAULT_INSTANCE = new com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model();
}
public static com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model getDefaultInstance() {
return DEFAULT_INSTANCE;
}
private static final com.google.protobuf.Parser<Model>
PARSER = new com.google.protobuf.AbstractParser<Model>() {
public Model parsePartialFrom(
com.google.protobuf.CodedInputStream input,
com.google.protobuf.ExtensionRegistryLite extensionRegistry)
throws com.google.protobuf.InvalidProtocolBufferException {
return new Model(input, extensionRegistry);
}
};
public static com.google.protobuf.Parser<Model> parser() {
return PARSER;
}
@java.lang.Override
public com.google.protobuf.Parser<Model> getParserForType() {
return PARSER;
}
public com.farsunset.cim.sdk.android.model.proto.SentBodyProto.Model getDefaultInstanceForType() {
return DEFAULT_INSTANCE;
}
}
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor;
private static final
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_fieldAccessorTable;
private static final com.google.protobuf.Descriptors.Descriptor
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_DataEntry_descriptor;
private static final
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_DataEntry_fieldAccessorTable;
public static com.google.protobuf.Descriptors.FileDescriptor
getDescriptor() {
return descriptor;
}
private static com.google.protobuf.Descriptors.FileDescriptor
descriptor;
static {
java.lang.String[] descriptorData = {
"\n\016SentBody.proto\022)com.farsunset.cim.sdk." +
"android.model.proto\"\236\001\n\005Model\022\013\n\003key\030\001 \001" +
"(\t\022\021\n\ttimestamp\030\002 \001(\003\022H\n\004data\030\003 \003(\0132:.co" +
"m.farsunset.cim.sdk.android.model.proto." +
"Model.DataEntry\032+\n\tDataEntry\022\013\n\003key\030\001 \001(" +
"\t\022\r\n\005value\030\002 \001(\t:\0028\001B\017B\rSentBodyProtob\006p" +
"roto3"
};
com.google.protobuf.Descriptors.FileDescriptor.InternalDescriptorAssigner assigner =
new com.google.protobuf.Descriptors.FileDescriptor. InternalDescriptorAssigner() {
public com.google.protobuf.ExtensionRegistry assignDescriptors(
com.google.protobuf.Descriptors.FileDescriptor root) {
descriptor = root;
return null;
}
};
com.google.protobuf.Descriptors.FileDescriptor
.internalBuildGeneratedFileFrom(descriptorData,
new com.google.protobuf.Descriptors.FileDescriptor[] {
}, assigner);
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor =
getDescriptor().getMessageTypes().get(0);
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_fieldAccessorTable = new
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor,
new java.lang.String[] { "Key", "Timestamp", "Data", });
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_DataEntry_descriptor =
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_descriptor.getNestedTypes().get(0);
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_DataEntry_fieldAccessorTable = new
com.google.protobuf.GeneratedMessageV3.FieldAccessorTable(
internal_static_com_farsunset_cim_sdk_android_model_proto_Model_DataEntry_descriptor,
new java.lang.String[] { "Key", "Value", });
}
// @@protoc_insertion_point(outer_class_scope)
}

View File

@ -0,0 +1,9 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
.externalNativeBuild

View File

@ -0,0 +1,105 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectInspectionProfilesVisibleTreeState">
<entry key="Project Default">
<profile-state>
<expanded-state>
<State>
<id />
</State>
<State>
<id>Android</id>
</State>
<State>
<id>Android &gt; Lint &gt; Correctness</id>
</State>
<State>
<id>Android &gt; Lint &gt; Internationalization</id>
</State>
<State>
<id>Android &gt; Lint &gt; Security</id>
</State>
<State>
<id>CorrectnessLintAndroid</id>
</State>
<State>
<id>Gradle</id>
</State>
<State>
<id>LintAndroid</id>
</State>
<State>
<id>Probable bugsGradle</id>
</State>
</expanded-state>
<selected-state>
<State>
<id>Android</id>
</State>
</selected-state>
</profile-state>
</entry>
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
<component name="SuppressionsComponent">
<option name="suppComments" value="[]" />
</component>
<component name="masterDetails">
<states>
<state key="ProjectJDKs.UI">
<settings>
<last-edited>1.8</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project>

View File

@ -0,0 +1 @@
/build

View File

@ -0,0 +1,35 @@
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.farsunset.ichat.example"
minSdkVersion 14
targetSdkVersion 21
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
lintOptions {
checkReleaseBuilds false
abortOnError false
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:25.1.0'
compile 'com.google.protobuf:protobuf-java:3.2.0'
compile 'org.apache.mina:mina-core:2.0.16'
compile 'org.slf4j:slf4j-api:1.7.24'
compile 'org.slf4j:slf4j-nop:1.7.24'
}

View File

@ -0,0 +1,17 @@
# Add project specific ProGuard rules here.
# By default, the flags in this file are appended to flags specified
# in D:\Program Files (x86)\dev\android-sdk-windos/tools/proguard/proguard-android.txt
# You can edit the include path and order by changing the proguardFiles
# directive in build.gradle.
#
# For more details, see
# http://developer.android.com/guide/developing/tools/proguard.html
# Add any project specific keep options here:
# If your project uses WebView with JS, uncomment the following
# and specify the fully qualified class name to the JavaScript interface
# class:
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
# public *;
#}

View File

@ -1,8 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.farsunset.ichat.example"
android:versionCode="3"
android:versionName="2.1.0" >
android:versionCode="30"
android:versionName="3.0.0" >
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
@ -10,10 +10,6 @@
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-sdk
android:minSdkVersion="10"
android:targetSdkVersion="19" />
<application
android:allowBackup="true"
@ -55,7 +51,7 @@
<service android:name="com.farsunset.cim.sdk.android.CIMPushService" android:process=":cimpush" />
<!--消息接受广播注册-->
<receiver android:name="com.farsunset.ichat.example.receiver.CustomCIMMessageReceiver" android:exported="false">
<receiver android:name="com.farsunset.ichat.example.receiver.CIMPushManagerReceiver" android:exported="false">
<intent-filter android:priority="0x7fffffff">
<action android:name="android.net.conn.CONNECTIVITY_CHANGE"/> <!-- 网络变化广播 -->
<action android:name="com.farsunset.cim.MESSAGE_RECEIVED"/><!-- 消息广播action -->

View File

@ -0,0 +1,38 @@
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.ichat.example.adapter;
import java.util.Comparator;
import com.farsunset.cim.sdk.android.model.Message;
public class MessageTimeDescComparator implements Comparator<Message>{
@Override
public int compare(Message arg0, Message arg1) {
return (int) (arg1.getTimestamp() - arg0.getTimestamp()) ;
}
}

View File

@ -1,9 +1,24 @@
/**
* probject:cim
* @version 2.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.ichat.example.adapter;
import java.text.SimpleDateFormat;
@ -67,7 +82,7 @@ public class SystemMsgListViewAdapter extends BaseAdapter {
((TextView) chatItemView.findViewById(R.id.time)).setText(getDateTimeString(Long.valueOf(msg.getTimestamp())));
((TextView) chatItemView.findViewById(R.id.content)).setText(msg.getContent() );
((ImageView) chatItemView.findViewById(R.id.headImageView)).setImageResource(R.drawable.icon_recent_sysmsg);
((ImageView) chatItemView.findViewById(R.id.headImageView)).setImageResource(R.drawable.icon);
return chatItemView;
}

View File

@ -0,0 +1,118 @@
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.ichat.example.app;
import com.farsunset.cim.sdk.android.CIMEventListener;
import com.farsunset.cim.sdk.android.CIMListenerManager;
import com.farsunset.cim.sdk.android.model.Message;
import com.farsunset.cim.sdk.android.model.ReplyBody;
import com.farsunset.cim.sdk.android.model.SentBody;
import android.app.Activity;
import android.net.NetworkInfo;
import android.os.Bundle;
public abstract class CIMMonitorActivity extends Activity implements CIMEventListener{
CommonBaseControl commonBaseControl;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
CIMListenerManager.registerMessageListener(this);
commonBaseControl = new CommonBaseControl(this);
}
@Override
public void finish() {
super.finish();
CIMListenerManager.removeMessageListener(this);
}
@Override
public void onRestart() {
super.onRestart();
CIMListenerManager.registerMessageListener(this);
}
public void showProgressDialog(String title,String content)
{
commonBaseControl.showProgressDialog(title, content);
}
public void hideProgressDialog()
{
commonBaseControl.hideProgressDialog();
}
public void showToask(String hint){
commonBaseControl.showToask(hint);
}
@Override
public void onMessageReceived(Message arg0){};
@Override
public void onNetworkChanged(NetworkInfo info){}
/**
* 与服务端断开连接时回调,不要在里面做连接服务端的操作
*/
@Override
public void onConnectionClosed() {}
@Override
public void onConnectionFailed() {
}
@Override
public int getEventDispatchOrder() {
return 0;
}
/**
* 连接服务端成功时回调
*/
@Override
public void onConnectionSuccessed(boolean arg0) {}
@Override
public void onReplyReceived(ReplyBody arg0) {}
@Override
public void onSentSuccessed(SentBody sentBody) {
}
}

View File

@ -0,0 +1,78 @@
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.ichat.example.app;
import android.app.ProgressDialog;
import android.content.Context;
import android.widget.Toast;
public class CommonBaseControl {
private ProgressDialog progressDialog;
Context mMontent;
public CommonBaseControl(Context content)
{
this.mMontent = content;
}
public void showProgressDialog(String title,String message)
{
if(progressDialog==null)
{
progressDialog = ProgressDialog.show(mMontent, title, message, true, true);
}else if(progressDialog.isShowing())
{
progressDialog.setTitle(title);
progressDialog.setMessage(message);
}
progressDialog.show();
}
public void hideProgressDialog()
{
if(progressDialog!=null&&progressDialog.isShowing())
{
progressDialog.dismiss();
}
}
public void showToask(String hint){
Toast toast=Toast.makeText(mMontent,hint,Toast.LENGTH_SHORT);
toast.show();
}
}

View File

@ -0,0 +1,53 @@
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.ichat.example.app;
public interface Constant {
//服务端IP地址
public static final String CIM_SERVER_HOST = "172.168.11.28";
//注意这里的端口不是tomcat的端口CIM端口在服务端spring-cim.xml中配置的没改动就使用默认的23456
public static final int CIM_SERVER_PORT = 23456;
public static interface MessageType{
//用户之间的普通消息
public static final String TYPE_0 = "0";
//下线类型
String TYPE_999 = "999";
}
public static interface MessageStatus{
//消息未读
public static final String STATUS_0 = "0";
//消息已经读取
public static final String STATUS_1 = "1";
}
}

View File

@ -0,0 +1,126 @@
/**
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.ichat.example.receiver;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.NetworkInfo;
import android.support.v4.app.NotificationCompat;
import com.farsunset.cim.sdk.android.CIMEventBroadcastReceiver;
import com.farsunset.cim.sdk.android.CIMListenerManager;
import com.farsunset.cim.sdk.android.model.Message;
import com.farsunset.cim.sdk.android.model.ReplyBody;
import com.farsunset.ichat.example.R;
import com.farsunset.ichat.example.ui.SystemMessageActivity;
import static android.R.id.message;
import static com.farsunset.ichat.example.R.id.content;
/**
* 消息入口所有消息都会经过这里
* @author 3979434
*
*/
public final class CIMPushManagerReceiver extends CIMEventBroadcastReceiver {
private NotificationManager notificationManager;
//当收到消息时会执行onMessageReceived这里是消息第一入口
@Override
public void onMessageReceived(Message message, Intent intent) {
//调用分发消息监听
CIMListenerManager.notifyOnMessageReceived(message);
//以开头的为动作消息无须显示,如被强行下线消息Constant.TYPE_999
if(message.getAction().startsWith("9"))
{
return ;
}
showNotify(context,message);
}
private void showNotify(Context context , Message msg)
{
this.notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
String title = "系统消息";
PendingIntent contentIntent = PendingIntent.getActivity(context,1, new Intent(context,SystemMessageActivity.class), PendingIntent.FLAG_UPDATE_CURRENT);
final NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
builder.setAutoCancel(true);
builder.setDefaults(Notification.DEFAULT_ALL);
builder.setWhen(msg.getTimestamp());
builder.setSmallIcon(R.drawable.icon);
builder.setTicker(title);
builder.setContentTitle(title);
builder.setContentText(msg.getContent());
builder.setDefaults(Notification.DEFAULT_LIGHTS);
builder.setContentIntent(contentIntent);
final Notification notification = builder.build();
notificationManager.notify(R.drawable.icon, notification);
}
@Override
public void onNetworkChanged(NetworkInfo info) {
CIMListenerManager.notifyOnNetworkChanged(info);
}
@Override
public void onConnectionSuccessed(boolean hasAutoBind) {
CIMListenerManager.notifyOnConnectionSuccessed(hasAutoBind);
}
@Override
public void onConnectionClosed() {
CIMListenerManager.notifyOnConnectionClosed();
}
@Override
public void onReplyReceived(ReplyBody body) {
CIMListenerManager.notifyOnReplyReceived(body);
}
@Override
public void onConnectionFailed() {
// TODO Auto-generated method stub
CIMListenerManager.notifyOnConnectionFailed();
}
}

View File

@ -1,9 +1,24 @@
/**
* probject:cim
* @version 2.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.ichat.example.ui;
import android.content.Intent;
@ -44,18 +59,13 @@ public class LoginActivity extends CIMMonitorActivity implements
if (!"".equals(accountEdit.getText().toString().trim())) {
showProgressDialog("提示", "正在登陆,请稍后......");
if(CIMPushManager.getState(this) == CIMPushManager.STATE_NORMAL )
{
if (CIMPushManager.isConnected(this)) {
CIMPushManager.bindAccount(this, accountEdit.getText().toString().trim());
return;
} else {
CIMPushManager.connect(this, Constant.CIM_SERVER_HOST, Constant.CIM_SERVER_PORT);
}
if(CIMPushManager.getState(this) == CIMPushManager.STATE_STOPED )
{
CIMPushManager.connect(this,Constant.CIM_SERVER_HOST, Constant.CIM_SERVER_PORT);
}
}
}
}
@Override

View File

@ -1,9 +1,24 @@
/**
* probject:cim
* @version 2.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.ichat.example.ui;

View File

@ -1,9 +1,24 @@
/**
* probject:cim
* @version 2.0
*
* @author 3979434@qq.com
*/
* Copyright 2013-2023 Xia Jun(3979434@qq.com).
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
***************************************************************************************
* *
* Website : http://www.farsunset.com *
* *
***************************************************************************************
*/
package com.farsunset.ichat.example.ui;
import java.util.ArrayList;
@ -25,29 +40,19 @@ import com.farsunset.ichat.example.R;
import com.farsunset.ichat.example.adapter.SystemMsgListViewAdapter;
import com.farsunset.ichat.example.app.CIMMonitorActivity;
import com.farsunset.ichat.example.app.Constant;
import com.farsunset.ichat.example.network.HttpAPIRequester;
import com.farsunset.ichat.example.network.HttpAPIResponser;
public class SystemMessageActivity extends CIMMonitorActivity implements OnClickListener, HttpAPIResponser{
public class SystemMessageActivity extends CIMMonitorActivity implements OnClickListener{
protected ListView chatListView;
int currentPage = 1;
protected SystemMsgListViewAdapter adapter;
private ArrayList<Message> list;
public HashMap<String, Object> apiParams = new HashMap<String, Object>();
//客户端向客户端发送消息接口地址
public final static String SEND_MESSAGE_API_URL=Constant.SERVER_URL+"/cgi/message_send.api";
HttpAPIRequester requester ;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_system_chat);
initViews();
requester = new HttpAPIRequester(this);
//绑定账号成功获取离线消息
getOfflineMessage();
}
@ -73,7 +78,7 @@ public class SystemMessageActivity extends CIMMonitorActivity implements OnClick
@Override
public void onMessageReceived(Message message) {
if(message.getType().equals(Constant.MessageType.TYPE_999))
if(message.getAction().equals(Constant.MessageType.TYPE_999))
{
//返回登录页面停止接受消息
CIMPushManager.stop(this);
@ -93,11 +98,11 @@ public class SystemMessageActivity extends CIMMonitorActivity implements OnClick
}
//获取离线消息代码示例前提是服务端要实现此功能
//获取离线消息代码示例前提是服务端要实现此功能,建议使用http 接口拉去大量的离线消息
private void getOfflineMessage()
{
SentBody sent = new SentBody();
sent.setKey(CIMConstant.RequestKey.CLIENT_OFFLINE_MESSAGE);
sent.setKey(CIMConstant.RequestKey.CLIENT_PULL_MESSAGE);
sent.put("account", this.getIntent().getStringExtra("account"));
CIMPushManager.sendRequest(this, sent);
}
@ -115,38 +120,8 @@ public class SystemMessageActivity extends CIMMonitorActivity implements OnClick
}
}
//发送消息示范用户客户端与客户端之间的消息发送
private void sendMessage() throws Exception
{
requester.execute(SEND_MESSAGE_API_URL);
}
@Override
public void onSuccess(String data,String url) {
hideProgressDialog();
showToask("发送成功");
}
@Override
public Map<String, Object> getRequestParams() {
apiParams.put("content", "hello world!");
apiParams.put("sender", "xiaogou");//发送者账号
apiParams.put("receiver", "xiaomao");//消息接收者账号
apiParams.put("type",Constant.MessageType.TYPE_0);
return apiParams;
}
@Override
public void onRequest() {
showProgressDialog("提示", "正在发送消息...");
}
@Override
public void onClick(View v) {
@ -158,9 +133,6 @@ public class SystemMessageActivity extends CIMMonitorActivity implements OnClick
}
}
@Override
public void onFailed(Exception e,String url) {}
@Override
public void onBackPressed() {
@ -173,4 +145,4 @@ public class SystemMessageActivity extends CIMMonitorActivity implements OnClick
}
}
}

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

@ -17,7 +17,6 @@
android:layout_height="91.0dip"
android:layout_gravity="center_horizontal"
android:layout_marginTop="68.0dip"
android:background="@drawable/card_avatar"
android:scaleType="fitXY"
android:src="@drawable/login_default_avatar" />

Some files were not shown because too many files have changed in this diff Show More