feat: 后端全量更新 - 含所有本次需求
- Contract.php: 返回合约账户余额(balance_contract) - My.php: 地址管理增加BTC/ETH - AppContract.php: 一键平仓(closeall) - AppProxy.php: 代理专属注册链接 + 分级权限(L1/L2) - site.php: 手续费减半(0.018→0.009) - agent_permission_setup.sql: 代理权限SQL - crypto_news_crawler.py: 新闻自动采集脚本
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
@@ -0,0 +1,445 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="Tutorial for GraphObject manipulation with GoJS." />
|
||||
<title>GraphObject Manipulation</title>
|
||||
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
|
||||
<link href="../assets/css/bootstrap.min.css" rel="stylesheet" >
|
||||
<!-- custom CSS after bootstrap -->
|
||||
<link href="../assets/css/main.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="../assets/css/highlight.css" rel="stylesheet" type="text/css" media="all" />
|
||||
<script src="../assets/js/highlight.js"></script>
|
||||
|
||||
<script src="../release/go.js"></script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-1506307-5', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- non-fixed navbar -->
|
||||
<nav id="non-fixed-nav" class="navbar navbar-inverse navbar-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<div class="navheader-container">
|
||||
<div class="navheader-collapse" data-toggle="collapse" data-target="#navbar">
|
||||
<a id="toplogo" class="navbar-brand" href="../index.html">GoJS</a>
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="../index.html">Home</a></li>
|
||||
<li><a href="../learn/index.html">Learn</a></li>
|
||||
<li><a href="../samples/index.html">Samples</a></li>
|
||||
<li><a href="../intro/index.html">Intro</a></li>
|
||||
<li><a href="../api/index.html" target="api">API</a></li>
|
||||
<li><a href="https://www.nwoods.com/components/evalform.htm">Register</a></li>
|
||||
<li><a href="../download.html">Download</a></li>
|
||||
<li><a href="https://forum.nwoods.com/c/gojs">Forum</a></li>
|
||||
<li><a href="https://www.nwoods.com/contact.html" onclick="ga('send','event','Outbound Link','click','contact');">Contact</a></li>
|
||||
<li class="buy"><a href="https://www.nwoods.com/sales/index.html" onclick="ga('send','event','Outbound Link','click','buy');">Buy</a></li>
|
||||
<li class="activate"><a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a></li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div id="bannertop" class="jumbotron banner">
|
||||
<div class="container-fluid plr15">
|
||||
<h1><span>GraphObject Manipulation</span></h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid learn-container">
|
||||
<h2 id="ProgrammaticallyInteractiveWithNodes">Programmatically interacting with Nodes</h2>
|
||||
|
||||
<p>
|
||||
This guide will show you some basic ways of programmatically interacting with <b>GoJS</b> nodes and links and model data.
|
||||
Throughout this page, we will use the following diagram setup as our starting point:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var $ = go.GraphObject.make;
|
||||
myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv",
|
||||
{ "undoManager.isEnabled": true });
|
||||
|
||||
// define a simple Node template
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape, "Rectangle",
|
||||
// don't draw any outline
|
||||
{ stroke: null },
|
||||
// the Shape.fill comes from the Node.data.color property
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
// leave some space around larger-than-normal text
|
||||
{ margin: 6, font: "18px sans-serif" },
|
||||
// the TextBlock.text comes from the Node.data.key property
|
||||
new go.Binding("text", "key"))
|
||||
);
|
||||
|
||||
myDiagram.model = new go.GraphLinksModel(
|
||||
[
|
||||
{ key: "Alpha", color: "lightblue" },
|
||||
{ key: "Beta", color: "orange" },
|
||||
{ key: "Gamma", color: "lightgreen" },
|
||||
{ key: "Delta", color: "pink" }
|
||||
]);</pre>
|
||||
|
||||
<p>
|
||||
The code produces this Diagram:
|
||||
</p>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv" class="diagramStyling" style="width:700px; height:150px"></div>
|
||||
<script>
|
||||
function setupDiagram(divname) {
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram = $(go.Diagram, divname,
|
||||
{ "undoManager.isEnabled": true });
|
||||
|
||||
// define a simple Node template
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape, "Rectangle",
|
||||
{ stroke: null },
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
{ margin: 6, font: "18px sans-serif" },
|
||||
new go.Binding("text", "key"))
|
||||
);
|
||||
|
||||
myDiagram.model = new go.GraphLinksModel(
|
||||
[
|
||||
{ key: "Alpha", color: "lightblue" },
|
||||
{ key: "Beta", color: "orange" },
|
||||
{ key: "Gamma", color: "lightgreen" },
|
||||
{ key: "Delta", color: "pink" }
|
||||
]);
|
||||
return myDiagram;
|
||||
}
|
||||
setupDiagram("myDiagramDiv");
|
||||
</script>
|
||||
|
||||
<h2 id="FindingSingleNodesDiagramFindNodeForKey">Finding single nodes: Diagram.findNodeForKey</h2>
|
||||
|
||||
<p>
|
||||
You can use <code>Diagram.findNodeForKey(key)</code> to get a reference to a Node in JavaScript.
|
||||
Key values in <b>GoJS</b> can be either strings or numbers.
|
||||
You can then use the Node reference to inspect and manipulate the Node.
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var node = myDiagram.findNodeForKey("Alpha");
|
||||
|
||||
// Selects the node programmatically, rather than clicking interactively:
|
||||
myDiagram.select(node);
|
||||
|
||||
// Outputs a JavaScript object in the developer console window.
|
||||
// The format of what is output will differ per browser, but is essentially the object:
|
||||
// { key: "Alpha", color: "lightblue" }
|
||||
// plus some internal implementation details.
|
||||
console.log(node.data);</pre>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv2" class="diagramStyling" style="width:700px; height:150px"></div>
|
||||
<script>
|
||||
var myDiagram = setupDiagram("myDiagramDiv2");
|
||||
var node = myDiagram.findNodeForKey("Alpha");
|
||||
myDiagram.select(node);
|
||||
if (window.console) console.log(node.data);
|
||||
</script>
|
||||
|
||||
<p>
|
||||
However <code>findNodeForKey</code> may return <code>null</code> if no node data uses that key value.
|
||||
Also, it only looks at the model data to find a node data that uses the given key value,
|
||||
from which it finds the corresponding Node in the Diagram.
|
||||
It does not look at the text values of any TextBlocks that are within the Nodes,
|
||||
so it can work even if no text is shown at all.
|
||||
</p>
|
||||
<p>
|
||||
Once you have a <code>Node</code>, you can get its key either via the <code>Node.key</code> property or
|
||||
by looking at its data: <code>someNode.data.key</code>, just as you can look at any of the data properties.
|
||||
</p>
|
||||
|
||||
<h2 id="CollectionsOfNodesAndLinks">Collections of Nodes and Links</h2>
|
||||
|
||||
<p>
|
||||
Diagrams have several properties and methods that return iterators describing collections of Parts.
|
||||
Both Nodes and Links are kinds of Parts.
|
||||
<code>Diagram.nodes</code> and <code>Diagram.links</code> return iterators of all Nodes and Links in the Diagram, respectively.
|
||||
<code>Diagram.selection</code> returns an iterator of selected Parts
|
||||
(both selected Nodes and selected Links).
|
||||
</p>
|
||||
|
||||
<p>
|
||||
There are also more specific methods for common operations, such as <code>Diagram.findTreeRoots()</code>
|
||||
which returns an iterator of all top-level Nodes that have no parent nodes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
This next example uses <code>Diagram.nodes</code> and shows how to iterate over the collection.
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
// Calling Diagram.commit executes the given function between startTransaction and commitTransaction
|
||||
// calls. That automatically updates the display and allows the effects to be undone.
|
||||
myDiagram.commit(function(d) { // this Diagram
|
||||
|
||||
// iterate over all nodes in Diagram
|
||||
d.nodes.each(function(node) {
|
||||
if (node.data.key === "Beta") continue; //skip Beta, just to contrast
|
||||
node.scale = 0.4; // shrink each node
|
||||
});
|
||||
|
||||
}, "decrease scale");</pre>
|
||||
|
||||
<p>As a result we have very scaled-down nodes, except for Beta:</p>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv3" class="diagramStyling" style="width:700px; height:150px"></div>
|
||||
<script>
|
||||
var myDiagram = setupDiagram("myDiagramDiv3");
|
||||
myDiagram.commit(function(d) { // this Diagram
|
||||
// iterate over all nodes in Diagram
|
||||
d.nodes.each(function(node) {
|
||||
if (node.data.key === "Beta") return; //skip Beta, just to contrast
|
||||
node.scale = 0.4; // shrink each node
|
||||
});
|
||||
}, "decrease scale");
|
||||
</script>
|
||||
|
||||
|
||||
<h2 id="NamedGraphObjectsAndPanelFindObject">Named GraphObjects and Panel.findObject</h2>
|
||||
|
||||
<p>
|
||||
Often we want to manipulate a property that belongs to one of the Node's elements,
|
||||
perhaps an element arbitrarily deep in the template.
|
||||
In our example Diagram, each Node has one Shape,
|
||||
and if we want to change the color of this Shape directly we would need a reference to it.
|
||||
To make it possible to find, we can give that Shape a name:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape, "Rectangle",
|
||||
{ stroke: null, name: "SHAPE" }, // added the name property
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
{ margin: 6, font: "18px sans-serif" },
|
||||
new go.Binding("text", "key"))
|
||||
);</pre>
|
||||
|
||||
<p>
|
||||
Names allow us to easily find GraphObjects inside of Panels
|
||||
(all Nodes are also Panels) using <code>Panel.findObject</code>,
|
||||
which will search the visual tree of a Panel starting at that panel.
|
||||
So when we have a reference to a Node, we can call <code>someNode.findObject("SomeName")</code>
|
||||
to search through the node for the named object.
|
||||
It will return a reference to the named GraphObject if it is found, or <code>null</code> otherwise.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Using this, we could make an HTML button that changes the fill of the Shape inside of a selected Node:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var selectionButton = document.getElementById("selectionButton");
|
||||
selectionButton.addEventListener("click", function() {
|
||||
myDiagram.commit(function(d) {
|
||||
d.selection.each(function(node) {
|
||||
var shape = node.findObject("SHAPE");
|
||||
// If there was a GraphObject in the node named SHAPE, then set its fill to red:
|
||||
if (shape !== null) {
|
||||
shape.fill = "red";
|
||||
}
|
||||
});
|
||||
}, "change color");
|
||||
});</pre>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv4" class="diagramStyling" style="width:700px; height:150px"></div>
|
||||
<button id="selectionButton">Select some Nodes; then click here to change Shape.fill inside selected Nodes</button>
|
||||
<script>
|
||||
var myDiagram = setupDiagram("myDiagramDiv4");
|
||||
var selectionButton = document.getElementById("selectionButton");
|
||||
selectionButton.addEventListener("click", function() {
|
||||
myDiagram.commit(function(d) {
|
||||
d.selection.each(function(node) {
|
||||
var shape = node.findObject("SHAPE");
|
||||
// If there was a GraphObject in the node named SHAPE, then set its fill to red:
|
||||
if (shape !== null) {
|
||||
shape.fill = "red";
|
||||
}
|
||||
});
|
||||
}, "change color");
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
<h2 id="ChangingProperteisAndUpdatingModelUsingDataBindings">Changing Properties and Updating the Model using Data Bindings</h2>
|
||||
|
||||
<p>
|
||||
Looking again at our Node template, we have the <code>Shape.fill</code>
|
||||
property data-bound to the "color" property of our Node data:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape, "Rectangle",
|
||||
{ stroke: null, name: "SHAPE" },
|
||||
new go.Binding("fill", "color")), // note this data binding
|
||||
$(go.TextBlock,
|
||||
{ margin: 6, font: "18px sans-serif" },
|
||||
new go.Binding("text", "key"))
|
||||
);</pre>
|
||||
|
||||
<p>
|
||||
Changing the Shape's <code>fill</code> property inside our node will not,
|
||||
as the Node template currently stands, update the model data.
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var node = myDiagram.findNodeForKey("Alpha");
|
||||
var shape = node.findObject("SHAPE");
|
||||
shape.fill = "red";
|
||||
|
||||
// outputs "lightblue" - the model has not changed!
|
||||
console.log(node.data.color);</pre>
|
||||
|
||||
<p>
|
||||
This is undesirable in some cases.
|
||||
When we want the change to persist after saving and loading,
|
||||
we will want the model data updated too.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
However, in some situations this lack of persistence might be a good thing.
|
||||
For instance if we want the color change for only cosmetic purposes,
|
||||
such as changing the color of a button when hovering over it with the mouse,
|
||||
we would not want to modify the model data that might be saved.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
For now, suppose that we do want to update the model.
|
||||
The preferred way to do this is to modify the data in the model
|
||||
and depend on the data binding to automatically update the Shape.
|
||||
However, we cannot modify the data directly by just setting the JavaScript property.
|
||||
</p>
|
||||
|
||||
<pre class="lang-js" style="border: 6px solid red">
|
||||
var node = myDiagram.findNodeForKey("Alpha");
|
||||
|
||||
// DO NOT DO THIS!
|
||||
// This would update the data, but GoJS would not be notified
|
||||
// that this arbitrary JavaScript object has been modified,
|
||||
// and the associated Node will not be updated appropriately
|
||||
node.data.color = "red";</pre>
|
||||
|
||||
<p>
|
||||
Instead we should set the data property using the method
|
||||
<code>Model.set(data, propertyName, propertyValue)</code>.
|
||||
</p>
|
||||
|
||||
<pre class="lang-js" style="border: 6px solid lime">
|
||||
var node = myDiagram.findNodeForKey("Alpha");
|
||||
|
||||
// Model.commit executes the given function within a transaction
|
||||
myDiagram.model.commit(function(m) { // m == the Model
|
||||
|
||||
// This is the safe way to change model data.
|
||||
// GoJS will be notified that the data has changed
|
||||
// so that it can update the node in the Diagram
|
||||
// and record the change in the UndoManager.
|
||||
m.set(node.data, "color", "red");
|
||||
|
||||
}, "change color");
|
||||
|
||||
// outputs "red" - the model has changed!
|
||||
console.log(node.data.color);
|
||||
// and the user will see the red node</pre>
|
||||
|
||||
<div id="myDiagramDiv5" class="diagramStyling" style="width:700px; height:150px"></div>
|
||||
<script>
|
||||
var myDiagram = setupDiagram("myDiagramDiv5");
|
||||
var node = myDiagram.findNodeForKey("Alpha");
|
||||
// Model.commit executes the given function within a transaction
|
||||
myDiagram.model.commit(function(m) { // m == the Model
|
||||
// This is the safe way to change model data.
|
||||
// GoJS will be notified that the data has changed
|
||||
// so that it can update the node in the Diagram
|
||||
// and record the change in the UndoManager.
|
||||
m.set(node.data, "color", "red");
|
||||
}, "change color");
|
||||
</script>
|
||||
|
||||
<p>
|
||||
Note that there is no longer any need to name the Shape "SHAPE",
|
||||
because there is no longer any need to call <code>findObject</code> to look for the particular Shape.
|
||||
Data binding will automatically update properties, so we do not have to do that ourselves.
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape, "Rectangle",
|
||||
{ stroke: null }, // removed the name property
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
{ margin: 6, font: "18px sans-serif" },
|
||||
new go.Binding("text", "key"))
|
||||
);</pre>
|
||||
|
||||
|
||||
<h2 id="SubjectMentionedAndFurtherReading">Subjects Mentioned and Further Reading</h2>
|
||||
<ul>
|
||||
<li>Data Binding — See the <a href="../intro/dataBinding.html">intro page on Data Binding for lots more detail</a>.</li>
|
||||
<li>Transactions — See the <a href="../intro/transactions.html">intro page on Transactions</a>.</li>
|
||||
<li>
|
||||
<code>console.log</code> — A powerful debugging aid that is part of most browser's developer tools.
|
||||
See the <a href="https://developers.google.com/chrome-developer-tools/docs/console">Chrome guide</a> or
|
||||
the <a href="https://developer.mozilla.org/en-US/docs/Tools/Browser_Console">Firefox guide</a> for their respective developer consoles.
|
||||
See more suggestions for debugging GoJS diagrams at the <a href="../intro/debugging.html">intro page on Debugging</a>.
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
You may want to read more tutorials, such as the <a href="index.html">Learn GoJS</a> tutorial.
|
||||
and the <a href="interactivity.html">Interactivity</a> tutorial.
|
||||
You can also watch tutorials on <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">YouTube</a>.
|
||||
</p>
|
||||
<p>
|
||||
If you are ready for a comprehensive overview of <b>GoJS</b>, have a look at the <a href="../intro/index.html">technical introduction</a>.
|
||||
If you want to explore by example, have a look at <a href="../samples/index.html">the samples</a> to get a feel for what's possible with <b>GoJS</b>.
|
||||
</p>
|
||||
|
||||
<p class="footer">
|
||||
GoJS ® by Northwoods Software. Copyright © 1998-2020 <a href="https://www.nwoods.com" target="_blank">Northwoods Software</a> ®
|
||||
</p>
|
||||
|
||||
</div> <!-- end main -->
|
||||
<div class="banner" id="bannerbottom">
|
||||
<!-- text in banner-->
|
||||
</div>
|
||||
<script src="../assets/js/jquery.min.js"></script>
|
||||
<script async src="../assets/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,824 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="Tutorial for getting started with GoJS." />
|
||||
<title>Get Started with GoJS</title>
|
||||
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
|
||||
<link href="../assets/css/bootstrap.min.css" rel="stylesheet" >
|
||||
<!-- custom CSS after bootstrap -->
|
||||
<link href="../assets/css/main.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="../assets/css/highlight.css" rel="stylesheet" type="text/css" media="all" />
|
||||
<script src="../assets/js/highlight.js"></script>
|
||||
|
||||
<script src="../release/go.js"></script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-1506307-5', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- non-fixed navbar -->
|
||||
<nav id="non-fixed-nav" class="navbar navbar-inverse navbar-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<div class="navheader-container">
|
||||
<div class="navheader-collapse" data-toggle="collapse" data-target="#navbar">
|
||||
<a id="toplogo" class="navbar-brand" href="../index.html">GoJS</a>
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="../index.html">Home</a></li>
|
||||
<li><a href="../learn/index.html">Learn</a></li>
|
||||
<li><a href="../samples/index.html">Samples</a></li>
|
||||
<li><a href="../intro/index.html">Intro</a></li>
|
||||
<li><a href="../api/index.html" target="api">API</a></li>
|
||||
<li><a href="https://www.nwoods.com/components/evalform.htm">Register</a></li>
|
||||
<li><a href="../download.html">Download</a></li>
|
||||
<li><a href="https://forum.nwoods.com/c/gojs">Forum</a></li>
|
||||
<li><a href="https://www.nwoods.com/contact.html" onclick="ga('send','event','Outbound Link','click','contact');">Contact</a></li>
|
||||
<li class="buy"><a href="https://www.nwoods.com/sales/index.html" onclick="ga('send','event','Outbound Link','click','buy');">Buy</a></li>
|
||||
<li class="activate"><a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a></li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div id="bannertop" class="jumbotron banner">
|
||||
<div class="container-fluid plr15">
|
||||
<h1><span>Get Started with GoJS</span></h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid learn-container">
|
||||
|
||||
<h2 id="GoJSTutorials">GoJS Tutorials</h2>
|
||||
<p>
|
||||
For video tutorials, see our <a href="https://www.nwoods.com/videos.html">YouTube videos</a>.
|
||||
For textual tutorials, read on.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>GoJS</b> is a JavaScript library for implementing interactive diagrams.
|
||||
This page will show you the essentials of using <b>GoJS</b>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Because <b>GoJS</b> is a JavaScript library that depends on HTML5 features,
|
||||
you will need to make sure that your page declares that it is an HTML5 document.
|
||||
And of course you need to load the library:
|
||||
</p>
|
||||
|
||||
<pre class="lang-html">
|
||||
<!DOCTYPE html> <!-- HTML5 document type -->
|
||||
<html>
|
||||
<head>
|
||||
<!-- use go-debug.js when developing and go.js when deploying -->
|
||||
<script src="go-debug.js"></script>
|
||||
. . .
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
You can download <b>GoJS</b> and all the documentation and samples from <a target="_blank" href="../download.html">here</a>.
|
||||
Alternatively you can link straight to a <b>GoJS</b> library provided by a
|
||||
<a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/CDN">CDN</a> such as:
|
||||
<pre class="lang-html"><script src="https://unpkg.com/gojs/release/go-debug.js"></script></pre>
|
||||
<p>
|
||||
Each <b>GoJS</b> diagram is contained in an HTML <code><div></code> element in your
|
||||
HTML page that you give an explicit size:
|
||||
</p>
|
||||
|
||||
<pre class="lang-html">
|
||||
<!-- The DIV for a Diagram needs an explicit size or else we will not see anything.
|
||||
In this case we also add a background color so we can see that area. -->
|
||||
<div id="myDiagramDiv"
|
||||
style="width:400px; height:150px; background-color: #DAE4E4;"></div>
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
In JavaScript code you pass the <code><div></code>'s <code>id</code> when making a Diagram:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv");
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Together, this creates an empty diagram:
|
||||
</p>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv" class="diagramStyling" style="width:400px; height:150px"></div>
|
||||
<script>
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram = $(go.Diagram, "myDiagramDiv");
|
||||
</script>
|
||||
|
||||
<p>
|
||||
Notice that <code>go</code> is the "namespace" in which all <b>GoJS</b> types reside.
|
||||
All code uses of <b>GoJS</b> classes such as Diagram or Node or Panel or Shape or TextBlock
|
||||
will be prefixed with "<code>go.</code>".
|
||||
</p>
|
||||
<p>
|
||||
This article will show you by example how to use <code>go.GraphObject.make</code> to build <b>GoJS</b> objects.
|
||||
For more detail, read <a href="../intro/buildingObjects.html">Building Objects in GoJS</a>.
|
||||
Using <code>$</code> as an abbreviation for <code>go.GraphObject.make</code>
|
||||
is so handy that we will assume its use from now on.
|
||||
If you use <code>$</code> for something else in your code,
|
||||
you can always pick a different short variable name,
|
||||
such as <code>$$</code> or <code>MAKE</code> or <code>GO</code>.
|
||||
</p>
|
||||
|
||||
<h2 id="DiagramsAndModels">Diagrams and Models</h2>
|
||||
|
||||
<p>
|
||||
The Nodes and Links of a Diagram are visualizations of data that is managed by a Model.
|
||||
<b>GoJS</b> has a model-view architecture,
|
||||
where Models hold the data (arrays of JavaScript objects) that describe nodes and links,
|
||||
and Diagrams act as views to visualize this data using actual Node and Link objects.
|
||||
Models, not Diagrams, are what you load and then save after editing.
|
||||
You add whatever properties you need for your app on the data objects in the model;
|
||||
you do not add properties to or modify the prototype of the Diagram and GraphObject classes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Here's an example of a Model and Diagram, followed by the actual diagram it generates:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv",
|
||||
{ // enable Ctrl-Z to undo and Ctrl-Y to redo
|
||||
"undoManager.isEnabled": true
|
||||
});
|
||||
|
||||
var myModel = $(go.Model);
|
||||
// for each object in this Array, the Diagram creates a Node to represent it
|
||||
myModel.nodeDataArray = [
|
||||
{ key: "Alpha" },
|
||||
{ key: "Beta" },
|
||||
{ key: "Gamma" }
|
||||
];
|
||||
myDiagram.model = myModel;
|
||||
</pre>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv2" class="diagramStyling" style="width:400px; height:150px"></div>
|
||||
<script>
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv2",
|
||||
{ // enable Ctrl-Z to undo and Ctrl-Y to redo
|
||||
"undoManager.isEnabled": true
|
||||
});
|
||||
|
||||
var myModel = $(go.Model);
|
||||
// for each object in this Array, the Diagram creates a Node to represent it
|
||||
myModel.nodeDataArray = [
|
||||
{ key: "Alpha" },
|
||||
{ key: "Beta" },
|
||||
{ key: "Gamma" }
|
||||
];
|
||||
myDiagram.model = myModel;
|
||||
</script>
|
||||
|
||||
<p>
|
||||
The diagram displays the three nodes that are in the model. Some interaction is already possible:
|
||||
</p>
|
||||
<ul>
|
||||
<li>Click and drag the background in the above diagram to pan the view.</li>
|
||||
<li>Click a node to select it, or press down on and drag a node to move it around.</li>
|
||||
<li>To create a selection box, click and hold on the background, then start dragging.</li>
|
||||
<li>Use CTRL-C and CTRL-V, or control-drag-and-drop, to make a copy of the selection.</li>
|
||||
<li>
|
||||
Press the Delete key to delete selected nodes.
|
||||
(Read about more <a href="../intro/commands.html">Keyboard Commands</a>.)
|
||||
</li>
|
||||
<li>
|
||||
On touch devices, press and hold to bring up a context menu.
|
||||
(Read about <a href="../intro/contextMenus.html">Context Menus</a>.)
|
||||
</li>
|
||||
<li>Since the undo manager was enabled, CTRL-Z and CTRL-Y will undo and redo moves and copies and deletions.</li>
|
||||
</ul>
|
||||
|
||||
<h2 id="StylingNodes">Styling Nodes</h2>
|
||||
|
||||
<p>
|
||||
Nodes are styled by creating templates consisting of GraphObjects and setting properties on those objects.
|
||||
To create a <a href="../intro/nodes.html">Node</a>, we have several building block classes at our disposal:
|
||||
</p>
|
||||
<ul>
|
||||
<li><a href="../intro/shapes.html">Shape</a>, to display pre-defined or custom geometry with colors</li>
|
||||
<li><a href="../intro/textblocks.html">TextBlock</a>, to display (potentially editable) text in various fonts</li>
|
||||
<li><a href="../intro/pictures.html">Picture</a>, to display images, including SVG files</li>
|
||||
<li>
|
||||
<a href="../intro/panels.html">Panel</a>, containers to hold a collection of other objects that
|
||||
can be positioned and sized in different manners according to the type of the Panel (like tables,
|
||||
vertical stacks, and stretching containers)
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
All of these building blocks are derived from the
|
||||
<a href="../api/symbols/GraphObject.html">GraphObject</a> abstract class,
|
||||
so we casually refer to them as GraphObjects or objects or elements.
|
||||
Note that a GraphObject is <em>not</em> an HTML DOM element, so much less overhead in
|
||||
creating or modifying such objects.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We want the model data properties to affect our Nodes, and this is done by way of data bindings.
|
||||
Data bindings allow us to change the appearance and behavior of GraphObjects in Nodes by automatically setting
|
||||
properties on those GraphObjects to values that are taken from the model data.
|
||||
The model data objects are plain JavaScript objects.
|
||||
You can choose to use whatever property names you like on the node data in the model.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The default Node template is simple: A Node which contains one TextBlock.
|
||||
There is a data binding between a TextBlock's <code>text</code> property and
|
||||
the model data's <code>key</code> property.
|
||||
In code, the template looks something like this:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node,
|
||||
$(go.TextBlock,
|
||||
// TextBlock.text is bound to Node.data.key
|
||||
new go.Binding("text", "key"))
|
||||
);
|
||||
</pre>
|
||||
<p>
|
||||
TextBlocks, Shapes, and Pictures are the primitive building blocks of <b>GoJS</b>.
|
||||
TextBlocks cannot contain images; Shapes cannot contain text.
|
||||
If you want your node to show some text, you must use a TextBlock.
|
||||
If you want to draw or fill some geometrical figures, you must use a Shape.
|
||||
</p>
|
||||
<p>
|
||||
More generally, the skeleton of a Node template will look something like this:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Vertical", // second argument of a Node (or any Panel) can be a Panel type
|
||||
/* set Node properties here */
|
||||
{ // the Node.location point will be at the center of each node
|
||||
locationSpot: go.Spot.Center
|
||||
},
|
||||
|
||||
/* add Bindings here */
|
||||
// example Node binding sets Node.location to the value of Node.data.loc
|
||||
new go.Binding("location", "loc"),
|
||||
|
||||
/* add GraphObjects contained within the Node */
|
||||
// this Shape will be vertically above the TextBlock
|
||||
$(go.Shape,
|
||||
"RoundedRectangle", // string argument can name a predefined figure
|
||||
{ /* set Shape properties here */ },
|
||||
// example Shape binding sets Shape.figure to the value of Node.data.fig
|
||||
new go.Binding("figure", "fig")),
|
||||
|
||||
$(go.TextBlock,
|
||||
"default text", // string argument can be initial text string
|
||||
{ /* set TextBlock properties here */ },
|
||||
// example TextBlock binding sets TextBlock.text to the value of Node.data.text
|
||||
new go.Binding("text"))
|
||||
);
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
The nesting of GraphObjects within Panels can be arbitrarily deep,
|
||||
and every class has its own unique set of properties to utilize,
|
||||
but this shows the general idea.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Now that we have seen how to make a Node template, let's see a live example.
|
||||
We will make a simple template commonly seen in organizational diagrams — an image next to a name.
|
||||
Consider the following Node template:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
A Node of "Horizontal" Panel type, meaning that its elements will be laid out horizontally side-by-side.
|
||||
It has two elements:
|
||||
<ul>
|
||||
<li>A Picture for the portrait, with the image source data bound</li>
|
||||
<li>A TextBlock for the name, with the text data bound</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<pre class="lang-js">
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv",
|
||||
{ // enable Ctrl-Z to undo and Ctrl-Y to redo
|
||||
"undoManager.isEnabled": true
|
||||
});
|
||||
|
||||
// define a simple Node template
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Horizontal",
|
||||
// the entire node will have a light-blue background
|
||||
{ background: "#44CCFF" },
|
||||
$(go.Picture,
|
||||
// Pictures should normally have an explicit width and height.
|
||||
// This picture has a red background, only visible when there is no source set
|
||||
// or when the image is partially transparent.
|
||||
{ margin: 10, width: 50, height: 50, background: "red" },
|
||||
// Picture.source is data bound to the "source" attribute of the model data
|
||||
new go.Binding("source")),
|
||||
$(go.TextBlock,
|
||||
"Default Text", // the initial value for TextBlock.text
|
||||
// some room around the text, a larger font, and a white stroke:
|
||||
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
||||
// TextBlock.text is data bound to the "name" property of the model data
|
||||
new go.Binding("text", "name"))
|
||||
);
|
||||
|
||||
var model = $(go.Model);
|
||||
model.nodeDataArray =
|
||||
[ // note that each node data object holds whatever properties it needs;
|
||||
// for this app we add the "name" and "source" properties
|
||||
{ name: "Don Meow", source: "cat1.png" },
|
||||
{ name: "Copricat", source: "cat2.png" },
|
||||
{ name: "Demeter", source: "cat3.png" },
|
||||
{ /* Empty node data */ }
|
||||
];
|
||||
myDiagram.model = model;
|
||||
</pre>
|
||||
|
||||
<p>That code produces this diagram:</p>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv3" class="diagramStyling" style="width:700px; height:200px"></div>
|
||||
<script>
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv3",
|
||||
{ // enable Ctrl-Z to undo and Ctrl-Y to redo
|
||||
"undoManager.isEnabled": true
|
||||
});
|
||||
|
||||
// define a simple Node template
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Horizontal",
|
||||
// the entire node will have a light-blue background
|
||||
{ background: "#44CCFF" },
|
||||
$(go.Picture,
|
||||
// Pictures should normally have an explicit width and height.
|
||||
// This picture has a red background, only visible when there is no source set
|
||||
// or when the image is partially transparent.
|
||||
{ margin: 10, width: 50, height: 50, background: "red" },
|
||||
// Picture.source is data bound to the "source" attribute of model data:
|
||||
new go.Binding("source")),
|
||||
$(go.TextBlock,
|
||||
"Default Text", // the initial value for TextBlock.text
|
||||
// some room around the text, a larger font, and a white stroke
|
||||
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
||||
// TextBlock.text is data bound to the "name" property of model data:
|
||||
new go.Binding("text", "name"))
|
||||
);
|
||||
|
||||
var model = $(go.Model);
|
||||
model.nodeDataArray =
|
||||
[ // note that each node data object holds whatever properties it needs;
|
||||
// for this app we add the "name" and "source" properties
|
||||
{ name: "Don Meow", source: "cat1.png" },
|
||||
{ name: "Copricat", source: "cat2.png" },
|
||||
{ name: "Demeter", source: "cat3.png" },
|
||||
{ /* Empty node data */ }
|
||||
];
|
||||
myDiagram.model = model;
|
||||
</script>
|
||||
|
||||
<p>
|
||||
We may want to show some "default" state when not all information is present,
|
||||
for instance when an image does not load or when a name is not known.
|
||||
The "empty" node data in this example is used to show that node templates can work
|
||||
perfectly well without any of the properties on the bound data.
|
||||
</p>
|
||||
|
||||
<h2 id="KindsOfNodes">Kinds of Models</h2>
|
||||
|
||||
<p>
|
||||
With a custom node template our diagram is becoming a pretty sight, but perhaps we want to show more.
|
||||
Perhaps we want an organizational chart to show that Don Meow is really the boss of a cat cartel.
|
||||
So we will create a complete organization chart diagram by adding some Links to show the relationship
|
||||
between individual nodes and a Layout to automatically position the nodes.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In order to get links into our diagram, the basic <code>Model</code> is not going to cut it.
|
||||
We are going to have to pick one of the other two models in <b>GoJS</b>, both of which support Links.
|
||||
These are <code>GraphLinksModel</code> and <code>TreeModel</code>.
|
||||
(Read more about models <a href="../intro/usingModels.html">here</a>.)
|
||||
</p>
|
||||
|
||||
<p>
|
||||
In GraphLinksModel, we have a <code>model.linkDataArray</code> in addition to the <code>model.nodeDataArray</code>.
|
||||
It holds an array of JavaScript objects, each describing a link by specifying the "to" and "from" node keys.
|
||||
Here's an example where node A links to node B and where node B links to node C:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var model = $(go.GraphLinksModel);
|
||||
model.nodeDataArray =
|
||||
[
|
||||
{ key: "A" },
|
||||
{ key: "B" },
|
||||
{ key: "C" }
|
||||
];
|
||||
model.linkDataArray =
|
||||
[
|
||||
{ from: "A", to: "B" },
|
||||
{ from: "B", to: "C" }
|
||||
];
|
||||
myDiagram.model = model;
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
A GraphLinksModel allows you to have any number of links between nodes, going in any direction.
|
||||
There could be ten links running from A to B, and three more running the opposite way, from B to A.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
A TreeModel works a little differently.
|
||||
Instead of maintaining a separate array of link data,
|
||||
the links in a tree model are created by specifying a "parent" for a node data.
|
||||
Links are then created from this association.
|
||||
Here's the same example done as a TreeModel, with node A linking to node B and node B linking to node C:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var model = $(go.TreeModel);
|
||||
model.nodeDataArray =
|
||||
[
|
||||
{ key: "A" },
|
||||
{ key: "B", parent: "A" },
|
||||
{ key: "C", parent: "B" }
|
||||
];
|
||||
myDiagram.model = model;
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
TreeModel is simpler than GraphLinksModel, but it cannot make arbitrary link relationships,
|
||||
such as multiple links between the same two nodes, or having multiple parents.
|
||||
Our organizational diagram is a simple hierarchical tree-like structure,
|
||||
so we will choose TreeModel for this example.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
First, we will complete the data by adding a few more nodes, using a TreeModel,
|
||||
and specifying keys and parents in the data.
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv",
|
||||
{ "undoManager.isEnabled": true });
|
||||
|
||||
// the template we defined earlier
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Horizontal",
|
||||
{ background: "#44CCFF" },
|
||||
$(go.Picture,
|
||||
{ margin: 10, width: 50, height: 50, background: "red" },
|
||||
new go.Binding("source")),
|
||||
$(go.TextBlock, "Default Text",
|
||||
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
||||
new go.Binding("text", "name"))
|
||||
);
|
||||
|
||||
var model = $(go.TreeModel);
|
||||
model.nodeDataArray =
|
||||
[ // the "key" and "parent" property names are required,
|
||||
// but you can add whatever data properties you need for your app
|
||||
{ key: "1", name: "Don Meow", source: "cat1.png" },
|
||||
{ key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
|
||||
{ key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
|
||||
{ key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
|
||||
{ key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
|
||||
{ key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" }
|
||||
];
|
||||
myDiagram.model = model;
|
||||
</pre>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv4" class="diagramStyling" style="width:700px; height:200px"></div>
|
||||
<script>
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv4",
|
||||
{ "undoManager.isEnabled": true });
|
||||
|
||||
// the template we defined earlier
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Horizontal",
|
||||
{ background: "#44CCFF" },
|
||||
$(go.Picture,
|
||||
{ margin: 10, width: 50, height: 50, background: "red" },
|
||||
new go.Binding("source")),
|
||||
$(go.TextBlock, "Default Text",
|
||||
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
||||
new go.Binding("text", "name"))
|
||||
);
|
||||
|
||||
var model = $(go.TreeModel);
|
||||
model.nodeDataArray =
|
||||
[
|
||||
{ key: "1", name: "Don Meow", source: "cat1.png" },
|
||||
{ key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
|
||||
{ key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
|
||||
{ key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
|
||||
{ key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
|
||||
{ key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" }
|
||||
];
|
||||
myDiagram.model = model;
|
||||
</script>
|
||||
|
||||
<h2 id="DiagramLayouts">Diagram Layouts</h2>
|
||||
|
||||
<p>
|
||||
As you can see the TreeModel automatically creates the necessary Links to associate the Nodes,
|
||||
but it's hard to tell whose parent is who.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Diagrams have a default layout which takes all nodes that do not have a location and gives them locations,
|
||||
arranging them in a grid.
|
||||
We could explicitly give each of our nodes a location to sort out this organizational mess,
|
||||
but as an easier solution in our case, we will use a layout that gives us good locations automatically.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
We want to show a hierarchy, and are already using a TreeModel, so the most natural layout choice is TreeLayout.
|
||||
TreeLayout defaults to flowing from left to right, so to get it to flow from top to bottom
|
||||
(as is common in organizational diagrams), we will set the <code>angle</code> property to 90.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Using layouts in <b>GoJS</b> is usually simple.
|
||||
Each kind of layout has a number of properties that affect the results.
|
||||
There are samples for each layout (like <a href="../samples/tLayout.html">TreeLayout Demo</a>)
|
||||
that showcase its properties.
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
// define a TreeLayout that flows from top to bottom
|
||||
myDiagram.layout =
|
||||
$(go.TreeLayout,
|
||||
{ angle: 90, layerSpacing: 35 });
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
<b>GoJS</b> has several other layouts, which you can read about <a href="../intro/layouts.html">here</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
Adding the layout to the diagram and model so far, we can see our results:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv",
|
||||
{
|
||||
"undoManager.isEnabled": true,
|
||||
layout: $(go.TreeLayout, // specify a Diagram.layout that arranges trees
|
||||
{ angle: 90, layerSpacing: 35 })
|
||||
});
|
||||
|
||||
// the template we defined earlier
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Horizontal",
|
||||
{ background: "#44CCFF" },
|
||||
$(go.Picture,
|
||||
{ margin: 10, width: 50, height: 50, background: "red" },
|
||||
new go.Binding("source")),
|
||||
$(go.TextBlock, "Default Text",
|
||||
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
||||
new go.Binding("text", "name"))
|
||||
);
|
||||
|
||||
var model = $(go.TreeModel);
|
||||
model.nodeDataArray =
|
||||
[
|
||||
{ key: "1", name: "Don Meow", source: "cat1.png" },
|
||||
{ key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
|
||||
{ key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
|
||||
{ key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
|
||||
{ key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
|
||||
{ key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" }
|
||||
];
|
||||
myDiagram.model = model;
|
||||
</pre>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv5" class="diagramStyling" style="width:700px; height:400px"></div>
|
||||
<script>
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv5",
|
||||
{
|
||||
"undoManager.isEnabled": true,
|
||||
layout: $(go.TreeLayout, // specify a Diagram.layout that arranges trees
|
||||
{ angle: 90, layerSpacing: 35 })
|
||||
});
|
||||
|
||||
// the template we defined earlier
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Horizontal",
|
||||
{ background: "#44CCFF" },
|
||||
$(go.Picture,
|
||||
{ margin: 10, width: 50, height: 50, background: "red" },
|
||||
new go.Binding("source")),
|
||||
$(go.TextBlock, "Default Text",
|
||||
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
||||
new go.Binding("text", "name"))
|
||||
);
|
||||
|
||||
var model = $(go.TreeModel);
|
||||
model.nodeDataArray =
|
||||
[
|
||||
{ key: "1", name: "Don Meow", source: "cat1.png" },
|
||||
{ key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
|
||||
{ key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
|
||||
{ key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
|
||||
{ key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
|
||||
{ key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" }
|
||||
];
|
||||
myDiagram.model = model;
|
||||
</script>
|
||||
|
||||
<p>
|
||||
Our diagram is starting to look like a proper organization chart, but we could do better with the links.
|
||||
</p>
|
||||
|
||||
<h2 id="LinkTemplates">Link Templates</h2>
|
||||
|
||||
<p>
|
||||
We will construct a new Link template that will better suit our wide, boxy nodes.
|
||||
A <a href="../intro/links.html">Link</a> is a different kind of Part, not like a Node.
|
||||
The main element of a Link is the Link's shape,
|
||||
and must be a Shape that will have its geometry computed dynamically by <b>GoJS</b>.
|
||||
Our link is going to consist of just this shape,
|
||||
with its stroke a little thicker than normal and dark gray instead of black.
|
||||
Unlike the default link template we will not have an arrowhead.
|
||||
And we will change the Link <code>routing</code> property from Normal to Orthogonal,
|
||||
and give it a <code>corner</code> value so that right-angle turns are rounded.
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
// define a Link template that routes orthogonally, with no arrowhead
|
||||
myDiagram.linkTemplate =
|
||||
$(go.Link,
|
||||
// default routing is go.Link.Normal
|
||||
// default corner is 0
|
||||
{ routing: go.Link.Orthogonal, corner: 5 },
|
||||
// the link path, a Shape
|
||||
$(go.Shape, { strokeWidth: 3, stroke: "#555" })
|
||||
|
||||
// if we wanted an arrowhead we would also add another Shape with toArrow defined:
|
||||
// $(go.Shape, { toArrow: "Standard", stroke: null }
|
||||
);
|
||||
</pre>
|
||||
|
||||
<p>
|
||||
Combining our Link template with our Node template, TreeModel, and TreeLayout,
|
||||
we finally have a full organization diagram.
|
||||
The complete code is repeated below, and the resulting diagram follows:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var $ = go.GraphObject.make;
|
||||
|
||||
var myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv",
|
||||
{
|
||||
"undoManager.isEnabled": true,
|
||||
layout: $(go.TreeLayout,
|
||||
{ angle: 90, layerSpacing: 35 })
|
||||
});
|
||||
|
||||
// the template we defined earlier
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Horizontal",
|
||||
{ background: "#44CCFF" },
|
||||
$(go.Picture,
|
||||
{ margin: 10, width: 50, height: 50, background: "red" },
|
||||
new go.Binding("source")),
|
||||
$(go.TextBlock, "Default Text",
|
||||
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
||||
new go.Binding("text", "name"))
|
||||
);
|
||||
|
||||
// define a Link template that routes orthogonally, with no arrowhead
|
||||
myDiagram.linkTemplate =
|
||||
$(go.Link,
|
||||
{ routing: go.Link.Orthogonal, corner: 5 },
|
||||
$(go.Shape, // the link's path shape
|
||||
{ strokeWidth: 3, stroke: "#555" }));
|
||||
|
||||
var model = $(go.TreeModel);
|
||||
model.nodeDataArray =
|
||||
[
|
||||
{ key: "1", name: "Don Meow", source: "cat1.png" },
|
||||
{ key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
|
||||
{ key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
|
||||
{ key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
|
||||
{ key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
|
||||
{ key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" }
|
||||
];
|
||||
myDiagram.model = model;
|
||||
</pre>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv6" class="diagramStyling" style="width:700px; height:400px"></div>
|
||||
<script>
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv6",
|
||||
{
|
||||
"undoManager.isEnabled": true, // enable Ctrl-Z to undo and Ctrl-Y to redo
|
||||
layout: $(go.TreeLayout,
|
||||
{ angle: 90, layerSpacing: 35 })
|
||||
});
|
||||
|
||||
// the template we defined earlier
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Horizontal",
|
||||
{ background: "#44CCFF" },
|
||||
$(go.Picture,
|
||||
{ margin: 10, width: 50, height: 50, background: "red" },
|
||||
new go.Binding("source")),
|
||||
$(go.TextBlock, "Default Text",
|
||||
{ margin: 12, stroke: "white", font: "bold 16px sans-serif" },
|
||||
new go.Binding("text", "name"))
|
||||
);
|
||||
|
||||
// define a Link template that routes orthogonally, with no arrowhead
|
||||
myDiagram.linkTemplate =
|
||||
$(go.Link,
|
||||
{ routing: go.Link.Orthogonal, corner: 5 },
|
||||
$(go.Shape, { strokeWidth: 3, stroke: "#555" })); // the link shape
|
||||
|
||||
var model = $(go.TreeModel);
|
||||
model.nodeDataArray =
|
||||
[
|
||||
{ key: "1", name: "Don Meow", source: "cat1.png" },
|
||||
{ key: "2", parent: "1", name: "Demeter", source: "cat2.png" },
|
||||
{ key: "3", parent: "1", name: "Copricat", source: "cat3.png" },
|
||||
{ key: "4", parent: "3", name: "Jellylorum", source: "cat4.png" },
|
||||
{ key: "5", parent: "3", name: "Alonzo", source: "cat5.png" },
|
||||
{ key: "6", parent: "2", name: "Munkustrap", source: "cat6.png" }
|
||||
];
|
||||
myDiagram.model = model;
|
||||
</script>
|
||||
|
||||
<h2 id="LearnMore">Learn More</h2>
|
||||
<p>
|
||||
You may want to read more tutorials, such as the <a href="graphObject.html">GraphObject Manipulation</a> tutorial
|
||||
and the <a href="interactivity.html">Interactivity</a> tutorial.
|
||||
You can also watch tutorials on <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">YouTube</a>.
|
||||
</p>
|
||||
<p>
|
||||
Also consider looking at the <a href="../samples/index.html">samples</a> to see some of the diagrams possible with <b>GoJS</b>,
|
||||
or read the <a href="../intro/index.html">technical introduction</a> to get
|
||||
an in-depth look at the components of <b>GoJS</b>.
|
||||
</p>
|
||||
|
||||
<p class="footer">
|
||||
GoJS ® by Northwoods Software. Copyright © 1998-2020 <a href="https://www.nwoods.com" target="_blank">Northwoods Software</a> ®
|
||||
</p>
|
||||
|
||||
</div> <!-- end container-fluid -->
|
||||
<div class="banner" id="bannerbottom">
|
||||
<!-- text in banner-->
|
||||
</div>
|
||||
<script src="../assets/js/jquery.min.js"></script>
|
||||
<script async src="../assets/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,592 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="Tutorial for interactivity with GoJS." />
|
||||
<title>GoJS Interactivity</title>
|
||||
<!-- Copyright 1998-2020 by Northwoods Software Corporation. -->
|
||||
<link href="../assets/css/bootstrap.min.css" rel="stylesheet" >
|
||||
<!-- custom CSS after bootstrap -->
|
||||
<link href="../assets/css/main.css" rel="stylesheet" type="text/css"/>
|
||||
<link href="../assets/css/highlight.css" rel="stylesheet" type="text/css" media="all" />
|
||||
<script src="../assets/js/highlight.js"></script>
|
||||
|
||||
<script src="../release/go.js"></script>
|
||||
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
|
||||
|
||||
ga('create', 'UA-1506307-5', 'auto');
|
||||
ga('send', 'pageview');
|
||||
</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- non-fixed navbar -->
|
||||
<nav id="non-fixed-nav" class="navbar navbar-inverse navbar-top">
|
||||
<div class="container-fluid">
|
||||
<div class="navbar-header">
|
||||
<div class="navheader-container">
|
||||
<div class="navheader-collapse" data-toggle="collapse" data-target="#navbar">
|
||||
<a id="toplogo" class="navbar-brand" href="../index.html">GoJS</a>
|
||||
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav navbar-right">
|
||||
<li><a href="../index.html">Home</a></li>
|
||||
<li><a href="../learn/index.html">Learn</a></li>
|
||||
<li><a href="../samples/index.html">Samples</a></li>
|
||||
<li><a href="../intro/index.html">Intro</a></li>
|
||||
<li><a href="../api/index.html" target="api">API</a></li>
|
||||
<li><a href="https://www.nwoods.com/components/evalform.htm">Register</a></li>
|
||||
<li><a href="../download.html">Download</a></li>
|
||||
<li><a href="https://forum.nwoods.com/c/gojs">Forum</a></li>
|
||||
<li><a href="https://www.nwoods.com/contact.html" onclick="ga('send','event','Outbound Link','click','contact');">Contact</a></li>
|
||||
<li class="buy"><a href="https://www.nwoods.com/sales/index.html" onclick="ga('send','event','Outbound Link','click','buy');">Buy</a></li>
|
||||
<li class="activate"><a href="https://www.nwoods.com/app/activate.aspx?sku=gojs">Activate</a></li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div id="bannertop" class="jumbotron banner">
|
||||
<div class="container-fluid plr15">
|
||||
<h1><span>GoJS Interactivity</span></h1>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid learn-container">
|
||||
|
||||
<h2 id="BuiltinGoJSInteractivity">Built-in GoJS Interactivity</h2>
|
||||
|
||||
<p>
|
||||
<b>GoJS</b> implements a number of common editing operations, such as manipulating parts
|
||||
(moving, adding, copying, cutting, and deleting).
|
||||
These editing abilities are accessible via mouse (or touch) and keyboard by default,
|
||||
and can also be invoked programmatically in JavaScript.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The following Diagram defines a node template and has four nodes in its model:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var $ = go.GraphObject.make;
|
||||
myDiagram =
|
||||
$(go.Diagram, "myDiagramDiv",
|
||||
{ "undoManager.isEnabled": true });
|
||||
|
||||
// define a simple Node template
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape, "Rectangle",
|
||||
// don't draw any outline
|
||||
{ stroke: null },
|
||||
// the Shape.fill comes from the Node.data.color property
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
// leave some space around larger-than-normal text
|
||||
{ margin: 6, font: "18px sans-serif" },
|
||||
// the TextBlock.text comes from the Node.data.key property
|
||||
new go.Binding("text", "key"))
|
||||
);
|
||||
|
||||
myDiagram.model = new go.GraphLinksModel(
|
||||
[
|
||||
{ key: "Alpha", color: "lightblue" },
|
||||
{ key: "Beta", color: "orange" },
|
||||
{ key: "Gamma", color: "lightgreen" },
|
||||
{ key: "Delta", color: "pink" }
|
||||
]);
|
||||
</pre>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv" class="diagramStyling" style="width:700px; height:150px"></div>
|
||||
<script>
|
||||
function setupDiagram(divname) {
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, divname,
|
||||
{ "undoManager.isEnabled": true });
|
||||
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape, "Rectangle",
|
||||
{ stroke: null },
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
{ margin: 6, font: "18px sans-serif" },
|
||||
new go.Binding("text", "key"))
|
||||
);
|
||||
|
||||
myDiagram.model = new go.GraphLinksModel(
|
||||
[
|
||||
{ key: "Alpha", color: "lightblue" },
|
||||
{ key: "Beta", color: "orange" },
|
||||
{ key: "Gamma", color: "lightgreen" },
|
||||
{ key: "Delta", color: "pink" }
|
||||
]);
|
||||
return myDiagram;
|
||||
}
|
||||
setupDiagram("myDiagramDiv")
|
||||
</script>
|
||||
|
||||
<p>
|
||||
Out of the box, several interactions are available:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
Click a node to select it.
|
||||
Press and drag on a node to move it around.
|
||||
Or press and drag in the diagram background to pan the entire Diagram.
|
||||
</li>
|
||||
<li>
|
||||
Common keyboard shortcuts such as <code>CTRL-C</code>, <code>CTRL-V</code>, <code>CTRL-X</code>
|
||||
will copy, paste, and cut diagram parts, respectively.
|
||||
</li>
|
||||
<li>
|
||||
Drag-and-hold allows you to create a selection box for selecting multiple nodes.
|
||||
CTRL-clicking on nodes allows you to toggle their selection.
|
||||
</li>
|
||||
<li>
|
||||
Since the Diagram's undoManager was enabled, <code>CTRL-Z</code> and <code>CTRL-Y</code> will undo and redo operations.
|
||||
Panning (scrolling) and selection are not considered undoable operations.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
By setting a few properties you can expose more interaction to a user:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, divname,
|
||||
{
|
||||
// allow double-click in background to create a new node
|
||||
"clickCreatingTool.archetypeNodeData": { key: "Node", color: "white" },
|
||||
// allow Ctrl-G to group
|
||||
"commandHandler.archetypeGroupData": { text: "Group", isGroup: true },
|
||||
// have mouse wheel events zoom in and out instead of scroll up and down
|
||||
"toolManager.mouseWheelBehavior": go.ToolManager.WheelZoom,
|
||||
"undoManager.isEnabled": true // enable undo & redo
|
||||
});
|
||||
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape, "Rectangle",
|
||||
{ stroke: null },
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
{ margin: 6, font: "18px sans-serif", editable: true },
|
||||
new go.Binding("text", "key"))
|
||||
);
|
||||
|
||||
// allow CTRL-SHIFT-G to ungroup a selected Group
|
||||
myDiagram.groupTemplate.ungroupable = true;
|
||||
|
||||
myDiagram.model = new go.GraphLinksModel(
|
||||
[
|
||||
{ key: "Alpha", color: "lightblue" },
|
||||
{ key: "Beta", color: "orange" },
|
||||
{ key: "Gamma", color: "lightgreen", group: "Group1" },
|
||||
{ key: "Delta", color: "pink", group: "Group1" },
|
||||
{ key: "Group1", isGroup: true }
|
||||
]);
|
||||
</pre>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv2" class="diagramStyling" style="width:700px; height:150px"></div>
|
||||
<script>
|
||||
function setupDiagram(divname) {
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, divname,
|
||||
{
|
||||
// allow double-click in background to create a new node
|
||||
"clickCreatingTool.archetypeNodeData": { key: "Node", color: "white" },
|
||||
// allow Ctrl-G to group
|
||||
"commandHandler.archetypeGroupData": { text: "Group", isGroup: true },
|
||||
// have mouse wheel events zoom in and out instead of scroll up and down
|
||||
"toolManager.mouseWheelBehavior": go.ToolManager.WheelZoom,
|
||||
"undoManager.isEnabled": true // enable undo & redo
|
||||
});
|
||||
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape, "Rectangle",
|
||||
{ stroke: null },
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
{ margin: 6, font: "18px sans-serif", editable: true },
|
||||
new go.Binding("text", "key"))
|
||||
);
|
||||
|
||||
// allow CTRL-SHIFT-G to ungroup a selected Group
|
||||
myDiagram.groupTemplate.ungroupable = true;
|
||||
|
||||
myDiagram.model = new go.GraphLinksModel(
|
||||
[
|
||||
{ key: "Alpha", color: "lightblue" },
|
||||
{ key: "Beta", color: "orange" },
|
||||
{ key: "Gamma", color: "lightgreen", group: "Group1" },
|
||||
{ key: "Delta", color: "pink", group: "Group1" },
|
||||
{ key: "Group1", isGroup: true }
|
||||
]);
|
||||
return myDiagram;
|
||||
}
|
||||
setupDiagram("myDiagramDiv2")
|
||||
</script>
|
||||
|
||||
<p>
|
||||
<ul>
|
||||
<li>
|
||||
<code>ClickCreatingTool.archetypeNodeData</code> allows a double-click in the background to create
|
||||
a new node with the specified data.
|
||||
</li>
|
||||
<li>
|
||||
<code>CommandHandler.archetypeGroupData</code> allows <code>CTRL-G</code> to group a selection of nodes.
|
||||
</li>
|
||||
<li>
|
||||
<code>Group.ungroupable</code> allows <code>CTRL-SHIFT-G</code> to ungroup a selected group.
|
||||
</li>
|
||||
<li>
|
||||
<code>ToolManager.mouseWheelBehavior</code> allows the mouse wheel to zoom instead of scroll by default.
|
||||
You can toggle this property by clicking on the mouse-wheel.
|
||||
On touch devices, pinch-zooming is enabled by default.
|
||||
</li>
|
||||
<li>
|
||||
<code>TextBlock.editable</code> in the <code>TextBlock</code> definition allows the text to be edited in place.
|
||||
Select a node and then click on the text, or press F2, to begin text editing.
|
||||
Click anywhere else on the diagram or press <code>Tab</code> to finish editing text.
|
||||
</li>
|
||||
</ul>
|
||||
</p>
|
||||
|
||||
<p>
|
||||
These interactions (and more!) are all present in the <a href="../samples/basic.html">basic.html sample</a>.
|
||||
Be sure to also see the <a href="../intro/commands.html">Intro page on GoJS commands</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You can disable portions of Diagram interactivity with several properties,
|
||||
depending on what you want to allow users to do.
|
||||
See the <a href="../intro/permissions.html">Intro page on GoJS permissions</a> for more.
|
||||
</p>
|
||||
|
||||
<h2 id="ContextMenus">Context Menus</h2>
|
||||
|
||||
<p>
|
||||
<b>GoJS</b> provides a mechanism for you to define context menus for any object or for the Diagram itself.
|
||||
In the example below, two context menus are defined, one on the Node template (with one button) and
|
||||
one on the Diagram (with two buttons).
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, divname,
|
||||
{ "undoManager.isEnabled": true });
|
||||
|
||||
// this function is called when the context menu button is clicked
|
||||
function nodeClicked(e, obj) {
|
||||
alert('node ' + obj.part.data.key + ' was clicked');
|
||||
}
|
||||
|
||||
// defines a context menu to be referenced in the node template
|
||||
var contextMenuTemplate =
|
||||
$(go.Adornment, "Vertical",
|
||||
$("ContextMenuButton",
|
||||
$(go.TextBlock, "Click me!"),
|
||||
{ click: nodeClicked })
|
||||
// more ContextMenuButtons would go here
|
||||
);
|
||||
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
{ contextMenu: contextMenuTemplate }, // set the context menu
|
||||
$(go.Shape, "Rectangle",
|
||||
{ stroke: null },
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
{ margin: 6, font: "18px sans-serif" },
|
||||
new go.Binding("text", "key"))
|
||||
);
|
||||
|
||||
// this function alerts the current number of nodes in the Diagram
|
||||
function countNodes(e, obj) {
|
||||
alert('there are ' + e.diagram.nodes.count + ' nodes');
|
||||
}
|
||||
|
||||
// this function creates a new node and inserts it at the last event's point
|
||||
function addNode(e, obj) {
|
||||
var data = { key: "Node", color: "white" };
|
||||
e.diagram.model.addNodeData(data);
|
||||
var node = e.diagram.findPartForData(data);
|
||||
node.location = e.diagram.lastInput.documentPoint;
|
||||
}
|
||||
|
||||
myDiagram.contextMenu =
|
||||
$(go.Adornment, "Vertical",
|
||||
$("ContextMenuButton",
|
||||
$(go.TextBlock, "Count Nodes"),
|
||||
{ click: countNodes }),
|
||||
$("ContextMenuButton",
|
||||
$(go.TextBlock, "Add Node"),
|
||||
{ click: addNode })
|
||||
// more ContextMenuButtons would go here
|
||||
);
|
||||
|
||||
myDiagram.model = new go.GraphLinksModel(
|
||||
[
|
||||
{ key: "Alpha", color: "lightblue" },
|
||||
{ key: "Beta", color: "orange" }
|
||||
]);
|
||||
return myDiagram;
|
||||
</pre>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv3" class="diagramStyling" style="width:700px; height:150px"></div>
|
||||
<script>
|
||||
function setupDiagram(divname) {
|
||||
var $ = go.GraphObject.make;
|
||||
var myDiagram =
|
||||
$(go.Diagram, divname,
|
||||
{ "undoManager.isEnabled": true });
|
||||
|
||||
// this function is called when the context menu button is clicked
|
||||
function nodeClicked(e, obj) {
|
||||
alert('node ' + obj.part.data.key + ' was clicked');
|
||||
}
|
||||
|
||||
// defines a context menu to be referenced in the node template
|
||||
var contextMenuTemplate =
|
||||
$(go.Adornment, "Vertical",
|
||||
$("ContextMenuButton",
|
||||
$(go.TextBlock, "Click me!"),
|
||||
{ click: nodeClicked })
|
||||
// more ContextMenuButtons would go here
|
||||
);
|
||||
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
{ contextMenu: contextMenuTemplate }, // set the context menu
|
||||
$(go.Shape, "Rectangle",
|
||||
{ stroke: null },
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
{ margin: 6, font: "18px sans-serif" },
|
||||
new go.Binding("text", "key"))
|
||||
);
|
||||
|
||||
// this function alerts the current number of nodes in the Diagram
|
||||
function countNodes(e, obj) {
|
||||
alert('there are ' + e.diagram.nodes.count + ' nodes');
|
||||
}
|
||||
|
||||
// this function creates a new node and inserts it at the last event's point
|
||||
function addNode(e, obj) {
|
||||
var data = { key: "Node", color: "white" };
|
||||
e.diagram.model.addNodeData(data);
|
||||
var node = e.diagram.findPartForData(data);
|
||||
node.location = e.diagram.lastInput.documentPoint;
|
||||
}
|
||||
|
||||
myDiagram.contextMenu =
|
||||
$(go.Adornment, "Vertical",
|
||||
$("ContextMenuButton",
|
||||
$(go.TextBlock, "Count Nodes"),
|
||||
{ click: countNodes }),
|
||||
$("ContextMenuButton",
|
||||
$(go.TextBlock, "Add Node"),
|
||||
{ click: addNode })
|
||||
// more ContextMenuButtons would go here
|
||||
);
|
||||
|
||||
myDiagram.model = new go.GraphLinksModel(
|
||||
[
|
||||
{ key: "Alpha", color: "lightblue" },
|
||||
{ key: "Beta", color: "orange" }
|
||||
]);
|
||||
return myDiagram;
|
||||
}
|
||||
setupDiagram("myDiagramDiv3")
|
||||
</script>
|
||||
|
||||
<p>
|
||||
If you right-click (or long-tap on a touch device) on a Node or the Diagram, you will see the <b>GoJS</b> context menu
|
||||
appear with the defined options.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
The <a href="../samples/basic.html">basic.html sample</a> contains more complex context menu examples.
|
||||
See the <a href="../intro/contextmenus.html">Intro page on GoJS context menus</a> for more.
|
||||
</p>
|
||||
|
||||
<h2 id="LinkInteractions">Link interactions</h2>
|
||||
|
||||
<p>
|
||||
<b>GoJS</b> lets users draw new links and re-link existing links by dragging out from a port or
|
||||
selecting a link and dragging its handles.
|
||||
To enable these tools, some properties need to be set:
|
||||
</p>
|
||||
|
||||
<pre class="lang-js">
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape, "Rectangle",
|
||||
{
|
||||
stroke: null,
|
||||
portId: "",
|
||||
cursor: "pointer",
|
||||
fromLinkable: true, fromLinkableSelfNode: true, fromLinkableDuplicates: true,
|
||||
toLinkable: true, toLinkableSelfNode: true, toLinkableDuplicates: true
|
||||
},
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
{ margin: 6, font: "18px sans-serif" },
|
||||
new go.Binding("text", "key"))
|
||||
);
|
||||
|
||||
myDiagram.linkTemplate =
|
||||
$(go.Link,
|
||||
{
|
||||
// allow the user to relink existing links:
|
||||
relinkableFrom: true, relinkableTo: true,
|
||||
// draw the link path shorter than normal,
|
||||
// so that it does not interfere with the appearance of the arrowhead
|
||||
toShortLength: 2
|
||||
},
|
||||
$(go.Shape,
|
||||
{ strokeWidth: 2 }),
|
||||
$(go.Shape,
|
||||
{ toArrow: "Standard", stroke: null })
|
||||
);
|
||||
|
||||
myDiagram.model = new go.GraphLinksModel(
|
||||
[
|
||||
{ key: "Alpha", color: "lightblue" },
|
||||
{ key: "Beta", color: "orange" },
|
||||
{ key: "Gamma", color: "lightgreen" },
|
||||
{ key: "Delta", color: "pink" }
|
||||
],
|
||||
[
|
||||
{ from: 'Alpha', to: 'Beta' },
|
||||
{ from: 'Alpha', to: 'Delta' },
|
||||
]
|
||||
);
|
||||
</pre>
|
||||
|
||||
<!-- LIVE -->
|
||||
<div id="myDiagramDiv4" class="diagramStyling" style="width:700px; height:150px"></div>
|
||||
<script>
|
||||
function setupDiagram(divname) {
|
||||
var $ = go.GraphObject.make;
|
||||
|
||||
var myDiagram =
|
||||
$(go.Diagram, divname,
|
||||
{ "undoManager.isEnabled": true });
|
||||
|
||||
myDiagram.nodeTemplate =
|
||||
$(go.Node, "Auto",
|
||||
$(go.Shape, "Rectangle",
|
||||
{
|
||||
stroke: null,
|
||||
portId: "",
|
||||
cursor: "pointer",
|
||||
fromLinkable: true, fromLinkableSelfNode: true, fromLinkableDuplicates: true,
|
||||
toLinkable: true, toLinkableSelfNode: true, toLinkableDuplicates: true
|
||||
},
|
||||
new go.Binding("fill", "color")),
|
||||
$(go.TextBlock,
|
||||
{ margin: 10, font: "18px sans-serif" },
|
||||
new go.Binding("text", "key"))
|
||||
);
|
||||
|
||||
myDiagram.linkTemplate =
|
||||
$(go.Link,
|
||||
{
|
||||
// allow the user to relink existing links:
|
||||
relinkableFrom: true, relinkableTo: true,
|
||||
// draw the link path shorter than normal,
|
||||
// so that it does not interfere with the appearance of the arrowhead
|
||||
toShortLength: 2
|
||||
},
|
||||
$(go.Shape,
|
||||
{ strokeWidth: 2 }),
|
||||
$(go.Shape,
|
||||
{ toArrow: "Standard", stroke: null })
|
||||
);
|
||||
|
||||
myDiagram.model = new go.GraphLinksModel(
|
||||
[
|
||||
{ key: "Alpha", color: "lightblue" },
|
||||
{ key: "Beta", color: "orange" },
|
||||
{ key: "Gamma", color: "lightgreen" },
|
||||
{ key: "Delta", color: "pink" }
|
||||
],
|
||||
[
|
||||
{ from: 'Alpha', to: 'Beta' },
|
||||
{ from: 'Alpha', to: 'Delta' },
|
||||
]);
|
||||
return myDiagram;
|
||||
}
|
||||
setupDiagram("myDiagramDiv4")
|
||||
</script>
|
||||
|
||||
<p>
|
||||
In the above example:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
The <code>Shape</code> has its <code>portId</code> set to make it the port instead of the entire node.
|
||||
Then several <code>...linkable</code> properties are set, allowing each node to link to itself and others.
|
||||
</li>
|
||||
<li>
|
||||
To create a new link to another node, drag from the port (the edge of the Shape that is not
|
||||
behind the TextBlock) to any node, including itself.
|
||||
</li>
|
||||
<li>
|
||||
In the link template, <code>relinkable...</code> properties are set, so that when the link is selected,
|
||||
it shows handles that can be dragged in order to reconnect the link with a different node.
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<p>
|
||||
<b>GoJS</b> allows linking and re-linking to abide by custom criteria in which source and destination nodes are valid.
|
||||
You can read about this in the <a href="../intro/validation.html">Intro page on Validation</a>.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
<b>GoJS</b> links have many interesting properties that are covered in depth in the
|
||||
<a href="../intro/links.html">Intro page on Links</a> and on the following pages.
|
||||
</p>
|
||||
|
||||
<p>
|
||||
You may want to read more tutorials, such as the <a href="index.html">Learn GoJS</a> tutorial
|
||||
and the <a href="graphObject.html">GraphObject Manipulation</a> tutorial
|
||||
You can also watch tutorials on <a href="https://www.youtube.com/channel/UC9We8EoX596-6XFjJDtZIDg">YouTube</a>.
|
||||
</p>
|
||||
|
||||
<p class="footer">
|
||||
GoJS ® by Northwoods Software. Copyright © 1998-2020 <a href="https://www.nwoods.com" target="_blank">Northwoods Software</a> ®
|
||||
</p>
|
||||
</div> <!-- end main -->
|
||||
<div class="banner" id="bannerbottom">
|
||||
<!-- text in banner-->
|
||||
</div>
|
||||
<script src="../assets/js/jquery.min.js"></script>
|
||||
<script async src="../assets/js/bootstrap.min.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,190 @@
|
||||
# KodExplorer
|
||||
|
||||
> ## Update to kodbox: [https://github.com/kalcaddle/kodbox](https://github.com/kalcaddle/kodbox)
|
||||
> [Download](https://kodcloud.com/download/) | [Demo](https://demo.kodcloud.com/)
|
||||
> *It is recommended to use a new design upgrade product:kodbox*
|
||||
> *该项目处于维护阶段,不再开发新功能.推荐使用全新设计升级产品kodbox*
|
||||
|
||||
----
|
||||
|
||||
|
||||
[](http://kodcloud.com) [](http://kodcloud.com) [](https://github.com/kalcaddle/KODExplorer/archive/master.zip)
|
||||
|
||||
> KodExplorer is a file manager for web. It is also a web code editor, which allows you to develop websites directly within the web browser.You can run KodExplorer either online or locally,on Linux, Windows or Mac based platforms. The only requirement is to have PHP 5 available.
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
### [Demo](http://demo.kodcloud.com/) [user: demo/demo]
|
||||
-----
|
||||
- [Change log](./ChangeLog.md)
|
||||
- [Document/开发文档](http://doc.kodcloud.com/)
|
||||
- [Donate](https://www.paypal.me/kalcaddle)
|
||||
|
||||
### Source code
|
||||
----
|
||||
- [github](https://github.com/kalcaddle/KodExplorer)
|
||||
- [gitee](https://gitee.com/kalcaddle/KODExplorer)
|
||||
|
||||
# Features
|
||||
- Use experience like operating system, Rich context menu and toolbar, drag and drop, shortcut keys......
|
||||
- Available in more than 40 languages.
|
||||
- File Manage
|
||||
- All operations with files and folders on a remote server(copy,cut,paste,move,remove,upload,create folder/file,rename,etc.)
|
||||
- Multi-User support,custom role group.
|
||||
- Flexible configuration of access rights,file types restriction, user - interface and other
|
||||
- Clipboard: copy, cut, paste, clear
|
||||
- Selectable files & folders support (mouse click & Ctrl & Shift & words & Keyboard shortcuts)
|
||||
- Keyboard shortcuts: delete deletion, ctrl+A select, ctrl+C replication, ctrl+X splicing, up/down/left/right/home/end etc.
|
||||
- Multiple actions support for selected files & folders: move,copy,cute,remove,rename,open,archive,delete,download etc.
|
||||
- Double or single click setup to open files & folders
|
||||
- Filetree: allow to open and display multiple subfolders at a time
|
||||
- Implemented natural sorting on the client-side
|
||||
- List,Icons and Split view;
|
||||
- Move/Copy/Clone/Delete files with Drag & Drop
|
||||
- Share files or folder to others.
|
||||
- Add folder to your favorites
|
||||
- Calculate directory sizes
|
||||
- Thumbnails for image files
|
||||
- Normalizer:UTF-8 Normalizer of file-name and file-path etc.
|
||||
- Muti Charset support, in a variety of circumstances garbled solution;Sanitizer of file-name and file-path etc.
|
||||
- Multiple & chunked uploads support,
|
||||
- Background file upload with Drag & Drop HTML5 support;Folder upload with Chrome, Firefox and Edge
|
||||
- Upload form URL (or list)
|
||||
- Direct extraction to the current working directory (you do not want - to create a folder)
|
||||
- Search: search by filename & file contents
|
||||
- File exclusion based on name
|
||||
- Copy direct file URL
|
||||
- Archives create/extract/preview (zip, rar, 7z, tar, gzip, tgz)
|
||||
- Quicklook, preview for common file types; image file,text file,pdf,swf,document file etc.
|
||||
- Video and audio player relying on web browser capabilities
|
||||
- Editor
|
||||
- Syntax highlighting for over 120 languages
|
||||
- Multiple label, Drag & Drop the label.
|
||||
- Over 15 themes,Choose your favorite programming style
|
||||
- Web development: HTML/JS/CSS editor with Emmet integrated
|
||||
- Automatic indent and outdent;Line wrapping;Code folding
|
||||
- Multiple cursors and selections;(Middle key select;Ctrl+Command+G)
|
||||
- Autocomplete.
|
||||
- Fully customizable key bindings including vim and Emacs modes
|
||||
- Search and replace with regular expressions;Highlight matching parentheses
|
||||
- Toggle between soft tabs and real tabs
|
||||
- Displays hidden characters
|
||||
- Drag and drop text using the mouse
|
||||
- Live syntax checker (JavaScript/CoffeeScript/CSS/XQuery/HTML/PHP etc.)
|
||||
- Cut, copy, and paste functionality
|
||||
- Markdown support.(live preview;convert to html etc.)
|
||||
- Format: JavaScript/CSS/HTML/JSON/PHP etc.
|
||||
- Cross-platform, even on mobile devices
|
||||
- Easy to integrate with other systems
|
||||
- Developed by kod itself, this is a nice try.
|
||||
|
||||
|
||||
# Install
|
||||
|
||||
**1. Install from source**
|
||||
```
|
||||
git clone https://github.com/kalcaddle/KODExplorer.git
|
||||
chmod -Rf 777 ./KODExplorer/*
|
||||
```
|
||||
|
||||
**2. Install via download**
|
||||
```
|
||||
wget https://github.com/kalcaddle/KODExplorer/archive/master.zip
|
||||
unzip master.zip
|
||||
chmod -Rf 777 ./*
|
||||
```
|
||||
|
||||
|
||||
|
||||
# FAQs
|
||||
|
||||
* Forget password
|
||||
> Login page: see the "Forget password".
|
||||
|
||||
* Upload with Drag & Drop
|
||||
> Browser compatibility: Chrome, Firefox and Edge
|
||||
|
||||
* How to make the system more secure?
|
||||
> Make sure the administrator password is more complex.
|
||||
> Open login verification code.
|
||||
> Set the http server to not allow list the directory;
|
||||
> PHP Security:Set the path for open_basedir.
|
||||
|
||||
# Screenshot
|
||||
### file manage:
|
||||
- Overview
|
||||

|
||||
- File list Type (icon,list,split)
|
||||

|
||||
- Archives create/extract/preview (zip, rar, 7z, tar, gzip, tgz)
|
||||

|
||||
- Drag upload
|
||||

|
||||
- Player
|
||||

|
||||
- Online Office view & Editor
|
||||

|
||||
|
||||
|
||||
### Editor:
|
||||
- Overview
|
||||

|
||||
- Live preview
|
||||

|
||||
- Search folder
|
||||

|
||||
- Markdown
|
||||

|
||||
- Code style
|
||||

|
||||
|
||||
|
||||
### Others:
|
||||
- System role
|
||||

|
||||
- Colorful Theme
|
||||

|
||||
- Custom Theme
|
||||

|
||||
- Language
|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
# Software requirements
|
||||
- Server:
|
||||
- Windows,Linux,Mac ...
|
||||
- PHP 5.0+
|
||||
- Database: File system driver;sqlite;mysql;...
|
||||
- Browser compatibility:
|
||||
- Chrome
|
||||
- Firefox
|
||||
- Opera
|
||||
- IE8+
|
||||
> Tips: It can also run on a router, or your home NAS
|
||||
|
||||
|
||||
# Credits
|
||||
kod is made possible by the following open source projects.
|
||||
|
||||
* [seajs](https://github.com/seajs/seajs)
|
||||
* [jQuery](https://github.com/jquery/jquery)
|
||||
* [ace](https://github.com/ajaxorg/ace)
|
||||
* [zTree](https://github.com/zTree/zTree_v3)
|
||||
* [webuploader](https://github.com/fex-team/webuploader)
|
||||
* [artTemplate](http://aui.github.com/artTemplate/)
|
||||
* [artDialog](https://github.com/aui/artDialog)
|
||||
* [jQuery-contextMenu](http://medialize.github.com/jQuery-contextMenu/)
|
||||
* ...
|
||||
|
||||
|
||||
# License
|
||||
kodcloud is issued under GPLv3. license.[License](http://kodcloud.com/tools/licenses/license.txt)
|
||||
Contact: warlee#kodcloud.com
|
||||
Copyright (C) 2013 kodcloud.com
|
||||
|
||||
# 版权声明
|
||||
kodexplorer 使用 GPL v3 协议.
|
||||
@@ -0,0 +1,109 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
if(!function_exists('get_client_ip')){
|
||||
require_once(dirname(dirname(__FILE__)).'/function/web.function.php');
|
||||
}
|
||||
class SSO{
|
||||
static private function init(){
|
||||
$sessionName = 'KOD_SESSION_SSO';
|
||||
$sessionID = $_COOKIE[$sessionName]?$_COOKIE[$sessionName]:md5(uniqid());
|
||||
$basicPath = dirname(dirname(dirname(__FILE__))).'/';
|
||||
$sessionPath = $basicPath.'data/session/';
|
||||
if(file_exists($basicPath.'config/define.php')){
|
||||
include($basicPath.'config/define.php');
|
||||
$sessionPath = DATA_PATH.'session/';
|
||||
}
|
||||
if(!file_exists($sessionPath)){
|
||||
mkdir($sessionPath);
|
||||
}
|
||||
$sessionSavePath = @session_save_path();
|
||||
@session_write_close();
|
||||
@session_name($sessionName);
|
||||
if( class_exists('SaeStorage') ||
|
||||
defined('SAE_APPNAME') ||
|
||||
defined('SESSION_PATH_DEFAULT') ||
|
||||
@ini_get('session.save_handler') != 'files' ||
|
||||
isset($_SERVER['HTTP_APPNAME']) ){
|
||||
//sae 关闭自定义session路径
|
||||
}else{
|
||||
@session_save_path($sessionPath);//session path
|
||||
}
|
||||
@session_id($sessionID);
|
||||
|
||||
@session_start();
|
||||
$_SESSION['kodSSO'] = true;
|
||||
@session_write_close();
|
||||
unset($_SESSION);
|
||||
@session_start();
|
||||
if(!isset($_SESSION['kodSSO']) || !$_SESSION['kodSSO']){
|
||||
@session_save_path($sessionSavePath);//session path
|
||||
@session_start();
|
||||
$_SESSION['kodSSO'] = true;
|
||||
@session_write_close();
|
||||
}
|
||||
//echo '<pre>';var_dump($_SESSION);echo '</pre>';exit;
|
||||
return $_SESSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置session 认证
|
||||
* @param [type] $key [认证key]
|
||||
*/
|
||||
static public function sessionSet($key,$value='success'){
|
||||
self::init();
|
||||
@session_start();
|
||||
$_SESSION[$key] = $value;
|
||||
@session_write_close();
|
||||
}
|
||||
|
||||
|
||||
static public function sessionCheck($key,$value='success'){
|
||||
$session = self::init();
|
||||
if( isset($session[$key]) && $session[$key] == $value){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 直接调用kod的登陆检测(适用于同服务器同域名;)
|
||||
* @param [type] $kodHost kod的地址;例如 http://test.com/ ;默认为插件目录
|
||||
* @param [type] $appKey 应用标记 例如 loginCheck
|
||||
* @param [type] $appUrl 验证后跳转到的url;默认为当前url
|
||||
* @param [type] $auth 验证方式:例如:'check=userName&value=smartx'
|
||||
* check (userID|userName|roleID|roleName|groupID|groupName) 校验方式,为空则所有登陆用户
|
||||
*/
|
||||
static public function sessionAuth($appKey,$auth,$kodHost='',$appUrl=''){
|
||||
if($kodHost==''){
|
||||
$appUrl = this_url();
|
||||
if(strstr($appUrl,'/plugins/')){
|
||||
$kodHost = substr($appUrl,0,strpos($appUrl,'/plugins/'));
|
||||
}else{
|
||||
if(isset($_COOKIE['APP_HOST'])){
|
||||
$kodHost = $_COOKIE['APP_HOST'];
|
||||
}else{
|
||||
$kodHost = $_SERVER['HTTP_REFERER'];
|
||||
if(strstr($kodHost,'/index.php?')){
|
||||
$kodHost = substr($kodHost,0,strpos($kodHost,'/index.php?'));
|
||||
}else if(strstr($kodHost,'/?')){
|
||||
$kodHost = substr($kodHost,0,strpos($kodHost,'/?'));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$authUrl = rtrim($kodHost,'/').'/index.php?user/sso&app='.$appKey.'&'.$auth;
|
||||
if($appUrl == ''){
|
||||
$appUrl = this_url();
|
||||
}
|
||||
if(!self::sessionCheck($appKey)){
|
||||
session_destroy();
|
||||
header('Location: '.$authUrl.'&link='.rawurlencode($appUrl));
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
class api extends Controller{
|
||||
function __construct(){
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* 通用文件预览方案
|
||||
* image,media,cad,office,webodf,pdf,epub,swf,text
|
||||
* 跨域:epub,pdf,odf,[text];
|
||||
* @return [type] [description]
|
||||
*/
|
||||
public function view(){
|
||||
if(!isset($this->in['path'])){
|
||||
show_tips('参数错误!');
|
||||
}
|
||||
$this->checkAccessToken();
|
||||
$this->setIdentify();
|
||||
$this->display('view.html');
|
||||
}
|
||||
private function setIdentify(){
|
||||
if(! $_SESSION['accessPlugin'] ){
|
||||
session_start();
|
||||
$_SESSION['accessPlugin'] = 'ok';
|
||||
session_write_close();
|
||||
}
|
||||
}
|
||||
public function checkAccessToken(){
|
||||
$model = $this->loadModel('Plugin');
|
||||
$config = $model->getConfig('fileView');
|
||||
if(!$config['apiKey']){
|
||||
return;
|
||||
}
|
||||
$timeTo = isset($this->in['timeTo'])?intval($this->in['timeTo']):'';
|
||||
$token = md5($config['apiKey'].$this->in['path'].$timeTo);
|
||||
|
||||
//show_tips(array($config['apiKey'],$token,$this->in));
|
||||
if($token != $this->in['token']){
|
||||
show_tips('token 错误!');
|
||||
}
|
||||
if($timeTo != '' && $timeTo <= time()){
|
||||
show_tips('token已失效!');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,141 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
class app extends Controller{
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->sql=new FileCache(USER_SYSTEM.'apps.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户首页展示
|
||||
*/
|
||||
public function index() {
|
||||
$this->display('index.html');
|
||||
}
|
||||
|
||||
public function initApp(){
|
||||
//为空则不初始化桌面
|
||||
if(!$this->config['settingSystem']['desktopFolder']){
|
||||
return;
|
||||
}
|
||||
$list = $this->sql->get();
|
||||
$newUserApp = $this->config['settingSystem']['newUserApp'];
|
||||
$default = explode(',',$newUserApp);
|
||||
$info = array();
|
||||
foreach ($default as $key) {
|
||||
$info[$key] = $list[$key];
|
||||
}
|
||||
|
||||
$desktop = iconv_system(HOME.DESKTOP_FOLDER.'/');
|
||||
if($GLOBALS['isRoot'] == 1){
|
||||
$desktop = iconv_system(MYHOME.DESKTOP_FOLDER.'/');
|
||||
}
|
||||
mk_dir($desktop);
|
||||
if(!path_writeable($desktop)){
|
||||
return;
|
||||
}
|
||||
foreach ($info as $key => $data) {
|
||||
if (!is_array($data)) {
|
||||
continue;
|
||||
}
|
||||
$path = $desktop.iconv_system($key).'.oexe';
|
||||
unset($data['name']);
|
||||
unset($data['desc']);
|
||||
unset($data['group']);
|
||||
file_put_contents($path, json_encode($data));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户app 添加、编辑
|
||||
*/
|
||||
public function userApp() {
|
||||
$path = _DIR($this->in['path']);
|
||||
if(get_path_ext($path) != 'oexe'){
|
||||
$path .= '.oexe';
|
||||
}
|
||||
if (!checkExt($path)) {
|
||||
show_json(LNG('error'));exit;
|
||||
}
|
||||
|
||||
$data = $this->_init();
|
||||
unset($data['name']);
|
||||
unset($data['path']);
|
||||
unset($data['desc']);
|
||||
unset($data['group']);
|
||||
$res = file_put_contents($path, json_encode($data));
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取列表
|
||||
*/
|
||||
public function get() {
|
||||
$list = array();
|
||||
if (!isset($this->in['group']) || $this->in['group']=='all') {
|
||||
$list = $this->sql->get();
|
||||
}else{
|
||||
$list = $this->sql->get(array('group',$this->in['group']));
|
||||
}
|
||||
$list = array_reverse($list);
|
||||
show_json($list);
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*/
|
||||
public function add() {
|
||||
$res=$this->sql->set(rawurldecode($this->in['name']),$this->_init());
|
||||
if($res) show_json(LNG('success'));
|
||||
show_json(LNG('error_repeat'),false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
public function edit() {
|
||||
//查找到一条记录,修改为该数组
|
||||
$this->sql->remove(rawurldecode($this->in['old_name']));
|
||||
if($this->sql->set(rawurldecode($this->in['name']),$this->_init())){
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
show_json(LNG('error_repeat'),false);
|
||||
}
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
public function del() {
|
||||
if($this->sql->remove(rawurldecode($this->in['name']))){
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
|
||||
public function getUrlTitle(){
|
||||
$html = curl_get_contents($this->in['url']);
|
||||
$result = match_text($html,"<title>(.*)<\/title>");
|
||||
if (strlen($result)>50) {
|
||||
$result = mb_substr($result,0,50,'utf-8');
|
||||
}
|
||||
if (!$result || strlen($result) == 0) {
|
||||
$result = $this->in['url'];
|
||||
$result = str_replace(array('http://','&','/'),array('','@','-'), $result);
|
||||
}
|
||||
show_json($result);
|
||||
}
|
||||
|
||||
private function _init(){
|
||||
$data = rawurldecode($this->in['data']);
|
||||
$arr = json_decode($data,true);
|
||||
if(!is_array($arr)){
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
return $arr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
class desktop extends Controller{
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
public function index() {
|
||||
$wap = is_wap() && (!isset($_COOKIE['forceWap']) || $_COOKIE['forceWap'] == '1');
|
||||
$desktopApps = include(DATA_PATH.'system/desktop_app.php');
|
||||
$wall = $this->config['user']['wall'];
|
||||
if( !strstr($wall,'/') ){
|
||||
$wall = STATIC_PATH.'images/wall_page/'.$wall.'.jpg';
|
||||
}
|
||||
|
||||
$wall = str_replace('&','&',$wall);
|
||||
$desktop = iconv_system(HOME.DESKTOP_FOLDER.'/');
|
||||
if($GLOBALS['isRoot'] == 1){
|
||||
$desktop = iconv_system(MYHOME.DESKTOP_FOLDER.'/');
|
||||
}
|
||||
mk_dir($desktop);
|
||||
|
||||
$this->assign('wall',$wall);
|
||||
$this->assign('desktopApps',$desktopApps);
|
||||
$this->display('index.html');
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
class editor extends Controller{
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
// 多文件编辑器
|
||||
public function index(){
|
||||
$this->themeSet();
|
||||
$this->display('editor.html');
|
||||
}
|
||||
// 单文件编辑
|
||||
public function edit(){
|
||||
$this->themeSet();
|
||||
$this->display('edit.html');
|
||||
}
|
||||
|
||||
private function themeSet(){
|
||||
$setClass = '';
|
||||
//获取编辑器配置数据
|
||||
$editorConfig = $this->config['editorDefault'];
|
||||
$configFile = USER.'data/editor_config.php';
|
||||
if (!file_exists(iconv_system($configFile))) {//不存在则创建
|
||||
$sql=FileCache::save($configFile,$editorConfig);
|
||||
}else{
|
||||
$editorConfig=FileCache::load($configFile);
|
||||
}
|
||||
|
||||
$blackTheme = array("ambiance","idle_fingers","monokai","pastel_on_dark","twilight",
|
||||
"solarized_dark","tomorrow_night_blue","tomorrow_night_eighties");
|
||||
if(in_array($editorConfig['theme'],$blackTheme)){
|
||||
$setClass = 'class="code-theme-black"';
|
||||
}
|
||||
$this->assign('editorConfig',json_encode($editorConfig));//获取编辑器配置信息
|
||||
$this->assign('codeThemeBlack',$setClass);//获取编辑器配置信息
|
||||
}
|
||||
|
||||
// 获取文件数据
|
||||
public function fileGet(){
|
||||
if(isset($this->in['fileUrl'])){
|
||||
$pass = $this->config['settingSystem']['systemPassword'];
|
||||
$fileUrl = $this->in['fileUrl'];
|
||||
if(!request_url_safe($fileUrl)){
|
||||
show_json(LNG('url error!'),false);
|
||||
}
|
||||
$urlInfo = parse_url_query($fileUrl);
|
||||
if( isset($urlInfo['fid']) &&
|
||||
strlen(Mcrypt::decode($urlInfo['fid'],$pass)) != 0
|
||||
){
|
||||
$filepath = Mcrypt::decode($urlInfo['fid'],$pass);
|
||||
$displayName = get_path_this($filepath);
|
||||
if(isset($urlInfo['downFilename'])){
|
||||
$displayName = rawurldecode($urlInfo['downFilename']);
|
||||
}
|
||||
}else{
|
||||
$displayName = rawurldecode($urlInfo['name']);
|
||||
$filepath = $fileUrl.'&accessToken='.access_token_get();
|
||||
}
|
||||
}else{
|
||||
$displayName = rawurldecode($this->in['filename']);
|
||||
$filepath =_DIR($this->in['filename']);
|
||||
if (!file_exists($filepath)){
|
||||
show_json(LNG('not_exists'),false);
|
||||
}
|
||||
if (!path_readable($filepath)){
|
||||
show_json(LNG('no_permission_read_all'),false);
|
||||
}
|
||||
if (filesize($filepath) >= 1024*1024*20){
|
||||
show_json(LNG('edit_too_big'),false);
|
||||
}
|
||||
}
|
||||
|
||||
$fileContents=file_get_contents($filepath);//文件内容
|
||||
//echo $fileContents;exit;
|
||||
if(isset($this->in['charset']) && $this->in['charset']){
|
||||
$charset = strtolower($this->in['charset']);
|
||||
}else{
|
||||
$charset = get_charset($fileContents);
|
||||
}
|
||||
if ($charset !='' &&
|
||||
$charset !='utf-8' &&
|
||||
function_exists("mb_convert_encoding")
|
||||
){
|
||||
$fileContents = @mb_convert_encoding($fileContents,'utf-8',$charset);
|
||||
}
|
||||
$data = array(
|
||||
'ext' => get_path_ext($displayName),
|
||||
'name' => iconv_app(get_path_this($displayName)),
|
||||
'filename' => $displayName,
|
||||
'charset' => $charset,
|
||||
'base64' => true,// 部分防火墙编辑文件误判问题处理
|
||||
'content' => base64_encode($fileContents)
|
||||
);
|
||||
show_json($data);
|
||||
}
|
||||
public function fileSave(){
|
||||
$fileStr = rawurldecode($this->in['filestr']);
|
||||
$path =_DIR($this->in['path']);
|
||||
if(isset($this->in['create_file']) && !file_exists($path)){//不存在则创建
|
||||
if(!@touch($path)){
|
||||
show_json(LNG('create_error'),false);
|
||||
}
|
||||
}
|
||||
if (!path_writeable($path)) show_json(LNG('no_permission_write_file'),false);
|
||||
//支持二进制文件读写操作(base64方式)
|
||||
if(isset($this->in['base64'])){
|
||||
$fileStr = base64_decode($fileStr);
|
||||
}
|
||||
|
||||
$charset = strtolower($this->in['charset']);
|
||||
if(isset($this->in['charsetSave'])){
|
||||
$charset = strtolower($this->in['charsetSave']);
|
||||
}
|
||||
if ( $charset !='' &&
|
||||
$charset != 'utf-8' &&
|
||||
$charset != 'ascii' &&
|
||||
function_exists("mb_convert_encoding")
|
||||
) {
|
||||
$fileStr = @mb_convert_encoding($fileStr,$charset,'utf-8');
|
||||
}
|
||||
$fp=fopen($path,'wb');
|
||||
fwrite($fp,$fileStr);
|
||||
fclose($fp);
|
||||
show_json(LNG('save_success'));
|
||||
}
|
||||
|
||||
/*
|
||||
* 获取编辑器配置信息
|
||||
*/
|
||||
public function setConfig(){
|
||||
$file = USER.'data/editor_config.php';
|
||||
if (!path_writeable(iconv_system($file))) {//配置不可写
|
||||
show_json(LNG('no_permission_write_file'),false);
|
||||
}
|
||||
$key= $this->in['k'];
|
||||
$value = $this->in['v'];
|
||||
if ($key !='' && $value != '') {
|
||||
$sql=new FileCache($file);
|
||||
$sql->set($key,$value);//没有则添加一条
|
||||
show_json(LNG('setting_success'));
|
||||
}else{
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
class fav extends Controller{
|
||||
private $sql;
|
||||
function __construct(){
|
||||
parent::__construct();
|
||||
$this->sql=new FileCache(USER.'data/fav.php');
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取收藏夹json
|
||||
*/
|
||||
public function get() {
|
||||
show_json($this->sql->get());
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加
|
||||
*/
|
||||
public function add() {
|
||||
$name = $this->in['name'];
|
||||
$path = $this->in['path'];
|
||||
if($this->sql->get($name)){//已存在则自动重命名
|
||||
$index = 0;
|
||||
while ($this->sql->get($name.'('.$index.')')) {
|
||||
$index ++;
|
||||
}
|
||||
$name = $name.'('.$index.')';
|
||||
}
|
||||
$res=$this->sql->set(
|
||||
$name,
|
||||
array(
|
||||
'name' => $name,
|
||||
'path' => $path,
|
||||
'ext' => $this->in['ext'],
|
||||
'type' => $this->in['type']
|
||||
)
|
||||
);
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
public function edit() {
|
||||
$this->in['name'] = $this->in['name'];
|
||||
$this->in['path'] = $this->in['path'];
|
||||
$this->in['nameTo'] = $this->in['nameTo'];
|
||||
$newFav = $this->sql->get($this->in['name']);
|
||||
if(!isset($newFav['type'])){
|
||||
$newFav['type'] = 'folder';
|
||||
}
|
||||
//查找到一条记录,修改为该数组
|
||||
$toArray=array(
|
||||
'name'=>$this->in['nameTo'],
|
||||
'path'=>$this->in['pathTo'],
|
||||
'type'=>$newFav['type']
|
||||
);
|
||||
$this->sql->remove($this->in['name']);
|
||||
if($this->sql->set($this->in['nameTo'],$toArray)){
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
show_json(LNG('error_repeat'),false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
public function del() {
|
||||
$this->in['name'] = $this->in['name'];
|
||||
if($this->sql->remove($this->in['name'])){
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,223 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*
|
||||
*
|
||||
* 插件管理:页面;列表;
|
||||
*/
|
||||
|
||||
class pluginApp extends Controller{
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
//?pluginApp/to/epubReader/index&a=1
|
||||
//?pluginApp/to/epubReader/&a=1 ==>ignore index;
|
||||
public function to() {
|
||||
$route = $this->in['URLremote'];
|
||||
if(count($route) >= 3){
|
||||
$app = clear_html($route[2]);
|
||||
$action = $route[3];
|
||||
|
||||
if(count($route) == 3){
|
||||
$action = 'index';
|
||||
}
|
||||
$model = $this->loadModel('Plugin');
|
||||
if(!$model->checkAuth($app)){
|
||||
if(!$_SESSION['kodLogin']){
|
||||
show_tips("出错了!您尚未登录",APP_HOST,3);
|
||||
}
|
||||
show_tips("出错了!插件未开启,或您没有{$app}插件的权限!");
|
||||
}
|
||||
|
||||
$appConfig = $model->getConfig($app);
|
||||
if(!$appConfig['pluginAuthOpen'] && !$this->checkAccessPlugin()){
|
||||
if(!$_SESSION['kodLogin']){
|
||||
show_tips("出错了!您尚未登录",APP_HOST,3);
|
||||
}
|
||||
show_tips("出错了!插件未开启,或您没有{$app}插件的权限");
|
||||
}
|
||||
Hook::trigger("pluginRun.before",$app.'Plugin.'.$action);
|
||||
Hook::trigger($app.'Plugin.'.$action.'.before');
|
||||
Hook::apply($app.'Plugin.'.$action);
|
||||
Hook::trigger($app.'Plugin.'.$action.'.after');
|
||||
Hook::trigger("pluginRun.after",$app.'Plugin.'.$action);
|
||||
}
|
||||
}
|
||||
|
||||
//权限认证
|
||||
private function checkAccessPlugin(){
|
||||
if( $_SESSION['kodLogin'] == true ||
|
||||
$_SESSION['accessPlugin'] == 'ok' ||
|
||||
$this->checkAccessShare()
|
||||
){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
private function checkAccessShare(){
|
||||
if(!isset($this->in['path'])){
|
||||
return false;
|
||||
}
|
||||
$share = KOD_USER_SHARE;
|
||||
if(substr(urldecode($this->in['path']),0,strlen($share)) == $share){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//plugin manager
|
||||
public function index() {
|
||||
$this->display('index.html');
|
||||
}
|
||||
|
||||
public function appList(){
|
||||
$model = $this->loadModel('Plugin');
|
||||
$list = $model->viewList();
|
||||
show_json($list);
|
||||
}
|
||||
|
||||
public function changeStatus(){
|
||||
if( !isset($this->in['app']) ||
|
||||
!isset($this->in['status'])){
|
||||
show_json(LNG('data_not_full'),false);
|
||||
}
|
||||
$app = $this->in['app'];
|
||||
$status = $this->in['status']?1:0;
|
||||
$model = $this->loadModel('Plugin');
|
||||
|
||||
//启用插件则检测配置文件,必填字段是否为空;为空则调用配置
|
||||
if($status){
|
||||
$config = $model->getConfig($app);
|
||||
$package = $model->getPackageJson($app);
|
||||
$needConfig = false;
|
||||
foreach($package['configItem'] as $key=>$item) {
|
||||
if( (isset($item['require']) && $item['require']) &&
|
||||
(!isset($item['value']) || $item['value'] === '' || $item['value'] === null) &&
|
||||
(!isset($config[$key]) || $config[$key] == "")
|
||||
){
|
||||
$needConfig = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if($needConfig){
|
||||
show_json('needConfig',false);
|
||||
}
|
||||
}
|
||||
$model->changeStatus($app,$status);
|
||||
$list = $model->viewList();
|
||||
show_json($list);
|
||||
}
|
||||
|
||||
public function setConfig(){
|
||||
if( !$this->in['app'] ||
|
||||
!$this->in['value']){
|
||||
show_json(LNG('data_not_full'),false);
|
||||
}
|
||||
$json = $this->in['value'];
|
||||
$app = $this->in['app'];
|
||||
$model = $this->loadModel('Plugin');
|
||||
|
||||
//重置为默认配置
|
||||
if($json == 'reset'){
|
||||
$json = $model->getConfigDefault($app);
|
||||
}else{
|
||||
if(!is_array($json)){
|
||||
show_json($json,false);
|
||||
}
|
||||
}
|
||||
$model->changeStatus($app,1);
|
||||
$model->setConfig($app,$json);
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
|
||||
// download=>fileSize=>unzip=>remove
|
||||
public function install(){
|
||||
if(!preg_match("/^[0-9a-zA-Z_]*$/",$this->in['app'])) show_json("error!",false);
|
||||
$app = _DIR_CLEAR($this->in['app']);
|
||||
$appPath = PLUGIN_DIR.$app.'.zip';
|
||||
$appPathTemp = $appPath.'.downloading';
|
||||
switch($this->in['step']){
|
||||
case 'check':
|
||||
$info = $this->pluginInfo($app);
|
||||
if(!is_array($info)){
|
||||
show_json(false,false);
|
||||
}
|
||||
echo json_encode($info);
|
||||
break;
|
||||
case 'download':
|
||||
if(!is_writable(PLUGIN_DIR)){
|
||||
show_json(LNG("no_permission_write").': '.PLUGIN_DIR,false);
|
||||
}
|
||||
$info = $this->pluginInfo($app);
|
||||
if(!$info || !$info['code']){
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
$result = Downloader::start($info['data'],$appPath);
|
||||
show_json($result['data'],!!$result['code'],$app);
|
||||
break;
|
||||
case 'fileSize':
|
||||
if(file_exists($appPath)){
|
||||
show_json(filesize($appPath));
|
||||
}
|
||||
if(file_exists($appPathTemp)){
|
||||
show_json(filesize($appPathTemp));
|
||||
}
|
||||
show_json(0,false);
|
||||
break;
|
||||
case 'unzip':
|
||||
//hook log
|
||||
$GLOBALS['isRoot'] = 1;
|
||||
if(!file_exists($appPath)){
|
||||
show_json(LNG("error"),false);
|
||||
}
|
||||
$result = KodArchive::extract($appPath,PLUGIN_DIR.$app.'/');
|
||||
del_file($appPathTemp);
|
||||
del_file($appPath);
|
||||
show_json($result['data'],!!$result['code']);
|
||||
break;
|
||||
case 'remove':
|
||||
del_file($appPathTemp);
|
||||
del_file($appPath);
|
||||
show_json(LNG('success'));
|
||||
break;
|
||||
case 'update':
|
||||
show_json(Hook::apply($app.'Plugin.update'));
|
||||
break;
|
||||
default:break;
|
||||
}
|
||||
}
|
||||
private function pluginInfo($app){
|
||||
$api = $this->config['settings']['pluginServer'].'plugin/install';
|
||||
$param = array(
|
||||
"app" => $app,
|
||||
"version" => KOD_VERSION,
|
||||
"versionHash" => $this->config['settingSystem']['versionHash'],
|
||||
"systemOS" => $this->config['systemOS'],
|
||||
"phpVersion" => PHP_VERSION,
|
||||
"channel" => INSTALL_CHANNEL,
|
||||
"lang" => I18n::getType()
|
||||
);
|
||||
$info = url_request($api,'POST',$param);
|
||||
$result = false;
|
||||
if($info && $info['data']){
|
||||
$result = json_decode($info['data'],true);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function unInstall(){
|
||||
if( !$this->in['app']){
|
||||
show_json(LNG('data_not_full'),false);
|
||||
}
|
||||
if(!preg_match("/^[0-9a-zA-Z_]*$/",$this->in['app'])) show_json("error!",false);
|
||||
$model = $this->loadModel('Plugin');
|
||||
$model->remove($this->in['app']);
|
||||
del_dir(PLUGIN_DIR.$this->in['app']);
|
||||
$list = $model->viewList();
|
||||
show_json($list);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
class setting extends Controller{
|
||||
private $sql;
|
||||
function __construct(){
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户首页展示
|
||||
*/
|
||||
public function index() {
|
||||
$this->display('index.html');
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户首页展示
|
||||
*/
|
||||
public function slider() {
|
||||
switch ($this->in['slider']) {
|
||||
case 'about':show_json(file_get_contents(LANGUAGE_PATH.I18n::getType().'/about.html'));break;
|
||||
case 'help':show_json(file_get_contents(LANGUAGE_PATH.I18n::getType().'/help.html'));break;
|
||||
case 'member':break;
|
||||
case 'fav':break;
|
||||
case 'user':
|
||||
case 'theme':
|
||||
case 'wall':
|
||||
show_json(array(
|
||||
'settingAll' => $this->config['settingAll'],
|
||||
'user' => $this->config['user'],
|
||||
'wallpageDesktop' => $this->config['settingSystem']['wallpageDesktop'],
|
||||
'wallpageLogin' => $this->config['settingSystem']['wallpageLogin'],
|
||||
));
|
||||
break;
|
||||
case 'system':
|
||||
if($GLOBALS['isRoot']){
|
||||
if(isset($this->in['env_check'])){
|
||||
show_json(php_env_check());
|
||||
}
|
||||
$result = $this->config['settingSystem'];
|
||||
unset($result['systemPassword']);
|
||||
show_json($result,true);
|
||||
}else{
|
||||
show_json('error',false);
|
||||
}
|
||||
break;
|
||||
default:break;
|
||||
}
|
||||
}
|
||||
|
||||
public function phpInfo(){
|
||||
phpinfo();
|
||||
}
|
||||
|
||||
|
||||
//管理员 系统设置全局数据
|
||||
public function systemSetting(){
|
||||
$settingFile = USER_SYSTEM.'system_setting.php';
|
||||
$data = json_decode($this->in['data'],true);
|
||||
if (!$data) {
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
$setting = $GLOBALS['config']['settingSystem'];
|
||||
foreach ($data as $key => $value){
|
||||
if ($key=='menu') {
|
||||
$setting[$key] = $value;
|
||||
}else{
|
||||
$setting[$key] = rawurldecode($value);
|
||||
}
|
||||
}
|
||||
//为了保存更多的数据;不直接覆盖文件 $data->setting_file;
|
||||
FileCache::save($settingFile,$setting);
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
|
||||
public function systemTools(){
|
||||
$action = $this->in['action'];
|
||||
switch($action){
|
||||
case 'clearCache':$this->_clearCache();break;
|
||||
case 'clearSession':$this->_clearSession();break;
|
||||
case 'clearUserRecycle':$this->_clearUserRecycle();break;
|
||||
default:break;
|
||||
}
|
||||
show_json(LNG('success'),true);
|
||||
}
|
||||
private function _clearSession(){
|
||||
del_dir(KOD_SESSION);
|
||||
}
|
||||
private function _clearCache(){
|
||||
del_dir(TEMP_PATH);
|
||||
mk_dir(TEMP_PATH.'log');
|
||||
mk_dir(TEMP_PATH.'thumb');
|
||||
}
|
||||
private function _clearUserRecycle(){
|
||||
$sql = systemMember::loadData();
|
||||
$user_arr = $sql->get();
|
||||
foreach ($user_arr as $key => $user) {
|
||||
$userPath = iconv_system(USER_PATH.$user['path']."/");
|
||||
$pathArr = array(
|
||||
$userPath.'data/temp',
|
||||
$userPath.'data/share_temp',
|
||||
$userPath.'recycle_kod'
|
||||
);
|
||||
foreach ($pathArr as $value) {
|
||||
del_dir($value);
|
||||
mk_dir($value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 参数设置
|
||||
* 可以同时修改多个:key=a,b,c&value=1,2,3
|
||||
* 防xss 做过滤
|
||||
*/
|
||||
public function set(){
|
||||
$file = USER.'data/config.php';
|
||||
if (!path_writeable(iconv_system($file))) {//配置不可写
|
||||
show_json(LNG('no_permission_write_file'),false);
|
||||
}
|
||||
$key = $this->in['k'];
|
||||
$value = $this->in['v'];
|
||||
if ($key !='' && $value != '') {
|
||||
$conf = $this->config['user'];
|
||||
if(!strpos($key,',')){//多个参数,value不能包含','
|
||||
$conf[$key] = clear_html($value);
|
||||
}else{
|
||||
$arr_k = explode(',', $key);
|
||||
$arr_v = explode(',',$value);
|
||||
$num = count($arr_k);
|
||||
for ($i=0; $i < $num; $i++) {
|
||||
$conf[$arr_k[$i]] = clear_html($arr_v[$i]);
|
||||
}
|
||||
}
|
||||
FileCache::save($file,$conf);
|
||||
show_json(LNG('setting_success'));
|
||||
}else{
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,631 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
class share extends Controller{
|
||||
private $sql;
|
||||
private $shareInfo;
|
||||
private $sharePath;
|
||||
private $path;
|
||||
function __construct(){
|
||||
parent::__construct();
|
||||
$auth = systemRole::getInfo(1);//经过role检测
|
||||
|
||||
$arrNotCheck = array('commonJs','manifest','manifestJS');
|
||||
if(substr($this->in['fileUrl'],0,4) == 'http'){
|
||||
$arrNotCheck[] = 'fileGet';
|
||||
}
|
||||
if (!in_array(ACT,$arrNotCheck)){
|
||||
$this->initShare();
|
||||
$this->checkShare();
|
||||
$this->assign('canDownload',$this->shareInfo['notDownload']=='1'?0:1);
|
||||
}
|
||||
//需要检查下载权限的Action
|
||||
$arrCheckDownload = array('fileDownload','zipDownload');//'fileProxy','fileGet'
|
||||
if (in_array(ACT,$arrCheckDownload)){
|
||||
if ($this->shareInfo['notDownload']=='1') {
|
||||
show_json(LNG('share_not_download_tips'),false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function initShare(){
|
||||
if(isset($this->in['user'])){
|
||||
$this->initShareOld();
|
||||
return;
|
||||
}
|
||||
$this->path = _DIR($this->in['path']);
|
||||
$this->shareInfo = $GLOBALS['kodShareInfo'];
|
||||
$user = systemMember::getInfo($GLOBALS['kodPathId']);
|
||||
|
||||
$userHome = user_home_path($user);
|
||||
define('USER',USER_PATH.$user['path'].'/');
|
||||
define('USER_TEMP',USER.'data/share_temp/');
|
||||
define('HOME',$userHome);
|
||||
}
|
||||
|
||||
private function checkShare(){
|
||||
$shareInfo = $this->shareInfo;
|
||||
if(!$this->shareInfo){
|
||||
$this->_error(LNG('share_error_user'));
|
||||
}
|
||||
if (isset($shareInfo['timeTo'])&&
|
||||
strlen($shareInfo['timeTo'])!=0) {
|
||||
$date = strtotime($shareInfo['timeTo']);
|
||||
if (time() > $date) {
|
||||
$this->_error(LNG('share_error_time'));
|
||||
}
|
||||
}
|
||||
//密码检测
|
||||
if ($shareInfo['sharePassword']=='') return;
|
||||
if (!isset($this->in['password'])){
|
||||
if ($_SESSION['password_'.$this->in['sid']]==$shareInfo['sharePassword']){
|
||||
return;
|
||||
}
|
||||
$this->_error('password');
|
||||
}else{
|
||||
if ($this->in['password'] == $shareInfo['sharePassword']) {
|
||||
session_start();
|
||||
$_SESSION['password_'.$this->in['sid']]=$shareInfo['sharePassword'];
|
||||
session_write_close();
|
||||
show_json('success');
|
||||
}else{
|
||||
show_json(LNG('share_error_password'),false);
|
||||
}
|
||||
}
|
||||
}
|
||||
private function initShareOld(){
|
||||
if (!isset($this->in['user']) || !isset($this->in['sid'])) {
|
||||
$this->_error(LNG('share_error_param'));
|
||||
}
|
||||
$member = systemMember::loadData();
|
||||
$user = $member->get($this->in['user']);
|
||||
if (!is_array($user) || !isset($user['password'])){
|
||||
$this->_error(LNG('share_error_user'));
|
||||
}
|
||||
|
||||
$userHome = user_home_path($user);
|
||||
define('USER',USER_PATH.$user['path'].'/');
|
||||
define('USER_TEMP',USER.'data/share_temp/');
|
||||
define('HOME',$userHome);
|
||||
$shareData = USER_PATH.$user['path'].'/data/share.php';
|
||||
if (!file_exists(iconv_system($shareData))) {
|
||||
$this->_error(LNG('share_error_user'));
|
||||
}
|
||||
$this->sql=new FileCache($shareData);
|
||||
$list = $this->sql->get();
|
||||
if (!isset($this->in['sid']) ||! $list[$this->in['sid']]){
|
||||
$this->_error(LNG('share_error_sid'));
|
||||
}
|
||||
$this->shareInfo = $list[$this->in['sid']];
|
||||
$sharePath = _DIR_CLEAR($this->shareInfo['path']);
|
||||
if ($user['role'] != '1') {
|
||||
$sharePath = HOME.ltrim($sharePath,'/');
|
||||
}
|
||||
if ($this->shareInfo['type'] != 'file'){
|
||||
$sharePath=rtrim($sharePath,'/').'/';
|
||||
}
|
||||
$sharePath = iconv_system($sharePath);
|
||||
if (!file_exists($sharePath)) {
|
||||
$this->_error(LNG('share_error_path'));
|
||||
}
|
||||
$this->sharePath = $sharePath;
|
||||
if($this->shareInfo['type'] == 'file'){
|
||||
$this->path = $sharePath;
|
||||
}else if(isset($this->in['path'])){
|
||||
$this->path = $sharePath.$this->_clear($this->in['path']);
|
||||
}else{
|
||||
$this->path = $sharePath;
|
||||
}
|
||||
$this->path = _DIR_CLEAR($this->path);
|
||||
$GLOBALS['kodPathPre'] = iconv_app(_DIR_CLEAR($sharePath));
|
||||
//debug_out($GLOBALS['kodPathPre'],$GLOBALS['kodPathId'],$this->shareInfo,$this->path,$sharePath);
|
||||
}
|
||||
private function _clear($path){
|
||||
return iconv_system(_DIR_CLEAR($path));
|
||||
}
|
||||
|
||||
|
||||
|
||||
private function _error($msg){
|
||||
$this->assign('configTheme','mac');
|
||||
$this->assign('msg',$msg);
|
||||
$this->display('tips.html');
|
||||
exit;
|
||||
}
|
||||
//==========================
|
||||
//页面统一注入变量
|
||||
private function _assignInfo(){
|
||||
$config = FileCache::load(USER.'data/config.php');
|
||||
if (count($config)<1) {
|
||||
$config = $GLOBALS['config']['settingDefault'];
|
||||
}
|
||||
$this->assign('configTheme',$config['theme']);
|
||||
$this->shareInfo['sharePassword'] = '';
|
||||
$this->shareInfo['path'] = get_path_this(iconv_app($this->path));
|
||||
$this->assign('shareInfo',$this->shareInfo);
|
||||
}
|
||||
|
||||
//下载次数统计
|
||||
private function _shareDownloadAdd(){
|
||||
$this->shareInfo['numDownload'] = abs(intval($this->shareInfo['numDownload'])) +1;
|
||||
$this->sql->set($this->in['sid'],$this->shareInfo);
|
||||
}
|
||||
|
||||
//==========================
|
||||
/*
|
||||
* 文件浏览
|
||||
*/
|
||||
public function file() {
|
||||
$this->shareViewAdd();
|
||||
if ($this->shareInfo['type']!='file') {
|
||||
//$this->shareInfo['name'] = get_path_this($this->path);
|
||||
}
|
||||
$size = filesize($this->path);
|
||||
$this->shareInfo['size'] = size_format($size);
|
||||
$this->_assignInfo();
|
||||
$this->display('file.html');
|
||||
}
|
||||
/*
|
||||
* 文件夹浏览
|
||||
*/
|
||||
public function folder() {
|
||||
$this->shareViewAdd();
|
||||
if(isset($this->in['path']) && $this->in['path'] !=''){
|
||||
$dir = '/'._DIR_CLEAR($this->in['path']);
|
||||
}else{
|
||||
$dir = '/';//首次进入系统,不带参数
|
||||
}
|
||||
$dir = '/'.trim($dir,'/').'/';
|
||||
$this->_assignInfo();
|
||||
$this->assign('dir',$dir);
|
||||
|
||||
if ($this->config['forceWap']) {
|
||||
$this->display('explorerWap.html');
|
||||
}else{
|
||||
$this->display('explorer.html');
|
||||
}
|
||||
}
|
||||
/*
|
||||
* 代码阅读
|
||||
*/
|
||||
public function codeRead() {
|
||||
$this->shareViewAdd();
|
||||
$this->_assignInfo();
|
||||
$this->display('editor.html');
|
||||
}
|
||||
//浏览次数统计
|
||||
private function shareViewAdd(){
|
||||
$this->shareInfo['numDownload'] = isset($this->shareInfo['numDownload'])?$this->shareInfo['numDownload']:0;
|
||||
$this->shareInfo['numView'] = isset($this->shareInfo['numView'])?$this->shareInfo['numView']:0;
|
||||
|
||||
$this->shareInfo['numView'] = abs(intval($this->shareInfo['numView'])) +1;
|
||||
$this->sql->set($this->in['sid'],$this->shareInfo);
|
||||
}
|
||||
public function commonJs(){
|
||||
$out = ob_get_clean();
|
||||
$versionDesc = isset($this->config['settings']['versionDesc'])?$this->config['settings']['versionDesc']:"";
|
||||
$theConfig = array(
|
||||
'environment' => STATIC_JS,
|
||||
'lang' => I18n::getType(),
|
||||
'systemOS' => $this->config['systemOS'],
|
||||
'isRoot' => 0,
|
||||
'webRoot' => '',
|
||||
'webHost' => HOST,
|
||||
'appHost' => APP_HOST,
|
||||
'staticPath' => STATIC_PATH,
|
||||
'appIndex' => $_SERVER['SCRIPT_NAME'],
|
||||
'version' => KOD_VERSION,
|
||||
'versionBuild' => KOD_VERSION_BUILD,
|
||||
'versionDesc' => $versionDesc,
|
||||
'kodID' => md5(BASIC_PATH.$this->config['settingSystem']['systemPassword']),
|
||||
|
||||
'jsonData' => "",
|
||||
'sharePage' => 'share',
|
||||
'settings' => array(
|
||||
'updloadChunkSize' => file_upload_size(),
|
||||
'updloadThreads' => $this->config['settings']['updloadThreads'],
|
||||
'updloadBindary' => $this->config['settings']['updloadBindary'],
|
||||
'uploadCheckChunk' => $this->config['settings']['uploadCheckChunk'],
|
||||
|
||||
'paramRewrite' => $this->config['settings']['paramRewrite'],
|
||||
'pluginServer' => $this->config['settings']['pluginServer'],
|
||||
//'appType' => $this->config['settings']['appType']
|
||||
),
|
||||
|
||||
//虚拟目录
|
||||
'KOD_GROUP_PATH' => KOD_GROUP_PATH,
|
||||
'KOD_GROUP_SHARE' => KOD_GROUP_SHARE,
|
||||
'KOD_USER_SELF' => KOD_USER_SELF,
|
||||
'KOD_USER_SHARE' => KOD_USER_SHARE,
|
||||
'KOD_USER_RECYCLE' => KOD_USER_RECYCLE,
|
||||
'KOD_USER_FAV' => KOD_USER_FAV,
|
||||
'KOD_GROUP_ROOT_SELF' => KOD_GROUP_ROOT_SELF,
|
||||
'KOD_GROUP_ROOT_ALL' => KOD_GROUP_ROOT_ALL,
|
||||
'ST' => $this->in['st'],
|
||||
'ACT' => $this->in['act'],
|
||||
);
|
||||
|
||||
if(ST.''.ACT == 'explorer.fileView'){
|
||||
unset($theConfig['sharePage']);
|
||||
}
|
||||
|
||||
$userConfig = $GLOBALS['config']['settingDefault'];
|
||||
if(isset($this->in['user'])){
|
||||
$member = systemMember::loadData();
|
||||
$user = $member->get($this->in['user']);
|
||||
$userConfig = FileCache::load(USER_PATH.$user['path'].'/'.'data/config.php');
|
||||
}
|
||||
|
||||
if(isset($this->config['settingSystem']['versionHash'])){
|
||||
$theConfig['versionHash'] = $this->config['settingSystem']['versionHash'];
|
||||
$theConfig['versionHashUser'] = $this->config['settingSystem']['versionHashUser'];
|
||||
}
|
||||
$theConfig['userConfig'] = $userConfig;
|
||||
$useTime = mtime() - $GLOBALS['config']['appStartTime'];
|
||||
|
||||
header("Content-Type: application/javascript; charset=utf-8");
|
||||
echo 'if(typeof(kodReady)=="undefined"){kodReady=[];}';
|
||||
Hook::trigger('user.commonJs.insert',$this->in['st'],$this->in['act']);
|
||||
echo ';AUTH=[];';
|
||||
echo 'G='.json_encode($theConfig).';';
|
||||
$lang = json_encode_force(I18n::getAll());
|
||||
if(!$lang){
|
||||
$lang = '{}';
|
||||
}
|
||||
echo 'LNG='.$lang.';G.useTime='.$useTime.';';
|
||||
}
|
||||
//chrome安装: 必须https;serviceWorker引入处理;manifest配置; [manifest.json配置目录同sw.js引入];
|
||||
public function manifest(){
|
||||
$json = file_get_contents(BASIC_PATH.'static/others/app/manifest.json');
|
||||
$name = stristr(I18n::getType(),'zh') ? '可道云':'kodExplorer';
|
||||
$static = STATIC_PATH == './static/' ? APP_HOST.'static/':STATIC_PATH;
|
||||
$assign = array(
|
||||
"{{name}}" => $name,
|
||||
"{{appDesc}}" => LNG('common.copyright.name'),
|
||||
"{{static}}" => $static,
|
||||
);
|
||||
$json = str_replace(array_keys($assign),array_values($assign),$json);
|
||||
header("Content-Type: application/javascript; charset=utf-8");
|
||||
echo $json;
|
||||
}
|
||||
public function manifestJS(){
|
||||
header("Content-Type: application/javascript; charset=utf-8");
|
||||
echo file_get_contents(BASIC_PATH.'static/others/app/sw.js');
|
||||
}
|
||||
|
||||
|
||||
//========ajax function============
|
||||
public function pathInfo(){
|
||||
$infoList = json_decode($this->in['dataArr'],true);
|
||||
foreach ($infoList as &$val) {
|
||||
$val['path'] = $this->sharePath.$this->_clear($val['path']);
|
||||
}
|
||||
$data = path_info_muti($infoList,LNG('time_type_info'));
|
||||
$data['path'] = _DIR_OUT($data['path']);
|
||||
|
||||
//属性查看,单个文件则生成临时下载地址。没有权限则不显示
|
||||
if (count($infoList)==1 && $infoList[0]['type']!='folder') {//单个文件
|
||||
$file = $infoList[0]['path'];
|
||||
if($this->shareInfo['notDownload']!='1'){
|
||||
$data['downloadPath'] = _make_file_proxy($file);
|
||||
}
|
||||
if($data['size'] < 100*1024|| isset($this->in['getMd5'])){
|
||||
$data['fileMd5'] = @md5_file($file);
|
||||
}else{
|
||||
$data['fileMd5'] = "...";
|
||||
}
|
||||
|
||||
//获取图片尺寸
|
||||
$ext = get_path_ext($file);
|
||||
if(in_array($ext,array('jpg','gif','png','jpeg','bmp')) ){
|
||||
$size = ImageThumb::imageSize($file);
|
||||
if($size){
|
||||
$data['imageSize'] = $size;
|
||||
}
|
||||
}
|
||||
}
|
||||
show_json($data);
|
||||
}
|
||||
public function fileSave(){
|
||||
show_json(LNG('no_permission'),false);
|
||||
}
|
||||
|
||||
// 单文件编辑
|
||||
public function edit(){
|
||||
$member = systemMember::loadData();
|
||||
$user = $member->get($this->in['user']);
|
||||
$codeConfig = FileCache::load(USER_PATH.$user['path'].'/data/editor_config.php');
|
||||
if(!is_array($codeConfig)){
|
||||
$codeConfig = $GLOBALS['config']['editorDefault'];
|
||||
}
|
||||
|
||||
$black_theme = array("ambiance","idle_fingers","monokai","pastel_on_dark","twilight",
|
||||
"solarized_dark","tomorrow_night_blue","tomorrow_night_eighties");
|
||||
$setClass = "";
|
||||
if(in_array($codeConfig['theme'],$black_theme)){
|
||||
$setClass = 'class="code-theme-black"';
|
||||
}
|
||||
$this->_assignInfo();
|
||||
$this->assign('editorConfig',json_encode($codeConfig));//获取编辑器配置信息
|
||||
$this->assign('codeThemeBlack',$setClass);//获取编辑器配置信息
|
||||
$this->display('edit.html');
|
||||
}
|
||||
|
||||
public function pathList(){
|
||||
$list=$this->_path($this->path);
|
||||
show_json($list);
|
||||
}
|
||||
public function treeList(){
|
||||
$path=$this->path;
|
||||
if (isset($this->in['project'])) {
|
||||
$path = $this->sharePath.$this->_clear($this->in['project']);
|
||||
}
|
||||
if (isset($this->in['path'])) {
|
||||
$path = $this->sharePath.$this->_clear($this->in['path']);
|
||||
}
|
||||
if (isset($this->in['name'])){
|
||||
$path=$path.'/'.$this->_clear($this->in['name']);
|
||||
}
|
||||
$listFile = ($this->in['app'] == 'editor'?true:false);//编辑器内列出文件
|
||||
$list=$this->_path($path,$listFile,true);
|
||||
function sort_by_key($a, $b){
|
||||
if ($a['name'] == $b['name']) return 0;
|
||||
return ($a['name'] > $b['name']) ? 1 : -1;
|
||||
}
|
||||
usort($list['folderList'], "sort_by_key");
|
||||
usort($list['fileList'], "sort_by_key");
|
||||
|
||||
$result = array_merge($list['folderList'],$list['fileList']);
|
||||
if ($this->in['app'] != 'editor') {
|
||||
$result =$list['folderList'];
|
||||
}
|
||||
if (isset($this->in['type']) && $this->in['type']=='init') {
|
||||
$result = array(
|
||||
array(
|
||||
'name' => iconv_app(get_path_this($path)),
|
||||
'children' => $result,
|
||||
//'menuType' => "menuTreeRoot",
|
||||
'open' => true,
|
||||
'type' => 'folder',
|
||||
'path' => '/',
|
||||
'isParent' => count($result)>0?true:false
|
||||
)
|
||||
);
|
||||
}
|
||||
show_json($result);
|
||||
}
|
||||
public function search(){
|
||||
if (!isset($this->in['search'])) show_json(LNG('please_inpute_search_words'),false);
|
||||
$isContent = intval($this->in['is_content']);
|
||||
$isCase = intval($this->in['is_case']);
|
||||
$ext= trim($this->in['ext']);
|
||||
$list = path_search(
|
||||
$this->path,
|
||||
rawurldecode($this->in['search']),
|
||||
$isContent,$ext,$isCase);
|
||||
|
||||
show_json(_DIR_OUT($list));
|
||||
}
|
||||
/**
|
||||
* 上传,html5拖拽 flash 多文件
|
||||
*/
|
||||
public function fileUpload(){
|
||||
$fileName = $_FILES['file']['name']? $_FILES['file']['name']:$GLOBALS['in']['name'];
|
||||
$GLOBALS['isRoot']=0;
|
||||
$GLOBALS['auth']['extNotAllow'] = "htm|html|php|phtml|pwml|asp|aspx|ascx|jsp|pl|htaccess|shtml|shtm|phtm";
|
||||
if(!checkExt($fileName)){
|
||||
show_json(LNG('no_permission_ext'),false);
|
||||
}
|
||||
$savePath = $this->sharePath.$this->_clear($this->in['upload_to']);
|
||||
if (!path_writeable($savePath)) show_json(LNG('no_permission_write'),false);
|
||||
|
||||
if ($savePath == '') show_json(LNG('upload_error_big'),false);
|
||||
if (strlen($this->in['fullPath']) > 1) {//folder drag upload
|
||||
$fullPath = _DIR_CLEAR(rawurldecode($this->in['fullPath']));
|
||||
$fullPath = get_path_father($fullPath);
|
||||
$fullPath = iconv_system($fullPath);
|
||||
if (mk_dir($savePath.$fullPath)) {
|
||||
$savePath = $savePath.$fullPath;
|
||||
}
|
||||
}
|
||||
|
||||
//分片上传
|
||||
$tempDir = iconv_system(USER_TEMP);
|
||||
mk_dir($tempDir);
|
||||
if (!path_writeable($tempDir)) show_json(LNG('no_permission_write'),false);
|
||||
upload($savePath,$tempDir,'rename');
|
||||
}
|
||||
|
||||
|
||||
//代理输出
|
||||
public function fileProxy(){
|
||||
$mime = get_file_mime(get_path_ext($this->path));
|
||||
if($mime == 'text/plain' && is_file($this->path)){//文本则转编码
|
||||
$fileContents = file_get_contents($this->path);
|
||||
$charset=get_charset($fileContents);
|
||||
if ($charset!='' || $charset!='utf-8') {
|
||||
$fileContents=mb_convert_encoding($fileContents,'utf-8',$charset);
|
||||
}
|
||||
echo $fileContents;
|
||||
return;
|
||||
}
|
||||
$download = isset($_GET['download']);
|
||||
$filename = isset($_GET['downFilename'])?$_GET['downFilename']:false;
|
||||
file_put_out($this->path,$download,$filename);
|
||||
}
|
||||
public function fileDownload(){
|
||||
$this->_shareDownloadAdd();
|
||||
file_put_out($this->path,true);
|
||||
}
|
||||
//文件下载后删除,用于文件夹下载
|
||||
public function fileDownloadRemove(){
|
||||
if ($this->shareInfo['notDownload']=='1') {
|
||||
show_json(LNG('share_not_download_tips'),false);
|
||||
}
|
||||
$path = get_path_this(_DIR_CLEAR($this->in['path']));
|
||||
$path = iconv_system(USER_TEMP.$path);
|
||||
file_put_out($path,true);
|
||||
del_file($path);
|
||||
}
|
||||
public function zipDownload(){
|
||||
$this->_shareDownloadAdd();
|
||||
$userTemp = iconv_system(USER_TEMP);
|
||||
if(!file_exists($userTemp)){
|
||||
mkdir($userTemp);
|
||||
}else{//清除未删除的临时文件,一天前
|
||||
$list = path_list($userTemp,true,false);
|
||||
$maxTime = 3600*24;
|
||||
if ($list['fileList']>=1) {
|
||||
for ($i=0; $i < count($list['fileList']); $i++) {
|
||||
$createTime = $list['fileList'][$i]['mtime'];//最后修改时间
|
||||
if(time() - $createTime >$maxTime){
|
||||
del_file($list['fileList'][$i]['path'].$list['fileList'][$i]['name']);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$zipFile = $this->zip($userTemp);
|
||||
show_json(LNG('zip_success'),true,get_path_this($zipFile));
|
||||
}
|
||||
private function zip($zipPath){
|
||||
if (!isset($zipPath)) {
|
||||
show_json(LNG('share_not_download_tips'),false);
|
||||
}
|
||||
ignore_timeout();
|
||||
|
||||
$zipList = json_decode($this->in['dataArr'],true);
|
||||
$listNum = count($zipList);
|
||||
$files = array();
|
||||
for ($i=0; $i < $listNum; $i++) {
|
||||
$item = $this->path.$this->_clear($zipList[$i]['path']);
|
||||
if(file_exists($item)){
|
||||
$files[] = $item;
|
||||
}
|
||||
}
|
||||
if(count($files)==0){
|
||||
show_json(LNG('not_exists'),false);
|
||||
}
|
||||
|
||||
|
||||
//指定目录
|
||||
if (count($files) == 1) {
|
||||
$pathThisName=get_path_this($files[0]);
|
||||
}else{
|
||||
$pathThisName=get_path_this(get_path_father($files[0]));
|
||||
}
|
||||
$zipname = $zipPath.$pathThisName.'.zip';
|
||||
$zipname = get_filename_auto($zipname,date('_H-i-s'));
|
||||
KodArchive::create($zipname,$files);
|
||||
return iconv_app($zipname);
|
||||
}
|
||||
|
||||
|
||||
// 获取文件数据
|
||||
public function fileGet(){
|
||||
if(isset($this->in['fileUrl'])){ //http
|
||||
$displayName = $this->in['name'];
|
||||
$filepath = $this->in['fileUrl'];
|
||||
if(!request_url_safe($filepath)){
|
||||
show_json(LNG('url error!'),false);
|
||||
}
|
||||
}else{
|
||||
$displayName = _DIR_CLEAR($this->in['filename']);
|
||||
$filepath= $this->sharePath.iconv_system($displayName);
|
||||
if (!path_readable($filepath)){
|
||||
show_json(LNG('no_permission_read'),false);
|
||||
}
|
||||
if (filesize($filepath) >= 1024*1024*20){
|
||||
show_json(LNG('edit_too_big'),false);
|
||||
}
|
||||
if (!file_exists($filepath)){
|
||||
show_json(LNG('not_exists'),false);
|
||||
}
|
||||
}
|
||||
|
||||
$fileContents=file_get_contents($filepath);//文件内容
|
||||
$charset=get_charset($fileContents);
|
||||
if ($charset!='' &&
|
||||
$charset!='utf-8' &&
|
||||
function_exists("mb_convert_encoding")
|
||||
){
|
||||
$fileContents=@mb_convert_encoding($fileContents,'utf-8',$charset);
|
||||
}
|
||||
$data = array(
|
||||
'ext' => get_path_ext($displayName),
|
||||
'name' => iconv_app(get_path_this($displayName)),
|
||||
'filename' => $displayName,
|
||||
'charset' => $charset,
|
||||
'base64' => true,// 部分防火墙编辑文件误判问题处理
|
||||
'content' => base64_encode($fileContents)
|
||||
);
|
||||
show_json($data);
|
||||
}
|
||||
|
||||
public function image(){
|
||||
$thumbWidth = 250;
|
||||
if(isset($this->in['thumbWidth'])){
|
||||
$thumbWidth = intval($this->in['thumbWidth']);//自定义预览大图
|
||||
}
|
||||
if(substr($this->path,0,4) == 'http'){
|
||||
header('Location: '.$this->in['path']);
|
||||
exit;
|
||||
}
|
||||
if (@filesize($this->path) <= 1024*50 ||
|
||||
!function_exists('imagecolorallocate') ||
|
||||
get_path_ext($this->path) == 'gif') {//小于50k、不支持gd库、gif图 不再生成缩略图
|
||||
file_put_out($this->path,false);
|
||||
return;
|
||||
}
|
||||
if (!is_dir(DATA_THUMB)){
|
||||
mk_dir(DATA_THUMB);
|
||||
}
|
||||
$image = $this->path;
|
||||
$imageMd5 = @md5_file($image).'_'.$thumbWidth;//文件md5
|
||||
if (strlen($imageMd5)<5) {
|
||||
$imageMd5 = md5($image).'_'.$thumbWidth;
|
||||
}
|
||||
$imageThumb = DATA_THUMB.$imageMd5.'.png';
|
||||
if (!file_exists($imageThumb)){//如果拼装成的url不存在则没有生成过
|
||||
if (get_path_father($image)==DATA_THUMB){//当前目录则不生成缩略图
|
||||
$imageThumb=$this->path;
|
||||
}else {
|
||||
$cm = new ImageThumb($image,'file');
|
||||
$cm->prorate($imageThumb,$thumbWidth,$thumbWidth);//生成等比例缩略图
|
||||
}
|
||||
}
|
||||
if (!file_exists($imageThumb) ||
|
||||
filesize($imageThumb)<100){//缩略图生成失败则使用原图
|
||||
$imageThumb=$this->path;
|
||||
}
|
||||
file_put_out($imageThumb,false);
|
||||
file_put_out($imageThumb);//输出
|
||||
}
|
||||
|
||||
//获取文件列表&哦exe文件json解析
|
||||
private function _path($dir,$listFile=true,$check_children=false){
|
||||
$list = path_list($dir,$listFile,true);
|
||||
$listNew = array('fileList'=>array(),'folderList'=>array());
|
||||
$pathHidden = $this->config['settingSystem']['pathHidden'];
|
||||
$exName = explode(',',$pathHidden);
|
||||
foreach ($list['fileList'] as $key => $val) {
|
||||
if (in_array($val['name'],$exName)) continue;
|
||||
if ($val['ext'] == 'oexe'){
|
||||
$path = iconv_system($val['path']);
|
||||
$json = json_decode(@file_get_contents($path),true);
|
||||
if(is_array($json)) $val = array_merge($val,$json);
|
||||
}
|
||||
$listNew['fileList'][] = $val;
|
||||
}
|
||||
foreach ($list['folderList'] as $key => $val) {
|
||||
if (in_array($val['name'],$exName)) continue;
|
||||
$listNew['folderList'][] = $val;
|
||||
}
|
||||
$s = _DIR_OUT($listNew);
|
||||
return _DIR_OUT($listNew);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,279 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
//群组管理【管理员调用,or组空间大小变更】
|
||||
//根目录id为1==》共享空间
|
||||
class systemGroup extends Controller{
|
||||
public static $staticSql = null;
|
||||
private $sql;
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->sql= self::loadData();
|
||||
$this->_init();
|
||||
}
|
||||
|
||||
//保证只加载一次文件
|
||||
public static function loadData(){
|
||||
if(is_null(self::$staticSql)){
|
||||
self::$staticSql = systemGroupData();
|
||||
}
|
||||
return self::$staticSql;
|
||||
}
|
||||
public static function getInfo($theId){
|
||||
$sql = self::loadData();
|
||||
return $sql->get($theId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 空间使用变更
|
||||
* @param [type] $theId [userID or groupID]
|
||||
* @param [type] $sizeAdd [变更的大小 sizeMax G为单位 sizeUse Byte为单位]
|
||||
*/
|
||||
public static function spaceChange($theId,$sizeAdd=false){
|
||||
$sql = self::loadData();
|
||||
$info = $sql->get($theId);
|
||||
if(!is_array($info)){
|
||||
show_json(LNG('data_not_full'),false);
|
||||
}
|
||||
if($sizeAdd===false){//重置用户空间;避免覆盖、解压等导致的问题
|
||||
$pathinfo = _path_info_more(GROUP_PATH.$info['path'].'/');
|
||||
$currentUse = $pathinfo['size'];
|
||||
if(isset($info['homePath']) && file_exists(iconv_system($info['homePath']))){
|
||||
$pathinfo = _path_info_more(iconv_system($info['homePath']));
|
||||
$currentUse += $pathinfo['size'];
|
||||
}
|
||||
}else{
|
||||
$currentUse = floatval($info['config']['sizeUse'])+floatval($sizeAdd);
|
||||
}
|
||||
$info['config']['sizeUse'] = $currentUse<0?0:$currentUse;
|
||||
$sql->set($theId,$info);
|
||||
}
|
||||
|
||||
/**
|
||||
* 空间剩余检测
|
||||
* 1073741824 —— 1G
|
||||
*/
|
||||
public static function spaceCheck($theId){
|
||||
$sql = self::loadData();
|
||||
$info = $sql->get($theId);
|
||||
if(!is_array($info)){
|
||||
show_json(LNG('data_not_full'),false);
|
||||
}
|
||||
$sizeUse = floatval($info['config']['sizeUse']);
|
||||
$sizeMax = floatval($info['config']['sizeMax']);
|
||||
if($sizeMax!=0 && $sizeMax*1073741824<$sizeUse){
|
||||
show_json(LNG('space_is_full'),false);
|
||||
}
|
||||
}
|
||||
|
||||
//管理员调用
|
||||
//===================
|
||||
private function _init(){
|
||||
if(count($this->sql->get()) > 0) return;
|
||||
$default = array(
|
||||
'1' =>array(
|
||||
'groupID' => '1',
|
||||
'name' => 'root',
|
||||
'parentID' => '',
|
||||
'children' => '',
|
||||
'config' => array('sizeMax' => floatval(1.5),
|
||||
'sizeUse' => floatval(1024*1024)),//总大小,目前使用大小
|
||||
'path' => 'root',
|
||||
'createTime'=> time(),
|
||||
)
|
||||
);
|
||||
$this->sql->reset($default);
|
||||
$this->initDir($default[0]['path']);
|
||||
}
|
||||
//删除 path id
|
||||
public static function _filterList($list,$filter_key = 'path'){
|
||||
if($GLOBALS['isRoot']) return $list;
|
||||
foreach ($list as $key => &$val) {
|
||||
unset($val[$filter_key]);
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
public function get() {
|
||||
$items = self::_filterList($this->sql->get());
|
||||
show_json($items,true);
|
||||
}
|
||||
|
||||
/**
|
||||
* 群组添加
|
||||
* systemGroup/add&name=t1&parentID=101&sizeMax=0
|
||||
*/
|
||||
public function add(){
|
||||
if (!isset($this->in['name']) || //必填项
|
||||
!isset($this->in['parentID']) ||
|
||||
!isset($this->in['sizeMax'])
|
||||
) show_json(LNG('data_not_full'),false);
|
||||
|
||||
//名称可以重复
|
||||
$groupID = $this->sql->getMaxId().'';
|
||||
$groupName = rawurldecode($this->in['name']);
|
||||
$groupInfo = array(
|
||||
'groupID' => $groupID,
|
||||
'name' => $groupName,
|
||||
'parentID' => $this->in['parentID'],
|
||||
'children' => '',
|
||||
'config' => array('sizeMax' => floatval($this->in['sizeMax']),//G
|
||||
'sizeUse' => floatval(1024*1024)),//总大小,目前使用大小
|
||||
'path' => make_path($groupName),
|
||||
'createTime'=> time(),
|
||||
);
|
||||
if(file_exists(iconv_system(GROUP_PATH.$groupInfo['path'])) ){
|
||||
$groupInfo['path'] = make_path($groupInfo['path'].'_'.$groupInfo['groupID']);
|
||||
}
|
||||
|
||||
//用户组目录
|
||||
if( isset($this->in['homePath'])){
|
||||
$homePath = _DIR(rawurldecode($this->in['homePath']));
|
||||
if(file_exists($homePath)){
|
||||
$groupInfo['homePath'] = iconv_app($homePath);
|
||||
}
|
||||
}else{
|
||||
unset($groupInfo['homePath']);
|
||||
}
|
||||
$this->_parentChildChange($groupInfo,true);//更新父节点
|
||||
if ($this->sql->set($groupID,$groupInfo)) {
|
||||
$this->initDir($groupInfo['path']);
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑 systemGroup/edit&groupID=101&name=warlee&sizeMax=0
|
||||
*/
|
||||
public function edit() {
|
||||
if (!$this->in['groupID']) show_json(LNG('data_not_full'),false);
|
||||
$groupInfo = $this->sql->get($this->in['groupID']);
|
||||
if(!is_array($groupInfo)){//用户不存在
|
||||
show_json(LNG('not_exists'),false);
|
||||
}
|
||||
|
||||
//name sizeMax parentID
|
||||
if(isset($this->in['name'])){
|
||||
$groupInfo['name'] = rawurldecode($this->in['name']);
|
||||
}
|
||||
if(isset($this->in['sizeMax'])){
|
||||
$groupInfo['config']['sizeMax'] = floatval($this->in['sizeMax']);
|
||||
}
|
||||
if( isset($this->in['parentID']) &&
|
||||
$groupInfo['parentID']!= '' && //根目录不能修改父节点
|
||||
$this->in['parentID']!=$groupInfo['parentID']){//父节点变更
|
||||
|
||||
$childChange = explode(',',$groupInfo['children']);
|
||||
if( in_array($this->in['parentID'],$childChange)
|
||||
|| $this->in['parentID'] == $this->in['groupID']){//不能移动到子节点;死循环
|
||||
show_json(LNG('current_has_parent'),false);
|
||||
}
|
||||
self::spaceChange($this->in['groupID']);//重置用户使用空间
|
||||
$this->_parentChildChange($groupInfo,false);//向所有父节点,删除包含此节点的children
|
||||
$groupInfo['parentID'] = $this->in['parentID'];
|
||||
$this->_parentChildChange($groupInfo,true);//向所有新的父节点,添加包含此节点的children
|
||||
}
|
||||
|
||||
//用户组目录
|
||||
if( isset($this->in['homePath'])){
|
||||
$groupInfo['homePath'] = _DIR(rawurldecode($this->in['homePath']));
|
||||
if(!file_exists($groupInfo['homePath'])){
|
||||
show_json(LNG('not_exists'),false);
|
||||
}
|
||||
$groupInfo['homePath'] = iconv_app($groupInfo['homePath']);
|
||||
}else{
|
||||
unset($groupInfo['homePath']);
|
||||
}
|
||||
if($groupInfo != $this->sql->get($this->in['groupID'])){
|
||||
$this->sql->set($this->in['groupID'],$groupInfo);
|
||||
}
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除 ?systemMember/del&userID=102
|
||||
*/
|
||||
public function del() {
|
||||
if (!isset($this->in['groupID'])) show_json(LNG('data_not_full'),false);
|
||||
if (strlen($this->in['groupID']) <= 1) show_json(LNG('default_user_can_not_do'),false);
|
||||
$groupInfo = $this->sql->get($this->in['groupID']);
|
||||
$this->_parentChildChange($groupInfo,false);//向所有父节点,删除包含此节点的children
|
||||
$this->sql->set(//将该节点的子节点的父节点设置为根目录
|
||||
array('parentID',$groupInfo["groupID"]),
|
||||
array('parentID','1')
|
||||
);
|
||||
systemMember::groupRemoveUserUpdate($groupInfo["groupID"]);//用户所在组变更
|
||||
$this->sql->remove($this->in['groupID']);
|
||||
|
||||
if( strlen($groupInfo['path'])!=0){
|
||||
del_dir(iconv_system(GROUP_PATH.$groupInfo['path'].'/'));
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
|
||||
|
||||
//============内部处理函数=============
|
||||
//回溯更改节点的children
|
||||
private function _parentChildChange($groupInfo,$isAdd){
|
||||
if(!is_array($groupInfo)){
|
||||
show_json(LNG('not_exists'),false);
|
||||
}
|
||||
if($groupInfo['parentID'] == 1){
|
||||
return;
|
||||
}
|
||||
$childChange = explode(',',$groupInfo['children']);
|
||||
if($childChange[0]==''){
|
||||
unset($childChange[0]);
|
||||
}
|
||||
$childChange[] = $groupInfo['groupID'];//包含当前
|
||||
while(strlen($groupInfo['groupID'])>2){//节点id从100开始
|
||||
$groupInfo = $this->sql->get($groupInfo['parentID']);
|
||||
if(!is_array($groupInfo)){
|
||||
show_json(LNG('not_exists'),false);
|
||||
}
|
||||
$childrenNew = explode(',',$groupInfo['children']);
|
||||
if($childrenNew[0]==''){
|
||||
unset($childrenNew[0]);
|
||||
}
|
||||
if($isAdd){//添加
|
||||
foreach ($childChange as $key=>$val) {
|
||||
$childrenNew[] = $val;
|
||||
}
|
||||
}else{//删除
|
||||
foreach ($childrenNew as $key=>$val) {
|
||||
if(in_array($val,$childChange))
|
||||
unset($childrenNew[$key]);
|
||||
}
|
||||
}
|
||||
$childStr = implode(',',$childrenNew);
|
||||
if($childStr != $groupInfo['children']){//有变更
|
||||
$groupInfo['children'] = $childStr;
|
||||
$this->sql->set($groupInfo['groupID'],$groupInfo);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
/**
|
||||
*初始化用户数据和配置。
|
||||
*/
|
||||
public function initDir($path){
|
||||
$root = array('home','data');
|
||||
$newGroupFolder = $this->config['settingSystem']['newGroupFolder'];
|
||||
$home = explode(',',$newGroupFolder);
|
||||
$path = GROUP_PATH.$path.'/';
|
||||
foreach ($root as $dir) {
|
||||
mk_dir(iconv_system($path.$dir));
|
||||
}
|
||||
foreach ($home as $dir) {
|
||||
mk_dir(iconv_system($path.'home/'.$dir));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,529 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
//用户管理【管理员配置用户,or用户空间大小变更】
|
||||
class systemMember extends Controller{
|
||||
public static $staticSql = null;
|
||||
private $sql;
|
||||
function __construct() {
|
||||
parent::__construct();
|
||||
$this->tpl = TEMPLATE.'member/';
|
||||
$this->sql= self::loadData();
|
||||
}
|
||||
|
||||
//保证只加载一次文件
|
||||
public static function loadData(){
|
||||
if(is_null(self::$staticSql)){
|
||||
self::$staticSql = systemMemberData();
|
||||
}
|
||||
return self::$staticSql;
|
||||
}
|
||||
public static function getInfo($theId){
|
||||
$sql = self::loadData();
|
||||
return $sql->get($theId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 空间使用变更
|
||||
* @param [type] $theId [userID or groupID]
|
||||
* @param [type] $sizeAdd [变更的大小 sizeMax G为单位 sizeUse Byte为单位]
|
||||
*/
|
||||
public static function spaceChange($theId,$sizeAdd=false){
|
||||
$sql = self::loadData();
|
||||
$info = $sql->get($theId);
|
||||
if(!is_array($info)){
|
||||
show_json(LNG('data_not_full'),false);
|
||||
}
|
||||
if($sizeAdd===false){//重置用户空间;避免覆盖、解压等导致的问题
|
||||
$pathinfo = _path_info_more(iconv_system(USER_PATH.$info['path'].'/'));
|
||||
$currentUse = $pathinfo['size'];
|
||||
if(isset($info['homePath']) && file_exists(iconv_system($info['homePath']))){
|
||||
$pathinfo = _path_info_more(iconv_system($info['homePath']));
|
||||
$currentUse += $pathinfo['size'];
|
||||
}
|
||||
}else{
|
||||
$currentUse = floatval($info['config']['sizeUse'])+floatval($sizeAdd);
|
||||
}
|
||||
$info['config']['sizeUse'] = $currentUse<0?0:$currentUse;
|
||||
$sql->set($theId,$info);
|
||||
}
|
||||
/**
|
||||
* 空间剩余检测
|
||||
* 1073741824 —— 1G
|
||||
*/
|
||||
public static function spaceCheck($theId){
|
||||
$sql = self::loadData();
|
||||
$info = $sql->get($theId);
|
||||
if(!is_array($info)){
|
||||
show_json(LNG('data_not_full'),false);
|
||||
}
|
||||
$sizeUse = floatval($info['config']['sizeUse']);
|
||||
$sizeMax = floatval($info['config']['sizeMax']);
|
||||
if($sizeMax!=0 && $sizeMax*1073741824<$sizeUse){
|
||||
show_json(LNG('space_is_full'),false);
|
||||
}
|
||||
}
|
||||
|
||||
// 组删除后,所属该组的用户都删除;全局调用
|
||||
public static function groupRemoveUserUpdate($groupID){
|
||||
$sql = self::loadData();
|
||||
$userAll = $sql->get();
|
||||
foreach ($userAll as $key => $val) {
|
||||
if(in_array($groupID,array_keys($val['groupInfo']))){
|
||||
unset($val['groupInfo'][$groupID]);
|
||||
$sql->set($val['userID'],$val);
|
||||
}
|
||||
}
|
||||
}
|
||||
// 权限组删除,所属该组的用户删除权限id
|
||||
public static function roleRemoveUserUpdate($roleId){
|
||||
$sql = self::loadData();
|
||||
$userAll = $sql->get();
|
||||
foreach ($userAll as $key => $val) {
|
||||
if($val['role'] == $roleId){
|
||||
$val['role'] = '';
|
||||
$sql->set($val['userID'],$val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//获取当前用户在某个群组的权限id; false|[id]
|
||||
//兼容旧版本 'read'|'write'|false
|
||||
public static function userAuthGroup($groupID){
|
||||
$result = self::_userAuthGroupRole($groupID);
|
||||
if($result === false) return false;
|
||||
|
||||
$result = $result == 'read' ? "1" : $result;
|
||||
$result = $result == 'write' ? "2" : $result;
|
||||
if(!is_array($GLOBALS['config']['pathRoleGroup'][$result])){
|
||||
$result = "1";
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
//获取在某个组的用户
|
||||
public static function userAtGroup($groupID){
|
||||
$sql = self::loadData();
|
||||
$allUser = self::_filterList($sql->get());
|
||||
if($groupID=='0'){
|
||||
return $allUser;
|
||||
}
|
||||
$selectUser = array();
|
||||
foreach ($allUser as $val) {
|
||||
if(isset($val['groupInfo'][$groupID])){
|
||||
$selectUser[] = $val;
|
||||
}
|
||||
}
|
||||
return $selectUser;
|
||||
}
|
||||
|
||||
|
||||
//缓存用户共享对象=======================================
|
||||
public static function userShareSql($userID){
|
||||
static $userShareArr;
|
||||
if(!is_array($userShareArr)){
|
||||
$userShareArr = array();
|
||||
}
|
||||
if(!isset($userShareArr[$userID])){
|
||||
$userInfo = systemMember::getInfo($userID);
|
||||
if(!isset($userInfo['path'])){
|
||||
return;
|
||||
}
|
||||
$sql = new FileCache(USER_PATH.$userInfo['path'].'/data/share.php');
|
||||
$userShareArr[$userID] = $sql;
|
||||
}
|
||||
return $userShareArr[$userID];
|
||||
}
|
||||
//获取某个用户共享列表
|
||||
public static function userShareList($userID){
|
||||
$sql = self::userShareSql($userID);
|
||||
$list = $sql->get();
|
||||
if($userID == $_SESSION['kodUser']['userID']){//自己的列表则展示密码;否则清空密码
|
||||
return $list;
|
||||
}
|
||||
|
||||
//含有密码则不罗列
|
||||
foreach($list as $key=>&$val){
|
||||
if($val['sharePassword']){
|
||||
unset($list[$key]);
|
||||
}
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
//获取某个用户某个共享
|
||||
public static function userShareGet($userID,$name){
|
||||
$sql = self::userShareSql($userID);
|
||||
return $sql->get('name',$name);
|
||||
}
|
||||
|
||||
//判断自己对某个组的权限 return false/'read'/'write'
|
||||
public static function _userAuthGroupRole($groupID){
|
||||
$sql = self::loadData();
|
||||
$userInfo = $sql->get($_SESSION['kodUser']['userID']);
|
||||
$groupInfo = $userInfo['groupInfo'];//自己所在的组
|
||||
if(!is_array($groupInfo)){
|
||||
return false;
|
||||
}
|
||||
if(isset($groupInfo[$groupID])){
|
||||
return $groupInfo[$groupID];
|
||||
}
|
||||
|
||||
$role = false;
|
||||
$plist = array();
|
||||
foreach ($groupInfo as $key => $value) {//
|
||||
$group = systemGroup::getInfo($key);//测试组,是否在用户所在组的子组
|
||||
$arr = explode(',',$group['children']);
|
||||
if (in_array($groupID,$arr)) {
|
||||
//return $groupInfo[$key]; // 找到最近的父级部门,而非第一个
|
||||
if(empty($plist)){
|
||||
$plist = $arr;
|
||||
$role = $groupInfo[$key];
|
||||
}else if(in_array($group['groupID'], $plist)){
|
||||
$plist = $arr;
|
||||
$role = $groupInfo[$key];
|
||||
}
|
||||
}
|
||||
}
|
||||
return $role;
|
||||
}
|
||||
|
||||
//删除 path id
|
||||
public static function _filterList($list,$filter_key = 'path'){
|
||||
if($GLOBALS['isRoot']) return $list;
|
||||
foreach ($list as $key => &$val) {
|
||||
unset($val[$filter_key]);
|
||||
unset($val['password']);
|
||||
}
|
||||
return $list;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//后台管理=====================
|
||||
//管理员调用===================
|
||||
/**
|
||||
* 获取用户列表数据,根据用户组筛选;默认输出所有用户
|
||||
*/
|
||||
public function get($groupID='0') {
|
||||
$result = self::userAtGroup($groupID);
|
||||
foreach($result as $key=>&$val){
|
||||
unset($val['password']);
|
||||
}
|
||||
show_json($result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取用户列表数据,根据用户组筛选;默认输出所有用户
|
||||
*/
|
||||
public function getByName($name = '') {
|
||||
if(!$name){
|
||||
$name = $this->in['name'];
|
||||
}
|
||||
$result = $this->sql->get(array('name',$name));
|
||||
if(is_array($result) && count($result)>0){
|
||||
$arr = array_values($result);
|
||||
unset($arr[0]['password']);
|
||||
show_json($arr[0]);
|
||||
}
|
||||
show_json(LNG("not_exists"),false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户添加
|
||||
* systemMember/add&name=warlee&password=123&sizeMax=0&groupInfo={"0":"read","10":"write"}&role=default
|
||||
*/
|
||||
public function add($user = false){
|
||||
if (!isset($this->in['name']) || //必填项
|
||||
!isset($this->in['password']) ||
|
||||
!isset($this->in['role']) ||
|
||||
!isset($this->in['groupInfo']) || //{"0":"read","100":"read"}
|
||||
!isset($this->in['sizeMax'])
|
||||
){
|
||||
show_json(LNG('data_not_full'),false);
|
||||
}
|
||||
|
||||
$name = trim(rawurldecode($this->in['name']));
|
||||
$password = rawurldecode($this->in['password']);
|
||||
$groupInfo = json_decode(rawurldecode($this->in['groupInfo']),true);
|
||||
if(!is_array($groupInfo)){
|
||||
show_json(LNG('systemMember_group_error'),false);
|
||||
}
|
||||
if($this->sql->get(array('name',$name))){
|
||||
show_json(LNG('error_repeat'),false,$name);
|
||||
}
|
||||
|
||||
//非系统管理员,不能添加系统管理员
|
||||
if(!$GLOBALS['isRoot'] && $this->in['role']=='1'){
|
||||
show_json(LNG('group_role_error'),false);
|
||||
}
|
||||
|
||||
$userArray = array();
|
||||
if(isset($this->in['isImport'])){
|
||||
$arr = explode("\n",$name);
|
||||
foreach($arr as $v){
|
||||
if(trim($v)!=''){
|
||||
$userArray[] = trim($v);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
$userArray[] = $name;
|
||||
}
|
||||
$nickName = 0;
|
||||
if(isset($this->in['nickName'])){
|
||||
$nickName = trim(rawurldecode($this->in['nickName']));
|
||||
}
|
||||
|
||||
|
||||
//批量添加
|
||||
$errorArr = array();
|
||||
foreach ($userArray as $val) {
|
||||
if($this->sql->get('name',$val)){//已存在
|
||||
$errorArr[] = $val;
|
||||
continue;
|
||||
}
|
||||
$userID = $this->sql->getMaxId().'';
|
||||
$userInfo = array(
|
||||
'userID' => $userID,
|
||||
'name' => $val,
|
||||
'nickName' => $nickName ? $nickName : $val,
|
||||
'password' => md5($password),
|
||||
'role' => $this->in['role'],
|
||||
'config' => array('sizeMax' => floatval($this->in['sizeMax']),//M
|
||||
'sizeUse' => 1024*1024),//总大小,目前使用大小
|
||||
'groupInfo' => $groupInfo,
|
||||
'path' => make_path($val),
|
||||
'status' => 1, //0禁用;1启用
|
||||
'lastLogin' => '', //最后登录时间 首次登陆则激活
|
||||
'createTime'=> time(),
|
||||
);
|
||||
|
||||
if(file_exists(iconv_system(USER_PATH.$userInfo['path'])) ){
|
||||
$userInfo['path'] = $userInfo['path'].'_'.$userInfo['userID'];
|
||||
}
|
||||
//用户组目录
|
||||
if( isset($this->in['homePath'])){
|
||||
$homePath = _DIR(rawurldecode($this->in['homePath']));
|
||||
if(file_exists($homePath)){
|
||||
$userInfo['homePath'] = iconv_app($homePath);
|
||||
}
|
||||
}else{
|
||||
unset($userInfo['homePath']);
|
||||
}
|
||||
if ($this->sql->set($userID,$userInfo)) {
|
||||
$this->initDir($userInfo['path']);
|
||||
}else{
|
||||
$errorArr[] = $val;
|
||||
}
|
||||
}
|
||||
|
||||
$success = count($userArray)-count($errorArr);
|
||||
$msg = LNG('success');
|
||||
if(count($errorArr) > 0 ){
|
||||
$msg = LNG('word_success').' : '.$success.', ';//部分失败
|
||||
if($success == 0 ){
|
||||
$msg = LNG('error_repeat');
|
||||
}
|
||||
$msg .= LNG('word_error').' : '.count($errorArr);
|
||||
}
|
||||
if($success==count($userArray)){
|
||||
show_json($msg,true,$success);
|
||||
}else{
|
||||
show_json($msg,false,implode("\n",$errorArr));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑 systemMember/edit&userID=101&name=warlee&password=123&sizeMax=0
|
||||
* &groupInfo={%220%22:%22read%22,%22100%22:%22read%22}&role=default
|
||||
*/
|
||||
public function edit() {
|
||||
if (!$this->in['userID']) show_json(LNG('data_not_full'),false);
|
||||
|
||||
$userID = $this->in['userID'];
|
||||
$userInfo = $this->sql->get($userID);
|
||||
if(!$userInfo){//用户不存在,或者默认用户不能修改
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
//非系统管理员,不能将别人设置为系统管理员
|
||||
if(!$GLOBALS['isRoot'] && $this->in['role']=='1'){
|
||||
show_json(LNG('group_role_error'),false);
|
||||
}
|
||||
//非系统管理员,不能修改系统管理员
|
||||
if(!$GLOBALS['isRoot'] && $userInfo['role']=='1'){
|
||||
show_json(LNG('group_role_error_admin'),false);
|
||||
}
|
||||
|
||||
//管理员自己不能添加自己到非管理员组
|
||||
if($GLOBALS['isRoot']
|
||||
&& $_SESSION['kodUser']['userID']==$userID
|
||||
&& $this->in['role']!='1'){
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
|
||||
//修改为一个已存在的名字则提示
|
||||
$theName = trim(rawurldecode($this->in['name']));
|
||||
if($userInfo['name']!=$theName){
|
||||
if($this->sql->get(array('name',$theName))){
|
||||
show_json(LNG('error_repeat'),false);
|
||||
}
|
||||
}
|
||||
|
||||
$this->in['name'] = rawurlencode($theName);//还原
|
||||
$editArr = array('name','nickName','role','password','groupInfo','homePath','status','sizeMax');
|
||||
foreach ($editArr as $key) {
|
||||
if(!isset($this->in[$key])) continue;
|
||||
$userInfo[$key] = rawurldecode($this->in[$key]);
|
||||
if($key == 'password'){
|
||||
$userInfo['password'] = md5($userInfo[$key]);
|
||||
}else if($key == 'sizeMax'){
|
||||
$userInfo['config']['sizeMax'] = floatval($userInfo[$key]);
|
||||
}else if($key == 'groupInfo'){//分组信息
|
||||
$userInfo['groupInfo'] = json_decode(rawurldecode($this->in['groupInfo']),true);
|
||||
}
|
||||
}
|
||||
|
||||
//用户组目录
|
||||
if( isset($this->in['homePath'])){
|
||||
$userInfo['homePath'] = _DIR(rawurldecode($this->in['homePath']));
|
||||
if(!file_exists($userInfo['homePath'])){
|
||||
show_json(LNG('not_exists'),false);
|
||||
}
|
||||
$userInfo['homePath'] = iconv_app($userInfo['homePath']);
|
||||
}else{
|
||||
unset($userInfo['homePath']);
|
||||
}
|
||||
if($this->sql->set($userID,$userInfo)){
|
||||
//self::spaceChange($userID);//重置用户使用空间
|
||||
show_json(LNG('success'),true,$userInfo);
|
||||
}
|
||||
show_json(LNG('error_repeat'),false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户批量操作 systemMember/doAction&action=&userID=[101,222,131]¶m=
|
||||
* action :
|
||||
* -------------
|
||||
* del 删除用户
|
||||
* statusSet 启用&禁用 param=0/1
|
||||
* roleSet 权限组 param=roleID
|
||||
* groupReset 重置分组 param=group_json
|
||||
* groupRemoveFrom 从某个组删除 param=groupID
|
||||
* groupAdd 添加到某个分组 param=group_json
|
||||
*/
|
||||
public function doAction() {
|
||||
if (!isset($this->in['userID'])){
|
||||
show_json(LNG('username_can_not_null'),false);
|
||||
}
|
||||
$action = $this->in['action'];
|
||||
$userArr = json_decode($this->in['userID'],true);
|
||||
if(!is_array($userArr)){
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
if (in_array('1', $userArr)){//批量处理,不处理系统管理员admin
|
||||
show_json(LNG('default_user_can_not_do'),false);
|
||||
}
|
||||
foreach ($userArr as $userID) {
|
||||
switch ($action) {
|
||||
case 'del'://删除
|
||||
$userInfo = $this->sql->get($userID);
|
||||
if($this->sql->remove($userID) && $userInfo['name']!=''){
|
||||
del_dir(iconv_system(USER_PATH.$userInfo['path'].'/'));
|
||||
}
|
||||
break;
|
||||
case 'statusSet'://禁用&启用
|
||||
$status = intval($this->in['param']);
|
||||
$this->sql->set(array('userID',$userID),array('status',$status));
|
||||
break;
|
||||
case 'spaceSet'://批量设置用户空间大小
|
||||
$value = intval($this->in['param']);
|
||||
$userInfo = $this->sql->get($userID);
|
||||
$userInfo['config']['sizeMax'] = $value;
|
||||
$this->sql->set($userID,$userInfo);
|
||||
break;
|
||||
case 'roleSet'://设置权限组
|
||||
$role = $this->in['param'];
|
||||
//非系统管理员,不能将别人设置为系统管理员
|
||||
if(!$GLOBALS['isRoot'] && $role=='1'){
|
||||
show_json(LNG('group_role_error'),false);
|
||||
}
|
||||
$this->sql->set(array('userID',$userID),array('role',$role));
|
||||
break;
|
||||
case 'groupReset'://设置分组
|
||||
$groupArr = json_decode($this->in['param'],true);
|
||||
if(!is_array($groupArr)){
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
$this->sql->set(array('userID',$userID),array('groupInfo',$groupArr));
|
||||
break;
|
||||
case 'groupRemoveFrom'://从某个组移除
|
||||
$groupID = $this->in['param'];
|
||||
$userInfo = $this->sql->get($userID);
|
||||
unset($userInfo['groupInfo'][$groupID]);
|
||||
$this->sql->set($userID,$userInfo);
|
||||
break;
|
||||
case 'groupAdd'://添加到某个组
|
||||
$groupArr = json_decode($this->in['param'],true);
|
||||
if(!is_array($groupArr)){
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
$userInfo = $this->sql->get($userID);
|
||||
foreach ($groupArr as $key => $value) {
|
||||
$userInfo['groupInfo'][$key] = $value;
|
||||
}
|
||||
$this->sql->set($userID,$userInfo);
|
||||
default:break;
|
||||
}
|
||||
}
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
|
||||
public function initInstall(){
|
||||
$sql = systemMember::loadData();
|
||||
$list = $sql->get();
|
||||
foreach ($list as $id => &$info) {//创建用户目录及初始化
|
||||
$path = make_path($info['name']);
|
||||
$this->initDir($path);
|
||||
$info['path'] = $path;
|
||||
$info['createTime'] = time();
|
||||
}
|
||||
$sql->reset($list);
|
||||
|
||||
//初始化群组目录
|
||||
$homeFolders = explode(',',$this->config['settingSystem']['newGroupFolder']);
|
||||
$sql = systemGroup::loadData();
|
||||
$list = $sql->get();
|
||||
foreach ($list as $id => &$info) {//创建用户目录及初始化
|
||||
$path = make_path($info['name']);
|
||||
$rootPath = GROUP_PATH.$path.'/';
|
||||
foreach ($homeFolders as $dir) {
|
||||
mk_dir(iconv_system($rootPath.'home/'.$dir));
|
||||
}
|
||||
$info['path'] = $path;
|
||||
$info['createTime'] = time();
|
||||
}
|
||||
$sql->reset($list);
|
||||
}
|
||||
|
||||
//============内部处理函数=============
|
||||
/**
|
||||
*初始化用户数据和配置。
|
||||
*/
|
||||
public function initDir($path){
|
||||
$userFolder = array('home','recycle_kod','data');
|
||||
$homeFolders = explode(',',$this->config['settingSystem']['newUserFolder']);
|
||||
$rootPath = USER_PATH.$path.'/';
|
||||
foreach ($userFolder as $dir) {
|
||||
mk_dir(iconv_system($rootPath.$dir));
|
||||
}
|
||||
foreach ($homeFolders as $dir) {
|
||||
mk_dir(iconv_system($rootPath.'home/'.$dir));
|
||||
}
|
||||
FileCache::save($rootPath.'data/config.php',$this->config['settingDefault']);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
class systemRole extends Controller{
|
||||
public static $staticSql = null;
|
||||
private $sql;
|
||||
function __construct(){
|
||||
parent::__construct();
|
||||
$this->sql= self::loadData();
|
||||
}
|
||||
|
||||
//保证只加载一次文件
|
||||
public static function loadData(){
|
||||
if(is_null(self::$staticSql)){
|
||||
self::$staticSql = systemRoleData();
|
||||
}
|
||||
return self::$staticSql;
|
||||
}
|
||||
public static function getInfo($theId){
|
||||
$sql = self::loadData();
|
||||
return $sql->get($theId);
|
||||
}
|
||||
|
||||
|
||||
//获取所有权限组
|
||||
//用户组权限
|
||||
public function get() {
|
||||
if(isset($this->in['group_role'])){
|
||||
$this->in['action'] == 'get';
|
||||
$this->roleGroupAction();
|
||||
}
|
||||
show_json($this->sql->get());
|
||||
}
|
||||
/**
|
||||
* 权限添加
|
||||
*/
|
||||
public function add(){
|
||||
$role = $this->_initData();
|
||||
$roleId = $role['roleID'] = $this->sql->getMaxId().'';
|
||||
$this->_checkExist( $this->sql->get(),array('name',$role['name']),$roleId );
|
||||
if ($this->sql->set($role['roleID'],$role)) {
|
||||
show_json(LNG('success'),true,$role['roleID']);
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
public function edit(){
|
||||
$role = $this->_initData();
|
||||
$roleId = $this->in['roleID'];
|
||||
$this->_checkExist( $this->sql->get(),array('name',$role['name']),$roleId );
|
||||
if ($this->sql->set($roleId,$role)){
|
||||
show_json(LNG('success'),true,$roleId);
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
public function del() {
|
||||
if (!isset($this->in['roleID'])) show_json(LNG('data_not_full'),false);
|
||||
if (strlen($this->in['roleID']) <= 1) show_json(LNG('default_user_can_not_do'),false);
|
||||
systemMember::roleRemoveUserUpdate($this->in['roleID']);//用户所在权限组变更
|
||||
if($this->sql->remove($this->in['roleID'])){
|
||||
show_json(LNG('success'));
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 用户组权限列表配置
|
||||
* 增删改查
|
||||
*/
|
||||
public function roleGroupAction(){
|
||||
$sql = new FileCache(USER_SYSTEM.'system_role_group.php');
|
||||
switch ($this->in['action']) {
|
||||
case 'get':
|
||||
$roleGroup = $sql->get();
|
||||
if($roleGroup['1']['name'] == 'read'){
|
||||
$roleGroup['1']['name'] = LNG('system_role_read');
|
||||
}
|
||||
if($roleGroup['2']['name'] == 'write'){
|
||||
$roleGroup['2']['name'] = LNG('system_role_write');
|
||||
}
|
||||
show_json($roleGroup,true,$this->config['pathRoleDefine']);
|
||||
break;
|
||||
case 'add':
|
||||
$roleId = $sql->getMaxId().'';
|
||||
$roleArr = json_decode($this->in['role_arr'],true);
|
||||
if(!is_array($roleArr)) show_json(LNG('error'),false);
|
||||
if(!trim($roleArr['name'])) show_json(LNG("data_not_full"),false);
|
||||
$this->_checkExist( $sql->get(),array('name',$roleArr['name']),$roleId);
|
||||
if ($sql->set($roleId,$roleArr)) {
|
||||
show_json(array($roleId),true,$sql->get());
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
break;
|
||||
case 'set':
|
||||
$roleId = $this->in['roleID'];
|
||||
$roleArr = json_decode($this->in['role_arr'],true);
|
||||
if(!is_array($roleArr)) show_json(LNG('error'),false);
|
||||
if(!trim($roleArr['name'])) show_json(LNG("data_not_full"),false);
|
||||
$this->_checkExist( $sql->get(),array('name',$roleArr['name']),$roleId);
|
||||
if ($sql->set($roleId,$roleArr)){
|
||||
show_json(LNG('success'),true,$sql->get());
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
break;
|
||||
case 'del':
|
||||
$roleId = $this->in['roleID'];
|
||||
if(in_array($roleId,array("1","2"))){
|
||||
show_json(LNG('default_user_can_not_do'),false);
|
||||
}
|
||||
if($sql->remove($this->in['roleID'])){
|
||||
show_json(LNG('success'),true,$sql->get());
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
break;
|
||||
default:break;
|
||||
}
|
||||
}
|
||||
|
||||
//检测是否存在
|
||||
private function _checkExist($data,$find,$checkID){
|
||||
$findData = array();
|
||||
foreach ($data as $key => $val) {
|
||||
if ($val[$find[0]] == $find[1]) {
|
||||
$findData[$key] = $data[$key];
|
||||
}
|
||||
}
|
||||
if(is_array($findData) && count($findData)>0 ){
|
||||
$key = array_keys($findData);$key=$key[0];
|
||||
if($key != $checkID) show_json(LNG("error_repeat"),false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//===========内部调用============
|
||||
/**
|
||||
* 初始化数据 get
|
||||
* 只传键即可 &extNotAllow='php,jsp'&explorer.mkfile=1&explorer.pathRname=1
|
||||
*/
|
||||
private function _initData(){
|
||||
if (strlen($this->in['name'])<1) show_json(LNG('groupname_can_not_null'),false);
|
||||
$roleArr = array(
|
||||
'name' => rawurldecode($this->in['name']),
|
||||
'extNotAllow' => $this->in['extNotAllow']
|
||||
);
|
||||
foreach ($this->config['roleSetting'] as $key => $actions) {
|
||||
foreach ($actions as $action) {
|
||||
$keyUrl = $key.'_'.$action;//url explorer.mkdir => explorer_mkdir;
|
||||
$keyAuth = $key.'.'.$action;
|
||||
if (isset($this->in[$keyUrl])){
|
||||
$roleArr[$keyAuth] = 1;
|
||||
}else{
|
||||
$roleArr[$keyAuth] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $roleArr;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,653 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
class user extends Controller{
|
||||
private $user; //用户相关信息
|
||||
private $auth; //用户所属组权限
|
||||
private $notCheck;
|
||||
function __construct(){
|
||||
parent::__construct();
|
||||
|
||||
//php5.4 bug;需要重新读取一次
|
||||
@session_start();
|
||||
@session_write_close();
|
||||
if(!isset($_SESSION)){//避免session不可写导致循环跳转
|
||||
$this->login(DATA_PATH."<br/>".LNG('path_can_not_write_data') );
|
||||
}else{
|
||||
$this->user = &$_SESSION['kodUser'];
|
||||
if(!isset($this->user['path']) && isset($this->user['name'])){//旧版本数据
|
||||
$this->user['path'] = $this->user['name'];
|
||||
}
|
||||
}
|
||||
//不需要判断的action
|
||||
$this->notCheckST = array('share','debug');
|
||||
$this->notCheckACT = array(
|
||||
'loginFirst','login','logout','loginSubmit',
|
||||
'checkCode','publicLink','qrcode','sso');
|
||||
|
||||
$this->notCheckApp = array();//'pluginApp.to'
|
||||
if(!$this->user){
|
||||
$this->notCheckApp = array('pluginApp.to','api.view');
|
||||
}
|
||||
$this->config['forceWap'] = is_wap() && (!isset($_COOKIE['forceWap']) || $_COOKIE['forceWap'] == '1');
|
||||
if( isset($_GET['forceWap']) ){
|
||||
$this->config['forceWap'] = $_GET['forceWap'];
|
||||
}
|
||||
}
|
||||
|
||||
public function bindHook(){
|
||||
$this->loadModel('Plugin')->init();
|
||||
$this->bindCheckPassword();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录状态检测;并初始化数据状态
|
||||
*/
|
||||
public function loginCheck(){
|
||||
// CSRF-TOKEN更新后同步;关闭X-CSRF-TOKEN的httpOnly
|
||||
if( ACT == 'commonJs' && isset($_SESSION['X-CSRF-TOKEN'])){
|
||||
$this->_setCsrfToken();
|
||||
}
|
||||
if(in_array(ST,$this->notCheckST)) return;//不需要判断的控制器
|
||||
if(in_array(ACT,$this->notCheckACT)) return;//不需要判断的action
|
||||
if(in_array(ST.'.'.ACT,$this->notCheckApp)) return;//不需要判断的对应入口
|
||||
|
||||
if(isset($_SESSION['kodLogin']) && $_SESSION['kodLogin']===true && $this->user){
|
||||
$user = systemMember::getInfo($this->user['userID']);
|
||||
$this->_loginSuccess($user);
|
||||
return;
|
||||
}else if($_COOKIE['kodUserID']!='' && $_COOKIE['kodToken']!=''){
|
||||
$user = systemMember::getInfo($_COOKIE['kodUserID']);
|
||||
if (!is_array($user) || !isset($user['password'])) {
|
||||
$this->logout();
|
||||
}
|
||||
if($this->_makeLoginToken($user) === $_COOKIE['kodToken']){
|
||||
@session_start();//re start
|
||||
$_SESSION['kodLogin'] = true;
|
||||
$_SESSION['kodUser']= $user;
|
||||
$_SESSION['X-CSRF-TOKEN'] = rand_string(20);
|
||||
$this->_setCsrfToken();
|
||||
setcookie('kodUserID', $_COOKIE['kodUserID'], time()+3600*24*100);
|
||||
setcookie('kodToken',$_COOKIE['kodToken'],time()+3600*24*100);
|
||||
|
||||
//check if session work
|
||||
@session_write_close();
|
||||
unset($_SESSION);
|
||||
@session_start();
|
||||
if( !isset($_SESSION['kodUser']) ||
|
||||
!is_array($_SESSION['kodUser'])){
|
||||
$this->login(DATA_PATH."<br/>".LNG('path_can_not_write_data') );
|
||||
}else{
|
||||
$this->_loginSuccess($user);
|
||||
}
|
||||
return;
|
||||
}
|
||||
$this->logout();//session user数据不存在
|
||||
}else{
|
||||
if ($this->config['settingSystem']['autoLogin'] != '1') {
|
||||
$this->logout();//不自动登录
|
||||
}else{
|
||||
if (!file_exists(USER_SYSTEM.'install.lock')) {
|
||||
$this->display('install.html');
|
||||
exit;
|
||||
}
|
||||
header('location:./index.php?user/loginSubmit&name=guest&password=guest');
|
||||
exit;
|
||||
}
|
||||
}
|
||||
}
|
||||
private function _setCsrfToken(){
|
||||
setcookie_header('X-CSRF-TOKEN',$_SESSION['X-CSRF-TOKEN'], time()+3600*24*100);
|
||||
}
|
||||
|
||||
private function _loginSuccess($user){
|
||||
$this->user = $user;
|
||||
if(!$user){//false
|
||||
show_tips('[Error Code:1001] user data error!');
|
||||
}else if(!$user['path']){//服务器管理后立即生效
|
||||
$this->login("Your 'path' is empty,please install again!");
|
||||
}else if($user['status'] == 0){
|
||||
$this->login(LNG('login_error_user_not_use'));
|
||||
}else if($user['role']==''){
|
||||
$this->login(LNG('login_error_role'));
|
||||
}
|
||||
define('USER',USER_PATH.$this->user['path'].'/');//utf-8
|
||||
define('USER_TEMP',USER.'data/temp/');
|
||||
define('USER_RECYCLE',USER.'recycle_kod/');
|
||||
|
||||
@session_start();//re start
|
||||
$_SESSION['kodUser']= $user;
|
||||
@session_write_close();
|
||||
if (!file_exists(iconv_system(USER))) {
|
||||
$this->login("User/".get_path_this(USER)." ".LNG('not_exists'));
|
||||
}
|
||||
$user_home = user_home_path($this->user);//utf-8
|
||||
define('HOME_PATH',$user_home);
|
||||
if ($this->user['role'] == '1') {
|
||||
define('MYHOME',$user_home);
|
||||
define('HOME','');
|
||||
$GLOBALS['webRoot'] = WEB_ROOT;//服务器目录
|
||||
$GLOBALS['isRoot'] = 1;
|
||||
}else{
|
||||
define('HOME',$user_home);
|
||||
define('MYHOME','/');
|
||||
$GLOBALS['webRoot'] = '';//从服务器开始到用户目录
|
||||
$GLOBALS['isRoot'] = 0;
|
||||
}
|
||||
$desktop = $this->config['settingSystem']['desktopFolder'];
|
||||
if(isset($this->config['settingSystemDefault']['desktopFolder'])){
|
||||
$desktop = $this->config['settingSystemDefault']['desktopFolder'];
|
||||
}
|
||||
define('DESKTOP_FOLDER',$desktop);
|
||||
$this->config['user'] = FileCache::load(USER.'data/config.php');
|
||||
|
||||
if(!is_array($this->config['user'])){
|
||||
$this->config['user'] = array();
|
||||
}
|
||||
foreach($this->config['settingDefault'] as $key=>$val){
|
||||
if(!isset($this->config['user'][$key]) ){
|
||||
$this->config['user'][$key] = $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function _loginCheckPassword($user,$password){
|
||||
if($this->checkPassword($password)) return;
|
||||
if($user['role'] == '1'){ // 管理员,提示修改;
|
||||
if(isset($_SESSION['adminPasswordTips'])) return;
|
||||
@session_start();
|
||||
$_SESSION['adminPasswordTips']= 1;
|
||||
@session_write_close();
|
||||
show_tips("安全提示:<br/><br/>密码长度必须大于6,同时包含英文和数字;<br/>强烈建议登陆后修改密码!",false);
|
||||
}
|
||||
show_tips("密码长度必须大于6,同时包含英文和数字;<br/>请联系管理员修改后再试!",false);
|
||||
}
|
||||
private function checkPassword($password){
|
||||
if(defined('INSTALL_CHANNEL') && INSTALL_CHANNEL =='hikvision.com'){
|
||||
$this->config['settingSystemDefault']['passwordCheck'] = '1';
|
||||
}
|
||||
if($this->config['settingSystemDefault']['passwordCheck'] == '0') return true;
|
||||
|
||||
$hasNumber = preg_match('/\d/',$password);
|
||||
$hasChar = preg_match('/[A-Za-z]/',$password);
|
||||
if( strlen($password) >= 6 && $hasNumber && $hasChar) return true;
|
||||
return false;
|
||||
}
|
||||
private function bindCheckPassword(){
|
||||
$action = strtolower(ST.'.'.ACT);
|
||||
$check = array(
|
||||
'user.changepassword' => 'passwordNew',
|
||||
'systemmember.edit' => 'password',
|
||||
'systemmember.add' => 'password',
|
||||
);
|
||||
if(!isset($check[$action])) return;
|
||||
|
||||
$password = $this->in[$check[$action]];
|
||||
if($this->checkPassword($password)) return;
|
||||
show_json("密码长度必须大于6,同时包含英文和数字;<br/>请联系管理员修改后再试!",false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 共享kod登陆并跳转
|
||||
* check: 校验方式:userID|userName|roleID|roleName|groupID|groupName,为空则所有登陆用户
|
||||
* value: 对应的值
|
||||
* link : 登陆后的跳转链接
|
||||
*/
|
||||
public function sso(){
|
||||
$result = false;
|
||||
$error = "未登录!";
|
||||
if(!isset($_SESSION) || $_SESSION['kodLogin'] != 1){//避免session不可写导致循环跳转
|
||||
$this->login($error);
|
||||
}
|
||||
$user = $_SESSION['kodUser'];
|
||||
//admin 或者不填则允许所有kod用户登陆
|
||||
if( $user['role'] == '1' ||
|
||||
!isset($this->in['check']) ||
|
||||
!isset($this->in['value']) ){
|
||||
$result = true;
|
||||
}
|
||||
|
||||
$checkValue = false;
|
||||
switch ($this->in['check']) {
|
||||
case 'userID':$checkValue = $user['userID'];break;
|
||||
case 'userName':$checkValue = $user['name'];break;
|
||||
case 'roleID':$checkValue = $user['role'];break;
|
||||
case 'roleName':
|
||||
$role = systemRole::getInfo($user['role']);
|
||||
$checkValue = $role['name'];
|
||||
break;
|
||||
case 'groupID':
|
||||
$checkValue = array_keys($user['groupInfo']);
|
||||
break;
|
||||
case 'groupName':
|
||||
$checkValue = array();
|
||||
foreach ($user['groupInfo'] as $groupID=>$val){
|
||||
$item = systemGroup::getInfo($groupID);
|
||||
$checkValue[] = $item['name'];
|
||||
}
|
||||
break;
|
||||
default:break;
|
||||
}
|
||||
if(!$result && $checkValue != false){
|
||||
if( (is_string($checkValue) && $checkValue == $this->in['value']) ||
|
||||
(is_array($checkValue) && in_array($this->in['value'],$checkValue))
|
||||
){
|
||||
$result = true;
|
||||
}else{
|
||||
$error = clear_html($this->in['check']).' 没有权限, 配置权限需要为: "'
|
||||
.clear_html($this->in['value']).'"';
|
||||
}
|
||||
}
|
||||
if($result){
|
||||
include(LIB_DIR.'api/sso.class.php');
|
||||
SSO::sessionSet($this->in['app']);
|
||||
header('location:'.$this->in['link']);
|
||||
exit;
|
||||
}
|
||||
$this->login($error);
|
||||
}
|
||||
public function accessToken(){
|
||||
if($_SESSION['kodLogin'] === true){
|
||||
show_json(access_token_get(),true);
|
||||
}else{
|
||||
show_json('not login!',false);
|
||||
}
|
||||
}
|
||||
|
||||
//临时文件访问
|
||||
public function publicLink(){
|
||||
$pass = $this->config['settingSystem']['systemPassword'];
|
||||
$fid = $this->in['fid'];//$this->in['fid'] 第三项
|
||||
$path = Mcrypt::decode($fid,$pass);
|
||||
if (strlen($path) == 0) {
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
$download = isset($_GET['download']);
|
||||
$filename = isset($_GET['downFilename'])?$_GET['downFilename']:false;
|
||||
file_put_out($path,$download,$filename);
|
||||
}
|
||||
public function commonJs(){
|
||||
$out = ob_get_clean();
|
||||
$basicPath = BASIC_PATH;
|
||||
$userPath = USER_PATH;
|
||||
$groupPath = GROUP_PATH;
|
||||
if (!$GLOBALS['isRoot']) {//对非root用户隐藏地址
|
||||
$basicPath = '/';
|
||||
$userPath = '/';
|
||||
$groupPath = '/';
|
||||
}
|
||||
$theConfig = array(
|
||||
'environment' => STATIC_JS,
|
||||
'lang' => I18n::getType(),
|
||||
'systemOS' => $this->config['systemOS'],
|
||||
'isRoot' => $GLOBALS['isRoot'],
|
||||
'userID' => $this->user['userID'],
|
||||
'webRoot' => $GLOBALS['webRoot'],
|
||||
'webHost' => HOST,
|
||||
'appHost' => APP_HOST,
|
||||
'staticPath' => STATIC_PATH,
|
||||
'appIndex' => $_SERVER['SCRIPT_NAME'],
|
||||
'basicPath' => $basicPath,
|
||||
'userPath' => $userPath,
|
||||
'groupPath' => $groupPath,
|
||||
|
||||
'myhome' => MYHOME,
|
||||
'myDesktop' => MYHOME.DESKTOP_FOLDER.'/',
|
||||
'settings' => array(
|
||||
'updloadChunkSize' => file_upload_size(),
|
||||
'updloadThreads' => $this->config['settings']['updloadThreads'],
|
||||
'updloadBindary' => $this->config['settings']['updloadBindary'],
|
||||
'uploadCheckChunk' => $this->config['settings']['uploadCheckChunk'],
|
||||
|
||||
'paramRewrite' => $this->config['settings']['paramRewrite'],
|
||||
'pluginServer' => $this->config['settings']['pluginServer'],
|
||||
'appType' => $this->config['settings']['appType']
|
||||
),
|
||||
'phpVersion' => PHP_VERSION,
|
||||
'version' => KOD_VERSION,
|
||||
'versionBuild' => KOD_VERSION_BUILD,
|
||||
'kodID' => md5(BASIC_PATH.$this->config['settingSystem']['systemPassword']),
|
||||
'jsonData' => "",
|
||||
'selfShare' => systemMember::userShareList($this->user['userID']),
|
||||
'userConfig' => $this->config['user'],
|
||||
'accessToken' => access_token_get(),
|
||||
'versionEnv' => base64_encode(serverInfo()),
|
||||
|
||||
//虚拟目录
|
||||
'KOD_GROUP_PATH' => KOD_GROUP_PATH,
|
||||
'KOD_GROUP_SHARE' => KOD_GROUP_SHARE,
|
||||
'KOD_USER_SELF' => KOD_USER_SELF,
|
||||
'KOD_USER_SHARE' => KOD_USER_SHARE,
|
||||
'KOD_USER_RECYCLE' => KOD_USER_RECYCLE,
|
||||
'KOD_USER_FAV' => KOD_USER_FAV,
|
||||
'KOD_GROUP_ROOT_SELF' => KOD_GROUP_ROOT_SELF,
|
||||
'KOD_GROUP_ROOT_ALL' => KOD_GROUP_ROOT_ALL,
|
||||
'ST' => $this->in['st'],
|
||||
'ACT' => $this->in['act'],
|
||||
);
|
||||
if(isset($this->config['settingSystem']['versionHash'])){
|
||||
$theConfig['versionHash'] = $this->config['settingSystem']['versionHash'];
|
||||
$theConfig['versionHashUser'] = $this->config['settingSystem']['versionHashUser'];
|
||||
}
|
||||
if (!isset($GLOBALS['auth'])) {
|
||||
$GLOBALS['auth'] = array();
|
||||
}
|
||||
|
||||
$useTime = mtime() - $GLOBALS['config']['appStartTime'];
|
||||
header("Content-Type: application/javascript; charset=utf-8");
|
||||
echo 'if(typeof(kodReady)=="undefined"){kodReady=[];}';
|
||||
Hook::trigger('user.commonJs.insert',$this->in['st'],$this->in['act']);
|
||||
echo ';AUTH='.json_encode($GLOBALS['auth']).';';
|
||||
echo 'G='.json_encode($theConfig).';';
|
||||
|
||||
$lang = json_encode_force(I18n::getAll());
|
||||
if(!$lang){
|
||||
$lang = '{}';
|
||||
}
|
||||
echo 'LNG='.$lang.';G.useTime='.$useTime.';';
|
||||
}
|
||||
public function appConfig(){
|
||||
$theConfig = array(
|
||||
'lang' => I18n::getType(),
|
||||
'isRoot' => $GLOBALS['isRoot'],
|
||||
'userID' => $this->user['userID'],
|
||||
'myhome' => MYHOME,
|
||||
'settings' => array(
|
||||
'updloadChunkSize' => file_upload_size(),
|
||||
'updloadThreads' => $this->config['settings']['updloadThreads'],
|
||||
'uploadCheckChunk' => $this->config['settings']['uploadCheckChunk'],
|
||||
),
|
||||
'version' => KOD_VERSION,
|
||||
'versionBuild' => KOD_VERSION_BUILD,
|
||||
// 'userConfig' => $this->config['user'],
|
||||
);
|
||||
show_json($theConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录view
|
||||
*/
|
||||
public function login($msg = ''){
|
||||
if(isset($this->in['isAjax'])){
|
||||
show_json($msg,false);
|
||||
}
|
||||
if (!file_exists(USER_SYSTEM.'install.lock')) {
|
||||
chmod_path(BASIC_PATH,DEFAULT_PERRMISSIONS);
|
||||
$this->display('install.html');
|
||||
exit;
|
||||
}
|
||||
$this->assign('msg',$msg);
|
||||
if (is_wap()) {
|
||||
$this->display('loginWap.html');
|
||||
}else{
|
||||
$this->display('login.html');
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* 首次登录
|
||||
*/
|
||||
public function loginFirst(){
|
||||
if (!file_exists(USER_SYSTEM.'install.lock')) {
|
||||
touch(USER_SYSTEM.'install.lock');
|
||||
if(!isset($this->in['password'])){
|
||||
$this->in['password'] = 'admin';
|
||||
}
|
||||
$root = '1';
|
||||
$sql = systemMember::loadData();
|
||||
$user = array(//重置admin
|
||||
'name' => 'admin',
|
||||
'path' => "admin",
|
||||
'password' => md5($this->in['password']),
|
||||
'userID' => $root,
|
||||
'role' => '1',
|
||||
'config' => array('sizeMax'=>'0','sizeUse'=>1024),
|
||||
'groupInfo' => array('1'=>'write'),
|
||||
'createTime' => time(),
|
||||
'status' => 1,
|
||||
);
|
||||
$sql->set($root,$user);
|
||||
if( !$user['createTime'] ||
|
||||
!$user['path'] ||
|
||||
!file_exists(USER_PATH.$user['path'])
|
||||
){
|
||||
$member = new systemMember();
|
||||
$member->initInstall();
|
||||
}
|
||||
}
|
||||
header('location:./index.php?user/login');
|
||||
exit;
|
||||
}
|
||||
/**
|
||||
* 退出处理
|
||||
*/
|
||||
public function logout(){
|
||||
session_start();
|
||||
user_logout();
|
||||
}
|
||||
|
||||
/**
|
||||
* 登录数据提交处理;登陆跳转:
|
||||
*
|
||||
* 自动登陆:index.php?user/loginSubmit&name=guest&password=guest
|
||||
* 登陆自动跳转:index.php?user/login&link=http://baidu.com
|
||||
* api登陆:index.php?user/loginSubmit&login_token=ZGVtbw==|da9926fdab0c7c32ab2c329255046793
|
||||
*/
|
||||
public function loginSubmit(){
|
||||
$apiLoginCheck = false;
|
||||
if(isset($this->in['login_token'])){
|
||||
$api_token = $this->config['settings']['apiLoginTonken'];
|
||||
$param = explode('|',$this->in['login_token']);
|
||||
if( strlen($api_token) < 5 ||
|
||||
count($param) != 2 ||
|
||||
md5(base64_decode($param[0]).$api_token) != $param[1]
|
||||
){
|
||||
$this->_loginDisplay("API 接口参数错误!",false);
|
||||
}
|
||||
$this->in['name'] = urlencode(base64_decode($param[0]));
|
||||
$apiLoginCheck = true;
|
||||
}else{
|
||||
if(!isset($this->in['name']) || !isset($this->in['password'])) {
|
||||
$this->_loginDisplay(LNG('login_not_null'),false);
|
||||
}
|
||||
if( need_check_code()
|
||||
&& $this->in['name'] != 'guest'
|
||||
&& $_SESSION['checkCode'] !== strtolower($this->in['checkCode']) ){
|
||||
$this->_loginDisplay(LNG('code_error'),false);
|
||||
}
|
||||
}
|
||||
|
||||
$name = rawurldecode($this->in['name']);
|
||||
$password = rawurldecode($this->in['password']);
|
||||
|
||||
if($this->in['salt']){
|
||||
$key = substr($password,0,5)."2&$%@(*@(djfhj1923";
|
||||
$password = Mcrypt::decode(substr($password,5),$key);
|
||||
}
|
||||
|
||||
$member = systemMember::loadData();
|
||||
$user = $member->get('name',$name);
|
||||
if($apiLoginCheck && $user){//api自动登陆
|
||||
}else if ($user === false || md5($password) !== $user['password']){
|
||||
$this->_loginDisplay(LNG('password_error'),false);//$member->get()
|
||||
}else if($user['status'] == 0){
|
||||
$this->_loginDisplay(LNG('login_error_user_not_use'),false);
|
||||
}else if($user['role']==''){
|
||||
$this->_loginDisplay(LNG('login_error_role'),false);
|
||||
}
|
||||
|
||||
//首次登陆,初始化app 没有最后登录时间
|
||||
$this->_loginCheckPassword($user,$password);
|
||||
$this->_loginSuccess($user);//登陆成功
|
||||
if(!$user['lastLogin']){
|
||||
$app = init_controller('app');
|
||||
$app->initApp($user);
|
||||
}
|
||||
$user['lastLogin'] = time();//记录最后登录时间
|
||||
$member->set($user['userID'],$user);
|
||||
|
||||
session_start();//re start 有新的修改后调用
|
||||
$_SESSION['kodLogin'] = true;
|
||||
$_SESSION['kodUser']= $user;
|
||||
$_SESSION['X-CSRF-TOKEN'] = rand_string(20);
|
||||
$this->_setCsrfToken();
|
||||
setcookie('kodUserID', $user['userID'], time()+3600*24*100);
|
||||
if ($this->in['rememberPassword'] == '1') {
|
||||
setcookie('kodToken',$this->_makeLoginToken($user),time()+3600*24*100);
|
||||
}
|
||||
$this->_loginDisplay('ok',true);
|
||||
}
|
||||
private function _loginDisplay($msg,$success){
|
||||
if(isset($this->in['isAjax'])){
|
||||
if(isset($this->in['getToken']) && $success){
|
||||
show_json(access_token_get(),true);
|
||||
}
|
||||
show_json($msg,$success);
|
||||
}else{
|
||||
if($success){
|
||||
$href = './';
|
||||
if(isset($this->in['link'])){
|
||||
$href = rawurldecode($this->in['link']);
|
||||
}
|
||||
header('location:'.$href);
|
||||
}else{
|
||||
$this->login($msg);
|
||||
}
|
||||
}
|
||||
exit;
|
||||
}
|
||||
|
||||
//登陆token
|
||||
private function _makeLoginToken($userInfo){
|
||||
//$ua = $_SERVER['HTTP_USER_AGENT'];
|
||||
$system_pass = $this->config['settingSystem']['systemPassword'];
|
||||
return md5($userInfo['password'].$system_pass.$userInfo['userID']);
|
||||
}
|
||||
public function versionInstall(){
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改密码
|
||||
*/
|
||||
public function changePassword(){
|
||||
$passwordNow=rawurldecode($this->in['passwordNow']);
|
||||
$passwordNew=rawurldecode($this->in['passwordNew']);
|
||||
if (!$passwordNow && !$passwordNew)show_json(LNG('password_not_null'),false);
|
||||
if ($this->user['password']==md5($passwordNow)){
|
||||
$sql=systemMember::loadData();
|
||||
$this->user['password'] = md5($passwordNew);
|
||||
$sql->set($this->user['userID'],$this->user);
|
||||
show_json('success');
|
||||
}else {
|
||||
show_json(LNG('old_password_error'),false);
|
||||
}
|
||||
}
|
||||
|
||||
//CSRF 防护;cookie设置:CSRF-TOKEN;header:提交X-CSRF-TOKEN
|
||||
//referer检测
|
||||
private function _checkCSRF(){
|
||||
$not_check = array('user.commonJs','pluginApp.index');
|
||||
if( !$this->config['settingSystem']['csrfProtect'] ||
|
||||
isset($this->in['accessToken']) ||
|
||||
in_array(ST.'.'.ACT, $not_check)
|
||||
){
|
||||
return;
|
||||
}
|
||||
if( !isset($_SERVER['HTTP_X_CSRF_TOKEN'])||
|
||||
$_SERVER['HTTP_X_CSRF_TOKEN'] != $_SESSION['X-CSRF-TOKEN']
|
||||
){
|
||||
show_json('token_error',false);
|
||||
}
|
||||
}
|
||||
private function _checkKey($key){
|
||||
if(!isset($this->in[$key])){
|
||||
return '';
|
||||
}
|
||||
return is_string($this->in[$key])? rawurldecode($this->in[$key]):'';
|
||||
}
|
||||
|
||||
private function initAuth(){
|
||||
$auth = systemRole::getInfo($this->user['role']);
|
||||
//向下版本兼容处理
|
||||
//未定义;新版本首次使用默认开放的功能
|
||||
if(!isset($auth['userShare.set'])){
|
||||
$auth['userShare.set'] = 1;
|
||||
}
|
||||
if(!isset($auth['explorer.fileDownload'])){
|
||||
$auth['explorer.fileDownload'] = 1;
|
||||
}
|
||||
//默认扩展功能 等价权限
|
||||
$auth['user.commonJs'] = 1;//权限数据配置后输出到前端
|
||||
$auth['explorer.pathDeleteRecycle'] = $auth['explorer.pathDelete'];
|
||||
$auth['explorer.pathCopyDrag'] = $auth['explorer.pathCuteDrag'];
|
||||
|
||||
$auth['explorer.officeSave'] = $auth['editor.fileSave'];
|
||||
$auth['explorer.fileSave'] = $auth['editor.fileSave'];
|
||||
$auth['explorer.imageRotate'] = $auth['editor.fileSave'];
|
||||
$auth['explorer.fileDownloadRemove']= $auth['explorer.fileDownload'];
|
||||
$auth['explorer.zipDownload'] = $auth['explorer.fileDownload'];
|
||||
$auth['explorer.unzipList'] = $auth['explorer.unzip'];
|
||||
|
||||
//彻底禁止下载;文件获取
|
||||
//$auth['explorer.fileProxy'] = $auth['explorer.fileDownload'];
|
||||
//$auth['editor.fileGet'] = $auth['explorer.fileDownload'];
|
||||
//$auth['explorer.officeView'] = $auth['explorer.fileDownload'];
|
||||
$auth['editor.fileGet'] = 1;
|
||||
$auth['explorer.fileProxy'] = 1;
|
||||
$auth['explorer.officeView']= 1;
|
||||
$auth['explorer.pathList'] = 1;
|
||||
$auth['explorer.treeList'] = 1;
|
||||
if(!$auth['explorer.fileDownload']){
|
||||
$auth['explorer.zip'] = 0;
|
||||
}
|
||||
$auth['userShare.del'] = $auth['userShare.set'];
|
||||
$GLOBALS['auth'] = $auth;
|
||||
}
|
||||
|
||||
/**
|
||||
* 权限验证;统一入口检验
|
||||
*/
|
||||
public function authCheck(){
|
||||
$this->initAuth();
|
||||
if(in_array(ST,$this->notCheckST)) return;//不需要判断的控制器
|
||||
if(in_array(ACT,$this->notCheckACT)) return;//不需要判断的action
|
||||
if(in_array(ST.'.'.ACT,$this->notCheckApp)) return;//不需要判断的对应入口
|
||||
if (!array_key_exists(ST,$this->config['roleSetting']) ) return;
|
||||
if (!in_array(ACT,$this->config['roleSetting'][ST])) return;//输出处理过的权限
|
||||
$this->_checkCSRF();
|
||||
if (isset($GLOBALS['isRoot']) && $GLOBALS['isRoot'] == 1) return;
|
||||
|
||||
if ($GLOBALS['auth'][ST.'.'.ACT] != 1) show_json(LNG('no_permission'),false);
|
||||
//扩展名限制:新建文件&上传文件&重命名文件&保存文件&zip解压文件
|
||||
$check_arr = array(
|
||||
'mkfile' => $this->_checkKey('path'),
|
||||
'pathRname' => $this->_checkKey('rnameTo'),
|
||||
'fileUpload'=> $_FILES['file']['name']? $_FILES['file']['name']:$GLOBALS['in']['name'],
|
||||
'fileSave' => $this->_checkKey('path')
|
||||
);
|
||||
if (array_key_exists(ACT,$check_arr) && !checkExt($check_arr[ACT])){
|
||||
show_json(LNG('no_permission_ext'),false);
|
||||
}
|
||||
}
|
||||
public function checkCode() {
|
||||
session_start();//re start
|
||||
$captcha = new MyCaptcha(4);
|
||||
$_SESSION['checkCode'] = $captcha->getString();
|
||||
}
|
||||
|
||||
public function qrcode(){
|
||||
$url = $this->in['url'];
|
||||
if(function_exists('imagecolorallocate')){
|
||||
ob_get_clean();
|
||||
QRcode::png($this->in['url']);
|
||||
}else{
|
||||
header('location: https://demo.kodcloud.com/?user/view/qrcode&url='.rawurlencode($url));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
class userShare extends Controller{
|
||||
private $sql;
|
||||
function __construct(){
|
||||
parent::__construct();
|
||||
$this->sql=new FileCache(USER.'data/share.php');
|
||||
}
|
||||
/**
|
||||
* 获取
|
||||
*/
|
||||
public function get($ret = 0) {
|
||||
$list = $this->sql->get();
|
||||
foreach($list as $key=>&$val){
|
||||
//unset($val['sharePassword']);
|
||||
}
|
||||
if($ret){
|
||||
return $list;
|
||||
}
|
||||
show_json($list, true);
|
||||
}
|
||||
|
||||
//检测该目录是否已被共享
|
||||
public function checkByPath(){
|
||||
$this->in['path'] = _DIR_CLEAR($this->in['path']);
|
||||
$shareInfo = $this->sql->get('path',$this->in['path']);
|
||||
if (!$shareInfo) {
|
||||
show_json('',false);//没有找到
|
||||
}else{
|
||||
show_json($shareInfo,true,$this->get(1));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 编辑
|
||||
*/
|
||||
public function set(){
|
||||
if (!$this->in['name'] || !$this->in['path'] || !$this->in['type']){
|
||||
show_json(LNG('data_not_full'),false);
|
||||
}
|
||||
$shareInfo = array(
|
||||
'mtime' => time(),//更新则记录最后时间
|
||||
'sid' => isset($this->in['sid'])?$this->in['sid']:'',
|
||||
'type' => $this->in['type'],
|
||||
'path' => _DIR_CLEAR($this->in['path']),
|
||||
'name' => $this->in['name'],
|
||||
'showName' => isset($this->in['showName'])?$this->in['showName']:$this->in['name'],
|
||||
'timeTo' => isset($this->in['timeTo'])?$this->in['timeTo']:'',
|
||||
'sharePassword' => isset($this->in['sharePassword'])?$this->in['sharePassword']:'',
|
||||
'codeRead' => isset($this->in['codeRead'])?$this->in['codeRead']:'',
|
||||
'canUpload' => isset($this->in['canUpload'])?$this->in['canUpload']:'',
|
||||
'notDownload' => isset($this->in['notDownload'])?$this->in['notDownload']:''
|
||||
);
|
||||
if(substr($shareInfo['path'],0,1) == '{'){//用户只能分享自己的目录;
|
||||
show_json(LNG('path_can_not_action'),false);
|
||||
}
|
||||
|
||||
$name = $shareInfo['name'];
|
||||
$search = $this->sql->get('name',$name);
|
||||
$i = 0;
|
||||
while($i>200 || $search && $search['sid']!=$shareInfo['sid']){
|
||||
$name = $shareInfo['name'].'('.$i.')';
|
||||
$search = $this->sql->get('name',$name);
|
||||
$i++;
|
||||
}
|
||||
if($i !=0){
|
||||
$shareInfo['name'] = $name;
|
||||
}
|
||||
|
||||
//含有sid则为更新,否则为插入
|
||||
if (isset($this->in['sid']) && strlen($this->in['sid']) == 8) {
|
||||
$infoNew = $this->sql->get($this->in['sid']);
|
||||
foreach ($shareInfo as $key=>$val) {//只更新指定key
|
||||
$infoNew[$key] = $val;
|
||||
}
|
||||
if($this->sql->set($this->in['sid'],$infoNew)){
|
||||
show_json($infoNew,true,$this->get(1));
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
}else{//插入
|
||||
$shareList = $this->sql->get();
|
||||
$newId = rand_string(8);
|
||||
while (isset($shareList[$newId])) {
|
||||
$newId = rand_string(8);
|
||||
}
|
||||
$shareInfo['sid'] = $newId;
|
||||
if($this->sql->set($newId,$shareInfo)){
|
||||
show_json($shareInfo,true,$this->get(1));
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
show_json(LNG('error'),false);
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除
|
||||
*/
|
||||
public function del() {
|
||||
$list = json_decode($this->in['dataArr'],true);
|
||||
foreach ($list as $val) {
|
||||
$this->sql->remove($val['path']);
|
||||
}
|
||||
show_json(LNG('success'),true,$this->get(1));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
/**
|
||||
* 程序路由处理类
|
||||
* 这里类判断外界参数调用内部方法
|
||||
*/
|
||||
class Application {
|
||||
private $defaultController = null; //默认的类名
|
||||
private $defaultAction = null; //默认的方法名
|
||||
public $subDir =''; //控制器子目录
|
||||
public $model = ''; //控制器对应模型 对象。
|
||||
|
||||
/**
|
||||
* 设置默认的类名
|
||||
* @param string $defaultController
|
||||
*/
|
||||
public function setDefaultController($defaultController){
|
||||
$this -> defaultController = $defaultController;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置默认的方法名
|
||||
* @param string $defaultAction
|
||||
*/
|
||||
public function setDefaultAction($defaultAction){
|
||||
$this -> defaultAction = $defaultAction;
|
||||
}
|
||||
|
||||
/**
|
||||
* 设置控制器子目录
|
||||
* @param string $dir
|
||||
*/
|
||||
public function setSubDir($dir){
|
||||
$this -> subDir = $dir;
|
||||
}
|
||||
|
||||
/**
|
||||
* 运行controller 的方法
|
||||
* @param $class , controller类名。
|
||||
* @param $function , 方法名
|
||||
*/
|
||||
public function appRun($className,$function){
|
||||
$subDir = $this -> subDir ? $this -> subDir . '/' : '';
|
||||
$classFile = CONTROLLER_DIR . $subDir.$className.'.class.php';
|
||||
Hook::filter('Application.appRun',$classFile);
|
||||
if (!file_exists_case($classFile)) {
|
||||
show_tips($className.' controller '.LNG("not_exists"),APP_HOST,5);
|
||||
}
|
||||
|
||||
include_once($classFile);
|
||||
if (!class_exists($className)) {
|
||||
show_tips($className.' class '.LNG("not_exists"),APP_HOST,5);
|
||||
}
|
||||
$instance = new $className();
|
||||
if (!method_exists($instance, $function)) {
|
||||
show_tips($function.' method '.LNG("not_exists"),APP_HOST,5);
|
||||
}
|
||||
return $instance -> $function();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 运行自动加载的控制器
|
||||
*/
|
||||
private function autorun(){
|
||||
global $config;
|
||||
if (count($config['autorun']) > 0) {
|
||||
foreach ($config['autorun'] as $key => $var) {
|
||||
$this->appRun($var['controller'],$var['function']);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 调用实际类和方式
|
||||
*/
|
||||
public function run(){
|
||||
$URI = $GLOBALS['in']['URLremote'];
|
||||
if (!isset($URI[0]) || $URI[0] == '') $URI[0] = $this->defaultController;
|
||||
if (!isset($URI[1]) || $URI[1] == '') $URI[1] = $this->defaultAction;
|
||||
|
||||
//需要校验权限的方法,统一大小写敏感;处理需要权限的方法
|
||||
$roleSetting = $GLOBALS['config']['roleSetting'];
|
||||
$st = $URI[0];
|
||||
$act = $URI[1];
|
||||
if (array_key_exists($st,$roleSetting) ){
|
||||
if( !in_array($act,$roleSetting[$st]) &&
|
||||
in_array_not_case($act,$roleSetting[$st])
|
||||
){
|
||||
show_tips($act.' action not exists!');
|
||||
}
|
||||
}
|
||||
|
||||
define('ST',$st);
|
||||
define('ACT',$act);
|
||||
//自动加载运行类。
|
||||
$this->autorun();
|
||||
$this->appRun(ST,ACT);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
/**
|
||||
* 控制器抽象类
|
||||
*/
|
||||
abstract class Controller {
|
||||
public $in;
|
||||
public $config; // 全局配置
|
||||
public $tpl; // 模板目录
|
||||
public $values; // 模板变量
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
*/
|
||||
function __construct(){
|
||||
global $in,$config;
|
||||
$this ->config = &$config;
|
||||
$this ->in = &$in;
|
||||
$this ->values['config'] = &$config;
|
||||
$this ->values['in'] = &$in;
|
||||
$this ->tpl = TEMPLATE.get_class($this).'/';
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载模型
|
||||
* @param string $class
|
||||
*/
|
||||
public function loadModel($class){
|
||||
$args = func_get_args();
|
||||
$this -> $class = call_user_func_array('init_model', $args);
|
||||
return $this -> $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载类库文件
|
||||
* @param string $class
|
||||
*/
|
||||
public function loadClass($class){
|
||||
if (1 === func_num_args()) {
|
||||
$this -> $class = new $class;
|
||||
} else {
|
||||
$reflectionObj = new ReflectionClass($class);
|
||||
$args = func_get_args();
|
||||
array_shift($args);
|
||||
$this -> $class = $reflectionObj -> newInstanceArgs($args);
|
||||
}
|
||||
return $this -> $class;
|
||||
}
|
||||
|
||||
/**
|
||||
* 显示模板
|
||||
*
|
||||
* TODO smarty
|
||||
* @param
|
||||
*/
|
||||
protected function assign($key,$value){
|
||||
$this->values[$key] = $value;
|
||||
}
|
||||
/**
|
||||
* 显示模板
|
||||
* @param
|
||||
*/
|
||||
protected function display($tplFile){
|
||||
ob_end_clean();
|
||||
extract($this->values);
|
||||
require($this->tpl.$tplFile);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
/**
|
||||
* 模型抽象类
|
||||
* 一个关于各种模型的基本行为类,每个模型都必须继承这个类的方法
|
||||
*/
|
||||
|
||||
abstract class Model {
|
||||
var $db = null;
|
||||
var $in;
|
||||
var $config;
|
||||
|
||||
/**
|
||||
* 构造函数
|
||||
* @return Null
|
||||
*/
|
||||
function __construct(){
|
||||
global $config, $in;
|
||||
$this -> in = &$in;
|
||||
$this -> config = &$config;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO db
|
||||
*/
|
||||
function db(){
|
||||
if ($this ->db != NULL) {
|
||||
return $this ->db;
|
||||
}else{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,534 @@
|
||||
<?php
|
||||
|
||||
//扩展名权限判断 有权限则返回1 不是true
|
||||
function checkExt($file){
|
||||
if($GLOBALS['isRoot']) return 1;
|
||||
if($file == '.htaccess' || $file == '.user.ini') return false;
|
||||
if (strstr($file,'<') || strstr($file,'>') || $file=='') {
|
||||
return 0;
|
||||
}
|
||||
|
||||
//'php|phtml|phtm|pwml|asp|aspx|ascx|jsp|pl|htaccess|shtml|shtm'
|
||||
$notAllow = strtolower($GLOBALS['auth']['extNotAllow']);
|
||||
$extArr = explode('|',$notAllow);
|
||||
if(in_array('asp',$extArr)){
|
||||
$extArr = array_merge($extArr,array('aspx','ascx','pwml'));
|
||||
}
|
||||
if(in_array('php',$extArr)){
|
||||
$extArr = array_merge($extArr,array('phtml','phtm','htaccess','pwml'));
|
||||
}
|
||||
if(in_array('htm',$extArr) || in_array('html',$extArr)){
|
||||
$extArr = array_merge($extArr,array('html','shtml','shtm','html','svg'));
|
||||
}
|
||||
foreach ($extArr as $current) {
|
||||
if ($current !== '' && stristr($file,'.'.$current)){//含有扩展名
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
function checkExtSafe($file){
|
||||
if($file == '.htaccess' || $file == '.user.ini') return false;
|
||||
if (strstr($file,'<') || strstr($file,'>') || $file=='') return false;
|
||||
$disable = 'php|phtml|phtm|pwml|asp|aspx|ascx|jsp|pl|html|htm|svg|shtml|shtm';
|
||||
$extArr = explode('|',$disable);
|
||||
foreach ($extArr as $ext) {
|
||||
if ($ext && stristr($file,'.'.$ext)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//-----解压缩跨平台编码转换;自动识别编码-----
|
||||
//压缩前,文件名处理;
|
||||
//ACT=zip——压缩到当前
|
||||
//ACT=zipDownload---打包下载[判断浏览器&UA——得到地区自动转换为目标编码];
|
||||
function zip_pre_name($fileName,$toCharset=false){
|
||||
if(get_path_this($fileName) == '.DS_Store') return '';//过滤文件
|
||||
if (!function_exists('iconv')){
|
||||
return $fileName;
|
||||
}
|
||||
$charset = $GLOBALS['config']['systemCharset'];
|
||||
if($toCharset == false){//默认从客户端和浏览器自动识别
|
||||
$toCharset = 'utf-8';
|
||||
$clientLanugage = I18n::defaultLang();
|
||||
$langType = I18n::getType();
|
||||
if( client_is_windows() && (
|
||||
$clientLanugage =='zh-CN' ||
|
||||
$clientLanugage =='zh-TW' ||
|
||||
$langType =='zh-CN' ||
|
||||
$langType =='zh-TW' )
|
||||
){
|
||||
$toCharset = "gbk";//压缩或者打包下载压缩时文件名采用的编码
|
||||
}
|
||||
}
|
||||
|
||||
$result = iconv_to($fileName,$charset,$toCharset);
|
||||
if(!$result){
|
||||
$result = $fileName;
|
||||
}
|
||||
//write_log("zip:".$charset.'=>'.$toCharset.';'.$fileName.'=>'.$result,'zip');
|
||||
return $result;
|
||||
}
|
||||
|
||||
function unzip_filter_ext($name){
|
||||
$add = '.txt';
|
||||
if( checkExt($name) &&
|
||||
!stristr($name,'user.ini') &&
|
||||
!stristr($name,'.htaccess')
|
||||
){//允许
|
||||
return $name;
|
||||
}
|
||||
return $name.$add;
|
||||
}
|
||||
//解压到kod,文件名处理;识别编码并转换到当前系统编码
|
||||
function unzip_pre_name($fileName){
|
||||
$fileName = str_replace(array('../','..\\',''),'',$fileName);
|
||||
if (!function_exists('iconv')){
|
||||
return unzip_filter_ext($fileName);
|
||||
}
|
||||
if(isset($GLOBALS['unzipFileCharsetGet'])){
|
||||
$charset = $GLOBALS['unzipFileCharsetGet'];
|
||||
}else{
|
||||
$charset = get_charset($fileName);
|
||||
}
|
||||
$toCharset = $GLOBALS['config']['systemCharset'];
|
||||
$result = iconv_to($fileName,$charset,$toCharset);
|
||||
if(!$result){
|
||||
$result = $fileName;
|
||||
}
|
||||
$result = unzip_filter_ext($result);
|
||||
//echo $charset.'==>'.$toCharset.':'.$result.'==='.$fileName.'<br/>';
|
||||
return $result;
|
||||
}
|
||||
|
||||
// 获取压缩文件内编码
|
||||
// $GLOBALS['unzipFileCharsetGet']
|
||||
function unzip_charset_get($list){
|
||||
if(count($list) == 0) return 'utf-8';
|
||||
$charsetArr = array();
|
||||
for ($i=0; $i < count($list); $i++) {
|
||||
$charset = get_charset($list[$i]['filename']);
|
||||
if(!isset($charsetArr[$charset])){
|
||||
$charsetArr[$charset] = 1;
|
||||
}else{
|
||||
$charsetArr[$charset] += 1;
|
||||
}
|
||||
}
|
||||
arsort($charsetArr);
|
||||
$keys = array_keys($charsetArr);
|
||||
|
||||
if(in_array('gbk',$keys)){//含有gbk,则认为是gbk
|
||||
$keys[0] = 'gbk';
|
||||
}
|
||||
$GLOBALS['unzipFileCharsetGet'] = $keys[0];
|
||||
return $keys[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* 服务器相关环境
|
||||
* 检测环境是否支持升级版本
|
||||
*/
|
||||
function serverInfo(){
|
||||
$lib = array(
|
||||
"sqlit3"=>intval( class_exists('SQLite3') ),
|
||||
"sqlit" =>intval( extension_loaded('sqlite') ),
|
||||
"curl" =>intval( function_exists('curl_init') ),
|
||||
"pdo" =>intval( class_exists('PDO') ),
|
||||
"mysqli"=>intval( extension_loaded('mysqli') ),
|
||||
"mysql" =>intval( extension_loaded('mysql') ),
|
||||
);
|
||||
$libStr = "";
|
||||
foreach($lib as $key=>$val){
|
||||
$libStr .= $key.'='.$val.';';
|
||||
}
|
||||
$system = explode(" ", php_uname());
|
||||
$env = array(
|
||||
"sys" => strtolower($system[0]),
|
||||
"php" => floatval(PHP_VERSION),
|
||||
"server"=> $_SERVER['SERVER_SOFTWARE'],
|
||||
"lib" => $libStr,
|
||||
"info" => php_uname().';php='.PHP_VERSION,
|
||||
);
|
||||
$result = str_replace("\/","@",json_encode($env));
|
||||
return $result;
|
||||
}
|
||||
|
||||
function charset_check(&$str,$check,$tempCharset='utf-8'){
|
||||
if ($str === '' || !function_exists("mb_convert_encoding")){
|
||||
return false;
|
||||
}
|
||||
$testStr1 = @mb_convert_encoding($str,$tempCharset,$check);
|
||||
$testStr2 = @mb_convert_encoding($testStr1,$check,$tempCharset);
|
||||
if($str == $testStr2){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//https://segmentfault.com/a/1190000003020776
|
||||
//http://blog.sina.com.cn/s/blog_b97feef301019571.html
|
||||
function get_charset(&$str) {
|
||||
if($GLOBALS['config']['checkCharsetDefault']){//直接指定编码
|
||||
return $GLOBALS['config']['checkCharsetDefault'];
|
||||
}
|
||||
if ($str === '' || !function_exists("mb_detect_encoding")){
|
||||
return 'utf-8';
|
||||
}
|
||||
$bom_arr = array(
|
||||
'utf-8' => chr(0xEF) . chr(0xBB) .chr(0xBF),
|
||||
'utf-16le' => chr(0xFF) . chr(0xFE),
|
||||
'utf-16be' => chr(0xFE) . chr(0xFF),
|
||||
'utf-32le' => chr(0xFF) . chr(0xFE) . chr(0x00) . chr(0x00),
|
||||
'utf-32be' => chr(0x00) . chr(0x00) . chr(0xFE) . chr(0xFF),
|
||||
);
|
||||
foreach ($bom_arr as $key => $value) {
|
||||
if (substr($str,0,strlen($value)) === $value ){
|
||||
return $key;
|
||||
}
|
||||
}
|
||||
|
||||
//前面检测成功则,自动忽略后面
|
||||
$charset=strtolower(@mb_detect_encoding($str,$GLOBALS['config']['checkCharset']));
|
||||
$charsetGet = $charset;
|
||||
if ($charset == 'cp936'){
|
||||
// 有交叉,部分文件无法识别
|
||||
if(charset_check($str,'ISO-8859-4') && !charset_check($str,'gbk') && !charset_check($str,'big5')){
|
||||
$charset = 'ISO-8859-4';
|
||||
}elseif(charset_check($str,'gbk') && !charset_check($str,'big5')){
|
||||
$charset = 'gbk';
|
||||
}else if(charset_check($str,'big5')){
|
||||
$charset = 'big5';
|
||||
}
|
||||
}else if ($charset == 'euc-cn'){
|
||||
$charset = 'gbk';
|
||||
}else if ($charset == 'ascii'){
|
||||
$charset = 'utf-8';
|
||||
}
|
||||
if ($charset == 'iso-8859-1'){
|
||||
//检测详细编码;value为用什么编码检测;为空则用utf-8
|
||||
$check = array(
|
||||
'utf-8' => $charset,
|
||||
'utf-16' => 'gbk',
|
||||
'cp1251' => 'utf-8',
|
||||
'cp1252' => 'utf-8'
|
||||
);
|
||||
foreach($check as $key => $val){
|
||||
if(charset_check($str,$key,$val)){
|
||||
if($val == ''){
|
||||
$val = 'utf-8';
|
||||
}
|
||||
$charset = $key;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
//show_json($charset,false,$charsetGet);
|
||||
return $charset;
|
||||
}
|
||||
|
||||
|
||||
function file_upload_size(){
|
||||
global $config;
|
||||
$size = get_post_max();
|
||||
if(isset($config['settings']['updloadChunkSize'])){
|
||||
$chunk = $config['settings']['updloadChunkSize'];
|
||||
if($size >= $chunk){
|
||||
$size = $chunk;
|
||||
}
|
||||
}
|
||||
return $size;
|
||||
}
|
||||
|
||||
function check_list_dir(){
|
||||
$url = APP_HOST.'app/core/';
|
||||
$find = "Application.class.php";
|
||||
|
||||
@ini_set('default_socket_timeout',1);
|
||||
$context = stream_context_create(array('http'=>array('method'=>"GET",'timeout'=>1)));
|
||||
$str = @file_get_contents($url,false,$context);
|
||||
if(stripos($str,$find) === false){//not find;ok success
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function php_env_check(){
|
||||
$error = '';
|
||||
if(!function_exists('iconv')) $error.= '<li>'.LNG('php_env_error').' iconv</li>';
|
||||
if(!function_exists('json_encode')) $error.= '<li>'.LNG('php_env_error').' json</li>';
|
||||
if(!function_exists('curl_init')) $error.= '<li>'.LNG('php_env_error').' curl</li>';
|
||||
if(!function_exists('mb_convert_encoding')) $error.= '<li>'.LNG('php_env_error').' mb_string</li>';
|
||||
if(!function_exists('file_get_contents')) $error.='<li>'.LNG('php_env_error').' file_get_contents</li>';
|
||||
if(!version_compare(PHP_VERSION,'5.0','>=')) $error.= '<li>'.LNG('php_env_error_version').'</li>';
|
||||
if(!check_list_dir()) $error.='<li>'.LNG('php_env_error_list_dir').'</li>';
|
||||
|
||||
$parent = get_path_father(BASIC_PATH);
|
||||
$arr_check = array(
|
||||
BASIC_PATH,
|
||||
DATA_PATH,
|
||||
DATA_PATH.'system',
|
||||
DATA_PATH.'User',
|
||||
DATA_PATH.'Group',
|
||||
DATA_PATH.'session'
|
||||
);
|
||||
foreach ($arr_check as $value) {
|
||||
if(!path_writeable($value)){
|
||||
$error.= '<li>'.str_replace($parent,'',$value).'/ '.LNG('php_env_error_path').'</li>';
|
||||
}
|
||||
}
|
||||
if( !function_exists('imagecreatefromjpeg')||
|
||||
!function_exists('imagecreatefromgif')||
|
||||
!function_exists('imagecreatefrompng')||
|
||||
!function_exists('imagecolorallocate')){
|
||||
$error.= '<li>'.LNG('php_env_error_gd').'</li>';
|
||||
}
|
||||
return $error;
|
||||
}
|
||||
|
||||
//提前判断版本是否一致;
|
||||
function check_cache(){
|
||||
//检查是否更新失效
|
||||
$content = file_get_contents(BASIC_PATH.'config/version.php');
|
||||
$result = match_text($content,"'KOD_VERSION','(.*)'");
|
||||
if($result != KOD_VERSION){
|
||||
show_tips("您服务器开启了php缓存,文件更新尚未生效;
|
||||
请关闭缓存,或稍后1分钟刷新页面再试!
|
||||
<a href='http://www.tuicool.com/articles/QVjeu2i' target='_blank'>了解详情</a>");
|
||||
}
|
||||
}
|
||||
|
||||
function init_common(){
|
||||
$GLOBALS['in'] = parse_incoming();
|
||||
if(!file_exists(DATA_PATH)){
|
||||
show_tips("data 目录不存在!\n\n(检查 DATA_PATH);");
|
||||
}
|
||||
// session path create and check
|
||||
$errorTips = "[Error Code:1002] 目录权限错误!请设置程序目录及所有子目录为读写状态,
|
||||
linux 运行如下指令:
|
||||
<pre>su -c 'setenforce 0'\nchmod -R 777 ".BASIC_PATH.'</pre>';
|
||||
if( !defined('SESSION_PATH_DEFAULT') ){
|
||||
//检查session是否存在
|
||||
if( !file_exists(KOD_SESSION) ||
|
||||
!file_exists(KOD_SESSION.'index.html')){
|
||||
mk_dir(KOD_SESSION);
|
||||
touch(KOD_SESSION.'index.html');
|
||||
if(!file_exists(KOD_SESSION.'index.html') ){
|
||||
show_tips($errorTips);
|
||||
}
|
||||
}
|
||||
//检查目录权限
|
||||
if( !is_writable(KOD_SESSION) ||
|
||||
!is_writable(KOD_SESSION.'index.html') ||
|
||||
!is_writable(DATA_PATH.'system/apps.php') ||
|
||||
!is_writable(DATA_PATH)){
|
||||
show_tips($errorTips);
|
||||
}
|
||||
}
|
||||
|
||||
//version check update
|
||||
$file = LIB_DIR.'update.php';
|
||||
if(file_exists($file)){
|
||||
//覆盖安装文件删除不了重定向问题优化
|
||||
if(!is_writable($file) ){
|
||||
show_tips($errorTips);
|
||||
}
|
||||
|
||||
//update;
|
||||
include($file);
|
||||
updateCheck($file);
|
||||
|
||||
//clear
|
||||
del_file($file);
|
||||
if(file_exists($file)){
|
||||
show_tips($errorTips);
|
||||
}
|
||||
user_logout();
|
||||
}
|
||||
}
|
||||
|
||||
//登陆是否需要验证码
|
||||
function need_check_code(){
|
||||
$setting = $GLOBALS['config']['settingSystem'];
|
||||
if( !$setting['needCheckCode'] ||
|
||||
!function_exists('imagecreatefromjpeg')||
|
||||
!function_exists('imagecreatefromgif')||
|
||||
!function_exists('imagecreatefrompng')||
|
||||
!function_exists('imagecolorallocate')
|
||||
){
|
||||
return false;
|
||||
}else{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
function make_path($str){
|
||||
//return md5(rand_string(30).$str.time());
|
||||
$replace = array('/','\\',':','*','?','"','<','>','|');
|
||||
return str_replace($replace, "_", $str);
|
||||
}
|
||||
|
||||
function init_setting(){
|
||||
$settingFile = USER_SYSTEM.'system_setting.php';
|
||||
$settingSystemDefault = $GLOBALS['config']['settingSystemDefault'];
|
||||
if (!file_exists($settingFile)){
|
||||
$setting = $settingSystemDefault;
|
||||
FileCache::save($settingFile,$setting);
|
||||
}else{
|
||||
$setting = FileCache::load($settingFile);
|
||||
}
|
||||
//合并配置
|
||||
foreach ($settingSystemDefault as $key => $value) {
|
||||
if(!isset($setting[$key])){
|
||||
$setting[$key] = $value;
|
||||
}
|
||||
}
|
||||
$GLOBALS['app']->setDefaultController($setting['firstIn']);
|
||||
$GLOBALS['app']->setDefaultAction('index');
|
||||
$GLOBALS['config']['settingSystem'] = $setting;
|
||||
|
||||
//group_role
|
||||
$roleGroupFile = USER_SYSTEM.'system_role_group.php';
|
||||
$roleGroup = $GLOBALS['config']['pathRoleGroupDefault'];
|
||||
if (!file_exists($roleGroupFile)){
|
||||
FileCache::save($roleGroupFile,$roleGroup);
|
||||
}else{
|
||||
$roleGroup = FileCache::load($roleGroupFile);
|
||||
}
|
||||
$GLOBALS['config']['pathRoleGroup'] = $roleGroup;
|
||||
|
||||
if(is_array($GLOBALS['L'])){
|
||||
I18n::set($GLOBALS['L']);
|
||||
}
|
||||
I18n::set(array(
|
||||
'kod_name' => $GLOBALS['config']['settingSystem']['systemName'],
|
||||
'kod_name_desc' => $GLOBALS['config']['settingSystem']['systemDesc'],
|
||||
));
|
||||
if(isset($GLOBALS['config']['setting_system']['system_name'])){
|
||||
I18n::set(array(
|
||||
'kod_name' => $GLOBALS['config']['setting_system']['system_name'],
|
||||
'kod_name_desc' => $GLOBALS['config']['setting_system']['system_desc'],
|
||||
));
|
||||
}
|
||||
define('STATIC_PATH',$GLOBALS['config']['settings']['staticPath']);
|
||||
}
|
||||
|
||||
function user_logout(){
|
||||
@session_destroy();
|
||||
@session_name('KOD_SESSION_SSO');
|
||||
@session_start();
|
||||
@session_destroy();
|
||||
|
||||
setcookie(SESSION_ID, '', time()-3600,'/');
|
||||
setcookie('kod_name', '', time()-3600);
|
||||
setcookie('kodToken', '', time()-3600);
|
||||
setcookie('X-CSRF-TOKEN','',time()-3600);
|
||||
|
||||
$url = './index.php?user/login';
|
||||
//之前界面维持,不是主动退出则登陆后跳转到之前页面
|
||||
if(defined('ACT') && ACT != 'logout' && count($_GET)!=0 ){
|
||||
$url .= '&link='.rawurlencode(this_url());
|
||||
}
|
||||
//移动端;接口请求时退出
|
||||
if(isset($_REQUEST['HTTP_X_PLATFORM'])){
|
||||
show_json('login error!',10001);
|
||||
}
|
||||
header('Location:'.$url);
|
||||
exit;
|
||||
}
|
||||
|
||||
function hash_encode($str) {
|
||||
return str_replace(
|
||||
base64_encode($str),
|
||||
array('+','/','='),
|
||||
array('_a','_b','_c')
|
||||
);
|
||||
}
|
||||
function hash_decode($str) {
|
||||
return base64_decode(
|
||||
str_replace($str,array('_a','_b','_c'),array('+','/','='))
|
||||
);
|
||||
}
|
||||
|
||||
// 目录hash;
|
||||
function hash_path($path,$addExt=false){
|
||||
$password = 'kodcloud';
|
||||
if(isset($GLOBALS['config']['settingSystem']['systemPassword'])){
|
||||
$password = $GLOBALS['config']['settingSystem']['systemPassword'];
|
||||
}
|
||||
|
||||
$pre = substr(md5($path.$password),0,8);
|
||||
$result = $pre.md5($path);
|
||||
if(file_exists($path)){
|
||||
$result = $pre.md5($path.filemtime($path));
|
||||
if(filesize($path) < 50*1024*1024){
|
||||
$fileMd5 = @md5_file($path);
|
||||
if($fileMd5){
|
||||
$result = $fileMd5;
|
||||
}
|
||||
}
|
||||
}
|
||||
if($addExt){
|
||||
$result = $result.'.'.get_path_ext($path);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
function navbar_menu_add($array){
|
||||
$menu = &$GLOBALS['config']['settingSystem']['menu'];
|
||||
$exist = false;
|
||||
foreach ($menu as $value) {
|
||||
if($value['name'] == $array['name']){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$menu[] = $array;
|
||||
}
|
||||
|
||||
/**
|
||||
* 检测用户是否在用户选择数据中
|
||||
* @param [type] $info 组合数据 "all:0;role:1;2;user:2;group:101,102;"
|
||||
* @return [type] [description]
|
||||
*/
|
||||
function check_user_select($info){
|
||||
if(!is_string($info) || !$info) return true;
|
||||
$valueArr = array(
|
||||
"all" => "0",
|
||||
"user" => array(),
|
||||
"group" => array(),
|
||||
"role" => array()
|
||||
);
|
||||
$userTypeArr = explode(';',$info);
|
||||
for($i = 0;$i< count($userTypeArr);$i++){
|
||||
$splitArr = explode(':',$userTypeArr[$i]);
|
||||
if(count($splitArr) == 2){
|
||||
$valueArr[$splitArr[0]] = $splitArr[1];
|
||||
if($splitArr[0] != 'all'){
|
||||
$valueArr[$splitArr[0]] = explode(',',$splitArr[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
if(!$valueArr['user'] && !$valueArr['group'] && !$valueArr['role']){
|
||||
$valueArr['all'] = '1';
|
||||
}
|
||||
if($valueArr['all'] == '1'){
|
||||
return true;
|
||||
}
|
||||
|
||||
$userInfo = $_SESSION['kodUser'];
|
||||
if(!$userInfo){
|
||||
return false;
|
||||
}
|
||||
if( $valueArr['all'] == '1' ||
|
||||
in_array($userInfo['userID'],$valueArr['user']) ||
|
||||
in_array($userInfo['role'],$valueArr['role']) ){
|
||||
return true;
|
||||
}
|
||||
$groupArr = array_keys($userInfo['groupInfo']);
|
||||
foreach ($groupArr as $id) {
|
||||
if( in_array($id,$valueArr['group']) ){
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@@ -0,0 +1,788 @@
|
||||
<?php
|
||||
/* vim: set expandtab tabstop=4 shiftwidth=4 softtabstop=4: */
|
||||
|
||||
/**
|
||||
* Converts to and from JSON format.
|
||||
*
|
||||
* JSON (JavaScript Object Notation) is a lightweight data-interchange
|
||||
* format. It is easy for humans to read and write. It is easy for machines
|
||||
* to parse and generate. It is based on a subset of the JavaScript
|
||||
* Programming Language, Standard ECMA-262 3rd Edition - December 1999.
|
||||
* This feature can also be found in Python. JSON is a text format that is
|
||||
* completely language independent but uses conventions that are familiar
|
||||
* to programmers of the C-family of languages, including C, C++, C#, Java,
|
||||
* JavaScript, Perl, TCL, and many others. These properties make JSON an
|
||||
* ideal data-interchange language.
|
||||
*
|
||||
* This package provides a simple encoder and decoder for JSON notation. It
|
||||
* is intended for use with client-side Javascript applications that make
|
||||
* use of HTTPRequest to perform server communication functions - data can
|
||||
* be encoded into JSON notation for use in a client-side javascript, or
|
||||
* decoded from incoming Javascript requests. JSON format is native to
|
||||
* Javascript, and can be directly eval()'ed with no further parsing
|
||||
* overhead
|
||||
*
|
||||
* All strings should be in ASCII or UTF-8 format!
|
||||
*
|
||||
* LICENSE: Redistribution and use in source and binary forms, with or
|
||||
* without modification, are permitted provided that the following
|
||||
* conditions are met: Redistributions of source code must retain the
|
||||
* above copyright notice, this list of conditions and the following
|
||||
* disclaimer. Redistributions in binary form must reproduce the above
|
||||
* copyright notice, this list of conditions and the following disclaimer
|
||||
* in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN
|
||||
* NO EVENT SHALL CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
|
||||
* TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
|
||||
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
|
||||
* DAMAGE.
|
||||
*
|
||||
* @category
|
||||
* @package Services_JSON
|
||||
* @author Michal Migurski <mike-json@teczno.com>
|
||||
* @author Matt Knapp <mdknapp[at]gmail[dot]com>
|
||||
* @author Brett Stimmerman <brettstimmerman[at]gmail[dot]com>
|
||||
* @copyright 2005 Michal Migurski
|
||||
* @version CVS: $Id: JSON.php,v 1.31 2006/06/28 05:54:17 migurski Exp $
|
||||
* @license http://www.opensource.org/licenses/bsd-license.php
|
||||
* @link http://pear.php.net/pepr/pepr-proposal-show.php?id=198
|
||||
*/
|
||||
|
||||
/**
|
||||
* Marker constant for Services_JSON::decode(), used to flag stack state
|
||||
*/
|
||||
define('SERVICES_JSON_SLICE', 1);
|
||||
|
||||
/**
|
||||
* Marker constant for Services_JSON::decode(), used to flag stack state
|
||||
*/
|
||||
define('SERVICES_JSON_IN_STR', 2);
|
||||
|
||||
/**
|
||||
* Marker constant for Services_JSON::decode(), used to flag stack state
|
||||
*/
|
||||
define('SERVICES_JSON_IN_ARR', 3);
|
||||
|
||||
/**
|
||||
* Marker constant for Services_JSON::decode(), used to flag stack state
|
||||
*/
|
||||
define('SERVICES_JSON_IN_OBJ', 4);
|
||||
|
||||
/**
|
||||
* Marker constant for Services_JSON::decode(), used to flag stack state
|
||||
*/
|
||||
define('SERVICES_JSON_IN_CMT', 5);
|
||||
|
||||
/**
|
||||
* Behavior switch for Services_JSON::decode()
|
||||
*/
|
||||
define('SERVICES_JSON_LOOSE_TYPE', 16);
|
||||
|
||||
/**
|
||||
* Behavior switch for Services_JSON::decode()
|
||||
*/
|
||||
define('SERVICES_JSON_SUPPRESS_ERRORS', 32);
|
||||
|
||||
/**
|
||||
* Converts to and from JSON format.
|
||||
*
|
||||
* Brief example of use:
|
||||
*
|
||||
* <code>
|
||||
* // create a new instance of Services_JSON
|
||||
* $json = new Services_JSON();
|
||||
*
|
||||
* // convert a complexe value to JSON notation, and send it to the browser
|
||||
* $value = array('foo', 'bar', array(1, 2, 'baz'), array(3, array(4)));
|
||||
* $output = $json->encode($value);
|
||||
*
|
||||
* print($output);
|
||||
* // prints: ["foo","bar",[1,2,"baz"],[3,[4]]]
|
||||
*
|
||||
* // accept incoming POST data, assumed to be in JSON notation
|
||||
* $input = file_get_contents('php://input', 1000000);
|
||||
* $value = $json->decode($input);
|
||||
* </code>
|
||||
*/
|
||||
class Services_JSON
|
||||
{
|
||||
/**
|
||||
* constructs a new JSON instance
|
||||
*
|
||||
* @param int $use object behavior flags; combine with boolean-OR
|
||||
*
|
||||
* possible values:
|
||||
* - SERVICES_JSON_LOOSE_TYPE: loose typing.
|
||||
* "{...}" syntax creates associative arrays
|
||||
* instead of objects in decode().
|
||||
* - SERVICES_JSON_SUPPRESS_ERRORS: error suppression.
|
||||
* Values which can't be encoded (e.g. resources)
|
||||
* appear as NULL instead of throwing errors.
|
||||
* By default, a deeply-nested resource will
|
||||
* bubble up with an error, so all return values
|
||||
* from encode() should be checked with isError()
|
||||
*/
|
||||
function __construct($use = 0)
|
||||
{
|
||||
$this->use = $use;
|
||||
}
|
||||
|
||||
/**
|
||||
* convert a string from one UTF-16 char to one UTF-8 char
|
||||
*
|
||||
* Normally should be handled by mb_convert_encoding, but
|
||||
* provides a slower PHP-only method for installations
|
||||
* that lack the multibye string extension.
|
||||
*
|
||||
* @param string $utf16 UTF-16 character
|
||||
* @return string UTF-8 character
|
||||
* @access private
|
||||
*/
|
||||
function utf162utf8($utf16)
|
||||
{
|
||||
// oh please oh please oh please oh please oh please
|
||||
if(function_exists('mb_convert_encoding')) {
|
||||
return mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
|
||||
}
|
||||
|
||||
$bytes = (ord($utf16[0]) << 8) | ord($utf16[1]);
|
||||
|
||||
switch(true) {
|
||||
case ((0x7F & $bytes) == $bytes):
|
||||
// this case should never be reached, because we are in ASCII range
|
||||
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
return chr(0x7F & $bytes);
|
||||
|
||||
case (0x07FF & $bytes) == $bytes:
|
||||
// return a 2-byte UTF-8 character
|
||||
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
return chr(0xC0 | (($bytes >> 6) & 0x1F))
|
||||
. chr(0x80 | ($bytes & 0x3F));
|
||||
|
||||
case (0xFFFF & $bytes) == $bytes:
|
||||
// return a 3-byte UTF-8 character
|
||||
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
return chr(0xE0 | (($bytes >> 12) & 0x0F))
|
||||
. chr(0x80 | (($bytes >> 6) & 0x3F))
|
||||
. chr(0x80 | ($bytes & 0x3F));
|
||||
}
|
||||
|
||||
// ignoring UTF-32 for now, sorry
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* convert a string from one UTF-8 char to one UTF-16 char
|
||||
*
|
||||
* Normally should be handled by mb_convert_encoding, but
|
||||
* provides a slower PHP-only method for installations
|
||||
* that lack the multibye string extension.
|
||||
*
|
||||
* @param string $utf8 UTF-8 character
|
||||
* @return string UTF-16 character
|
||||
* @access private
|
||||
*/
|
||||
function utf82utf16($utf8)
|
||||
{
|
||||
// oh please oh please oh please oh please oh please
|
||||
if(function_exists('mb_convert_encoding')) {
|
||||
return mb_convert_encoding($utf8, 'UTF-16', 'UTF-8');
|
||||
}
|
||||
|
||||
switch(strlen($utf8)) {
|
||||
case 1:
|
||||
// this case should never be reached, because we are in ASCII range
|
||||
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
return $utf8;
|
||||
|
||||
case 2:
|
||||
// return a UTF-16 character from a 2-byte UTF-8 char
|
||||
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
return chr(0x07 & (ord($utf8[0]) >> 2))
|
||||
. chr((0xC0 & (ord($utf8[0]) << 6))
|
||||
| (0x3F & ord($utf8[1])));
|
||||
|
||||
case 3:
|
||||
// return a UTF-16 character from a 3-byte UTF-8 char
|
||||
// see: http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
return chr((0xF0 & (ord($utf8[0]) << 4))
|
||||
| (0x0F & (ord($utf8[1]) >> 2)))
|
||||
. chr((0xC0 & (ord($utf8[1]) << 6))
|
||||
| (0x7F & ord($utf8[2])));
|
||||
}
|
||||
|
||||
// ignoring UTF-32 for now, sorry
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* encodes an arbitrary variable into JSON format
|
||||
*
|
||||
* @param mixed $var any number, boolean, string, array, or object to be encoded.
|
||||
* see argument 1 to Services_JSON() above for array-parsing behavior.
|
||||
* if var is a strng, note that encode() always expects it
|
||||
* to be in ASCII or UTF-8 format!
|
||||
*
|
||||
* @return mixed JSON string representation of input var or an error if a problem occurs
|
||||
* @access public
|
||||
*/
|
||||
function encode($var)
|
||||
{
|
||||
switch (gettype($var)) {
|
||||
case 'boolean':
|
||||
return $var ? 'true' : 'false';
|
||||
|
||||
case 'NULL':
|
||||
return 'null';
|
||||
|
||||
case 'integer':
|
||||
return (int) $var;
|
||||
|
||||
case 'double':
|
||||
case 'float':
|
||||
return (float) $var;
|
||||
|
||||
case 'string':
|
||||
// STRINGS ARE EXPECTED TO BE IN ASCII OR UTF-8 FORMAT
|
||||
$ascii = '';
|
||||
$strlen_var = strlen($var);
|
||||
|
||||
/*
|
||||
* Iterate over every character in the string,
|
||||
* escaping with a slash or encoding to UTF-8 where necessary
|
||||
*/
|
||||
for ($c = 0; $c < $strlen_var; ++$c) {
|
||||
|
||||
$ord_var_c = ord($var{$c});
|
||||
|
||||
switch (true) {
|
||||
case $ord_var_c == 0x08:
|
||||
$ascii .= '\b';
|
||||
break;
|
||||
case $ord_var_c == 0x09:
|
||||
$ascii .= '\t';
|
||||
break;
|
||||
case $ord_var_c == 0x0A:
|
||||
$ascii .= '\n';
|
||||
break;
|
||||
case $ord_var_c == 0x0C:
|
||||
$ascii .= '\f';
|
||||
break;
|
||||
case $ord_var_c == 0x0D:
|
||||
$ascii .= '\r';
|
||||
break;
|
||||
|
||||
case $ord_var_c == 0x22:
|
||||
case $ord_var_c == 0x2F:
|
||||
case $ord_var_c == 0x5C:
|
||||
// double quote, slash, slosh
|
||||
$ascii .= '\\'.$var{$c};
|
||||
break;
|
||||
|
||||
case (($ord_var_c >= 0x20) && ($ord_var_c <= 0x7F)):
|
||||
// characters U-00000000 - U-0000007F (same as ASCII)
|
||||
$ascii .= $var{$c};
|
||||
break;
|
||||
|
||||
case (($ord_var_c & 0xE0) == 0xC0):
|
||||
// characters U-00000080 - U-000007FF, mask 110XXXXX
|
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
$char = pack('C*', $ord_var_c, ord($var{$c + 1}));
|
||||
$c += 1;
|
||||
$utf16 = $this->utf82utf16($char);
|
||||
$ascii .= sprintf('\u%04s', bin2hex($utf16));
|
||||
break;
|
||||
|
||||
case (($ord_var_c & 0xF0) == 0xE0):
|
||||
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
|
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
$char = pack('C*', $ord_var_c,
|
||||
ord($var{$c + 1}),
|
||||
ord($var{$c + 2}));
|
||||
$c += 2;
|
||||
$utf16 = $this->utf82utf16($char);
|
||||
$ascii .= sprintf('\u%04s', bin2hex($utf16));
|
||||
break;
|
||||
|
||||
case (($ord_var_c & 0xF8) == 0xF0):
|
||||
// characters U-00010000 - U-001FFFFF, mask 11110XXX
|
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
$char = pack('C*', $ord_var_c,
|
||||
ord($var{$c + 1}),
|
||||
ord($var{$c + 2}),
|
||||
ord($var{$c + 3}));
|
||||
$c += 3;
|
||||
$utf16 = $this->utf82utf16($char);
|
||||
$ascii .= sprintf('\u%04s', bin2hex($utf16));
|
||||
break;
|
||||
|
||||
case (($ord_var_c & 0xFC) == 0xF8):
|
||||
// characters U-00200000 - U-03FFFFFF, mask 111110XX
|
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
$char = pack('C*', $ord_var_c,
|
||||
ord($var{$c + 1}),
|
||||
ord($var{$c + 2}),
|
||||
ord($var{$c + 3}),
|
||||
ord($var{$c + 4}));
|
||||
$c += 4;
|
||||
$utf16 = $this->utf82utf16($char);
|
||||
$ascii .= sprintf('\u%04s', bin2hex($utf16));
|
||||
break;
|
||||
|
||||
case (($ord_var_c & 0xFE) == 0xFC):
|
||||
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
|
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
$char = pack('C*', $ord_var_c,
|
||||
ord($var{$c + 1}),
|
||||
ord($var{$c + 2}),
|
||||
ord($var{$c + 3}),
|
||||
ord($var{$c + 4}),
|
||||
ord($var{$c + 5}));
|
||||
$c += 5;
|
||||
$utf16 = $this->utf82utf16($char);
|
||||
$ascii .= sprintf('\u%04s', bin2hex($utf16));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return '"'.$ascii.'"';
|
||||
|
||||
case 'array':
|
||||
/*
|
||||
* As per JSON spec if any array key is not an integer
|
||||
* we must treat the the whole array as an object. We
|
||||
* also try to catch a sparsely populated associative
|
||||
* array with numeric keys here because some JS engines
|
||||
* will create an array with empty indexes up to
|
||||
* max_index which can cause memory issues and because
|
||||
* the keys, which may be relevant, will be remapped
|
||||
* otherwise.
|
||||
*
|
||||
* As per the ECMA and JSON specification an object may
|
||||
* have any string as a property. Unfortunately due to
|
||||
* a hole in the ECMA specification if the key is a
|
||||
* ECMA reserved word or starts with a digit the
|
||||
* parameter is only accessible using ECMAScript's
|
||||
* bracket notation.
|
||||
*/
|
||||
|
||||
// treat as a JSON object
|
||||
if (is_array($var) && count($var) && (array_keys($var) !== range(0, sizeof($var) - 1))) {
|
||||
$properties = array_map(array($this, 'name_value'),
|
||||
array_keys($var),
|
||||
array_values($var));
|
||||
|
||||
foreach($properties as $property) {
|
||||
if(Services_JSON::isError($property)) {
|
||||
return $property;
|
||||
}
|
||||
}
|
||||
|
||||
return '{' . join(',', $properties) . '}';
|
||||
}
|
||||
|
||||
// treat it like a regular array
|
||||
$elements = array_map(array($this, 'encode'), $var);
|
||||
|
||||
foreach($elements as $element) {
|
||||
if(Services_JSON::isError($element)) {
|
||||
return $element;
|
||||
}
|
||||
}
|
||||
|
||||
return '[' . join(',', $elements) . ']';
|
||||
|
||||
case 'object':
|
||||
$vars = get_object_vars($var);
|
||||
|
||||
$properties = array_map(array($this, 'name_value'),
|
||||
array_keys($vars),
|
||||
array_values($vars));
|
||||
|
||||
foreach($properties as $property) {
|
||||
if(Services_JSON::isError($property)) {
|
||||
return $property;
|
||||
}
|
||||
}
|
||||
|
||||
return '{' . join(',', $properties) . '}';
|
||||
|
||||
default:
|
||||
return ($this->use & SERVICES_JSON_SUPPRESS_ERRORS)
|
||||
? 'null'
|
||||
: new Services_JSON_Error(gettype($var)." can not be encoded as JSON string");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* array-walking function for use in generating JSON-formatted name-value pairs
|
||||
*
|
||||
* @param string $name name of key to use
|
||||
* @param mixed $value reference to an array element to be encoded
|
||||
*
|
||||
* @return string JSON-formatted name-value pair, like '"name":value'
|
||||
* @access private
|
||||
*/
|
||||
function name_value($name, $value)
|
||||
{
|
||||
$encoded_value = $this->encode($value);
|
||||
|
||||
if(Services_JSON::isError($encoded_value)) {
|
||||
return $encoded_value;
|
||||
}
|
||||
|
||||
return $this->encode(strval($name)) . ':' . $encoded_value;
|
||||
}
|
||||
|
||||
/**
|
||||
* reduce a string by removing leading and trailing comments and whitespace
|
||||
*
|
||||
* @param $str string string value to strip of comments and whitespace
|
||||
*
|
||||
* @return string string value stripped of comments and whitespace
|
||||
* @access private
|
||||
*/
|
||||
function reduce_string($str){
|
||||
$str = preg_replace(array(
|
||||
|
||||
// eliminate single line comments in '// ...' form
|
||||
'#^\s*//(.+)$#m',
|
||||
|
||||
// eliminate multi-line comments in '/* ... */' form, at start of string
|
||||
'#^\s*/\*(.+)\*/#Us',
|
||||
|
||||
// eliminate multi-line comments in '/* ... */' form, at end of string
|
||||
'#/\*(.+)\*/\s*$#Us'
|
||||
|
||||
), '', $str);
|
||||
|
||||
// eliminate extraneous space
|
||||
return trim($str);
|
||||
}
|
||||
|
||||
/**
|
||||
* decodes a JSON string into appropriate variable
|
||||
*
|
||||
* @param string $str JSON-formatted string
|
||||
*
|
||||
* @return mixed number, boolean, string, array, or object
|
||||
* corresponding to given JSON input string.
|
||||
* See argument 1 to Services_JSON() above for object-output behavior.
|
||||
* Note that decode() always returns strings
|
||||
* in ASCII or UTF-8 format!
|
||||
* @access public
|
||||
*/
|
||||
function decode($str)
|
||||
{
|
||||
$str = $this->reduce_string($str);
|
||||
|
||||
switch (strtolower($str)) {
|
||||
case 'true':
|
||||
return true;
|
||||
|
||||
case 'false':
|
||||
return false;
|
||||
|
||||
case 'null':
|
||||
return null;
|
||||
|
||||
default:
|
||||
$m = array();
|
||||
|
||||
if (is_numeric($str)) {
|
||||
// Lookie-loo, it's a number
|
||||
|
||||
// This would work on its own, but I'm trying to be
|
||||
// good about returning integers where appropriate:
|
||||
// return (float)$str;
|
||||
|
||||
// Return float or int, as appropriate
|
||||
return ((float)$str == (integer)$str)
|
||||
? (integer)$str
|
||||
: (float)$str;
|
||||
|
||||
} elseif (preg_match('/^("|\').*(\1)$/s', $str, $m) && $m[1] == $m[2]) {
|
||||
// STRINGS RETURNED IN UTF-8 FORMAT
|
||||
$delim = substr($str, 0, 1);
|
||||
$chrs = substr($str, 1, -1);
|
||||
$utf8 = '';
|
||||
$strlen_chrs = strlen($chrs);
|
||||
|
||||
for ($c = 0; $c < $strlen_chrs; ++$c) {
|
||||
|
||||
$substr_chrs_c_2 = substr($chrs, $c, 2);
|
||||
$ord_chrs_c = ord($chrs{$c});
|
||||
|
||||
switch (true) {
|
||||
case $substr_chrs_c_2 == '\b':
|
||||
$utf8 .= chr(0x08);
|
||||
++$c;
|
||||
break;
|
||||
case $substr_chrs_c_2 == '\t':
|
||||
$utf8 .= chr(0x09);
|
||||
++$c;
|
||||
break;
|
||||
case $substr_chrs_c_2 == '\n':
|
||||
$utf8 .= chr(0x0A);
|
||||
++$c;
|
||||
break;
|
||||
case $substr_chrs_c_2 == '\f':
|
||||
$utf8 .= chr(0x0C);
|
||||
++$c;
|
||||
break;
|
||||
case $substr_chrs_c_2 == '\r':
|
||||
$utf8 .= chr(0x0D);
|
||||
++$c;
|
||||
break;
|
||||
|
||||
case $substr_chrs_c_2 == '\\"':
|
||||
case $substr_chrs_c_2 == '\\\'':
|
||||
case $substr_chrs_c_2 == '\\\\':
|
||||
case $substr_chrs_c_2 == '\\/':
|
||||
if (($delim == '"' && $substr_chrs_c_2 != '\\\'') ||
|
||||
($delim == "'" && $substr_chrs_c_2 != '\\"')) {
|
||||
$utf8 .= $chrs{++$c};
|
||||
}
|
||||
break;
|
||||
|
||||
case preg_match('/\\\u[0-9A-F]{4}/i', substr($chrs, $c, 6)):
|
||||
// single, escaped unicode character
|
||||
$utf16 = chr(hexdec(substr($chrs, ($c + 2), 2)))
|
||||
. chr(hexdec(substr($chrs, ($c + 4), 2)));
|
||||
$utf8 .= $this->utf162utf8($utf16);
|
||||
$c += 5;
|
||||
break;
|
||||
|
||||
case ($ord_chrs_c >= 0x20) && ($ord_chrs_c <= 0x7F):
|
||||
$utf8 .= $chrs{$c};
|
||||
break;
|
||||
|
||||
case ($ord_chrs_c & 0xE0) == 0xC0:
|
||||
// characters U-00000080 - U-000007FF, mask 110XXXXX
|
||||
//see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
$utf8 .= substr($chrs, $c, 2);
|
||||
++$c;
|
||||
break;
|
||||
|
||||
case ($ord_chrs_c & 0xF0) == 0xE0:
|
||||
// characters U-00000800 - U-0000FFFF, mask 1110XXXX
|
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
$utf8 .= substr($chrs, $c, 3);
|
||||
$c += 2;
|
||||
break;
|
||||
|
||||
case ($ord_chrs_c & 0xF8) == 0xF0:
|
||||
// characters U-00010000 - U-001FFFFF, mask 11110XXX
|
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
$utf8 .= substr($chrs, $c, 4);
|
||||
$c += 3;
|
||||
break;
|
||||
|
||||
case ($ord_chrs_c & 0xFC) == 0xF8:
|
||||
// characters U-00200000 - U-03FFFFFF, mask 111110XX
|
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
$utf8 .= substr($chrs, $c, 5);
|
||||
$c += 4;
|
||||
break;
|
||||
|
||||
case ($ord_chrs_c & 0xFE) == 0xFC:
|
||||
// characters U-04000000 - U-7FFFFFFF, mask 1111110X
|
||||
// see http://www.cl.cam.ac.uk/~mgk25/unicode.html#utf-8
|
||||
$utf8 .= substr($chrs, $c, 6);
|
||||
$c += 5;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return $utf8;
|
||||
|
||||
} elseif (preg_match('/^\[.*\]$/s', $str) || preg_match('/^\{.*\}$/s', $str)) {
|
||||
// array, or object notation
|
||||
|
||||
if ($str[0]== '[') {
|
||||
$stk = array(SERVICES_JSON_IN_ARR);
|
||||
$arr = array();
|
||||
} else {
|
||||
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
|
||||
$stk = array(SERVICES_JSON_IN_OBJ);
|
||||
$obj = array();
|
||||
} else {
|
||||
$stk = array(SERVICES_JSON_IN_OBJ);
|
||||
$obj = new stdClass();
|
||||
}
|
||||
}
|
||||
|
||||
array_push($stk, array('what' => SERVICES_JSON_SLICE,
|
||||
'where' => 0,
|
||||
'delim' => false));
|
||||
|
||||
$chrs = substr($str, 1, -1);
|
||||
$chrs = $this->reduce_string($chrs);
|
||||
|
||||
if ($chrs == '') {
|
||||
if (reset($stk) == SERVICES_JSON_IN_ARR) {
|
||||
return $arr;
|
||||
|
||||
} else {
|
||||
return $obj;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//print("\nparsing {$chrs}\n");
|
||||
|
||||
$strlen_chrs = strlen($chrs);
|
||||
|
||||
for ($c = 0; $c <= $strlen_chrs; ++$c) {
|
||||
|
||||
$top = end($stk);
|
||||
$substr_chrs_c_2 = substr($chrs, $c, 2);
|
||||
|
||||
if (($c == $strlen_chrs) || (($chrs{$c} == ',') && ($top['what'] == SERVICES_JSON_SLICE))) {
|
||||
// found a comma that is not inside a string, array, etc.,
|
||||
// OR we've reached the end of the character list
|
||||
$slice = substr($chrs, $top['where'], ($c - $top['where']));
|
||||
array_push($stk, array('what' => SERVICES_JSON_SLICE, 'where' => ($c + 1), 'delim' => false));
|
||||
//print("Found split at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
|
||||
|
||||
if (reset($stk) == SERVICES_JSON_IN_ARR) {
|
||||
// we are in an array, so just push an element onto the stack
|
||||
array_push($arr, $this->decode($slice));
|
||||
|
||||
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
|
||||
// we are in an object, so figure
|
||||
// out the property name and set an
|
||||
// element in an associative array,
|
||||
// for now
|
||||
$parts = array();
|
||||
|
||||
if (preg_match('/^\s*(["\'].*[^\\\]["\'])\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
|
||||
// "name":value pair
|
||||
$key = $this->decode($parts[1]);
|
||||
$val = $this->decode($parts[2]);
|
||||
|
||||
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
|
||||
$obj[$key] = $val;
|
||||
} else {
|
||||
$obj->$key = $val;
|
||||
}
|
||||
} elseif (preg_match('/^\s*(\w+)\s*:\s*(\S.*),?$/Uis', $slice, $parts)) {
|
||||
// name:value pair, where name is unquoted
|
||||
$key = $parts[1];
|
||||
$val = $this->decode($parts[2]);
|
||||
|
||||
if ($this->use & SERVICES_JSON_LOOSE_TYPE) {
|
||||
$obj[$key] = $val;
|
||||
} else {
|
||||
$obj->$key = $val;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} elseif ((($chrs{$c} == '"') || ($chrs{$c} == "'")) && ($top['what'] != SERVICES_JSON_IN_STR)) {
|
||||
// found a quote, and we are not inside a string
|
||||
array_push($stk, array('what' => SERVICES_JSON_IN_STR, 'where' => $c, 'delim' => $chrs{$c}));
|
||||
//print("Found start of string at {$c}\n");
|
||||
|
||||
} elseif (($chrs{$c} == $top['delim']) &&
|
||||
($top['what'] == SERVICES_JSON_IN_STR) &&
|
||||
((strlen(substr($chrs, 0, $c)) - strlen(rtrim(substr($chrs, 0, $c), '\\'))) % 2 != 1)) {
|
||||
// found a quote, we're in a string, and it's not escaped
|
||||
// we know that it's not escaped becase there is _not_ an
|
||||
// odd number of backslashes at the end of the string so far
|
||||
array_pop($stk);
|
||||
//print("Found end of string at {$c}: ".substr($chrs, $top['where'], (1 + 1 + $c - $top['where']))."\n");
|
||||
|
||||
} elseif (($chrs{$c} == '[') &&
|
||||
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
|
||||
// found a left-bracket, and we are in an array, object, or slice
|
||||
array_push($stk, array('what' => SERVICES_JSON_IN_ARR, 'where' => $c, 'delim' => false));
|
||||
//print("Found start of array at {$c}\n");
|
||||
|
||||
} elseif (($chrs{$c} == ']') && ($top['what'] == SERVICES_JSON_IN_ARR)) {
|
||||
// found a right-bracket, and we're in an array
|
||||
array_pop($stk);
|
||||
//print("Found end of array at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
|
||||
|
||||
} elseif (($chrs{$c} == '{') &&
|
||||
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
|
||||
// found a left-brace, and we are in an array, object, or slice
|
||||
array_push($stk, array('what' => SERVICES_JSON_IN_OBJ, 'where' => $c, 'delim' => false));
|
||||
//print("Found start of object at {$c}\n");
|
||||
|
||||
} elseif (($chrs{$c} == '}') && ($top['what'] == SERVICES_JSON_IN_OBJ)) {
|
||||
// found a right-brace, and we're in an object
|
||||
array_pop($stk);
|
||||
//print("Found end of object at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
|
||||
|
||||
} elseif (($substr_chrs_c_2 == '/*') &&
|
||||
in_array($top['what'], array(SERVICES_JSON_SLICE, SERVICES_JSON_IN_ARR, SERVICES_JSON_IN_OBJ))) {
|
||||
// found a comment start, and we are in an array, object, or slice
|
||||
array_push($stk, array('what' => SERVICES_JSON_IN_CMT, 'where' => $c, 'delim' => false));
|
||||
$c++;
|
||||
//print("Found start of comment at {$c}\n");
|
||||
|
||||
} elseif (($substr_chrs_c_2 == '*/') && ($top['what'] == SERVICES_JSON_IN_CMT)) {
|
||||
// found a comment end, and we're in one now
|
||||
array_pop($stk);
|
||||
$c++;
|
||||
|
||||
for ($i = $top['where']; $i <= $c; ++$i)
|
||||
$chrs = substr_replace($chrs, ' ', $i, 1);
|
||||
|
||||
//print("Found end of comment at {$c}: ".substr($chrs, $top['where'], (1 + $c - $top['where']))."\n");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (reset($stk) == SERVICES_JSON_IN_ARR) {
|
||||
return $arr;
|
||||
|
||||
} elseif (reset($stk) == SERVICES_JSON_IN_OBJ) {
|
||||
return $obj;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo Ultimately, this should just call PEAR::isError()
|
||||
*/
|
||||
function isError($data, $code = null){
|
||||
if (class_exists('pear')) {
|
||||
return PEAR::isError($data, $code);
|
||||
} elseif (is_object($data) && (get_class($data) == 'services_json_error' ||
|
||||
is_subclass_of($data, 'services_json_error'))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (class_exists('PEAR_Error')) {
|
||||
class Services_JSON_Error extends PEAR_Error{
|
||||
function __construct($message = 'unknown error', $code = null,
|
||||
$mode = null, $options = null, $userinfo = null){
|
||||
parent::PEAR_Error($message, $code, $mode, $options, $userinfo);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
class Services_JSON_Error{
|
||||
function __construct($message = 'unknown error', $code = null,
|
||||
$mode = null, $options = null, $userinfo = null){
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
class Downloader {
|
||||
static function start($url,$saveFile,$timeout = 10) {
|
||||
$dataFile = $saveFile . '.download.cfg';
|
||||
$saveTemp = $saveFile . '.downloading';
|
||||
|
||||
//header:{'url','length','name','supportRange'}
|
||||
if(is_array($url)){
|
||||
$fileHeader = $url;
|
||||
}else{
|
||||
$fileHeader = url_header($url);
|
||||
}
|
||||
$url = $fileHeader['url'];
|
||||
if(!$url){
|
||||
return array('code'=>false,'data'=>'url error!');
|
||||
}
|
||||
//默认下载方式if not support range
|
||||
if(!$fileHeader['supportRange'] ||
|
||||
$fileHeader['length'] == 0 ){
|
||||
@unlink($saveTemp);@unlink($saveFile);
|
||||
$result = self::fileDownloadFopen($url,$saveFile,$fileHeader['length']);
|
||||
if($result['code']) {
|
||||
return $result;
|
||||
}else{
|
||||
@unlink($saveTemp);@unlink($saveFile);
|
||||
$result = self::fileDownloadCurl($url,$saveFile,false,0,$fileHeader['length']);
|
||||
@unlink($saveTemp);@unlink($saveFile);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
$existsLength = is_file($saveTemp) ? filesize($saveTemp) : 0;
|
||||
$contentLength = intval($fileHeader['length']);
|
||||
if( file_exists($saveTemp) &&
|
||||
time() - filemtime($saveTemp) < 3) {//has Changed in 3s,is downloading
|
||||
return array('code'=>false,'data'=>'downloading');
|
||||
}
|
||||
|
||||
$existsData = array();
|
||||
if(is_file($dataFile)){
|
||||
$tempData = file_get_contents($dataFile);
|
||||
$existsData = json_decode($tempData, 1);
|
||||
}
|
||||
// exist and is the same file;
|
||||
if( file_exists($saveFile) && $contentLength == filesize($saveFile)){
|
||||
@unlink($saveTemp);
|
||||
@unlink($dataFile);
|
||||
return array('code'=>true,'data'=>'exist');
|
||||
}
|
||||
|
||||
// check file is expire
|
||||
if ($existsData['length'] != $contentLength) {
|
||||
$existsData = array('length' => $contentLength);
|
||||
}
|
||||
if($existsLength > $contentLength){
|
||||
@unlink($saveTemp);
|
||||
}
|
||||
// write exists data
|
||||
file_put_contents($dataFile, json_encode($existsData));
|
||||
$result = self::fileDownloadCurl($url,$saveFile,true,$existsLength,$contentLength);
|
||||
if($result['code']){
|
||||
@unlink($dataFile);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
// fopen then download
|
||||
static function fileDownloadFopen($url, $fileName,$headerSize=0){
|
||||
@ini_set('user_agent','Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36');
|
||||
|
||||
$fileTemp = $fileName.'.downloading';
|
||||
@set_time_limit(0);
|
||||
@unlink($fileTemp);
|
||||
if ($fp = @fopen ($url, "rb")){
|
||||
if(!$downloadFp = @fopen($fileTemp, "wb")){
|
||||
return array('code'=>false,'data'=>'open_downloading_error');
|
||||
}
|
||||
while(!feof($fp)){
|
||||
if(!file_exists($fileTemp)){//删除目标文件;则终止下载
|
||||
fclose($downloadFp);
|
||||
return array('code'=>false,'data'=>'stoped');
|
||||
}
|
||||
//对于部分fp不结束的通过文件大小判断
|
||||
clearstatcache();
|
||||
if( $headerSize>0 &&
|
||||
$headerSize==get_filesize(iconv_system($fileTemp))
|
||||
){
|
||||
break;
|
||||
}
|
||||
fwrite($downloadFp, fread($fp, 1024 * 8 ), 1024 * 8);
|
||||
}
|
||||
//下载完成,重命名临时文件到目标文件
|
||||
fclose($downloadFp);
|
||||
fclose($fp);
|
||||
self::checkGzip($fileTemp);
|
||||
if(!@rename($fileTemp,$fileName)){
|
||||
usleep(round(rand(0,1000)*50));//0.01~10ms
|
||||
@unlink($fileName);
|
||||
$res = @rename($fileTemp,$fileName);
|
||||
if(!$res){
|
||||
return array('code'=>false,'data'=>'rename error![open]');
|
||||
}
|
||||
}
|
||||
return array('code'=>true,'data'=>'success');
|
||||
}else{
|
||||
return array('code'=>false,'data'=>'url_open_error');
|
||||
}
|
||||
}
|
||||
|
||||
// curl 方式下载
|
||||
// 断点续传 http://www.linuxidc.com/Linux/2014-10/107508.htm
|
||||
static function fileDownloadCurl($url, $fileName,$supportRange=false,$existsLength=0,$length=0){
|
||||
$fileTemp = $fileName.'.downloading';
|
||||
@set_time_limit(0);
|
||||
if ($fp = @fopen ($fileTemp, "a")){
|
||||
$ch = curl_init($url);
|
||||
//断点续传
|
||||
if($supportRange){
|
||||
curl_setopt($ch, CURLOPT_RANGE, $existsLength."-");
|
||||
}
|
||||
curl_setopt($ch, CURLOPT_FILE, $fp);
|
||||
curl_setopt($ch, CURLOPT_REFERER,get_url_link($url));
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_setopt($ch, CURLOPT_USERAGENT,'Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/27.0.1453.94 Safari/537.36');
|
||||
|
||||
$res = curl_exec($ch);
|
||||
curl_close($ch);
|
||||
fclose($fp);
|
||||
|
||||
$filesize = get_filesize(iconv_system($fileTemp));
|
||||
if($filesize < $length && $length!=0){
|
||||
return array('code'=>false,'data'=>'downloading');
|
||||
}
|
||||
if($res && filesize($fileTemp) != 0){
|
||||
self::checkGzip($fileTemp);
|
||||
if(!@rename($fileTemp,$fileName)){
|
||||
@unlink($fileName);
|
||||
$res = @rename($fileTemp,$fileName);
|
||||
if(!$res){
|
||||
return array('code'=>false,'data'=>'rename error![curl]');
|
||||
}
|
||||
}
|
||||
return array('code'=>true,'data'=>'success');
|
||||
}
|
||||
return array('code'=>false,'data'=>'curl exec error!');
|
||||
}else{
|
||||
return array('code'=>false,'data'=>'file create error');
|
||||
}
|
||||
}
|
||||
|
||||
static function checkGzip($file){
|
||||
$char = "\x1f\x8b";
|
||||
$str = file_sub_str($file,0,2);
|
||||
if($char != $str) return;
|
||||
|
||||
ob_start();
|
||||
readgzfile($file);
|
||||
$out = ob_get_clean();
|
||||
file_put_contents($file,$out);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
/**
|
||||
* 数据的缓存存储类;key=>value 模式;value可以是任意类型数据。
|
||||
* 完整流程测试;读取最低5000次/s 含有写的1000次/s
|
||||
* get($find=null)
|
||||
* 1.get(); //返回所有
|
||||
* 2.get(key); //直接通过key获取
|
||||
* 3.get(data_key,value); //搜索key为value的数据 直接返回数据不含key
|
||||
* 4.get(array('key','value')); //搜索数据,符合key为指定value的所有数据;key value形式
|
||||
*
|
||||
* set($find=null,$change=null)
|
||||
* 1.set(string,val) //添加或更新;
|
||||
* 2.set(array('key','value_find'),array('key','change_to')) //查找方式更新 多条数据
|
||||
*
|
||||
* remove($find,$value)
|
||||
* 1.remove(); //清空
|
||||
* 2.remove(string); //删除 eg:set('37'),删除key为37的数据 存在且删除成功则返回true
|
||||
* 3.remove(array('key','value_find')); //查找方式删除;多条数据
|
||||
* reset($arr);//初始化数据
|
||||
*/
|
||||
|
||||
|
||||
define('CONFIG_EXIT', '<?php exit;?>');
|
||||
class FileCache{
|
||||
private $data;
|
||||
private $file;
|
||||
private $fileHash;//最后一次修改;保存时判断,如果有新修改则先读取再保存
|
||||
|
||||
function __construct($file) {
|
||||
$this->file = $file;
|
||||
$this->data= self::load($file);
|
||||
$this->fileChangeCheck();
|
||||
}
|
||||
|
||||
public function get($find=null,$value=null){
|
||||
if (is_null($find)){
|
||||
return $this->data;
|
||||
}else if(is_array($find)){//查找内容数据方式获取;返回多条
|
||||
$result = array();
|
||||
foreach ($this->data as $key => $val) {
|
||||
if ($val[$find[0]] == $find[1]) {
|
||||
$result[$key] = $this->data[$key];
|
||||
}
|
||||
}
|
||||
if(count($result)!=0){
|
||||
return $result;
|
||||
}
|
||||
}else{//单条数据获取
|
||||
$find .= '';//字符串
|
||||
if(!is_null($value)){//通过某个key寻找单条数据
|
||||
foreach ($this->data as $key => $val) {
|
||||
if ($val[$find] == $value) {
|
||||
return $val;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(isset($this->data[$find])){
|
||||
return $this->data[$find];
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
//添加或更新
|
||||
public function set($find,$value){
|
||||
$this->fileChangeCheck();
|
||||
//最后有修改则先更新本地。
|
||||
if(is_string($find)){//单条数据更新
|
||||
$this->data[$find] = $value;
|
||||
}else if(is_array($find)){//查找方式更新;更新多条
|
||||
foreach ($this->data as $key => $val) {
|
||||
if ($val[$find[0]] == $find[1]) {
|
||||
$this->data[$key][$value[0]] = $value[1];
|
||||
}
|
||||
}
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
self::save($this->file,$this->data);
|
||||
return true;
|
||||
}
|
||||
|
||||
//删除,查找删除
|
||||
public function remove($find){
|
||||
$this->fileChangeCheck();
|
||||
if(is_string($find)){//单条数据删除
|
||||
unset($this->data[$find]);
|
||||
}else if(is_array($find)){//查找删除
|
||||
foreach ($this->data as $key => $val) {
|
||||
if ($val[$find[0]] == $find[1]){
|
||||
unset($this->data[$key]);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
self::save($this->file,$this->data);
|
||||
return true;
|
||||
}
|
||||
|
||||
private function fileChangeCheck(){
|
||||
if(is_null($this->fileHash)){
|
||||
$this->fileHash = @md5_file($this->file);
|
||||
return;
|
||||
}
|
||||
//是否发生改变
|
||||
$lastHash = @md5_file($this->file);
|
||||
if($lastHash != $this->fileHash){
|
||||
$this->fileHash = $lastHash;
|
||||
$this->data= self::load($this->file);
|
||||
}
|
||||
}
|
||||
|
||||
public function reset($data,$save = true){
|
||||
$this->data = $data;
|
||||
if($save){
|
||||
self::save($this->file,$this->data);
|
||||
}
|
||||
}
|
||||
|
||||
//=====================================================
|
||||
public static function arrSort(&$arr,$key, $type = 'asc'){
|
||||
$keysValue = $newArray = array();
|
||||
foreach ($arr as $k => $v) {
|
||||
$keysValue[$k] = $v[$key];
|
||||
}
|
||||
if ($type == 'asc') {
|
||||
asort($keysValue);
|
||||
} else {
|
||||
arsort($keysValue);
|
||||
}
|
||||
reset($keysValue);
|
||||
foreach ($keysValue as $k => $v) {
|
||||
$newArray[$k] = $arr[$k];
|
||||
}
|
||||
return $newArray;
|
||||
}
|
||||
|
||||
public function getMaxId(){
|
||||
$minId = 100;
|
||||
if(count($this->data)==0){
|
||||
return $minId;//一切从100开始
|
||||
}
|
||||
$idArr = array_keys($this->data);
|
||||
rsort($idArr,SORT_NUMERIC);//id从高到底
|
||||
$the_id = intval($idArr[0])+1;
|
||||
if($the_id<=$minId){
|
||||
return $minId;
|
||||
}
|
||||
return $the_id;
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载数据;并解析成程序数据
|
||||
*/
|
||||
public static function load($file){//10000次需要4s 数据量差异不大。
|
||||
if (!$file) return false;
|
||||
$file = iconv_system($file);
|
||||
if ( !file_exists($file) ){
|
||||
@file_put_contents($file,CONFIG_EXIT.'[]');
|
||||
chmod_path($file,0777);
|
||||
return array();
|
||||
}
|
||||
|
||||
$str = file_read_safe($file,10.5);
|
||||
if( $str === false || $str === 0 || $str === -1){
|
||||
show_tips('[Error Code:1010] FileCache data read error!<br/>'.get_path_this($file));
|
||||
}
|
||||
|
||||
if (strlen($str) == 0 ||
|
||||
strlen($str) == strlen(CONFIG_EXIT) ){
|
||||
@file_put_contents($file,CONFIG_EXIT.'[]');
|
||||
chmod_path($file,0777);
|
||||
return array();
|
||||
}
|
||||
|
||||
if($str === false || strlen($str) < strlen(CONFIG_EXIT) ){
|
||||
show_tips('[Error Code:1011] FileCache data error!<br/>'.get_path_this($file));
|
||||
}
|
||||
$data= json_decode(substr($str, strlen(CONFIG_EXIT)),true);
|
||||
if (is_null($data)) $data = array();
|
||||
return $data;
|
||||
}
|
||||
/**
|
||||
* 保存数据;
|
||||
*/
|
||||
public static function save($file,$data){//10000次需要6s
|
||||
if (!$file) return false;
|
||||
$file = iconv_system($file);
|
||||
if ( !file_exists($file) ){
|
||||
@file_put_contents($file,CONFIG_EXIT.'[]');
|
||||
chmod_path($file,0777);
|
||||
}
|
||||
|
||||
if (!path_writeable($file)) {
|
||||
show_tips(BASIC_PATH."<br/>".LNG('path_can_not_write_data'));
|
||||
}
|
||||
if(defined('JSON_PRETTY_PRINT')){
|
||||
$jsonStr = json_encode($data,JSON_UNESCAPED_UNICODE|JSON_PRETTY_PRINT);
|
||||
}else{
|
||||
$jsonStr = json_encode($data);
|
||||
}
|
||||
if(is_null($jsonStr) || strlen($jsonStr) == 0){//含有二进制或非utf8字符串对应检测
|
||||
show_tips('[Error Code:1013] json_encode error!<br/>'.get_path_this($file));
|
||||
}
|
||||
|
||||
$result = file_wirte_safe($file,CONFIG_EXIT.$jsonStr,10.5);
|
||||
if($result === false){
|
||||
show_tips('[Error Code:1012] FileCache save error!<br/>'.get_path_this($file));
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
/**
|
||||
* hook::add('function','function')
|
||||
* hook::add('class:function','class.function')
|
||||
*
|
||||
* hook::run('class.function',param)
|
||||
* hook::run('function',param)
|
||||
*
|
||||
*/
|
||||
|
||||
class Hook{
|
||||
static private $events = array();
|
||||
static public function get($event=false){
|
||||
if(!$event){
|
||||
return self::$events;
|
||||
}else{
|
||||
return self::$events[$event];
|
||||
}
|
||||
}
|
||||
static public function apply($action,$args=array()) {
|
||||
if(!is_string($action)){
|
||||
return;
|
||||
}
|
||||
if(strstr($action,'.')){
|
||||
$arr = explode('.',$action);
|
||||
if(count($arr) !== 2){
|
||||
return;
|
||||
}
|
||||
$className = $arr[0];
|
||||
$functionName = $arr[1];
|
||||
if(class_exists($className)){
|
||||
$class = new $className();
|
||||
if( method_exists($class,$functionName) ){
|
||||
//return $class -> $functionName($args);
|
||||
return @call_user_func_array(array($class,$functionName), $args);
|
||||
}
|
||||
}
|
||||
}else{
|
||||
if(function_exists($action)){
|
||||
return @call_user_func_array($action, $args);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static public function bind($event,$action,$once=false) {
|
||||
if(!isset(self::$events[$event])){
|
||||
self::$events[$event] = array();
|
||||
}
|
||||
if(!is_array($action)){
|
||||
$action = array($action);
|
||||
}
|
||||
for ($i=0; $i < count($action); $i++) {
|
||||
self::$events[$event][] = array(
|
||||
'action' => $action[$i],
|
||||
'once' => $once,
|
||||
'times' => 0
|
||||
);
|
||||
}
|
||||
}
|
||||
static public function once($event,$action) {
|
||||
self::bind($event,$action,true);
|
||||
}
|
||||
static public function unbind($event) {
|
||||
self::$events[$event] = false;
|
||||
}
|
||||
|
||||
//数据处理;只支持传入一个参数
|
||||
static public function filter($event,&$param) {
|
||||
$result = self::trigger($event,$param);
|
||||
if($result){
|
||||
$param = $result;
|
||||
}
|
||||
}
|
||||
static public function trigger($event) {
|
||||
$events = self::$events;
|
||||
if( !isset($events[$event]) ){
|
||||
return;
|
||||
}
|
||||
$actions = $events[$event];
|
||||
$result = false;
|
||||
if(is_array($actions) && count($actions) >= 1) {
|
||||
$args = func_get_args();
|
||||
array_shift($args);
|
||||
for ($i=0; $i < count($actions); $i++) {
|
||||
$action = $actions[$i];
|
||||
if( $action['once'] && $action['times'] > 1){
|
||||
continue;
|
||||
}
|
||||
|
||||
if(defined("GLOBAL_DEBUG_HOOK") && GLOBAL_DEBUG_HOOK){
|
||||
write_log($event.'==>start: '.$action['action'],'hook-trigger');
|
||||
}
|
||||
|
||||
self::$events[$event][$i]['times'] = $action['times'] + 1;
|
||||
$res = self::apply($action['action'],$args);
|
||||
|
||||
if(defined("GLOBAL_DEBUG_HOOK") && GLOBAL_DEBUG_HOOK){
|
||||
write_log($event.'==>end['.$action['times'].']: '.$action['action'],'hook-trigger');
|
||||
}
|
||||
//避免循环调用
|
||||
if( $action['times'] >= 5000){
|
||||
show_json("ERROR,Too many trigger on:".$event.'==>'.$action['action'],fasle);
|
||||
}
|
||||
if(!is_null($res)){
|
||||
$result = $res;
|
||||
}
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
function LNG($key){
|
||||
if (func_num_args() == 1) {
|
||||
return I18n::get($key);
|
||||
} else {
|
||||
$args = func_get_args();
|
||||
array_shift($args);
|
||||
return vsprintf(I18n::get($key), $args);
|
||||
}
|
||||
}
|
||||
|
||||
class I18n{
|
||||
private static $loaded = false;
|
||||
private static $lang = NULL;
|
||||
public static $langType = NULL;
|
||||
|
||||
public static function defaultLang(){
|
||||
if(isset($GLOBALS['config']['settings']['language'])){
|
||||
return $GLOBALS['config']['settings']['language'];
|
||||
}
|
||||
$lang = "en";
|
||||
$arr = $GLOBALS['config']['settingAll']['language'];
|
||||
$langs = array();
|
||||
if(!$arr) return 'zh-CN';
|
||||
foreach ($arr as $key => $value) {
|
||||
$langs[$key] = $key;
|
||||
}
|
||||
$langs['zh'] = 'zh-CN'; //增加大小写对应关系
|
||||
$langs['zh-tw'] = 'zh-TW';
|
||||
|
||||
$acceptLanguage = array();
|
||||
if(!isset($_SERVER['HTTP_ACCEPT_LANGUAGE'])){
|
||||
$httpLang = 'en';
|
||||
}else{
|
||||
$httpLang = str_replace("_","-",strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE']));
|
||||
}
|
||||
preg_match_all('~([-a-z]+)(;q=([0-9.]+))?~',$httpLang,$matches,PREG_SET_ORDER);
|
||||
foreach ($matches as $match) {
|
||||
$acceptLanguage[$match[1]] = (isset($match[3]) ? $match[3] : 1);
|
||||
}
|
||||
arsort($acceptLanguage);
|
||||
foreach ($acceptLanguage as $key => $q) {
|
||||
if (isset($langs[$key])) {
|
||||
$lang = $langs[$key];break;
|
||||
}
|
||||
$key = preg_replace('~-.*~','', $key);
|
||||
if (!isset($acceptLanguage[$key]) && isset($langs[$key])) {
|
||||
$lang = $langs[$key];break;
|
||||
}
|
||||
}
|
||||
return $lang;
|
||||
}
|
||||
|
||||
public static function getAll(){
|
||||
self::init();
|
||||
return self::$lang;
|
||||
}
|
||||
public static function getType(){
|
||||
self::init();
|
||||
return self::$langType;
|
||||
}
|
||||
|
||||
public static function init(){
|
||||
if(self::$loaded !== false){
|
||||
return;
|
||||
}
|
||||
$cookieLang = 'kodUserLanguage';
|
||||
if (isset($_COOKIE[$cookieLang])) {
|
||||
$lang = $_COOKIE[$cookieLang];
|
||||
}else{
|
||||
$lang = self::defaultLang();
|
||||
//setcookie_header($cookieLang,$lang, time()+3600*24*100);
|
||||
}
|
||||
|
||||
$lang = str_replace(array('/','\\','..','.'),'',$lang);
|
||||
//兼容旧版本
|
||||
if($lang == 'zh_CN') $lang = 'zh-CN';
|
||||
if($lang == 'zh_TW') $lang = 'zh-TW';
|
||||
|
||||
if(isset($GLOBALS['config']['settings']['language'])){
|
||||
$lang = $GLOBALS['config']['settings']['language'];
|
||||
}
|
||||
$langFile = LANGUAGE_PATH.$lang.'/main.php';
|
||||
if(!file_exists($langFile)){//allow remove some I18n folder
|
||||
$lang = 'en';
|
||||
$langFile = LANGUAGE_PATH.$lang.'/main.php';
|
||||
}
|
||||
|
||||
self::$langType = $lang;
|
||||
self::$lang = include($langFile);
|
||||
self::$loaded = true;
|
||||
$GLOBALS['L'] = self::$lang;
|
||||
}
|
||||
|
||||
public static function get($key){
|
||||
self::init();
|
||||
if(!isset(self::$lang[$key])){
|
||||
return $key;
|
||||
}
|
||||
if (func_num_args() == 1) {
|
||||
return self::$lang[$key];
|
||||
} else {
|
||||
$args = func_get_args();
|
||||
array_shift($args);
|
||||
return vsprintf(self::$lang[$key], $args);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 添加多语言;
|
||||
* @param [type] $args [description]
|
||||
*/
|
||||
public static function set($array){
|
||||
self::init();
|
||||
if(!is_array($array)) return;
|
||||
foreach ($array as $key => $value) {
|
||||
self::$lang[$key] = $value;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,290 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* 功能:图片处理
|
||||
* 基本参数:$srcFile,$echoType
|
||||
*
|
||||
* eg:
|
||||
* $cm=new ImageThumb('1.jpg','file');
|
||||
*
|
||||
* $cm->Distortion('dis_bei.jpg',150,200); //生成固定宽高缩略图;
|
||||
* $cm->Prorate('pro_bei.jpg',150,200); //等比缩略图;附带切割
|
||||
* $cm->Cut('cut_bei.jpg',150,200); //等比缩略图;多出部分切割
|
||||
* $cm->BackFill('fill_bei.jpg',150,200); //等比缩略图;多出部分填充
|
||||
*
|
||||
* $cm->imgRotate('out.jpg',90); //旋转图片
|
||||
*/
|
||||
class ImageThumb {
|
||||
var $srcFile = ''; //原图
|
||||
var $imgData = ''; //图片信息
|
||||
var $echoType; //输出图片类型,link--不保存为文件;file--保存为文件
|
||||
var $im = ''; //临时变量
|
||||
var $srcW = ''; //原图宽
|
||||
var $srcH = ''; //原图高
|
||||
|
||||
function __construct($srcFile, $echoType){
|
||||
$this->srcFile = $srcFile;
|
||||
$this->echoType = $echoType;
|
||||
$this->im = self::image($srcFile);
|
||||
if(!$this->im){
|
||||
return false;
|
||||
}
|
||||
|
||||
$info = '';
|
||||
$this->imgData = GetImageSize($srcFile, $info);
|
||||
$this->srcW = imageSX($this->im);
|
||||
$this->srcH = imageSY($this->im);
|
||||
return $this;
|
||||
}
|
||||
public static function image($file){
|
||||
$info = '';
|
||||
$data = GetImageSize($file, $info);
|
||||
$img = false;
|
||||
//var_dump($data,$file,memory_get_usage()-$GLOBALS['config']['appMemoryStart']);
|
||||
switch ($data[2]) {
|
||||
case IMAGETYPE_GIF:
|
||||
if (!function_exists('imagecreatefromgif')) {
|
||||
break;
|
||||
}
|
||||
$img = imagecreatefromgif($file);
|
||||
break;
|
||||
case IMAGETYPE_JPEG:
|
||||
if (!function_exists('imagecreatefromjpeg')) {
|
||||
break;
|
||||
}
|
||||
$img = imagecreatefromjpeg($file);
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
if (!function_exists('imagecreatefrompng')) {
|
||||
break;
|
||||
}
|
||||
$img = @imagecreatefrompng($file);
|
||||
imagesavealpha($img,true);
|
||||
break;
|
||||
case IMAGETYPE_XBM:
|
||||
$img = imagecreatefromxbm($file);
|
||||
break;
|
||||
case IMAGETYPE_WBMP:
|
||||
$img = imagecreatefromwbmp($file);
|
||||
break;
|
||||
case IMAGETYPE_BMP:
|
||||
$img = imagecreatefrombmp($file);
|
||||
break;
|
||||
default:break;
|
||||
}
|
||||
return $img;
|
||||
}
|
||||
|
||||
public static function imageSize($file){
|
||||
$size = GetImageSize($file);
|
||||
if(!$size){
|
||||
return false;
|
||||
}
|
||||
return array('width'=>$size[0],"height"=>$size[1]);
|
||||
}
|
||||
|
||||
// 生成扭曲型缩图
|
||||
function distortion($toFile, $toW, $toH){
|
||||
$cImg = $this->creatImage($this->im, $toW, $toH, 0, 0, 0, 0, $this->srcW, $this->srcH);
|
||||
return $this->echoImage($cImg, $toFile);
|
||||
}
|
||||
// 生成按比例缩放的缩图
|
||||
function prorate($toFile, $toW, $toH){
|
||||
$toWH = $toW / $toH;
|
||||
$srcWH = $this->srcW / $this->srcH;
|
||||
if ($toWH<=$srcWH) {
|
||||
$ftoW = $toW;
|
||||
$ftoH = $ftoW * ($this->srcH / $this->srcW);
|
||||
} else {
|
||||
$ftoH = $toH;
|
||||
$ftoW = $ftoH * ($this->srcW / $this->srcH);
|
||||
}
|
||||
if ($this->srcW > $toW || $this->srcH > $toH) {
|
||||
$cImg = $this->creatImage($this->im, $ftoW, $ftoH, 0, 0, 0, 0, $this->srcW, $this->srcH);
|
||||
return $this->echoImage($cImg, $toFile);
|
||||
} else {
|
||||
$cImg = $this->creatImage($this->im, $this->srcW, $this->srcH, 0, 0, 0, 0, $this->srcW, $this->srcH);
|
||||
return $this->echoImage($cImg, $toFile);
|
||||
}
|
||||
}
|
||||
// 生成最小裁剪后的缩图
|
||||
function cut($toFile, $toW, $toH){
|
||||
$toWH = $toW / $toH;
|
||||
$srcWH = $this->srcW / $this->srcH;
|
||||
if ($toWH<=$srcWH) {
|
||||
$ctoH = $toH;
|
||||
$ctoW = $ctoH * ($this->srcW / $this->srcH);
|
||||
} else {
|
||||
$ctoW = $toW;
|
||||
$ctoH = $ctoW * ($this->srcH / $this->srcW);
|
||||
}
|
||||
$allImg = $this->creatImage($this->im, $ctoW, $ctoH, 0, 0, 0, 0, $this->srcW, $this->srcH);
|
||||
$cImg = $this->creatImage($allImg, $toW, $toH, 0, 0, ($ctoW - $toW) / 2, ($ctoH - $toH) / 2, $toW, $toH);
|
||||
imageDestroy($allImg);
|
||||
return $this->echoImage($cImg, $toFile);
|
||||
}
|
||||
// 生成背景填充的缩图,默认用白色填充剩余空间,传入$isAlpha为真时用透明色填充
|
||||
function backFill($toFile, $toW, $toH,$isAlpha=false,$red=255, $green=255, $blue=255){
|
||||
$toWH = $toW / $toH;
|
||||
$srcWH = $this->srcW / $this->srcH;
|
||||
if ($toWH<=$srcWH) {
|
||||
$ftoW = $toW;
|
||||
$ftoH = $ftoW * ($this->srcH / $this->srcW);
|
||||
} else {
|
||||
$ftoH = $toH;
|
||||
$ftoW = $ftoH * ($this->srcW / $this->srcH);
|
||||
}
|
||||
if (function_exists('imagecreatetruecolor')) {
|
||||
@$cImg = imageCreateTrueColor($toW, $toH);
|
||||
if (!$cImg) {
|
||||
$cImg = imageCreate($toW, $toH);
|
||||
}
|
||||
} else {
|
||||
$cImg = imageCreate($toW, $toH);
|
||||
}
|
||||
|
||||
$fromTop = ($toH - $ftoH)/2;//从正中间填充
|
||||
$backcolor = imagecolorallocate($cImg,$red,$green, $blue); //填充的背景颜色
|
||||
if ($isAlpha){//填充透明色
|
||||
$backcolor=imageColorTransparent($cImg,$backcolor);
|
||||
$fromTop = $toH - $ftoH;//从底部填充
|
||||
}
|
||||
|
||||
imageFilledRectangle($cImg, 0, 0, $toW, $toH, $backcolor);
|
||||
if ($this->srcW > $toW || $this->srcH > $toH) {
|
||||
$proImg = $this->creatImage($this->im, $ftoW, $ftoH, 0, 0, 0, 0, $this->srcW, $this->srcH);
|
||||
if ($ftoW < $toW) {
|
||||
imageCopy($cImg, $proImg, ($toW - $ftoW) / 2, 0, 0, 0, $ftoW, $ftoH);
|
||||
} else if ($ftoH < $toH) {
|
||||
imageCopy($cImg, $proImg, 0, $fromTop, 0, 0, $ftoW, $ftoH);
|
||||
} else {
|
||||
imageCopy($cImg, $proImg, 0, 0, 0, 0, $ftoW, $ftoH);
|
||||
}
|
||||
} else {
|
||||
imageCopyMerge($cImg, $this->im, ($toW - $ftoW) / 2,$fromTop, 0, 0, $ftoW, $ftoH, 100);
|
||||
}
|
||||
return $this->echoImage($cImg, $toFile);
|
||||
}
|
||||
|
||||
function creatImage($img, $creatW, $creatH, $dstX, $dstY, $srcX, $srcY, $srcImgW, $srcImgH){
|
||||
if (function_exists('imagecreatetruecolor')) {
|
||||
@$creatImg = ImageCreateTrueColor($creatW, $creatH);
|
||||
@imagealphablending($creatImg,false);//是不合并颜色,直接用$img图像颜色替换,包括透明色;
|
||||
@imagesavealpha($creatImg,true);//不要丢了$thumb图像的透明色;
|
||||
if ($creatImg){
|
||||
imageCopyResampled($creatImg, $img, $dstX, $dstY, $srcX, $srcY, $creatW, $creatH, $srcImgW, $srcImgH);
|
||||
}else {
|
||||
$creatImg = ImageCreate($creatW, $creatH);
|
||||
imageCopyResized($creatImg, $img, $dstX, $dstY, $srcX, $srcY, $creatW, $creatH, $srcImgW, $srcImgH);
|
||||
}
|
||||
} else {
|
||||
$creatImg = ImageCreate($creatW, $creatH);
|
||||
imageCopyResized($creatImg, $img, $dstX, $dstY, $srcX, $srcY, $creatW, $creatH, $srcImgW, $srcImgH);
|
||||
}
|
||||
return $creatImg;
|
||||
}
|
||||
|
||||
|
||||
// Rotate($toFile, 90);
|
||||
public function imgRotate($toFile,$degree) {
|
||||
if (!$this->im ||
|
||||
$degree % 360 === 0 ||
|
||||
!function_exists('imageRotate')) {
|
||||
return false;
|
||||
}
|
||||
$rotate = imageRotate($this->im,360-$degree,0);
|
||||
$result = false;
|
||||
switch ($this->imgData[2]) {
|
||||
case IMAGETYPE_GIF:
|
||||
$result = imagegif($rotate, $toFile);
|
||||
break;
|
||||
case IMAGETYPE_JPEG:
|
||||
$result = imagejpeg($rotate, $toFile,100);//压缩质量
|
||||
break;
|
||||
case IMAGETYPE_PNG:
|
||||
$result = imagePNG($rotate, $toFile);
|
||||
break;
|
||||
default:break;
|
||||
}
|
||||
imageDestroy($rotate);
|
||||
imageDestroy($this->im);
|
||||
return $result;
|
||||
}
|
||||
|
||||
// 输出图片,link---只输出,不保存文件。file--保存为文件
|
||||
function echoImage($img, $toFile){
|
||||
if(!$img) return false;
|
||||
ob_get_clean();
|
||||
$result = false;
|
||||
switch ($this->echoType) {
|
||||
case 'link':$result = imagePNG($img);break;
|
||||
case 'file':$result = imagePNG($img, $toFile);break;
|
||||
//return ImageJpeg($img, $to_File);
|
||||
}
|
||||
imageDestroy($img);
|
||||
imageDestroy($this->im);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
if(!function_exists('imageflip')){
|
||||
/**
|
||||
* Flip (mirror) an image left to right.
|
||||
*
|
||||
* @param image resource
|
||||
* @param x int
|
||||
* @param y int
|
||||
* @param width int
|
||||
* @param height int
|
||||
* @return bool
|
||||
* @require PHP 3.0.7 (function_exists), GD1
|
||||
*/
|
||||
define('IMG_FLIP_HORIZONTAL', 0);
|
||||
define('IMG_FLIP_VERTICAL', 1);
|
||||
define('IMG_FLIP_BOTH', 2);
|
||||
function imageflip($image, $mode) {
|
||||
switch ($mode) {
|
||||
case IMG_FLIP_HORIZONTAL: {
|
||||
$max_x = imagesx($image) - 1;
|
||||
$half_x = $max_x / 2;
|
||||
$sy = imagesy($image);
|
||||
$temp_image = imageistruecolor($image)? imagecreatetruecolor(1, $sy): imagecreate(1, $sy);
|
||||
for ($x = 0; $x < $half_x; ++$x) {
|
||||
imagecopy($temp_image, $image, 0, 0, $x, 0, 1, $sy);
|
||||
imagecopy($image, $image, $x, 0, $max_x - $x, 0, 1, $sy);
|
||||
imagecopy($image, $temp_image, $max_x - $x, 0, 0, 0, 1, $sy);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IMG_FLIP_VERTICAL: {
|
||||
$sx = imagesx($image);
|
||||
$max_y = imagesy($image) - 1;
|
||||
$half_y = $max_y / 2;
|
||||
$temp_image = imageistruecolor($image)? imagecreatetruecolor($sx, 1): imagecreate($sx, 1);
|
||||
for ($y = 0; $y < $half_y; ++$y) {
|
||||
imagecopy($temp_image, $image, 0, 0, 0, $y, $sx, 1);
|
||||
imagecopy($image, $image, 0, $y, 0, $max_y - $y, $sx, 1);
|
||||
imagecopy($image, $temp_image, 0, $max_y - $y, 0, 0, $sx, 1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case IMG_FLIP_BOTH: {
|
||||
$sx = imagesx($image);
|
||||
$sy = imagesy($image);
|
||||
$temp_image = imagerotate($image, 180, 0);
|
||||
imagecopy($image, $temp_image, 0, 0, 0, 0, $sx, $sy);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
return;
|
||||
}
|
||||
}
|
||||
imagedestroy($temp_image);
|
||||
}
|
||||
}
|
||||
if(!function_exists('imagecreatefrombmp')){
|
||||
function imagecreatefrombmp( $filename ){
|
||||
return imageGdBMP::load($filename);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,332 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
|
||||
define('ARCHIVE_LIB',dirname(__FILE__).'/archiveLib/');
|
||||
define('PCLZIP_TEMPORARY_DIR',TEMP_PATH);
|
||||
define('PCLTAR_TEMPORARY_DIR',TEMP_PATH);
|
||||
define('PCLZIP_SEPARATOR',';@@@,');//压缩多个文件,组成字符串分割
|
||||
mk_dir(TEMP_PATH);
|
||||
|
||||
require_once ARCHIVE_LIB.'pclerror.lib.php';
|
||||
require_once ARCHIVE_LIB.'pcltrace.lib.php';
|
||||
require_once ARCHIVE_LIB.'pcltar.lib.php';
|
||||
require_once ARCHIVE_LIB.'pclzip.class.php';
|
||||
require_once ARCHIVE_LIB.'kodRarArchive.class.php';
|
||||
require_once ARCHIVE_LIB.'kodZipArchive.class.php';
|
||||
|
||||
class KodArchive {
|
||||
/**
|
||||
* [checkIfType get the app by ext]
|
||||
* @param [type] $guess [check]
|
||||
* @param [type] $ext [file ext]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
static function checkIfType($ext,$appType){
|
||||
$extArray = array(
|
||||
'zip' => array('zip','ipa','apk','epub'),
|
||||
'tar' => array('tar','tar.gz','tgz','gz'),
|
||||
'rar' => array('rar','7z','xz','bz2','arj','cab','iso')
|
||||
);
|
||||
$result = in_array($ext,$extArray[$appType]);
|
||||
if( $result &&
|
||||
($appType == 'zip' || $appType == 'tar') &&
|
||||
(!function_exists('gzopen') || !function_exists('gzinflate'))
|
||||
){
|
||||
show_tips("[Error] Can't Open; Missing zlib extensions");
|
||||
}
|
||||
|
||||
if( $result && $appType == 'rar' &&
|
||||
(!function_exists('shell_exec') || !strstr(shell_exec('echo "kodcloud"'),'kodcloud'))
|
||||
){
|
||||
show_tips("[Error] Can't Open; shell_exec Can't use");
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* [listContent description]
|
||||
* @param [type] $file [archive file]
|
||||
* @return [type] [array or false]
|
||||
*/
|
||||
static function listContent($file,$output=true) {
|
||||
$ext = get_path_ext($file);
|
||||
$result = false;
|
||||
if( self::checkIfType($ext,'tar') ){
|
||||
//TrOn(10);
|
||||
$resultOld = PclTarList($file);
|
||||
//TrDisplay();exit;
|
||||
$result = array();
|
||||
for ($i=0; $i < count($resultOld); $i++) {
|
||||
$item = $resultOld[$i];
|
||||
//http://rpm5.org/docs/api/tar_8c-source.html
|
||||
if( $item['typeflag'] == 'x' || $item['typeflag'] == 'g'){
|
||||
continue;
|
||||
}
|
||||
if($output){
|
||||
$item['filename'] = ltrim($item['filename'],'./');
|
||||
}
|
||||
if($item['typeflag'] == '5'){
|
||||
$item['folder'] = true;
|
||||
}else{
|
||||
$item['folder'] = false;
|
||||
}
|
||||
$item['index'] = $i;
|
||||
$result[] = $item;
|
||||
}
|
||||
}else if( self::checkIfType($ext,'rar') ){
|
||||
$appResult = kodRarArchive::listContent($file);
|
||||
if(!$appResult['code']){
|
||||
return $appResult;
|
||||
}else{
|
||||
$result = $appResult['data'];
|
||||
}
|
||||
}else{//默认zip
|
||||
if(kodZipArchive::support('list')){
|
||||
$result = kodZipArchive::listContent($file);
|
||||
}else{
|
||||
$zip = new PclZip($file);
|
||||
$result = $zip->listContent();
|
||||
}
|
||||
}
|
||||
if($result){
|
||||
//编码转换
|
||||
$charset = unzip_charset_get($result);
|
||||
$output = $output && function_exists('iconv');
|
||||
for ($i=0; $i < count($result); $i++) {
|
||||
//不允许相对路径
|
||||
$result[$i]['filename'] = str_replace(array('../','..\\'),"_",$result[$i]['filename']);
|
||||
// $charset = get_charset($result[$i]['filename']);
|
||||
if($output){
|
||||
$result[$i]['filename'] = iconv_to($result[$i]['filename'],$charset,'utf-8');
|
||||
unset($result[$i]['stored_filename']);
|
||||
}
|
||||
}
|
||||
return array('code'=>true,'data'=>$result);
|
||||
}else{
|
||||
return array('code'=>false,'data'=>$result);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* [extract description]
|
||||
* @param [type] $file [archive file]
|
||||
* @param [type] $dest [extract to folder]
|
||||
* @param string $part [archive file content]
|
||||
* @return [type] [array]
|
||||
*/
|
||||
static function extract($file, $dest, $part = '-1',&$partName=false) {
|
||||
$ext = get_path_ext($file);
|
||||
$listContent = self::listContent($file,false);//不转码
|
||||
if(!$listContent['code']){
|
||||
return $listContent;
|
||||
}
|
||||
if($part != '-1'){//解压部分.则构造 $pathRemove $indexPath
|
||||
$indexInfo = self::fileIndex($listContent['data'],$part);
|
||||
$partName = str_replace(array('../','..\\'),'_',$indexInfo['filename']);
|
||||
$indexPath = $partName;
|
||||
if($GLOBALS['config']['systemCharset'] != 'utf-8'){
|
||||
$indexPath = unzip_pre_name($partName);//系统编码
|
||||
}
|
||||
|
||||
//$pathRemove = get_path_father($indexPath);
|
||||
$pathRemove = get_path_father($partName);//中文情况文件情况兼容
|
||||
|
||||
if($indexInfo['folder']){
|
||||
$indexPath = rtrim($indexPath,'/').'/';//tar 解压文件夹需要/结尾
|
||||
$partName = array($partName);
|
||||
}
|
||||
|
||||
$tempCheck = str_replace('\\','/',$indexPath);
|
||||
if(substr($tempCheck,-1) == '/'){
|
||||
//跟目录;需要追加一层文件夹;window a\b\c\ linux a/b/c/
|
||||
if( !strstr(trim($tempCheck,'/'),'/') ){
|
||||
$dest = $dest.unzip_pre_name(get_path_this($tempCheck)).'/';
|
||||
}
|
||||
}else{
|
||||
if($pathRemove == $indexPath){//根目录文件;
|
||||
$pathRemove = '';
|
||||
}
|
||||
}
|
||||
//debug_out($indexInfo,$indexPath,$partName,$pathRemove,$tempCheck);
|
||||
}
|
||||
|
||||
if( self::checkIfType($ext,'tar') ){
|
||||
//TrOn(10);
|
||||
if($part != '-1'){
|
||||
//tar 默认都进行转码;
|
||||
$indexPath = unzip_pre_name($indexPath);
|
||||
$pathRemove = unzip_pre_name($pathRemove);
|
||||
$result = PclTarExtractList($file,array($indexPath),$dest,$pathRemove);
|
||||
}else{
|
||||
$result = PclTarExtract($file,$dest);
|
||||
}
|
||||
//TrDisplay();exit;
|
||||
return array('code'=>$result,'data'=>PclErrorString(true));
|
||||
}else if( self::checkIfType($ext,'rar')){ // || $ext == 'zip'
|
||||
return kodRarArchive::extract($file,$dest,$ext,$partName);
|
||||
}else if(kodZipArchive::support('extract')){
|
||||
return kodZipArchive::extract($file,$dest,$partName);
|
||||
}else{
|
||||
$zip = new PclZip($file);
|
||||
//解压内部的一部分,按文件名或文件夹来
|
||||
if($part != '-1'){
|
||||
$result = $zip->extract(PCLZIP_OPT_PATH,$dest,
|
||||
PCLZIP_OPT_SET_CHMOD,DEFAULT_PERRMISSIONS,
|
||||
PCLZIP_CB_PRE_FILE_NAME,'unzip_pre_name',
|
||||
|
||||
PCLZIP_OPT_BY_NAME,$indexInfo['filename'],
|
||||
PCLZIP_OPT_REMOVE_PATH,$pathRemove,
|
||||
PCLZIP_OPT_REPLACE_NEWER);
|
||||
}else{
|
||||
$result = $zip->extract(PCLZIP_OPT_PATH,$dest,
|
||||
PCLZIP_OPT_SET_CHMOD,DEFAULT_PERRMISSIONS,
|
||||
PCLZIP_CB_PRE_FILE_NAME,'unzip_pre_name',
|
||||
PCLZIP_OPT_REPLACE_NEWER);//解压到某个地方,覆盖方式
|
||||
}
|
||||
return array('code'=>$result,'data'=>$zip->errorName(true));
|
||||
}
|
||||
return array('code'=>false,'data'=>'File Type Not Support');
|
||||
}
|
||||
|
||||
static function fileIndex($list,$index,$key=false){
|
||||
if(!is_array($list)) return false;
|
||||
$len = count($list);
|
||||
for ($i=0; $i < $len; $i++) {
|
||||
if($index == $list[$i]['index']){
|
||||
$item = $list[$i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!$item){
|
||||
show_tips('KodArchive:fileIndex; index error;file not exists!');
|
||||
}
|
||||
$result = $item;
|
||||
if($key){
|
||||
$result = $item[$key];
|
||||
if($item['folder']){
|
||||
$result = rtrim($result,'/').'/';//tar 解压文件夹需要结尾/
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
static function extractZipFile($file,$byName,$cacheName = false){
|
||||
$temp = TEMP_PATH.'archivePreview/'.hash_path($file).'/';
|
||||
mk_dir($temp);
|
||||
touch(TEMP_PATH.'archivePreview/index.html');
|
||||
$newFile = $temp.md5($file.$byName);
|
||||
if($cacheName){
|
||||
$newFile = $temp.$cacheName;
|
||||
}
|
||||
|
||||
if(file_exists($newFile)){
|
||||
return $newFile;
|
||||
}
|
||||
$zip = new PclZip($file);
|
||||
$outFile = unzip_filter_ext($temp.get_path_this($byName));
|
||||
$parent = get_path_father($byName);
|
||||
if($parent == $byName){
|
||||
$parent = '';
|
||||
}
|
||||
$result = $zip->extract(
|
||||
PCLZIP_OPT_PATH,$temp,
|
||||
PCLZIP_CB_PRE_FILE_NAME,'unzip_pre_name',
|
||||
PCLZIP_OPT_REMOVE_PATH,$parent,
|
||||
PCLZIP_OPT_BY_NAME,$byName);
|
||||
if(!file_exists($outFile)){
|
||||
return false;
|
||||
}
|
||||
@rename($outFile,$newFile);
|
||||
return $newFile;
|
||||
}
|
||||
|
||||
/**
|
||||
* [filePreview file preview or download a file;]
|
||||
* 解压后自动缓存;
|
||||
* @param [type] $file [archive file name]
|
||||
* @param [type] $index [file index]
|
||||
* @return [type] [echo to client;]
|
||||
*/
|
||||
static function filePreview($file,$index,$download=false,$byName = false){
|
||||
$temp = TEMP_PATH.'archivePreview/'.hash_path($file).'/';
|
||||
mk_dir($temp);
|
||||
touch(TEMP_PATH.'archivePreview/index.html');
|
||||
$newFile = $temp.md5($file.$index.$byName);
|
||||
$partName = '';//引用传值,传入处理
|
||||
$result = self::extract($file, $temp,$index,$partName);
|
||||
if(is_array($partName)){//不能是数组——文件夹
|
||||
show_json('unzip preview folder error!',false);
|
||||
}
|
||||
if(file_exists($newFile)){
|
||||
file_put_out($newFile,$download,get_path_this($partName));
|
||||
return;
|
||||
}
|
||||
//$partName 压缩文件原名;初始编码;转为当前文件系统编码
|
||||
$partName = unzip_pre_name($partName);
|
||||
$filenameOutput = get_path_this($partName);
|
||||
$outFile = unzip_filter_ext($temp.$filenameOutput);
|
||||
if(!$result['code']){
|
||||
show_json($result['data'],false);
|
||||
}
|
||||
//debug_out($partName,$file,$outFile,$byName);
|
||||
if(!file_exists($outFile)){
|
||||
show_json('unzip error!',false);
|
||||
}
|
||||
@rename($outFile,$newFile);
|
||||
if(!file_exists($newFile)){
|
||||
del_dir($temp);
|
||||
show_json('unzip:rename error!');
|
||||
}
|
||||
file_put_out($newFile,$download,$filenameOutput);
|
||||
}
|
||||
/**
|
||||
* [create description]
|
||||
* @param [type] $file [archive file name]
|
||||
* @param [type] $files [files add;file or folders]
|
||||
* @return [type] [bool]
|
||||
*/
|
||||
static function create($file,$files) {
|
||||
$ext = get_path_ext($file);
|
||||
$result = false;
|
||||
if( self::checkIfType($ext,'zip') ){
|
||||
if(kodZipArchive::support('add')){
|
||||
return kodZipArchive::create($file,$files);
|
||||
}
|
||||
$archive = new PclZip($file);
|
||||
foreach ($files as $key =>$val) {
|
||||
$val = str_replace('//','/',$val);
|
||||
$removePathPre = _DIR_CLEAR(get_path_father($val));
|
||||
if($key == 0){
|
||||
$result = $archive->create($val,
|
||||
PCLZIP_OPT_REMOVE_PATH,$removePathPre,
|
||||
PCLZIP_CB_PRE_FILE_NAME,'zip_pre_name'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$result = $archive->add($val,
|
||||
PCLZIP_OPT_REMOVE_PATH,$removePathPre,
|
||||
PCLZIP_CB_PRE_FILE_NAME,'zip_pre_name'
|
||||
);
|
||||
}
|
||||
}else if( self::checkIfType($ext,'tar') ){
|
||||
//TrOn(10);
|
||||
foreach ($files as $key =>$val) {
|
||||
$val = str_replace('//','/',$val);
|
||||
$removePathPre = _DIR_CLEAR(get_path_father($val));
|
||||
if($key == 0){
|
||||
$result = PclTarCreate($file,array($val), $ext,null, $removePathPre);
|
||||
continue;
|
||||
}
|
||||
$result = PclTarAddList($file,array($val),'',$removePathPre,$ext);
|
||||
}
|
||||
//TrDisplay();exit;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
<?php
|
||||
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*------
|
||||
* 字符串加解密类;
|
||||
* 一次一密;且定时解密有效
|
||||
* 可用于加密&动态key生成
|
||||
* demo:
|
||||
* 加密:echo Mcrypt::encode('abc','123');
|
||||
* 解密:echo Mcrypt::decode('9f843I0crjv5y0dWE_-uwzL_mZRyRb1ynjGK4I_IACQ','123');
|
||||
*/
|
||||
|
||||
class Mcrypt{
|
||||
public static $default_key = 'a!takA:dlmcldEv,e';
|
||||
|
||||
/**
|
||||
* 字符加解密,一次一密,可定时解密有效
|
||||
*
|
||||
* @param string $string 原文或者密文
|
||||
* @param string $operation 操作(encode | decode)
|
||||
* @param string $key 密钥
|
||||
* @param int $expiry 密文有效期,单位s,0 为永久有效
|
||||
* @return string 处理后的 原文或者 经过 base64_encode 处理后的密文
|
||||
*/
|
||||
public static function encode($string,$key = '', $expiry = 0){
|
||||
$ckeyLength = 4;
|
||||
$key = md5($key ? $key : self::$default_key); //解密密匙
|
||||
$keya = md5(substr($key, 0, 16)); //做数据完整性验证
|
||||
$keyb = md5(substr($key, 16, 16)); //用于变化生成的密文 (初始化向量IV)
|
||||
$keyc = substr(md5(microtime()), - $ckeyLength);
|
||||
$cryptkey = $keya . md5($keya . $keyc);
|
||||
$keyLength = strlen($cryptkey);
|
||||
$string = sprintf('%010d', $expiry ? $expiry + time() : 0).substr(md5($string . $keyb), 0, 16) . $string;
|
||||
$stringLength = strlen($string);
|
||||
|
||||
$rndkey = array();
|
||||
for($i = 0; $i <= 255; $i++) {
|
||||
$rndkey[$i] = ord($cryptkey[$i % $keyLength]);
|
||||
}
|
||||
|
||||
$box = range(0, 255);
|
||||
// 打乱密匙簿,增加随机性
|
||||
for($j = $i = 0; $i < 256; $i++) {
|
||||
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
|
||||
$tmp = $box[$i];
|
||||
$box[$i] = $box[$j];
|
||||
$box[$j] = $tmp;
|
||||
}
|
||||
// 加解密,从密匙簿得出密匙进行异或,再转成字符
|
||||
$result = '';
|
||||
for($a = $j = $i = 0; $i < $stringLength; $i++) {
|
||||
$a = ($a + 1) % 256;
|
||||
$j = ($j + $box[$a]) % 256;
|
||||
$tmp = $box[$a];
|
||||
$box[$a] = $box[$j];
|
||||
$box[$j] = $tmp;
|
||||
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
|
||||
}
|
||||
$result = $keyc . str_replace('=', '', base64_encode($result));
|
||||
$result = str_replace(array('+', '/', '='),array('-', '_', '.'), $result);
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符加解密,一次一密,可定时解密有效
|
||||
*
|
||||
* @param string $string 原文或者密文
|
||||
* @param string $operation 操作(encode | decode)
|
||||
* @param string $key 密钥
|
||||
* @param int $expiry 密文有效期,单位s,0 为永久有效
|
||||
* @return string 处理后的 原文或者 经过 base64_encode 处理后的密文
|
||||
*/
|
||||
public static function decode($string,$key = '')
|
||||
{
|
||||
$string = str_replace(array('-', '_', '.'),array('+', '/', '='), $string);
|
||||
$ckeyLength = 4;
|
||||
$key = md5($key ? $key : self::$default_key); //解密密匙
|
||||
$keya = md5(substr($key, 0, 16)); //做数据完整性验证
|
||||
$keyb = md5(substr($key, 16, 16)); //用于变化生成的密文 (初始化向量IV)
|
||||
$keyc = substr($string, 0, $ckeyLength);
|
||||
$cryptkey = $keya . md5($keya . $keyc);
|
||||
$keyLength = strlen($cryptkey);
|
||||
$string = base64_decode(substr($string, $ckeyLength));
|
||||
$stringLength = strlen($string);
|
||||
|
||||
$rndkey = array();
|
||||
for($i = 0; $i <= 255; $i++) {
|
||||
$rndkey[$i] = ord($cryptkey[$i % $keyLength]);
|
||||
}
|
||||
|
||||
$box = range(0, 255);
|
||||
// 打乱密匙簿,增加随机性
|
||||
for($j = $i = 0; $i < 256; $i++) {
|
||||
$j = ($j + $box[$i] + $rndkey[$i]) % 256;
|
||||
$tmp = $box[$i];
|
||||
$box[$i] = $box[$j];
|
||||
$box[$j] = $tmp;
|
||||
}
|
||||
// 加解密,从密匙簿得出密匙进行异或,再转成字符
|
||||
$result = '';
|
||||
for($a = $j = $i = 0; $i < $stringLength; $i++) {
|
||||
$a = ($a + 1) % 256;
|
||||
$j = ($j + $box[$a]) % 256;
|
||||
$tmp = $box[$a];
|
||||
$box[$a] = $box[$j];
|
||||
$box[$j] = $tmp;
|
||||
$result .= chr(ord($string[$i]) ^ ($box[($box[$a] + $box[$j]) % 256]));
|
||||
}
|
||||
$theTime = intval(substr($result, 0, 10));
|
||||
if (($theTime == 0 || $theTime - time() > 0)
|
||||
&& substr($result, 10, 16) == substr(md5(substr($result, 26) . $keyb), 0, 16)
|
||||
) {
|
||||
return substr($result, 26);
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,303 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
class PluginBase{
|
||||
public $in;
|
||||
public $pluginName;
|
||||
public $pluginPath;
|
||||
public $pluginHost;
|
||||
public $pluginHostDefault;
|
||||
public $pluginApi;
|
||||
public $packageData;
|
||||
|
||||
private $pluginLangArr;
|
||||
private $pluginConfig;
|
||||
function __construct(){
|
||||
global $in,$config;
|
||||
$this->config = &$config;
|
||||
$this->in = &$in;
|
||||
|
||||
$this->pluginName = str_replace('Plugin','',get_class($this));
|
||||
$this->pluginPath = PLUGIN_DIR.$this->pluginName.'/';
|
||||
$this->pluginApi = rtrim(APP_HOST,'/').'/index.php?pluginApp/to/'.$this->pluginName.'/';
|
||||
$this->pluginHost = $this->config['settings']['pluginHost'].$this->pluginName.'/';
|
||||
$this->pluginHostDefault = PLUGIN_HOST.$this->pluginName.'/';
|
||||
$this->pluginLangArr = $this->initLang();
|
||||
return $this;
|
||||
}
|
||||
public function regiest(){
|
||||
$this->hookRegiest(array());
|
||||
$this->setConfig(array());
|
||||
}
|
||||
public function install(){}
|
||||
public function update(){}
|
||||
public function unInstall(){}
|
||||
|
||||
|
||||
/**
|
||||
* 注册hook到当前插件配置
|
||||
* @param [type] $array [description]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
final function hookRegiest($array){
|
||||
$id = $this->pluginName;
|
||||
$systemConfig = &$this->config['settingSystem'];
|
||||
if(!is_array($systemConfig['pluginList'])){
|
||||
$systemConfig['pluginList'] = array();
|
||||
}
|
||||
if(is_array($systemConfig['pluginList'][$id])){
|
||||
$systemConfig['pluginList'][$id]['regiest'] = $array;
|
||||
}else{
|
||||
$systemConfig['pluginList'][$id] = array(
|
||||
'id' => $id,
|
||||
'regiest' => $array,
|
||||
'status' => 0,
|
||||
'config' => $this->getConfig()
|
||||
);
|
||||
}
|
||||
}
|
||||
final function appIcon(){
|
||||
$package = $this->appPackage();
|
||||
$icon = '';
|
||||
if(isset($package['source'])){
|
||||
if($package['source']['icon']){
|
||||
$icon = '<img class="icon" src="'.$package['source']['icon'].'"/>';
|
||||
}else if($package['source']['className']){
|
||||
$icon = "<i class='icon font-icon ".$package['source']['className']."'></i>";
|
||||
}
|
||||
}
|
||||
return $icon;
|
||||
}
|
||||
final function filePath($path){
|
||||
if(substr($path,0,4) == 'http'){
|
||||
if(!request_url_safe($path)){
|
||||
show_json(LNG('url error!'),false);
|
||||
}
|
||||
$cacheName = md5($path.'kodcloud').'.'.get_path_ext($path);
|
||||
$cacheFile = $this->filePathName($cacheName);
|
||||
mk_dir(get_path_father($cacheFile));
|
||||
if(!file_exists($cacheFile)){
|
||||
$result = url_request($path,'DOWNLOAD',$cacheFile);
|
||||
}
|
||||
$path = $cacheFile;
|
||||
}else{
|
||||
$path = _DIR($path);
|
||||
//php7.1,含有中文文件,windows下 curl上传会有问题
|
||||
if( strtoupper(substr(PHP_OS, 0,3)) === 'WIN' &&
|
||||
version_compare(phpversion(), '7.1.0', '>=') &&
|
||||
preg_match("/([\x81-\xfe][\x40-\xfe])/", $path, $match)){
|
||||
|
||||
$cacheName = hash_path($path).'.'.get_path_ext($path);
|
||||
$cacheFile = $this->filePathName($cacheName);
|
||||
mk_dir(get_path_father($cacheFile));
|
||||
if(!file_exists($cacheFile)){
|
||||
@copy($path,$cacheFile);
|
||||
}
|
||||
$path = $cacheFile;
|
||||
}
|
||||
}
|
||||
if (!file_exists($path)) {
|
||||
show_tips(LNG('file').' '.LNG('not_exists'));
|
||||
}
|
||||
return $path;
|
||||
}
|
||||
private function filePathName($fileName){
|
||||
if(! checkExtSafe($fileName)){$fileName = $fileName.'.txt';}
|
||||
return TEMP_PATH.$this->pluginName.'/files/'.$fileName;
|
||||
}
|
||||
|
||||
/**
|
||||
* 插件配置数据加载
|
||||
* @return [type] [description]
|
||||
*/
|
||||
final function appPackage(){
|
||||
if($this->packageData){
|
||||
return $this->packageData;
|
||||
}
|
||||
$content = $this->parseFile($this->pluginPath.'package.json');
|
||||
$this->parseLang($content);
|
||||
$result = json_decode_force($content);
|
||||
if(!$result){
|
||||
return $content;
|
||||
}
|
||||
$this->packageData = $result;
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取package.json中的数据;通过key获取,支持auther.copyright 多级获取
|
||||
* @param [type] $key [description]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
public function packageInfoGet($key){
|
||||
$data = $this->appPackage();
|
||||
$result = null;
|
||||
$keyArr = explode('.',$key);
|
||||
for ($i = 0; $i < count($keyArr); $i++) {
|
||||
if($i == 0){
|
||||
$result = $data[$keyArr[$i]];
|
||||
continue;
|
||||
}
|
||||
if(is_array($result)){
|
||||
$result = $result[$keyArr[$i]];
|
||||
}else{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
public function packageVersion(){return $this->packageInfoGet('version');}
|
||||
public function packageTitle(){return $this->packageInfoGet('title');}
|
||||
public function packageCopyright(){return $this->packageInfoGet('auther.copyright');}
|
||||
|
||||
private function parseFile($file){
|
||||
$content = file_get_contents($file);
|
||||
$replaceFrom = array(
|
||||
'{{pluginHost}}',
|
||||
'{{pluginHostDefault}}',
|
||||
'{{pluginApi}}',
|
||||
'{{pluginName}}',
|
||||
'{{pluginPath}}',
|
||||
'{{appHost}}',
|
||||
'{{staticPath}}',
|
||||
//"\r","\n"
|
||||
);
|
||||
$replaceTo = array(
|
||||
$this->pluginHost,
|
||||
$this->pluginHostDefault,
|
||||
$this->pluginApi,
|
||||
$this->pluginName,
|
||||
$this->pluginPath,
|
||||
APP_HOST,
|
||||
$this->config['settings']['staticPath'],
|
||||
//" "," "
|
||||
);
|
||||
$content = str_replace($replaceFrom,$replaceTo,$content);
|
||||
return $content;
|
||||
}
|
||||
|
||||
private function parseLang(&$content){
|
||||
$pre = '{{LNG.';
|
||||
if(!strstr($content,$pre)){
|
||||
return;
|
||||
}
|
||||
preg_match_all('/{{LNG\..*}}/isU',$content,$match);
|
||||
if( !is_array($match) || count($match) == 0 ||
|
||||
!is_array($match[0]) || count($match[0]) == 0 ){
|
||||
return;
|
||||
}
|
||||
$replaceFrom = array();
|
||||
$replaceTo = array();
|
||||
foreach ($match[0] as $key) {
|
||||
$langKey = substr($key,strlen($pre),-2); //{{LNG.file}}
|
||||
$langVal = LNG($langKey);
|
||||
|
||||
$replaceFrom[] = $key;
|
||||
$replaceTo[] = str_replace(
|
||||
array("\n","\r","\t",'"'),
|
||||
array(' ',' ','','\\"'),
|
||||
$langVal
|
||||
);
|
||||
}
|
||||
$content = str_replace($replaceFrom,$replaceTo,$content);
|
||||
}
|
||||
private function parseConfig(&$content){
|
||||
$config = $this->getConfig();
|
||||
$pre = '{{config.';
|
||||
if(!strstr($content,$pre)){
|
||||
return;
|
||||
}
|
||||
preg_match_all('/{{config\..*}}/isU',$content,$match);
|
||||
if( !is_array($match) || count($match) == 0 ||
|
||||
!is_array($match[0]) || count($match[0]) == 0 ){
|
||||
return;
|
||||
}
|
||||
$replaceFrom = array();
|
||||
$replaceTo = array();
|
||||
foreach ($match[0] as $key) {
|
||||
$langKey = substr($key,strlen($pre),-2); //{{config.file}}
|
||||
$replaceFrom[] = $key;
|
||||
$replaceTo[] = $config[$langKey];
|
||||
}
|
||||
$content = str_replace($replaceFrom,$replaceTo,$content);
|
||||
}
|
||||
|
||||
/**
|
||||
* 输出文件
|
||||
* @param [type] $file [description]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
final function echoFile($file,$replace=false){
|
||||
$filePath = $this->pluginPath.$file;
|
||||
if(ACT == 'commonJs'){
|
||||
echo "\n/* [".$this->pluginName.'/'.$file."] */";
|
||||
if(!file_exists($filePath)){
|
||||
echo " /* ==>[not exist]*/";
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
$content = $this->parseFile($filePath);
|
||||
$this->parseLang($content);
|
||||
$this->parseConfig($content);
|
||||
if(is_array($replace) && count($replace) == 2){
|
||||
$content = str_replace($replace[0],$replace[1],$content);
|
||||
}
|
||||
echo "\n".$content;
|
||||
}
|
||||
|
||||
/**
|
||||
* 初始化多语言
|
||||
* @return [type] [description]
|
||||
*/
|
||||
final function initLang(){
|
||||
$default = 'en';
|
||||
$path = $this->pluginPath.'i18n/';
|
||||
$lang = I18n::getType();
|
||||
$array = array();
|
||||
if(file_exists($path.$lang.'.php')){
|
||||
$array = include($path.$lang.'.php');
|
||||
}else if(file_exists($path.$default.'.php')){
|
||||
$array = include($path.$default.'.php');
|
||||
}
|
||||
if(!is_array($array)) return array();
|
||||
if(count($array) > 0){
|
||||
I18n::set($array);
|
||||
}
|
||||
return $array;
|
||||
}
|
||||
|
||||
final function isFileExtence($st,$act){
|
||||
if(in_array($st,array('desktop','editor','explorer','share','api'))){
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取插件配置
|
||||
* @return [type] [description]
|
||||
*/
|
||||
final function getConfig(){
|
||||
if(!$this->pluginConfig){
|
||||
$model = new PluginModel();
|
||||
$this->pluginConfig = $model->getConfig($this->pluginName);
|
||||
}
|
||||
return $this->pluginConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* 修改插件配置
|
||||
* @return [type] [description]
|
||||
*/
|
||||
final function setConfig($value){
|
||||
$model = new PluginModel();
|
||||
return $model->setConfig($this->pluginName,$value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* 7zip 解压缩: 7z,xz,bz2(bzip2),gz(gzip),tar,zip
|
||||
* 7zip 仅解压: 7z,xz,,bz2(bzip2),gz(gzip),tar,zip,arj,cab,chm,cpio,deb,dmg,
|
||||
* fat,hfs,iso,lzh,lzma,mbr,msi,nsis,ntfs,,rpm,udf,vhd,wim,xar,z
|
||||
*
|
||||
* rar 仅支持rar文件解压缩
|
||||
* 目前使用解压功能:7z,bz2,zx,z,ios,arj;压缩功能暂停
|
||||
* ------------
|
||||
* 7zip命令行:http://blog.csdn.net/earbao/article/details/51382534
|
||||
* rar命令行 :http://www.cnblogs.com/fetty/p/4769279.html
|
||||
* 7za命令行 :https://www.mankier.com/1/7za //当rar解压失败时尝试调用系统内置7za解压; 支持大于60G文件
|
||||
*/
|
||||
|
||||
|
||||
class kodRarArchive {
|
||||
static function bin($type){
|
||||
$file = dirname(__FILE__).'/bin/'.$type;
|
||||
$file = str_replace('\\','/',$file);
|
||||
if(PHP_OS == "Darwin"){//mac
|
||||
$file = PLUGIN_DIR.'/zipView/lib/bin/'.$type.'_mac';
|
||||
}
|
||||
if(!file_exists($file)){
|
||||
show_json('bin file not exists!',false);
|
||||
}
|
||||
if(PATH_SEPARATOR == ':') {
|
||||
@chmod($file,0777);
|
||||
}
|
||||
return $file;
|
||||
}
|
||||
static function run($cmd){
|
||||
if (strtoupper(substr(PHP_OS, 0,3)) != 'WIN') {//linux
|
||||
$cmd = "export LANG='en_US.UTF-8' && ".$cmd;
|
||||
@setlocale(LC_ALL,'en_US.UTF-8');
|
||||
@putenv('LC_ALL=en_US.UTF-8');
|
||||
}
|
||||
$result = shell_exec($cmd);
|
||||
//debug_out($cmd,$result);
|
||||
if(!strstr($result,'Copyright')){
|
||||
return array('code'=>false,'data'=>'[shell_exec error!] No Result!');
|
||||
}
|
||||
return array('code'=>true,'data'=>$result);
|
||||
}
|
||||
|
||||
/**
|
||||
* 防止通过构造文件名,进行shell注入
|
||||
*/
|
||||
static function extract($file,$dest,$ext,$partName=false,$passwd=false) {
|
||||
$dest_before = $dest;
|
||||
$dest = TEMP_PATH.'archivePreview/'.md5(rand_string(40).time()).'/';
|
||||
mk_dir($dest);touch(TEMP_PATH.'archivePreview/index.html');
|
||||
|
||||
$passwd = $passwd ?" -p".escapeShell($passwd).' ':'';
|
||||
if($ext == 'rar'){
|
||||
$param = ' -y '.$passwd.escapeShell($file).' '.escapeShell($dest).' ';
|
||||
if($partName === false){
|
||||
$command = self::bin('rar').' x'.$param;
|
||||
}else if(is_array($partName)){
|
||||
$command = self::bin('rar').' x'.$param.escapeShell($partName[0]);
|
||||
}else{
|
||||
$command = self::bin('rar').' e'.$param.escapeShell($partName);
|
||||
}
|
||||
}else{
|
||||
if($ext == 'bz2'){
|
||||
$ext = 'bzip2';
|
||||
}
|
||||
$param = ' -y -t'.escapeShell($ext).$passwd.' -o'.escapeShell($dest).' '.escapeShell($file).' ';
|
||||
if($partName === false){
|
||||
$command = self::bin('7z').' x'.$param;
|
||||
}else if(is_array($partName)){
|
||||
$command = self::bin('7z').' x'.$param.escapeShell($partName[0]);
|
||||
}else{
|
||||
$command = self::bin('7z').' e'.$param.escapeShell($partName);
|
||||
}
|
||||
}
|
||||
$result = self::run($command);
|
||||
|
||||
//7za 兼容 rar解压大文件
|
||||
if(strstr($result['data'],'is not RAR archive') && shell_exec('7za')){
|
||||
$param = ' -y -o'.escapeShell($dest).' '.escapeShell($file).' ';
|
||||
if($partName === false){
|
||||
$command = '7za x'.$param;
|
||||
}else if(is_array($partName)){
|
||||
$command = '7za x'.$param.escapeShell($partName[0]);
|
||||
}else{
|
||||
$command = '7za e'.$param.escapeShell($partName);
|
||||
}
|
||||
$result = self::run($command);
|
||||
}
|
||||
|
||||
//echo "<pre>";var_dump($result,$command);exit;
|
||||
if(!$result['code']){
|
||||
return $result;
|
||||
}
|
||||
|
||||
//子目录解压移除多余层级目录
|
||||
if( is_array($partName) ){
|
||||
$thePath = trim(str_replace("\\",'/',$partName[0]),'/');
|
||||
$pathGroup = explode('/',$thePath);
|
||||
//一级目录解压不用移动
|
||||
if(count($pathGroup) > 1){
|
||||
move_path($dest.$partName[0],$dest.get_path_this($thePath));
|
||||
del_dir($dest.$pathGroup[0]);
|
||||
}else{
|
||||
$dest_before = get_path_father($dest_before);
|
||||
}
|
||||
}
|
||||
|
||||
//扩展名处理;文件名重命名处理
|
||||
$arr = dir_list($dest);
|
||||
foreach($arr as $f){
|
||||
$itemPath = str_replace(array($dest,"\\"),array('','/'),$f);
|
||||
$itemPath = unzip_pre_name($itemPath);
|
||||
$from = $dest.get_path_father($itemPath).get_path_this($f);
|
||||
if(strstr($itemPath,'/') == false){
|
||||
$from = $dest.get_path_this($f);
|
||||
}
|
||||
if($dest.$itemPath != $from){
|
||||
@rename($from,$dest.$itemPath);
|
||||
}
|
||||
}
|
||||
move_path($dest,$dest_before);
|
||||
del_dir(rtrim($dest,'/'));
|
||||
return $result;
|
||||
}
|
||||
|
||||
static function listContent($file) {
|
||||
if(get_path_ext($file) == 'rar'){
|
||||
return self::listContentRar($file);
|
||||
}else{
|
||||
return self::listContent7z($file);
|
||||
}
|
||||
}
|
||||
|
||||
static function listContentRar($file) {
|
||||
$command = self::bin('rar').' v '.escapeShell($file);
|
||||
$result = self::run($command);
|
||||
//7za 兼容 rar解压大文件
|
||||
if(strstr($result['data'],'is not RAR archive') && shell_exec('7za')){
|
||||
return self::listContent7z($file,'7za l ');
|
||||
}
|
||||
if(!$result['code']){
|
||||
return $result;
|
||||
}
|
||||
|
||||
preg_match('/-------- ----\n([\d\D]*)\n-----------/i', $result['data'], $match);
|
||||
if(!is_array($match) || strlen($match[1]) < 10){
|
||||
return array('code'=>false,'data'=>'Match Nothing Content!');
|
||||
}
|
||||
|
||||
//windows :...D... 93691 82633 88% 2016-12-09 02:20 396CC62C 000/a/32486963.png
|
||||
//linux: :-rwxr-xr-x 93691 82643 88% 2016-12-09 02:20 396CC62C 000/a/32486963.png
|
||||
$reg = '/\s*([-\.\w]+)\s+(\d+)\s+(\d+)\s+\d+%|-+>\s+(\d{2,4}-\d{2}-\d{2} \d{2}:\d{2})\s+\w+\s+(.*)\n/i';
|
||||
preg_match_all($reg,$match[1]."\n",$matchItem);
|
||||
if( !is_array($matchItem) ||
|
||||
count($matchItem) != 6 ||
|
||||
count($matchItem[0]) == 0
|
||||
){
|
||||
return array('code'=>false,'data'=>'Match Nothing Item!');
|
||||
}
|
||||
|
||||
$itemArr = array();
|
||||
for ($i = 0; $i < count($matchItem[0]); $i++) {
|
||||
$mode = strtoupper($matchItem[1][$i]);
|
||||
$isFolder = substr($mode,0,1) == 'D' || substr($mode,3,1) == 'D';
|
||||
$itemArr[] = array(
|
||||
'mtime' => strtotime($matchItem[4][$i]),
|
||||
'size' => $matchItem[2][$i],
|
||||
'z_size' => $matchItem[3][$i],
|
||||
'filename' => trim($matchItem[5][$i]),
|
||||
'index' => $i,
|
||||
'folder' => intval($isFolder)
|
||||
);
|
||||
}
|
||||
//debug_out($result,$match,$matchItem,$itemArr);
|
||||
return array('code'=>true,'data'=>$itemArr);
|
||||
}
|
||||
static function listContent7z($file,$bin=false) {
|
||||
$command = self::bin('7z').' l '.escapeShell($file);
|
||||
if($bin){
|
||||
$command = $bin.escapeShell($file);
|
||||
}
|
||||
$result = self::run($command);
|
||||
if(!$result['code']){
|
||||
return $result;
|
||||
}
|
||||
|
||||
preg_match('/-----------\n([\d\D]*)\n--------------/i', $result['data'], $match);
|
||||
if(!is_array($match) || strlen($match[1]) < 10){
|
||||
return array('code'=>false,'data'=>'Match Nothing Content!');
|
||||
}
|
||||
|
||||
//2017-03-08 11:22:16 ..... 10727 9385 000\test11.docx
|
||||
//2017-03-09 13:43:10 ....A 6254 000\111.md
|
||||
$reg = '/(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}) (D?\.+A?)\s+(\d+)\s+(\d*)\s+(.*)/i';
|
||||
preg_match_all($reg,$match[1],$matchItem);
|
||||
if( !is_array($matchItem) ||
|
||||
count($matchItem) != 6 ||
|
||||
count($matchItem[0]) == 0
|
||||
){
|
||||
return array('code'=>false,'data'=>'Match Nothing Item!');
|
||||
}
|
||||
|
||||
$itemArr = array();
|
||||
for ($i = 0; $i < count($matchItem[0]); $i++) {
|
||||
$itemArr[] = array(
|
||||
'mtime' => strtotime($matchItem[1][$i]),
|
||||
'size' => $matchItem[3][$i],
|
||||
'z_size' => $matchItem[4][$i],
|
||||
'filename' => trim($matchItem[5][$i]),
|
||||
'index' => $i,
|
||||
'folder' => substr($matchItem[2][$i],0,1) == 'D'
|
||||
);
|
||||
}
|
||||
//debug_out($result,$match,$matchItem,$itemArr);
|
||||
return array('code'=>true,'data'=>$itemArr);;
|
||||
}
|
||||
|
||||
/**
|
||||
* [create description]
|
||||
* @param [type] $file [creat file to]
|
||||
* @param [type] $ext [ext:7z,xz,bz2,gzip,tar,zip]
|
||||
* @param [type] $files [array from]
|
||||
* @param boolean $passwd [password]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
// static function create($file,$files,$ext,$passwd=false) {
|
||||
// $passwd = $passwd? " -p".$passwd.' ':"";
|
||||
// $spearat = (PATH_SEPARATOR != ':')?("&& ".substr($files,0,2)." "):"";//win=>; linux=>:
|
||||
// $command = 'cd "'.$files.'" '.$spearat.' &&';//cd到所在文件夹;
|
||||
// $command = $command.self::bin().' a -r -y -t'.$ext.' '.$passwd.' "'.$file.'" *';
|
||||
// return self::run($command);
|
||||
// }
|
||||
}
|
||||
|
||||
// 不允许双引号
|
||||
function escapeShell($param){
|
||||
return escapeshellarg($param);
|
||||
//$param = escapeshellarg($param);
|
||||
$os = strtoupper(substr(PHP_OS, 0,3));
|
||||
if ( $os != 'WIN' && $os != 'DAR') {//linux
|
||||
$param = str_replace('!','\!',$param);
|
||||
}
|
||||
$param = rtrim($param,"\\");
|
||||
return '"'.str_replace(array('"',"\0",'`'),'_',$param).'"';
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
// ZipArchive 解压缩
|
||||
class kodZipArchive{
|
||||
static $listCache = array();
|
||||
static function support($type=''){
|
||||
$result = false;
|
||||
if($type == 'extract' && defined("ZIP_ARCHIVE_LOCAL")){// 只允许创建压缩文件用系统调用
|
||||
$result = true;
|
||||
}
|
||||
if(!class_exists('ZipArchive')){
|
||||
$result = false;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
static function listContent($file){
|
||||
$file_hash = hash_path($file);
|
||||
if(isset(self::$listCache[$file_hash])){
|
||||
return self::$listCache[$file_hash];
|
||||
}
|
||||
$zip = new ZipArchive();
|
||||
$zip->open($file);
|
||||
$count = $zip->numFiles;
|
||||
for ($i = 0; $i < $count; $i++) {
|
||||
$entry = $zip->statIndex($i);
|
||||
$filename = str_replace('\\', '/', $entry['name']);
|
||||
$result[] = array(
|
||||
'filename' => $entry['name'],
|
||||
'stored_filename' => $entry['name'],
|
||||
'size' => $entry['size'],
|
||||
'compressed_size' => $entry['comp_size'],
|
||||
'mtime' => $entry['mtime'],
|
||||
'index' => $i,
|
||||
'folder' => (substr($entry['name'], -1, 1) == '/'),
|
||||
'crc' => $entry['crc']
|
||||
);
|
||||
}
|
||||
self::$listCache[$file_hash] = $result;
|
||||
return $result;
|
||||
}
|
||||
/**
|
||||
* [extract description]
|
||||
* @param [type] $file [archive file]
|
||||
* @param [type] $dest [extract to folder]
|
||||
* @param string $part [archive file content]
|
||||
* @return [type] [array]
|
||||
*/
|
||||
static function extract($file,$dest,$partName=false) {
|
||||
$dest_before = $dest;
|
||||
$dest = TEMP_PATH.'archivePreview/'.md5(rand_string(40).time()).'/';
|
||||
mk_dir($dest);touch(TEMP_PATH.'archivePreview/index.html');
|
||||
|
||||
$zip = new ZipArchive();
|
||||
if(!$zip->open($file)){
|
||||
return array('code'=>false,'data'=>'Can not open zip file!');
|
||||
}
|
||||
|
||||
if($partName === false){
|
||||
$result = $zip->extractTo($dest);
|
||||
}else{
|
||||
if(!is_array($partName)){
|
||||
$partName = array($partName);
|
||||
}
|
||||
$matchFiles = $partName;
|
||||
//解压文件夹
|
||||
if(substr($partName[0], -1, 1) == '/'){
|
||||
$matchFiles = array();
|
||||
$list = self::listContent($file);
|
||||
foreach ($list as $item) {
|
||||
if ( strpos($item['filename'],$partName[0]) === 0 ) {
|
||||
$matchFiles[] = $item['filename'];
|
||||
}
|
||||
}
|
||||
}
|
||||
$result = $zip->extractTo($dest,$matchFiles);
|
||||
}
|
||||
$zip->close();
|
||||
|
||||
//子目录解压移除多余层级目录
|
||||
if( is_array($partName) ){
|
||||
$thePath = trim(str_replace("\\",'/',$partName[0]),'/');
|
||||
$pathGroup = explode('/',$thePath);
|
||||
//一级目录解压不用移动
|
||||
if(count($pathGroup) > 1){
|
||||
move_path($dest.$partName[0],$dest.get_path_this($thePath));
|
||||
del_dir($dest.$pathGroup[0]);
|
||||
}else{
|
||||
$dest_before = get_path_father($dest_before);
|
||||
}
|
||||
}
|
||||
|
||||
//扩展名处理;文件名重命名处理
|
||||
$arr = dir_list($dest);
|
||||
foreach($arr as $f){
|
||||
$itemPath = str_replace(array($dest,"\\"),array('','/'),$f);
|
||||
$itemPath = unzip_pre_name($itemPath);
|
||||
$from = $dest.get_path_father($itemPath).get_path_this($f);
|
||||
if(strstr($itemPath,'/') == false){
|
||||
$from = $dest.get_path_this($f);
|
||||
}
|
||||
if($dest.$itemPath != $from){
|
||||
@rename($from,$dest.$itemPath);
|
||||
}
|
||||
}
|
||||
move_path($dest,$dest_before);
|
||||
del_dir(rtrim($dest,'/'));
|
||||
return array('code'=>$result,'data'=>$result);
|
||||
}
|
||||
|
||||
/**
|
||||
* [create description]
|
||||
* @param [type] $file [creat file to]
|
||||
* @param [type] $files [array from]
|
||||
* @return [type] [description]
|
||||
*/
|
||||
static function create($file,$files) {
|
||||
$zip = new ZipArchive();
|
||||
if(!$zip->open($file, ZipArchive::CREATE)){
|
||||
return false;//Can not open(create) zip file!'
|
||||
}
|
||||
foreach ($files as $key =>$val) {
|
||||
$val = str_replace(array('//','\\'),'/',$val);
|
||||
$removePathPre = _DIR_CLEAR(get_path_father($val));
|
||||
$list = array($val);
|
||||
if(is_dir($val)){
|
||||
$list = dir_list($val);
|
||||
$list[] = $val;
|
||||
}
|
||||
foreach ($list as $item) {
|
||||
$addName = zip_pre_name(str_replace($removePathPre,'',$item));
|
||||
if(is_dir($item)){
|
||||
$result = $zip->addEmptyDir($addName);
|
||||
}else{
|
||||
$result = $zip->addFile($item,$addName);
|
||||
}
|
||||
}
|
||||
}
|
||||
$zip->close();
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
// --------------------------------------------------------------------------------
|
||||
// PhpConcept Library (PCL) Error 1.0
|
||||
// --------------------------------------------------------------------------------
|
||||
// License GNU/GPL - Vincent Blavet - Mars 2001
|
||||
// http://www.phpconcept.net & http://phpconcept.free.fr
|
||||
// --------------------------------------------------------------------------------
|
||||
// Français :
|
||||
// La description de l'usage de la librairie PCL Error 1.0 n'est pas encore
|
||||
// disponible. Celle-ci n'est pour le moment distribuée qu'avec les
|
||||
// développements applicatifs de PhpConcept.
|
||||
// Une version indépendante sera bientot disponible sur http://www.phpconcept.net
|
||||
//
|
||||
// English :
|
||||
// The PCL Error 1.0 library description is not available yet. This library is
|
||||
// released only with PhpConcept application and libraries.
|
||||
// An independant release will be soon available on http://www.phpconcept.net
|
||||
//
|
||||
// --------------------------------------------------------------------------------
|
||||
//
|
||||
// * Avertissement :
|
||||
//
|
||||
// Cette librairie a été créée de façon non professionnelle.
|
||||
// Son usage est au risque et péril de celui qui l'utilise, en aucun cas l'auteur
|
||||
// de ce code ne pourra être tenu pour responsable des éventuels dégats qu'il pourrait
|
||||
// engendrer.
|
||||
// Il est entendu cependant que l'auteur a réalisé ce code par plaisir et n'y a
|
||||
// caché aucun virus, ni malveillance.
|
||||
// Cette libairie est distribuée sous la license GNU/GPL (http://www.gnu.org)
|
||||
//
|
||||
// * Auteur :
|
||||
//
|
||||
// Ce code a été écrit par Vincent Blavet (vincent@blavet.net) sur son temps
|
||||
// de loisir.
|
||||
//
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// ----- Look for double include
|
||||
if (!defined("PCLERROR_LIB"))
|
||||
{
|
||||
define( "PCLERROR_LIB", 1 );
|
||||
|
||||
// ----- Version
|
||||
$g_pcl_error_version = "1.0";
|
||||
|
||||
// ----- Internal variables
|
||||
// These values must only be change by PclError library functions
|
||||
$g_pcl_error_string = "";
|
||||
$g_pcl_error_code = 1;
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : PclErrorLog()
|
||||
// Description :
|
||||
// Parameters :
|
||||
// --------------------------------------------------------------------------------
|
||||
function PclErrorLog($p_error_code=0, $p_error_string="")
|
||||
{
|
||||
global $g_pcl_error_string;
|
||||
global $g_pcl_error_code;
|
||||
|
||||
$g_pcl_error_code = $p_error_code;
|
||||
$g_pcl_error_string = $p_error_string;
|
||||
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : PclErrorFatal()
|
||||
// Description :
|
||||
// Parameters :
|
||||
// --------------------------------------------------------------------------------
|
||||
function PclErrorFatal($p_file, $p_line, $p_error_string="")
|
||||
{
|
||||
global $g_pcl_error_string;
|
||||
global $g_pcl_error_code;
|
||||
|
||||
$v_message = "<html><body>";
|
||||
$v_message .= "<p align=center><font color=red bgcolor=white><b>PclError Library has detected a fatal error on file '$p_file', line $p_line</b></font></p>";
|
||||
$v_message .= "<p align=center><font color=red bgcolor=white><b>$p_error_string</b></font></p>";
|
||||
$v_message .= "</body></html>";
|
||||
die($v_message);
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : PclErrorReset()
|
||||
// Description :
|
||||
// Parameters :
|
||||
// --------------------------------------------------------------------------------
|
||||
function PclErrorReset()
|
||||
{
|
||||
global $g_pcl_error_string;
|
||||
global $g_pcl_error_code;
|
||||
|
||||
$g_pcl_error_code = 1;
|
||||
$g_pcl_error_string = "";
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : PclErrorCode()
|
||||
// Description :
|
||||
// Parameters :
|
||||
// --------------------------------------------------------------------------------
|
||||
function PclErrorCode()
|
||||
{
|
||||
global $g_pcl_error_string;
|
||||
global $g_pcl_error_code;
|
||||
|
||||
return($g_pcl_error_code);
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : PclErrorString()
|
||||
// Description :
|
||||
// Parameters :
|
||||
// --------------------------------------------------------------------------------
|
||||
function PclErrorString()
|
||||
{
|
||||
global $g_pcl_error_string;
|
||||
global $g_pcl_error_code;
|
||||
|
||||
return($g_pcl_error_string." [code $g_pcl_error_code]");
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// ----- End of double include look
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,453 @@
|
||||
<?php
|
||||
// --------------------------------------------------------------------------------
|
||||
// PhpConcept Library (PCL) Trace 1.0
|
||||
// --------------------------------------------------------------------------------
|
||||
// License GNU/GPL - Vincent Blavet - Janvier 2001
|
||||
// http://www.phpconcept.net & http://phpconcept.free.fr
|
||||
// --------------------------------------------------------------------------------
|
||||
// Français :
|
||||
// La description de l'usage de la librairie PCL Trace 1.0 n'est pas encore
|
||||
// disponible. Celle-ci n'est pour le moment distribuée qu'avec l'application
|
||||
// et la librairie PhpZip.
|
||||
// Une version indépendante sera bientot disponible sur http://www.phpconcept.net
|
||||
//
|
||||
// English :
|
||||
// The PCL Trace 1.0 library description is not available yet. This library is
|
||||
// released only with PhpZip application and library.
|
||||
// An independant release will be soon available on http://www.phpconcept.net
|
||||
//
|
||||
// --------------------------------------------------------------------------------
|
||||
//
|
||||
// * Avertissement :
|
||||
//
|
||||
// Cette librairie a été créée de façon non professionnelle.
|
||||
// Son usage est au risque et péril de celui qui l'utilise, en aucun cas l'auteur
|
||||
// de ce code ne pourra être tenu pour responsable des éventuels dégats qu'il pourrait
|
||||
// engendrer.
|
||||
// Il est entendu cependant que l'auteur a réalisé ce code par plaisir et n'y a
|
||||
// caché aucun virus, ni malveillance.
|
||||
// Cette libairie est distribuée sous la license GNU/GPL (http://www.gnu.org)
|
||||
//
|
||||
// * Auteur :
|
||||
//
|
||||
// Ce code a été écrit par Vincent Blavet (vincent@blavet.net) sur son temps
|
||||
// de loisir.
|
||||
//
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// ----- Look for double include
|
||||
if (!defined("PCLTRACE_LIB"))
|
||||
{
|
||||
define( "PCLTRACE_LIB", 1 );
|
||||
|
||||
// ----- Version
|
||||
$g_pcl_trace_version = "1.0";
|
||||
|
||||
// ----- Internal variables
|
||||
// These values must be change by PclTrace library functions
|
||||
$g_pcl_trace_mode = "memory";
|
||||
$g_pcl_trace_filename = "trace.txt";
|
||||
$g_pcl_trace_name = array();
|
||||
$g_pcl_trace_index = 0;
|
||||
$g_pcl_trace_level = 10;
|
||||
$g_pcl_trace_entries = array();
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : TrOn($p_level, $p_mode, $p_filename)
|
||||
// Description :
|
||||
// Parameters :
|
||||
// $p_level : Trace level
|
||||
// $p_mode : Mode of trace displaying :
|
||||
// 'normal' : messages are displayed at function call
|
||||
// 'memory' : messages are memorized in a table and can be display by
|
||||
// TrDisplay() function. (default)
|
||||
// 'log' : messages are writed in the file $p_filename
|
||||
// --------------------------------------------------------------------------------
|
||||
function TrOn($p_level=1, $p_mode="memory", $p_filename="trace.txt")
|
||||
{
|
||||
global $g_pcl_trace_level;
|
||||
global $g_pcl_trace_mode;
|
||||
global $g_pcl_trace_filename;
|
||||
global $g_pcl_trace_name;
|
||||
global $g_pcl_trace_index;
|
||||
global $g_pcl_trace_entries;
|
||||
|
||||
// ----- Enable trace mode
|
||||
$g_pcl_trace_level = $p_level;
|
||||
|
||||
// ----- Memorize mode and filename
|
||||
switch ($p_mode) {
|
||||
case "normal" :
|
||||
case "memory" :
|
||||
case "log" :
|
||||
$g_pcl_trace_mode = $p_mode;
|
||||
break;
|
||||
default :
|
||||
$g_pcl_trace_mode = "logged";
|
||||
}
|
||||
|
||||
// ----- Memorize filename
|
||||
$g_pcl_trace_filename = $p_filename;
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : IsTrOn()
|
||||
// Description :
|
||||
// Return value :
|
||||
// The trace level (0 for disable).
|
||||
// --------------------------------------------------------------------------------
|
||||
function IsTrOn()
|
||||
{
|
||||
global $g_pcl_trace_level;
|
||||
|
||||
return($g_pcl_trace_level);
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : TrOff()
|
||||
// Description :
|
||||
// Parameters :
|
||||
// --------------------------------------------------------------------------------
|
||||
function TrOff()
|
||||
{
|
||||
global $g_pcl_trace_level;
|
||||
global $g_pcl_trace_mode;
|
||||
global $g_pcl_trace_filename;
|
||||
global $g_pcl_trace_name;
|
||||
global $g_pcl_trace_index;
|
||||
|
||||
// ----- Clean
|
||||
$g_pcl_trace_mode = "memory";
|
||||
unset($g_pcl_trace_entries);
|
||||
unset($g_pcl_trace_name);
|
||||
unset($g_pcl_trace_index);
|
||||
|
||||
// ----- Switch off trace
|
||||
$g_pcl_trace_level = 0;
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : TrFctStart()
|
||||
// Description :
|
||||
// Just a trace function for debbugging purpose before I use a better tool !!!!
|
||||
// Start and stop of this function is by $g_pcl_trace_level global variable.
|
||||
// Parameters :
|
||||
// $p_level : Level of trace required.
|
||||
// --------------------------------------------------------------------------------
|
||||
function TrFctStart($p_file, $p_line, $p_name, $p_param="", $p_message="")
|
||||
{
|
||||
global $g_pcl_trace_level;
|
||||
global $g_pcl_trace_mode;
|
||||
global $g_pcl_trace_filename;
|
||||
global $g_pcl_trace_name;
|
||||
global $g_pcl_trace_index;
|
||||
global $g_pcl_trace_entries;
|
||||
|
||||
// ----- Look for disabled trace
|
||||
if ($g_pcl_trace_level < 1)
|
||||
return;
|
||||
|
||||
// ----- Add the function name in the list
|
||||
if (!isset($g_pcl_trace_name))
|
||||
$g_pcl_trace_name = $p_name;
|
||||
else
|
||||
$g_pcl_trace_name .= ",".$p_name;
|
||||
|
||||
// ----- Update the function entry
|
||||
$i = sizeof($g_pcl_trace_entries);
|
||||
$g_pcl_trace_entries[$i][name] = $p_name;
|
||||
$g_pcl_trace_entries[$i][param] = $p_param;
|
||||
$g_pcl_trace_entries[$i][message] = "";
|
||||
$g_pcl_trace_entries[$i][file] = $p_file;
|
||||
$g_pcl_trace_entries[$i][line] = $p_line;
|
||||
$g_pcl_trace_entries[$i][index] = $g_pcl_trace_index;
|
||||
$g_pcl_trace_entries[$i][type] = "1"; // means start of function
|
||||
|
||||
// ----- Update the message entry
|
||||
if ($p_message != "")
|
||||
{
|
||||
$i = sizeof($g_pcl_trace_entries);
|
||||
$g_pcl_trace_entries[$i][name] = "";
|
||||
$g_pcl_trace_entries[$i][param] = "";
|
||||
$g_pcl_trace_entries[$i][message] = $p_message;
|
||||
$g_pcl_trace_entries[$i][file] = $p_file;
|
||||
$g_pcl_trace_entries[$i][line] = $p_line;
|
||||
$g_pcl_trace_entries[$i][index] = $g_pcl_trace_index;
|
||||
$g_pcl_trace_entries[$i][type] = "3"; // means message
|
||||
}
|
||||
|
||||
// ----- Action depending on mode
|
||||
PclTraceAction($g_pcl_trace_entries[$i]);
|
||||
|
||||
// ----- Increment the index
|
||||
$g_pcl_trace_index++;
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : TrFctEnd()
|
||||
// Description :
|
||||
// Just a trace function for debbugging purpose before I use a better tool !!!!
|
||||
// Start and stop of this function is by $g_pcl_trace_level global variable.
|
||||
// Parameters :
|
||||
// $p_level : Level of trace required.
|
||||
// --------------------------------------------------------------------------------
|
||||
function TrFctEnd($p_file, $p_line, $p_return=1, $p_message="")
|
||||
{
|
||||
global $g_pcl_trace_level;
|
||||
global $g_pcl_trace_mode;
|
||||
global $g_pcl_trace_filename;
|
||||
global $g_pcl_trace_name;
|
||||
global $g_pcl_trace_index;
|
||||
global $g_pcl_trace_entries;
|
||||
|
||||
// ----- Look for disabled trace
|
||||
if ($g_pcl_trace_level < 1)
|
||||
return;
|
||||
|
||||
// ----- Extract the function name in the list
|
||||
// ----- Remove the function name in the list
|
||||
if (!($v_name = strrchr($g_pcl_trace_name, ",")))
|
||||
{
|
||||
$v_name = $g_pcl_trace_name;
|
||||
$g_pcl_trace_name = "";
|
||||
}
|
||||
else
|
||||
{
|
||||
$g_pcl_trace_name = substr($g_pcl_trace_name, 0, strlen($g_pcl_trace_name)-strlen($v_name));
|
||||
$v_name = substr($v_name, -strlen($v_name)+1);
|
||||
}
|
||||
|
||||
// ----- Decrement the index
|
||||
$g_pcl_trace_index--;
|
||||
|
||||
// ----- Update the message entry
|
||||
if ($p_message != "")
|
||||
{
|
||||
$i = sizeof($g_pcl_trace_entries);
|
||||
$g_pcl_trace_entries[$i][name] = "";
|
||||
$g_pcl_trace_entries[$i][param] = "";
|
||||
$g_pcl_trace_entries[$i][message] = $p_message;
|
||||
$g_pcl_trace_entries[$i][file] = $p_file;
|
||||
$g_pcl_trace_entries[$i][line] = $p_line;
|
||||
$g_pcl_trace_entries[$i][index] = $g_pcl_trace_index;
|
||||
$g_pcl_trace_entries[$i][type] = "3"; // means message
|
||||
}
|
||||
|
||||
// ----- Update the function entry
|
||||
$i = sizeof($g_pcl_trace_entries);
|
||||
$g_pcl_trace_entries[$i][name] = $v_name;
|
||||
$g_pcl_trace_entries[$i][param] = $p_return;
|
||||
$g_pcl_trace_entries[$i][message] = "";
|
||||
$g_pcl_trace_entries[$i][file] = $p_file;
|
||||
$g_pcl_trace_entries[$i][line] = $p_line;
|
||||
$g_pcl_trace_entries[$i][index] = $g_pcl_trace_index;
|
||||
$g_pcl_trace_entries[$i][type] = "2"; // means end of function
|
||||
|
||||
// ----- Action depending on mode
|
||||
PclTraceAction($g_pcl_trace_entries[$i]);
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : TrFctMessage()
|
||||
// Description :
|
||||
// Parameters :
|
||||
// --------------------------------------------------------------------------------
|
||||
function TrFctMessage($p_file, $p_line, $p_level, $p_message="")
|
||||
{
|
||||
global $g_pcl_trace_level;
|
||||
global $g_pcl_trace_mode;
|
||||
global $g_pcl_trace_filename;
|
||||
global $g_pcl_trace_name;
|
||||
global $g_pcl_trace_index;
|
||||
global $g_pcl_trace_entries;
|
||||
|
||||
// ----- Look for disabled trace
|
||||
if ($g_pcl_trace_level < $p_level)
|
||||
return;
|
||||
|
||||
// ----- Update the entry
|
||||
$i = sizeof($g_pcl_trace_entries);
|
||||
$g_pcl_trace_entries[$i][name] = "";
|
||||
$g_pcl_trace_entries[$i][param] = "";
|
||||
$g_pcl_trace_entries[$i][message] = $p_message;
|
||||
$g_pcl_trace_entries[$i][file] = $p_file;
|
||||
$g_pcl_trace_entries[$i][line] = $p_line;
|
||||
$g_pcl_trace_entries[$i][index] = $g_pcl_trace_index;
|
||||
$g_pcl_trace_entries[$i][type] = "3"; // means message of function
|
||||
|
||||
// ----- Action depending on mode
|
||||
PclTraceAction($g_pcl_trace_entries[$i]);
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : TrMessage()
|
||||
// Description :
|
||||
// Parameters :
|
||||
// --------------------------------------------------------------------------------
|
||||
function TrMessage($p_file, $p_line, $p_level, $p_message="")
|
||||
{
|
||||
global $g_pcl_trace_level;
|
||||
global $g_pcl_trace_mode;
|
||||
global $g_pcl_trace_filename;
|
||||
global $g_pcl_trace_name;
|
||||
global $g_pcl_trace_index;
|
||||
global $g_pcl_trace_entries;
|
||||
|
||||
// ----- Look for disabled trace
|
||||
if ($g_pcl_trace_level < $p_level)
|
||||
return;
|
||||
|
||||
// ----- Update the entry
|
||||
$i = sizeof($g_pcl_trace_entries);
|
||||
$g_pcl_trace_entries[$i][name] = "";
|
||||
$g_pcl_trace_entries[$i][param] = "";
|
||||
$g_pcl_trace_entries[$i][message] = $p_message;
|
||||
$g_pcl_trace_entries[$i][file] = $p_file;
|
||||
$g_pcl_trace_entries[$i][line] = $p_line;
|
||||
$g_pcl_trace_entries[$i][index] = $g_pcl_trace_index;
|
||||
$g_pcl_trace_entries[$i][type] = "4"; // means simple message
|
||||
|
||||
// ----- Action depending on mode
|
||||
PclTraceAction($g_pcl_trace_entries[$i]);
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : TrDisplay()
|
||||
// Description :
|
||||
// Parameters :
|
||||
// --------------------------------------------------------------------------------
|
||||
function TrDisplay()
|
||||
{
|
||||
global $g_pcl_trace_level;
|
||||
global $g_pcl_trace_mode;
|
||||
global $g_pcl_trace_filename;
|
||||
global $g_pcl_trace_name;
|
||||
global $g_pcl_trace_index;
|
||||
global $g_pcl_trace_entries;
|
||||
|
||||
// ----- Look for disabled trace
|
||||
if (($g_pcl_trace_level <= 0) || ($g_pcl_trace_mode != "memory"))
|
||||
return;
|
||||
|
||||
$v_font = "\"Verdana, Arial, Helvetica, sans-serif\"";
|
||||
|
||||
// ----- Trace Header
|
||||
echo "<table width=100% border=0 cellspacing=0 cellpadding=0>";
|
||||
echo "<tr bgcolor=#0000CC>";
|
||||
echo "<td bgcolor=#0000CC width=1>";
|
||||
echo "</td>";
|
||||
echo "<td><div align=center><font size=3 color=#FFFFFF face=$v_font>Trace</font></div></td>";
|
||||
echo "</tr>";
|
||||
echo "<tr>";
|
||||
echo "<td bgcolor=#0000CC width=1>";
|
||||
echo "</td>";
|
||||
echo "<td>";
|
||||
|
||||
// ----- Content header
|
||||
echo "<table width=100% border=0 cellspacing=0 cellpadding=0>";
|
||||
|
||||
// ----- Display
|
||||
$v_again=0;
|
||||
for ($i=0; $i<sizeof($g_pcl_trace_entries); $i++)
|
||||
{
|
||||
// ---- Row header
|
||||
echo "<tr>";
|
||||
echo "<td><table width=100% border=0 cellspacing=0 cellpadding=0><tr>";
|
||||
$n = ($g_pcl_trace_entries[$i][index]+1)*10;
|
||||
echo "<td width=".$n."><table width=100% border=0 cellspacing=0 cellpadding=0><tr>";
|
||||
|
||||
for ($j=0; $j<=$g_pcl_trace_entries[$i][index]; $j++)
|
||||
{
|
||||
if ($j==$g_pcl_trace_entries[$i][index])
|
||||
{
|
||||
if (($g_pcl_trace_entries[$i][type] == 1) || ($g_pcl_trace_entries[$i][type] == 2))
|
||||
echo "<td width=10><div align=center><font size=2 face=$v_font>+</font></div></td>";
|
||||
}
|
||||
else
|
||||
echo "<td width=10><div align=center><font size=2 face=$v_font>|</font></div></td>";
|
||||
}
|
||||
//echo "<td> </td>";
|
||||
echo "</tr></table></td>";
|
||||
|
||||
echo "<td width=2></td>";
|
||||
switch ($g_pcl_trace_entries[$i][type]) {
|
||||
case 1:
|
||||
echo "<td><font size=2 face=$v_font>".$g_pcl_trace_entries[$i][name]."(".$g_pcl_trace_entries[$i][param].")</font></td>";
|
||||
break;
|
||||
case 2:
|
||||
echo "<td><font size=2 face=$v_font>".$g_pcl_trace_entries[$i][name]."()=".$g_pcl_trace_entries[$i][param]."</font></td>";
|
||||
break;
|
||||
case 3:
|
||||
case 4:
|
||||
echo "<td><table width=100% border=0 cellspacing=0 cellpadding=0><td width=20></td><td>";
|
||||
echo "<font size=2 face=$v_font>".$g_pcl_trace_entries[$i][message]."</font>";
|
||||
echo "</td></table></td>";
|
||||
break;
|
||||
default:
|
||||
echo "<td><font size=2 face=$v_font>".$g_pcl_trace_entries[$i][name]."(".$g_pcl_trace_entries[$i][param].")</font></td>";
|
||||
}
|
||||
echo "</tr></table></td>";
|
||||
echo "<td width=5></td>";
|
||||
echo "<td><font size=1 face=$v_font>".basename($g_pcl_trace_entries[$i][file])."</font></td>";
|
||||
echo "<td width=5></td>";
|
||||
echo "<td><font size=1 face=$v_font>".$g_pcl_trace_entries[$i][line]."</font></td>";
|
||||
echo "</tr>";
|
||||
}
|
||||
|
||||
// ----- Content footer
|
||||
echo "</table>";
|
||||
|
||||
// ----- Trace footer
|
||||
echo "</td>";
|
||||
echo "<td bgcolor=#0000CC width=1>";
|
||||
echo "</td>";
|
||||
echo "</tr>";
|
||||
echo "<tr bgcolor=#0000CC>";
|
||||
echo "<td bgcolor=#0000CC width=1>";
|
||||
echo "</td>";
|
||||
echo "<td><div align=center><font color=#FFFFFF face=$v_font> </font></div></td>";
|
||||
echo "</tr>";
|
||||
echo "</table>";
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// --------------------------------------------------------------------------------
|
||||
// Function : PclTraceAction()
|
||||
// Description :
|
||||
// Parameters :
|
||||
// --------------------------------------------------------------------------------
|
||||
function PclTraceAction($p_entry)
|
||||
{
|
||||
global $g_pcl_trace_level;
|
||||
global $g_pcl_trace_mode;
|
||||
global $g_pcl_trace_filename;
|
||||
global $g_pcl_trace_name;
|
||||
global $g_pcl_trace_index;
|
||||
global $g_pcl_trace_entries;
|
||||
|
||||
if ($g_pcl_trace_mode == "normal")
|
||||
{
|
||||
for ($i=0; $i<$p_entry[index]; $i++)
|
||||
echo "---";
|
||||
if ($p_entry[type] == 1)
|
||||
echo "<b>".$p_entry[name]."</b>(".$p_entry[param].") : ".$p_entry[message]." [".$p_entry[file].", ".$p_entry[line]."]<br>";
|
||||
else if ($p_entry[type] == 2)
|
||||
echo "<b>".$p_entry[name]."</b>()=".$p_entry[param]." : ".$p_entry[message]." [".$p_entry[file].", ".$p_entry[line]."]<br>";
|
||||
else
|
||||
echo $p_entry[message]." [".$p_entry[file].", ".$p_entry[line]."]<br>";
|
||||
}
|
||||
}
|
||||
// --------------------------------------------------------------------------------
|
||||
|
||||
// ----- End of double include look
|
||||
}
|
||||
@@ -0,0 +1,286 @@
|
||||
<?php
|
||||
// from elfinder;
|
||||
class imageGdBMP{
|
||||
public static function load($filename){
|
||||
$fp = fopen($filename, "rb");
|
||||
if ($fp === false){
|
||||
return false;
|
||||
}
|
||||
$bmp = self::loadFromStream($fp);
|
||||
fclose($fp);
|
||||
return $bmp;
|
||||
}
|
||||
public static function loadFromStream($stream){
|
||||
$buf = fread($stream, 14); //2+4+2+2+4
|
||||
if ($buf === false){
|
||||
return false;
|
||||
}
|
||||
if ($buf[0] != 'B' || $buf[1] != 'M'){
|
||||
return false;
|
||||
}
|
||||
$bitmapHeader = unpack(
|
||||
"vtype/".
|
||||
"Vsize/".
|
||||
"vreserved1/".
|
||||
"vreserved2/".
|
||||
"Voffbits", $buf
|
||||
);
|
||||
return self::loadFromStreamAndFileHeader($stream, $bitmapHeader);
|
||||
}
|
||||
public static function loadFromStreamAndFileHeader($stream, array $bitmapHeader){
|
||||
if ($bitmapHeader["type"] != 0x4d42){
|
||||
return false;
|
||||
}
|
||||
$buf = fread($stream, 4);
|
||||
if ($buf === false){
|
||||
return false;
|
||||
}
|
||||
list(,$header_size) = unpack("V", $buf);
|
||||
if ($header_size == 12){
|
||||
$buf = fread($stream, $header_size - 4);
|
||||
if ($buf === false){
|
||||
return false;
|
||||
}
|
||||
extract(unpack(
|
||||
"vwidth/".
|
||||
"vheight/".
|
||||
"vplanes/".
|
||||
"vbit_count", $buf
|
||||
));
|
||||
$clr_used = $clr_important = $alpha_mask = $compression = 0;
|
||||
$red_mask = 0x00ff0000;
|
||||
$green_mask = 0x0000ff00;
|
||||
$blue_mask = 0x000000ff;
|
||||
} else if (124 < $header_size || $header_size < 40) {
|
||||
return false;
|
||||
} else {
|
||||
$buf = fread($stream, 36);
|
||||
if ($buf === false){
|
||||
return false;
|
||||
}
|
||||
extract(unpack(
|
||||
"Vwidth/".
|
||||
"Vheight/".
|
||||
"vplanes/".
|
||||
"vbit_count/".
|
||||
"Vcompression/".
|
||||
"Vsize_image/".
|
||||
"Vx_pels_per_meter/".
|
||||
"Vy_pels_per_meter/".
|
||||
"Vclr_used/".
|
||||
"Vclr_important", $buf
|
||||
));
|
||||
if ($width & 0x80000000){ $width = -(~$width & 0xffffffff) - 1; }
|
||||
if ($height & 0x80000000){ $height = -(~$height & 0xffffffff) - 1; }
|
||||
if ($x_pels_per_meter & 0x80000000){ $x_pels_per_meter = -(~$x_pels_per_meter & 0xffffffff) - 1; }
|
||||
if ($y_pels_per_meter & 0x80000000){ $y_pels_per_meter = -(~$y_pels_per_meter & 0xffffffff) - 1; }
|
||||
if ($bitmapHeader["size"] != 0){
|
||||
$colorsize = $bit_count == 1 || $bit_count == 4 || $bit_count == 8 ? ($clr_used ? $clr_used : pow(2, $bit_count))<<2 : 0;
|
||||
$bodysize = $size_image ? $size_image : ((($width * $bit_count + 31) >> 3) & ~3) * abs($height);
|
||||
$calcsize = $bitmapHeader["size"] - $bodysize - $colorsize - 14;
|
||||
if ($header_size < $calcsize && 40 <= $header_size && $header_size <= 124){
|
||||
$header_size = $calcsize;
|
||||
}
|
||||
}
|
||||
if ($header_size - 40 > 0){
|
||||
$buf = fread($stream, $header_size - 40);
|
||||
if ($buf === false){
|
||||
return false;
|
||||
}
|
||||
extract(unpack(
|
||||
"Vred_mask/".
|
||||
"Vgreen_mask/".
|
||||
"Vblue_mask/".
|
||||
"Valpha_mask", $buf . str_repeat("\x00", 120)
|
||||
));
|
||||
} else {
|
||||
$alpha_mask = $red_mask = $green_mask = $blue_mask = 0;
|
||||
}
|
||||
if (
|
||||
($bit_count == 16 || $bit_count == 24 || $bit_count == 32)&&
|
||||
$compression == 0 &&
|
||||
$red_mask == 0 && $green_mask == 0 && $blue_mask == 0
|
||||
){
|
||||
switch($bit_count){
|
||||
case 16:
|
||||
$red_mask = 0x7c00;
|
||||
$green_mask = 0x03e0;
|
||||
$blue_mask = 0x001f;
|
||||
break;
|
||||
case 24:
|
||||
case 32:
|
||||
$red_mask = 0x00ff0000;
|
||||
$green_mask = 0x0000ff00;
|
||||
$blue_mask = 0x000000ff;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
($width == 0)||
|
||||
($height == 0)||
|
||||
($planes != 1)||
|
||||
(($alpha_mask & $red_mask ) != 0)||
|
||||
(($alpha_mask & $green_mask) != 0)||
|
||||
(($alpha_mask & $blue_mask ) != 0)||
|
||||
(($red_mask & $green_mask) != 0)||
|
||||
(($red_mask & $blue_mask ) != 0)||
|
||||
(($green_mask & $blue_mask ) != 0)
|
||||
){
|
||||
return false;
|
||||
}
|
||||
if ($compression == 4 || $compression == 5){
|
||||
$buf = stream_get_contents($stream, $size_image);
|
||||
if ($buf === false){
|
||||
return false;
|
||||
}
|
||||
return imagecreatefromstring($buf);
|
||||
}
|
||||
$line_bytes = (($width * $bit_count + 31) >> 3) & ~3;
|
||||
$lines = abs($height);
|
||||
$y = $height > 0 ? $lines-1 : 0;
|
||||
$line_step = $height > 0 ? -1 : 1;
|
||||
if ($bit_count == 1 || $bit_count == 4 || $bit_count == 8){
|
||||
$img = imagecreate($width, $lines);
|
||||
$palette_size = $header_size == 12 ? 3 : 4;
|
||||
$colors = $clr_used ? $clr_used : pow(2, $bit_count);
|
||||
$palette = array();
|
||||
for($i = 0; $i < $colors; ++$i){
|
||||
$buf = fread($stream, $palette_size);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
extract(unpack("Cb/Cg/Cr/Cx", $buf . "\x00"));
|
||||
$palette[] = imagecolorallocate($img, $r, $g, $b);
|
||||
}
|
||||
|
||||
$shift_base = 8 - $bit_count;
|
||||
$mask = ((1 << $bit_count) - 1) << $shift_base;
|
||||
if ($compression == 1 || $compression == 2){
|
||||
$x = 0;
|
||||
$qrt_mod2 = $bit_count >> 2 & 1;
|
||||
for(;;){
|
||||
if ($x < -1 || $x > $width || $y < -1 || $y > $height){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
$buf = fread($stream, 1);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
switch($buf){
|
||||
case "\x00":
|
||||
$buf = fread($stream, 1);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
switch($buf){
|
||||
case "\x00": //EOL
|
||||
$y += $line_step;
|
||||
$x = 0;
|
||||
break;
|
||||
case "\x01": //EOB
|
||||
$y = 0;
|
||||
$x = 0;
|
||||
break 3;
|
||||
case "\x02": //MOV
|
||||
$buf = fread($stream, 2);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
list(,$xx, $yy) = unpack("C2", $buf);
|
||||
$x += $xx;
|
||||
$y += $yy * $line_step;
|
||||
break;
|
||||
default:
|
||||
list(,$pixels) = unpack("C", $buf);
|
||||
$bytes = ($pixels >> $qrt_mod2) + ($pixels & $qrt_mod2);
|
||||
$buf = fread($stream, ($bytes + 1) & ~1);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
for ($i = 0, $pos = 0; $i < $pixels; ++$i, ++$x, $pos += $bit_count){
|
||||
list(,$c) = unpack("C", $buf[$pos >> 3]);
|
||||
$b = $pos & 0x07;
|
||||
imagesetpixel($img, $x, $y, $palette[($c & ($mask >> $b)) >> ($shift_base - $b)]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
$buf2 = fread($stream, 1);
|
||||
if ($buf2 === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
list(,$size, $c) = unpack("C2", $buf . $buf2);
|
||||
for($i = 0, $pos = 0; $i < $size; ++$i, ++$x, $pos += $bit_count){
|
||||
$b = $pos & 0x07;
|
||||
imagesetpixel($img, $x, $y, $palette[($c & ($mask >> $b)) >> ($shift_base - $b)]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for ($line = 0; $line < $lines; ++$line, $y += $line_step){
|
||||
$buf = fread($stream, $line_bytes);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
|
||||
$pos = 0;
|
||||
for ($x = 0; $x < $width; ++$x, $pos += $bit_count){
|
||||
list(,$c) = unpack("C", $buf[$pos >> 3]);
|
||||
$b = $pos & 0x7;
|
||||
imagesetpixel($img, $x, $y, $palette[($c & ($mask >> $b)) >> ($shift_base - $b)]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
$img = imagecreatetruecolor($width, $lines);
|
||||
imagealphablending($img, false);
|
||||
if ($alpha_mask){
|
||||
imagesavealpha($img, true);
|
||||
}
|
||||
|
||||
//x軸進行量
|
||||
$pixel_step = $bit_count >> 3;
|
||||
$alpha_max = $alpha_mask ? 0x7f : 0x00;
|
||||
$alpha_mask_r = $alpha_mask ? 1/$alpha_mask : 1;
|
||||
$red_mask_r = $red_mask ? 1/$red_mask : 1;
|
||||
$green_mask_r = $green_mask ? 1/$green_mask : 1;
|
||||
$blue_mask_r = $blue_mask ? 1/$blue_mask : 1;
|
||||
|
||||
for ($line = 0; $line < $lines; ++$line, $y += $line_step){
|
||||
$buf = fread($stream, $line_bytes);
|
||||
if ($buf === false){
|
||||
imagedestroy($img);
|
||||
return false;
|
||||
}
|
||||
$pos = 0;
|
||||
for ($x = 0; $x < $width; ++$x, $pos += $pixel_step){
|
||||
list(,$c) = unpack("V", substr($buf, $pos, $pixel_step). "\x00\x00");
|
||||
$a_masked = $c & $alpha_mask;
|
||||
$r_masked = $c & $red_mask;
|
||||
$g_masked = $c & $green_mask;
|
||||
$b_masked = $c & $blue_mask;
|
||||
$a = $alpha_max - ((($a_masked<<7) - $a_masked) * $alpha_mask_r);
|
||||
$r = (($r_masked<<8) - $r_masked) * $red_mask_r;
|
||||
$g = (($g_masked<<8) - $g_masked) * $green_mask_r;
|
||||
$b = (($b_masked<<8) - $b_masked) * $blue_mask_r;
|
||||
imagesetpixel($img, $x, $y, ($a<<24)|($r<<16)|($g<<8)|$b);
|
||||
}
|
||||
}
|
||||
imagealphablending($img, true);
|
||||
}
|
||||
return $img;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
<?php
|
||||
class ConfigModel extends Model{
|
||||
}
|
||||
|
||||
@@ -0,0 +1,191 @@
|
||||
<?php
|
||||
class pluginModel{
|
||||
var $in;
|
||||
var $config;
|
||||
function __construct(){
|
||||
global $config, $in;
|
||||
//parent::__construct();
|
||||
$this -> in = &$in;
|
||||
$this -> config = &$config;
|
||||
}
|
||||
public function loadData(){
|
||||
if(!isset($this->config['settingSystem']['pluginList'])){
|
||||
$this->config['settingSystem']['pluginList'] = array();
|
||||
$this->initDefaultPlugin();//首次,加载并开启默认插件
|
||||
}
|
||||
return $this->config['settingSystem']['pluginList'];
|
||||
}
|
||||
public function saveData(){
|
||||
$settingFile = USER_SYSTEM.'system_setting.php';
|
||||
FileCache::save($settingFile,$this->config['settingSystem']);
|
||||
}
|
||||
private function initDefaultPlugin(){
|
||||
$this->pluginScan();
|
||||
$list = $this->loadData();
|
||||
foreach ($list as $app => $val) {
|
||||
$this->changeStatus($app,1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 加载所有插件hook;
|
||||
*/
|
||||
public function init(){
|
||||
$pluginList = $this->loadData();
|
||||
foreach ($pluginList as $key=>$item) {
|
||||
if(!is_array($item) && isset($item['id'])){
|
||||
continue;
|
||||
}
|
||||
$file = PLUGIN_DIR.$item['id'].'/app.php';
|
||||
if( !$item['status'] || !is_file($file)) {
|
||||
continue;
|
||||
}
|
||||
if(!$this->checkAuth($item['id'])){
|
||||
continue;
|
||||
}
|
||||
foreach ($item['regiest'] as $tag => $action) {
|
||||
Hook::bind($tag,$action);
|
||||
}
|
||||
}
|
||||
//执行全局插件绑定
|
||||
Hook::trigger("globalRequest");
|
||||
Hook::trigger(ST.'.'.ACT);
|
||||
}
|
||||
|
||||
public function checkAuth($app){
|
||||
$pluginList = $this->loadData();
|
||||
if( !isset($pluginList[$app]) ||
|
||||
!$pluginList[$app]['status']){
|
||||
show_tips("Not exist or disabled!");
|
||||
}
|
||||
if( !isset($pluginList[$app]['config']['pluginAuth']) ){
|
||||
return true;
|
||||
}
|
||||
|
||||
$auth = $pluginList[$app]['config']['pluginAuth'];
|
||||
if(plugin_check_auth($app,$auth)){
|
||||
return true;
|
||||
}else{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public function add($app){
|
||||
if( !file_exists(PLUGIN_DIR.$app.'/package.json') ||
|
||||
!file_exists(PLUGIN_DIR.$app.'/app.php')){
|
||||
return;
|
||||
}
|
||||
Hook::apply($app.'Plugin.regiest');
|
||||
$this->saveData();
|
||||
}
|
||||
public function remove($app){
|
||||
$pluginList = &$this->config['settingSystem']['pluginList'];
|
||||
unset($pluginList[$app]);
|
||||
|
||||
if( file_exists(PLUGIN_DIR.$app)){
|
||||
Hook::apply($app.'Plugin.unInstall');
|
||||
}
|
||||
$this->saveData();
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 切换插件启用关闭状态
|
||||
* @param [type] $app 插件名
|
||||
* @param [type] $open 开关状态 0-禁用;1-启用
|
||||
* @return
|
||||
*/
|
||||
public function changeStatus($app,$open){
|
||||
$pluginList = &$this->config['settingSystem']['pluginList'];
|
||||
if(is_array($pluginList[$app])){
|
||||
if($open){
|
||||
$config = $this->getConfig($app);
|
||||
$default = $this->getConfigDefault($app);
|
||||
$config = array_merge($default,$config);//保存初始配置;兼容新增默认配置
|
||||
Hook::apply($app.'Plugin.regiest');
|
||||
$this->setConfig($app,$config);
|
||||
}
|
||||
$pluginList[$app]['status'] = $open;
|
||||
}
|
||||
$this->saveData();
|
||||
}
|
||||
|
||||
public function getConfigDefault($app){
|
||||
$result = array();
|
||||
$json = $this->getPackageJson($app);
|
||||
if(!$json && is_array($json['configItem'])){
|
||||
return $result;
|
||||
}
|
||||
foreach($json['configItem'] as $key=>$item) {
|
||||
if(!isset($item['value']) ||
|
||||
isset($result[$key]) ){
|
||||
continue;
|
||||
}
|
||||
$result[$key] = $item['value'];
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function getPackageJson($app){
|
||||
return Hook::apply($app.'Plugin.appPackage');
|
||||
}
|
||||
public function getConfig($app){
|
||||
$result = array();
|
||||
$pluginList = &$this->config['settingSystem']['pluginList'];
|
||||
if( isset($pluginList[$app]) &&
|
||||
is_array($pluginList[$app]['config']) ){
|
||||
$result = $pluginList[$app]['config'];
|
||||
}
|
||||
if(!$result){
|
||||
$result = $this->getConfigDefault($app);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function setConfig($app,$value){
|
||||
$pluginList = &$this->config['settingSystem']['pluginList'];
|
||||
if(isset($pluginList[$app])){
|
||||
foreach ($value as $key => $val) {
|
||||
$pluginList[$app]['config'][$key] = $val;
|
||||
}
|
||||
}
|
||||
$this->saveData();
|
||||
}
|
||||
|
||||
/**
|
||||
* 遍历查检目录;自动加载插件;
|
||||
* @return [type] [description]
|
||||
*/
|
||||
public function pluginScan(){
|
||||
$pluginList = &$this->config['settingSystem']['pluginList'];
|
||||
recursion_dir(PLUGIN_DIR,$dirs,$files,0);
|
||||
foreach ($dirs as $path) {
|
||||
$app = get_path_this($path);
|
||||
if(isset($pluginList[$app])){
|
||||
continue;
|
||||
}
|
||||
if( !file_exists($path.'/package.json') ||
|
||||
!file_exists($path.'/app.php')){
|
||||
continue;
|
||||
}
|
||||
Hook::apply($app.'Plugin.regiest');
|
||||
}
|
||||
$this->saveData();
|
||||
}
|
||||
public function viewList(){
|
||||
$this->pluginScan();
|
||||
$list = $this->loadData();
|
||||
$result = array();
|
||||
foreach ($list as $key => $item) {
|
||||
if(!plugin_check_allow($key)){
|
||||
continue;
|
||||
}
|
||||
unset($item['regiest']);
|
||||
$package = Hook::apply($item['id'].'Plugin.appPackage');
|
||||
if(is_array($package)){
|
||||
$result[$key] = array_merge($item,$package);
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,224 @@
|
||||
<?php
|
||||
class MyCaptcha{
|
||||
var $keystring;
|
||||
function __construct($length){
|
||||
$alphabet = "0123456789abcdefghijklmnopqrstuvwxyz"; # do not change without changing font files!
|
||||
$width = 140;
|
||||
$height = 60;
|
||||
$fluctuation_amplitude = $height/10;//上下起伏
|
||||
$white_noise_density=1/10;//$white_noise_density=0; // no white noise
|
||||
$black_noise_density=1/100;//$black_noise_density=0; // no black noise
|
||||
$foreground_color = array(mt_rand(0,120), mt_rand(0,120), mt_rand(0,120));
|
||||
$background_color = array(mt_rand(220,255), mt_rand(220,255), mt_rand(220,255));
|
||||
|
||||
$font_path = dirname(__FILE__).'/MyCaptcha_fonts/';
|
||||
$fonts=array($font_path.'font_1.png',$font_path.'font_2.png',$font_path.'font_3.png');
|
||||
$alphabet_length=strlen($alphabet);
|
||||
do{
|
||||
$this->keystring = $this->randString($length);
|
||||
$font_file=$fonts[mt_rand(0, count($fonts)-1)];
|
||||
$font=imagecreatefrompng($font_file);
|
||||
imagealphablending($font, true);
|
||||
$fontfile_width=imagesx($font);
|
||||
$fontfile_height=imagesy($font)-1;
|
||||
|
||||
$font_metrics=array();
|
||||
$symbol=0;
|
||||
$reading_symbol=false;
|
||||
|
||||
// loading font
|
||||
for($i=0;$i<$fontfile_width && $symbol<$alphabet_length;$i++){
|
||||
$transparent = (imagecolorat($font, $i, 0) >> 24) == 127;
|
||||
if(!$reading_symbol && !$transparent){
|
||||
$font_metrics[$alphabet{$symbol}]=array('start'=>$i);
|
||||
$reading_symbol=true;
|
||||
continue;
|
||||
}
|
||||
if($reading_symbol && $transparent){
|
||||
$font_metrics[$alphabet{$symbol}]['end']=$i;
|
||||
$reading_symbol=false;
|
||||
$symbol++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
$img=imagecreatetruecolor($width, $height);
|
||||
imagealphablending($img, true);
|
||||
$white=imagecolorallocate($img, 255, 255, 255);
|
||||
$black=imagecolorallocate($img, 0, 0, 0);
|
||||
imagefilledrectangle($img, 0, 0, $width-1, $height-1, $white);
|
||||
$x=1;
|
||||
$odd=mt_rand(0,1);
|
||||
if($odd==0) $odd=-1;
|
||||
for($i=0;$i<$length;$i++){
|
||||
$m=$font_metrics[$this->keystring{$i}];
|
||||
|
||||
$y=(($i%2)*$fluctuation_amplitude - $fluctuation_amplitude/2)*$odd
|
||||
+ mt_rand(-round($fluctuation_amplitude/3), round($fluctuation_amplitude/3))
|
||||
+ ($height-$fontfile_height)/2;
|
||||
$shift=1;
|
||||
imagecopy($img, $font, $x-$shift, $y, $m['start'], 1, $m['end']-$m['start'], $fontfile_height);
|
||||
$x+=$m['end']-$m['start']-$shift;
|
||||
}
|
||||
}while($x>=$width-10); // while not fit in canvas
|
||||
|
||||
//noise
|
||||
$white=imagecolorallocate($font, 255, 255, 255);
|
||||
$black=imagecolorallocate($font, 0, 0, 0);
|
||||
for($i=0;$i<(($height-30)*$x)*$white_noise_density;$i++){
|
||||
imagesetpixel($img, mt_rand(0, $x-1), mt_rand(10, $height-15), $white);
|
||||
}
|
||||
for($i=0;$i<(($height-30)*$x)*$black_noise_density;$i++){
|
||||
imagesetpixel($img, mt_rand(0, $x-1), mt_rand(10, $height-15), $black);
|
||||
}
|
||||
|
||||
$center=$x/2;
|
||||
// credits. To remove, see configuration file
|
||||
$img2=imagecreatetruecolor($width, $height);
|
||||
$foreground=imagecolorallocate($img2, $foreground_color[0], $foreground_color[1], $foreground_color[2]);
|
||||
$background=imagecolorallocate($img2, $background_color[0], $background_color[1], $background_color[2]);
|
||||
imagefilledrectangle($img2, 0, 0, $width-1, $height-1, $background);
|
||||
imagefilledrectangle($img2, 0, $height, $width-1, $height+12, $foreground);
|
||||
$this->drawLine($img2,$width,$height);
|
||||
|
||||
// periods
|
||||
$rand1=mt_rand(750000,1200000)/10000000;
|
||||
$rand2=mt_rand(750000,1200000)/10000000;
|
||||
$rand3=mt_rand(750000,1200000)/10000000;
|
||||
$rand4=mt_rand(750000,1200000)/10000000;
|
||||
// phases
|
||||
$rand5=mt_rand(0,31415926)/10000000;
|
||||
$rand6=mt_rand(0,31415926)/10000000;
|
||||
$rand7=mt_rand(0,31415926)/10000000;
|
||||
$rand8=mt_rand(0,31415926)/10000000;
|
||||
// amplitudes
|
||||
$rand9=mt_rand(330,420)/110;
|
||||
$rand10=mt_rand(330,450)/100;
|
||||
|
||||
//wave distortion
|
||||
for($x=0;$x<$width;$x++){
|
||||
for($y=0;$y<$height;$y++){
|
||||
$sx=$x+(sin($x*$rand1+$rand5)+sin($y*$rand3+$rand6))*$rand9-$width/2+$center+1;
|
||||
$sy=$y+(sin($x*$rand2+$rand7)+sin($y*$rand4+$rand8))*$rand10;
|
||||
|
||||
if($sx<0 || $sy<0 || $sx>=$width-1 || $sy>=$height-1){
|
||||
continue;
|
||||
}else{
|
||||
$color=imagecolorat($img, $sx, $sy) & 0xFF;
|
||||
$color_x=imagecolorat($img, $sx+1, $sy) & 0xFF;
|
||||
$color_y=imagecolorat($img, $sx, $sy+1) & 0xFF;
|
||||
$color_xy=imagecolorat($img, $sx+1, $sy+1) & 0xFF;
|
||||
}
|
||||
if($color==255 && $color_x==255 && $color_y==255 && $color_xy==255){
|
||||
continue;
|
||||
}else if($color==0 && $color_x==0 && $color_y==0 && $color_xy==0){
|
||||
$newred=$foreground_color[0];
|
||||
$newgreen=$foreground_color[1];
|
||||
$newblue=$foreground_color[2];
|
||||
}else{
|
||||
$frsx=$sx-floor($sx);
|
||||
$frsy=$sy-floor($sy);
|
||||
$frsx1=1-$frsx;
|
||||
$frsy1=1-$frsy;
|
||||
|
||||
$newcolor=(
|
||||
$color*$frsx1*$frsy1+
|
||||
$color_x*$frsx*$frsy1+
|
||||
$color_y*$frsx1*$frsy+
|
||||
$color_xy*$frsx*$frsy
|
||||
);
|
||||
if($newcolor>255) $newcolor=255;
|
||||
$newcolor=$newcolor/255;
|
||||
$newcolor0=1-$newcolor;
|
||||
|
||||
$newred=$newcolor0*$foreground_color[0]+$newcolor*$background_color[0];
|
||||
$newgreen=$newcolor0*$foreground_color[1]+$newcolor*$background_color[1];
|
||||
$newblue=$newcolor0*$foreground_color[2]+$newcolor*$background_color[2];
|
||||
}
|
||||
imagesetpixel($img2, $x, $y, imagecolorallocate($img2, $newred, $newgreen, $newblue));
|
||||
}
|
||||
}
|
||||
$this->showImage($img2);
|
||||
}
|
||||
public function getString(){
|
||||
return $this->keystring;
|
||||
}
|
||||
private function randString($length){
|
||||
$str = '';
|
||||
$allowed_symbols = "23456789abcdegikpqsvxyz"; //without symbols (o=0, 1=l, i=j, t=f)
|
||||
while(true){
|
||||
$str = '';
|
||||
for($i=0;$i<$length;$i++){
|
||||
$str .= $allowed_symbols{mt_rand(0,strlen($allowed_symbols)-1)};
|
||||
}
|
||||
if(!preg_match('/cp|cb|ck|c6|c9|rn|rm|mm|co|do|cl|db|qp|qb|dp|ww/',$str)) break;
|
||||
}
|
||||
return $str;
|
||||
}
|
||||
|
||||
private function frand(){
|
||||
return mt_rand(0,9999)/10000;
|
||||
}
|
||||
private function drawLine(&$img,$width,$height){
|
||||
$line_number = 5;
|
||||
$color_from = 100;
|
||||
for ($line = 0; $line < $line_number; ++ $line) {
|
||||
$line_color = imagecolorallocate($img, mt_rand($color_from,255),
|
||||
mt_rand($color_from, 255),mt_rand($color_from, 255));
|
||||
$x = $width * (1 + $line) / ($line_number + 1);
|
||||
$x += (0.5 - $this->frand()) * $width / $line_number;
|
||||
$y = mt_rand($height * 0.1, $height * 0.9);
|
||||
|
||||
$theta = ($this->frand() - 0.5) * M_PI * 0.7;
|
||||
$w = $width;
|
||||
$len = mt_rand($w * 0.4, $w * 0.7);
|
||||
$lwid = mt_rand(0, 2);
|
||||
|
||||
$k = $this->frand() * 0.6 + 0.2;
|
||||
$k = $k * $k * 0.5;
|
||||
$phi = $this->frand() * 6.28;
|
||||
$step = 0.5;
|
||||
$dx = $step * cos($theta);
|
||||
$dy = $step * sin($theta);
|
||||
$n = $len / $step;
|
||||
$amp = 1.5 * $this->frand() / ($k + 5.0 / $len);
|
||||
$x0 = $x - 0.5 * $len * cos($theta);
|
||||
$y0 = $y - 0.5 * $len * sin($theta);
|
||||
|
||||
$ldx = round(- $dy * $lwid);
|
||||
$ldy = round($dx * $lwid);
|
||||
for ($i = 0; $i < $n; ++ $i) {
|
||||
$x = $x0 + $i * $dx + $amp * $dy * sin($k * $i * $step + $phi);
|
||||
$y = $y0 + $i * $dy - $amp * $dx * sin($k * $i * $step + $phi);
|
||||
imagefilledrectangle($img, $x, $y, $x + $lwid, $y + $lwid,$line_color);
|
||||
}
|
||||
}
|
||||
|
||||
$allowed_symbols = "0123456789abcdefghijklmnopqrstuvwxyz";
|
||||
for ($i = 0; $i < 20; $i++) {//写入随机字串
|
||||
$char = $allowed_symbols[mt_rand(0,strlen($allowed_symbols)-1)];
|
||||
$line_color = imagecolorallocate($img,
|
||||
mt_rand($color_from,255),mt_rand($color_from, 255),mt_rand($color_from, 255));
|
||||
imagechar($img,mt_rand(0,4),mt_rand(0,$width),rand(0,$height),$char,$line_color);
|
||||
}
|
||||
}
|
||||
private function showImage(&$img){
|
||||
ob_get_clean();
|
||||
$out = ob_get_clean();//清除之前所有输出缓冲 TODO
|
||||
|
||||
header('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
|
||||
header('Cache-Control: no-store, no-cache, must-revalidate');
|
||||
header('Cache-Control: post-check=0, pre-check=0', FALSE);
|
||||
header('Pragma: no-cache');
|
||||
if(function_exists("imagejpeg")){
|
||||
header("Content-Type: image/jpeg");
|
||||
imagejpeg($img, null,90);//图片质量
|
||||
}else if(function_exists("imagegif")){
|
||||
header("Content-Type: image/gif");
|
||||
imagegif($img);
|
||||
}else if(function_exists("imagepng")){
|
||||
header("Content-Type: image/x-png");
|
||||
imagepng($img);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 14 KiB |
@@ -0,0 +1,91 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta http-equiv="Content-Script-Type" content="text/javascript">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
|
||||
<meta name="renderer" content="webkit">
|
||||
<link href="<?php echo STATIC_PATH;?>images/common/favicon.ico" rel="Shortcut Icon">
|
||||
<link href="<?php echo STATIC_PATH;?>style/common.css?ver=<?php echo KOD_VERSION;?>" rel="stylesheet"/>
|
||||
<link href="./static/style/font-awesome/css/font-awesome.css?ver=<?php echo KOD_VERSION;?>" rel="stylesheet">
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_explorer.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/win10.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<title>File View</title>
|
||||
<!--[if IE 7]>
|
||||
<link rel="stylesheet" href="./static/style/font-awesome/css/font-awesome-ie7.css">
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
|
||||
<style type="text/css">
|
||||
body{background: transparent;}
|
||||
.frame-main {top: 0;bottom: 0;}
|
||||
.show-code{width: 100%;left: 0;margin: 0;border: none;padding: 0;}
|
||||
.content-box{position: absolute;bottom: 0;top: 0;width: 100%;}
|
||||
.content-box iframe{width: 100%;height: 100%;}
|
||||
.content-box.markdown-preview {padding: 0;height: 100%;}
|
||||
.show-code,.show-code .ace_editor{height: 100%;}
|
||||
|
||||
.eidior-box{width:100%;height:100%;overflow: hidden;position: relative;}
|
||||
.eidior-content{position: absolute;top: 0;left: 0;bottom: 0;right: 0;}
|
||||
.eidior-content .ace_editor{height:100%;}
|
||||
.content-markdown {overflow: auto;height: 100%;padding: 0 20px;}
|
||||
|
||||
.context-menu-list.menu-zip-list-folder{display:none !important;}
|
||||
.menu-zip-list-file .context-menu-item.unzip-to,
|
||||
.menu-zip-list-file .context-menu-item.unzip-this,
|
||||
.menu-zip-list-file .context-menu-item.info,
|
||||
.menu-zip-list-file .context-menu-item.open-with,
|
||||
.menu-zip-list-file .context-menu-item.context-menu-separator{display:none !important;}
|
||||
|
||||
.ztree li a,.ztree li a:hover,
|
||||
.ztree li a.curSelectedNode, .ztree li span.name,
|
||||
.ztree li a.curDropTreeNode{height:30px;line-height:30px;}
|
||||
.ztree li span.tree_icon {height: 28px;width: 26px;}
|
||||
.ztree li span.tree_icon .x-item-file{width: 24px;height: 24px;}
|
||||
.zip-view-dialog .zip-view-content .ztree li a .menu-item-parent{width:30px;height:30px;line-height: 30px;}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<div class="full-background"></div>
|
||||
<div class="init-loading"><div><img src="<?php echo STATIC_PATH;?>images/common/loading_simple.gif?v=<?php echo KOD_VERSION;?>"/></div></div>
|
||||
<div class="frame-main">
|
||||
<div class="bindary-box hidden">
|
||||
<div class="title"><div class="ico"></div></div>
|
||||
<div class="content-info">
|
||||
<div class="name"></div>
|
||||
<div class="size"><span></span><i class="share-time"></i></div>
|
||||
<div class="btn-group">
|
||||
<a type="button" class="btn btn-primary btn-download" href=""><?php echo LNG('download');?></a>
|
||||
</div>
|
||||
<div class="error-tips"><?php echo LNG('share_error_show_tips');?></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-box"></div>
|
||||
</div><!-- / frame-main end-->
|
||||
<script type="text/javascript" src="<?php echo STATIC_PATH;?>js/lib/seajs/sea.js?ver=<?php echo KOD_VERSION;?>"></script>
|
||||
<script type="text/javascript" src="./index.php?share/commonJs&st=api&act=view#id=<?php echo rand_string(4);?>"></script>
|
||||
|
||||
<?php
|
||||
$path = rawurldecode($_GET['path']);
|
||||
$name = get_path_this($path);
|
||||
if(isset($_GET['name'])){$name = rawurldecode($_GET['name']);}
|
||||
?>
|
||||
<script type="text/javascript">
|
||||
G.shareInfo = {
|
||||
path:"<?php echo clear_html($path);?>",
|
||||
name:"<?php echo clear_html($name);?>",
|
||||
mtime:0,size:0
|
||||
}
|
||||
<?php if(ST.'.'.ACT == 'explorer.fileView'){echo "G.shareInfo.view = true;G.sharePage=undefined;";}?>
|
||||
G['accessToken'] = "<?php echo access_token_get();?>";
|
||||
seajs.config({
|
||||
base: "<?php echo STATIC_PATH;?>js/",
|
||||
preload: ["lib/jquery-1.8.0.min",'lib/ace/src-min-noconflict/ace'],
|
||||
map:[[/^(.*\.(?:css|js|html|htm|json|text))([\?|#].*)$/i,'$1$2?ver='+G.version]]
|
||||
});
|
||||
seajs.use("<?php echo STATIC_JS;?>/src/api/view/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,33 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_setting.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/<?php echo $config['user']['theme'];?>.css?ver=<?php echo KOD_VERSION;?>" id='link-theme-style'/>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
<div id="body">
|
||||
<div class="app-menu-left menu-left">
|
||||
<h1><?php echo LNG('app');?></h1>
|
||||
<ul class='setting'>
|
||||
<a data-type="all"><i class="font-icon icon-reorder"></i><?php echo LNG('app_group_all');?></a>
|
||||
<?php foreach($config['settings']['appType'] as $item){?>
|
||||
<a data-type="<?php echo $item['type'];?>">
|
||||
<i class="font-icon <?php echo $item['class']?>"></i><?php echo LNG($item['name']);?></a>
|
||||
<?php } ?>
|
||||
</ul>
|
||||
</div>
|
||||
<div class='app-content main'>
|
||||
<div class="app-model">
|
||||
<?php if($GLOBALS['isRoot']){ ?><button class="btn btn-default create-app" action='createApp'><?php echo LNG('app_create');?></button><?php } ?>
|
||||
<div class='h1'><i class="font-icon icon-user"></i><?php echo LNG('app_group_all');?></div>
|
||||
<ul class="app-list"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include(TEMPLATE.'common/footerCommon.html');?>
|
||||
<script type="text/javascript">
|
||||
seajs.use('app/src/app/main');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,26 @@
|
||||
<div class="common-footer aero">
|
||||
<?php
|
||||
$settings = $GLOBALS['config']['settings'];
|
||||
$settingSystem = $GLOBALS['config']['settingSystem'];
|
||||
$copyrightInfo = LNG('copyright_info',APP_HOST);
|
||||
if(is_wap()){
|
||||
echo '<span class="pr-10"><a href="javascript:void(0);" forceWap="1">'.LNG('wap_page_phone').'</a> | '.
|
||||
'<a href="javascript:void(0);" forceWap="0">'.LNG('wap_page_pc').'</a></span> ';
|
||||
echo $copyrightInfo.' v'.KOD_VERSION;
|
||||
}else{
|
||||
echo '<span class="copyright-content">';
|
||||
if(isset($settings['copyright'])){
|
||||
echo $settings['copyright'];
|
||||
}else{
|
||||
echo LNG('copyright_pre').' v'.KOD_VERSION.' | '.$copyrightInfo;
|
||||
}
|
||||
echo '<a href="javascript:core.copyright();" class="icon-info-sign copyright-bottom pl-5"></a>';
|
||||
if(isset($settingSystem['globalIcp'])){
|
||||
echo " ".$settingSystem['globalIcp'];
|
||||
}
|
||||
echo '</span>';
|
||||
}
|
||||
?>
|
||||
</div>
|
||||
<!-- https://getfirebug.com/firebuglite -->
|
||||
<?php include(TEMPLATE.'common/footerCommon.html');?>
|
||||
@@ -0,0 +1,44 @@
|
||||
<script type="text/javascript" src="<?php echo STATIC_PATH;?>js/lib/seajs/sea.js?ver=<?php echo KOD_VERSION;?>"></script>
|
||||
<?php
|
||||
//commonjs
|
||||
if(ST == 'share' || isset($GLOBALS['loadCommonJs'])){
|
||||
if(isset($_GET['user'])){
|
||||
$userInfo = '&user='.clear_html($_GET['user']).'&sid='.clear_html($_GET['sid']);
|
||||
}else{//login...
|
||||
$userInfo = "";
|
||||
}
|
||||
echo '<script type="text/javascript" src="./index.php?share/commonJs&st='.ST.'&act='.ACT.$userInfo.'#id='.rand_string(4).'"></script>';
|
||||
}else{
|
||||
echo '<script type="text/javascript" src="./index.php?user/commonJs&st='.ST.'&act='.ACT.'#id='.rand_string(4).'"></script>';
|
||||
}
|
||||
|
||||
$settings = $GLOBALS['config']['settings'];
|
||||
$settingSystem = $GLOBALS['config']['settingSystem'];
|
||||
if(isset($settings['globalJs'])){
|
||||
echo "\n ".'<script type="text/javascript" id="settings-global-js">'.$settings['globalJs'].'</script>';
|
||||
}
|
||||
if(isset($settings['globalCss'])){
|
||||
echo "\n ".'<style type="text/css" id="settings-global-css">'.$settings['globalCss'].'</style>';
|
||||
}
|
||||
if(isset($settingSystem['globalCss'])){
|
||||
echo "\n ".'<style type="text/css" id="setting-system-global-css">'.$settingSystem['globalCss'].'</style>';
|
||||
}
|
||||
if(isset($settingSystem['globalHtml'])){
|
||||
echo "\n ".$settingSystem['globalHtml']."\n";
|
||||
}
|
||||
?>
|
||||
|
||||
<script type="text/javascript">
|
||||
<?php
|
||||
if(defined('INSTALL_CHANNEL')){
|
||||
echo "var installChannel='".INSTALL_CHANNEL."';\n";
|
||||
}
|
||||
?>
|
||||
seajs.config({
|
||||
base: "<?php echo STATIC_PATH;?>js/",
|
||||
preload: ["lib/jquery-1.8.0.min"],
|
||||
map:[[/^(.*\.(?:css|js|html|htm|json|text))([\?|#].*)$/i,'$1$2?ver='+G.version]]
|
||||
});
|
||||
if(navigator.serviceWorker){navigator.serviceWorker.register('./?share/manifestJS');}
|
||||
</script>
|
||||
<?php Hook::trigger('templateCommonFooter');?>
|
||||
@@ -0,0 +1,39 @@
|
||||
<?php Hook::trigger('templateCommonHeaderStart'); ?>
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<meta http-equiv="Content-Script-Type" content="text/javascript">
|
||||
<meta http-equiv="Cache-Control" content="no-transform">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
|
||||
<meta name="renderer" content="webkit">
|
||||
<meta name="description" itemprop="description" content="<?php echo LNG('kod_meta_description');?>">
|
||||
<meta name="keywords" content="<?php echo LNG('kod_meta_keywords');?>" />
|
||||
<meta name="generator" content="<?php echo LNG('kod_meta_name').' '.KOD_VERSION;?>"/>
|
||||
<meta name="author" content="<?php echo LNG('kod_meta_name');?>" />
|
||||
<meta name="copyright" content="<?php echo LNG('kod_meta_copyright');?>" />
|
||||
<meta itemprop="image" content="<?php echo STATIC_PATH;?>images/common/ico.png?ver=<?php echo KOD_VERSION;?>" />
|
||||
<link href="<?php echo STATIC_PATH;?>images/common/ico.png?ver=<?php echo KOD_VERSION;?>" rel="Shortcut Icon" type="image/x-icon">
|
||||
<link href="<?php echo STATIC_PATH;?>images/common/ico.png?ver=<?php echo KOD_VERSION;?>" rel="icon" type="image/x-icon">
|
||||
<link href="<?php echo STATIC_PATH;?>style/common.css?ver=<?php echo KOD_VERSION;?>" rel="stylesheet"/>
|
||||
<link href="./static/style/font-awesome/css/font-awesome.css?ver=<?php echo KOD_VERSION;?>" rel="stylesheet">
|
||||
<link href="./?share/manifest" rel="manifest" />
|
||||
<!--[if IE 7]>
|
||||
<link rel="stylesheet" href="./static/style/font-awesome/css/font-awesome-ie7.css">
|
||||
<![endif]-->
|
||||
<?php
|
||||
Hook::trigger('templateCommonHeader');
|
||||
function pageBackground(){
|
||||
$arr = explode(',',$GLOBALS['config']['settingSystem']['wallpageLogin']);
|
||||
$background = $arr[mt_rand(0,count($arr)-1)];
|
||||
if(!$background){
|
||||
$background = 'linear-gradient(160deg, #5648c1, #6fe3e7)';
|
||||
}else if(!strstr($background,'/')){
|
||||
$background = "url('./static/images/wall_page/{$background}.jpg')";
|
||||
}else{
|
||||
$background = "url('{$background}')";
|
||||
}
|
||||
return "<style type='text/css'>.aero:before,.aero:after,.background{background-color:#bbb;background-image:{$background};}</style>\n";
|
||||
}
|
||||
?>
|
||||
@@ -0,0 +1,118 @@
|
||||
<div class="full-background"></div>
|
||||
<div class="init-loading">
|
||||
<div><img src="<?php echo STATIC_PATH;?>images/common/loading_simple.gif?v=<?php echo KOD_VERSION;?>"/></div>
|
||||
</div>
|
||||
<div class="topbar aero">
|
||||
<div class="content">
|
||||
<button class="btn btn-wap-menu hidden"
|
||||
data-toggle="collapse" data-target="#top-menu-left"
|
||||
><i class="font-icon icon-reorder"></i></button>
|
||||
|
||||
<div class="top-left collapse" id="top-menu-left">
|
||||
<?php
|
||||
$config = $GLOBALS['config'];
|
||||
$html = '<a href="./" class="topbar-menu title">';
|
||||
$subMenu = '';
|
||||
$isWap = is_wap();
|
||||
if(substr(LNG('kod_name'),0,4) == '<img'){
|
||||
$html .= LNG('kod_name').'</a>';
|
||||
}else{
|
||||
$html .= '<i class="icon-cloud"></i>'.LNG('kod_name').'</a>';
|
||||
}
|
||||
foreach ($config['settingSystem']['menu'] as $key=>$value) {
|
||||
if ($value['use']!='1') continue;
|
||||
$has = ST==$value['name']?'this':'';
|
||||
$target = " target='_self'" ;
|
||||
if($value['target']=='1' || $value['target'] == '_blank'){
|
||||
$target = " target='_blank'" ;
|
||||
}
|
||||
$name = rawurldecode($value['name']);
|
||||
if(LNG('ui_'.$name) != 'ui_'.$name){
|
||||
$name = "<i class='font-icon menu-".$name."'></i><span>".LNG('ui_'.$name).'</span>';
|
||||
}else if($value['icon']){
|
||||
$name = $value['icon'].'<span>'.LNG($name).'</span>';
|
||||
}else if(!strstr($name,'<') && $value['subMenu']){
|
||||
$name = "<i class='font-icon words'><em>".$name."</em></i><span>".LNG($name).'</span>';
|
||||
}
|
||||
if($value['subMenu'] && !$isWap){
|
||||
$subMenu .= "<li><a class='topbar-menu-sub ".$has."' href='".urldecode($value['url'])."'"
|
||||
.$target.">".urldecode($name)."</a></li>";
|
||||
}else{
|
||||
$html .= "<a class='topbar-menu ".$has."' href='".urldecode($value['url'])."'"
|
||||
.$target.">".urldecode($name)."</a>";
|
||||
}
|
||||
}
|
||||
echo $html;
|
||||
?>
|
||||
|
||||
<?php if($subMenu){?>
|
||||
<div class="menu-group fl">
|
||||
<a class="topbar-menu" id="topbar-submenu"
|
||||
data-toggle="dropdown" href="#" title="<?php echo LNG('menu_sub_menu');?>">
|
||||
<i class="icon-th-large"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu topbar-submenu pull-left animated menuShow" role="menu" aria-labelledby="topbar-submenu">
|
||||
<?php echo $subMenu;?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<div class="top-right">
|
||||
<?php if(!isset($config['settings']['language'])){ ?>
|
||||
<div class="menu-group">
|
||||
<a id='topbar-language' data-toggle="dropdown" href="#" class="topbar-menu">
|
||||
<i class='font-icon icon-flag'></i> <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu topbar-language pull-right animated menuShow" role="menu" aria-labelledby="topbar-language">
|
||||
<?php
|
||||
$tpl = "";
|
||||
foreach ($config['settingAll']['language'] as $key => $value) {
|
||||
$name = $value[0];
|
||||
$select = I18n::getType() == $key ? "this":"";
|
||||
$tpl .= "<li><a href='javascript:core.language(\"{$key}\");' title=\"{$key}/{$value[1]}/{$value[2]}\" class='{$select}'><i class='lang-flag flag-{$key}'></i>{$name}</a></li>";
|
||||
}
|
||||
echo $tpl;
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<!-- 全局设置语言则不再显示 -->
|
||||
|
||||
<div class="menu-group">
|
||||
<a href="#" id='topbar-user' data-toggle="dropdown" class="topbar-menu">
|
||||
<i class="font-icon icon-user"></i>
|
||||
<?php
|
||||
$user = $_SESSION['kodUser'];
|
||||
$name = $user['nickName']?$user['nickName']:$user['name'];
|
||||
echo clear_html($name);
|
||||
?>
|
||||
<b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu menu-topbar-user pull-right animated menuShow" role="menu" aria-labelledby="topbar-user">
|
||||
<?php if($GLOBALS['isRoot']){ ?>
|
||||
<li class="menu-system-setting"><a href="#" onclick="core.setting('system');"><i class="font-icon icon-cog"></i><?php echo LNG('system_setting');?></a></li>
|
||||
<?php } ?>
|
||||
|
||||
<?php if($GLOBALS['isRoot'] || $GLOBALS['auth']['systemMember.get']){ ?>
|
||||
<li class="menu-system-group"><a href="#" onclick="core.setting('member');"><i class="font-icon icon-group"></i><?php echo LNG('setting_member');?></a></li>
|
||||
<?php } ?>
|
||||
<?php if($GLOBALS['isRoot'] || $GLOBALS['auth']['pluginApp.index']){ ?>
|
||||
<li class="menu-system-plugin">
|
||||
<a href="#" onclick="core.openWindowBig('./index.php?pluginApp/index','<?php echo LNG('PluginCenter');?>');"><i class="font-icon icon-puzzle-piece"></i><?php echo LNG('PluginCenter');?></a></li>
|
||||
<li role="presentation" class="divider"></li>
|
||||
<?php } ?>
|
||||
|
||||
|
||||
<li class="menu-system-user"><a href="#" onclick="core.setting('user');"><i class="font-icon icon-user"></i><?php echo LNG('setting_user');?></a></li>
|
||||
<li class="menu-system-theme"><a href="#" onclick="core.setting('theme');"><i class="font-icon icon-dashboard"></i><?php echo LNG('setting_theme');?></a></li>
|
||||
<li class="menu-system-full"><a href="#" onclick="core.fullScreen();"><i class="font-icon icon-fullscreen"></i><?php echo LNG('full_screen');?></a></li>
|
||||
<li class="menu-system-help"><a href="#" onclick="core.setting('help');"><i class="font-icon icon-question"></i><?php echo LNG('setting_help');?></a></li>
|
||||
<li class="menu-system-about"><a href="#" onclick="core.setting('about');"><i class="font-icon icon-info-sign"></i><?php echo LNG('setting_about');?></a></li>
|
||||
<li role="presentation" class="divider"></li>
|
||||
<li class="menu-system-logout"><a href="./index.php?user/logout"><i class="font-icon icon-signout"></i><?php echo LNG('ui_logout');?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,67 @@
|
||||
<div class="full-background"></div>
|
||||
<div class="init-loading"><div>
|
||||
<img src="<?php echo STATIC_PATH;?>images/common/loading_simple.gif?v=<?php echo KOD_VERSION;?>"/></div>
|
||||
</div>
|
||||
<div class="topbar share-page-topbar">
|
||||
<div class="content">
|
||||
<div class="top-left">
|
||||
<a href="./" class="topbar-menu title">
|
||||
<?php
|
||||
if(substr(LNG('kod_name'),0,4) == '<img'){
|
||||
echo LNG('kod_name');
|
||||
}else{
|
||||
echo '<i class="icon-cloud"></i>'.LNG('kod_name');
|
||||
}
|
||||
?>
|
||||
</a>
|
||||
<div class="share-info">
|
||||
<span class="share-title">
|
||||
<b class="share-title-info">
|
||||
<?php clear_html($shareInfo['showName']);?>
|
||||
</b>
|
||||
</span>
|
||||
<span class="size"></span>
|
||||
<span class="time"></span>
|
||||
</div>
|
||||
<div style="clear:both;"></div>
|
||||
</div>
|
||||
<div class="top-right">
|
||||
<div class="share-info-user hidden menu-group" style="z-index:9999;">
|
||||
<span class="info"></span>
|
||||
<div class="btn-group">
|
||||
<a type="button" class="btn btn-primary btn-download" target="_blank" href=""><?php echo LNG('download');?></a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if(!isset($config['settings']['language'])){ ?>
|
||||
<div class="menu-group">
|
||||
<a id='topbar-language' data-toggle="dropdown" href="#" class="topbar-menu">
|
||||
<i class='font-icon icon-flag'></i> <b class="caret"></b>
|
||||
</a>
|
||||
<a href="#" onclick="core.qrcode(window.location.href);" title="<?php echo LNG('qrcode');?>" class="topbar-menu" style="padding: 0 15px;margin-left: -2px;">
|
||||
<i class="font-icon icon-qrcode"></i>
|
||||
</a>
|
||||
<ul class="dropdown-menu topbar-language pull-right animated menuShow" role="menu" aria-labelledby="topbar-language">
|
||||
<?php
|
||||
$tpl = "";
|
||||
foreach ($config['settingAll']['language'] as $key => $value) {
|
||||
$name = $value[0];
|
||||
$select = I18n::getType() == $key ? "this":"";
|
||||
$tpl .= "<li><a href='javascript:core.language(\"{$key}\");' title=\"{$key}/{$value[1]}/{$value[2]}\" class='{$select}'><i class='lang-flag flag-{$key}'></i>{$name}</a></li>";
|
||||
}
|
||||
echo $tpl;
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php } ?>
|
||||
<div class="menu-group">
|
||||
<a href="#" id='topbar-user' class="topbar-menu" data-toggle="dropdown"><i class="font-icon icon-user"></i><?php echo $_SESSION['kodUser']['name'];?> <b class="caret"></b></a>
|
||||
<ul class="dropdown-menu menu-topbar-user pull-right animated menuShow" role="menu" aria-labelledby="topbar-user">
|
||||
<li><a href="#" onclick="core.fullScreen();"><i class="font-icon icon-fullscreen"></i><?php echo LNG('full_screen');?></a></li>
|
||||
<li class="version_vip_free"><a href="http://kodcloud.com" target="_blank"><i class="font-icon icon-code-fork"></i><?php echo LNG('ui_project_home');?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -0,0 +1,103 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
|
||||
<link href="<?php echo STATIC_PATH;?>style/common.css?ver=<?php echo KOD_VERSION;?>" rel="stylesheet"/>
|
||||
<link href="./static/style/font-awesome/css/font-awesome.css?ver=<?php echo KOD_VERSION;?>" rel="stylesheet">
|
||||
<title><?php echo $title;?></title>
|
||||
<script type="text/javascript" src="<?php echo STATIC_PATH;?>js/lib/jquery-1.8.0.min.js?ver=<?php echo KOD_VERSION;?>"></script>
|
||||
<style type="text/css">
|
||||
body{
|
||||
background-color:#f0f2f5;
|
||||
font-family: Verdana,"Lantinghei SC","Hiragino Sans GB","Microsoft Yahei",Helvetica,arial,sans-serif;
|
||||
line-height: 1.5em;
|
||||
}
|
||||
body a,body a:hover{color: #1890ff;}
|
||||
.body-panel{
|
||||
width:70%;margin:10% auto 5% auto;
|
||||
font-size: 13px;
|
||||
color:#666;
|
||||
background:#fff;border-radius:4px;
|
||||
padding-top:50px;padding-bottom:100px;
|
||||
box-shadow: 0 5px 20px rgba(0,0,0,0.05);
|
||||
}
|
||||
.body-panel .check-result{text-align: center;color:#000;}
|
||||
.body-panel .check-result .icon{width:70px;height:70px;line-height:70px;font-size:30px;}
|
||||
.check-result-title{font-size: 24px;line-height: 32px;margin:20px 0;}
|
||||
.check-result-desc{
|
||||
color: #333;
|
||||
margin: 0 0 20px 0;
|
||||
background: #fafafa;
|
||||
font-size: 16px;
|
||||
width: 80%;
|
||||
margin: 0 auto;
|
||||
border-radius: 2px;
|
||||
padding: 24px 40px;
|
||||
text-align: left;
|
||||
}
|
||||
.error-info{
|
||||
border-left: 5px solid #1890ff;
|
||||
display: block;
|
||||
padding: 5px 10px;
|
||||
background: #fcfcfc;
|
||||
color: #666;
|
||||
word-break: break-all;
|
||||
font-family: monospace;
|
||||
}
|
||||
.location-to{padding: 10px 0;color: #888;font-size: 13px;font-style: italic;}
|
||||
.icon{
|
||||
font-family: FontAwesome;
|
||||
display: inline-block;
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
background: rgba(0, 0, 0, 0.02);
|
||||
text-align: center;
|
||||
color: #666;
|
||||
border-radius: 50%;
|
||||
line-height: 20px;
|
||||
font-size: 12px;
|
||||
}
|
||||
.icon.icon-loading{
|
||||
-webkit-animation: moveCircleLoopRight 1.4s infinite linear;
|
||||
animation: moveCircleLoopRight 1.4s infinite linear;
|
||||
}
|
||||
.icon.icon-loading:before{content:"\f110";}
|
||||
.icon.icon-success{background:#52c41a;color:#fff;}
|
||||
.icon.icon-success:before{content:"\f00c";}
|
||||
.icon.icon-error{background:#f5222d;color:#fff;}
|
||||
.icon.icon-error:before{content:"\f00d";}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
|
||||
<body>
|
||||
<div class="body-panel">
|
||||
<div class="check-result">
|
||||
<!-- <div class="icon icon-error"></div> -->
|
||||
<div class="check-result-title"><?php echo $title;?></div>
|
||||
<div class="check-result-desc">
|
||||
<span class="error-info"><?php echo $message;?></span>
|
||||
<div class="location-to"><?php echo $info;?></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php if($url){ ?>
|
||||
<script>
|
||||
var timeout = parseInt("<?php echo $time;?>");
|
||||
var link = "<?php echo $url;?>";
|
||||
var loop = setInterval(function(){
|
||||
timeout --;
|
||||
var info = timeout + "s 后自动跳转, <a href='"+link+"'>立即跳转</a>";
|
||||
$('.location-to').html(info);
|
||||
if(timeout<=0){
|
||||
clearInterval(loop);
|
||||
window.location.href = link;
|
||||
}
|
||||
},1000);
|
||||
</script>
|
||||
<?php } ?>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo LNG('ui_desktop').' - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_desktop.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/<?php echo $config['user']['theme'];?>.css?ver=<?php echo KOD_VERSION;?>" id='link-theme-style'/>
|
||||
|
||||
</head>
|
||||
<body style="overflow: hidden;" oncontextmenu="return core.contextmenu();" id="page-desktop">
|
||||
<?php echo '<style >.aero:before,.aero:after,.full-background-wall{background-image:url('.$wall.')}</style>';?>
|
||||
<div class="full-background-wall desktop"><img class="background" /></div>
|
||||
|
||||
<?php include(TEMPLATE.'common/navbar.html');?>
|
||||
<div class='bodymain drag-upload-box desktop'>
|
||||
<div class="file-continer file-list-icon hidden"></div>
|
||||
</div><!-- html5拖拽上传list -->
|
||||
|
||||
<a href="#" class="start"></a>
|
||||
<div id="taskbar" style="display:block;" class="">
|
||||
<div class="taskbar-background aero"></div>
|
||||
<div id="desktop"></div>
|
||||
</div>
|
||||
<div class="taskbar-right">
|
||||
<div class="copyright dropdown-toggle"><i class="icon-info-sign"></i></div>
|
||||
<div class="tab-hide-all"></div>
|
||||
</div>
|
||||
<div id="menuwin" class="aero">
|
||||
<div id="startmenu"></div>
|
||||
<ul id="programs">
|
||||
<li class='setting_help'><a href="#" onclick="core.setting('help');"><?php echo LNG('setting_help');?></a></li>
|
||||
<li><div id="leftspliter"></div></li>
|
||||
<li class='setting_about'><a href="#" onclick="core.setting('about');"><?php echo LNG('setting_about');?></a></li>
|
||||
<li class='setting_user'><a href="#" onclick="core.setting('user');"><?php echo LNG('setting_user');?></a></li>
|
||||
<li class='setting_homepage'><a href="#" onclick="core.openWindow('http://kodcloud.com','<?php echo $L['my_document'];?>');">kodCloud 主页</a></li>
|
||||
</ul>
|
||||
<ul id="links">
|
||||
<li class="icon"></li>
|
||||
<li><a href="#" onclick="core.explorer('<?php echo KOD_USER_SHARE.':'.$_SESSION['kodUser']['userID'].'/';?>','<?php echo LNG('my_share');?>');"><span><?php echo LNG('my_share');?></span></a></li>
|
||||
<li><a href="#" onclick="core.explorer('<?php echo MYHOME;?>/pictures','<?php echo LNG('my_picture');?>');"><span><?php echo LNG('my_picture');?></span></a></li>
|
||||
<li><a href="#" onclick="core.explorer('<?php echo MYHOME;?>/music','<?php echo LNG('my_music');?>');"><span><?php echo LNG('my_music');?></span></a></li>
|
||||
<li><a href="#" onclick="core.explorer('<?php echo MYHOME;?>/download','<?php echo LNG('download');?>');"><span><?php echo LNG('download');?></span></a></li>
|
||||
<li><div id="rightspliter"></div></li>
|
||||
<li><a href="#" onclick="core.setting('wall');"><span><?php echo LNG('setting_wall');?></span></a></li>
|
||||
<li><a href="#" onclick="core.setting('fav');"><span><?php echo LNG('setting_fav');?></span></a></li>
|
||||
<li><a href="#" onclick="core.setting('theme');"><span><?php echo LNG('setting_theme');?></span></a></li>
|
||||
<li><a href="./index.php?user/logout" style="margin-top:70px;"><span><?php echo LNG('ui_logout');?>></span></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<?php include(TEMPLATE.'common/footerCommon.html');?>
|
||||
<script type="text/javascript">
|
||||
var desktopApps = <?php echo json_encode($desktopApps);?>;
|
||||
G.thisPath = G.myDesktop;
|
||||
seajs.use("app/src/desktop/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_code_edit.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/<?php echo $config['user']['theme'];?>.css?ver=<?php echo KOD_VERSION;?>" id='link-theme-style'/>
|
||||
|
||||
</head>
|
||||
<body <?php echo $codeThemeBlack;?>>
|
||||
<div class="init-loading">
|
||||
<div><img src="<?php echo STATIC_PATH;?>images/common/loading_simple.gif?v=<?php echo KOD_VERSION;?>"/></div>
|
||||
</div>
|
||||
<div class="edit-main" style="height: 100%;" oncontextmenu="return core.contextmenu();">
|
||||
<div class="tools">
|
||||
<div class="left top-toolbar">
|
||||
<div class="disable-mask"></div>
|
||||
<a action="save" href="javascript:;" title="<?php echo LNG('button_save');?>(Ctrl-S)"><i class="font-icon icon-save"></i></a>
|
||||
<a action="saveall" href="javascript:;" title="<?php echo LNG('button_save_all');?>"><i class="font-icon icon-paste"></i></a>
|
||||
<span class="line"></span>
|
||||
<a href="javascript:;" id="editor-history-back" title="<?php echo LNG('history_back');?>(Ctrl -)"><i class="font-icon icon-chevron-left"></i></a>
|
||||
<a href="javascript:;" id="editor-history-next" title="<?php echo LNG('history_next');?>(Ctrl Shift -)"><i class="font-icon icon-chevron-right"></i></a>
|
||||
<span class="line"></span>
|
||||
<a action="undo" href="javascript:;" title="<?php echo LNG('undo');?>(Ctrl-Z)"><i class="font-icon icon-undo"></i></a>
|
||||
<a action="redo" href="javascript:;" title="<?php echo LNG('redo');?>(Ctrl-Y)"><i class="font-icon icon-repeat"></i></a>
|
||||
<a action="refresh" href="javascript:;" title="<?php echo LNG('refresh');?>(F5)"><i class="font-icon icon-refresh"></i></a>
|
||||
<span class="line"></span>
|
||||
<a href="javascript:;" class="toolbar-menu menu-view-goto-line" title="<?php echo LNG('gotoline');?>(Ctrl-L)"><i class="font-icon icon-pushpin"></i></a>
|
||||
<a action="search" href="javascript:;" title="<?php echo LNG('search');?>(Ctrl-F)"><i class="font-icon icon-search"></i></a>
|
||||
<a action="searchReplace" href="javascript:;" title="<?php echo LNG('replace');?>(Ctrl-F-F)"><i class="font-icon icon-random"></i></a>
|
||||
<span class="line"></span>
|
||||
<a action="font" class="toolbar-menu menu-view-font" href="javascript:;" title="<?php echo LNG('font_size');?>">
|
||||
<i class="font-icon icon-font"></i><i class="font-icon icon-caret-down"></i>
|
||||
</a>
|
||||
<span class="line"></span>
|
||||
<a class="toolbar-menu menu-view-theme" href="javascript:;" title="<?php echo LNG('code_theme');?>">
|
||||
<i class="font-icon icon-magic"></i><i class="font-icon icon-caret-down"></i>
|
||||
</a>
|
||||
<a class="toolbar-menu menu-view-setting" href="javascript:;">
|
||||
<i class="font-icon icon-cog"></i><i class="font-icon icon-caret-down"></i>
|
||||
</a>
|
||||
<a action="preview" href="javascript:;" title="<?php echo LNG('preview');?>(Ctrl-Shift-S)"><i class="font-icon icon-eye-open"></i></a>
|
||||
</div>
|
||||
<div class="right">
|
||||
|
||||
<button class="btn btn-xs btn-default btn-right" action="close" title="<?php echo LNG('close');?>"><i class="font-icon icon-remove"></i></button>
|
||||
<button class="btn btn-xs btn-default btn-left" action="fullscreen" title="<?php echo LNG('full_screen');?>"><i class="font-icon icon-resize-full"></i></button>
|
||||
</div>
|
||||
<div style="clear:both"></div>
|
||||
</div><!-- end tools -->
|
||||
|
||||
<!-- 主体部分 -->
|
||||
<div class="frame-left">
|
||||
<div class="edit-tab">
|
||||
<div class="tabs">
|
||||
<a href="javascript:Editor.add()" class="add icon-plus"></a>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="edit-body">
|
||||
<div class="introduction hidden">
|
||||
<button class="btn btn-default font-icon icon-remove close-item"></button>
|
||||
<?php include(LANGUAGE_PATH.I18n::getType().'/edit.html');?>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
<div class="tabs"></div>
|
||||
<div class="bottom-toolbar hidden">
|
||||
<a class="toolbar-menu menu-view-goto-line editor_position" href="javascript:;">0:0</a>
|
||||
<a class="file-mode" href="javascript:;">text</a>
|
||||
<a class="toolbar-menu menu-view-file-charset " href="javascript:;">UTF-8</a>
|
||||
<a class="toolbar-menu menuViewTab config-tab" href="javascript:;">Tabs:4</a>
|
||||
<a class="toolbar-menu menu-view-setting config" href="javascript:;"><i class="font-icon icon-cog"></i></a>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-content hidden"></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include(TEMPLATE.'common/footerCommon.html');?>
|
||||
<script type="text/javascript">
|
||||
G.codeConfig = <?php echo $editorConfig;?>;
|
||||
G.codeThemeAll = "<?php echo $config['settingAll']['codethemeall']?>";
|
||||
G.codeFontAll = "<?php echo $config['settingAll']['codefontall']?>";
|
||||
seajs.config({
|
||||
preload: [
|
||||
"lib/jquery-1.8.0.min",
|
||||
'lib/ace/src-min-noconflict/ace'
|
||||
]
|
||||
});
|
||||
seajs.use("app/src/edit/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo LNG('ui_editor').' - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_editor.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/<?php echo $config['user']['theme'];?>.css?ver=<?php echo KOD_VERSION;?>" id='link-theme-style'/>
|
||||
|
||||
</head>
|
||||
|
||||
<?php if(isset($_GET['project'])){?>
|
||||
<style>.topbar{display: none;}.frame-header{top:0;}.frame-main{top:0px;}</style>
|
||||
<?php } ?>
|
||||
|
||||
<body style="overflow:hidden;" oncontextmenu="return core.contextmenu();" id="page-editor">
|
||||
<?php include(TEMPLATE.'common/navbar.html');?>
|
||||
<div class="frame-main">
|
||||
<div class="tools-left">
|
||||
<a class="home" href="#" title='<?php echo LNG('root_path');?>'><i class="icon-home"></i></a>
|
||||
<a class="view" href="#" title='<?php echo LNG('manage_folder');?>'><i class="icon-laptop"></i></a>
|
||||
<a class="folder" href="#" title='<?php echo LNG('newfolder');?>'><i class="icon-folder-close-alt"></i></a>
|
||||
<a class="file" href="#" title='<?php echo LNG('newfile');?>'><i class="icon-file-alt"></i></a>
|
||||
<a class="refresh" href="#" title='<?php echo LNG('refresh');?>'><i class="icon-refresh"></i></a>
|
||||
</div>
|
||||
<div class='frame-left'>
|
||||
<ul id="folder-list-tree" class="ztree"></ul>
|
||||
</div><!-- / frame-left end-->
|
||||
<div class='frame-resize'></div>
|
||||
<div class='frame-right'>
|
||||
<div class="frame-right-main" style="height:100%;padding:0;margin:0;">
|
||||
<div class="resize-mask"></div>
|
||||
<div class="message-box"><div class="content"></div></div>
|
||||
<div class="menu-tree-root"></div>
|
||||
<div class="menu-tree-folder"></div>
|
||||
<div class="menu-tree-file"></div>
|
||||
<div class ='frame'>
|
||||
<iframe name="OpenopenEditor" src="./index.php?editor/edit" style="width:100%;height:100%;border:0;" frameborder=0></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- / frame-right end-->
|
||||
</div><!-- / frame-main end-->
|
||||
<?php include(TEMPLATE.'common/footerCommon.html');?>
|
||||
<script type="text/javascript">
|
||||
G.project = "<?php echo clear_html($_GET['project']) ;?>";
|
||||
seajs.use("app/src/editor/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,234 @@
|
||||
<div class="frame-main">
|
||||
<div class='frame-left'>
|
||||
<ul id="folder-list-tree" class="ztree"></ul>
|
||||
<div class="bottom-box">
|
||||
<div class="user-space-info"></div>
|
||||
<div class="box-content">
|
||||
<div class="cell menu-recycle-button"><i class="font-icon icon-trash"></i><span><?php echo LNG('recycle');?></span></div>
|
||||
<div class="cell menuShareButton"><i class="font-icon icon-share-sign"></i><span><?php echo LNG('my_share');?></span></div>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- / frame-left end-->
|
||||
|
||||
<div class='frame-resize'></div>
|
||||
<div class='frame-right'>
|
||||
<div class="frame-header">
|
||||
<div class="header-content">
|
||||
<div class="header-left">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button class="btn btn-default" id='btn-history-back' title='<?php echo LNG('history_back');?>' type="button">
|
||||
<i class="font-icon icon-angle-left"></i>
|
||||
</button>
|
||||
<button class="btn btn-default" id='btn-history-next' title='<?php echo LNG('history_next');?>' type="button">
|
||||
<i class="font-icon icon-angle-right"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div><!-- /header left -->
|
||||
|
||||
<div class='header-middle'>
|
||||
<button class="btn btn-default btn-left-radius ml-10" id='home' title='<?php echo LNG('root_path');?>'>
|
||||
<i class="font-icon icon-home"></i>
|
||||
</button>
|
||||
<div id='yarnball' title="<?php echo LNG('address_in_edit');?>"></div>
|
||||
<div id='yarnball-input'><input type="text" name="path" value="" class="path" id="path"/></div>
|
||||
|
||||
<button class="btn btn-default" id='fav' title='<?php echo LNG('add_to_fav');?>' type="button">
|
||||
<i class="font-icon icon-star"></i>
|
||||
</button>
|
||||
<!-- <button class="btn btn-default" id='refresh' title='<?php echo LNG('refresh_all');?>' type="button">
|
||||
<i class="font-icon icon-refresh"></i>
|
||||
</button> -->
|
||||
<button class="btn btn-default btn-right-radius" id='goto-father' title='<?php echo LNG('go_up');?>' type="button">
|
||||
<i class="font-icon icon-circle-arrow-up"></i>
|
||||
</button>
|
||||
<div class="path-tips" title="<?php echo LNG('only_read_desc');?>" title-timeout="0">
|
||||
<i class="icon-warning-sign"></i><span></span>
|
||||
</div>
|
||||
|
||||
<div class="role-label-box"></div>
|
||||
</div><!-- /header-middle end-->
|
||||
<div class='header-right'>
|
||||
<input type="text" name="seach" class="btn-left-radius"/>
|
||||
<button class="btn btn-default btn-right-radius" id='search' title='<?php echo LNG('search');?>' type="button">
|
||||
<i class="font-icon icon-search"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- / header end -->
|
||||
<div class="frame-right-main">
|
||||
<div class="tools">
|
||||
<div class="tools-left tools-left-share <?php if(ST!='share'){echo 'hidden';}?>">
|
||||
<!-- 文件功能 -->
|
||||
<div class="kod-toolbar kod-toolbar-path btn-group btn-group-sm">
|
||||
<button data-action='select-all' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-check"></i><?php echo LNG('selectAll');?>
|
||||
</button>
|
||||
<button data-action='upload' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-cloud-upload"></i><?php echo LNG('upload');?>
|
||||
</button>
|
||||
|
||||
<button data-action='download' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-download"></i><?php echo LNG('download');?>
|
||||
</button>
|
||||
</div>
|
||||
<span class='msg'><?php echo LNG('path_loading');?></span>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="tools-left tools-left-explorer <?php if(ST=='share'){echo 'hidden';}?>">
|
||||
<!-- 回收站tool -->
|
||||
<div class="kod-toolbar kod-toolbar-recycle btn-group btn-group-sm hidden fl-left">
|
||||
<button data-action='recycle-clear' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-folder-close-alt"></i><?php echo LNG('recycle_clear');?>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<!-- 分享 tool -->
|
||||
<div class="kod-toolbar kod-toolbar-share hidden fl-left">
|
||||
<button data-action='refresh' class="btn btn-sm btn-default fl-left" type="button">
|
||||
<i class="font-icon icon-refresh"></i><?php echo LNG('refresh');?>
|
||||
</button>
|
||||
<div class="select-button-show-share btn-group btn-group-sm fl-left ml-10 mr-10 hidden">
|
||||
<button data-action='remove' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-remove"></i><?php echo LNG('share_remove');?>
|
||||
</button>
|
||||
<button data-action='shareEdit' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-edit"></i><?php echo LNG('share_edit');?>
|
||||
</button>
|
||||
<button data-action='shareOpenWindow' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-link"></i><?php echo LNG('share_open_page');?>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 文件功能 -->
|
||||
<div class="kod-toolbar kod-toolbar-path fl-left">
|
||||
<div class="select-button-default btn-group btn-group-sm fl-left mr-10">
|
||||
<button data-action='newfolder' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-folder-close-alt"></i><?php echo LNG('newfolder');?>
|
||||
</button>
|
||||
<button data-action='newfile' class="btn btn-default tool-path-newfile" type="button">
|
||||
<i class="font-icon icon-caret-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="select-button-default btn-group btn-group-sm fl-left mr-10">
|
||||
<button data-action='upload' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-cloud-upload"></i><?php echo LNG('upload');?>
|
||||
</button>
|
||||
<button data-action='upload-more' class="btn btn-default tool-path-upload" type="button">
|
||||
<i class="font-icon icon-caret-down"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="select-button-show btn-group btn-group-sm fl-left ml-10 mr-10 hidden">
|
||||
<button data-action='share' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-share"></i><?php echo LNG('share');?>
|
||||
</button>
|
||||
<button data-action='download' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-download"></i><?php echo LNG('download');?>
|
||||
</button>
|
||||
<button data-action='remove' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-remove"></i><?php echo LNG('remove');?>
|
||||
</button>
|
||||
<button data-action='rname' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-rename"></i><?php echo LNG('rename');?>
|
||||
</button>
|
||||
|
||||
<button data-action='copy' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-copy"></i><?php echo LNG('copy');?>
|
||||
</button>
|
||||
<button data-action='cute' class="btn btn-default" type="button">
|
||||
<i class="font-icon icon-cute"></i><?php echo LNG('cute');?>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm toolbar-path-more fl-left mr-10">
|
||||
<i class="font-icon icon-ellipsis-horizontal"></i>
|
||||
<?php echo LNG('button_more');?> <span class="caret"></span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="group-space-use fl-left hidden"></div>
|
||||
<div class="admin-real-path hidden fl-left">
|
||||
<button type="button" class="btn btn-default btn-sm dialog-goto-path ml-10" title="<?php echo LNG('open_the_path');?>">
|
||||
<i class="font-icon icon-folder-open"></i>
|
||||
</button>
|
||||
</div>
|
||||
<span class='msg fl-left'><?php echo LNG('path_loading');?></span>
|
||||
<div class="clear"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tools-right">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button data-action='set-icon' title="<?php echo LNG('list_icon');?>" type="button" class="btn btn-default">
|
||||
<i class="font-icon icon-th"></i>
|
||||
</button>
|
||||
<button data-action='set-list' title="<?php echo LNG('list_list');?>" type="button" class="btn btn-default">
|
||||
<i class="font-icon icon-list"></i>
|
||||
</button>
|
||||
<button data-action='set-split' title="<?php echo LNG('list_list_split');?>" type="button" class="btn btn-default">
|
||||
<i class="font-icon icon-columns"></i>
|
||||
</button>
|
||||
|
||||
<div class="btn-group btn-group-sm menu-theme-list">
|
||||
<button data-action="set-theme" title="<?php echo LNG('setting_theme');?>" type="button" class="btn btn-default btn-sm dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="font-icon icon-dashboard"></i> <span class="caret"></span>
|
||||
</button>
|
||||
<ul class="dropdown-menu pull-right dropdown-menu-theme animated menuShow">
|
||||
<?php
|
||||
$arr = explode(',',$config['settingAll']['themeall']);
|
||||
foreach ($arr as $value) {
|
||||
echo "<li class='list' theme='{$value}'><a href='javascript:void(0);'>".LNG('theme_'.$value)."</a></li>\n";
|
||||
}
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="set-icon-size">
|
||||
<span class="dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="font-icon icon-zoom-in"></i>
|
||||
</span>
|
||||
<ul class="dropdown-menu set-icon-size-slider animated menuShow">
|
||||
<div class="slider-bg"></div>
|
||||
<div class="slider-handle"></div>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div style="clear:both"></div>
|
||||
</div><!-- end tools -->
|
||||
<div id='list-type-header' class="hidden">
|
||||
<div id="main-title">
|
||||
<div class="filename" field="name"><?php echo LNG('name');?><span></span></div><div class="resize filename-resize"></div>
|
||||
<div class="filetype" field="ext"><?php echo LNG('type');?><span></span></div><div class="resize filetype-resize"></div>
|
||||
<div class="filesize" field="size"><?php echo LNG('size');?><span></span></div><div class="resize filesize-resize"></div>
|
||||
<div class="filetime" field="mtime"><?php echo LNG('modify_time');?><span></span></div><div class="resize filetime-resize"></div>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- list type 列表排序方式 -->
|
||||
|
||||
<div class='bodymain drag-upload-box menu-body-main'>
|
||||
<div class="line-split-box hidden">
|
||||
<div class="split-line"></div>
|
||||
<div class="split-line"></div>
|
||||
<div class="split-line"></div>
|
||||
<div class="split-line"></div>
|
||||
<div class="split-line"></div>
|
||||
<div class="split-line"></div>
|
||||
<div class="split-line"></div>
|
||||
<div class="split-line"></div>
|
||||
<div class="split-line"></div>
|
||||
<div class="split-line"></div>
|
||||
</div>
|
||||
<div class="file-continer"></div>
|
||||
<div class="file-continer-more"></div>
|
||||
</div><!-- html5拖拽上传list -->
|
||||
<div class="file-select-info">
|
||||
<span class="item-num"></span>
|
||||
<span class="item-select"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- / frame-right end-->
|
||||
</div><!-- / frame-main end-->
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo LNG('ui_explorer').' - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link href="<?php echo STATIC_PATH;?>style/wap/app_explorer.css?ver=<?php echo KOD_VERSION;?>" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="init-loading"><div><img src="<?php echo STATIC_PATH;?>images/common/loading_simple.gif?v=<?php echo KOD_VERSION;?>"/></div></div>
|
||||
<div class="panel-menu">
|
||||
<div class="panel-hd">
|
||||
<span class="my-avator">
|
||||
<?php
|
||||
$avatar = STATIC_PATH.'images/common/pic.jpg';
|
||||
$name = $_SESSION['kodUser']['name'];
|
||||
if($_SESSION['kodUser']['avatar']){
|
||||
$avatar = $_SESSION['kodUser']['avatar'];
|
||||
}
|
||||
if($_SESSION['kodUser']['nickName']){
|
||||
$name = $_SESSION['kodUser']['nickName'];
|
||||
}
|
||||
echo '<img src="'.$avatar.'"/>';
|
||||
?>
|
||||
</span>
|
||||
<div><h3 class="name"><?php echo clear_html($name);?></h3></div>
|
||||
</div>
|
||||
<ul class="left-menu-path"></ul>
|
||||
</div>
|
||||
<div class="frame-main">
|
||||
<div class="panel-mask"></div>
|
||||
<div class="frame-header">
|
||||
<div class="tool tool-menu-left">
|
||||
<div class="menu"><i class="font-icon icon-reorder"></i></div>
|
||||
</div>
|
||||
|
||||
<?php
|
||||
$config = $GLOBALS['config'];
|
||||
$subMenu = '';
|
||||
foreach ($config['settingSystem']['menu'] as $key=>$value) {
|
||||
if ($value['use']!='1') continue;
|
||||
$has = ST==$value['name']?'this':'';
|
||||
$target = " target='_self'" ;
|
||||
if($value['target']=='1' || $value['target'] == '_blank'){
|
||||
$target = " target='_blank'" ;
|
||||
}
|
||||
$name = $value['name'];
|
||||
if(LNG('ui_'.$name) != 'ui_'.$name){
|
||||
$name = "<i class='font-icon menu-".$value['name']."'></i><span>".LNG('ui_'.$name).'</span>';
|
||||
}
|
||||
if($value['icon']){
|
||||
$name = $value['icon'].'<span>'.LNG($value['name']).'</span>';
|
||||
}
|
||||
$subMenu .= "<li><a class='topbar-menu-sub ".$has."' href='".urldecode($value['url'])."'"
|
||||
.$target.">".urldecode($name)."</a></li>";
|
||||
}
|
||||
?>
|
||||
<?php if($subMenu){?>
|
||||
<div class="menu-group fl tool tool-submenu">
|
||||
<button class="topbar-menu" id="topbar-submenu" data-toggle="dropdown">
|
||||
<i class="icon-home"></i>
|
||||
</button>
|
||||
<ul class="dropdown-menu topbar-submenu pull-left animated menuShow" role="menu" aria-labelledby="topbar-submenu">
|
||||
<?php echo $subMenu;?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php } ?>
|
||||
|
||||
<div class="title"><?php echo LNG('kod_name');?></div>
|
||||
<div class="menu-group">
|
||||
<div class="btn-list-icon"><i class="font-icon icon-home"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="address">
|
||||
<ul class="yarnball"></ul>
|
||||
<div style="clear: both"></div>
|
||||
</div>
|
||||
<div class='bodymain'>
|
||||
<div class="file-continer file-list-list"></div>
|
||||
</div>
|
||||
|
||||
<div class="file-menu">
|
||||
<div class="file-action-menu hidden">
|
||||
<div class="action-menu" data-action="action-copy">
|
||||
<span class="content">
|
||||
<i class="font-icon icon-copy"></i><?php echo LNG('copy');?>
|
||||
</span>
|
||||
</div>
|
||||
<div class="action-menu" data-action="action-cute">
|
||||
<span class="content">
|
||||
<i class="font-icon icon-cut"></i><?php echo LNG('cute');?>
|
||||
</span>
|
||||
</div>
|
||||
<div class='action-menu' data-action="action-share">
|
||||
<span class="content">
|
||||
<i class="font-icon icon-share"></i><?php echo LNG('share');?>
|
||||
</span>
|
||||
</div>
|
||||
<div class='action-menu' data-action="action-rname">
|
||||
<span class="content">
|
||||
<i class="font-icon icon-pencil"></i><?php echo LNG('rename');?>
|
||||
</span>
|
||||
</div>
|
||||
<div class='action-menu' data-action="action-download">
|
||||
<span class="content">
|
||||
<i class="font-icon icon-cloud-download"></i><?php echo LNG('download');?>
|
||||
</span>
|
||||
</div>
|
||||
<div class='action-menu' data-action="action-info">
|
||||
<span class="content">
|
||||
<i class="font-icon icon-info"></i><?php echo LNG('info');?>
|
||||
</span>
|
||||
</div>
|
||||
<div class="action-menu" data-action="action-remove">
|
||||
<span class="content">
|
||||
<i class="font-icon icon-trash"></i><?php echo LNG('remove');?>
|
||||
</span>
|
||||
</div>
|
||||
<div class="menu-close">
|
||||
<span class="content">
|
||||
<i class="font-icon icon-ellipsis-horizontal"></i>
|
||||
</span>
|
||||
</div>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include(TEMPLATE.'common/footer.html');?>
|
||||
</div><!-- / frame-main end-->
|
||||
|
||||
<div class="toolbar-menu">
|
||||
<button class="menu-plus tool tool-menu-right-btn" data-toggle="dropdown"></button>
|
||||
<ul class="dropdown-menu tool-menu-right pull-right animated menuShow" role="menu" >
|
||||
<li data-action="upload"><a href="javascript:void();">
|
||||
<i class="font-icon icon-cloud-upload"></i><?php echo LNG('upload');?></a></li>
|
||||
<li data-action="newfolder"><a href="javascript:void();">
|
||||
<i class="font-icon icon-folder-close-alt"></i><?php echo LNG('newfolder');?></a></li>
|
||||
<li data-action="newfile"><a href="javascript:void();">
|
||||
<i class="font-icon icon-file-text"></i><?php echo LNG('newfile');?></a></li>
|
||||
<li data-action="past"><a href="javascript:void();">
|
||||
<i class="font-icon icon-paste"></i><?php echo LNG('past');?></a></li>
|
||||
<li data-action="search"><a href="javascript:void();">
|
||||
<i class="font-icon icon-search"></i><?php echo LNG('search');?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<script type="text/javascript" >
|
||||
G.thisPath = "<?php echo clear_html($dir);?>";
|
||||
seajs.use("<?php echo STATIC_JS;?>/src/explorerWap/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,47 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo LNG('ui_explorer').' - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_explorer.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/<?php echo $config['user']['theme'];?>.css?ver=<?php echo KOD_VERSION;?>" id='link-theme-style'/>
|
||||
|
||||
</head>
|
||||
|
||||
<style>
|
||||
<?php if(isset($_GET['type'])){?>
|
||||
.topbar,.common-footer,.bottom-box{display:none;}
|
||||
.frame-header{top:0;}
|
||||
.frame-main{top:0px;bottom:0px;}
|
||||
.frame-main .frame-left #folder-list-tree{bottom:0px !important;}
|
||||
<?php if($_GET['type']=="explorer"){?>
|
||||
.frame-header .header-content .header-left{display:none;}
|
||||
.frame-header .header-content .header-middle{left:12px;}
|
||||
.frame-main .frame-left,.frame-main .frame-resize{display:none;}
|
||||
.frame-main .frame-right{left:0px;}
|
||||
.task-tab{display:none;}
|
||||
<?php } ?>
|
||||
|
||||
<?php if($_GET['type']=="fileList"){?>
|
||||
.frame-header{display:none;}
|
||||
.frame-main .frame-left,.frame-main .frame-resize{display:none;}
|
||||
.frame-main .frame-right{left:0px;}
|
||||
.frame-main{top:0px;}
|
||||
.task-tab,#set_theme,#fav,#home{display:none !important;}
|
||||
.header-middle{top:3px;left:5px;right:140px;}
|
||||
#list-type-header{top:35px;}
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
</style>
|
||||
|
||||
|
||||
<body style="overflow:hidden;" oncontextmenu="return core.contextmenu();" id="page-explorer">
|
||||
<?php include(TEMPLATE.'common/navbar.html');?>
|
||||
<?php include(TEMPLATE.'explorer/content.html');?>
|
||||
<?php include(TEMPLATE.'common/footer.html');?>
|
||||
<script type="text/javascript">
|
||||
G.thisPath = "<?php echo clear_html($dir);?>";
|
||||
seajs.use("app/src/explorer/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo LNG('PluginCenter').' - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_setting.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/<?php echo $config['user']['theme'];?>.css?ver=<?php echo KOD_VERSION;?>" id='link-theme-style'/>
|
||||
|
||||
</head>
|
||||
<body oncontextmenu="return core.contextmenu();">
|
||||
<div id="body" class="plugin-page">
|
||||
<div class="app-menu-left menu-left">
|
||||
<div class="search">
|
||||
<div class="search-btn btn-search font-icon icon-search"></div>
|
||||
<div class="search-btn btn-close font-icon icon-remove hidden"></div>
|
||||
<input type="text" placeholder="<?php echo LNG('search');?>" />
|
||||
</div>
|
||||
<ul class='setting'>
|
||||
<a data-type="install"><i class="font-icon icon-download-alt"></i><?php echo LNG('PluginInstalled');?></a>
|
||||
<a data-type="update"><i class="font-icon icon-refresh"></i><?php echo LNG('PluginUpdate');?></a>
|
||||
</ul>
|
||||
|
||||
<div class="line"><?php echo LNG("PluginType");?></div>
|
||||
<ul class='setting'>
|
||||
<a data-type="all"><i class="font-icon icon-reorder"></i><?php echo LNG("PluginTypeAll");?></a>
|
||||
<a data-type="file"><i class="font-icon icon-folder-open-alt"></i><?php echo LNG("PluginTypeFile");?></la>
|
||||
<a data-type="safe"><i class="font-icon icon-book"></i><?php echo LNG("PluginTypeSafe");?></a>
|
||||
<a data-type="tools"><i class="font-icon icon-suitcase"></i><?php echo LNG("PluginTypeTools");?></a>
|
||||
<a data-type="media"><i class="font-icon icon-film"></i><?php echo LNG("PluginTypeMedia");?></a>
|
||||
<a data-type="others"><i class="font-icon icon-ellipsis-horizontal"></i><?php echo LNG("PluginTypeOthers");?></a>
|
||||
</ul>
|
||||
</div>
|
||||
<div class='app-content main app-plugins'>
|
||||
<div class="app-model app-content-box">
|
||||
<div class='h1'></div>
|
||||
<ul class="app-list"></ul>
|
||||
</div>
|
||||
<div class="app-model app-descript can-select can-right-menu hidden"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php include(TEMPLATE.'common/footerCommon.html');?>
|
||||
<script type="text/javascript">
|
||||
seajs.use('app/src/plugins/main');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_setting.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/<?php echo $config['user']['theme'];?>.css?ver=<?php echo KOD_VERSION;?>" id='link-theme-style'/>
|
||||
|
||||
</head>
|
||||
<body class="setting-page" oncontextmenu="return core.contextmenu();">
|
||||
<div class="init-loading">
|
||||
<div><img src="<?php echo STATIC_PATH;?>images/common/loading_simple.gif?v=<?php echo KOD_VERSION;?>"/></div>
|
||||
</div>
|
||||
<div id="body">
|
||||
<div class="menu-left">
|
||||
<h1><?php echo LNG('setting_title');?></h1>
|
||||
<ul class='setting'>
|
||||
<a href="javascript:void(0);" id="system"><i class="font-icon icon-cog"></i><?php echo LNG('system_setting');?></a>
|
||||
<a href="javascript:void(0);" id="member"><i class="font-icon icon-group"></i><?php echo LNG('system_group');?></a>
|
||||
<a href="javascript:void(0);" id="user"><i class="font-icon icon-user"></i><?php echo LNG('setting_user');?></li>
|
||||
<a href="javascript:void(0);" id="theme"><i class="font-icon icon-dashboard"></i><?php echo LNG('setting_theme');?></a>
|
||||
<a href="javascript:void(0);" id="wall"><i class="font-icon icon-picture"></i><?php echo LNG('setting_wall');?></a>
|
||||
<a href="javascript:void(0);" id="fav"><i class="font-icon icon-star"></i><?php echo LNG('setting_fav');?></a>
|
||||
<a href="javascript:void(0);" id="help"><i class="font-icon icon-question"></i><?php echo LNG('setting_help');?></a>
|
||||
<a href="javascript:void(0);" id="about"><i class="font-icon icon-info-sign"></i><?php echo LNG('setting_about');?></a>
|
||||
</ul>
|
||||
</div>
|
||||
<div class='main'></div>
|
||||
</div>
|
||||
<?php include(TEMPLATE.'common/footerCommon.html');?>
|
||||
<script type="text/javascript">
|
||||
seajs.use('app/src/setting/main');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,87 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo clear_html($shareInfo['name']).' - '.LNG('share_title').' - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_code_edit.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/<?php echo $configTheme;?>.css?ver=<?php echo KOD_VERSION;?>" id='link-theme-style'/>
|
||||
|
||||
</head>
|
||||
<body <?php echo $codeThemeBlack;?>>
|
||||
<div class="edit-main" style="height: 100%;" oncontextmenu="return core.contextmenu();">
|
||||
<div class="tools">
|
||||
<div class="left top-toolbar">
|
||||
<div class="disable-mask"></div>
|
||||
<a action="save" href="javascript:;" title="<?php echo LNG('button_save');?>(Ctrl-S)"><i class="font-icon icon-save"></i></a>
|
||||
<a action="saveall" href="javascript:;" title="<?php echo LNG('button_save_all');?>"><i class="font-icon icon-paste"></i></a>
|
||||
<span class="line"></span>
|
||||
<a action="undo" href="javascript:;" title="<?php echo LNG('undo');?>(Ctrl-Z)"><i class="font-icon icon-undo"></i></a>
|
||||
<a action="redo" href="javascript:;" title="<?php echo LNG('redo');?>(Ctrl-Y)"><i class="font-icon icon-repeat"></i></a>
|
||||
<a action="refresh" href="javascript:;" title="<?php echo LNG('refresh');?>(F5)"><i class="font-icon icon-refresh"></i></a>
|
||||
<span class="line"></span>
|
||||
<a href="javascript:;" class="toolbar-menu menu-view-goto-line" title="<?php echo LNG('gotoline');?>(Ctrl-L)"><i class="font-icon icon-pushpin"></i></a>
|
||||
<a action="search" href="javascript:;" title="<?php echo LNG('search');?>(Ctrl-F)"><i class="font-icon icon-search"></i></a>
|
||||
<a action="searchReplace" href="javascript:;" title="<?php echo LNG('replace');?>(Ctrl-F-F)"><i class="font-icon icon-random"></i></a>
|
||||
<span class="line"></span>
|
||||
<a action="font" class="toolbar-menu menu-view-font" href="javascript:;" title="<?php echo LNG('font_size');?>">
|
||||
<i class="font-icon icon-font"></i><i class="font-icon icon-caret-down"></i>
|
||||
</a>
|
||||
<span class="line"></span>
|
||||
<a class="toolbar-menu menu-view-theme" href="javascript:;" title="<?php echo LNG('code_theme');?>">
|
||||
<i class="font-icon icon-magic"></i><i class="font-icon icon-caret-down"></i>
|
||||
</a>
|
||||
<a class="toolbar-menu menu-view-setting" href="javascript:;" title="<?php echo LNG('setting');?>">
|
||||
<i class="font-icon icon-cog"></i><i class="font-icon icon-caret-down"></i>
|
||||
</a>
|
||||
<a action="preview" href="javascript:;" title="<?php echo LNG('preview');?>(Ctrl-Shift-S)"><i class="font-icon icon-eye-open"></i></a>
|
||||
</div>
|
||||
<div class="right">
|
||||
<a action="fullscreen" href="javascript:;" title="<?php echo LNG('full_screen');?>"><i class="font-icon icon-resize-full"></i></a>
|
||||
<a action="close" href="javascript:;" title="<?php echo LNG('close');?>"><i class="font-icon icon-remove"></i></a>
|
||||
</div>
|
||||
<div style="clear:both"></div>
|
||||
</div><!-- end tools -->
|
||||
|
||||
<!-- 主体部分 -->
|
||||
<div class="frame-left">
|
||||
<div class="edit-tab">
|
||||
<div class="tabs">
|
||||
<a href="javascript:Editor.add()" class="add icon-plus"></a>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="edit-body">
|
||||
<div class="introduction hidden">
|
||||
<?php include(LANGUAGE_PATH.I18n::getType().'/edit.html');?>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
<div class="tabs"></div>
|
||||
<div class="bottom-toolbar hidden">
|
||||
<a class="toolbar-menu menu-view-goto-line editor_position" href="javascript:;">0:0</a>
|
||||
<a class="file-mode" href="javascript:;">text</a>
|
||||
<a class="toolbar-menu menuViewTab config-tab" href="javascript:;">Tabs:4</a>
|
||||
<a class="toolbar-menu menu-view-setting config" href="javascript:;"><i class="font-icon icon-cog"></i></a>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="search-content hidden"></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include(TEMPLATE.'common/footerCommon.html');?>
|
||||
<script type="text/javascript">
|
||||
AUTH = {'explorer.fileDownload':<?php echo $canDownload;?>};
|
||||
G.fristFile = "<?php echo (isset($_GET['filename']) ? clear_html($_GET['filename']) :'') ;?>";
|
||||
G.codeConfig = <?php echo $editorConfig;?>;
|
||||
G.codeThemeAll = "<?php echo $config['settingAll']['codethemeall']?>";
|
||||
G.codeFontAll = "<?php echo $config['settingAll']['codefontall']?>";
|
||||
G.user = "<?php echo clear_html($_GET['user']);?>";
|
||||
G.sid = "<?php echo clear_html($_GET['sid']);?>";
|
||||
G.theme = "<?php echo $configTheme;?>";
|
||||
seajs.config({
|
||||
preload: [
|
||||
"lib/jquery-1.8.0.min",
|
||||
'lib/ace/src-min-noconflict/ace'
|
||||
]
|
||||
});
|
||||
seajs.use("app/src/edit/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo clear_html($shareInfo['name']).' - '.LNG('share_title').' - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_editor.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/<?php echo $configTheme;?>.css?ver=<?php echo KOD_VERSION;?>" id='link-theme-style'/>
|
||||
|
||||
</head>
|
||||
|
||||
|
||||
<?php if(isset($_GET['project'])){?>
|
||||
<style>
|
||||
.topbar{display: none;}
|
||||
.frame-header,.frame-main,.frame-main .frame-left{top:0;}
|
||||
.edit-content.markdown-full-page .edit-right-frame .markdown-preview {padding-top: 50px;}
|
||||
.edit-body {bottom: 30px;}
|
||||
</style>
|
||||
<?php } ?>
|
||||
|
||||
<?php if(isset($_GET['user'])){?>
|
||||
<style>
|
||||
.frame-main .frame-left{top:0;}
|
||||
.frame-main{bottom:0px;}
|
||||
</style>
|
||||
<?php } ?>
|
||||
|
||||
<body style="overflow:hidden;" oncontextmenu="return core.contextmenu();" id="page-editor">
|
||||
<?php include(TEMPLATE.'common/navbarShare.html');?>
|
||||
<div class="frame-main">
|
||||
<div class='frame-left'>
|
||||
<ul id="folder-list-tree" style="margin-top:10px;" class="ztree"></ul>
|
||||
</div><!-- / frame-left end-->
|
||||
<div class='frame-resize'></div>
|
||||
<div class='frame-right'>
|
||||
<div class="frame-right-main" style="height:100%;padding:0;margin:0;">
|
||||
<div class="resize-mask"></div>
|
||||
<div class="message-box"><div class="content"></div></div>
|
||||
<div class="menu-tree-root"></div>
|
||||
<div class="menu-tree-folder"></div>
|
||||
<div class="menu-tree-file"></div>
|
||||
<div class ='frame'>
|
||||
<iframe name="OpenopenEditor"
|
||||
src="./index.php?share/edit&user=<?php echo clear_html($_GET['user']);?>&sid=<?php echo clear_html($_GET['sid']);?>"
|
||||
style="width:100%;height:100%;border:0;" frameborder=0></iframe>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- / frame-right end-->
|
||||
</div><!-- / frame-main end-->
|
||||
<?php include(TEMPLATE.'common/footerCommon.html');?>
|
||||
<script type="text/javascript">
|
||||
AUTH = {'explorer.fileDownload':<?php echo $canDownload;?>};
|
||||
G.project = "<?php echo (isset($_GET['project'])?clear_html($_GET['project']):'') ;?>";
|
||||
G.user = "<?php echo clear_html($_GET['user']);?>";
|
||||
G.sid = "<?php echo clear_html($_GET['sid']);?>";
|
||||
G.shareInfo = <?php echo json_encode($shareInfo);?>;
|
||||
G.theme = "<?php echo $configTheme;?>";
|
||||
seajs.use("app/src/shareEditor/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo clear_html($shareInfo['name']).' - '.LNG('share_title').' - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_explorer.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/<?php echo $configTheme;?>.css?ver=<?php echo KOD_VERSION;?>" id='link-theme-style'/>
|
||||
|
||||
</head>
|
||||
|
||||
<style>
|
||||
.frame-main .frame-left {bottom: 0px;}
|
||||
.frame-main .bottom-box{display:none !important;}
|
||||
.tools-right #set_theme{display:none !important;}
|
||||
#PV_rotate_Left,#PV_rotate_Right,#PV_Btn_Remove{display:none !important;}
|
||||
<?php if(isset($_GET['type'])){?>
|
||||
.topbar,.common-footer,.bottom-box{display:none;}
|
||||
.frame-header{top:0;}
|
||||
.frame-main{top:0px;bottom:0px;}
|
||||
.frame-main .frame-left #folder-list-tree{bottom:5px;}
|
||||
<?php if($_GET['type']=="explorer"){?>
|
||||
.frame-header .header-content .header-left{display:none;}
|
||||
.frame-header .header-content .header-middle{left:12px;}
|
||||
.frame-main .frame-left,.frame-main .frame-resize{display:none;}
|
||||
.frame-main .frame-right{left:0px;}
|
||||
.task-tab{display:none;}
|
||||
<?php } ?>
|
||||
|
||||
<?php if($_GET['type']=="fileList"){?>
|
||||
.frame-header{display:none;}
|
||||
.frame-main .frame-left,.frame-main .frame-resize{display:none;}
|
||||
.frame-main .frame-right{left:0px;}
|
||||
.frame-main{top:0px;}
|
||||
.task-tab,#set_theme,#fav,#home{display:none !important;}
|
||||
.header-middle{top:3px;left:5px;right:140px;}
|
||||
#list-type-header{top:35px;}
|
||||
<?php } ?>
|
||||
<?php } ?>
|
||||
</style>
|
||||
|
||||
|
||||
<body style="overflow:hidden;" oncontextmenu="return core.contextmenu();" id="page-explorer">
|
||||
<?php include(TEMPLATE.'common/navbarShare.html');?>
|
||||
<?php include(TEMPLATE.'explorer/content.html');?>
|
||||
<?php include(TEMPLATE.'common/footer.html');?>
|
||||
<script type="text/javascript" >
|
||||
AUTH = {'explorer.fileDownload':<?php echo clear_html($canDownload);?>};
|
||||
G.thisPath = "<?php echo clear_html($dir);?>";
|
||||
G.user = "<?php echo clear_html($_GET['user']);?>";
|
||||
G.sid = "<?php echo clear_html($_GET['sid']);?>";
|
||||
G.shareInfo = <?php echo json_encode($shareInfo);?>;
|
||||
G.theme = "<?php echo $configTheme;?>";
|
||||
seajs.use("app/src/shareExplorer/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo LNG('ui_explorer').' - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link href="<?php echo STATIC_PATH;?>style/wap/app_explorer.css?ver=<?php echo KOD_VERSION;?>" rel="stylesheet"/>
|
||||
</head>
|
||||
<body>
|
||||
<div class="frame-main">
|
||||
<div class="frame-header">
|
||||
<div class="title"><?php echo clear_html($shareInfo['name']);?></div>
|
||||
<div class="menu-group">
|
||||
<div class="btn-list-icon"><i class="font-icon icon-home"></i></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="address">
|
||||
<ul class="yarnball"></ul>
|
||||
<div style="clear: both"></div>
|
||||
</div>
|
||||
<div class='bodymain'>
|
||||
<div class="file-continer file-list-list"></div>
|
||||
</div>
|
||||
|
||||
<div class="file-menu">
|
||||
<div class="file-action-menu hidden">
|
||||
<div class='action-menu' data-action="action-download"><i class="font-icon icon-info"></i><?php echo LNG('download');?></div>
|
||||
<div class='action-menu' data-action="action-share-open">
|
||||
<span class="content">
|
||||
<i class="font-icon icon-share"></i><?php echo LNG('open');?>
|
||||
</span>
|
||||
</div>
|
||||
<div class="menu-close"><i class="font-icon icon-ellipsis-horizontal"></i></div>
|
||||
<div style="clear:both"></div>
|
||||
</div>
|
||||
</div>
|
||||
<?php include(TEMPLATE.'common/footer.html');?>
|
||||
</div><!-- / frame-main end-->
|
||||
<div class="toolbar-menu">
|
||||
<button class="menu-plus tool tool-menu-right-btn" data-toggle="dropdown"></button>
|
||||
<ul class="dropdown-menu tool-menu-right pull-right animated menuShow" role="menu" >
|
||||
<li data-action="upload"><a href="javascript:void();">
|
||||
<i class="font-icon icon-cloud-upload"></i><?php echo LNG('upload');?></a></li>
|
||||
<li data-action="newfolder"><a href="javascript:void();">
|
||||
<i class="font-icon icon-folder-close-alt"></i><?php echo LNG('newfolder');?></a></li>
|
||||
<li data-action="newfile"><a href="javascript:void();">
|
||||
<i class="font-icon icon-file-text"></i><?php echo LNG('newfile');?></a></li>
|
||||
<li data-action="past"><a href="javascript:void();">
|
||||
<i class="font-icon icon-paste"></i><?php echo LNG('past');?></a></li>
|
||||
<li data-action="search"><a href="javascript:void();">
|
||||
<i class="font-icon icon-search"></i><?php echo LNG('search');?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<script type="text/javascript">
|
||||
G.thisPath = "<?php echo clear_html($dir);?>";
|
||||
G.user = "<?php echo clear_html($_GET['user']);?>";
|
||||
G.sid = "<?php echo clear_html($_GET['sid']);?>";
|
||||
G.shareInfo = <?php echo json_encode($shareInfo);?>;
|
||||
seajs.use("<?php echo STATIC_JS;?>/src/explorerWap/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,45 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo clear_html($shareInfo['name']).' - '.LNG('share_title').' - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_code_edit.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/<?php echo $configTheme;?>.css?ver=<?php echo KOD_VERSION;?>" id='link-theme-style'/>
|
||||
|
||||
</head>
|
||||
<style type="text/css">
|
||||
.frame-main{bottom: 32px;}
|
||||
</style>
|
||||
|
||||
<body>
|
||||
<?php include(TEMPLATE.'common/navbarShare.html');?>
|
||||
<div class="frame-main share-page-main">
|
||||
<!-- bindary-box -->
|
||||
<div class="bindary-box hidden">
|
||||
<div class="title"><div class="ico"></div></div>
|
||||
<div class="content-info">
|
||||
<div class="name"></div>
|
||||
<div class="size"><span></span><i class="share-time"></i></div>
|
||||
<div class="btn-group">
|
||||
<a type="button" class="btn btn-primary btn-download" href=""><?php echo LNG('download');?></a>
|
||||
</div>
|
||||
<div class="error-tips"><?php echo LNG('share_error_show_tips');?></div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="content-box"></div>
|
||||
</div><!-- / frame-main end-->
|
||||
<?php include(TEMPLATE.'common/footer.html');?>
|
||||
<script type="text/javascript">
|
||||
AUTH = {'explorer.fileDownload':<?php echo $canDownload;?>};
|
||||
G.user = "<?php echo clear_html($_GET['user']);?>";
|
||||
G.path = "<?php echo clear_html($_GET['path']);?>";
|
||||
G.sid = "<?php echo clear_html($_GET['sid']);?>";
|
||||
G.shareInfo = <?php echo json_encode($shareInfo);?>;
|
||||
G.theme = "<?php echo $configTheme;?>";
|
||||
seajs.config({
|
||||
preload: [
|
||||
"lib/jquery-1.8.0.min",
|
||||
'lib/ace/src-min-noconflict/ace'
|
||||
]
|
||||
});
|
||||
seajs.use("app/src/shareIndex/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,26 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title>tips - <?php echo LNG('share_title').' - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/base/app_code_edit.css?ver=<?php echo KOD_VERSION;?>"/>
|
||||
<link rel="stylesheet" href="<?php echo STATIC_PATH;?>style/skin/<?php echo $configTheme;?>.css?ver=<?php echo KOD_VERSION;?>" id='link-theme-style'/>
|
||||
|
||||
</head>
|
||||
|
||||
<body style="overflow:hidden;">
|
||||
<?php include(TEMPLATE.'common/navbarShare.html');?>
|
||||
<div class="frame-main">
|
||||
<?php if($msg=='password'){?>
|
||||
<div class="share-page-passowrd">
|
||||
<div class="title"><?php echo LNG('share_password');?></div>
|
||||
<input type="password" class="form-control"/>
|
||||
<a href="javascript:void(0);" class="btn btn-primary share-login"><?php echo LNG('button_ok');?></a>
|
||||
</div>
|
||||
<?php }else{?>
|
||||
<div class="share-page-error"><b>tips:</b><?php echo $msg;?></div>
|
||||
<?php }?>
|
||||
</div><!-- / frame-main end-->
|
||||
<?php include(TEMPLATE.'common/footer.html');?>
|
||||
<script type="text/javascript">
|
||||
seajs.use("app/src/shareIndex/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,63 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<link href="<?php echo STATIC_PATH;?>style/login.css?ver=<?php echo KOD_VERSION;?>" rel="stylesheet">
|
||||
<title><?php echo LNG('php_env_check').' - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<?php echo pageBackground();?>
|
||||
<div class="background"></div>
|
||||
<div class="loginbox box-install aero" >
|
||||
<div class="title">
|
||||
<div class="logo"><i class="icon-cloud"></i><?php echo strip_tags(LNG('kod_name'));?></div>
|
||||
<div class='info'><?php echo LNG('kod_name_desc');?></div>
|
||||
<div class="menu-group">
|
||||
<a id='footer-language' data-toggle="dropdown" href="javascript:void(0);" class="topbar-menu">
|
||||
<i class='font-icon icon-flag'></i>Language<b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu footer-language pull-left animated menuShow" role="menu" aria-labelledby="footer-language">
|
||||
<?php
|
||||
$tpl = "";
|
||||
foreach ($config['settingAll']['language'] as $key => $value) {
|
||||
$name = $value[0];
|
||||
$select = I18n::getType() == $key ? "this":"";
|
||||
$tpl .= "<li><a href='javascript:core.language(\"{$key}\");' title=\"{$key}/{$value[1]}/{$value[2]}\" class='{$select}'><i class='lang-flag flag-{$key}'></i>{$name}</a></li>";
|
||||
}
|
||||
echo $tpl;
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form" style="padding: 10px 20px 40px 20px;">
|
||||
<h3><?php echo LNG('php_env_check');?></h3>
|
||||
<?php
|
||||
$error = php_env_check();
|
||||
$login = LNG('login');
|
||||
if ($error=='') {
|
||||
echo '<div class="success">';
|
||||
}else{
|
||||
echo '<div class="error"><h4>error:</h4>'.$error."<br/>";
|
||||
$login = LNG('php_env_error_ignore');
|
||||
}
|
||||
$login_info = str_replace(array("{0}","{1}","{2}"),array('admin','demo/demo','guest/guest'),LNG('install_user_default'));
|
||||
echo LNG('install_login'),'<br/>'.$login_info.'</div>';
|
||||
echo '<div class="inputs admin-password"><input type="password" placeholder="'.LNG('login_root_password').'"/></div><div class="inputs admin-password-repeat"><input type="password" placeholder="'.LNG('login_root_password_repeat').'"/></div>';
|
||||
echo '<div class="guest"><a href="javascript:void(0);" class="start">'.$login.'</a></div>';
|
||||
?>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php $GLOBALS['loadCommonJs'] = true;?>
|
||||
<?php include(TEMPLATE.'common/footer.html');?>
|
||||
<script type="text/javascript" >
|
||||
setTimeout(function(){
|
||||
if( typeof(seajs) == 'undefined' ||
|
||||
typeof(LNG) == 'undefined'
|
||||
){
|
||||
alert('js文件不完整,请查看浏览器控制台和服务器配置是否正常。或检查文件是否被修改(或咨询主机商压缩js导致文件损坏);[js load error!]');
|
||||
}
|
||||
},1000);
|
||||
seajs.use("<?php echo STATIC_JS;?>/src/user/main");
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo 'License Register - '.strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link href="<?php echo STATIC_PATH;?>style/login.css?ver=<?php echo KOD_VERSION;?>" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body class="license-page">
|
||||
<?php echo pageBackground();?>
|
||||
<div class="background"></div>
|
||||
<div class="loginbox aero" >
|
||||
<div class="title">
|
||||
<div class="logo">升级为商业版</div>
|
||||
<div class='info'><?php echo LNG('copyright_contact');?></div>
|
||||
</div>
|
||||
<div class="form" style="padding: 10px 20px;">
|
||||
<div class="inputs admin-password"><input type="text" placeholder="LICENSE KEY"/></div>
|
||||
<a href="javascript:void(0);" class="LICENSE_SUBMIT btn btn-primary">注册授权</a>
|
||||
<div class="links">
|
||||
<a href="./index.php?user/versionInstall&reset=1" class="btn btn-link license-use-free"><?php echo LNG('use_free');?></a>
|
||||
<a href="http://kodcloud.com/buy.html#<?php echo I18n::getType();?>" target="_blank" class="btn btn-link license-learn-more"><?php echo LNG('learn_more');?></a>
|
||||
</div>
|
||||
<br/>
|
||||
</div>
|
||||
</div>
|
||||
<?php $GLOBALS['loadCommonJs'] = true;?>
|
||||
<?php include(TEMPLATE.'common/footer.html');?>
|
||||
<script type="text/javascript" >
|
||||
seajs.use("<?php echo STATIC_JS;?>/src/user/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,91 @@
|
||||
<!--user login-->
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<title><?php echo strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
<link href="<?php echo STATIC_PATH;?>style/login.css?ver=<?php echo KOD_VERSION;?>" rel="stylesheet">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<?php echo pageBackground();?>
|
||||
<div class="background"></div>
|
||||
<div class="init-loading"><div><img src="<?php echo STATIC_PATH;?>images/common/loading_simple.gif?v=<?php echo KOD_VERSION;?>"/></div></div>
|
||||
<div class="loginbox animated-500 fadeInDown aero" >
|
||||
<div class="title">
|
||||
<div class="logo"><i class="icon-cloud"></i><?php echo strip_tags(LNG('kod_name'));?></div>
|
||||
<div class='info'><?php echo LNG('kod_name_desc');?></div>
|
||||
<?php if(!isset($config['settings']['language'])){ ?>
|
||||
<div class="menu-group">
|
||||
<a id='footer-language' data-toggle="dropdown" href="javascript:void(0);" class="topbar-menu">
|
||||
<i class='font-icon icon-flag'></i>Language<b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu footer-language pull-left animated menuShow" role="menu" aria-labelledby="footer-language">
|
||||
<?php
|
||||
$tpl = "";
|
||||
foreach ($config['settingAll']['language'] as $key => $value) {
|
||||
$name = $value[0];
|
||||
$select = I18n::getType() == $key ? "this":"";
|
||||
$tpl .= "<li><a href='javascript:core.language(\"{$key}\");' title=\"{$key}/{$value[1]}/{$value[2]}\" class='{$select}'><i class='lang-flag flag-{$key}'></i>{$name}</a></li>";
|
||||
}
|
||||
echo $tpl;
|
||||
?>
|
||||
</ul>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</div>
|
||||
<div class="form">
|
||||
<form action="#">
|
||||
<div class="inputs">
|
||||
<div>
|
||||
<i class="font-icon icon-user"></i>
|
||||
<input id="username" name='name' type="text" placeholder="<?php echo LNG('username');?>"
|
||||
required autocomplete="on" disabled/>
|
||||
</div>
|
||||
<div>
|
||||
<i class="font-icon icon-key"></i>
|
||||
<input id="password" name='password' type="password" placeholder="<?php echo LNG('password');?>"
|
||||
required autocomplete="on" disabled/>
|
||||
<input type='hidden' name='csrfLogin' value="<?php echo $_SESSION['csrfLogin'];?>"/>
|
||||
</div>
|
||||
<?php if(need_check_code()){?>
|
||||
<div class='check-code'>
|
||||
<i class="font-icon icon-unlock-alt"></i>
|
||||
<input name='checkCode' class="check-code" type="text" placeholder="<?php echo LNG('login_code');?>" required/>
|
||||
<img src='./index.php?user/checkCode' onclick="this.src='./index.php?user/checkCode'" />
|
||||
</div>
|
||||
<?php }?>
|
||||
</div>
|
||||
|
||||
<div class="actions">
|
||||
<label for='rm'>
|
||||
<input type="checkbox" class="checkbox" name="rememberPassword" id='rm'/>
|
||||
<?php echo LNG('login_rember_password');?>
|
||||
</label>
|
||||
<a href="javascript:void(0);" class="forget-password"><?php echo LNG('forget_password');?></a>
|
||||
<br/>
|
||||
<input type="submit" id="submit" value="<?php echo LNG('login');?>" />
|
||||
</div>
|
||||
|
||||
<div class="msg"><?php echo $msg;?></div>
|
||||
|
||||
<?php if ($this->config['settingSystem']['autoLogin'] == '1') {?>
|
||||
<div class='guest'>
|
||||
<a href="./index.php?user/loginSubmit&name=guest&password=guest"><?php echo LNG('guest_login');?><i class=' icon-arrow-right'></i></a>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php $GLOBALS['loadCommonJs'] = true;?>
|
||||
<?php include(TEMPLATE.'common/footer.html');?>
|
||||
<script type="text/javascript" >
|
||||
setTimeout(function(){
|
||||
if( typeof(seajs) == 'undefined' ||
|
||||
typeof(LNG) == 'undefined'
|
||||
){
|
||||
alert('js文件不完整,请查看浏览器控制台和服务器配置是否正常。或检查文件是否被修改(或咨询主机商压缩js导致文件损坏);[js load error!]');
|
||||
}
|
||||
},1000);
|
||||
seajs.use("<?php echo STATIC_JS;?>/src/user/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,65 @@
|
||||
<!--user login-->
|
||||
<?php include(TEMPLATE.'common/header.html');?>
|
||||
<link href="<?php echo STATIC_PATH;?>style/wap/login.css?ver=<?php echo KOD_VERSION;?>" rel="stylesheet">
|
||||
<title><?php echo strip_tags(LNG('kod_name')).LNG('kod_power_by');?></title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<?php echo pageBackground();?>
|
||||
<div class="background"></div>
|
||||
<div class="loginbox login-wap aero" >
|
||||
<div class="title">
|
||||
<div class="logo">
|
||||
<i class="icon-cloud"></i><?php echo strip_tags(LNG('kod_name'));?>
|
||||
</div>
|
||||
<div class='info'><?php echo LNG('kod_name_desc');?></div>
|
||||
</div>
|
||||
<div class="form">
|
||||
<form action="#">
|
||||
<div class="inputs">
|
||||
<div>
|
||||
<i class="font-icon icon-user"></i>
|
||||
<input id="username" name='name' type="text" placeholder="<?php echo LNG('username');?>"
|
||||
required disabled/>
|
||||
</div>
|
||||
<div>
|
||||
<i class="font-icon icon-key"></i>
|
||||
<input id="password" name='password' type="password" placeholder="<?php echo LNG('password');?>"
|
||||
required disabled/>
|
||||
<input type='hidden' name='csrfLogin' value="<?php echo $_SESSION['csrfLogin'];?>"/>
|
||||
</div>
|
||||
|
||||
<?php if(need_check_code()){?>
|
||||
<div class='check-code'>
|
||||
<i class="font-icon icon-unlock-alt"></i>
|
||||
<input name='checkCode' class="check-code" type="text" placeholder="<?php echo LNG('login_code');?>" required/>
|
||||
<img src='./index.php?user/checkCode' onclick="this.src='./index.php?user/checkCode'" />
|
||||
</div>
|
||||
<?php }?>
|
||||
</div>
|
||||
<div class="actions">
|
||||
<label for='rm'>
|
||||
<input type="checkbox" class="checkbox" name="rememberPassword" id='rm'/>
|
||||
<?php echo LNG('login_rember_password');?>
|
||||
</label>
|
||||
<a href="javascript:void(0);" class="forget-password"><?php echo LNG('forget_password');?></a>
|
||||
<input type="submit" id="submit" value="<?php echo LNG('login');?>" />
|
||||
</div>
|
||||
<div class="msg"><?php echo $msg;?></div>
|
||||
|
||||
<?php if ($this->config['settingSystem']['autoLogin'] == '1') {?>
|
||||
<div class='guest'>
|
||||
<a href="./index.php?user/loginSubmit&name=guest&password=guest"><?php echo LNG('guest_login');?><i class=' icon-arrow-right'></i></a>
|
||||
</div>
|
||||
<?php } ?>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php $GLOBALS['loadCommonJs'] = true;?>
|
||||
<?php include(TEMPLATE.'common/footer.html');?>
|
||||
<script type="text/javascript" >
|
||||
seajs.use("<?php echo STATIC_JS;?>/src/user/main");
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
/*
|
||||
* @link http://kodcloud.com/
|
||||
* @author warlee | e-mail:kodcloud@qq.com
|
||||
* @copyright warlee 2014.(Shanghai)Co.,Ltd
|
||||
* @license http://kodcloud.com/tools/license/license.txt
|
||||
*/
|
||||
|
||||
define('GLOBAL_DEBUG',0);//0 or 1
|
||||
define('GLOBAL_DEBUG_HOOK',0);//0 or 1
|
||||
@date_default_timezone_set(@date_default_timezone_get());
|
||||
@set_time_limit(1200);//20min pathInfoMuti,search,upload,download...
|
||||
@ini_set("max_execution_time",1200);
|
||||
@ini_set('memory_limit','500M');//
|
||||
@ini_set('session.cache_expire',1800);
|
||||
|
||||
if(GLOBAL_DEBUG){
|
||||
define('STATIC_JS','_dev'); //_dev||app
|
||||
define('STATIC_LESS','less');//less||css
|
||||
@ini_set("display_errors","on");
|
||||
@error_reporting(E_ALL^E_NOTICE^E_WARNING^E_DEPRECATED);//
|
||||
}else{
|
||||
define('STATIC_JS','app'); //app
|
||||
define('STATIC_LESS','css');//css
|
||||
@ini_set("display_errors","on");//on off
|
||||
@error_reporting(E_ALL^E_NOTICE^E_WARNING^E_DEPRECATED);// 0
|
||||
}
|
||||
|
||||
//header('HTTP/1.1 200 Ok');//兼容部分lightHttp服务器环境; php5.1以下会输出异常;暂屏蔽
|
||||
header("Content-type: text/html; charset=utf-8");
|
||||
define('BASIC_PATH',str_replace('\\','/',dirname(dirname(__FILE__))).'/');
|
||||
define('LIB_DIR', BASIC_PATH .'app/'); //系统库目录
|
||||
define('PLUGIN_DIR', BASIC_PATH .'plugins/'); //插件目录
|
||||
define('CONTROLLER_DIR',LIB_DIR .'controller/'); //控制器目录
|
||||
define('MODEL_DIR', LIB_DIR .'model/'); //模型目录
|
||||
define('TEMPLATE', LIB_DIR .'template/'); //模版文件路径
|
||||
define('FUNCTION_DIR', LIB_DIR .'function/'); //函数库目录
|
||||
define('CLASS_DIR', LIB_DIR .'kod/'); //工具类目录
|
||||
define('CORER_DIR', LIB_DIR .'core/'); //核心目录
|
||||
define('SDK_DIR', LIB_DIR .'sdks/'); //
|
||||
define('DEFAULT_PERRMISSIONS',0755); //新建文件、解压文件默认权限,777 部分虚拟主机限制了777;
|
||||
|
||||
/*
|
||||
* 可以数据目录;移到web目录之外,可以使程序更安全, 就不用限制用户的扩展名权限了;
|
||||
* 1. 需要先将data文件夹移到别的地方 例如将data文件夹拷贝到D:/
|
||||
* 2. 在config文件夹下新建define.php 新增一行 <?php define('DATA_PATH','D:/data/');
|
||||
* 注意:路径不能写错;其次php需要有权限访问移动后的目录(设置了防跨站需要关闭) 路径结尾/斜杠绝对不能缺少
|
||||
*/
|
||||
if(file_exists(BASIC_PATH.'config/define.php')){
|
||||
include(BASIC_PATH.'config/define.php');
|
||||
}
|
||||
if(!defined('DATA_PATH')){
|
||||
define('DATA_PATH',BASIC_PATH .'data/'); //用户数据目录
|
||||
}
|
||||
define('USER_PATH', DATA_PATH .'User/'); //用户目录
|
||||
define('GROUP_PATH', DATA_PATH .'Group/'); //群组目录
|
||||
define('USER_SYSTEM', DATA_PATH .'system/'); //用户数据存储目录
|
||||
define('TEMP_PATH', DATA_PATH .'temp/'); //临时目录
|
||||
define('LOG_PATH', TEMP_PATH .'log/'); //日志
|
||||
define('DATA_THUMB', TEMP_PATH .'thumb/'); //缩略图生成存放
|
||||
define('LANGUAGE_PATH', BASIC_PATH .'config/i18n/');//多语言目录
|
||||
define('SESSION_ID','KOD_SESSION_ID_'.substr(md5(BASIC_PATH),0,5));
|
||||
define('KOD_SESSION', DATA_PATH .'session/'); //session目录
|
||||
include(FUNCTION_DIR.'common.function.php');
|
||||
include(FUNCTION_DIR.'web.function.php');
|
||||
include(FUNCTION_DIR.'file.function.php');
|
||||
include(FUNCTION_DIR.'helper.function.php');
|
||||
include(CLASS_DIR.'I18n.class.php');
|
||||
include(BASIC_PATH.'config/version.php');
|
||||
check_cache();
|
||||
|
||||
$config['appStartTime'] = mtime();
|
||||
$config['appCharset'] = 'utf-8';//该程序整体统一编码
|
||||
$config['checkCharset'] = 'ASCII,UTF-8,GB2312,GBK,BIG5,UTF-16,UCS-2,'.
|
||||
'Unicode,EUC-KR,EUC-JP,SHIFT-JIS,EUCJP-WIN,SJIS-WIN,JIS,LATIN1';//文件打开自动检测编码
|
||||
$config['checkCharsetDefault'] = '';//if set,not check;
|
||||
|
||||
//when edit a file ;check charset and auto converto utf-8;
|
||||
if (strtoupper(substr(PHP_OS, 0,3)) === 'WIN') {
|
||||
$config['systemOS']='windows';
|
||||
$config['systemCharset']='gbk';// EUC-JP/Shift-JIS/BIG5 //user set your server system charset
|
||||
if(version_compare(phpversion(), '7.1.0', '>=')){//7.1 has auto apply the charset
|
||||
$config['systemCharset']='utf-8';
|
||||
}
|
||||
} else {
|
||||
$config['systemOS']='linux';
|
||||
$config['systemCharset']='utf-8';
|
||||
}
|
||||
|
||||
// 部分反向代理导致获取不到url的问题优化;忽略同域名http和https的情况
|
||||
if(isset($_COOKIE['APP_HOST'])){
|
||||
if( get_url_domain($_COOKIE['HOST']) != get_url_domain($_COOKIE['APP_HOST']) ||
|
||||
get_url_scheme($_COOKIE['HOST']) == get_url_scheme($_COOKIE['APP_HOST']) ){
|
||||
define('HOST',$_COOKIE['HOST']);
|
||||
define('APP_HOST',$_COOKIE['APP_HOST']);
|
||||
}
|
||||
}
|
||||
if(!defined('HOST')){ define('HOST',rtrim(get_host(),'/').'/');}
|
||||
if(!defined('WEB_ROOT')){ define('WEB_ROOT',webroot_path(BASIC_PATH) );}
|
||||
if(!defined('APP_HOST')){ define('APP_HOST',HOST.str_replace(WEB_ROOT,'',BASIC_PATH));} //程序根目录
|
||||
define('PLUGIN_HOST',APP_HOST.str_replace(BASIC_PATH,'',PLUGIN_DIR));//插件目录
|
||||
|
||||
include(CONTROLLER_DIR.'utils.php');
|
||||
include(BASIC_PATH.'config/setting.php');
|
||||
if (file_exists(BASIC_PATH.'config/setting_user.php')) {
|
||||
include_once(BASIC_PATH.'config/setting_user.php');
|
||||
}
|
||||
if(file_exists(CONTROLLER_DIR.'debug.class.php')){
|
||||
include_once(CONTROLLER_DIR.'debug.class.php');
|
||||
}
|
||||
init_common();
|
||||
$config['autorun'] = array(
|
||||
array('controller'=>'user','function'=>'loginCheck'),
|
||||
array('controller'=>'user','function'=>'authCheck'),
|
||||
array('controller'=>'user','function'=>'bindHook'),
|
||||
);
|
||||
@@ -0,0 +1,33 @@
|
||||
<div class="box">
|
||||
<div class="title"><span>KODExplorer غير ماذا؟</span></div>
|
||||
<p>KODExplorer هو إدارة الوثائق على الانترنت على شبكة الإنترنت مفتوح المصدر، محرر التعليمات البرمجية. ويوفر نوعا من النوافذ الكلاسيكية واجهة المستخدم، ومجموعة من إدارة الوثائق على الانترنت، ومعاينة ملف، تحرير، تحميل وتنزيل، بفك الانترنت تشغيل الموسيقى. يسمح لك لتحقيق التنمية على شبكة الإنترنت مباشرة في المتصفح، وشفرة المصدر معاينة الملف، ونشر صاحب الموقع والعملية المحلية وسهلة وسريعة وتجربة آمنة.</p>
|
||||
<p><b>- تصميم -</b></p>
|
||||
<p>التقاليد الكلاسيكية، والسعي للابتكار، لتزويد المستخدمين مع مريحة، آمنة وسهلة لاستخدام نظام إدارة سحابة على الانترنت.</p>
|
||||
<p>كلما (متى)، حيث (حيث)، لديه شبكة الإنترنت كلما تريد (تريد) هو أداة لإدارة الخاص بك (4W السياسة).</p>
|
||||
<p><b>- المستخدم المنحى -</b></p>
|
||||
<p>حاليا نظام إدارة KODExplorer تقع أساسا في سحابة استضافة شخصية، صغير إدارة المشاريع سحابة الموارد وإدارة القرص الشبكة، وإدارة المواقع الصغيرة والمتوسطة. مطور ويب و الماجستير (قدامى المحاربين): محرر على الانترنت، والنسخ الاحتياطي مضغوط، نشر، الكلاسيكية تشغيل ويندوز واجهة، من السهل أن تبدأ وتخلص من SSH المضيف، الأمر FTP عمليات الحفر معقدة.</p>
|
||||
<p>سحابة شخصية خاصة (الصاعد): موارد القرص شبكة الإدارية، ونفس العملية النوافذ الكلاسيكية واجهة، يمكنك وضع محرك الأقراص الموسيقى تصفح الشبكة، وملفات الشاشة، تحميل وتنزيل بسرعة وسهولة.</p>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<div class="title"><span>ميزات</span></div>
|
||||
<p>إدارة ثيقة شاملة وقوية محرر الملفات على الإنترنت</p>
|
||||
<p>أينما كنت، يمكنك إدارة الملفات الخاصة بك، والترفيه عبر الإنترنت، على شبكة الإنترنت كتابة رمز! تماما كما مناسبة للاستخدام في نظام التشغيل.</p>
|
||||
<p>واسعة النطاق بحق عملية تجربة زرع المحلي، السحب، مربع التحديد، اختصارات، البحث عن الملفات (المحتوى البحث) ......</p>
|
||||
<p>مربع الاختيار، السحب الحركة، وسحب وإسقاط تحميل، محرر على الانترنت، ومشغل فيديو، ضغط. كامل الأداء ضمان اياكس والخبرة!</p>
|
||||
<p>كل وظيفة الربط السلس المباشر، في شكل حوار، وظائف إدارة متعددة المهام</p>
|
||||
<p>محرر يدعم-متعددة وثيقة، ودعم ZendCoding أتش تي أم أل، المغلق، شبيبة أعلى الترميز الكفاءة!</p>
|
||||
<p>الدعم الصيني الكمال، مشوه حل حالات مختلفة؛</p>
|
||||
</div>
|
||||
|
||||
<div class="box">
|
||||
<div class="title"><span>المصدر المفتوح اعتماد التكنولوجيا</span></div>
|
||||
<p><b>1.Jquery:</b>jpuery (المساعد: Hotkeys.ztree.contentmenu) شبيبة إطار التنمية السائد. تشغيل عملية دوم، BOM، عملية المغلق، وحزمة اياكس</p>
|
||||
<p><b>2.ArtDialog:</b>تصميم جميل، والتوافق متصفح قوي القطعة الحوار. لذا المنبثقة مقبض، والأحداث، ونقل البيانات للحصول على إدارة أفضل موحدة</p>
|
||||
<p><b>3.Ztree:</b>شجرة التحكم القائمة، والتدرجية هو جدا قوية شجرة معالجة البيانات القطعة</p>
|
||||
<p><b>4.codemirror:</b>محرر كود شبيبة الإضافات، ويدعم مجموعة متنوعة من لغات البرمجة لتسليط الضوء على</p>
|
||||
<p><b>5.zendcoding:</b>على رموز الدعم أتش تي أم أل الكتابة بسرعة المكونات الإضافية. يبسط يتم كتابة تعريف من التعليمات البرمجية. تجميع بسيط</p>
|
||||
<p><b>6.less:</b>نموذج تنمية المغلق كفاءة وظيفية لتحسين الواجهة الأمامية المغلق إعادة استخدام . تجميع بسيط</p>
|
||||
<p><b>7.SWFUpload:</b>ملف فلاش تحميل</p>
|
||||
<p><b>8 .CMP4:</b>لاعب فلاش جيد جدا المساعد ملفات الوسائط، ودعم تدفق وسائل الاعلام، شعبية أداة تشغيل الموسيقى والفيديو. دعم للبشرة، وإعدادات شكلي للغاية. قائمة ديناميكية أكس تحميل. رسائل الوسائط المتعددة تدفق وسائل الاعلام، RSTP رخصة مفتوحة المصدر دعم تشغيل الوسائط</p>
|
||||
</div>
|
||||
@@ -0,0 +1,72 @@
|
||||
<div class="intro-left" style=";text-align:right;direction:rtl">
|
||||
<div class="tips blue" style=";text-align:right;direction:rtl">
|
||||
<h1 style=";text-align:right;direction:rtl"> <span>الوظائف الغنية</span> </h1>
|
||||
<p style=";text-align:right;direction:rtl"> كود يطالب تلقائيا </p>
|
||||
<p style=";text-align:right;direction:rtl"> متعددة موضوع: اختيار أسلوب البرمجة المفضلة لديك </p>
|
||||
<p style=";text-align:right;direction:rtl"> الخط مخصص: للاستخدام في المشهد </p>
|
||||
<p style=";text-align:right;direction:rtl"> تحرير المؤشر متعددة، كتلة التحرير على الانترنت خبرة في البرمجة مماثلة للسامية </p>
|
||||
<p style=";text-align:right;direction:rtl"> كتلة قابلة للطي، التوسع؛ التفاف </p>
|
||||
<p style=";text-align:right;direction:rtl"> دعم العديد من علامات التبويب، اسحب تسلسل التبديل. </p>
|
||||
<p style=";text-align:right;direction:rtl"> الحفاظ على وثائق متعددة، والعثور على واستبدال، التاريخ؛ </p>
|
||||
<p style=";text-align:right;direction:rtl"> الإكمال التلقائي []، {}، ()، '' '' </p>
|
||||
<p style=";text-align:right;direction:rtl"> على الانترنت المعاينة في الوقت الحقيقي الذي يسمح لك أن تقع في الحب مع البرمجة على الانترنت! </p>
|
||||
<p style=";text-align:right;direction:rtl"> zendcodeing الدعم، كتابة التعليمات البرمجية ثمانين </p>
|
||||
<p style=";text-align:right;direction:rtl"> المزيد من الميزات انتظار اكتشاف الخاص بك ...... </p>
|
||||
</div>
|
||||
<div class="tips orange" style=";text-align:right;direction:rtl">
|
||||
<h1 style=";text-align:right;direction:rtl"> <span>150 نوعا من تسليط الضوء على كود</span> </h1>
|
||||
<p style=";text-align:right;direction:rtl"> نصيحة: أتش تي أم أل، وجافا سكريبت، المغلق، أقل، ساس، SCSS </p>
|
||||
<p style=";text-align:right;direction:rtl"> تطوير الشبكة: PHP، بيرل، بيثون، روبي، elang، انتقل ... </p>
|
||||
<p style=";text-align:right;direction:rtl"> اللغات التقليدية: جافا، C و C ++، C #، أكشن، فبسكريبت ... </p>
|
||||
<p style=";text-align:right;direction:rtl"> البعض: تخفيض السعر، قذيفة، مزود، لوا، أكس، YAML ... </p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="intro-right" style=";text-align:right;direction:rtl">
|
||||
<div class="tips green" style=";text-align:right;direction:rtl">
|
||||
<h1 style=";text-align:right;direction:rtl"> <span>عمل اختصار</span> </h1>
|
||||
<pre style=";text-align:right;direction:rtl"> الاختصارات المستخدمة شيوعا:
|
||||
CTRL + S لحفظ
|
||||
+ السيطرة على اختيار كل CTRL + X قص
|
||||
CTRL + C CTRL + V لصق نسخة
|
||||
CTRL + Z التراجع عن التراجع عن مكافحة CTRL + Y
|
||||
CTRL + F للبحث عن استبدال CTRL + و + و
|
||||
فوز + ALT + 0 انهيار كل فوز + Alt + العالي + 0 توسيع جميع
|
||||
ESC [بحث الخروج تلقائيا إلغاء يطالب ...]
|
||||
السيطرة التحول ليالي معاينة
|
||||
السيطرة التحول الإلكتروني تظهر وإغلاق وظيفة
|
||||
</pre>
|
||||
<pre style=";text-align:right;direction:rtl"> اختيار:
|
||||
سرادق الماوس - السحب
|
||||
تحول + الوطن / نهاية / أعلى / يسار / أسفل / الحق
|
||||
تحول + PAGEUP / بين pagedown الوجه صعودا وهبوطا لتحديد
|
||||
السيطرة تحول + + الوطن / نهاية المؤشر الحالي إلى بداية ونهاية
|
||||
ALT + الماوس لسحب اختيار كتلة
|
||||
CTRL + ALT + ز دفعة حدد وأدخل محرر متعدد التبويب الحالي
|
||||
</pre>
|
||||
<pre style=";text-align:right;direction:rtl"> المؤشر:
|
||||
الوطن / نهاية / أعلى / يسار / أسفل / الحق
|
||||
CTRL + الوطن / نهاية تحريك المؤشر إلى الوثيقة رأس / ذيل
|
||||
CTRL + ص الانتقال إلى العلامة مطابقة
|
||||
PAGEUP / بين pagedown المؤشر صعودا وهبوطا
|
||||
ALT + المؤشر الأيسر / الأيمن للانتقال إلى أعلى من خط
|
||||
تحول + المؤشر الأيسر / الأيمن إلى نهاية السطر و
|
||||
السيطرة + لتر إلى القفز إلى صف معين
|
||||
CTRL + ALT + لأعلى / أسفل (أدناه) زيادة المؤشر
|
||||
</pre>
|
||||
<pre style=";text-align:right;direction:rtl"> تحرير:
|
||||
CTRL + / تعليق والسيطرة غير تعليق + ALT + وبرر
|
||||
علامة التبويب جدول محاذاة التحول + طاولة التقدم الشامل
|
||||
حذف حذف حذف السيطرة خط كامل + د
|
||||
السيطرة + حذف لحذف الصف والكلمة الصحيحة
|
||||
السيطرة / التحول + BACKSPACE لحذف كلمة على اليسار
|
||||
SHIFT + ALT + أعلى / أسفل، وأضاف إلى خط النسخ (أدناه) طائرة
|
||||
ALT + DELETE لحذف محتويات يمين المؤشر
|
||||
بديل + أعلى / أسفل على السطر الحالي والخط (تبادل السطر التالي)
|
||||
CTRL + SHIFT + د صفوف نسخ وإضافة إلى ما يلي
|
||||
السيطرة + حذف لحذف يمين الكلمة
|
||||
السيطرة تحول + + يو تحويلها إلى أحرف صغيرة
|
||||
CTRL + ش النص المحدد إلى أحرف كبيرة
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<div class="box" style=";text-align:right;direction:rtl">
|
||||
<div class="title" style=";text-align:right;direction:rtl"> <span>إدارة ملف</span> </div>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> اختيار ملف: راديو، سرادق الماوس، وتحول الانتخابات، السيطرة اختيارهم عشوائيا، لوحة المفاتيح صعودا وهبوطا، المنزل، واختيار نهاية. </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-folder-open"></i> تشغيل ملف: بعد اختيار الملف، يمكنك نسخ، قص، حذف، عرض خصائص ضغط، إعادة تسمية، ومعاينة المفتوحة وغيرها من العمليات ...... </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-cloud-upload"></i> تحميل الملف: تحميل ملفات متعددة دفعة، HTML5 تحميل السحب (سحب للتحميل بسهولة النافذة، سحب وإسقاط الدعم للمجلدات) </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-cogs"></i> وظيفة الصحيحة: بزر الماوس الأيمن ملف أو مجلد، الحق، الحق أكثر بعد العملية الانتخابية، سطح المكتب، والحق، والحق شجرة الدليل، اختصارات القائمة ملزمة اليمين <br/>
|
||||
(حدد الكل - نسخ - قص - لصق - حذف - إعادة تسمية، تعيين ......) </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-sitemap"></i> متصفح ملف: وضع قائمة، وضع رمز، انقر نقرا مزدوجا فوق في مجلدات فرعية، عملية شريط العنوان؛ فتح سجل سجل مجلد مناقضة (إلى الأمام والخلف) </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-move"></i> دعم السحب والإسقاط: تحقق من السحب، وقطع لتحقيق وظيفة المجلد المحدد </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-reply"></i> مفاتيح الاختصار: حذف حذف، CTRL + A تحديد الكل، CTRL + C لنسخ، + X قص، بحث ملف (محتوى البحث) السيطرة </p>
|
||||
</div>
|
||||
<div class="box" style=";text-align:right;direction:rtl">
|
||||
<div class="title" style=";text-align:right;direction:rtl"> <span>معاينة ملف</span> </div>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-edit"></i> معاينة الملف: عرض محتويات ملف تحرير النص والادخار، أتش تي أم أل، معاينة ملف فرنك سويسري، </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-picture"></i> معاينة الصورة: الجيل التلقائي للصور المصغرة، صورة عرض الشرائح. </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-music"></i> تشغيل الصوت: تشغيل الموسيقى على الانترنت وملفات الفيديو؛ دعم MP3، WMA، منتصف، AAC، WAV، MP4، </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-play"></i> فيديو: تشغيل الفيديو عبر الإنترنت، الصيغ المدعومة: FLV، F4V، 3GP </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-play"></i> المكتب: مكتب معاينة الانترنت، الصيغ المدعومة: وثيقة، docx، باور بوينت، PPTX، XLS، XLSX </p>
|
||||
</div>
|
||||
<div class="box" style=";text-align:right;direction:rtl">
|
||||
<div class="title" style=";text-align:right;direction:rtl"> <span>الاختصارات</span> </div>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> إدخال المفتوحة </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> + السيطرة مختارة جميع </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> CTRL + C لنسخ المحدد </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> CTRL + V للصق </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> CTRL + X قص </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> CTRL + F للبحث في الدليل الحالي </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> بديل + ن ملف جديد </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> ALT + م مجلد جديد </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> حذف حذف المحدد </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> مسافة للخلف العودة </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> CTRL + مسافة للخلف إلى الأمام </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> F2 إعادة تسمية مختارة (مجلد) </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> الوطن / نهاية / أعلى / أسفل / يسار / يمين لتحديد الملف </p>
|
||||
<p style=";text-align:right;direction:rtl"><i class="icon-tags"></i> لرد ضغط تحقق للضغط على الحرف الأول من الملفات الشخصية والمجلدات المحددة دورة التلقائي </p>
|
||||
</div>
|
||||
@@ -0,0 +1,804 @@
|
||||
<?php
|
||||
return array(
|
||||
"path_api_select_file" => "يرجى اختيار ملف ...",
|
||||
"path_api_select_folder" => "الرجاء تحديد مجلد ...",
|
||||
"path_api_select_image" => "يرجى اختيار صورة ...",
|
||||
"share_can_upload" => "السماح بالتحميل",
|
||||
"move_error" => "فشل نقل",
|
||||
"setting_basic" => "الإعدادات الأساسية",
|
||||
"setting_user_sound_open" => "فتح الصوت",
|
||||
"setting_user_animate_open" => "فتح الرسوم المتحركة",
|
||||
"recycle_open_if" => "فتح سلة المحذوفات",
|
||||
"recycle_open" => "فتح",
|
||||
"setting_user_recycle_desc" => "بعد حذف سيتم حذف الحذف المادي مباشرة",
|
||||
"setting_user_animate_desc" => "نافذة مفتوحة والرسوم المتحركة الأخرى",
|
||||
"setting_user_sound_desc" => "تشغيل الصوت",
|
||||
"setting_user_imageThumb" => "الصور المصغرة",
|
||||
"setting_user_imageThumb_desc" => "تجربة تصفح أفضل بعد الفتح",
|
||||
"setting_user_fileSelect" => "فتح الاختيار رمز الملف",
|
||||
"setting_user_fileSelect_desc" => "رمز الملف الاختيار مفتاح اليسار، انقر بزر الماوس الأيمن فوق القائمة اختصار الإدخال",
|
||||
"qrcode" => "URL رمز الاستجابة السريعة",
|
||||
"theme_mac" => "ماك الأبيض الحد الأدنى",
|
||||
"theme_win7" => "Windows 7",
|
||||
"theme_win10" => "Windows 10",
|
||||
"theme_metro" => "المترو الأزرق كلاسيك",
|
||||
"theme_metro_green" => "مترو الضوء الأخضر",
|
||||
"theme_metro_purple" => "مترو أنيقة الأرجواني",
|
||||
"theme_metro_pink" => "مترو روز",
|
||||
"theme_metro_orange" => "مترو برتقالية زاهية",
|
||||
"theme_alpha_image" => "مشرق - الطيران",
|
||||
"theme_alpha_image_sun" => "مشرق - الغروب",
|
||||
"theme_alpha_image_sky" => "سمفونية - السماء الزرقاء",
|
||||
"theme_diy" => "<b>مخصص</b>",
|
||||
"theme_diy_title" => "إعدادات مخصصة لقضاء وقت الفراغ",
|
||||
"theme_diy_background" => "خلفية",
|
||||
"theme_diy_image" => "صور",
|
||||
"theme_diy_color_blur" => "التدرج اللوني",
|
||||
"theme_diy_image_blur" => "الصورة ضبابية",
|
||||
"theme_diy_image_url" => "عنوان صور",
|
||||
"theme_diy_color_start" => "اللون ابتداء من",
|
||||
"theme_diy_color_end" => "نهاية اللون",
|
||||
"theme_diy_color_radius" => "زاوية الانحدار",
|
||||
"system_role_admin_set" => "الإداريين من جميع الحقوق، دون أن يحدد!",
|
||||
"login_error_user_not_use" => "تم تعطيل المستخدم! الرجاء الاتصال بمسؤول",
|
||||
"login_error_kod_version" => "الصراع نسخة",
|
||||
"login_error_role" => "لا وجود مجموعة عرض أذونات، يرجى الاتصال بمسؤول",
|
||||
"no_permission_group" => "أنت لست في هذه المجموعة!",
|
||||
"no_permission_write" => "الدليل لايوجد إذن الكتابة",
|
||||
"user" => "المستخدم",
|
||||
"save_as" => "حفظ ك",
|
||||
"check_update" => "تحديث",
|
||||
"keyboard_type" => "وضع لوحة المفاتيح",
|
||||
"font_family" => "الخطوط",
|
||||
"code_mode" => "تسليط الضوء على تركيب",
|
||||
"path_can_not_share" => "يدعم فقط مشاركة المستندات الخاصة بك!",
|
||||
"path_can_not_action" => "هذا الدليل لا يدعم هذه العملية!",
|
||||
"wap_page_pc" => "نسخة الكمبيوتر",
|
||||
"wap_page_phone" => "متحرك",
|
||||
"image_size" => "أبعاد الصورة",
|
||||
"no_permission_action" => "لم يكن لديك هذا الإذن، يرجى الاتصال بمسؤول!",
|
||||
"path_is_root_tips" => "قد حان إلى الدليل الجذر!",
|
||||
"kod_group" => "منظمة",
|
||||
"my_kod_group" => "أنا في القسم",
|
||||
"space_tips_default" => "(GB) 0 لا حدود",
|
||||
"space_tips_full" => "دون الحد",
|
||||
"space_size" => "الفضاء",
|
||||
"space_size_use" => "استخدام الفضاء",
|
||||
"space_is_full" => "لا توجد مساحة كافية متبقية ، يرجى الاتصال بالمسؤول!",
|
||||
"system_open_true_path" => "افتتح بنجاح في إدارة ملف!",
|
||||
"group_role_error" => "خطأ أذونات دور (أي إعدادات إذن)",
|
||||
"group_role_error_admin" => "أذونات غير كافية",
|
||||
"markdown_content" => "جدول المحتويات",
|
||||
"system_group" => "المستخدمين والإدارات",
|
||||
"system_group_edit" => "إدارة القسم",
|
||||
"system_group_role" => "هوية دور",
|
||||
"system_group_create" => "إدارة جديدة",
|
||||
"system_group_name" => "اسم القسم",
|
||||
"system_group_father" => "الإدارة العليا",
|
||||
"system_group_add" => "إضافة إدارة فرعية",
|
||||
"system_group_remove" => "إزالة القسم",
|
||||
"system_group_remove_tips" => "هل تريد بالتأكيد حذف القسم؟<br/>بعد حذف جزء من المستخدم سيتم إزالة، انتقل القطاع الفرعي إلى قطاع الجذر",
|
||||
"system_group_select" => "اختر قسم",
|
||||
"system_group_select_result" => "سوف الأعضاء تنتمي إلى القطاعات التالية",
|
||||
"system_role_admin_tips" => "ملاحظات: غير مصرح لمسؤولي النظام للتحكم",
|
||||
"system_member_action" => "إدارة المستخدم",
|
||||
"system_member_add" => "العضو الجديد",
|
||||
"system_member_role" => "أدوار إذن",
|
||||
"system_member_role_select" => "اختر",
|
||||
"system_member_password_tips" => "لا تملأ لا تعديل",
|
||||
"system_set_home_path" => "كتالوج مخصص",
|
||||
"system_set_home_path_tips" => "الدليل الافتراضي فارغ",
|
||||
"system_member_group" => "حيث الإدارة",
|
||||
"system_member_group_edit" => "قسم التحرير",
|
||||
"system_member_remove" => "حذف العضو",
|
||||
"system_member_remove_tips" => "تأكيد المستخدم حذف؟<br/>بعد إزالة دليل المستخدم سوف تمحى تماما",
|
||||
"system_member_set_role" => "لتأكيد التغيير من الأذونات مجموعة مختارة من المستخدمين؟",
|
||||
"system_member_remove_group" => "تحديد ستتم إزالة المستخدم المحدد من هذه المجموعة؟",
|
||||
"system_member_import" => "إضافة السائبة",
|
||||
"system_member_import_desc" => "مستخدم واحد في كل سطر،<br/>بالفعل موجودة يتم تجاهل بصمت",
|
||||
"system_member_use" => "تمكين",
|
||||
"system_member_unuse" => "تعطيل",
|
||||
"system_member_space" => "تعيين حجم مساحة المستخدم ",
|
||||
"system_member_space_tips" => " تعيين حجم مساحة المستخدم ",
|
||||
"system_member_space_number" => " يجب ان يكون رقم!",
|
||||
"system_member_group_config" => "دفعة إدارة الإعداد",
|
||||
"system_member_group_remove" => "تمت إزالتها من القسم",
|
||||
"system_member_group_insert" => "أضف إلى القسم",
|
||||
"system_member_group_reset" => "إعادة تعيين القسم",
|
||||
"system_member_group_error" => "خطأ في الإدارة",
|
||||
"system_group_action" => "إدارة القسم",
|
||||
"system_role_add" => "إضافة الهوية دور",
|
||||
"system_role_read" => "قراءة فقط",
|
||||
"system_role_write" => "يمكن القراءة والكتابة",
|
||||
"system_setting_root_path" => "وصول الجذر",
|
||||
"system_setting_root_path_desc" => "مسؤول النظام فقط يمكن الوصول إلى كافة الدلائل، يمكن للجماعات حقوقية أخرى من المستخدمين ترى سوى دليل المستخدم الخاص بهم. إذا كنت ترغب في تشغيل أو إيقاف وصول المسؤول<br/>إلى الدلائل الأخرى، يمكنك تعديل فب open_basedir المعلمات مكافحة المواقع المشتركة،<a href=\"https://www.google.com.hk/search?&q=php+open_basedir\" target=\"_ | ||||