Compare commits
2 Commits
zentaopms_
...
zentaopms_
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
befa7343c7 | ||
|
|
d6d2087d65 |
9
.gitignore
vendored
@@ -1,9 +0,0 @@
|
||||
config/my.php
|
||||
www/data/
|
||||
release/*
|
||||
tmp/extensions/*
|
||||
tmp/log/*
|
||||
tmp/model/*
|
||||
tmp/cache/*
|
||||
tmp/extension/*
|
||||
.gitkeep
|
||||
76
Makefile
@@ -1,17 +1,16 @@
|
||||
VERSION=$(shell head -n 1 VERSION)
|
||||
|
||||
all: prepare pms
|
||||
all: tgz
|
||||
linux: tgz build4linux
|
||||
|
||||
clean:
|
||||
rm -fr zentaopms
|
||||
rm -fr zentaostory
|
||||
rm -fr zentaotask
|
||||
rm -fr zentaotest
|
||||
rm -fr *.tar.gz
|
||||
rm -fr *.zip
|
||||
rm -fr api*
|
||||
rm -fr build/linux/lampp
|
||||
rm -fr lampp
|
||||
prepare:
|
||||
tgz:
|
||||
mkdir zentaopms
|
||||
cp -fr bin zentaopms/
|
||||
cp -fr config zentaopms/ && rm -fr zentaopms/config/my.php
|
||||
@@ -28,12 +27,13 @@ prepare:
|
||||
rm -fr zentaopms/tmp/model/*
|
||||
cp VERSION zentaopms/
|
||||
# combine js and css files.
|
||||
cp -fr tools zentaopms/tools && cd zentaopms/tools/ && php ./minifyfront.php
|
||||
rm -fr zentaopms/tools
|
||||
mkdir -p zentaopms/build/tools && cp build/tools/minifyfront.php zentaopms/build/tools/
|
||||
cd zentaopms/build/tools/ && php ./minifyfront.php
|
||||
rm -fr zentaopms/build
|
||||
# create the restart file for svn.
|
||||
# touch zentaopms/module/svn/restart
|
||||
# delee the unused files.
|
||||
find zentaopms -name .gitkeep |xargs rm -fr
|
||||
find zentaopms -name .svn |xargs rm -fr
|
||||
find zentaopms -name tests |xargs rm -fr
|
||||
# notify.zip.
|
||||
mkdir zentaopms/www/data/notify/
|
||||
@@ -45,42 +45,18 @@ prepare:
|
||||
chmod 777 zentaopms/module
|
||||
chmod a+rx zentaopms/bin/*
|
||||
find zentaopms/ -name ext |xargs chmod -R 777
|
||||
pms:
|
||||
echo full > zentaopms/.flow
|
||||
# add zentaotest zentaotask zentaostory extension.
|
||||
svn export https://svn.cnezsoft.com/easysoft/trunk/zentaoext/zentaotest
|
||||
svn export https://svn.cnezsoft.com/easysoft/trunk/zentaoext/zentaotask
|
||||
svn export https://svn.cnezsoft.com/easysoft/trunk/zentaoext/zentaostory
|
||||
zip -rm -9 zentaotest.zip zentaotest
|
||||
zip -rm -9 zentaotask.zip zentaotask
|
||||
zip -rm -9 zentaostory.zip zentaostory
|
||||
mv zentaotest.zip zentaopms/tmp/extension
|
||||
mv zentaostory.zip zentaopms/tmp/extension
|
||||
mv zentaotask.zip zentaopms/tmp/extension
|
||||
# zip it.
|
||||
zip -r -9 ZenTaoPMS.$(VERSION).zip zentaopms
|
||||
zstory:
|
||||
cp -frp zentaopms zentaostory
|
||||
svn export https://svn.cnezsoft.com/easysoft/trunk/zentaoext/zentaostory storyext
|
||||
cp -fr storyext/module/* zentaostory/module/
|
||||
find zentaostory/ -name ext |xargs chmod -R 777
|
||||
echo zentaostory > zentaostory/.flow
|
||||
sed -e 's/zentao/story/g' zentaostory/www/.ztaccess > .ztaccess.bak
|
||||
mv .ztaccess.bak zentaostory/www/.ztaccess
|
||||
zip -r -9 ZenTaoStory.$(VERSION).zip zentaostory
|
||||
rm -fr storyext
|
||||
rm -fr zentaostory
|
||||
ztask:
|
||||
cp -frp zentaopms zentaotask
|
||||
svn export https://svn.cnezsoft.com/easysoft/trunk/zentaoext/zentaotask taskext
|
||||
cp -fr taskext/module/* zentaotask/module/
|
||||
find zentaotask/ -name ext |xargs chmod -R 777
|
||||
echo zentaotask > zentaotask/.flow
|
||||
sed -e 's/zentao/task/g' zentaotask/www/.ztaccess > .ztaccess.bak
|
||||
mv .ztaccess.bak zentaotask/www/.ztaccess
|
||||
zip -r -9 ZenTaoTask.$(VERSION).zip zentaotask
|
||||
rm -fr taskext
|
||||
rm -fr zentaotask
|
||||
ztest:
|
||||
cp -frp zentaopms zentaotest
|
||||
svn export https://svn.cnezsoft.com/easysoft/trunk/zentaoext/zentaotest testext
|
||||
cp -fr testext/module/* zentaotest/module/
|
||||
find zentaotest/ -name ext |xargs chmod -R 777
|
||||
echo zentaotest > zentaotest/.flow
|
||||
sed -e 's/zentao/test/g' zentaotest/www/.ztaccess > .ztaccess.bak
|
||||
mv .ztaccess.bak zentaotest/www/.ztaccess
|
||||
zip -r -9 ZenTaoTest.$(VERSION).zip zentaotest
|
||||
rm -fr testext
|
||||
rm -fr zentaotest
|
||||
rm -fr zentaopms
|
||||
patchphpdoc:
|
||||
sudo cp misc/doc/phpdoc/*.tpl /usr/share/php/data/PhpDocumentor/phpDocumentor/Converters/HTML/frames/templates/phphtmllib/templates/
|
||||
@@ -89,3 +65,17 @@ phpdoc:
|
||||
phpdoc -d bin,framework,config,lib,module,www -t api.chm -o chm:default:default -ti ZenTaoPMSAPI<50>ο<EFBFBD><CEBF>ֲ<EFBFBD> -s on -pp on -i *test*
|
||||
doxygen:
|
||||
doxygen doc/doxygen/doxygen.conf
|
||||
build4linux:
|
||||
unzip ZenTaoPMS.$(VERSION).zip
|
||||
rm -fr ZenTaoPMS.$(VERSION).zip
|
||||
# build xmapp.
|
||||
cd ./build/linux/ && ./buildxmapp.sh $(xampp)
|
||||
mv ./build/linux/lampp ./
|
||||
saas:
|
||||
mkdir backup
|
||||
mkdir tmp/model
|
||||
mkdir tmp/extension
|
||||
mkdir www/data/upload -p
|
||||
chmod 777 backup
|
||||
chmod 777 -R tmp
|
||||
chmod 777 -R www/data
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
欢迎访问<a href='http://www.zentao.net' target='_blank'>禅道项目管理软件</a>主站,获得最新动态和文档支持。
|
||||
BIN
app/corona/Icon-72.png
Normal file
|
After Width: | Height: | Size: 8.1 KiB |
BIN
app/corona/Icon-hdpi.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
app/corona/Icon-ldpi.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
app/corona/Icon-mdpi.png
Normal file
|
After Width: | Height: | Size: 7.5 KiB |
BIN
app/corona/Icon.png
Normal file
|
After Width: | Height: | Size: 5.8 KiB |
BIN
app/corona/Icon@2x.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
BIN
app/corona/Thumbs.db
Normal file
103
app/corona/autoLogin.lua
Normal file
@@ -0,0 +1,103 @@
|
||||
|
||||
local storyboard = require( "storyboard" )
|
||||
local scene = storyboard.newScene()
|
||||
|
||||
loginAPI = ""
|
||||
sessionAPI = ""
|
||||
myTodoAPI = ""
|
||||
myBugAPI = ""
|
||||
myTaskAPI = ""
|
||||
|
||||
config = {}
|
||||
session = {}
|
||||
|
||||
function autoLogin()
|
||||
local response = {}
|
||||
-- 获取config
|
||||
local result = http.request {url = configAPI, method = "GET", sink = ltn12.sink.table(response) }
|
||||
|
||||
if table.getn(response) == 0 then
|
||||
native.showAlert("提示", "网络错误,请查看网络或重新设置!", {"我知道了"} )
|
||||
else
|
||||
for i, val in pairs(response) do
|
||||
config = json.decode(val)
|
||||
end
|
||||
|
||||
-- 设置API地址
|
||||
if config.requestType == "GET" then
|
||||
loginAPI = zentaoRoot .. "?m=user&f=login"
|
||||
sessionAPI = zentaoRoot .. "?m=api&f=getSessionID&t=json"
|
||||
|
||||
myTodoAPI = zentaoRoot .. "?m=my&f=todo&t=json"
|
||||
myTaskAPI = zentaoRoot .. "?m=my&f=task&t=json"
|
||||
myBugAPI = zentaoRoot .. "?m=my&f=bug&t=json"
|
||||
elseif config.requestType == "PATH_INFO" then
|
||||
loginAPI = zentaoRoot .. "user-login.json?a=1"
|
||||
sessionAPI = zentaoRoot .. "api-getsessionid.json?a=1"
|
||||
|
||||
myTodoAPI = zentaoRoot .. "my-todo.json?a=1"
|
||||
myTaskAPI = zentaoRoot .. "my-task.json?a=1"
|
||||
myBugAPI = zentaoRoot .. "my-bug.json?a=1"
|
||||
end
|
||||
|
||||
-- 获取session
|
||||
http.request{url = sessionAPI, method = "GET", sink = ltn12.sink.table(session)}
|
||||
|
||||
if table.getn(session) == 0 then
|
||||
native.showAlert("提示", "网络错误,请查看网络或重新设置!", {"我知道了"} )
|
||||
else
|
||||
session = json.decode(table.concat(session))
|
||||
session.data = json.decode(session.data)
|
||||
|
||||
-- 用户登录
|
||||
local response2 = {}
|
||||
|
||||
mixPassword = crypto.digest(crypto.md5, md5Password .. session.data.rand)
|
||||
loginAPI = loginAPI .. "&account=" .. account .. "&password=" .. mixPassword .. "&" .. session.data.sessionName .. "=" .. session.data.sessionID
|
||||
http.request{url = loginAPI, method = "GET", sink = ltn12.sink.table(response2) }
|
||||
|
||||
if json.decode(table.concat(response2)).status == "failed" then
|
||||
native.showAlert("登录失败", "网络问题,或用户信息设置错误!", {"我知道了"})
|
||||
else
|
||||
storyboard.gotoScene(true, "index", "slideLeft", 100)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Called when the scene's view does not exist:
|
||||
function scene:createScene( event )
|
||||
local screenGroup = self.view
|
||||
|
||||
zentaoImg = display.newImage("zentao.png")
|
||||
zentaoImg.xOrigin = display.contentWidth/2
|
||||
zentaoImg.yOrigin = display.contentHeight/2
|
||||
screenGroup:insert(zentaoImg)
|
||||
|
||||
end
|
||||
|
||||
-- Called immediately after scene has moved onscreen:
|
||||
function scene:enterScene( event )
|
||||
timer.performWithDelay(2000, autoLogin)
|
||||
end
|
||||
|
||||
-- Called when scene is about to move offscreen:
|
||||
function scene:exitScene( event )
|
||||
local group = self.view
|
||||
end
|
||||
|
||||
-- Called prior to the removal of scene's "view" (display group)
|
||||
function scene:destroyScene( event )
|
||||
local group = self.view
|
||||
end
|
||||
|
||||
scene:addEventListener( "createScene", scene )
|
||||
scene:addEventListener( "enterScene", scene )
|
||||
scene:addEventListener( "exitScene", scene )
|
||||
scene:addEventListener( "destroyScene", scene )
|
||||
|
||||
return scene
|
||||
|
||||
BIN
app/corona/backButton.png
Normal file
|
After Width: | Height: | Size: 3.2 KiB |
BIN
app/corona/backButton_over.png
Normal file
|
After Width: | Height: | Size: 3.6 KiB |
BIN
app/corona/background.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
15
app/corona/build.settings
Normal file
@@ -0,0 +1,15 @@
|
||||
settings =
|
||||
{
|
||||
iphone =
|
||||
{
|
||||
plist =
|
||||
{
|
||||
CFBundleIconFile = "Icon.png",
|
||||
CFBundleIconFiles = {
|
||||
"Icon.png",
|
||||
"Icon@2x.png",
|
||||
"Icon-72.png",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
BIN
app/corona/button.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/corona/button_over.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
12
app/corona/config.lua
Normal file
@@ -0,0 +1,12 @@
|
||||
-- config.lua
|
||||
|
||||
application =
|
||||
{
|
||||
content =
|
||||
{
|
||||
width = 320,
|
||||
height = 480,
|
||||
scale = "letterbox"
|
||||
|
||||
},
|
||||
}
|
||||
806
app/corona/dkjson.lua
Normal file
@@ -0,0 +1,806 @@
|
||||
--[==[
|
||||
|
||||
David Kolf's JSON module for Lua 5.1/5.2
|
||||
========================================
|
||||
|
||||
*Version 2.1*
|
||||
|
||||
This module writes no global values, not even the module table.
|
||||
Import it using
|
||||
|
||||
json = require ("dkjson")
|
||||
|
||||
Exported functions and values:
|
||||
|
||||
`json.encode (object [, state])`
|
||||
--------------------------------
|
||||
|
||||
Create a string representing the object. `Object` can be a table,
|
||||
a string, a number, a boolean, `nil`, `json.null` or any object with
|
||||
a function `__tojson` in its metatable. A table can only use strings
|
||||
and numbers as keys and its values have to be valid objects as
|
||||
well. It raises an error for any invalid data types or reference
|
||||
cycles.
|
||||
|
||||
`state` is an optional table with the following fields:
|
||||
|
||||
- `indent`
|
||||
When `indent` (a boolean) is set, the created string will contain
|
||||
newlines and indentations. Otherwise it will be one long line.
|
||||
- `keyorder`
|
||||
`keyorder` is an array to specify the ordering of keys in the
|
||||
encoded output. If an object has keys which are not in this array
|
||||
they are written after the sorted keys.
|
||||
- `level`
|
||||
This is the initial level of indentation used when `indent` is
|
||||
set. For each level two spaces are added. When absent it is set
|
||||
to 0.
|
||||
- `buffer`
|
||||
`buffer` is an array to store the strings for the result so they
|
||||
can be concatenated at once. When it isn't given, the encode
|
||||
function will create it temporary and will return the
|
||||
concatenated result.
|
||||
- `bufferlen`
|
||||
When `bufferlen` is set, it has to be the index of the last
|
||||
element of `buffer`.
|
||||
- `tables`
|
||||
`tables` is a set to detect reference cycles. It is created
|
||||
temporary when absent. Every table that is currently processed
|
||||
is used as key, the value is `true`.
|
||||
|
||||
When `state.buffer` was set, the return value will be `true` on
|
||||
success. Without `state.buffer` the return value will be a string.
|
||||
|
||||
`json.decode (string [, position [, null]])`
|
||||
--------------------------------------------
|
||||
|
||||
Decode `string` starting at `position` or at 1 if `position` was
|
||||
omitted.
|
||||
|
||||
`null` is an optional value to be returned for null values. The
|
||||
default is `nil`, but you could set it to `json.null` or any other
|
||||
value.
|
||||
|
||||
The return values are the object or `nil`, the position of the next
|
||||
character that doesn't belong to the object, and in case of errors
|
||||
an error message.
|
||||
|
||||
Two metatables are created. Every array or object that is decoded gets
|
||||
a metatable with the `__jsontype` field set to either `array` or
|
||||
`object`. If you want to provide your own metatables use the syntax
|
||||
|
||||
json.decode (string, position, null, objectmeta, arraymeta)
|
||||
|
||||
`<metatable>.__jsonorder`
|
||||
-------------------------
|
||||
|
||||
`__jsonorder` can overwrite the `keyorder` for a specific table.
|
||||
|
||||
`<metatable>.__jsontype`
|
||||
------------------------
|
||||
|
||||
`__jsontype` can be either `"array"` or `"object"`. This is mainly useful
|
||||
for tables that can be empty. (The default for empty tables is
|
||||
`"array"`).
|
||||
|
||||
`<metatable>.__tojson (self, state)`
|
||||
------------------------------------
|
||||
|
||||
You can provide your own `__tojson` function in a metatable. In this
|
||||
function you can either add directly to the buffer and return true,
|
||||
or you can return a string. On errors nil and a message should be
|
||||
returned.
|
||||
|
||||
`json.null`
|
||||
-----------
|
||||
|
||||
You can use this value for setting explicit `null` values.
|
||||
|
||||
`json.version`
|
||||
--------------
|
||||
|
||||
Set to `"dkjson 2.1"`.
|
||||
|
||||
`json.quotestring (string)`
|
||||
---------------------------
|
||||
|
||||
Quote a UTF-8 string and escape critical characters using JSON
|
||||
escape sequences. This function is only necessary when you build
|
||||
your own `__tojson` functions.
|
||||
|
||||
`json.addnewline (state)`
|
||||
-------------------------
|
||||
|
||||
When `state.indent` is set, add a newline to `state.buffer` and spaces
|
||||
according to `state.level`.
|
||||
|
||||
LPeg support
|
||||
------------
|
||||
|
||||
When the local configuration variable
|
||||
`always_try_using_lpeg` is set, this module tries to load LPeg to
|
||||
replace the functions `quotestring` and `decode`. The speed increase
|
||||
is significant. You can get the LPeg module at
|
||||
<http://www.inf.puc-rio.br/~roberto/lpeg/>.
|
||||
When LPeg couldn't be loaded, the pure Lua functions stay active.
|
||||
|
||||
In case you don't want this module to require LPeg on its own,
|
||||
disable this option:
|
||||
|
||||
--]==]
|
||||
local always_try_using_lpeg = true
|
||||
--[==[
|
||||
|
||||
In this case you can later load LPeg support using
|
||||
|
||||
### `json.use_lpeg ()`
|
||||
|
||||
Require the LPeg module and replace the functions `quotestring` and
|
||||
and `decode` with functions that use LPeg patterns.
|
||||
This function returns the module table, so you can load the module
|
||||
using:
|
||||
|
||||
json = require "dkjson".use_lpeg()
|
||||
|
||||
Alternatively you can use `pcall` so the JSON module still works when
|
||||
LPeg isn't found.
|
||||
|
||||
json = require "dkjson"
|
||||
pcall (json.use_lpeg)
|
||||
|
||||
### `json.using_lpeg`
|
||||
|
||||
This variable is set to `true` when LPeg was loaded successfully.
|
||||
|
||||
You can contact the author by sending an e-mail to 'kolf' at the
|
||||
e-mail provider 'gmx.de'.
|
||||
|
||||
---------------------------------------------------------------------
|
||||
|
||||
*Copyright (C) 2010, 2011 David Heiko Kolf*
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
<!-- This documentation can be parsed using Markdown to generate HTML.
|
||||
The source code is enclosed in a HTML comment so it won't be displayed
|
||||
by browsers, but it should be removed from the final HTML file as
|
||||
it isn't a valid HTML comment (and wastes space).
|
||||
-->
|
||||
|
||||
<!--]==]
|
||||
|
||||
-- global dependencies:
|
||||
local pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset =
|
||||
pairs, type, tostring, tonumber, getmetatable, setmetatable, rawset
|
||||
local error, require, pcall = error, require, pcall
|
||||
local floor, huge = math.floor, math.huge
|
||||
local strrep, gsub, strsub, strbyte, strchar, strfind, strlen, strformat =
|
||||
string.rep, string.gsub, string.sub, string.byte, string.char,
|
||||
string.find, string.len, string.format
|
||||
local concat = table.concat
|
||||
|
||||
if _VERSION == 'Lua 5.1' then
|
||||
local function noglobals (s,k,v) error ("global access: " .. k, 2) end
|
||||
setfenv (1, setmetatable ({}, { __index = noglobals, __newindex = noglobals }))
|
||||
end
|
||||
local _ENV = nil -- blocking globals in Lua 5.2
|
||||
|
||||
local json = { version = "dkjson 2.1" }
|
||||
|
||||
pcall (function()
|
||||
-- Enable access to blocked metatables.
|
||||
-- Don't worry, this module doesn't change anything in them.
|
||||
local debmeta = require "debug".getmetatable
|
||||
if debmeta then getmetatable = debmeta end
|
||||
end)
|
||||
|
||||
json.null = setmetatable ({}, {
|
||||
__tojson = function () return "null" end
|
||||
})
|
||||
|
||||
local function isarray (tbl)
|
||||
local max, n, arraylen = 0, 0, 0
|
||||
for k,v in pairs (tbl) do
|
||||
if k == 'n' and type(v) == 'number' then
|
||||
arraylen = v
|
||||
if v > max then
|
||||
max = v
|
||||
end
|
||||
else
|
||||
if type(k) ~= 'number' or k < 1 or floor(k) ~= k then
|
||||
return false
|
||||
end
|
||||
if k > max then
|
||||
max = k
|
||||
end
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
if max > 10 and max > arraylen and max > n * 2 then
|
||||
return false -- don't create an array with too many holes
|
||||
end
|
||||
return true, max
|
||||
end
|
||||
|
||||
local escapecodes = {
|
||||
["\""] = "\\\"", ["\\"] = "\\\\", ["\b"] = "\\b", ["\f"] = "\\f",
|
||||
["\n"] = "\\n", ["\r"] = "\\r", ["\t"] = "\\t"
|
||||
}
|
||||
|
||||
local function escapeutf8 (uchar)
|
||||
local value = escapecodes[uchar]
|
||||
if value then
|
||||
return value
|
||||
end
|
||||
local a, b, c, d = strbyte (uchar, 1, 4)
|
||||
a, b, c, d = a or 0, b or 0, c or 0, d or 0
|
||||
if a <= 0x7f then
|
||||
value = a
|
||||
elseif 0xc0 <= a and a <= 0xdf and b >= 0x80 then
|
||||
value = (a - 0xc0) * 0x40 + b - 0x80
|
||||
elseif 0xe0 <= a and a <= 0xef and b >= 0x80 and c >= 0x80 then
|
||||
value = ((a - 0xe0) * 0x40 + b - 0x80) * 0x40 + c - 0x80
|
||||
elseif 0xf0 <= a and a <= 0xf7 and b >= 0x80 and c >= 0x80 and d >= 0x80 then
|
||||
value = (((a - 0xf0) * 0x40 + b - 0x80) * 0x40 + c - 0x80) * 0x40 + d - 0x80
|
||||
else
|
||||
return ""
|
||||
end
|
||||
if value <= 0xffff then
|
||||
return strformat ("\\u%.4x", value)
|
||||
elseif value <= 0x10ffff then
|
||||
-- encode as UTF-16 surrogate pair
|
||||
value = value - 0x10000
|
||||
local highsur, lowsur = 0xD800 + floor (value/0x400), 0xDC00 + (value % 0x400)
|
||||
return strformat ("\\u%.4x\\u%.4x", highsur, lowsur)
|
||||
else
|
||||
return ""
|
||||
end
|
||||
end
|
||||
|
||||
local function fsub (str, pattern, repl)
|
||||
-- gsub always builds a new string in a buffer, even when no match
|
||||
-- exists. First using find should be more efficient when most strings
|
||||
-- don't contain the pattern.
|
||||
if strfind (str, pattern) then
|
||||
return gsub (str, pattern, repl)
|
||||
else
|
||||
return str
|
||||
end
|
||||
end
|
||||
|
||||
local function quotestring (value)
|
||||
-- based on the regexp "escapable" in https://github.com/douglascrockford/JSON-js
|
||||
value = fsub (value, "[%z\1-\31\"\\\127]", escapeutf8)
|
||||
if strfind (value, "[\194\216\220\225\226\239]") then
|
||||
value = fsub (value, "\194[\128-\159\173]", escapeutf8)
|
||||
value = fsub (value, "\216[\128-\132]", escapeutf8)
|
||||
value = fsub (value, "\220\143", escapeutf8)
|
||||
value = fsub (value, "\225\158[\180\181]", escapeutf8)
|
||||
value = fsub (value, "\226\128[\140-\143\168\175]", escapeutf8)
|
||||
value = fsub (value, "\226\129[\160-\175]", escapeutf8)
|
||||
value = fsub (value, "\239\187\191", escapeutf8)
|
||||
value = fsub (value, "\239\191[\176\191]", escapeutf8)
|
||||
end
|
||||
return "\"" .. value .. "\""
|
||||
end
|
||||
json.quotestring = quotestring
|
||||
|
||||
local function addnewline2 (level, buffer, buflen)
|
||||
buffer[buflen+1] = "\n"
|
||||
buffer[buflen+2] = strrep (" ", level)
|
||||
buflen = buflen + 2
|
||||
return buflen
|
||||
end
|
||||
|
||||
function json.addnewline (state)
|
||||
if state.indent then
|
||||
state.bufferlen = addnewline2 (state.level or 0,
|
||||
state.buffer, state.bufferlen or #(state.buffer))
|
||||
end
|
||||
end
|
||||
|
||||
local encode2 -- forward declaration
|
||||
|
||||
local function addpair (key, value, prev, indent, level, buffer, buflen, tables, globalorder)
|
||||
local kt = type (key)
|
||||
if kt ~= 'string' and kt ~= 'number' then
|
||||
return nil, "type '" .. kt .. "' is not supported as a key by JSON."
|
||||
end
|
||||
if prev then
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = ","
|
||||
end
|
||||
if indent then
|
||||
buflen = addnewline2 (level, buffer, buflen)
|
||||
end
|
||||
buffer[buflen+1] = quotestring (key)
|
||||
buffer[buflen+2] = ":"
|
||||
return encode2 (value, indent, level, buffer, buflen + 2, tables, globalorder)
|
||||
end
|
||||
|
||||
encode2 = function (value, indent, level, buffer, buflen, tables, globalorder)
|
||||
local valtype = type (value)
|
||||
local valmeta = getmetatable (value)
|
||||
valmeta = type (valmeta) == 'table' and valmeta -- only tables
|
||||
local valtojson = valmeta and valmeta.__tojson
|
||||
if valtojson then
|
||||
if tables[value] then
|
||||
return nil, "reference cycle"
|
||||
end
|
||||
tables[value] = true
|
||||
local state = {
|
||||
indent = indent, level = level, buffer = buffer,
|
||||
bufferlen = buflen, tables = tables, keyorder = globalorder
|
||||
}
|
||||
local ret, msg = valtojson (value, state)
|
||||
if not ret then return nil, msg end
|
||||
tables[value] = nil
|
||||
buflen = state.bufferlen
|
||||
if type (ret) == 'string' then
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = ret
|
||||
end
|
||||
elseif value == nil then
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = "null"
|
||||
elseif valtype == 'number' then
|
||||
local s
|
||||
if value ~= value or value >= huge or -value >= huge then
|
||||
-- This is the behaviour of the original JSON implementation.
|
||||
s = "null"
|
||||
else
|
||||
s = tostring (value)
|
||||
end
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = s
|
||||
elseif valtype == 'boolean' then
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = value and "true" or "false"
|
||||
elseif valtype == 'string' then
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = quotestring (value)
|
||||
elseif valtype == 'table' then
|
||||
if tables[value] then
|
||||
return nil, "reference cycle"
|
||||
end
|
||||
tables[value] = true
|
||||
level = level + 1
|
||||
local metatype = valmeta and valmeta.__jsontype
|
||||
local isa, n
|
||||
if metatype == 'array' then
|
||||
isa = true
|
||||
n = value.n or #value
|
||||
elseif metatype == 'object' then
|
||||
isa = false
|
||||
else
|
||||
isa, n = isarray (value)
|
||||
end
|
||||
local msg
|
||||
if isa then -- JSON array
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = "["
|
||||
for i = 1, n do
|
||||
buflen, msg = encode2 (value[i], indent, level, buffer, buflen, tables, globalorder)
|
||||
if not buflen then return nil, msg end
|
||||
if i < n then
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = ","
|
||||
end
|
||||
end
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = "]"
|
||||
else -- JSON object
|
||||
local prev = false
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = "{"
|
||||
local order = valmeta and valmeta.__jsonorder or globalorder
|
||||
if order then
|
||||
local used = {}
|
||||
n = #order
|
||||
for i = 1, n do
|
||||
local k = order[i]
|
||||
local v = value[k]
|
||||
if v then
|
||||
used[k] = true
|
||||
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder)
|
||||
prev = true -- add a seperator before the next element
|
||||
end
|
||||
end
|
||||
for k,v in pairs (value) do
|
||||
if not used[k] then
|
||||
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder)
|
||||
if not buflen then return nil, msg end
|
||||
prev = true -- add a seperator before the next element
|
||||
end
|
||||
end
|
||||
else -- unordered
|
||||
for k,v in pairs (value) do
|
||||
buflen, msg = addpair (k, v, prev, indent, level, buffer, buflen, tables, globalorder)
|
||||
if not buflen then return nil, msg end
|
||||
prev = true -- add a seperator before the next element
|
||||
end
|
||||
end
|
||||
if indent then
|
||||
buflen = addnewline2 (level - 1, buffer, buflen)
|
||||
end
|
||||
buflen = buflen + 1
|
||||
buffer[buflen] = "}"
|
||||
end
|
||||
tables[value] = nil
|
||||
else
|
||||
return nil, "type '" .. valtype .. "' is not supported by JSON."
|
||||
end
|
||||
return buflen
|
||||
end
|
||||
|
||||
function json.encode (value, state)
|
||||
state = state or {}
|
||||
local oldbuffer = state.buffer
|
||||
local buffer = oldbuffer or {}
|
||||
local ret, msg = encode2 (value, state.indent, state.level or 0,
|
||||
buffer, state.bufferlen or 0, state.tables or {}, state.keyorder)
|
||||
if not ret then
|
||||
error (msg, 2)
|
||||
elseif oldbuffer then
|
||||
state.bufferlen = ret
|
||||
return true
|
||||
else
|
||||
return concat (buffer)
|
||||
end
|
||||
end
|
||||
|
||||
local function loc (str, where)
|
||||
local line, pos, linepos = 1, 1, 1
|
||||
while true do
|
||||
pos = strfind (str, "\n", pos, true)
|
||||
if pos and pos < where then
|
||||
line = line + 1
|
||||
linepos = pos
|
||||
pos = pos + 1
|
||||
else
|
||||
break
|
||||
end
|
||||
end
|
||||
return "line " .. line .. ", column " .. (where - linepos)
|
||||
end
|
||||
|
||||
local function unterminated (str, what, where)
|
||||
return nil, strlen (str) + 1, "unterminated " .. what .. " at " .. loc (str, where)
|
||||
end
|
||||
|
||||
local function scanwhite (str, pos)
|
||||
while true do
|
||||
pos = strfind (str, "%S", pos)
|
||||
if not pos then return nil end
|
||||
if strsub (str, pos, pos + 2) == "\239\187\191" then
|
||||
-- UTF-8 Byte Order Mark
|
||||
pos = pos + 3
|
||||
else
|
||||
return pos
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local escapechars = {
|
||||
["\""] = "\"", ["\\"] = "\\", ["/"] = "/", ["b"] = "\b", ["f"] = "\f",
|
||||
["n"] = "\n", ["r"] = "\r", ["t"] = "\t"
|
||||
}
|
||||
|
||||
local function unichar (value)
|
||||
if value < 0 then
|
||||
return nil
|
||||
elseif value <= 0x007f then
|
||||
return strchar (value)
|
||||
elseif value <= 0x07ff then
|
||||
return strchar (0xc0 + floor(value/0x40),
|
||||
0x80 + (floor(value) % 0x40))
|
||||
elseif value <= 0xffff then
|
||||
return strchar (0xe0 + floor(value/0x1000),
|
||||
0x80 + (floor(value/0x40) % 0x40),
|
||||
0x80 + (floor(value) % 0x40))
|
||||
elseif value <= 0x10ffff then
|
||||
return strchar (0xf0 + floor(value/0x40000),
|
||||
0x80 + (floor(value/0x1000) % 0x40),
|
||||
0x80 + (floor(value/0x40) % 0x40),
|
||||
0x80 + (floor(value) % 0x40))
|
||||
else
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
local function scanstring (str, pos)
|
||||
local lastpos = pos + 1
|
||||
local buffer, n = {}, 0
|
||||
while true do
|
||||
local nextpos = strfind (str, "[\"\\]", lastpos)
|
||||
if not nextpos then
|
||||
return unterminated (str, "string", pos)
|
||||
end
|
||||
if nextpos > lastpos then
|
||||
n = n + 1
|
||||
buffer[n] = strsub (str, lastpos, nextpos - 1)
|
||||
end
|
||||
if strsub (str, nextpos, nextpos) == "\"" then
|
||||
lastpos = nextpos + 1
|
||||
break
|
||||
else
|
||||
local escchar = strsub (str, nextpos + 1, nextpos + 1)
|
||||
local value
|
||||
if escchar == "u" then
|
||||
value = tonumber (strsub (str, nextpos + 2, nextpos + 5), 16)
|
||||
if value then
|
||||
local value2
|
||||
if 0xD800 <= value and value <= 0xDBff then
|
||||
-- we have the high surrogate of UTF-16. Check if there is a
|
||||
-- low surrogate escaped nearby to combine them.
|
||||
if strsub (str, nextpos + 6, nextpos + 7) == "\\u" then
|
||||
value2 = tonumber (strsub (str, nextpos + 8, nextpos + 11), 16)
|
||||
if value2 and 0xDC00 <= value2 and value2 <= 0xDFFF then
|
||||
value = (value - 0xD800) * 0x400 + (value2 - 0xDC00) + 0x10000
|
||||
else
|
||||
value2 = nil -- in case it was out of range for a low surrogate
|
||||
end
|
||||
end
|
||||
end
|
||||
value = value and unichar (value)
|
||||
if value then
|
||||
if value2 then
|
||||
lastpos = nextpos + 12
|
||||
else
|
||||
lastpos = nextpos + 6
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
if not value then
|
||||
value = escapechars[escchar] or escchar
|
||||
lastpos = nextpos + 2
|
||||
end
|
||||
n = n + 1
|
||||
buffer[n] = value
|
||||
end
|
||||
end
|
||||
if n == 1 then
|
||||
return buffer[1], lastpos
|
||||
elseif n > 1 then
|
||||
return concat (buffer), lastpos
|
||||
else
|
||||
return "", lastpos
|
||||
end
|
||||
end
|
||||
|
||||
local scanvalue -- forward declaration
|
||||
|
||||
local function scantable (what, closechar, str, startpos, nullval, objectmeta, arraymeta)
|
||||
local len = strlen (str)
|
||||
local tbl, n = {}, 0
|
||||
local pos = startpos + 1
|
||||
if what == 'object' then
|
||||
setmetatable (tbl, objectmeta)
|
||||
else
|
||||
setmetatable (tbl, arraymeta)
|
||||
end
|
||||
while true do
|
||||
pos = scanwhite (str, pos)
|
||||
if not pos then return unterminated (str, what, startpos) end
|
||||
local char = strsub (str, pos, pos)
|
||||
if char == closechar then
|
||||
return tbl, pos + 1
|
||||
end
|
||||
local val1, err
|
||||
val1, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
|
||||
if err then return nil, pos, err end
|
||||
pos = scanwhite (str, pos)
|
||||
if not pos then return unterminated (str, what, startpos) end
|
||||
char = strsub (str, pos, pos)
|
||||
if char == ":" then
|
||||
if val1 == nil then
|
||||
return nil, pos, "cannot use nil as table index (at " .. loc (str, pos) .. ")"
|
||||
end
|
||||
pos = scanwhite (str, pos + 1)
|
||||
if not pos then return unterminated (str, what, startpos) end
|
||||
local val2
|
||||
val2, pos, err = scanvalue (str, pos, nullval, objectmeta, arraymeta)
|
||||
if err then return nil, pos, err end
|
||||
tbl[val1] = val2
|
||||
pos = scanwhite (str, pos)
|
||||
if not pos then return unterminated (str, what, startpos) end
|
||||
char = strsub (str, pos, pos)
|
||||
else
|
||||
n = n + 1
|
||||
tbl[n] = val1
|
||||
end
|
||||
if char == "," then
|
||||
pos = pos + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
scanvalue = function (str, pos, nullval, objectmeta, arraymeta)
|
||||
pos = pos or 1
|
||||
pos = scanwhite (str, pos)
|
||||
if not pos then
|
||||
return nil, strlen (str) + 1, "no valid JSON value (reached the end)"
|
||||
end
|
||||
local char = strsub (str, pos, pos)
|
||||
if char == "{" then
|
||||
return scantable ('object', "}", str, pos, nullval, objectmeta, arraymeta)
|
||||
elseif char == "[" then
|
||||
return scantable ('array', "]", str, pos, nullval, objectmeta, arraymeta)
|
||||
elseif char == "\"" then
|
||||
return scanstring (str, pos)
|
||||
else
|
||||
local pstart, pend = strfind (str, "^%-?[%d%.]+[eE]?[%+%-]?%d*", pos)
|
||||
if pstart then
|
||||
local number = tonumber (strsub (str, pstart, pend))
|
||||
if number then
|
||||
return number, pend + 1
|
||||
end
|
||||
end
|
||||
pstart, pend = strfind (str, "^%a%w*", pos)
|
||||
if pstart then
|
||||
local name = strsub (str, pstart, pend)
|
||||
if name == "true" then
|
||||
return true, pend + 1
|
||||
elseif name == "false" then
|
||||
return false, pend + 1
|
||||
elseif name == "null" then
|
||||
return nullval, pend + 1
|
||||
end
|
||||
end
|
||||
return nil, pos, "no valid JSON value at " .. loc (str, pos)
|
||||
end
|
||||
end
|
||||
|
||||
function json.decode (str, pos, nullval, objectmeta, arraymeta)
|
||||
objectmeta = objectmeta or {__jsontype = 'object'}
|
||||
arraymeta = arraymeta or {__jsontype = 'array'}
|
||||
return scanvalue (str, pos, nullval, objectmeta, arraymeta)
|
||||
end
|
||||
|
||||
function json.use_lpeg ()
|
||||
local g = require ("lpeg")
|
||||
local pegmatch = g.match
|
||||
local P, S, R, V = g.P, g.S, g.R, g.V
|
||||
|
||||
local SpecialChars = (R"\0\31" + S"\"\\\127" +
|
||||
P"\194" * (R"\128\159" + P"\173") +
|
||||
P"\216" * R"\128\132" +
|
||||
P"\220\132" +
|
||||
P"\225\158" * S"\180\181" +
|
||||
P"\226\128" * (R"\140\143" + S"\168\175") +
|
||||
P"\226\129" * R"\160\175" +
|
||||
P"\239\187\191" +
|
||||
P"\229\191" + R"\176\191") / escapeutf8
|
||||
|
||||
local QuoteStr = g.Cs (g.Cc "\"" * (SpecialChars + 1)^0 * g.Cc "\"")
|
||||
|
||||
quotestring = function (str)
|
||||
return pegmatch (QuoteStr, str)
|
||||
end
|
||||
json.quotestring = quotestring
|
||||
|
||||
local function ErrorCall (str, pos, msg, state)
|
||||
if not state.msg then
|
||||
state.msg = msg .. " at " .. loc (str, pos)
|
||||
state.pos = pos
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
local function Err (msg)
|
||||
return g.Cmt (g.Cc (msg) * g.Carg (2), ErrorCall)
|
||||
end
|
||||
|
||||
local Space = (S" \n\r\t" + P"\239\187\191")^0
|
||||
|
||||
local PlainChar = 1 - S"\"\\\n\r"
|
||||
local EscapeSequence = (P"\\" * g.C (S"\"\\/bfnrt" + Err "unsupported escape sequence")) / escapechars
|
||||
local HexDigit = R("09", "af", "AF")
|
||||
local function UTF16Surrogate (match, pos, high, low)
|
||||
high, low = tonumber (high, 16), tonumber (low, 16)
|
||||
if 0xD800 <= high and high <= 0xDBff and 0xDC00 <= low and low <= 0xDFFF then
|
||||
return true, unichar ((high - 0xD800) * 0x400 + (low - 0xDC00) + 0x10000)
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
local function UTF16BMP (hex)
|
||||
return unichar (tonumber (hex, 16))
|
||||
end
|
||||
local U16Sequence = (P"\\u" * g.C (HexDigit * HexDigit * HexDigit * HexDigit))
|
||||
local UnicodeEscape = g.Cmt (U16Sequence * U16Sequence, UTF16Surrogate) + U16Sequence/UTF16BMP
|
||||
local Char = UnicodeEscape + EscapeSequence + PlainChar
|
||||
local String = P"\"" * g.Cs (Char ^ 0) * (P"\"" + Err "unterminated string")
|
||||
local Integer = P"-"^(-1) * (P"0" + (R"19" * R"09"^0))
|
||||
local Fractal = P"." * R"09"^0
|
||||
local Exponent = (S"eE") * (S"+-")^(-1) * R"09"^1
|
||||
local Number = (Integer * Fractal^(-1) * Exponent^(-1))/tonumber
|
||||
local Constant = P"true" * g.Cc (true) + P"false" * g.Cc (false) + P"null" * g.Carg (1)
|
||||
local SimpleValue = Number + String + Constant
|
||||
local ArrayContent, ObjectContent
|
||||
|
||||
-- The functions parsearray and parseobject parse only a single value/pair
|
||||
-- at a time and store them directly to avoid hitting the LPeg limits.
|
||||
local function parsearray (str, pos, nullval, state)
|
||||
local obj, cont
|
||||
local npos
|
||||
local t, nt = {}, 0
|
||||
repeat
|
||||
obj, cont, npos = pegmatch (ArrayContent, str, pos, nullval, state)
|
||||
if not npos then break end
|
||||
pos = npos
|
||||
nt = nt + 1
|
||||
t[nt] = obj
|
||||
until cont == 'last'
|
||||
return pos, setmetatable (t, state.arraymeta)
|
||||
end
|
||||
|
||||
local function parseobject (str, pos, nullval, state)
|
||||
local obj, key, cont
|
||||
local npos
|
||||
local t = {}
|
||||
repeat
|
||||
key, obj, cont, npos = pegmatch (ObjectContent, str, pos, nullval, state)
|
||||
if not npos then break end
|
||||
pos = npos
|
||||
t[key] = obj
|
||||
until cont == 'last'
|
||||
return pos, setmetatable (t, state.objectmeta)
|
||||
end
|
||||
|
||||
local Array = P"[" * g.Cmt (g.Carg(1) * g.Carg(2), parsearray) * Space * (P"]" + Err "']' expected")
|
||||
local Object = P"{" * g.Cmt (g.Carg(1) * g.Carg(2), parseobject) * Space * (P"}" + Err "'}' expected")
|
||||
local Value = Space * (Array + Object + SimpleValue)
|
||||
local ExpectedValue = Value + Space * Err "value expected"
|
||||
ArrayContent = Value * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
|
||||
local Pair = g.Cg (Space * String * Space * (P":" + Err "colon expected") * ExpectedValue)
|
||||
ObjectContent = Pair * Space * (P"," * g.Cc'cont' + g.Cc'last') * g.Cp()
|
||||
local DecodeValue = ExpectedValue * g.Cp ()
|
||||
|
||||
function json.decode (str, pos, nullval, objectmeta, arraymeta)
|
||||
local state = {
|
||||
objectmeta = objectmeta or {__jsontype = 'object'},
|
||||
arraymeta = arraymeta or {__jsontype = 'array'}
|
||||
}
|
||||
local obj, retpos = pegmatch (DecodeValue, str, pos, nullval, state)
|
||||
if state.msg then
|
||||
return nil, state.pos, state.msg
|
||||
else
|
||||
return obj, retpos
|
||||
end
|
||||
end
|
||||
|
||||
-- use this function only once:
|
||||
json.use_lpeg = function () return json end
|
||||
|
||||
json.using_lpeg = true
|
||||
|
||||
return json -- so you can get the module using json = require "dkjson".use_lpeg()
|
||||
end
|
||||
|
||||
if always_try_using_lpeg then
|
||||
pcall (json.use_lpeg)
|
||||
end
|
||||
|
||||
return json
|
||||
|
||||
-->
|
||||
96
app/corona/htmltotext.lua
Normal file
@@ -0,0 +1,96 @@
|
||||
function HTML_ToText (text)
|
||||
-- Declare variables, load the file. Make tags lowercase.
|
||||
text = string.gsub (text,"(%b<>)",
|
||||
function (tag)
|
||||
return tag:lower()
|
||||
end)
|
||||
--[[
|
||||
First we kill the developer formatting (tabs, CR, LF)
|
||||
and produce a long string with no newlines and tabs.
|
||||
We also kill repeated spaces as browsers ignore them anyway.
|
||||
]]
|
||||
local devkill=
|
||||
{
|
||||
["("..string.char(10)..")"] = " ",
|
||||
["("..string.char(13)..")"] = " ",
|
||||
["("..string.char(15)..")"] = "",
|
||||
["(%s%s+)"]=" ",
|
||||
}
|
||||
for pat, res in pairs (devkill) do
|
||||
text = string.gsub (text, pat, res)
|
||||
end
|
||||
-- Then we remove the header. We do this by stripping it first.
|
||||
text = string.gsub (text, "(<%s*head[^>]*>)", "<head>")
|
||||
text = string.gsub (text, "(<%s*%/%s*head%s*>)", "</head>")
|
||||
text = string.gsub (text, "(<head>,*<%/head>)", "")
|
||||
-- Kill all scripts. First we nuke their attribs.
|
||||
text = string.gsub (text, "(<%s*script[^>]*>)", "<script>")
|
||||
text = string.gsub (text, "(<%s*%/%s*script%s*>)", "</script>")
|
||||
text = string.gsub (text, "(<script>,*<%/script>)", "")
|
||||
-- Ok, same for styles.
|
||||
text = string.gsub (text, "(<%s*style[^>]*>)", "<style>")
|
||||
text = string.gsub (text, "(<%s*%/%s*style%s*>)", "</style>")
|
||||
text = string.gsub (text, "(<style>.*<%/style>)", "")
|
||||
|
||||
-- Replace <td> with tabulators.
|
||||
text = string.gsub (text, "(<%s*td[^>]*>)","\t")
|
||||
|
||||
-- Replace <br> with linebreaks.
|
||||
text = string.gsub (text, "(<%s*br%s*%/%s*>)","\n")
|
||||
|
||||
-- Replace <li> with an asterisk surrounded by 2 spaces.
|
||||
-- Replace </li> with a newline.
|
||||
text = string.gsub (text, "(<%s*li%s*%s*>)"," * ")
|
||||
text = string.gsub (text, "(<%s*/%s*li%s*%s*>)","\n")
|
||||
|
||||
-- <p>, <div>, <tr>, <ul> will be replaced to a double newline.
|
||||
text = string.gsub (text, "(<%s*div[^>]*>)", "\n\n")
|
||||
text = string.gsub (text, "(<%s*p[^>]*>)", "\n\n")
|
||||
text = string.gsub (text, "(<%s*tr[^>]*>)", "\n\n")
|
||||
text = string.gsub (text, "(<%s*%/*%s*ul[^>]*>)", "\n\n")
|
||||
--
|
||||
|
||||
-- Nuke all other tags now.
|
||||
text = string.gsub (text, "(%b<>)","")
|
||||
|
||||
-- Replace entities to their correspondant stuff where applicable.
|
||||
-- C# is owned badly here by using a table. :-P
|
||||
-- A metatable secures entities, so you can add them natively as keys.
|
||||
-- Enclosing brackets also get added automatically (capture!)
|
||||
local entities = {}
|
||||
setmetatable (entities,
|
||||
{
|
||||
__newindex = function (tbl, key, value)
|
||||
key = string.gsub (key, "(%#)" , "%%#")
|
||||
key = string.gsub (key, "(%&)" , "%%&")
|
||||
key = string.gsub (key, "(%;)" , "%%;")
|
||||
key = string.gsub (key, "(.+)" , "("..key..")")
|
||||
rawset (tbl, key, value)
|
||||
end
|
||||
})
|
||||
entities =
|
||||
{
|
||||
[" "] = " ",
|
||||
["•"] = " * ",
|
||||
["?"] = "<",
|
||||
["?"] = ">",
|
||||
["™"] = "(tm)",
|
||||
["⁄"] = "/",
|
||||
["<"] = "<",
|
||||
[">"] = ">",
|
||||
["©"] = "(c)",
|
||||
["®"] = "(r)",
|
||||
-- Then kill all others.
|
||||
-- You can customize this table if you would like to,
|
||||
-- I just got bored of copypasting. :-)
|
||||
-- http://hotwired.lycos.com/webmonkey/reference/special_characters/
|
||||
["%&.+%;"] = "",
|
||||
}
|
||||
for entity, repl in pairs (entities) do
|
||||
text = string.gsub (text, entity, repl)
|
||||
end
|
||||
|
||||
return text
|
||||
|
||||
end
|
||||
|
||||
96
app/corona/index.lua
Normal file
@@ -0,0 +1,96 @@
|
||||
local scene = storyboard.newScene()
|
||||
|
||||
local function backButtonRelease( self, event )
|
||||
storyboard.gotoScene(true, "login", "zoomInOut", 200)
|
||||
end
|
||||
|
||||
local viewController = require("viewController")
|
||||
local mainView, tabView, currentScreen, tabBar
|
||||
|
||||
local function loadScreen(newScreen)
|
||||
if currentScreen then
|
||||
currentScreen:cleanUp()
|
||||
end
|
||||
currentScreen = require(newScreen).createScreen()
|
||||
tabView:insert(currentScreen)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- Handler that gets notified when the exit alert closes
|
||||
local function exitListener(event)
|
||||
if "clicked" == event.action then
|
||||
local i = event.index
|
||||
if 1 == i then
|
||||
os.exit()
|
||||
elseif 2 == i then
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function showScreen(event)
|
||||
local t = event.target
|
||||
local phase = event.phase
|
||||
|
||||
if phase == "ended" then
|
||||
if t.id == 1 then
|
||||
loadScreen("myTodo")
|
||||
elseif t.id == 2 then
|
||||
loadScreen("myTask")
|
||||
elseif t.id == 3 then
|
||||
loadScreen("myBug")
|
||||
elseif t.id == 4 then
|
||||
native.showAlert("提示", "要退出吗?", {"确定", "取消"}, exitListener)
|
||||
end
|
||||
tabBar.selected(t)
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function scene:createScene( event )
|
||||
local screenGroup = self.view
|
||||
|
||||
local backgroundImg = display.newImage("background.png")
|
||||
backgroundImg.xOrigin = display.contentWidth/2
|
||||
backgroundImg.yOrigin = display.contentHeight/2
|
||||
screenGroup:insert(backgroundImg)
|
||||
|
||||
local screenGroup = self.view
|
||||
tabView = display.newGroup()
|
||||
screenGroup:insert(tabView)
|
||||
|
||||
loadScreen("myTodo")
|
||||
|
||||
tabBar = viewController.newTabBar{
|
||||
background = "tabBar.png",
|
||||
tabs = {"Todo", "任务", "Bug", "退出"},
|
||||
onRelease = showScreen
|
||||
}
|
||||
screenGroup:insert(tabBar)
|
||||
|
||||
tabBar.selected()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function scene:enterScene( event )
|
||||
storyboard.removeScene('login')
|
||||
storyboard.removeScene('viewTodo')
|
||||
storyboard.removeScene('viewTask')
|
||||
storyboard.removeScene('viewBug')
|
||||
end
|
||||
|
||||
function scene:exitScene()
|
||||
end
|
||||
|
||||
function scene:destroyScene(event)
|
||||
end
|
||||
|
||||
scene:addEventListener("createScene", scene)
|
||||
scene:addEventListener("enterScene", scene)
|
||||
scene:addEventListener("exitScene", scene)
|
||||
scene:addEventListener("destroyScene", scene)
|
||||
|
||||
return scene
|
||||
BIN
app/corona/listItemBg.png
Normal file
|
After Width: | Height: | Size: 3.0 KiB |
BIN
app/corona/listItemBg_over.png
Normal file
|
After Width: | Height: | Size: 3.1 KiB |
206
app/corona/login.lua
Normal file
@@ -0,0 +1,206 @@
|
||||
local scene = storyboard.newScene()
|
||||
|
||||
local zentaoImg
|
||||
local accountText, passwordText, zentaoRootText
|
||||
local accountField, passwordField, zentaoRootField
|
||||
local loginButton
|
||||
local fontSize = 14
|
||||
|
||||
local userData = {}
|
||||
|
||||
local zentaoRoot = "http://"
|
||||
local configAPI = ""
|
||||
local account = ""
|
||||
local password = ""
|
||||
local md5Password = ""
|
||||
local mixPassword = ""
|
||||
|
||||
-- global vars
|
||||
loginAPI = ""
|
||||
sessionAPI = ""
|
||||
myTodoAPI = ""
|
||||
myBugAPI = ""
|
||||
myTaskAPI = ""
|
||||
|
||||
config = {}
|
||||
session = {}
|
||||
|
||||
navBar = nil
|
||||
navHeader = nil
|
||||
|
||||
local function loginButtonRelease( self, event )
|
||||
if string.len(zentaoRootField.text) > 0 and string.len(accountField.text) > 0 and string.len(passwordField.text) > 0 then
|
||||
account = accountField.text
|
||||
password = passwordField.text
|
||||
if string.find(zentaoRootField.text, "http://") then
|
||||
zentaoRoot = zentaoRootField.text
|
||||
else
|
||||
zentaoRoot = zentaoRoot .. zentaoRootField.text
|
||||
end
|
||||
|
||||
if string.find(zentaoRoot, '/', string.len("http://")+1) == nil then
|
||||
zentaoRoot = zentaoRoot .. '/'
|
||||
end
|
||||
configAPI = zentaoRoot .. "?mode=getconfig"
|
||||
|
||||
local response = {}
|
||||
-- get the config
|
||||
local result = http.request {url = configAPI, method = "GET", sink = ltn12.sink.table(response) }
|
||||
|
||||
if table.getn(response) == 0 then
|
||||
native.showAlert("提示", "网络错误,请查看网络或重新设置!", {"我知道了"} )
|
||||
else
|
||||
for i, val in pairs(response) do
|
||||
config = json.decode(val)
|
||||
end
|
||||
|
||||
-- set APIs
|
||||
if config.requestType == "GET" then
|
||||
loginAPI = zentaoRoot .. "?m=user&f=login"
|
||||
sessionAPI = zentaoRoot .. "?m=api&f=getSessionID&t=json"
|
||||
|
||||
myTodoAPI = zentaoRoot .. "?m=my&f=todo&t=json"
|
||||
myTaskAPI = zentaoRoot .. "?m=my&f=task&t=json"
|
||||
myBugAPI = zentaoRoot .. "?m=my&f=bug&t=json"
|
||||
elseif config.requestType == "PATH_INFO" then
|
||||
loginAPI = zentaoRoot .. "user-login.json?a=1"
|
||||
sessionAPI = zentaoRoot .. "api-getsessionid.json?a=1"
|
||||
|
||||
myTodoAPI = zentaoRoot .. "my-todo.json?a=1"
|
||||
myTaskAPI = zentaoRoot .. "my-task.json?a=1"
|
||||
myBugAPI = zentaoRoot .. "my-bug.json?a=1"
|
||||
end
|
||||
|
||||
-- get the session
|
||||
http.request{url = sessionAPI, method = "GET", sink = ltn12.sink.table(session)}
|
||||
|
||||
if table.getn(session) == 0 then
|
||||
native.showAlert("提示", "网络错误,请查看网络或重新设置!", {"我知道了"} )
|
||||
else
|
||||
session = json.decode(table.concat(session))
|
||||
session.data = json.decode(session.data)
|
||||
|
||||
-- user login
|
||||
local response2 = {}
|
||||
md5Password = crypto.digest(crypto.md5, password)
|
||||
mixPassword = crypto.digest(crypto.md5, crypto.digest(crypto.md5, password) .. session.data.rand)
|
||||
|
||||
loginAPI = loginAPI .. "&account=" .. account .. "&password=" .. mixPassword .. "&" .. session.data.sessionName .. "=" .. session.data.sessionID
|
||||
http.request{url = loginAPI, method = "GET", sink = ltn12.sink.table(response2) }
|
||||
|
||||
if json.decode(table.concat(response2)).status == "failed" then
|
||||
native.showAlert("登录失败", "网络问题,或用户信息设置错误!", {"我知道了"})
|
||||
else
|
||||
local userData = json.encode({zentaoRoot = zentaoRoot, account = account, md5Password = md5Password})
|
||||
local path = system.pathForFile( "config.txt", system.DocumentsDirectory )
|
||||
local file = io.open(path, "w+")
|
||||
local result = file:write(userData)
|
||||
io.close( file )
|
||||
|
||||
storyboard.gotoScene(true, "index", "slideLeft", 100)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
else
|
||||
native.showAlert("提示", "请输入完整的用户信息!", {"我知道了"} )
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function scene:createScene( event )
|
||||
local screenGroup = self.view
|
||||
|
||||
zentaoImg = display.newImage("zentao.png")
|
||||
zentaoImg.xOrigin = display.contentWidth/2
|
||||
zentaoImg.yOrigin = display.contentHeight/2
|
||||
screenGroup:insert(zentaoImg)
|
||||
end
|
||||
|
||||
-- Called immediately after scene has moved onscreen:
|
||||
function scene:enterScene(event)
|
||||
local screenGroup = self.view
|
||||
|
||||
navBar = display.newImage("navBar.png")
|
||||
navBar.xOrigin = display.contentWidth/2 + display.screenOriginX
|
||||
navBar.yOrigin = navBar.yOrigin + display.screenOriginY
|
||||
screenGroup:insert(navBar)
|
||||
|
||||
navHeader = display.newText("禅道", 0, 0, native.systemFontBold, 18)
|
||||
navHeader:setTextColor(255, 255, 255)
|
||||
navHeader.xOrigin = display.contentWidth/2
|
||||
navHeader.yOrigin = navBar.yOrigin
|
||||
screenGroup:insert(navHeader)
|
||||
|
||||
local objectX = display.contentWidth /8
|
||||
local objectY = display.contentWidth / 3
|
||||
local textFieldWidth = math.floor(display.contentWidth*2/3)
|
||||
local textFieldHeight = 38
|
||||
|
||||
-- account
|
||||
accountText = display.newText("用户名:", objectX, objectY, native.systemFontBold, fontSize)
|
||||
accountText:setTextColor(0,0,0)
|
||||
screenGroup:insert(accountText)
|
||||
objectY = objectY + accountText.height
|
||||
|
||||
accountField = native.newTextField(objectX, objectY, textFieldWidth, textFieldHeight)
|
||||
accountField.text = account
|
||||
screenGroup:insert(accountField)
|
||||
objectY = objectY + accountField.height
|
||||
|
||||
-- password
|
||||
passwordText = display.newText("密码:", objectX, objectY , native.systemFontBold, fontSize)
|
||||
passwordText:setTextColor(0,0,0)
|
||||
screenGroup:insert(passwordText)
|
||||
objectY = objectY + passwordText.height
|
||||
|
||||
passwordField = native.newTextField(objectX, objectY, textFieldWidth, textFieldHeight)
|
||||
passwordField.text = password
|
||||
passwordField.isSecure = true
|
||||
screenGroup:insert(passwordField)
|
||||
objectY = objectY + passwordField.height
|
||||
|
||||
-- zentaoRoot
|
||||
zentaoRootText = display.newText("访问地址:", objectX, objectY, native.systemFontBold, fontSize)
|
||||
zentaoRootText:setTextColor(0,0,0)
|
||||
screenGroup:insert(zentaoRootText)
|
||||
objectY = objectY + zentaoRootText.height
|
||||
|
||||
zentaoRootField = native.newTextField(objectX, objectY, textFieldWidth, textFieldHeight)
|
||||
zentaoRootField.text = zentaoRoot
|
||||
screenGroup:insert(zentaoRootField)
|
||||
objectY = objectY + zentaoRootField.height
|
||||
|
||||
-- login button
|
||||
loginButton = ui.newButton
|
||||
{
|
||||
default = "button.png",
|
||||
over = "button_over.png",
|
||||
onRelease = loginButtonRelease,
|
||||
size = fontSize,
|
||||
text = "登录",
|
||||
textColor = {0, 0, 0, 165},
|
||||
emboss = true
|
||||
}
|
||||
loginButton.xOrigin = display.contentWidth/2
|
||||
loginButton.yOrigin = objectY + loginButton.height
|
||||
local tmpWidth = loginButton.width
|
||||
loginButton.width = math.floor(display.contentWidth/4)
|
||||
loginButton.height = math.floor(loginButton.width * loginButton.height / tmpWidth)
|
||||
screenGroup:insert(loginButton)
|
||||
|
||||
end
|
||||
|
||||
function scene:exitScene( event )
|
||||
end
|
||||
|
||||
function scene:destroyScene( event )
|
||||
end
|
||||
|
||||
scene:addEventListener("createScene", scene )
|
||||
scene:addEventListener("enterScene", scene )
|
||||
scene:addEventListener("exitScene", scene )
|
||||
scene:addEventListener("destroyScene", scene )
|
||||
|
||||
return scene
|
||||
31
app/corona/main.lua
Normal file
@@ -0,0 +1,31 @@
|
||||
--- global vars
|
||||
storyboard = require "storyboard"
|
||||
http = require("socket.http")
|
||||
crypto = require("crypto")
|
||||
ltn12 = require("ltn12")
|
||||
url = require("socket.url")
|
||||
json = require("dkjson")
|
||||
ui = require("ui")
|
||||
|
||||
local scene = storyboard.newScene()
|
||||
|
||||
display.setStatusBar(display.HiddenStatusBar)
|
||||
|
||||
local path = system.pathForFile("config.txt", system.DocumentsDirectory)
|
||||
local file = io.open(path, "r")
|
||||
|
||||
if file ~= nil then
|
||||
userData = file:read("*a")
|
||||
io.close(file)
|
||||
if userData then
|
||||
userData = json.decode(userData)
|
||||
zentaoRoot = userData.zentaoRoot
|
||||
account = userData.account
|
||||
md5Password = userData.md5Password
|
||||
configAPI = zentaoRoot .. "?mode=getconfig"
|
||||
|
||||
storyboard.gotoScene("autoLogin", "slideRight", 1)
|
||||
end
|
||||
else
|
||||
storyboard.gotoScene("login", "slideRight", 1)
|
||||
end
|
||||
115
app/corona/myBug.lua
Normal file
@@ -0,0 +1,115 @@
|
||||
module(..., package.seeall)
|
||||
|
||||
-- global vars
|
||||
myBugs = {}
|
||||
currentBugID = nil
|
||||
|
||||
-- local vars
|
||||
local scene = storyboard.newScene()
|
||||
local fontSize = 14
|
||||
|
||||
local function reLoginButtonRelease(self, event)
|
||||
storyboard.gotoScene("login", "slideRight", 100)
|
||||
end
|
||||
|
||||
local function view(event)
|
||||
_G.currentBugID = event.target.id
|
||||
storyboard.gotoScene(true, "viewBug", "slideLeft", 100)
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
function createScreen()
|
||||
local screenGroup = display.newGroup()
|
||||
|
||||
|
||||
-- 获取myBugs
|
||||
local response = {}
|
||||
myBugAPI = myBugAPI .. "&" .. session.data.sessionName .. "=" .. session.data.sessionID
|
||||
http.request{url = myBugAPI, method = "GET", sink = ltn12.sink.table(response) } -- type(response) = table
|
||||
|
||||
if table.getn(response) == 0 then
|
||||
native.showAlert("提示", "网络错误,请查看网络或重新设置!", {"我知道了"} )
|
||||
else
|
||||
response = json.decode(table.concat(response)) --type(response) = table ,type(response.data) = string
|
||||
if crypto.digest(crypto.md5, response.data) ~= response.md5 then
|
||||
native.showAlert("提示", "数据传输不完整", {"我知道了"})
|
||||
else
|
||||
|
||||
response.data = json.decode(response.data) --type(response.data) = table, type(response.data.response) = table
|
||||
|
||||
-- tableView
|
||||
if table.getn(response.data.bugs) == 0 then
|
||||
local noBugText = display.newText("您当前没有Bug!", 10, (display.contentHeight - 35)/2, native.systemFont, fontSize)
|
||||
noBugText.xOrigin = display.contentWidth / 2
|
||||
noBugText:setTextColor(0, 0, 0)
|
||||
screenGroup:insert(noBugText)
|
||||
else
|
||||
local tableView = require("tableView")
|
||||
local myList
|
||||
local listData = {}
|
||||
for i, val in pairs(response.data.bugs) do
|
||||
listData[i] = "#" .. val.id .. " " .. val.title:sub(1,40) -- 不控制长度的话,tableView会排版错误
|
||||
|
||||
if not val.title then
|
||||
val.title = ""
|
||||
elseif not val.steps then
|
||||
val.steps = ""
|
||||
end
|
||||
|
||||
myBugs[i] = val
|
||||
end
|
||||
_G.myBugs = myBugs
|
||||
|
||||
myList = tableView.newList{
|
||||
data = listData,
|
||||
default = "listItemBg.png",
|
||||
over = "listItemBg_over.png",
|
||||
onRelease = view,
|
||||
top = topBoundary,
|
||||
bottom = bottomBoundary,
|
||||
backgroundColor = { 255, 255, 255 },
|
||||
callback = function(row)
|
||||
local t = display.newText(row, 0, 0, native.systemFont, fontSize)
|
||||
t:setTextColor(0, 0, 0)
|
||||
t.x = math.floor(t.width/2) + 12
|
||||
t.y = 30
|
||||
return t
|
||||
end
|
||||
}
|
||||
screenGroup:insert(myList)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function screenGroup:cleanUp()
|
||||
screenGroup:removeSelf()
|
||||
end
|
||||
|
||||
local navBar = display.newImage("navBar.png")
|
||||
navBar.xOrigin = display.contentWidth/2 + display.screenOriginX
|
||||
navBar.yOrigin = navBar.yOrigin + display.screenOriginY
|
||||
screenGroup:insert(navBar)
|
||||
|
||||
local reLoginButton = ui.newButton{
|
||||
default = "reLoginButton.png",
|
||||
over = "reLoginButton_over.png",
|
||||
onRelease = reLoginButtonRelease,
|
||||
text = "重新登录",
|
||||
size = 12,
|
||||
emboss = true
|
||||
}
|
||||
reLoginButton.xOrigin = display.contentWidth - reLoginButton.width/2 + display.screenOriginX
|
||||
reLoginButton.yOrigin = navBar.height/2 + display.screenOriginY
|
||||
screenGroup:insert(reLoginButton)
|
||||
|
||||
|
||||
local navHeader = display.newText("我的Bug", 0, 0, native.systemFont, 18)
|
||||
navHeader:setTextColor(255, 255, 255)
|
||||
navHeader.xOrigin = display.contentWidth/2
|
||||
navHeader.yOrigin = navBar.yOrigin
|
||||
screenGroup:insert(navHeader)
|
||||
|
||||
return screenGroup
|
||||
end
|
||||
|
||||
110
app/corona/myTask.lua
Normal file
@@ -0,0 +1,110 @@
|
||||
module(..., package.seeall)
|
||||
|
||||
-- global vars
|
||||
myTasks = {}
|
||||
currentTaskID = nil
|
||||
|
||||
-- local vars
|
||||
local scene = storyboard.newScene()
|
||||
local fontSize = 14
|
||||
|
||||
local function reLoginButtonRelease(self, event)
|
||||
storyboard.gotoScene("login", "slideRight", 100)
|
||||
end
|
||||
|
||||
local function view(event)
|
||||
_G.currentTaskID = event.target.id
|
||||
storyboard.gotoScene(true, "viewTask", "slideLeft", 100)
|
||||
return true
|
||||
end
|
||||
|
||||
function createScreen()
|
||||
local screenGroup = display.newGroup()
|
||||
|
||||
-- 获取tasks
|
||||
local response = {}
|
||||
myTaskAPI = myTaskAPI .. "&" .. session.data.sessionName .. "=" .. session.data.sessionID
|
||||
http.request{url = myTaskAPI, method = "GET", sink = ltn12.sink.table(response) } -- type(response) = table
|
||||
|
||||
if table.getn(response) == 0 then
|
||||
native.showAlert("提示", "网络错误,请查看网络或重新设置!", {"我知道了"} )
|
||||
else
|
||||
response = json.decode(table.concat(response)) --type(response) = table ,type(response.data) = string
|
||||
if crypto.digest(crypto.md5, response.data) ~= response.md5 then
|
||||
native.showAlert("提示", "数据传输不完整", {"我知道了"})
|
||||
else
|
||||
|
||||
response.data = json.decode(response.data) --type(tasks.data) = table, type(tasks.data.tasks) = table
|
||||
|
||||
-- tableView
|
||||
if table.getn(response.data.tasks) == 0 then
|
||||
local noTaskText = display.newText("您当前没有任务!" , 10, (display.contentHeight - 35)/2, native.systemFont, fontSize)
|
||||
noTaskText.xOrigin = display.contentWidth / 2
|
||||
noTaskText:setTextColor(0, 0, 0)
|
||||
screenGroup:insert(noTaskText)
|
||||
else
|
||||
local tableView = require("tableView")
|
||||
local myList
|
||||
local listData = {}
|
||||
|
||||
for i, val in pairs(response.data.tasks) do
|
||||
listData[i] = "#" .. val.id .. " " .. val.name:sub(1,40)
|
||||
|
||||
if not val.desc then
|
||||
val.desc = ""
|
||||
end
|
||||
|
||||
myTasks[i] = val
|
||||
end
|
||||
_G.myTasks = myTasks
|
||||
|
||||
myList = tableView.newList{
|
||||
data = listData, -- listData下标必须从1开始,否则出错
|
||||
default = "listItemBg.png",
|
||||
over = "listItemBg_over.png",
|
||||
onRelease = view,
|
||||
top = topBoundary,
|
||||
bottom = bottomBoundary,
|
||||
backgroundColor = { 255, 255, 255 },
|
||||
callback = function(row)
|
||||
local t = display.newText(row, 0, 0, native.systemFont, fontSize)
|
||||
t:setTextColor(0, 0, 0)
|
||||
t.x = math.floor(t.width/2) + 12
|
||||
t.y = 30
|
||||
return t
|
||||
end
|
||||
}
|
||||
screenGroup:insert(myList)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function screenGroup:cleanUp()
|
||||
screenGroup:removeSelf()
|
||||
end
|
||||
|
||||
local navBar = display.newImage("navBar.png")
|
||||
navBar.xOrigin = display.contentWidth/2 + display.screenOriginX
|
||||
navBar.yOrigin = navBar.yOrigin + display.screenOriginY
|
||||
screenGroup:insert(navBar)
|
||||
|
||||
local reLoginButton = ui.newButton{
|
||||
default = "reLoginButton.png",
|
||||
over = "reLoginButton_over.png",
|
||||
onRelease = reLoginButtonRelease,
|
||||
text = "重新登录",
|
||||
size = 12,
|
||||
emboss = true
|
||||
}
|
||||
reLoginButton.xOrigin = display.contentWidth - reLoginButton.width/2 + display.screenOriginX
|
||||
reLoginButton.yOrigin = navBar.height/2 + display.screenOriginY
|
||||
screenGroup:insert(reLoginButton)
|
||||
|
||||
local navHeader = display.newText("我的任务", 0, 0, native.systemFont, 18)
|
||||
navHeader:setTextColor(255, 255, 255)
|
||||
navHeader.xOrigin = display.contentWidth/2
|
||||
navHeader.yOrigin = navBar.yOrigin
|
||||
screenGroup:insert(navHeader)
|
||||
|
||||
return screenGroup
|
||||
end
|
||||
118
app/corona/myTodo.lua
Normal file
@@ -0,0 +1,118 @@
|
||||
module(..., package.seeall)
|
||||
|
||||
-- global vars
|
||||
myTodos = {}
|
||||
currentTodoID = nil
|
||||
|
||||
-- local vars
|
||||
local physics = require( "physics" )
|
||||
local scene = storyboard.newScene()
|
||||
local tableView = require("tableView")
|
||||
local fontSize = 14
|
||||
|
||||
local function reLoginButtonRelease(self, event)
|
||||
storyboard.gotoScene("login", "slideRight", 100)
|
||||
end
|
||||
|
||||
local function view(event)
|
||||
_G.currentTodoID = event.target.id
|
||||
storyboard.gotoScene(true, "viewTodo", "slideLeft", 100)
|
||||
return true
|
||||
end
|
||||
|
||||
-- createScreen
|
||||
function createScreen()
|
||||
local screenGroup = display.newGroup()
|
||||
|
||||
local backgroundImg = display.newImage("background.png")
|
||||
backgroundImg.xOrigin = display.contentWidth/2
|
||||
backgroundImg.yOrigin = display.contentHeight/2
|
||||
screenGroup:insert(backgroundImg)
|
||||
|
||||
-- get the todos
|
||||
local response = {}
|
||||
myTodoAPI = myTodoAPI .. "&" .. session.data.sessionName .. "=" .. session.data.sessionID
|
||||
http.request{url = myTodoAPI, method = "GET", sink = ltn12.sink.table(response) } -- type(response) = table
|
||||
|
||||
if table.getn(response) == 0 then
|
||||
native.showAlert("提示", "网络错误,请查看网络或重新设置!", {"我知道了"} )
|
||||
else
|
||||
response = json.decode(table.concat(response)) --type(response) = table ,type(response.data) = string
|
||||
if crypto.digest(crypto.md5, response.data) ~= response.md5 then
|
||||
native.showAlert("提示", "数据传输不完整", {"我知道了"})
|
||||
else
|
||||
response.data = json.decode(response.data) --type(response.data) = table, type(response.data.todos) = table
|
||||
|
||||
if table.getn(response.data.todos) == 0 then
|
||||
local noTodoText = display.newText("您当前没有Todo!", 10, (display.contentHeight - 35)/2, native.systemFontBold, fontSize)
|
||||
noTodoText.xOrigin = display.contentWidth / 2
|
||||
noTodoText:setTextColor(0, 0, 0)
|
||||
screenGroup:insert(noTodoText)
|
||||
else
|
||||
-- tableView
|
||||
local myList
|
||||
local listData = {}
|
||||
for i, val in pairs(response.data.todos) do
|
||||
listData[i] = "#" .. val.id .. " " .. val.name:sub(1,40) -- 不控制长度的话,tableView会排版错误
|
||||
|
||||
if not val.name then
|
||||
val.name = ""
|
||||
elseif not val.desc then
|
||||
val.desc = ""
|
||||
end
|
||||
|
||||
myTodos[i] = val
|
||||
end
|
||||
|
||||
_G.myTodos = myTodos
|
||||
|
||||
myList = tableView.newList{
|
||||
data = listData, -- listData下标必须从1开始,否则出错
|
||||
default = "listItemBg.png",
|
||||
over = "listItemBg_over.png",
|
||||
onRelease = view,
|
||||
top = topBoundary,
|
||||
bottom = bottomBoundary,
|
||||
backgroundColor = { 255, 255, 255 },
|
||||
callback = function(row)
|
||||
local t = display.newText(row, 0, 0, native.systemFont, 14)
|
||||
t:setTextColor(0, 0, 0)
|
||||
t.x = math.floor(t.width/2) + 12
|
||||
t.y = 30
|
||||
return t
|
||||
end
|
||||
}
|
||||
screenGroup:insert(myList)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function screenGroup:cleanUp()
|
||||
screenGroup:removeSelf()
|
||||
end
|
||||
|
||||
local navBar = display.newImage("navBar.png")
|
||||
navBar.xOrigin = display.contentWidth/2 + display.screenOriginX
|
||||
navBar.yOrigin = navBar.yOrigin + display.screenOriginY
|
||||
screenGroup:insert(navBar)
|
||||
|
||||
local reLoginButton = ui.newButton{
|
||||
default = "reLoginButton.png",
|
||||
over = "reLoginButton_over.png",
|
||||
onRelease = reLoginButtonRelease,
|
||||
text = "重新登录",
|
||||
size = 12,
|
||||
emboss = true
|
||||
}
|
||||
reLoginButton.xOrigin = display.contentWidth - reLoginButton.width/2 + display.screenOriginX
|
||||
reLoginButton.yOrigin = navBar.height/2 + display.screenOriginY
|
||||
screenGroup:insert(reLoginButton)
|
||||
|
||||
local navHeader = display.newText("我的Todo", 0, 0, native.systemFontBold, 18)
|
||||
navHeader:setTextColor(255, 255, 255)
|
||||
navHeader.xOrigin = display.contentWidth/2
|
||||
navHeader.yOrigin = navBar.yOrigin
|
||||
screenGroup:insert(navHeader)
|
||||
|
||||
return screenGroup
|
||||
end
|
||||
BIN
app/corona/navBar.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/corona/reLoginButton.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/corona/reLoginButton_over.png
Normal file
|
After Width: | Height: | Size: 2.9 KiB |
206
app/corona/scrollView.lua
Normal file
@@ -0,0 +1,206 @@
|
||||
-- scrollView.lua
|
||||
--
|
||||
-- Version 1.0
|
||||
--
|
||||
-- Copyright (C) 2010 ANSCA Inc. All Rights Reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
-- this software and associated documentation files (the "Software"), to deal in the
|
||||
-- Software without restriction, including without limitation the rights to use, copy,
|
||||
-- modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
-- and to permit persons to whom the Software is furnished to do so, subject to the
|
||||
-- following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in all copies
|
||||
-- or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
-- FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
-- OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
-- DEALINGS IN THE SOFTWARE.
|
||||
|
||||
module(..., package.seeall)
|
||||
|
||||
-- set some global values for width and height of the screen
|
||||
local screenW, screenH = display.contentWidth, display.contentHeight
|
||||
local viewableScreenW, viewableScreenH = display.viewableContentWidth, display.viewableContentHeight
|
||||
local screenOffsetW, screenOffsetH = display.contentWidth - display.viewableContentWidth, display.contentHeight - display.viewableContentHeight
|
||||
|
||||
local prevTime = 0
|
||||
|
||||
function new(params)
|
||||
-- setup a group to be the scrolling screen
|
||||
local scrollView = display.newGroup()
|
||||
|
||||
scrollView.top = params.top or 0
|
||||
scrollView.bottom = params.bottom or 0
|
||||
|
||||
function scrollView:touch(event)
|
||||
local phase = event.phase
|
||||
print(phase)
|
||||
|
||||
if( phase == "began" ) then
|
||||
print(scrollView.y)
|
||||
self.startPos = event.y
|
||||
self.prevPos = event.y
|
||||
self.delta, self.velocity = 0, 0
|
||||
if self.tween then transition.cancel(self.tween) end
|
||||
|
||||
Runtime:removeEventListener("enterFrame", scrollView )
|
||||
|
||||
self.prevTime = 0
|
||||
self.prevY = 0
|
||||
|
||||
transition.to(self.scrollBar, { time=200, alpha=1 } )
|
||||
|
||||
-- Start tracking velocity
|
||||
Runtime:addEventListener("enterFrame", trackVelocity)
|
||||
|
||||
-- Subsequent touch events will target button even if they are outside the contentBounds of button
|
||||
display.getCurrentStage():setFocus( self )
|
||||
self.isFocus = true
|
||||
|
||||
elseif( self.isFocus ) then
|
||||
|
||||
if( phase == "moved" ) then
|
||||
local bottomLimit = screenH - self.height - self.bottom
|
||||
|
||||
self.delta = event.y - self.prevPos
|
||||
self.prevPos = event.y
|
||||
if ( self.y > self.top or self.y < bottomLimit ) then
|
||||
self.y = self.y + self.delta/2
|
||||
else
|
||||
self.y = self.y + self.delta
|
||||
end
|
||||
|
||||
scrollView:moveScrollBar()
|
||||
|
||||
elseif( phase == "ended" or phase == "cancelled" ) then
|
||||
local dragDistance = event.y - self.startPos
|
||||
self.lastTime = event.time
|
||||
|
||||
Runtime:addEventListener("enterFrame", scrollView )
|
||||
Runtime:removeEventListener("enterFrame", trackVelocity)
|
||||
|
||||
-- Allow touch events to be sent normally to the objects they "hit"
|
||||
display.getCurrentStage():setFocus( nil )
|
||||
self.isFocus = false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function scrollView:enterFrame(event)
|
||||
local friction = 0.9
|
||||
local timePassed = event.time - self.lastTime
|
||||
self.lastTime = self.lastTime + timePassed
|
||||
|
||||
--turn off scrolling if velocity is near zero
|
||||
if math.abs(self.velocity) < .01 then
|
||||
self.velocity = 0
|
||||
Runtime:removeEventListener("enterFrame", scrollView )
|
||||
transition.to(self.scrollBar, { time=400, alpha=0 } )
|
||||
end
|
||||
|
||||
self.velocity = self.velocity*friction
|
||||
|
||||
self.y = math.floor(self.y + self.velocity*timePassed)
|
||||
|
||||
local upperLimit = self.top
|
||||
local bottomLimit = screenH - self.height - self.bottom
|
||||
|
||||
if ( self.y > upperLimit ) then
|
||||
self.velocity = 0
|
||||
Runtime:removeEventListener("enterFrame", scrollView )
|
||||
self.tween = transition.to(self, { time=400, y=upperLimit, transition=easing.outQuad})
|
||||
transition.to(self.scrollBar, { time=400, alpha=0 } )
|
||||
elseif ( self.y < bottomLimit and bottomLimit < 0 ) then
|
||||
self.velocity = 0
|
||||
Runtime:removeEventListener("enterFrame", scrollView )
|
||||
self.tween = transition.to(self, { time=400, y=bottomLimit, transition=easing.outQuad})
|
||||
transition.to(self.scrollBar, { time=400, alpha=0 } )
|
||||
elseif ( self.y < bottomLimit ) then
|
||||
self.velocity = 0
|
||||
Runtime:removeEventListener("enterFrame", scrollView )
|
||||
self.tween = transition.to(self, { time=400, y=upperLimit, transition=easing.outQuad})
|
||||
transition.to(self.scrollBar, { time=400, alpha=0 } )
|
||||
end
|
||||
|
||||
scrollView:moveScrollBar()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function scrollView:moveScrollBar()
|
||||
if self.scrollBar then
|
||||
local scrollBar = self.scrollBar
|
||||
|
||||
scrollBar.y = -self.y*self.yRatio + scrollBar.height*0.5 + self.top
|
||||
|
||||
if scrollBar.y < 5 + self.top + scrollBar.height*0.5 then
|
||||
scrollBar.y = 5 + self.top + scrollBar.height*0.5
|
||||
end
|
||||
if scrollBar.y > screenH - self.bottom - 5 - scrollBar.height*0.5 then
|
||||
scrollBar.y = screenH - self.bottom - 5 - scrollBar.height*0.5
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
function trackVelocity(event)
|
||||
local timePassed = event.time - scrollView.prevTime
|
||||
scrollView.prevTime = scrollView.prevTime + timePassed
|
||||
|
||||
if scrollView.prevY then
|
||||
scrollView.velocity = (scrollView.y - scrollView.prevY)/timePassed
|
||||
end
|
||||
scrollView.prevY = scrollView.y
|
||||
end
|
||||
|
||||
scrollView.y = scrollView.top
|
||||
|
||||
-- setup the touch listener
|
||||
scrollView:addEventListener( "touch", scrollView )
|
||||
|
||||
function scrollView:addScrollBar(r,g,b,a)
|
||||
if self.scrollBar then self.scrollBar:removeSelf() end
|
||||
|
||||
local scrollColorR = r or 0
|
||||
local scrollColorG = g or 0
|
||||
local scrollColorB = b or 0
|
||||
local scrollColorA = a or 120
|
||||
|
||||
local viewPortH = screenH - self.top - self.bottom
|
||||
local scrollH = viewPortH*self.height/(self.height*2 - viewPortH)
|
||||
local scrollBar = display.newRoundedRect(viewableScreenW-8,0,5,scrollH,2)
|
||||
scrollBar:setFillColor(scrollColorR, scrollColorG, scrollColorB, scrollColorA)
|
||||
|
||||
local yRatio = scrollH/self.height
|
||||
self.yRatio = yRatio
|
||||
|
||||
scrollBar.y = scrollBar.height*0.5 + self.top
|
||||
|
||||
self.scrollBar = scrollBar
|
||||
|
||||
transition.to(scrollBar, { time=400, alpha=0 } )
|
||||
end
|
||||
|
||||
function scrollView:removeScrollBar()
|
||||
if self.scrollBar then
|
||||
self.scrollBar:removeSelf()
|
||||
self.scrollBar = nil
|
||||
end
|
||||
end
|
||||
|
||||
function scrollView:cleanUp()
|
||||
Runtime:removeEventListener("enterFrame", trackVelocity)
|
||||
Runtime:removeEventListener( "touch", scrollView )
|
||||
Runtime:removeEventListener("enterFrame", scrollView )
|
||||
scrollView:removeScrollBar()
|
||||
end
|
||||
|
||||
return scrollView
|
||||
end
|
||||
149
app/corona/setting.lua
Normal file
@@ -0,0 +1,149 @@
|
||||
local scene = storyboard.newScene()
|
||||
|
||||
-- zentao vars
|
||||
local allConfigs = {} -- read all configs from config.json
|
||||
local currentName = ""
|
||||
local currentUrl = "http://"
|
||||
|
||||
-- page elements
|
||||
local backgroundImg
|
||||
local nameField, urlField
|
||||
local savaButton, resetButton, backButton
|
||||
|
||||
local function fieldHandler( event )
|
||||
if ( "began" == event.phase ) then
|
||||
-- This is the "keyboard has appeared" event
|
||||
-- In some cases you may want to adjust the interface when the keyboard appears.
|
||||
elseif ( "ended" == event.phase ) then
|
||||
|
||||
-- This event is called when the user stops editing a field: for example, when they touch a different field
|
||||
elseif ( "submitted" == event.phase ) then
|
||||
-- This event occurs when the user presses the "return" key (if available) on the onscreen keyboard
|
||||
-- Hide keyboard
|
||||
native.setKeyboardFocus( nil )
|
||||
end
|
||||
end
|
||||
|
||||
local function saveButtonRelease( self, event )
|
||||
|
||||
if string.len(nameField.text) > 0 and string.len(urlField.text) > 0 then
|
||||
currentName = nameField.text
|
||||
if string.find(urlField.text, "http://") then
|
||||
currentUrl = urlField.text
|
||||
else
|
||||
currentUrl = currentUrl .. urlField.text .. '/'
|
||||
end
|
||||
|
||||
local userData = json.encode({name = currentName, url = currentUrl})
|
||||
local path = system.pathForFile( "config.txt", system.DocumentsDirectory )
|
||||
local file = io.open(path, "w+")
|
||||
local result = file:write(userData)
|
||||
if result then
|
||||
native.showAlert("提示", "保存成功", { "OK" })
|
||||
end
|
||||
io.close( file )
|
||||
else
|
||||
native.showAlert("提示", "请正确填写!", { "OK" })
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function backButtonRelease( self, event )
|
||||
storyboard.gotoScene(true, "login", "slideRight", 200)
|
||||
end
|
||||
|
||||
|
||||
function scene:createScene( event )
|
||||
local screenGroup = self.view
|
||||
|
||||
backgroundImg = display.newImage("background.png")
|
||||
backgroundImg.xOrigin = display.contentWidth/2 + display.screenOriginX
|
||||
backgroundImg.yOrigin = display.contentHeight/2 + display.screenOriginY
|
||||
screenGroup:insert(backgroundImg)
|
||||
|
||||
end
|
||||
|
||||
function scene:enterScene( event )
|
||||
storyboard.purgeScene("login")
|
||||
|
||||
local screenGroup = self.view
|
||||
|
||||
screenGroup:insert(navBar)
|
||||
screenGroup:insert(navHeader)
|
||||
|
||||
-- newText
|
||||
nameText = display.newText("名称:", display.contentWidth/6, display.contentHeight / 3, native.systemFontBold, 18)
|
||||
nameText:setTextColor(0,0,0)
|
||||
screenGroup:insert(nameText)
|
||||
|
||||
urlText = display.newText(" " .. " Url:", display.contentWidth/6, display.contentHeight*13/ 30 , native.systemFontBold, 18)
|
||||
urlText:setTextColor(0,0,0)
|
||||
screenGroup:insert(urlText)
|
||||
|
||||
-- newTextField
|
||||
nameField = native.newTextField(display.contentWidth/6 + nameText.width + 10, display.contentHeight / 3, display.contentWidth/2, 40)
|
||||
nameField.text = currentName
|
||||
screenGroup:insert(nameField)
|
||||
|
||||
urlField = native.newTextField(display.contentWidth/6 + urlText.width + 10, display.contentHeight *13/30, display.contentWidth/2, 40)
|
||||
urlField.text = currentUrl
|
||||
urlField.inputType = "url"
|
||||
screenGroup:insert(urlField)
|
||||
|
||||
-- Button
|
||||
saveButton = ui.newButton{
|
||||
default = "button.png",
|
||||
over = "button_over.png",
|
||||
onRelease = saveButtonRelease,
|
||||
size = 24,
|
||||
text = "保存",
|
||||
emboss = true
|
||||
}
|
||||
saveButton.xOrigin = display.contentWidth/4
|
||||
saveButton.yOrigin = display.contentHeight*3/4
|
||||
local tmpWidth = saveButton.width
|
||||
saveButton.width = math.floor(display.contentWidth/3)
|
||||
saveButton.height = math.floor(saveButton.width * saveButton.height / tmpWidth)
|
||||
screenGroup:insert(saveButton)
|
||||
|
||||
resetButton = ui.newButton{
|
||||
default = "button.png",
|
||||
over = "button_over.png",
|
||||
onRelease = resetButtonRelease,
|
||||
size = 24,
|
||||
text = "重置",
|
||||
emboss = true
|
||||
}
|
||||
resetButton.xOrigin = display.contentWidth*3/4
|
||||
resetButton.yOrigin = display.contentHeight*3/4
|
||||
tmpWidth = resetButton.width
|
||||
resetButton.width = display.contentWidth/3
|
||||
resetButton.height = math.floor(resetButton.width * resetButton.height / tmpWidth)
|
||||
screenGroup:insert(resetButton)
|
||||
|
||||
backButton = ui.newButton{
|
||||
default = "backButton.png",
|
||||
over = "backButton_over.png",
|
||||
onRelease = backButtonRelease,
|
||||
size = 16,
|
||||
emboss = true
|
||||
}
|
||||
backButton.xOrigin = display.contentWidth - backButton.width/2 + display.screenOriginX
|
||||
backButton.yOrigin = display.contentHeight - backButton.height/2 - display.screenOriginY
|
||||
screenGroup:insert(backButton)
|
||||
|
||||
end
|
||||
|
||||
function scene:exitScene()
|
||||
end
|
||||
|
||||
function scene:destroyScene(event)
|
||||
end
|
||||
|
||||
scene:addEventListener("createScene", scene)
|
||||
scene:addEventListener("enterScene", scene)
|
||||
scene:addEventListener("exitScene", scene)
|
||||
scene:addEventListener("destroyScene", scene)
|
||||
|
||||
return scene
|
||||
BIN
app/corona/tab1.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/corona/tab1_over.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/corona/tab2.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/corona/tab2_over.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/corona/tab3.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/corona/tab3_over.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/corona/tab4.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/corona/tab4_over.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
BIN
app/corona/tabBar.png
Normal file
|
After Width: | Height: | Size: 2.8 KiB |
420
app/corona/tableView.lua
Normal file
@@ -0,0 +1,420 @@
|
||||
-- tableView.lua, Table View Library
|
||||
--
|
||||
-- Version 1.3
|
||||
--
|
||||
-- Copyright (C) 2010 ANSCA Inc. All Rights Reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
-- this software and associated documentation files (the "Software"), to deal in the
|
||||
-- Software without restriction, including without limitation the rights to use, copy,
|
||||
-- modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
-- and to permit persons to whom the Software is furnished to do so, subject to the
|
||||
-- following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in all copies
|
||||
-- or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
-- FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
-- OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
-- DEALINGS IN THE SOFTWARE.
|
||||
|
||||
|
||||
module(..., package.seeall)
|
||||
|
||||
--properties
|
||||
local screenW, screenH = display.contentWidth, display.contentHeight
|
||||
local viewableScreenW, viewableScreenH = display.viewableContentWidth, display.viewableContentHeight
|
||||
local screenOffsetW, screenOffsetH = display.contentWidth - display.viewableContentWidth, display.contentHeight - display.viewableContentHeight
|
||||
|
||||
local currentTarget, detailScreen, velocity, currentDefault, currentOver, prevY
|
||||
local startTime, lastTime, prevTime = 0, 0, 0
|
||||
|
||||
--methods
|
||||
|
||||
function showHighlight(event)
|
||||
local timePassed = system.getTimer() - startTime
|
||||
|
||||
if timePassed > 100 then
|
||||
print("highlight")
|
||||
currentDefault.isVisible = false
|
||||
currentOver.isVisible = true
|
||||
Runtime:removeEventListener( "enterFrame", showHighlight )
|
||||
end
|
||||
end
|
||||
|
||||
function newListItemHandler(self, event)
|
||||
local t = currentTarget --could use self.target.parent possibly
|
||||
local phase = event.phase
|
||||
print("touch: ".. phase)
|
||||
|
||||
local default = self.default
|
||||
local over = self.over
|
||||
local top = self.top
|
||||
local bottom = self.bottom
|
||||
local upperLimit, bottomLimit = top, screenH - currentTarget.height - bottom
|
||||
|
||||
local result = true
|
||||
|
||||
if( phase == "began" ) then
|
||||
-- Subsequent touch events will target button even if they are outside the contentBounds of button
|
||||
display.getCurrentStage():setFocus( self )
|
||||
self.isFocus = true
|
||||
|
||||
startPos = event.y
|
||||
prevPos = event.y
|
||||
delta, velocity = 0, 0
|
||||
if currentTarget.tween then transition.cancel(currentTarget.tween) end
|
||||
|
||||
Runtime:removeEventListener("enterFrame", scrollList )
|
||||
Runtime:addEventListener("enterFrame", moveCat)
|
||||
|
||||
-- Start tracking velocity
|
||||
Runtime:addEventListener("enterFrame", trackVelocity)
|
||||
|
||||
if over then
|
||||
currentDefault = default
|
||||
currentOver = over
|
||||
startTime = system.getTimer()
|
||||
Runtime:addEventListener( "enterFrame", showHighlight )
|
||||
end
|
||||
|
||||
elseif( self.isFocus ) then
|
||||
|
||||
if( phase == "moved" ) then
|
||||
|
||||
Runtime:removeEventListener( "enterFrame", showHighlight )
|
||||
if over then
|
||||
default.isVisible = true
|
||||
over.isVisible = false
|
||||
end
|
||||
|
||||
delta = event.y - prevPos
|
||||
prevPos = event.y
|
||||
if ( t.y > upperLimit or t.y < bottomLimit ) then
|
||||
t.y = t.y + delta/2
|
||||
else
|
||||
t.y = t.y + delta
|
||||
end
|
||||
|
||||
elseif( phase == "ended" or phase == "cancelled" ) then
|
||||
|
||||
lastTime = event.time
|
||||
|
||||
local dragDistance = event.y - startPos
|
||||
--velocity = delta
|
||||
Runtime:removeEventListener("enterFrame", moveCat)
|
||||
Runtime:removeEventListener("enterFrame", trackVelocity)
|
||||
Runtime:addEventListener("enterFrame", scrollList )
|
||||
|
||||
local bounds = self.contentBounds
|
||||
local x, y = event.x, event.y
|
||||
local isWithinBounds = bounds.xMin <= x and bounds.xMax >= x and bounds.yMin <= y and bounds.yMax >= y
|
||||
|
||||
-- Only consider this a "click", if the user lifts their finger inside button's contentBounds
|
||||
if isWithinBounds and (dragDistance < 10 and dragDistance > -10 ) then
|
||||
velocity = 0
|
||||
result = self.onRelease(event)
|
||||
end
|
||||
|
||||
-- Allow touch events to be sent normally to the objects they "hit"
|
||||
display.getCurrentStage():setFocus( nil )
|
||||
self.isFocus = false
|
||||
|
||||
if over then
|
||||
default.isVisible = true
|
||||
over.isVisible = false
|
||||
Runtime:removeEventListener( "enterFrame", showHighlight )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
function newListItem(params)
|
||||
local data = params.data
|
||||
local default = params.default
|
||||
local over = params.over
|
||||
local onRelease = params.onRelease
|
||||
local top = params.top
|
||||
local bottom = params.bottom
|
||||
local callback = params.callback
|
||||
local id = params.id
|
||||
|
||||
local thisItem = display.newGroup()
|
||||
|
||||
if params.default then
|
||||
default = display.newImage( params.default )
|
||||
thisItem:insert( default )
|
||||
default.x = default.width*.5 - screenOffsetW
|
||||
thisItem.default = default
|
||||
end
|
||||
|
||||
if params.over then
|
||||
over = display.newImage( params.over )
|
||||
over.isVisible = false
|
||||
thisItem:insert( over )
|
||||
over.x = over.width*.5 - screenOffsetW
|
||||
thisItem.over = over
|
||||
end
|
||||
|
||||
thisItem.id = id
|
||||
thisItem.data = data
|
||||
thisItem.onRelease = onRelease
|
||||
thisItem.top = top
|
||||
thisItem.bottom = bottom
|
||||
|
||||
local t = callback(data)
|
||||
thisItem:insert( t )
|
||||
|
||||
thisItem.touch = newListItemHandler
|
||||
thisItem:addEventListener( "touch", thisItem )
|
||||
|
||||
return thisItem
|
||||
end
|
||||
|
||||
function newList(params)
|
||||
local textSize = 16
|
||||
local data = params.data
|
||||
local default = params.default
|
||||
local over = params.over
|
||||
local onRelease = params.onRelease
|
||||
local top = params.top or 20
|
||||
local bottom = params.bottom or 48
|
||||
local cat = params.cat
|
||||
local order = params.order or {}
|
||||
local categoryBackground = params.categoryBackground
|
||||
local backgroundColor = params.backgroundColor
|
||||
local callback = params.callback or function(item)
|
||||
local t = display.newText(item, 0, 0, native.systemFontBold, textSize)
|
||||
t:setTextColor(255, 255, 255)
|
||||
t.x = math.floor(t.width/2) + 20
|
||||
t.y = 24
|
||||
return t
|
||||
end
|
||||
|
||||
--setup the list view
|
||||
local listView = display.newGroup()
|
||||
local prevY, prevH = 0, 0
|
||||
|
||||
|
||||
if cat then
|
||||
local catTable = {}
|
||||
|
||||
--get the implicit categories
|
||||
local prevCat = 0
|
||||
for i=1, #data do
|
||||
if data[i][cat] ~= prevCat then
|
||||
table.insert(catTable, data[i][cat])
|
||||
prevCat = data[i][cat]
|
||||
end
|
||||
end
|
||||
|
||||
if order then
|
||||
--clean up the user provided order table by removing any empty categories
|
||||
local n = 1
|
||||
while n < #order do
|
||||
if not in_table(order[n], catTable) then
|
||||
table.remove(order, n)
|
||||
else
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
|
||||
--add any categories not specified to the user order of categories
|
||||
for i=1, #catTable do
|
||||
if not in_table(catTable[i], order) then
|
||||
table.insert(order, catTable[i])
|
||||
end
|
||||
end
|
||||
else
|
||||
order = catTable
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
local j = 1
|
||||
local c = {}
|
||||
local offset = 12
|
||||
while true do
|
||||
local h = order[j]
|
||||
|
||||
if h then
|
||||
local g = display.newGroup()
|
||||
local b
|
||||
if categoryBackground then
|
||||
b = display.newImage(categoryBackground, true)
|
||||
else
|
||||
b = display.newRect(0, 0, screenW, textSize*1.5)
|
||||
b:setFillColor(0, 0, 0, 100)
|
||||
end
|
||||
g:insert( b )
|
||||
|
||||
local labelShadow = display.newText( h, 0, 0, native.systemFontBold, textSize )
|
||||
labelShadow:setTextColor( 0, 0, 0, 128 )
|
||||
g:insert( labelShadow, true )
|
||||
labelShadow.x = labelShadow.width*.5 + 1 + offset + screenOffsetW*.5
|
||||
labelShadow.y = textSize*.8 + 1
|
||||
|
||||
local t = display.newText(h, 0, 0, native.systemFontBold, textSize)
|
||||
t:setTextColor(255, 255, 255)
|
||||
g:insert( t )
|
||||
t.x = t.width*.5 + offset + screenOffsetW*.5
|
||||
t.y = textSize*.8
|
||||
|
||||
listView:insert( g )
|
||||
g.x = 0
|
||||
g.y = prevY + prevH
|
||||
prevY = g.y
|
||||
prevH = g.height
|
||||
table.insert(c, g)
|
||||
c[#c].yInit = g.y
|
||||
end
|
||||
|
||||
--iterate over the data and add items to the list view
|
||||
for i=1, #data do
|
||||
if data[i][cat] == h then
|
||||
local thisItem = newListItem{
|
||||
data = data[i],
|
||||
default = default,
|
||||
over = over,
|
||||
onRelease = onRelease,
|
||||
top = top,
|
||||
bottom = bottom,
|
||||
callback = callback,
|
||||
id = i
|
||||
}
|
||||
|
||||
listView:insert( 1, thisItem )
|
||||
|
||||
thisItem.x = 0 + screenOffsetW*.5
|
||||
thisItem.y = prevY + prevH
|
||||
|
||||
--save the Y and height
|
||||
prevY = thisItem.y
|
||||
prevH = thisItem.height
|
||||
end --if
|
||||
end --for
|
||||
|
||||
j = j + 1
|
||||
|
||||
if not order[j] then break end
|
||||
end --while
|
||||
|
||||
if backgroundColor then
|
||||
local bgColor = display.newRect(0, 0, screenW, screenH)
|
||||
bgColor:setFillColor(backgroundColor[1], backgroundColor[2], backgroundColor[3])
|
||||
bgColor.width = listView.width
|
||||
bgColor.height = listView.height
|
||||
bgColor.y = bgColor.height*.5
|
||||
listView:insert(1, bgColor)
|
||||
end
|
||||
|
||||
listView.y = top
|
||||
listView.top = top
|
||||
listView.bottom = bottom
|
||||
listView.c = c
|
||||
|
||||
currentTarget = listView
|
||||
|
||||
function listView:cleanUp()
|
||||
print("tableView cleanUp")
|
||||
Runtime:removeEventListener("enterFrame", moveCat )
|
||||
Runtime:removeEventListener("enterFrame", scrollList )
|
||||
Runtime:removeEventListener( "enterFrame", showHighlight )
|
||||
Runtime:removeEventListener("enterFrame", trackVelocity)
|
||||
local i
|
||||
for i = listView.numChildren, 1, -1 do
|
||||
--test
|
||||
listView[i]:removeEventListener("touch", newListItemHandler)
|
||||
listView:remove(i)
|
||||
listView[i] = nil
|
||||
end
|
||||
end
|
||||
|
||||
return listView
|
||||
end
|
||||
|
||||
function scrollList(event)
|
||||
local friction = 0.9
|
||||
local timePassed = event.time - lastTime
|
||||
lastTime = lastTime + timePassed
|
||||
|
||||
--turn off scrolling if velocity is near zero
|
||||
if math.abs(velocity) < .01 then
|
||||
velocity = 0
|
||||
Runtime:removeEventListener("enterFrame", scrollList )
|
||||
end
|
||||
|
||||
velocity = velocity*friction
|
||||
|
||||
currentTarget.y = math.floor(currentTarget.y + velocity*timePassed)
|
||||
|
||||
moveCat()
|
||||
|
||||
local upperLimit = currentTarget.top
|
||||
local bottomLimit = screenH - currentTarget.height - currentTarget.bottom
|
||||
|
||||
if ( currentTarget.y > upperLimit ) then
|
||||
velocity = 0
|
||||
Runtime:removeEventListener("enterFrame", scrollList )
|
||||
Runtime:addEventListener("enterFrame", moveCat )
|
||||
currentTarget.tween = transition.to(currentTarget, { time=400, y=upperLimit, transition=easing.outQuad})
|
||||
elseif ( currentTarget.y < bottomLimit and bottomLimit < 0 ) then
|
||||
velocity = 0
|
||||
Runtime:removeEventListener("enterFrame", scrollList )
|
||||
Runtime:addEventListener("enterFrame", moveCat )
|
||||
currentTarget.tween = transition.to(currentTarget, { time=400, y=bottomLimit, transition=easing.outQuad})
|
||||
elseif ( currentTarget.y < bottomLimit ) then
|
||||
velocity = 0
|
||||
Runtime:removeEventListener("enterFrame", scrollList )
|
||||
Runtime:addEventListener("enterFrame", moveCat )
|
||||
currentTarget.tween = transition.to(currentTarget, { time=400, y=upperLimit, transition=easing.outQuad})
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function moveCat()
|
||||
local upperLimit = currentTarget.top
|
||||
|
||||
for i=1, #currentTarget.c do
|
||||
if( currentTarget.y > upperLimit - currentTarget.c[i].yInit ) then
|
||||
currentTarget.c[i].y = currentTarget.c[i].yInit
|
||||
end
|
||||
|
||||
if ( currentTarget.y < upperLimit - currentTarget.c[i].yInit ) then
|
||||
currentTarget.c[i].y = upperLimit - currentTarget.y
|
||||
end
|
||||
|
||||
if( i > 1 ) then
|
||||
if ( currentTarget.c[i].y < currentTarget.c[i-1].y + currentTarget.c[i].height ) then
|
||||
currentTarget.c[i-1].y = currentTarget.c[i].y - currentTarget.c[i].height
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function trackVelocity(event)
|
||||
local timePassed = event.time - prevTime
|
||||
prevTime = prevTime + timePassed
|
||||
|
||||
if prevY then
|
||||
velocity = (currentTarget.y - prevY)/timePassed
|
||||
end
|
||||
prevY = currentTarget.y
|
||||
end
|
||||
|
||||
--look for an item in a table
|
||||
function in_table ( e, t )
|
||||
for _,v in pairs(t) do
|
||||
if (v==e) then return true end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
289
app/corona/ui.lua
Normal file
@@ -0,0 +1,289 @@
|
||||
-- ui.lua (currently includes Button class with labels, font selection and optional event model)
|
||||
|
||||
-- Version 1.5 (works with multitouch, adds setText() method to buttons)
|
||||
--
|
||||
-- Copyright (C) 2010 ANSCA Inc. All Rights Reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
-- this software and associated documentation files (the "Software"), to deal in the
|
||||
-- Software without restriction, including without limitation the rights to use, copy,
|
||||
-- modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
-- and to permit persons to whom the Software is furnished to do so, subject to the
|
||||
-- following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in all copies
|
||||
-- or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
-- FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
-- OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
-- DEALINGS IN THE SOFTWARE.
|
||||
|
||||
module(..., package.seeall)
|
||||
|
||||
-----------------
|
||||
-- Helper function for newButton utility function below
|
||||
local function newButtonHandler( self, event )
|
||||
|
||||
local result = true
|
||||
|
||||
local default = self[1]
|
||||
local over = self[2]
|
||||
|
||||
-- General "onEvent" function overrides onPress and onRelease, if present
|
||||
local onEvent = self._onEvent
|
||||
|
||||
local onPress = self._onPress
|
||||
local onRelease = self._onRelease
|
||||
|
||||
local buttonEvent = {}
|
||||
if (self._id) then
|
||||
buttonEvent.id = self._id
|
||||
end
|
||||
|
||||
local phase = event.phase
|
||||
if "began" == phase then
|
||||
if over then
|
||||
default.isVisible = false
|
||||
over.isVisible = true
|
||||
end
|
||||
|
||||
if onEvent then
|
||||
buttonEvent.phase = "press"
|
||||
result = onEvent( buttonEvent )
|
||||
elseif onPress then
|
||||
result = onPress( event )
|
||||
end
|
||||
|
||||
-- Subsequent touch events will target button even if they are outside the contentBounds of button
|
||||
display.getCurrentStage():setFocus( self, event.id )
|
||||
self.isFocus = true
|
||||
|
||||
elseif self.isFocus then
|
||||
local bounds = self.contentBounds
|
||||
local x,y = event.x,event.y
|
||||
local isWithinBounds =
|
||||
bounds.xMin <= x and bounds.xMax >= x and bounds.yMin <= y and bounds.yMax >= y
|
||||
|
||||
if "moved" == phase then
|
||||
if over then
|
||||
-- The rollover image should only be visible while the finger is within button's contentBounds
|
||||
default.isVisible = not isWithinBounds
|
||||
over.isVisible = isWithinBounds
|
||||
end
|
||||
|
||||
elseif "ended" == phase or "cancelled" == phase then
|
||||
if over then
|
||||
default.isVisible = true
|
||||
over.isVisible = false
|
||||
end
|
||||
|
||||
if "ended" == phase then
|
||||
-- Only consider this a "click" if the user lifts their finger inside button's contentBounds
|
||||
if isWithinBounds then
|
||||
if onEvent then
|
||||
buttonEvent.phase = "release"
|
||||
result = onEvent( buttonEvent )
|
||||
elseif onRelease then
|
||||
result = onRelease( event )
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Allow touch events to be sent normally to the objects they "hit"
|
||||
display.getCurrentStage():setFocus( self, nil )
|
||||
self.isFocus = false
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
---------------
|
||||
-- Button class
|
||||
|
||||
function newButton( params )
|
||||
local button, default, over, size, font, textColor, offset
|
||||
|
||||
if params.default then
|
||||
button = display.newGroup()
|
||||
default = display.newImage( params.default )
|
||||
button:insert( default, true )
|
||||
end
|
||||
|
||||
if params.over then
|
||||
over = display.newImage( params.over )
|
||||
over.isVisible = false
|
||||
button:insert( over, true )
|
||||
end
|
||||
|
||||
-- Public methods
|
||||
function button:setText( newText )
|
||||
|
||||
local labelText = self.text
|
||||
if ( labelText ) then
|
||||
labelText:removeSelf()
|
||||
self.text = nil
|
||||
end
|
||||
|
||||
local labelShadow = self.shadow
|
||||
if ( labelShadow ) then
|
||||
labelShadow:removeSelf()
|
||||
self.shadow = nil
|
||||
end
|
||||
|
||||
local labelHighlight = self.highlight
|
||||
if ( labelHighlight ) then
|
||||
labelHighlight:removeSelf()
|
||||
self.highlight = nil
|
||||
end
|
||||
|
||||
if ( params.size and type(params.size) == "number" ) then size=params.size else size=20 end
|
||||
if ( params.font ) then font=params.font else font=native.systemFontBold end
|
||||
if ( params.textColor ) then textColor=params.textColor else textColor={ 255, 255, 255, 255 } end
|
||||
|
||||
-- Optional vertical correction for fonts with unusual baselines (I'm looking at you, Zapfino)
|
||||
if ( params.offset and type(params.offset) == "number" ) then offset=params.offset else offset = 0 end
|
||||
|
||||
if ( params.emboss ) then
|
||||
-- Make the label text look "embossed" (also adjusts effect for textColor brightness)
|
||||
local textBrightness = ( textColor[1] + textColor[2] + textColor[3] ) / 3
|
||||
|
||||
labelHighlight = display.newText( newText, 0, 0, font, size )
|
||||
if ( textBrightness > 127) then
|
||||
labelHighlight:setTextColor( 255, 255, 255, 20 )
|
||||
else
|
||||
labelHighlight:setTextColor( 255, 255, 255, 140 )
|
||||
end
|
||||
button:insert( labelHighlight, true )
|
||||
labelHighlight.x = labelHighlight.x + 1.5; labelHighlight.y = labelHighlight.y + 1.5 + offset
|
||||
self.highlight = labelHighlight
|
||||
|
||||
labelShadow = display.newText( newText, 0, 0, font, size )
|
||||
if ( textBrightness > 127) then
|
||||
labelShadow:setTextColor( 0, 0, 0, 128 )
|
||||
else
|
||||
labelShadow:setTextColor( 0, 0, 0, 20 )
|
||||
end
|
||||
button:insert( labelShadow, true )
|
||||
labelShadow.x = labelShadow.x - 1; labelShadow.y = labelShadow.y - 1 + offset
|
||||
self.shadow = labelShadow
|
||||
end
|
||||
|
||||
labelText = display.newText( newText, 0, 0, font, size )
|
||||
labelText:setTextColor( textColor[1], textColor[2], textColor[3], textColor[4] )
|
||||
button:insert( labelText, true )
|
||||
labelText.y = labelText.y + offset
|
||||
self.text = labelText
|
||||
end
|
||||
|
||||
if params.text then
|
||||
button:setText( params.text )
|
||||
end
|
||||
|
||||
if ( params.onPress and ( type(params.onPress) == "function" ) ) then
|
||||
button._onPress = params.onPress
|
||||
end
|
||||
if ( params.onRelease and ( type(params.onRelease) == "function" ) ) then
|
||||
button._onRelease = params.onRelease
|
||||
end
|
||||
|
||||
if (params.onEvent and ( type(params.onEvent) == "function" ) ) then
|
||||
button._onEvent = params.onEvent
|
||||
end
|
||||
|
||||
-- Set button as a table listener by setting a table method and adding the button as its own table listener for "touch" events
|
||||
button.touch = newButtonHandler
|
||||
button:addEventListener( "touch", button )
|
||||
|
||||
if params.x then
|
||||
button.x = params.x
|
||||
end
|
||||
|
||||
if params.y then
|
||||
button.y = params.y
|
||||
end
|
||||
|
||||
if params.id then
|
||||
button._id = params.id
|
||||
end
|
||||
|
||||
return button
|
||||
end
|
||||
|
||||
|
||||
--------------
|
||||
-- Label class
|
||||
|
||||
function newLabel( params )
|
||||
local labelText
|
||||
local size, font, textColor, align
|
||||
local t = display.newGroup()
|
||||
|
||||
if ( params.bounds ) then
|
||||
local bounds = params.bounds
|
||||
local left = bounds[1]
|
||||
local top = bounds[2]
|
||||
local width = bounds[3]
|
||||
local height = bounds[4]
|
||||
|
||||
if ( params.size and type(params.size) == "number" ) then size=params.size else size=20 end
|
||||
if ( params.font ) then font=params.font else font=native.systemFontBold end
|
||||
if ( params.textColor ) then textColor=params.textColor else textColor={ 255, 255, 255, 255 } end
|
||||
if ( params.offset and type(params.offset) == "number" ) then offset=params.offset else offset = 0 end
|
||||
if ( params.align ) then align = params.align else align = "center" end
|
||||
|
||||
if ( params.text ) then
|
||||
labelText = display.newText( params.text, 0, 0, font, size )
|
||||
labelText:setTextColor( textColor[1], textColor[2], textColor[3], textColor[4] )
|
||||
t:insert( labelText )
|
||||
-- TODO: handle no-initial-text case by creating a field with an empty string?
|
||||
|
||||
if ( align == "left" ) then
|
||||
labelText.x = left + labelText.contentWidth * 0.5
|
||||
elseif ( align == "right" ) then
|
||||
labelText.x = (left + width) - labelText.contentWidth * 0.5
|
||||
else
|
||||
labelText.x = ((2 * left) + width) * 0.5
|
||||
end
|
||||
end
|
||||
|
||||
labelText.y = top + labelText.contentHeight * 0.5
|
||||
|
||||
-- Public methods
|
||||
function t:setText( newText )
|
||||
if ( newText ) then
|
||||
labelText.text = newText
|
||||
|
||||
if ( "left" == align ) then
|
||||
labelText.x = left + labelText.contentWidth / 2
|
||||
elseif ( "right" == align ) then
|
||||
labelText.x = (left + width) - labelText.contentWidth / 2
|
||||
else
|
||||
labelText.x = ((2 * left) + width) / 2
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function t:setTextColor( r, g, b, a )
|
||||
local newR = 255
|
||||
local newG = 255
|
||||
local newB = 255
|
||||
local newA = 255
|
||||
|
||||
if ( r and type(r) == "number" ) then newR = r end
|
||||
if ( g and type(g) == "number" ) then newG = g end
|
||||
if ( b and type(b) == "number" ) then newB = b end
|
||||
if ( a and type(a) == "number" ) then newA = a end
|
||||
|
||||
labelText:setTextColor( r, g, b, a )
|
||||
end
|
||||
end
|
||||
|
||||
-- Return instance (as display group)
|
||||
return t
|
||||
|
||||
end
|
||||
33
app/corona/utf8sub.lua
Normal file
@@ -0,0 +1,33 @@
|
||||
local function chsize(char)
|
||||
if not char then
|
||||
return 0
|
||||
elseif char > 240 then
|
||||
return 4
|
||||
elseif char > 225 then
|
||||
return 3
|
||||
elseif char > 192 then
|
||||
return 2
|
||||
else
|
||||
return 1
|
||||
end
|
||||
end
|
||||
|
||||
function utf8sub(str, startChar, numChars)
|
||||
local startIndex = 1
|
||||
while startChar > 1 do
|
||||
local char = string.byte(str, startIndex)
|
||||
startIndex = startIndex + chsize(char)
|
||||
startChar = startChar - 1
|
||||
end
|
||||
|
||||
local currentIndex = startIndex
|
||||
|
||||
while numChars > 0 and currentIndex <= #str do
|
||||
local char = string.byte(str, currentIndex)
|
||||
currentIndex = currentIndex + chsize(char)
|
||||
numChars = numChars -1
|
||||
end
|
||||
return str:sub(startIndex, currentIndex - 1)
|
||||
end
|
||||
|
||||
|
||||
321
app/corona/util.lua
Normal file
@@ -0,0 +1,321 @@
|
||||
-- util.lua
|
||||
--
|
||||
-- Version 1.0
|
||||
--
|
||||
-- Copyright (C) 2010 ANSCA Inc. All Rights Reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
-- this software and associated documentation files (the "Software"), to deal in the
|
||||
-- Software without restriction, including without limitation the rights to use, copy,
|
||||
-- modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
-- and to permit persons to whom the Software is furnished to do so, subject to the
|
||||
-- following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in all copies
|
||||
-- or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
-- FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
-- OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
-- DEALINGS IN THE SOFTWARE.
|
||||
|
||||
module(..., package.seeall)
|
||||
|
||||
-- set some global values for width and height of the screen
|
||||
local screenW, screenH = display.contentWidth, display.contentHeight
|
||||
local viewableScreenW, viewableScreenH = display.viewableContentWidth, display.viewableContentHeight
|
||||
local screenOffsetW, screenOffsetH = display.contentWidth - display.viewableContentWidth, display.contentHeight - display.viewableContentHeight
|
||||
|
||||
--------------------------------------------
|
||||
-- Wrap text
|
||||
function wrap(str, limit, indent, indent1)
|
||||
indent = indent or ""
|
||||
indent1 = indent1 or indent
|
||||
limit = limit or 72
|
||||
local here = 1-#indent1
|
||||
return indent1..str:gsub("(%s+)()(%S+)()",
|
||||
function(sp, st, word, fi)
|
||||
if fi-here > limit then
|
||||
here = st - #indent
|
||||
return "\n"..indent..word
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function explode(div,str)
|
||||
if (div=='') then return false end
|
||||
local pos,arr = 0,{}
|
||||
-- for each divider found
|
||||
for st,sp in function() return string.find(str,div,pos,true) end do
|
||||
table.insert(arr,string.sub(str,pos,st-1)) -- Attach chars left of current divider
|
||||
pos = sp + 1 -- Jump past current divider
|
||||
end
|
||||
table.insert(arr,string.sub(str,pos)) -- Attach chars right of last divider
|
||||
return arr
|
||||
end
|
||||
|
||||
|
||||
function wrappedText(str, limit, size, font, color, indent, indent1)
|
||||
str = explode("\n", str)
|
||||
size = tonumber(size) or 12
|
||||
color = color or {255, 255, 255}
|
||||
font = font or "Helvetica"
|
||||
|
||||
--apply line breaks using the wrapping function
|
||||
local i = 1
|
||||
local strFinal = ""
|
||||
while i <= #str do
|
||||
strW = wrap(str[i], limit, indent, indent1)
|
||||
strFinal = strFinal.."\n"..strW
|
||||
i = i + 1
|
||||
end
|
||||
str = strFinal
|
||||
|
||||
--search for each line that ends with a line break and add to an array
|
||||
local pos, arr = 0, {}
|
||||
for st,sp in function() return string.find(str,"\n",pos,true) end do
|
||||
table.insert(arr,string.sub(str,pos,st-1))
|
||||
pos = sp + 1
|
||||
end
|
||||
table.insert(arr,string.sub(str,pos))
|
||||
|
||||
--iterate through the array and add each item as a display object to the group
|
||||
local g = display.newGroup()
|
||||
local i = 1
|
||||
while i <= #arr do
|
||||
local t = display.newText( arr[i], 0, 0, font, size )
|
||||
t:setTextColor( color[1], color[2], color[3] )
|
||||
t.x = math.floor(t.width/2)
|
||||
t.y = math.floor((size*1.3)*(i-1))
|
||||
g:insert(t)
|
||||
i = i + 1
|
||||
end
|
||||
return g
|
||||
end
|
||||
|
||||
--[[
|
||||
|
||||
-- USAGE:
|
||||
local myText = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc euismod justo sapien, at sollicitudin lacus. Quisque vestibulum commodo felis id posuere."
|
||||
local myTextObject = wrappedText(myText, 46)
|
||||
--local myTextObject = wrappedText(myText, 46, 16)
|
||||
--local myTextObject = wrappedText(myText, 46, 16, {255, 0, 0})
|
||||
local myGroup = display.newGroup()
|
||||
myGroup:insert( myTextObject )
|
||||
|
||||
]]--
|
||||
|
||||
|
||||
--------------------------------------------
|
||||
-- XML Parser
|
||||
function parseargs(s)
|
||||
local arg = {}
|
||||
string.gsub(s, "(%w+)=([\"'])(.-)%2", function (w, _, a)
|
||||
arg[w] = a
|
||||
end)
|
||||
return arg
|
||||
end
|
||||
|
||||
function collect(s)
|
||||
local stack = {}
|
||||
local top = {}
|
||||
table.insert(stack, top)
|
||||
local ni,c,label,xarg, empty
|
||||
local i, j = 1, 1
|
||||
while true do
|
||||
ni,j,c,label,xarg, empty = string.find(s, "<(%/?)([%w:]+)(.-)(%/?)>", i)
|
||||
if not ni then break end
|
||||
local text = string.sub(s, i, ni-1)
|
||||
if not string.find(text, "^%s*$") then
|
||||
table.insert(top, text)
|
||||
end
|
||||
if empty == "/" then -- empty element tag
|
||||
table.insert(top, {label=label, xarg=parseargs(xarg), empty=1})
|
||||
elseif c == "" then -- start tag
|
||||
top = {label=label, xarg=parseargs(xarg)}
|
||||
table.insert(stack, top) -- new level
|
||||
else -- end tag
|
||||
local toclose = table.remove(stack) -- remove top
|
||||
top = stack[#stack]
|
||||
if #stack < 1 then
|
||||
error("nothing to close with "..label)
|
||||
end
|
||||
if toclose.label ~= label then
|
||||
error("trying to close "..toclose.label.." with "..label)
|
||||
end
|
||||
table.insert(top, toclose)
|
||||
end
|
||||
i = j+1
|
||||
end
|
||||
local text = string.sub(s, i)
|
||||
if not string.find(text, "^%s*$") then
|
||||
table.insert(stack[#stack], text)
|
||||
end
|
||||
if #stack > 1 then
|
||||
error("unclosed "..stack[stack.n].label)
|
||||
end
|
||||
return stack[1]
|
||||
end
|
||||
|
||||
------------------------------
|
||||
|
||||
function aLink(e)
|
||||
local t = e.target
|
||||
if (t.link) then
|
||||
print(e.target.link)
|
||||
system.openURL( e.target.link )
|
||||
else
|
||||
print("no link found")
|
||||
end
|
||||
end
|
||||
|
||||
--------------------------------------------
|
||||
-- Helper function for newLink utility function below
|
||||
local function newLinkHandler( self, event )
|
||||
local result = true
|
||||
local default = self[1]
|
||||
local over = self[2]
|
||||
local t = self.parent
|
||||
local phase = event.phase
|
||||
print ("newButtonHandler: "..phase)
|
||||
|
||||
if over then
|
||||
linkCurrentDefault = default
|
||||
linkCurrentRollover = over
|
||||
end
|
||||
|
||||
local function showHighlight (event)
|
||||
local timePassed = event.time - startTime
|
||||
print("timePassed: "..timePassed)
|
||||
|
||||
if timePassed > 100 then
|
||||
print("highlight")
|
||||
linkCurrentDefault.isVisible = false
|
||||
linkCurrentRollover.isVisible = true
|
||||
Runtime:removeEventListener( "enterFrame", showHighlight )
|
||||
end
|
||||
end
|
||||
|
||||
if "began" == phase then
|
||||
t.startPos = event.y
|
||||
t.prevPos = event.y
|
||||
t.delta, t.velocity = 0, 0
|
||||
if t.tween then transition.cancel(t.tween) end
|
||||
Runtime:removeEventListener("enterFrame", t )
|
||||
|
||||
self.prevTime = 0
|
||||
self.prevY = 0
|
||||
|
||||
if over then
|
||||
startTime = event.time
|
||||
Runtime:addEventListener( "enterFrame", showHighlight )
|
||||
end
|
||||
|
||||
local onPress = self._onPress
|
||||
if onPress then
|
||||
result = onPress( event )
|
||||
end
|
||||
|
||||
-- Subsequent touch events will target button even if they are outside the contentBounds of button
|
||||
display.getCurrentStage():setFocus( self )
|
||||
self.isFocus = true
|
||||
|
||||
elseif self.isFocus then
|
||||
|
||||
if "moved" == phase then
|
||||
local bottomLimit = screenH - t.height - t.bottom
|
||||
|
||||
t.delta = event.y - t.prevPos
|
||||
t.prevPos = event.y
|
||||
if ( t.y > t.top or t.y < bottomLimit ) then
|
||||
t.y = t.y + t.delta/2
|
||||
else
|
||||
t.y = t.y + t.delta
|
||||
end
|
||||
|
||||
--Track velocity while the user is moving the view
|
||||
local timePassed = event.time - t.prevTime
|
||||
t.prevTime = t.prevTime + timePassed
|
||||
if t.prevY then
|
||||
t.velocity = (t.y - t.prevY)/timePassed
|
||||
end
|
||||
t.prevY = t.y
|
||||
|
||||
if over then
|
||||
Runtime:removeEventListener( "enterFrame", showHighlight )
|
||||
-- the over image should only be visible while the finger is within button's contentBounds
|
||||
default.isVisible = true --not isWithinBounds
|
||||
over.isVisible = false --isWithinBounds
|
||||
end
|
||||
elseif "ended" == phase or "cancelled" == phase then
|
||||
local dragDistance = event.y - t.startPos
|
||||
t.lastTime = event.time
|
||||
|
||||
Runtime:addEventListener("enterFrame", t )
|
||||
|
||||
local bounds = self.contentBounds
|
||||
local x,y = event.x,event.y
|
||||
local isWithinBounds =
|
||||
bounds.xMin <= x and bounds.xMax >= x and bounds.yMin <= y and bounds.yMax >= y
|
||||
|
||||
if over then
|
||||
Runtime:removeEventListener( "enterFrame", showHighlight )
|
||||
default.isVisible = true
|
||||
over.isVisible = false
|
||||
end
|
||||
|
||||
-- Only consider this a "click", if the user lifts their finger inside button's contentBounds
|
||||
if isWithinBounds and (dragDistance < 10 and dragDistance > -10 ) then
|
||||
result = self._onRelease( event )
|
||||
end
|
||||
|
||||
-- Allow touch events to be sent normally to the objects they "hit"
|
||||
display.getCurrentStage():setFocus( nil )
|
||||
self.isFocus = false
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
|
||||
function newLink( params )
|
||||
local button
|
||||
|
||||
if params.default and params.onRelease then
|
||||
button = display.newGroup()
|
||||
local default = display.newImage( params.default )
|
||||
button:insert( default, true )
|
||||
|
||||
if params.over then
|
||||
local over = display.newImage( params.over )
|
||||
over.isVisible = false
|
||||
button:insert( over, true )
|
||||
end
|
||||
|
||||
if type( params.onPress ) == "function" then
|
||||
button._onPress = params.onPress
|
||||
end
|
||||
if type( params.onRelease ) == "function" then
|
||||
button._onRelease = params.onRelease
|
||||
end
|
||||
|
||||
button.buttonID = params.buttonID
|
||||
|
||||
-- Set button as a table listener by setting a table method and adding the button as its own table listener for "touch" events
|
||||
button.touch = newLinkHandler
|
||||
button:addEventListener( "touch", button )
|
||||
end
|
||||
|
||||
if params.x then
|
||||
button.x = params.x
|
||||
end
|
||||
if params.y then
|
||||
button.y = params.y
|
||||
end
|
||||
|
||||
return button
|
||||
end
|
||||
92
app/corona/viewBug.lua
Normal file
@@ -0,0 +1,92 @@
|
||||
require("htmltotext")
|
||||
require("utf8sub")
|
||||
|
||||
local storyboard = require "storyboard"
|
||||
local scene = storyboard.newScene()
|
||||
|
||||
local function backButtonRelease( self, event )
|
||||
storyboard.gotoScene("index", "slideRight", 100)
|
||||
end
|
||||
|
||||
-- 第一创建的时候才把代码放在这里,以后重新进入就不会调用createScene了
|
||||
-- 所以逻辑代码应该放到enterScene中
|
||||
function scene:createScene(event)
|
||||
local screenGroup = self.view
|
||||
|
||||
local backgroundImg = display.newImage("background.png")
|
||||
backgroundImg.xOrigin = display.contentWidth/2
|
||||
backgroundImg.yOrigin = display.contentHeight/2
|
||||
screenGroup:insert(backgroundImg)
|
||||
end
|
||||
|
||||
function scene:enterScene( event )
|
||||
local screenGroup = self.view
|
||||
|
||||
display.setStatusBar( display.HiddenStatusBar )
|
||||
|
||||
--import the scrolling classes
|
||||
local scrollView = require("scrollView")
|
||||
|
||||
-- Setup a scrollable content group
|
||||
local scrollView = scrollView.new{ top=display.screenOriginY, bottom=display.screenOriginY }
|
||||
screenGroup:insert(scrollView)
|
||||
|
||||
local fontSize = 18
|
||||
local textHeight = fontSize+10
|
||||
local startX = 10
|
||||
local startY = 10
|
||||
local lineLimit = math.floor(display.contentWidth / fontSize)
|
||||
local output = ""
|
||||
local i = 0
|
||||
|
||||
-- display bug title
|
||||
local title = "#" .. myBugs[currentBugID].id .. " " .. myBugs[currentBugID].title
|
||||
while string.len(output) < string.len(title) do
|
||||
output = output .. utf8sub(title, i*lineLimit+1, lineLimit) .. "\n"
|
||||
i = i+1
|
||||
end
|
||||
local titleText = display.newText(output, startX, startY, system.defaultFontBold, fontSize)
|
||||
titleText:setTextColor(0, 0, 0)
|
||||
scrollView:insert(titleText)
|
||||
startY = startY + (i-1)*textHeight
|
||||
|
||||
-- display bug basic information
|
||||
output = ""
|
||||
i = 0
|
||||
local steps = "步骤:" .. HTML_ToText(myBugs[currentBugID].steps)
|
||||
local steps = string.gsub(steps, "\n", "")
|
||||
while string.len(output) < string.len(steps) do
|
||||
output = output .. utf8sub(steps, i*lineLimit+1, lineLimit) .. "\n"
|
||||
i = i+1
|
||||
end
|
||||
local stepsText = display.newText(output, startX, startY + 2*textHeight, system.defaultFont, 14)
|
||||
stepsText:setTextColor(0, 0, 0)
|
||||
scrollView:insert(stepsText)
|
||||
|
||||
backButton = ui.newButton{
|
||||
default = "backButton.png",
|
||||
over = "backButton_over.png",
|
||||
onRelease = backButtonRelease,
|
||||
size = 16,
|
||||
emboss = true
|
||||
}
|
||||
backButton.xOrigin = display.contentWidth - backButton.width/2
|
||||
backButton.yOrigin = display.contentHeight - backButton.height/2 - display.screenOriginY
|
||||
screenGroup:insert(backButton)
|
||||
|
||||
scrollView:addScrollBar()
|
||||
|
||||
end
|
||||
|
||||
function scene:exitScene( event )
|
||||
end
|
||||
|
||||
function scene:destroyScene( event )
|
||||
end
|
||||
|
||||
scene:addEventListener("createScene", scene )
|
||||
scene:addEventListener("enterScene", scene )
|
||||
scene:addEventListener("exitScene", scene )
|
||||
scene:addEventListener("destroyScene", scene )
|
||||
|
||||
return scene
|
||||
110
app/corona/viewController.lua
Normal file
@@ -0,0 +1,110 @@
|
||||
-- viewController.lua, View Controller Library
|
||||
--
|
||||
-- Version 1.0, currently supports tabs
|
||||
--
|
||||
-- Copyright (C) 2010 ANSCA Inc. All Rights Reserved.
|
||||
--
|
||||
-- Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
-- this software and associated documentation files (the "Software"), to deal in the
|
||||
-- Software without restriction, including without limitation the rights to use, copy,
|
||||
-- modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
-- and to permit persons to whom the Software is furnished to do so, subject to the
|
||||
-- following conditions:
|
||||
--
|
||||
-- The above copyright notice and this permission notice shall be included in all copies
|
||||
-- or substantial portions of the Software.
|
||||
--
|
||||
-- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
-- INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
|
||||
-- PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
|
||||
-- FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
|
||||
-- OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
-- DEALINGS IN THE SOFTWARE.
|
||||
|
||||
module(..., package.seeall)
|
||||
|
||||
--initial values
|
||||
local screenW, screenH = display.contentWidth, display.contentHeight
|
||||
local viewableScreenW, viewableScreenH = display.viewableContentWidth, display.viewableContentHeight
|
||||
local screenOffsetW, screenOffsetH = display.contentWidth - display.viewableContentWidth, display.contentHeight - display.viewableContentHeight
|
||||
|
||||
function newTabBar(params)
|
||||
local background = params.background
|
||||
local tabs = params.tabs
|
||||
local default = params.default
|
||||
local over = params.over
|
||||
local onRelease = params.onRelease
|
||||
|
||||
local tabBar = display.newGroup()
|
||||
|
||||
if background then
|
||||
local tabBG = display.newImage("tabBar.png")
|
||||
tabBar:insert(tabBG)
|
||||
end
|
||||
|
||||
--check for tab and tab over images specified by the user
|
||||
if not default then
|
||||
--if no tab images, use tab1.png, tab2.png, etc.
|
||||
default = {}
|
||||
for i=1, #tabs do
|
||||
table.insert(default, "tab".. i ..".png")
|
||||
end
|
||||
end
|
||||
if not over then
|
||||
--if no tab over images, use tab1_over.png, tab2_over.png, etc.
|
||||
over = {}
|
||||
for i=1, #tabs do
|
||||
table.insert(over, "tab".. i .."_over.png")
|
||||
end
|
||||
end
|
||||
|
||||
tabBar.y = math.floor(screenH - tabBar.height - display.screenOriginY)
|
||||
tabBar.x = 0
|
||||
|
||||
--create the tabs
|
||||
for i=1, #tabs do
|
||||
local tab = ui.newButton{
|
||||
default = default[i],
|
||||
over = over[i],
|
||||
onRelease = onRelease,
|
||||
text = tabs[i],
|
||||
textColor = {0, 0, 0, 165},
|
||||
font = "Helvetica",
|
||||
size = 14,
|
||||
}
|
||||
tabBar:insert(tab)
|
||||
|
||||
local numberOfTabs = #tabs
|
||||
local tabButtonWidth = tab.width
|
||||
local totalButtonWidth = tabButtonWidth * numberOfTabs
|
||||
local tabSpacing = (screenW - totalButtonWidth)/(numberOfTabs+1)
|
||||
|
||||
tab.x = tab.width*(i-1) + tabSpacing * i + tab.width*0.5
|
||||
tab.y = tab.height*0.5
|
||||
|
||||
tab.id = i
|
||||
end
|
||||
|
||||
tabBar.selected = function(target)
|
||||
if not target then target = tabBar[2] end
|
||||
if tabBar.highlight then tabBar:remove(tabBar.highlight) end
|
||||
|
||||
local highlight = ui.newButton{
|
||||
default = over[target.id],
|
||||
over = default[target.id],
|
||||
onRelease = onRelease,
|
||||
text = tabs[target.id],
|
||||
font = "Helvetica",
|
||||
size = 14,
|
||||
}
|
||||
highlight.id = target.id
|
||||
tabBar:insert(highlight)
|
||||
|
||||
highlight.x = target.x
|
||||
highlight.y = target.y
|
||||
|
||||
tabBar.highlight = highlight
|
||||
end
|
||||
|
||||
return tabBar
|
||||
end
|
||||
87
app/corona/viewTask.lua
Normal file
@@ -0,0 +1,87 @@
|
||||
require("htmltotext")
|
||||
require("utf8sub")
|
||||
|
||||
local storyboard = require "storyboard"
|
||||
local scene = storyboard.newScene()
|
||||
|
||||
local function backButtonRelease( self, event )
|
||||
storyboard.gotoScene("index", "slideRight", 100)
|
||||
end
|
||||
|
||||
function scene:createScene(event)
|
||||
local screenGroup = self.view
|
||||
|
||||
local backgroundImg = display.newImage("view_background.png")
|
||||
backgroundImg.xOrigin = display.contentWidth/2
|
||||
backgroundImg.yOrigin = display.contentHeight/2
|
||||
screenGroup:insert(backgroundImg)
|
||||
end
|
||||
|
||||
function scene:enterScene( event )
|
||||
local screenGroup = self.view
|
||||
|
||||
--import the scrolling classes
|
||||
local scrollView = require("scrollView")
|
||||
|
||||
-- Setup a scrollable content group
|
||||
local scrollView = scrollView.new{top=display.screenOriginY, bottom=display.screenOriginY}
|
||||
screenGroup:insert(scrollView)
|
||||
|
||||
local fontSize = 18
|
||||
local textHeight = fontSize+10
|
||||
local startX = 10
|
||||
local startY = 10
|
||||
local lineLimit = math.floor(display.contentWidth / fontSize)
|
||||
local output = ""
|
||||
local i = 0
|
||||
|
||||
-- display task name
|
||||
local name = "#" .. myTasks[currentTaskID].id .. " " .. myTasks[currentTaskID].name
|
||||
while string.len(output) < string.len(name) do
|
||||
output = output .. utf8sub(name, i*lineLimit+1, lineLimit) .. "\n"
|
||||
i = i+1
|
||||
end
|
||||
local nameText = display.newText(output, startX, startY, system.defaultFontBold, fontSize)
|
||||
nameText:setTextColor(0, 0, 0)
|
||||
scrollView:insert(nameText)
|
||||
startY = startY + (i-1)*textHeight
|
||||
|
||||
output = ""
|
||||
i = 0
|
||||
local desc = HTML_ToText(myTasks[currentTaskID].desc)
|
||||
local desc = string.gsub(desc, "\n", "")
|
||||
while string.len(output) < string.len(desc) do
|
||||
output = output .. utf8sub(desc, i*lineLimit+1, lineLimit) .. "\n"
|
||||
i = i+1
|
||||
end
|
||||
local descText = display.newText(output, startX, startY + textHeight, system.defaultFont, 14)
|
||||
descText:setTextColor(0, 0, 0)
|
||||
scrollView:insert(descText)
|
||||
startY = startY + (i-1)*textHeight
|
||||
|
||||
backButton = ui.newButton{
|
||||
default = "backButton.png",
|
||||
over = "backButton_over.png",
|
||||
onRelease = backButtonRelease,
|
||||
size = 16,
|
||||
emboss = true
|
||||
}
|
||||
backButton.xOrigin = display.contentWidth - backButton.width/2
|
||||
backButton.yOrigin = display.contentHeight - backButton.height/2 - display.screenOriginY
|
||||
screenGroup:insert(backButton)
|
||||
|
||||
scrollView:addScrollBar()
|
||||
end
|
||||
|
||||
function scene:exitScene( event )
|
||||
end
|
||||
|
||||
function scene:destroyScene( event )
|
||||
end
|
||||
|
||||
scene:addEventListener("createScene", scene )
|
||||
scene:addEventListener("enterScene", scene )
|
||||
scene:addEventListener("exitScene", scene )
|
||||
scene:addEventListener("destroyScene", scene )
|
||||
|
||||
return scene
|
||||
91
app/corona/viewTodo.lua
Normal file
@@ -0,0 +1,91 @@
|
||||
require("htmltotext")
|
||||
require("utf8sub")
|
||||
local storyboard = require "storyboard"
|
||||
local scene = storyboard.newScene()
|
||||
|
||||
local function backButtonRelease( self, event )
|
||||
storyboard.gotoScene("index", "slideRight", 100)
|
||||
end
|
||||
|
||||
function scene:createScene(event)
|
||||
local screenGroup = self.view
|
||||
|
||||
local backgroundImg = display.newImage("view_background.png")
|
||||
backgroundImg.xOrigin = display.contentWidth/2
|
||||
backgroundImg.yOrigin = display.contentHeight/2
|
||||
screenGroup:insert(backgroundImg)
|
||||
|
||||
end
|
||||
|
||||
function scene:enterScene( event )
|
||||
local screenGroup = self.view
|
||||
|
||||
display.setStatusBar( display.HiddenStatusBar )
|
||||
|
||||
--import the scrolling classes
|
||||
local scrollView = require("scrollView")
|
||||
|
||||
-- Setup a scrollable content group
|
||||
local scrollView = scrollView.new{ top=display.screenOriginY, bottom=display.screenOriginY }
|
||||
screenGroup:insert(scrollView)
|
||||
|
||||
local fontSize = 18
|
||||
local textHeight = fontSize+10
|
||||
local startX = 10
|
||||
local startY = 10
|
||||
local lineLimit = math.floor(display.contentWidth / fontSize)
|
||||
local output = ""
|
||||
local i = 0
|
||||
|
||||
-- display todo name
|
||||
local name = "#" .. myTodos[currentTodoID].id .. " " .. myTodos[currentTodoID].name
|
||||
while string.len(output) < string.len(name) do
|
||||
output = output .. utf8sub(name, i*lineLimit+1, lineLimit) .. "\n"
|
||||
i = i+1
|
||||
end
|
||||
local nameText = display.newText(output, startX, startY, system.defaultFontBold, fontSize)
|
||||
nameText:setTextColor(0, 0, 0)
|
||||
startY = startY + (i-1)*textHeight
|
||||
scrollView:insert(nameText)
|
||||
|
||||
-- desc text
|
||||
output = ""
|
||||
i = 0
|
||||
local desc = HTML_ToText(myTodos[currentTodoID].desc)
|
||||
local desc = string.gsub(desc, "\n", "")
|
||||
while string.len(output) < string.len(desc) do
|
||||
output = output .. utf8sub(desc, i*lineLimit+1, lineLimit) .. "\n"
|
||||
i = i+1
|
||||
end
|
||||
|
||||
local descText = display.newText(output, startX, startY + textHeight, system.defaultFont, 14)
|
||||
descText:setTextColor(0, 0, 0)
|
||||
scrollView:insert(descText)
|
||||
|
||||
backButton = ui.newButton{
|
||||
default = "backButton.png",
|
||||
over = "backButton_over.png",
|
||||
onRelease = backButtonRelease,
|
||||
size = 16,
|
||||
emboss = true
|
||||
}
|
||||
backButton.xOrigin = display.contentWidth - backButton.width/2
|
||||
backButton.yOrigin = display.contentHeight - backButton.height/2 - display.screenOriginY
|
||||
screenGroup:insert(backButton)
|
||||
|
||||
scrollView:addScrollBar()
|
||||
|
||||
end
|
||||
|
||||
function scene:exitScene( event )
|
||||
end
|
||||
|
||||
function scene:destroyScene( event )
|
||||
end
|
||||
|
||||
scene:addEventListener("createScene", scene )
|
||||
scene:addEventListener("enterScene", scene )
|
||||
scene:addEventListener("exitScene", scene )
|
||||
scene:addEventListener("destroyScene", scene )
|
||||
|
||||
return scene
|
||||
BIN
app/corona/view_background.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
app/corona/zentao.png
Normal file
|
After Width: | Height: | Size: 122 KiB |
26
bin/init.bat
@@ -42,7 +42,7 @@ echo backup.bat ok
|
||||
if %requestType% == 'PATH_INFO' (
|
||||
SET computeburn= %phpcli% %baseDir%ztcli "%pmsRoot%/report-remind"
|
||||
)else (
|
||||
SET computeburn= %phpcli% %baseDir%ztcli "%pmsRoot%/index.php?m=report&f=remind"
|
||||
SET computeburn= %phpcli% %baseDir%ztcli "%pmsRoot%/?m=report&f=remind"
|
||||
)
|
||||
echo %computeburn% > %baseDir%dailyreminder.bat
|
||||
echo dailyreminder.bat ok
|
||||
@@ -51,7 +51,7 @@ echo dailyreminder.bat ok
|
||||
if %requestType% == 'PATH_INFO' (
|
||||
SET computeburn= %phpcli% %baseDir%ztcli "%pmsRoot%/project-computeburn"
|
||||
)else (
|
||||
SET computeburn= %phpcli% %baseDir%ztcli "%pmsRoot%/index.php?m=project&f=computeburn"
|
||||
SET computeburn= %phpcli% %baseDir%ztcli "%pmsRoot%/?m=project&f=computeburn"
|
||||
)
|
||||
echo %computeburn% > %baseDir%computeburn.bat
|
||||
echo computeburn.bat ok
|
||||
@@ -60,28 +60,19 @@ echo computeburn.bat ok
|
||||
if %requestType% == 'PATH_INFO' (
|
||||
SET checkdb= %phpcli% %baseDir%ztcli "%pmsRoot%/admin-checkdb"
|
||||
)else (
|
||||
SET checkdb= %phpcli% %baseDir%ztcli "%pmsRoot%/index.php?m=admin&f=checkdb"
|
||||
SET checkdb= %phpcli% %baseDir%ztcli "%pmsRoot%/?m=admin&f=checkdb"
|
||||
)
|
||||
echo %checkdb% > %baseDir%checkdb.bat
|
||||
echo checkdb.bat ok
|
||||
|
||||
:: create syncsvn.bat
|
||||
if %requestType% == 'PATH_INFO' (
|
||||
SET syncsvn= %phpcli% %baseDir%ztcli "%pmsRoot%/svn-run"
|
||||
SET svnrun= %phpcli% %baseDir%ztcli "%pmsRoot%/svn-run"
|
||||
)else (
|
||||
SET syncsvn= %phpcli% %baseDir%ztcli "%pmsRoot%/index.php?m=svn&f=run"
|
||||
SET svnrun= %phpcli% %baseDir%ztcli "%pmsRoot%/?m=svn&f=run"
|
||||
)
|
||||
echo %syncsvn% > %baseDir%syncsvn.bat
|
||||
echo syncsvn.bat ok
|
||||
|
||||
:: create syncgit.bat
|
||||
if %requestType% == 'PATH_INFO' (
|
||||
SET syncgit= %phpcli% %baseDir%ztcli "%pmsRoot%/git-run"
|
||||
)else (
|
||||
SET syncgit= %phpcli% %baseDir%ztcli "%pmsRoot%/index.php?m=git&f=run"
|
||||
)
|
||||
echo %syncgit% > %baseDir%syncgit.bat
|
||||
echo syncgit.bat ok
|
||||
echo %svnrun% > %baseDir%svnrun.bat
|
||||
echo svnrun.bat ok
|
||||
|
||||
:: create crond.bat
|
||||
SET cron= %phpcli% %baseDir%php\crond.php
|
||||
@@ -95,8 +86,7 @@ echo #min hour day month week command. >> %sysCron%
|
||||
echo 0 1 * * * %baseDir%dailyreminder.bat # daily reminder. >> %sysCron%
|
||||
echo 1 1 * * * %baseDir%backup.bat # backup database and file. >> %sysCron%
|
||||
echo 1 23 * * * %baseDir%computeburn.bat # compute burndown chart. >> %sysCron%
|
||||
echo 1-59/2 * * * * %baseDir%syncsvn.bat # sync subversion. >> %sysCron%
|
||||
echo 1-59/2 * * * * %baseDir%syncgit.bat # sync git. >> %sysCron%
|
||||
echo 1-59/2 * * * * %baseDir%svnrun.bat # sync subversion. >> %sysCron%
|
||||
|
||||
:: return 0 when success.
|
||||
exit /b 0
|
||||
|
||||
27
bin/init.sh
@@ -50,7 +50,7 @@ echo "backup.sh ok"
|
||||
if [ $requestType == 'PATH_INFO' ]; then
|
||||
computeburn="$phpcli $basePath/ztcli '$pmsRoot/project-computeburn'";
|
||||
else
|
||||
computeburn="$phpcli $basePath/ztcli '$pmsRoot/index.php?m=project&f=computeburn'";
|
||||
computeburn="$phpcli $basePath/ztcli '$pmsRoot/?m=project&f=computeburn'";
|
||||
fi
|
||||
echo $computeburn > $basePath/computeburn.sh
|
||||
echo "computeburn.sh ok"
|
||||
@@ -59,7 +59,7 @@ echo "computeburn.sh ok"
|
||||
if [ $requestType == 'PATH_INFO' ]; then
|
||||
checkdb="$phpcli $basePath/ztcli '$pmsRoot/report-remind'";
|
||||
else
|
||||
checkdb="$phpcli $basePath/ztcli '$pmsRoot/index.php?m=report&f=remind'";
|
||||
checkdb="$phpcli $basePath/ztcli '$pmsRoot/?m=report&f=remind'";
|
||||
fi
|
||||
echo $checkdb > $basePath/dailyreminder.sh
|
||||
echo "dailyreminder.sh ok"
|
||||
@@ -68,38 +68,20 @@ echo "dailyreminder.sh ok"
|
||||
if [ $requestType == 'PATH_INFO' ]; then
|
||||
checkdb="$phpcli $basePath/ztcli '$pmsRoot/admin-checkdb'";
|
||||
else
|
||||
checkdb="$phpcli $basePath/ztcli '$pmsRoot/index.php?m=admin&f=checkdb'";
|
||||
checkdb="$phpcli $basePath/ztcli '$pmsRoot/?m=admin&f=checkdb'";
|
||||
fi
|
||||
echo $checkdb > $basePath/checkdb.sh
|
||||
echo "checkdb.sh ok"
|
||||
|
||||
# win to unix
|
||||
if [ $requestType == 'PATH_INFO' ]; then
|
||||
win2Unix="$phpcli $basePath/ztcli '$pmsRoot/admin-win2Unix'";
|
||||
else
|
||||
win2Unix="$phpcli $basePath/ztcli '$pmsRoot/index.php?m=admin&f=win2Unix'";
|
||||
fi
|
||||
echo $win2Unix > $basePath/win2unix.sh
|
||||
echo "win2unix.sh ok"
|
||||
|
||||
# syncsvn.
|
||||
if [ $requestType == 'PATH_INFO' ]; then
|
||||
syncsvn="$phpcli $basePath/ztcli '$pmsRoot/svn-run'";
|
||||
else
|
||||
syncsvn="$phpcli $basePath/ztcli '$pmsRoot/index.php?m=svn&f=run'";
|
||||
syncsvn="$phpcli $basePath/ztcli '$pmsRoot/?m=svn&f=run'";
|
||||
fi
|
||||
echo $syncsvn > $basePath/syncsvn.sh
|
||||
echo "syncsvn.sh ok"
|
||||
|
||||
# syncgit.
|
||||
if [ $requestType == 'PATH_INFO' ]; then
|
||||
syncgit="$phpcli $basePath/ztcli '$pmsRoot/git-run'";
|
||||
else
|
||||
syncgit="$phpcli $basePath/ztcli '$pmsRoot/index.php?m=git&f=run'";
|
||||
fi
|
||||
echo $syncgit > $basePath/syncgit.sh
|
||||
echo "syncgit.sh ok"
|
||||
|
||||
# cron
|
||||
if [ ! -d "$basePath/cron" ]; then
|
||||
mkdir $basePath/cron
|
||||
@@ -110,7 +92,6 @@ echo "0 1 * * * $basePath/dailyreminder.sh # dailyreminder."
|
||||
echo "1 1 * * * $basePath/backup.sh # backup database and file." >> $basePath/cron/sys.cron
|
||||
echo "1 23 * * * $basePath/computeburn.sh # compute burndown chart." >> $basePath/cron/sys.cron
|
||||
echo "1-59/2 * * * * $basePath/syncsvn.sh # sync subversion." >> $basePath/cron/sys.cron
|
||||
echo "1-59/2 * * * * $basePath/syncgit.sh # sync git" >> $basePath/cron/sys.cron
|
||||
cron="$phpcli $basePath/php/crond.php"
|
||||
echo $cron > $basePath/cron.sh
|
||||
echo "cron.sh ok"
|
||||
|
||||
@@ -1,60 +1,11 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
include dirname(dirname(dirname(__FILE__))) . "/config/config.php";
|
||||
|
||||
$tables2Rename = array();
|
||||
$tables2Rename['zt_casestep'] = 'zt_caseStep';
|
||||
$tables2Rename['zt_doclib'] = 'zt_docLib';
|
||||
$tables2Rename['zt_grouppriv'] = 'zt_groupPriv';
|
||||
$tables2Rename['zt_productplan'] = 'zt_productPlan';
|
||||
$tables2Rename['zt_projectproduct'] = 'zt_projectProduct';
|
||||
$tables2Rename['zt_projectstory'] = 'zt_projectStory';
|
||||
$tables2Rename['zt_storyspec'] = 'zt_storySpec';
|
||||
$tables2Rename['zt_taskestimate'] = 'zt_taskEstimate';
|
||||
$tables2Rename['zt_testresult'] = 'zt_testResult';
|
||||
$tables2Rename['zt_testrun'] = 'zt_testRun';
|
||||
$tables2Rename['zt_testtask'] = 'zt_testTask';
|
||||
$tables2Rename['zt_usercontact'] = 'zt_userContact';
|
||||
$tables2Rename['zt_usergroup'] = 'zt_userGroup';
|
||||
$tables2Rename['zt_userquery'] = 'zt_userQuery';
|
||||
$tables2Rename['zt_usertpl'] = 'zt_userTPL';
|
||||
|
||||
/* Zentao Pro table. */
|
||||
$tables2Rename['zt_relationoftasks'] = 'zt_relationOfTasks';
|
||||
$tables2Rename['zt_repohistory'] = 'zt_repoHistory';
|
||||
|
||||
try
|
||||
if($config->requestType == 'PATH_INFO')
|
||||
{
|
||||
$params = $config->db;
|
||||
$dbh = new PDO("mysql:host={$params->host}; port={$params->port}; dbname={$params->name}", $params->user, $params->password);
|
||||
$dbh->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
|
||||
$dbh->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
|
||||
$dbh->exec("SET NAMES utf8");
|
||||
system('php ztcli "http://localhost/admin-win2Unix"');
|
||||
}
|
||||
catch(PDOException $e)
|
||||
elseif($config->requestType == 'GET')
|
||||
{
|
||||
echo 'Connection failed: ' . $e->getMessage() . "\n";
|
||||
die("connect to db failed.\n");
|
||||
system('php ztcli "http://localhost/?m=admin&f=win2Unix"');
|
||||
}
|
||||
|
||||
$tablesExists = $dbh->query('SHOW TABLES')->fetchAll();
|
||||
foreach($tablesExists as $key => $table) $tablesExists[$key] = current((array)$table);
|
||||
$tablesExists = array_flip($tablesExists);
|
||||
|
||||
foreach($tables2Rename as $oldTable => $newTable)
|
||||
{
|
||||
if(isset($tablesExists[$newTable]))
|
||||
{
|
||||
echo "Has existed table '$newTable'\n";
|
||||
}
|
||||
elseif(!isset($tablesExists[$oldTable]))
|
||||
{
|
||||
echo "No found table '$oldTable'\n";
|
||||
}
|
||||
else
|
||||
{
|
||||
$dbh->query("RENAME TABLE `$oldTable` TO `$newTable`");
|
||||
echo "RENAME TABLE `$oldTable` TO `$newTable`\n";
|
||||
}
|
||||
}
|
||||
echo "Finish!\n";
|
||||
|
||||
20
build/linux/Makefile
Normal file
@@ -0,0 +1,20 @@
|
||||
VERSION=$(shell head -n 1 zentao/VERSION)
|
||||
|
||||
all: 7z
|
||||
7z:
|
||||
sudo ./lampp stop
|
||||
sudo rm -fr logs/*
|
||||
sudo rm -fr var/mysql/*.err
|
||||
sudo rm -fr var/mysql/ib*
|
||||
sudo mkdir .package
|
||||
sudo mv * .package
|
||||
sudo mv .package lampp
|
||||
sudo mv lampp/Makefile .
|
||||
sudo chmod a+rx lampp/start*
|
||||
sudo chmod a+rx lampp/start88
|
||||
sudo 7z a -sfx ZenTaoPMS.${VERSION}.linux.7z lampp
|
||||
clean:
|
||||
sudo mv lampp lampp.bak
|
||||
sudo mv lampp.bak/* .
|
||||
sudo rm -fr *.7z
|
||||
sudo rm -fr lampp.bak
|
||||
4
build/linux/adduser.sh
Executable file
@@ -0,0 +1,4 @@
|
||||
echo "This tool is used to add user to access phpmyadmin.";
|
||||
read -p "Account: " account
|
||||
read -s -p "Password: " password
|
||||
../bin/htpasswd -b users $account $password
|
||||
226
build/linux/buildxmapp.sh
Executable file
@@ -0,0 +1,226 @@
|
||||
tar zxvf $1/xampp.tar.gz
|
||||
cd lampp
|
||||
|
||||
# rm useless files.
|
||||
rm -fr RELEASENOTES
|
||||
rm -fr error
|
||||
rm -fr icons
|
||||
rm -fr licenses
|
||||
rm -fr logs/*
|
||||
rm -fr htdocs/*
|
||||
rm -fr cgi-bin
|
||||
rm -fr libexec
|
||||
rm -fr phpmyadmin
|
||||
rm -fr php
|
||||
rm -fr tmp/*
|
||||
chmod -R 777 tmp
|
||||
|
||||
# rm useless settings.
|
||||
rm -fr etc/proftpd.conf
|
||||
rm -fr etc/webalizer.conf*
|
||||
rm -fr etc/freetds.conf
|
||||
rm -fr etc/openssl.cnf
|
||||
rm -fr etc/php.ini-pre1.7.2
|
||||
rm -fr etc/pear.conf
|
||||
rm -fr etc/pool.conf
|
||||
rm -fr etc/openldap
|
||||
rm -fr etc/original
|
||||
rm -fr etc/httpd.conf.bak
|
||||
rm -fr etc/lampp/startftp
|
||||
rm -fr etc/ssl*
|
||||
rm -fr etc/extra
|
||||
rm -fr etc/magic
|
||||
rm -fr etc/locales.conf
|
||||
|
||||
# process httpd conf
|
||||
cp ../httpd.conf etc/httpd.conf
|
||||
|
||||
# process my.cnf
|
||||
cp ../my.cnf etc/my.cnf
|
||||
|
||||
# process php.ini
|
||||
cp ../php.ini etc/php.ini
|
||||
|
||||
# rm useless binaries.
|
||||
mv bin bin.bak
|
||||
mkdir bin
|
||||
cd bin.bak
|
||||
cp htpasswd apachectl my_print_defaults mysql mysql.server mysqld_safe mysqldump php php-config phpize httpd ../bin/
|
||||
cd ../
|
||||
rm -fr bin.bak
|
||||
|
||||
# fix bug of the mysqld_safe
|
||||
sed -e 's/\/opt\/lampp\/\/opt\/lampp\/sbin/\/opt\/lampp\/sbin/g' bin/mysqld_safe > bin/mysqld_safe.new
|
||||
mv bin/mysqld_safe.new bin/mysqld_safe
|
||||
chmod a+rx bin/mysqld_safe
|
||||
|
||||
# rm useless binaries at sbin directory, keep mysqld.
|
||||
mv sbin sbin.bak
|
||||
mkdir sbin
|
||||
mv sbin.bak/mysqld sbin/
|
||||
rm -fr sbin.bak
|
||||
|
||||
# process share directory. keep english and lampp directory.
|
||||
mv share share.bak
|
||||
mkdir share
|
||||
mv share.bak/english share/
|
||||
mv share.bak/lampp share
|
||||
echo >share/lampp/allons
|
||||
rm -fr share.bak
|
||||
|
||||
rm -fr share/lampp/alladdons
|
||||
touch share/lampp/alladdons
|
||||
chmod a+rx share/lampp/alladdons
|
||||
|
||||
# process lib directory.
|
||||
mkdir libnew
|
||||
cp lib/VERSION libnew/
|
||||
cp lib/ioncube.so libnew/
|
||||
cp lib/libapr-1.so.0 libnew/
|
||||
cp lib/libaprutil-1.so.0 libnew/
|
||||
cp lib/libc-client.so libnew/
|
||||
cp lib/libcrypto.so.1.0.0 libnew/
|
||||
cp lib/libct.so.3 libnew/
|
||||
cp lib/libcurl.so.4 libnew/
|
||||
cp lib/libexpat.so.0 libnew/
|
||||
cp lib/libexslt.so.0 libnew/
|
||||
cp lib/libfreetype.so.6 libnew/
|
||||
cp lib/libgcc_s.so.1 libnew/
|
||||
cp lib/libgdbm.so.2 libnew/
|
||||
cp lib/libiconv.so.2 libnew/
|
||||
cp lib/libicudata.so.42 libnew/
|
||||
cp lib/libicui18n.so.42 libnew/
|
||||
cp lib/libicuio.so.42 libnew/
|
||||
cp lib/libicuuc.so.42 libnew/
|
||||
cp lib/libintl.so.2 libnew/
|
||||
cp lib/libjpeg.so.62 libnew/
|
||||
cp lib/liblber-2.4.so.2 libnew/
|
||||
cp lib/libldap-2.4.so.2 libnew/
|
||||
cp lib/libmcrypt.so.4 libnew/
|
||||
cp lib/libncurses.so.5 libnew/
|
||||
cp lib/libpcre.so.0 libnew/
|
||||
cp lib/libpng12.so.0 libnew/
|
||||
cp lib/libpq.so.4 libnew/
|
||||
cp lib/libsqlite3.so.0 libnew/
|
||||
cp lib/libssl.so.1.0.0 libnew/
|
||||
cp lib/libstdc++.so.5 libnew/
|
||||
cp lib/libsybdb.so.5 libnew/
|
||||
cp lib/libxml2.so.2 libnew/
|
||||
cp lib/libxslt.so.1 libnew/
|
||||
cp lib/libz.so.1 libnew/
|
||||
|
||||
rm -fr lib
|
||||
mv libnew lib
|
||||
|
||||
# process var directory.
|
||||
rm -fr var/perl
|
||||
rm -fr var/proftpd*
|
||||
rm -fr var/mysql/cdcol
|
||||
rm -fr var/mysql/*.err
|
||||
rm -fr var/mysql/ib*
|
||||
rm -fr var/mysql/test
|
||||
rm -fr var/mysql/phpmyadmin
|
||||
rm -fr var/mysql/mysql_upgrade_info
|
||||
chmod -R 777 var/mysql
|
||||
|
||||
# process modules directory.
|
||||
rm -fr modules/httpd.exp
|
||||
rm -fr modules/mod_perl.so
|
||||
rm -fr modules/mod_actions.so
|
||||
rm -fr modules/mod_allowmethods.so
|
||||
rm -fr modules/mod_asis.so
|
||||
rm -fr modules/mod_authn_dbm
|
||||
rm -fr modules/mod_authn_anon
|
||||
rm -fr modules/mod_authn_dbd
|
||||
rm -fr modules/mod_authn_default
|
||||
rm -fr modules/mod_authz_dbm.so
|
||||
rm -fr modules/mod_authz_default.so
|
||||
rm -fr modules/mod_authz_groupfile.so
|
||||
rm -fr modules/mod_authz_owner.so
|
||||
rm -fr modules/mod_auth_digest.so
|
||||
rm -fr modules/mod_auth_form.so
|
||||
rm -fr modules/mod_authn_anon.so
|
||||
rm -fr modules/mod_authn_dbd.so
|
||||
rm -fr modules/mod_authn_dbm.so
|
||||
rm -fr modules/mod_authn_socache.so
|
||||
rm -fr modules/mod_authnz_ldap.so
|
||||
rm -fr modules/mod_authz_dbd.so
|
||||
rm -fr modules/mod_bucketeer.so
|
||||
rm -fr modules/mod_buffer.so
|
||||
rm -fr modules/mod_cache*
|
||||
rm -fr modules/mod_case**
|
||||
rm -fr modules/mod_cern_meta.so
|
||||
rm -fr modules/mod_cgi*
|
||||
rm -fr modules/mod_charset_lite.so
|
||||
rm -fr modules/mod_echo.so
|
||||
rm -fr modules/mod_dav*.so
|
||||
rm -fr modules/mod_dbd.so
|
||||
rm -fr modules/mod_disk_cache.so
|
||||
rm -fr modules/mod_dumpio.so
|
||||
rm -fr modules/mod_ext_filter.so
|
||||
rm -fr modules/mod_file_cache.so
|
||||
rm -fr modules/mod_headers.so
|
||||
rm -fr modules/mod_ident.so
|
||||
rm -fr modules/mod_imagemap.so
|
||||
rm -fr modules/mod_include.so
|
||||
rm -fr modules/mod_info.so
|
||||
rm -fr modules/mod_ldap.so
|
||||
rm -fr modules/mod_log_debug.so
|
||||
rm -fr modules/mod_logio.so
|
||||
rm -fr modules/mod_lbmethod*
|
||||
rm -fr modules/mod_mem_cache.so
|
||||
rm -fr modules/mod_mime_magic.so
|
||||
rm -fr modules/mod_negotiation.so
|
||||
rm -fr modules/mod_proxy*
|
||||
rm -fr modules/mod_reqtimeout.so
|
||||
rm -fr modules/mod_ratelimit.so
|
||||
rm -fr modules/mod_remoteip.so
|
||||
rm -fr modules/mod_request.so
|
||||
rm -fr modules/mod_sed.so
|
||||
rm -fr modules/mod_sess*.so
|
||||
rm -fr modules/mod_slotmem_shm.so
|
||||
rm -fr modules/mod_socache*.so
|
||||
rm -fr modules/mod_speling.so
|
||||
rm -fr modules/mod_ssl.so
|
||||
rm -fr modules/mod_status.so
|
||||
rm -fr modules/mod_substitute.so
|
||||
rm -fr modules/mod_suexec.so
|
||||
rm -fr modules/mod_unique_id.so
|
||||
rm -fr modules/mod_userdir.so
|
||||
rm -fr modules/mod_usertrack.so
|
||||
rm -fr modules/mod_version.so
|
||||
rm -fr modules/mod_vhost_alias.so
|
||||
|
||||
# copy the zentao code.
|
||||
mv ../../../zentaopms ./zentao
|
||||
|
||||
# copy needed files.
|
||||
cp ../Makefile .
|
||||
cp ../start .
|
||||
cp ../start88 .
|
||||
cp ../stop .
|
||||
cp ../lamppctl ./lampp
|
||||
cp ../../windows/index.php htdocs/
|
||||
|
||||
# make the auth file
|
||||
mkdir auth
|
||||
touch auth/users
|
||||
cp ../adduser.sh auth/
|
||||
|
||||
# process the phpmyadmin
|
||||
7z x $1/phpmyadmin.7z
|
||||
mv phpMyAdmin-3.5.5-all-languages phpmyadmin
|
||||
mv phpmyadmin/locale phpmyadmin/locale.bak
|
||||
mkdir phpmyadmin/locale
|
||||
mv phpmyadmin/locale.bak/en_GB phpmyadmin/locale
|
||||
mv phpmyadmin/locale.bak/zh_* phpmyadmin/locale
|
||||
rm -fr phpmyadmin/locale.bak
|
||||
cp ../../windows/phpmyadmin.php phpmyadmin/config.inc.php
|
||||
rm -fr phpmyadmin/examples
|
||||
rm -fr phpmyadmin/js/openlayers
|
||||
rm -fr phpmyadmin/libraries/tcpdf
|
||||
rm -fr phpmyadmin/Documentation*
|
||||
rm -fr phpmyadmin/themes/original
|
||||
|
||||
# copy the ioncube loader.
|
||||
cp ../ioncube_loader_lin_5.4.so lib/
|
||||
109
build/linux/httpd.conf
Normal file
@@ -0,0 +1,109 @@
|
||||
# server basic settings.
|
||||
ServerRoot "/opt/lampp"
|
||||
DocumentRoot "/opt/lampp/htdocs"
|
||||
Listen 80
|
||||
User nobody
|
||||
Group nogroup
|
||||
ServerAdmin zentao@localhost.net
|
||||
ServerName localhost
|
||||
EnableMMAP off
|
||||
EnableSendfile off
|
||||
TypesConfig etc/mime.types
|
||||
|
||||
# performance settings.
|
||||
Timeout 300
|
||||
KeepAlive On
|
||||
MaxKeepAliveRequests 100
|
||||
KeepAliveTimeout 5
|
||||
UseCanonicalName Off
|
||||
HostnameLookups Off
|
||||
|
||||
# security.
|
||||
AccessFileName .ztaccess
|
||||
ServerTokens Prod
|
||||
ServerSignature Off
|
||||
|
||||
# deflat.
|
||||
AddType image/x-icon .ico
|
||||
AddType image/gif .gif
|
||||
AddType image/jpeg .jpg .jpeg
|
||||
AddType image/png .png
|
||||
AddType application/javascript .js
|
||||
DeflateCompressionLevel 9
|
||||
AddOutputFilterByType DEFLATE text/html text/css application/javascript
|
||||
|
||||
# modules.
|
||||
LoadModule authn_file_module modules/mod_authn_file.so
|
||||
LoadModule access_compat_module modules/mod_access_compat.so
|
||||
LoadModule alias_module modules/mod_alias.so
|
||||
LoadModule authn_core_module modules/mod_authn_core.so
|
||||
LoadModule auth_basic_module modules/mod_auth_basic.so
|
||||
LoadModule authz_core_module modules/mod_authz_core.so
|
||||
LoadModule authz_host_module modules/mod_authz_host.so
|
||||
LoadModule authz_user_module modules/mod_authz_user.so
|
||||
LoadModule autoindex_module modules/mod_autoindex.so
|
||||
LoadModule deflate_module modules/mod_deflate.so
|
||||
LoadModule dir_module modules/mod_dir.so
|
||||
LoadModule env_module modules/mod_env.so
|
||||
LoadModule expires_module modules/mod_expires.so
|
||||
LoadModule filter_module modules/mod_filter.so
|
||||
LoadModule log_config_module modules/mod_log_config.so
|
||||
LoadModule mime_module modules/mod_mime.so
|
||||
LoadModule rewrite_module modules/mod_rewrite.so
|
||||
LoadModule setenvif_module modules/mod_setenvif.so
|
||||
LoadModule unixd_module modules/mod_unixd.so
|
||||
|
||||
# php module.
|
||||
LoadModule php5_module modules/libphp5.so
|
||||
AddType application/x-httpd-php .php .php3 .php4
|
||||
|
||||
# directory settings.
|
||||
DirectoryIndex index.html index.htm index.php
|
||||
<Directory />
|
||||
AllowOverride none
|
||||
Require all denied
|
||||
</Directory>
|
||||
<Directory "/opt/lampp/htdocs">
|
||||
Options Indexes FollowSymLinks
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
<Files ".zt*">
|
||||
Require all denied
|
||||
</Files>
|
||||
|
||||
# logs
|
||||
ErrorLog "logs/error_log"
|
||||
LogLevel warn
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||
CustomLog "logs/access_log" combined
|
||||
|
||||
# If you want visit zentao like http://localhost/, uncomment these lines.
|
||||
#<VirtualHost *:80>
|
||||
# ServerAdmin zentao@local.net
|
||||
# DocumentRoot "/opt/lampp/zentao/www"
|
||||
# ServerName localhost
|
||||
# <Directory />
|
||||
# AllowOverride none
|
||||
# Require all granted
|
||||
# </Directory>
|
||||
# ErrorLog "logs/error_log"
|
||||
# CustomLog "logs/access_log" combind
|
||||
#</VirtualHost>
|
||||
|
||||
# setting for zentao.
|
||||
Alias /zentao "/opt/lampp/zentao/www/"
|
||||
<Directory "/opt/lampp/zentao/www">
|
||||
Options Indexes FollowSymLinks
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
# setting for admin
|
||||
Alias /phpmyadmin "/opt/lampp/phpmyadmin"
|
||||
<Directory "/opt/lampp/phpmyadmin">
|
||||
AuthName 'zentao admin(run /opt/lampp/auth/adduser.sh to add user.)'
|
||||
AuthType Basic
|
||||
AuthUserFile /opt/lampp/auth/users
|
||||
require valid-user
|
||||
</Directory>
|
||||
BIN
build/linux/ioncube_loader_lin_5.4.so
Normal file
600
build/linux/lamppctl
Executable file
@@ -0,0 +1,600 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# For RedHat (thanks to Sudhaker Raj):
|
||||
# chkconfig: 345 95 05
|
||||
# description: Starts and stops the XAMPP \
|
||||
# used to control Apache, MySQL, ProFTPD.
|
||||
# For SuSE:
|
||||
### BEGIN INIT INFO
|
||||
# Provides: apache2 httpd2 xampp
|
||||
# Required-Start: $local_fs $remote_fs $network
|
||||
# Required-Stop: $local_fs $remote_fs $network
|
||||
# Default-Start: 3 5
|
||||
# Default-Stop: 0 1 2 6
|
||||
# Short-Description: XAMPP
|
||||
# Description: Starts and stops XAMPP
|
||||
### END INIT INFO
|
||||
###############################################################################
|
||||
# Copyright 2002-2005 by Kai 'Oswald' Seidler, oswald@apachefriends.org, GPL-licensed
|
||||
|
||||
function testport() {
|
||||
if netstat -an | egrep ":$1 .*LISTEN" > /dev/null
|
||||
then
|
||||
return 0
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function testrun() {
|
||||
if test -f $1
|
||||
then
|
||||
pid=`cat $1`
|
||||
if ps ax 2>/dev/null | egrep "^ *$pid.*$2" > /dev/null
|
||||
then
|
||||
return 0
|
||||
else
|
||||
rm $1
|
||||
return 1
|
||||
fi
|
||||
else
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
function osguess() {
|
||||
if test -f /etc/redhat-release
|
||||
then
|
||||
if egrep "9 " /etc/redhat-release > /dev/null
|
||||
then
|
||||
if egrep "Fedora" /etc/redhat-release > /dev/null
|
||||
then
|
||||
echo "unknown"
|
||||
return 0
|
||||
fi
|
||||
echo "rh9"
|
||||
return 0
|
||||
fi
|
||||
else
|
||||
echo "unknown"
|
||||
return 0
|
||||
fi
|
||||
}
|
||||
|
||||
de="false"
|
||||
case $LANG in
|
||||
de*) de="true";;
|
||||
esac
|
||||
|
||||
|
||||
# we need root to run
|
||||
if test "`id -u`" -ne 0
|
||||
then
|
||||
$de && echo "XAMPP muss als root aufgerufen werden!"
|
||||
$de || echo "You need to start XAMPP as root!"
|
||||
exit
|
||||
fi
|
||||
|
||||
# XAMPP is currently 32 bit only
|
||||
case `uname -m` in
|
||||
*_64)
|
||||
if /opt/lampp/bin/php -v > /dev/null 2>&1
|
||||
then
|
||||
:
|
||||
else
|
||||
$de && echo "XAMPP gibt es zur Zeit nur als 32-Bit Applikation. Bitte verwende eine 32-Bit Kompatibilitaetsbibliothek fuer Dein System."
|
||||
$de || echo "XAMPP is currently only availably as 32 bit application. Please use a 32 bit compatibility library for your system."
|
||||
$de || echo "For centos, rhel or fedora systems, please try 'sudo yum install glibc.i686 libgcc.i686 libstdc++.i686'."
|
||||
$de || echo "For ubuntu, debian systems, please try 'sudo apt-get install 'sudo apt-get install ia32-libs'."
|
||||
exit
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# do we have that new red hat linux 9 with posix native threads?
|
||||
if test "`osguess`" = "rh9"
|
||||
then
|
||||
# for now disable PNTL. if PNTL gets more popular we will support it. - oswald [8apr3]
|
||||
export LD_ASSUME_KERNEL=2.2.5
|
||||
#echo "XAMPP: DISABLE PNTL..."
|
||||
fi
|
||||
|
||||
# Thanks to drosenbe! - oswald [3sep10]
|
||||
if test -z $LD_LIBRARY_PATH
|
||||
then
|
||||
export LD_LIBRARY_PATH=/opt/lampp/lib
|
||||
else
|
||||
export LD_LIBRARY_PATH=/opt/lampp/lib:$LD_LIBRARY_PATH
|
||||
fi
|
||||
|
||||
# Do we use Oracle? If yes, add Oracle's lib directory to LD_LIBRARY_PATH - oswald [6jul5]
|
||||
if test -f /opt/lampp/etc/lampp/oraclelib
|
||||
then
|
||||
export LD_LIBRARY_PATH=`cat /opt/lampp/etc/lampp/oraclelib`:$LD_LIBRARY_PATH
|
||||
fi
|
||||
|
||||
iswebmin="false";
|
||||
if test -d /opt/lampp/webmin
|
||||
then
|
||||
iswebmin="true";
|
||||
fi
|
||||
|
||||
version=`cat /opt/lampp/lib/VERSION`
|
||||
bon="[1m"
|
||||
boff="[m"
|
||||
lc="/opt/lampp/etc/lampp"
|
||||
|
||||
# Hack to let XAMPP run with SELinux (for Fedora)
|
||||
/opt/lampp/share/lampp/selinux
|
||||
|
||||
case $1 in
|
||||
"start")
|
||||
$de && echo "Starte XAMPP fuer Linux $version..."
|
||||
$de || echo "Starting XAMPP for Linux $version..."
|
||||
|
||||
/opt/lampp/share/lampp/nogroupcheck
|
||||
|
||||
$0 startapache %
|
||||
$0 startmysql %
|
||||
$0 startftp %
|
||||
$iswebmin && $0 startwebmin %
|
||||
|
||||
/opt/lampp/share/lampp/alladdons start
|
||||
|
||||
$de && echo "XAMPP fuer Linux gestartet."
|
||||
$de || echo "XAMPP for Linux started."
|
||||
;;
|
||||
|
||||
"reload")
|
||||
$0 reloadapache
|
||||
$0 reloadmysql
|
||||
$0 reloadftp
|
||||
|
||||
/opt/lampp/share/lampp/alladdons reload
|
||||
;;
|
||||
|
||||
"stopssl")
|
||||
if test -f $lc/startssl
|
||||
then
|
||||
if test -f /opt/lampp/logs/httpd.pid
|
||||
then
|
||||
$0 stopapache
|
||||
rm $lc/startssl
|
||||
$0 startapache
|
||||
else
|
||||
$de && echo "XAMPP: XAMPP-Apache laeuft gar nicht."
|
||||
$de || echo "XAMPP: XAMPP-Apache is not running."
|
||||
rm $lc/startssl
|
||||
fi
|
||||
else
|
||||
$de && echo "XAMPP: SSL laeuft nicht!"
|
||||
$de || echo "XAMPP: SSL isn't running!"
|
||||
fi
|
||||
;;
|
||||
|
||||
"startssl")
|
||||
if testrun /opt/lampp/logs/httpd.pid httpd
|
||||
then
|
||||
if test -f $lc/startssl
|
||||
then
|
||||
$de && echo "XAMPP: SSL laeuft bereits!"
|
||||
$de || echo "XAMPP: SSL is already running!"
|
||||
else
|
||||
$0 stopapache
|
||||
touch $lc/startssl
|
||||
$0 startapache
|
||||
fi
|
||||
else
|
||||
touch $lc/startssl
|
||||
$0 startapache
|
||||
fi
|
||||
;;
|
||||
|
||||
"startapache")
|
||||
if testrun /opt/lampp/logs/httpd.pid httpd
|
||||
then
|
||||
$de && echo "XAMPP: XAMPP-Apache laeuft bereits."
|
||||
$de || echo "XAMPP: XAMPP-Apache is already running."
|
||||
else
|
||||
if testport 80
|
||||
then
|
||||
$de && echo "XAMPP: Ein anderer Webserver laeuft bereits."
|
||||
$de || echo "XAMPP: Another web server daemon is already running."
|
||||
else
|
||||
case `$0 phpstatus` in
|
||||
5*) xampp_apachedefine="$xampp_apachedefine -DPHP5"
|
||||
$de && phpextra="(und PHP5)"
|
||||
$de || phpextra="(and PHP5)"
|
||||
;;
|
||||
4*) xampp_apachedefine="$xampp_apachedefine -DPHP4"
|
||||
$de && phpextra="(und PHP4)"
|
||||
$de || phpextra="(and PHP4)"
|
||||
;;
|
||||
esac
|
||||
if test -f $lc/startssl
|
||||
then
|
||||
if testport 443
|
||||
then
|
||||
$de && echo "XAMPP: Ein anderer Webserver mit SSL laeuft bereits."
|
||||
$de || echo "XAMPP: Another web server daemon with SSL is already running."
|
||||
else
|
||||
$de && echo "XAMPP: Starte Apache mit SSL $phpextra..."
|
||||
$de || echo "XAMPP: Starting Apache with SSL $phpextra..."
|
||||
/opt/lampp/bin/apachectl -k start -DSSL $xampp_apachedefine -E /opt/lampp/logs/error_log
|
||||
fi
|
||||
else
|
||||
$de && echo "XAMPP: Starte Apache..."
|
||||
$de || echo "XAMPP: Starting Apache..."
|
||||
/opt/lampp/bin/apachectl -k start $xampp_apachedefine -E /opt/lampp/logs/error_log
|
||||
fi
|
||||
error=$?
|
||||
if test $error -gt 0
|
||||
then
|
||||
$de && echo "XAMPP: ${bon}Fehler $error beim Starten vom Apache!${boff}"
|
||||
$de || echo "XAMPP: ${bon}Error $error! Couldn't start Apache!${boff}"
|
||||
/opt/lampp/share/lampp/diagnose apache
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
|
||||
"startmysql")
|
||||
if testrun /opt/lampp/var/mysql/`/bin/hostname`.pid mysqld
|
||||
then
|
||||
$de && echo "XAMPP: XAMPP-MySQL laeuft bereits."
|
||||
$de || echo "XAMPP: XAMPP-MySQL is already running."
|
||||
else
|
||||
if testport 3306
|
||||
then
|
||||
$de && echo "XAMPP: Ein anderer MySQL daemon laeuft bereits."
|
||||
$de || echo "XAMPP: Another MySQL daemon is already running."
|
||||
else
|
||||
$de && echo "XAMPP: Starte MySQL..."
|
||||
$de || echo "XAMPP: Starting MySQL..."
|
||||
/opt/lampp/bin/mysql.server start > /dev/null
|
||||
if test $? -ne 0
|
||||
then
|
||||
$de && echo "XAMPP: MySQL konnte nicht gestartet werden!"
|
||||
$de || echo "XAMPP: Couldn't start MySQL!"
|
||||
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
"startwebmin")
|
||||
if $iswebmin
|
||||
then
|
||||
if test "$2" != "%"
|
||||
then
|
||||
touch $lc/startwebmin
|
||||
fi
|
||||
if test -f $lc/startwebmin
|
||||
then
|
||||
if testrun /opt/lampp/var/webmin/miniserv.pid miniserv
|
||||
then
|
||||
$de && echo "XAMPP: Webmin laeuft bereits."
|
||||
$de || echo "XAMPP: Webmin is already running."
|
||||
else
|
||||
$de && echo "XAMPP: Starte Webmin..."
|
||||
$de || echo "XAMPP: Starting Webmin..."
|
||||
/opt/lampp/etc/webmin/start quiet
|
||||
fi
|
||||
fi
|
||||
else
|
||||
$de && echo "XAMPP: Webmin ist nicht installiert."
|
||||
$de || echo "XAMPP: Webmin isn't installed."
|
||||
fi
|
||||
;;
|
||||
|
||||
"stopwebmin")
|
||||
if $iswebmin
|
||||
then
|
||||
if test -f $lc/startwebmin
|
||||
then
|
||||
if testrun /opt/lampp/var/webmin/miniserv.pid miniserv
|
||||
then
|
||||
$de && echo "XAMPP: Stoppe Webmin..."
|
||||
$de || echo "XAMPP: Stopping Webmin..."
|
||||
/opt/lampp/etc/webmin/stop quiet
|
||||
else
|
||||
$de && echo "XAMPP: XAMPP-Webmin laeuft gar nicht."
|
||||
$de || echo "XAMPP: XAMPP-Webmin is not running."
|
||||
fi
|
||||
if test "$2" != "%"
|
||||
then
|
||||
rm $lc/startwebmin 2> /dev/null
|
||||
fi
|
||||
fi
|
||||
else
|
||||
$de && echo "XAMPP: Webmin ist nicht installiert."
|
||||
$de || echo "XAMPP: Webmin isn't installed."
|
||||
fi
|
||||
;;
|
||||
|
||||
"startftp")
|
||||
if test "$2" != "%"
|
||||
then
|
||||
touch $lc/startftp
|
||||
fi
|
||||
if test -f $lc/startftp
|
||||
then
|
||||
if testrun /opt/lampp/var/proftpd.pid proftpd
|
||||
then
|
||||
$de && echo "XAMPP: XAMPP-ProFTPD laeuft bereits."
|
||||
$de || echo "XAMPP: XAMPP-ProFTPD is already running."
|
||||
else
|
||||
if testport 21
|
||||
then
|
||||
$de && echo "XAMPP: Ein anderer FTP daemon laeuft bereits."
|
||||
$de || echo "XAMPP: Another FTP daemon is already running."
|
||||
else
|
||||
$de && echo "XAMPP: Starte ProFTPD..."
|
||||
$de || echo "XAMPP: Starting ProFTPD..."
|
||||
/opt/lampp/sbin/proftpd > /opt/lampp/var/proftpd/start.err 2>&1
|
||||
error=$?
|
||||
if test $error -gt 0
|
||||
then
|
||||
echo "XAMPP: `cat /opt/lampp/var/proftpd/start.err`"
|
||||
$de && echo "XAMPP: ${bon}Fehler $error beim Starten von ProFTPD!${boff}"
|
||||
$de || echo "XAMPP: ${bon}Error $error! Couln't start ProFTPD!${boff}"
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
;;
|
||||
|
||||
"stop")
|
||||
$de && echo "Stoppe XAMPP fuer Linux $version..."
|
||||
$de || echo "Stopping XAMPP for Linux $version..."
|
||||
|
||||
$0 stopapache %
|
||||
$0 stopmysql %
|
||||
$0 stopftp %
|
||||
$iswebmin && $0 stopwebmin %
|
||||
|
||||
/opt/lampp/share/lampp/alladdons stop
|
||||
|
||||
$de && echo "XAMPP beendet."
|
||||
$de || echo "XAMPP stopped."
|
||||
;;
|
||||
|
||||
"stopapache")
|
||||
if test -f /opt/lampp/logs/httpd.pid
|
||||
then
|
||||
if test -f $lc/startssl
|
||||
then
|
||||
$de && echo "XAMPP: Stoppe Apache mit SSL..."
|
||||
$de || echo "XAMPP: Stopping Apache with SSL..."
|
||||
else
|
||||
$de && echo "XAMPP: Stoppe Apache..."
|
||||
$de || echo "XAMPP: Stopping Apache..."
|
||||
fi
|
||||
|
||||
|
||||
# Thanks to Emilio Paolini <ep@im-netz.de> for the next 12 lines - Oswald, 30sep04
|
||||
|
||||
case `$0 phpstatus` in
|
||||
5*) xampp_apachedefine="$xampp_apachedefine -D PHP5"
|
||||
$de && phpextra="(und PHP5)"
|
||||
$de || phpextra="(and PHP5)"
|
||||
;;
|
||||
4*) xampp_apachedefine="$xampp_apachedefine -D PHP4"
|
||||
$de && phpextra="(und PHP4)"
|
||||
$de || phpextra="(and PHP4)"
|
||||
;;
|
||||
esac
|
||||
|
||||
/opt/lampp/bin/apachectl $xampp_apachedefine -k stop > /dev/null
|
||||
|
||||
sleep 2
|
||||
#test -f /opt/lampp/logs/httpd.pid && rm /opt/lampp/logs/httpd.pid
|
||||
else
|
||||
$de && echo "XAMPP: XAMPP-Apache laeuft gar nicht."
|
||||
$de || echo "XAMPP: XAMPP-Apache is not running."
|
||||
fi
|
||||
;;
|
||||
|
||||
"reloadapache")
|
||||
if test -f /opt/lampp/logs/httpd.pid
|
||||
then
|
||||
kill -USR1 `cat /opt/lampp/logs/httpd.pid`
|
||||
$de && echo "XAMPP: Aktualisiere Apache..."
|
||||
$de || echo "XAMPP: Reload Apache..."
|
||||
else
|
||||
$de && echo "XAMPP: Apache laeuft nicht..."
|
||||
$de || echo "XAMPP: Apache isn't running..."
|
||||
fi
|
||||
;;
|
||||
|
||||
|
||||
"stopmysql")
|
||||
if test -f /opt/lampp/var/mysql/`/bin/hostname`.pid
|
||||
then
|
||||
/opt/lampp/bin/mysql.server stop > /dev/null 2>&1 &
|
||||
$de && echo "XAMPP: Stoppe MySQL..."
|
||||
$de || echo "XAMPP: Stopping MySQL..."
|
||||
sleep 2
|
||||
test -f /opt/lampp/var/mysql/`/bin/hostname`.pid && rm /opt/lampp/var/mysql/`/bin/hostname`.pid
|
||||
else
|
||||
$de && echo "XAMPP: XAMPP-MySQL laeuft gar nicht."
|
||||
$de || echo "XAMPP: XAMPP-MySQL is not running."
|
||||
fi
|
||||
;;
|
||||
|
||||
"reloadmysql")
|
||||
if test -f /opt/lampp/var/mysql/`/bin/hostname`.pid
|
||||
then
|
||||
h="`/bin/hostname`"
|
||||
kill -HUP `cat /opt/lampp/var/mysql/$h.pid`
|
||||
$de && echo "XAMPP: Aktualisiere MySQL..."
|
||||
$de || echo "XAMPP: Reload MySQL..."
|
||||
else
|
||||
$de && echo "XAMPP: MySQL laeuft nicht..."
|
||||
$de || echo "XAMPP: MySQL isn't running..."
|
||||
fi
|
||||
;;
|
||||
|
||||
|
||||
"stopftp")
|
||||
if test -f /opt/lampp/var/proftpd.pid
|
||||
then
|
||||
kill `cat /opt/lampp/var/proftpd.pid`
|
||||
$de && echo "XAMPP: Stoppe ProFTPD..."
|
||||
$de || echo "XAMPP: Stopping ProFTPD..."
|
||||
else
|
||||
if test -f $lc/startftp
|
||||
then
|
||||
$de && echo "XAMPP: XAMPP-ProFTPD laeuft gar nicht."
|
||||
$de || echo "XAMPP: XAMPP-ProFTPD is not running."
|
||||
fi
|
||||
fi
|
||||
if test "$2" != "%"
|
||||
then
|
||||
rm $lc/startftp 2> /dev/null
|
||||
fi
|
||||
;;
|
||||
|
||||
"reloadftp")
|
||||
if test -f /opt/lampp/var/proftpd.pid
|
||||
then
|
||||
kill -HUP `cat /opt/lampp/var/proftpd.pid`
|
||||
$de && echo "XAMPP: Aktualisiere ProFTPD..."
|
||||
$de || echo "XAMPP: Reload ProFTPD..."
|
||||
else
|
||||
$de && echo "XAMPP: ProFTPD laeuft gar nicht..."
|
||||
$de || echo "XAMPP: ProFTPD isn't running..."
|
||||
fi
|
||||
;;
|
||||
|
||||
"wizard")
|
||||
/opt/lampp/bin/php /opt/lampp/share/lampp/wizard.php
|
||||
;;
|
||||
|
||||
"restartapache")
|
||||
$0 stopapache
|
||||
sleep 4
|
||||
$0 startapache
|
||||
;;
|
||||
|
||||
"restart")
|
||||
$0 stop
|
||||
sleep 4
|
||||
$0 start
|
||||
;;
|
||||
|
||||
"security")
|
||||
/opt/lampp/share/lampp/checkall
|
||||
;;
|
||||
|
||||
"oci8")
|
||||
/opt/lampp/share/lampp/oci8install
|
||||
;;
|
||||
|
||||
"backup")
|
||||
/opt/lampp/share/lampp/backup $2
|
||||
;;
|
||||
|
||||
"php4")
|
||||
/opt/lampp/share/lampp/activatephp 4
|
||||
;;
|
||||
|
||||
"php5")
|
||||
/opt/lampp/share/lampp/activatephp 5.4.7
|
||||
;;
|
||||
|
||||
"phpstatus")
|
||||
/opt/lampp/share/lampp/phpstatus
|
||||
;;
|
||||
|
||||
"panel")
|
||||
exec /opt/lampp/share/xampp-control-panel/xampp-control-panel
|
||||
;;
|
||||
|
||||
"status")
|
||||
. /opt/lampp/share/lampp/status
|
||||
;;
|
||||
|
||||
"statusraw")
|
||||
. /opt/lampp/share/lampp/statusraw
|
||||
;;
|
||||
|
||||
start*|stop*|reload*|status*|restart*)
|
||||
/opt/lampp/share/lampp/addons $*
|
||||
;;
|
||||
|
||||
"version")
|
||||
$de && echo "Version: XAMPP fuer Linux $version"
|
||||
$de || echo "Version: XAMPP for Linux $version"
|
||||
;;
|
||||
|
||||
*) if $de
|
||||
then
|
||||
echo "Aufruf: $0 <Aktion>"
|
||||
echo ""
|
||||
echo " start Starte XAMPP (Apache, MySQL und evtl. weitere)"
|
||||
echo " startapache Starte nur den Apache"
|
||||
echo " startssl Starte nur die SSL-Unterstuetzung des Apache"
|
||||
echo " startmysql Starte nur den MySQL"
|
||||
echo " startftp Starte nur den ProFTPD"
|
||||
$iswebmin && echo " startwebmin Starte nur Webmin"
|
||||
echo ""
|
||||
echo " stop Stoppe XAMPP (Apache, MySQL und evtl. weitere)"
|
||||
echo " stopapache Stoppe nur den Apache"
|
||||
echo " stopssl Stoppe nur die SSL-Unterstuetzung des Apache"
|
||||
echo " stopmysql Stoppe nur den MySQL"
|
||||
echo " stopftp Stoppe nur den ProFTPD"
|
||||
$iswebmin && echo " stopwebmin Stoppe nur Webmin"
|
||||
echo ""
|
||||
echo " reload Aktualisiere XAMPP (Apache, MySQL und evtl. weitere)"
|
||||
echo " reloadapache Aktualisiere nur den Apache"
|
||||
echo " reloadmysql Aktualisiere nur den MySQL"
|
||||
echo " reloadftp Aktualisiere nur den ProFTPD"
|
||||
echo ""
|
||||
echo " restart Stoppe und starte XAMPP"
|
||||
echo " security <20>berpruefe XAMPPs Sicherheit"
|
||||
echo ""
|
||||
echo " php5 Aktiviere PHP5"
|
||||
##echo " php4 Aktiviere PHP4"
|
||||
echo " phpstatus Welches PHP ist aktiv?"
|
||||
echo ""
|
||||
echo " backup Backup der XAMPP-Konfig, Logs und Daten erstellen"
|
||||
echo " panel Startet das grafische XAMPP control panel"
|
||||
echo ""
|
||||
else
|
||||
echo "Usage: $0 <action>"
|
||||
echo ""
|
||||
echo " start Start XAMPP (Apache, MySQL and eventually others)"
|
||||
echo " startapache Start only Apache"
|
||||
echo " startssl Start only SSL support"
|
||||
echo " startmysql Start only MySQL"
|
||||
echo " startftp Start only ProFTPD"
|
||||
$iswebmin && echo " startwebmin Start only Webmin"
|
||||
echo ""
|
||||
echo " stop Stop XAMPP (Apache, MySQL and eventually others)"
|
||||
echo " stopapache Stop only Apache"
|
||||
echo " stopssl Stop only SSL support"
|
||||
echo " stopmysql Stop only MySQL"
|
||||
echo " stopftp Stop only ProFTPD"
|
||||
$iswebmin && echo " stopwebmin Stop only Webmin"
|
||||
echo ""
|
||||
echo " reload Reload XAMPP (Apache, MySQL and eventually others)"
|
||||
echo " reloadapache Reload only Apache"
|
||||
echo " reloadmysql Reload only MySQL"
|
||||
echo " reloadftp Reload only ProFTPD"
|
||||
echo ""
|
||||
echo " restart Stop and start XAMPP"
|
||||
echo " security Check XAMPP's security"
|
||||
echo ""
|
||||
echo " php5 Activate PHP5"
|
||||
##echo " php4 Activate PHP4"
|
||||
echo " phpstatus Which version of PHP is active?"
|
||||
echo ""
|
||||
echo " backup Make backup file of your XAMPP config, log and data files"
|
||||
echo " panel Starts graphical XAMPP control panel"
|
||||
echo ""
|
||||
fi
|
||||
|
||||
;;
|
||||
esac
|
||||
45
build/linux/my.cnf
Normal file
@@ -0,0 +1,45 @@
|
||||
[client]
|
||||
port = 3306
|
||||
socket = /opt/lampp/var/mysql/mysql.sock
|
||||
|
||||
[mysqld]
|
||||
user = nobody
|
||||
port = 3306
|
||||
socket = /opt/lampp/var/mysql/mysql.sock
|
||||
server-id = 1
|
||||
|
||||
key_buffer = 16M
|
||||
max_allowed_packet = 1M
|
||||
table_cache = 64
|
||||
sort_buffer_size = 512K
|
||||
net_buffer_length = 8K
|
||||
read_buffer_size = 256K
|
||||
read_rnd_buffer_size = 512K
|
||||
myisam_sort_buffer_size = 8M
|
||||
|
||||
skip-innodb
|
||||
default-storage-engine=MyISAM
|
||||
|
||||
skip-external-locking
|
||||
|
||||
[mysqldump]
|
||||
quick
|
||||
max_allowed_packet = 16M
|
||||
|
||||
[mysql]
|
||||
no-auto-rehash
|
||||
|
||||
[isamchk]
|
||||
key_buffer = 20M
|
||||
sort_buffer_size = 20M
|
||||
read_buffer = 2M
|
||||
write_buffer = 2M
|
||||
|
||||
[myisamchk]
|
||||
key_buffer = 20M
|
||||
sort_buffer_size = 20M
|
||||
read_buffer = 2M
|
||||
write_buffer = 2M
|
||||
|
||||
[mysqlhotcopy]
|
||||
interactive-timeout
|
||||
129
build/linux/php.ini
Normal file
@@ -0,0 +1,129 @@
|
||||
zend_extension = /opt/lampp/lib/ioncube_loader_lin_5.4.so
|
||||
[PHP]
|
||||
engine = On
|
||||
|
||||
short_open_tag = On
|
||||
asp_tags = Off
|
||||
|
||||
precision = 14
|
||||
y2k_compliance = On
|
||||
|
||||
output_buffering = 4096
|
||||
zlib.output_compression = Off
|
||||
implicit_flush = Off
|
||||
unserialize_callback_func =
|
||||
serialize_precision = 100
|
||||
allow_call_time_pass_reference = Off
|
||||
|
||||
safe_mode = Off
|
||||
safe_mode_gid = Off
|
||||
safe_mode_include_dir =
|
||||
safe_mode_exec_dir =
|
||||
safe_mode_allowed_env_vars = PHP_
|
||||
safe_mode_protected_env_vars = LD_LIBRARY_PATH
|
||||
|
||||
disable_functions =
|
||||
disable_classes =
|
||||
expose_php = Off
|
||||
|
||||
max_execution_time = 30
|
||||
max_input_time = 60
|
||||
memory_limit = 128M
|
||||
|
||||
error_reporting = E_ALL | E_STRICT
|
||||
display_errors = On
|
||||
display_startup_errors = On
|
||||
log_errors = On
|
||||
log_errors_max_len = 1024
|
||||
ignore_repeated_errors = Off
|
||||
ignore_repeated_source = Off
|
||||
report_memleaks = On
|
||||
track_errors = On
|
||||
html_errors = On
|
||||
error_log = "/opt/lampp/logs/php_error_log"
|
||||
|
||||
variables_order = "GPCS"
|
||||
request_order = "GP"
|
||||
register_globals = Off
|
||||
register_long_arrays = Off
|
||||
register_argc_argv = Off
|
||||
auto_globals_jit = On
|
||||
post_max_size = 50M
|
||||
magic_quotes_gpc = Off
|
||||
magic_quotes_runtime = Off
|
||||
magic_quotes_sybase = Off
|
||||
|
||||
auto_prepend_file =
|
||||
auto_append_file =
|
||||
|
||||
default_mimetype = "text/html"
|
||||
|
||||
doc_root =
|
||||
user_dir =
|
||||
|
||||
enable_dl = Off
|
||||
|
||||
file_uploads = On
|
||||
upload_max_filesize = 50M
|
||||
|
||||
allow_url_fopen = On
|
||||
allow_url_include = Off
|
||||
default_socket_timeout = 60
|
||||
[Date]
|
||||
date.timezone = Europe/Berlin
|
||||
[Pdo_mysql]
|
||||
pdo_mysql.cache_size = 2000
|
||||
pdo_mysql.default_socket=
|
||||
[MySQL]
|
||||
mysql.allow_local_infile = On
|
||||
mysql.allow_persistent = On
|
||||
mysql.cache_size = 2000
|
||||
mysql.max_persistent = -1
|
||||
mysql.max_links = -1
|
||||
mysql.default_port =
|
||||
mysql.default_socket =
|
||||
mysql.default_host =
|
||||
mysql.default_user =
|
||||
mysql.default_password =
|
||||
mysql.connect_timeout = 60
|
||||
mysql.trace_mode = Off
|
||||
[MySQLi]
|
||||
mysqli.max_persistent = -1
|
||||
mysqli.max_links = -1
|
||||
mysqli.cache_size = 2000
|
||||
mysqli.default_port = 3306
|
||||
mysqli.default_socket =
|
||||
mysqli.default_host =
|
||||
mysqli.default_user =
|
||||
mysqli.default_pw =
|
||||
mysqli.reconnect = Off
|
||||
[mysqlnd]
|
||||
mysqlnd.collect_statistics = On
|
||||
mysqlnd.collect_memory_statistics = On
|
||||
[Session]
|
||||
session.save_handler = files
|
||||
session.use_cookies = 1
|
||||
session.use_only_cookies = 1
|
||||
session.name = PHPSESSID
|
||||
session.auto_start = 0
|
||||
session.cookie_lifetime = 0
|
||||
session.cookie_path = /
|
||||
session.cookie_domain =
|
||||
session.cookie_httponly =
|
||||
session.serialize_handler = php
|
||||
session.gc_probability = 1
|
||||
session.gc_divisor = 1000
|
||||
session.gc_maxlifetime = 1440
|
||||
session.bug_compat_42 = On
|
||||
session.bug_compat_warn = On
|
||||
session.referer_check =
|
||||
session.entropy_length = 0
|
||||
session.entropy_file =
|
||||
session.cache_limiter = nocache
|
||||
session.cache_expire = 180
|
||||
session.use_trans_sid = 0
|
||||
session.hash_function = 0
|
||||
session.hash_bits_per_character = 5
|
||||
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
|
||||
[ldap]
|
||||
ldap.max_links = -1
|
||||
57
build/linux/start
Normal file
@@ -0,0 +1,57 @@
|
||||
#!/bin/bash
|
||||
# This file is used to start apache at 80 port and mysql at 3306 port.
|
||||
|
||||
# check the directory, must at /opt/lampp.
|
||||
pwd | grep ^/opt/lampp > /dev/null 2>&1 # check the pwd is /opt/lampp or not.
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
# if the pwd is not /opt/lampp, may be the /opt/lampp is a link, check /opt/lampp exists or not.
|
||||
ls /opt/lampp > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "The lampp can only run at /opt/lampp"
|
||||
fi
|
||||
fi
|
||||
|
||||
# check the run user, must be root.
|
||||
if test "`id -u`" -ne 0
|
||||
then
|
||||
echo "You need to start XAMPP as root!"
|
||||
exit
|
||||
fi
|
||||
|
||||
# replace ports.
|
||||
sed -e 's/88/80/g' lampp | sed -e 's/3308/3306/g'> lampp.80
|
||||
mv lampp.80 lampp
|
||||
|
||||
sed -e 's/88/80/g' etc/httpd.conf > etc/httpd.conf.80
|
||||
mv etc/httpd.conf.80 etc/httpd.conf
|
||||
|
||||
sed -e 's/3308/3306/g' etc/my.cnf > etc/my.cnf.3306
|
||||
mv etc/my.cnf.3306 etc/my.cnf
|
||||
|
||||
sed -e 's/3308/3306/g' zentao/config/my.php > zentao/config/my.php.3306
|
||||
mv zentao/config/my.php.3306 zentao/config/my.php
|
||||
|
||||
sed -e 's/3308/3306/g' phpmyadmin/config.inc.php > phpmyadmin/config.inc.php.3306
|
||||
mv phpmyadmin/config.inc.php.3306 phpmyadmin/config.inc.php
|
||||
|
||||
# change directory permissions.
|
||||
chmod a+rx lampp
|
||||
chown nobody -R var/mysql
|
||||
chmod 777 tmp
|
||||
chmod a+rx -R zentao
|
||||
chmod 777 -R zentao/tmp
|
||||
chmod 777 -R zentao/www/data
|
||||
chmod 777 zentao/module
|
||||
find zentao/ -name ext |xargs chmod -R 777
|
||||
|
||||
# init the shells in zentao/bin
|
||||
if [ ! -f ./zentao/bin/backup.sh ]; then
|
||||
ip=`ifconfig |grep inet|head -n 1 |awk -F':' '{print $2}' |awk -F ' ' '{print $1}'`
|
||||
pmsRoot=http://$ip/zentao/
|
||||
./zentao/bin/init.sh /opt/lampp/bin/php $pmsRoot > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# start apache, mysql.
|
||||
./lampp start
|
||||
58
build/linux/start88
Executable file
@@ -0,0 +1,58 @@
|
||||
#!/bin/bash
|
||||
# This file is used to start apache at 88 port and mysql at 3308 port.
|
||||
|
||||
# check the directory, must at /opt/lampp.
|
||||
pwd | grep ^/opt/lampp > /dev/null 2>&1 # check the pwd is /opt/lampp or not.
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
# if the pwd is not /opt/lampp, may be the /opt/lampp is a link, check /opt/lampp exists or not.
|
||||
ls /opt/lampp > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]
|
||||
then
|
||||
echo "The lampp can only run at /opt/lampp"
|
||||
fi
|
||||
fi
|
||||
|
||||
# check the run user, must be root.
|
||||
if test "`id -u`" -ne 0
|
||||
then
|
||||
echo "You need to start XAMPP as root!"
|
||||
exit
|
||||
fi
|
||||
|
||||
# replace ports.
|
||||
sed -e 's/80/88/g' lampp | sed -e 's/3306/3308/g' > lampp.88
|
||||
mv lampp.88 lampp
|
||||
|
||||
sed -e 's/80/88/g' etc/httpd.conf > etc/httpd.conf.88
|
||||
mv etc/httpd.conf.88 etc/httpd.conf
|
||||
|
||||
sed -e 's/3306/3308/g' etc/my.cnf > etc/my.cnf.3308
|
||||
mv etc/my.cnf.3308 etc/my.cnf
|
||||
|
||||
sed -e 's/3306/3308/g' zentao/config/my.php > zentao/config/my.php.3308
|
||||
mv zentao/config/my.php.3308 zentao/config/my.php
|
||||
|
||||
sed -e 's/3306/3308/g' phpmyadmin/config.inc.php > phpmyadmin/config.inc.php.3308
|
||||
mv phpmyadmin/config.inc.php.3308 phpmyadmin/config.inc.php
|
||||
|
||||
# change directory permissions.
|
||||
chmod a+rx lampp
|
||||
chown nobody -R var/mysql
|
||||
chmod 777 tmp
|
||||
chmod a+rx -R zentao
|
||||
chmod 777 -R zentao/tmp
|
||||
chmod 777 -R zentao/www/data
|
||||
chmod 777 zentao/module
|
||||
find zentao/ -name ext |xargs chmod -R 777
|
||||
|
||||
# init the shells in zentao/bin
|
||||
# init the shells in zentao/bin
|
||||
if [ ! -f ./zentao/bin/backup.sh ]; then
|
||||
ip=`ifconfig |grep inet|head -n 1 |awk -F':' '{print $2}' |awk -F ' ' '{print $1}'`
|
||||
pmsRoot=http://$ip:88/zentao/
|
||||
./zentao/bin/init.sh /opt/lampp/bin/php $pmsRoot > /dev/null 2>&1
|
||||
fi
|
||||
|
||||
# start apache, mysql.
|
||||
./lampp start
|
||||
8
build/linux/stop
Executable file
@@ -0,0 +1,8 @@
|
||||
#!/bin/bash
|
||||
if test "`id -u`" -ne 0
|
||||
then
|
||||
echo "You need to start XAMPP as root!"
|
||||
exit
|
||||
fi
|
||||
|
||||
./lampp stop
|
||||
@@ -6,7 +6,7 @@
|
||||
class control {}
|
||||
|
||||
/* set module root path and included the resource of group module. */
|
||||
$moduleRoot = '../module/';
|
||||
$moduleRoot = '../../module/';
|
||||
include $moduleRoot . '/group/lang/resource.php';
|
||||
foreach(glob($moduleRoot . '/group/ext/lang/zh-cn/*.php') as $resourceFile)
|
||||
{
|
||||
@@ -45,7 +45,6 @@ $whiteList[] = 'user-deny';
|
||||
$whiteList[] = 'user-logout';
|
||||
$whiteList[] = 'user-setreferer';
|
||||
$whiteList[] = 'svn-run';
|
||||
$whiteList[] = 'git-run';
|
||||
$whiteList[] = 'admin-ignore';
|
||||
$whiteList[] = 'admin-register';
|
||||
$whiteList[] = 'admin-win2unix';
|
||||
@@ -54,9 +53,6 @@ $whiteList[] = 'story-commonaction';
|
||||
$whiteList[] = 'story-sendmail';
|
||||
$whiteList[] = 'webapp-ajaxaddview';
|
||||
$whiteList[] = 'report-remind';
|
||||
$whiteList[] = 'sso-auth';
|
||||
$whiteList[] = 'sso-depts';
|
||||
$whiteList[] = 'sso-users';
|
||||
|
||||
/* checking actions of every module. */
|
||||
echo '-------------action checking-----------------' . "\n";
|
||||
@@ -115,8 +111,8 @@ foreach(glob($moduleRoot . '*') as $modulePath)
|
||||
|
||||
/* checking actions of every module. */
|
||||
echo '-------------lang checking-----------------' . "\n";
|
||||
include '../module/common/lang/zh-cn.php';
|
||||
include '../config/config.php';
|
||||
include '../../module/common/lang/zh-cn.php';
|
||||
include '../../config/config.php';
|
||||
foreach(glob($moduleRoot . '*') as $modulePath)
|
||||
{
|
||||
unset($lang);
|
||||
@@ -146,7 +142,7 @@ foreach(glob($moduleRoot . '*') as $modulePath)
|
||||
$key = trim($key);
|
||||
$lineNO = $lineNO + 1;
|
||||
echo "module $moduleName need checking, command is:";
|
||||
echo " vim -O +$lineNO ../module/$moduleName/lang/zh-cn.php +$lineNO ../module/$moduleName/lang/en.php \n";
|
||||
echo " vim -O +$lineNO ../../module/$moduleName/lang/zh-cn.php +$lineNO ../../module/$moduleName/lang/en.php \n";
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
$langType = 'zh-tw';
|
||||
$langDesc = 'zh-tw';
|
||||
if(empty($langType)) die('lang') . "\n";
|
||||
foreach(glob('../module/*') as $moduleName)
|
||||
foreach(glob('../../module/*') as $moduleName)
|
||||
{
|
||||
$moduleLangPath = realpath($moduleName) . '/lang/';
|
||||
$defaultLangFile = $moduleLangPath . 'zh-cn.php';
|
||||
@@ -3,7 +3,7 @@
|
||||
$langType = $argv[1];
|
||||
$langDesc = $argv[2];
|
||||
if(empty($langType)) die('lang') . "\n";
|
||||
foreach(glob('../module/*') as $moduleName)
|
||||
foreach(glob('../../module/*') as $moduleName)
|
||||
{
|
||||
$moduleLangPath = realpath($moduleName) . '/lang/';
|
||||
$defaultLangFile = $moduleLangPath . 'zh-cn.php';
|
||||
@@ -1,7 +1,7 @@
|
||||
<?php
|
||||
error_reporting(E_ALL);
|
||||
$langType = empty($argv[1]) ? 'zh-cn' : $argv[1];
|
||||
$modules = glob('../module/*');
|
||||
$modules = glob('../../module/*');
|
||||
$maxLength = 0;
|
||||
foreach($modules as $modulePath)
|
||||
{
|
||||
@@ -9,10 +9,10 @@
|
||||
* @version $Id$
|
||||
* @link http://www.zentao.net
|
||||
*/
|
||||
include '../config/config.php';
|
||||
include '../../config/config.php';
|
||||
|
||||
$modules = array();
|
||||
$moduleRoot = realpath('../module/') . '/';
|
||||
$moduleRoot = realpath('../../module/') . '/';
|
||||
|
||||
if(is_dir($moduleRoot))
|
||||
{
|
||||
@@ -37,8 +37,6 @@ foreach($modules as $module)
|
||||
$extControl = $extRoot . DIRECTORY_SEPARATOR . 'control';
|
||||
$extModel = $extRoot . DIRECTORY_SEPARATOR . 'model';
|
||||
$extView = $extRoot . DIRECTORY_SEPARATOR . 'view';
|
||||
$extCSS = $extRoot . DIRECTORY_SEPARATOR . 'css';
|
||||
$extJS = $extRoot . DIRECTORY_SEPARATOR . 'js';
|
||||
$extConfig = $extRoot . DIRECTORY_SEPARATOR . 'config';
|
||||
$extLang = $extRoot . DIRECTORY_SEPARATOR . 'lang' . DIRECTORY_SEPARATOR;
|
||||
|
||||
@@ -47,26 +45,15 @@ foreach($modules as $module)
|
||||
if(!file_exists($extControl)) mkdir($extControl, 0777);
|
||||
if(!file_exists($extModel)) mkdir($extModel, 0777);
|
||||
if(!file_exists($extView)) mkdir($extView, 0777);
|
||||
if(!file_exists($extCSS)) mkdir($extCSS, 0777);
|
||||
if(!file_exists($extJS)) mkdir($extJS, 0777);
|
||||
if(!file_exists($extConfig)) mkdir($extConfig, 0777);
|
||||
if(!file_exists($extLang)) mkdir($extLang, 0777);
|
||||
|
||||
/* Touch .gitkeep file. */
|
||||
touch($extControl . '/.gitkeep');
|
||||
touch($extModel . '/.gitkeep');
|
||||
touch($extView . '/.gitkeep');
|
||||
touch($extCSS . '/.gitkeep');
|
||||
touch($extJS . '/.gitkeep');
|
||||
touch($extConfig . '/.gitkeep');
|
||||
|
||||
/* 创建语言目录。*/
|
||||
$langs = array_keys($config->langs);
|
||||
foreach($langs as $lang)
|
||||
{
|
||||
$langPath = $extLang . $lang;
|
||||
if(!file_exists($langPath)) mkdir($langPath, 0777);
|
||||
touch($langPath . '/.gitkeep');
|
||||
}
|
||||
|
||||
echo "init $module ... \n";
|
||||
@@ -3,7 +3,7 @@
|
||||
* This file is used to compress css and js files.
|
||||
*/
|
||||
|
||||
$baseDir = dirname(dirname(__FILE__));
|
||||
$baseDir = dirname(dirname(dirname(__FILE__)));
|
||||
|
||||
//--------------------------------- PROCESS JS FILES ------------------------------ //
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?php
|
||||
include '../config/config.php';
|
||||
include '../../config/config.php';
|
||||
connectDB();
|
||||
|
||||
$databases[] = 'zentao_03';
|
||||
22
build/tools/tags.php
Executable file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
/* This file is used to crete a tag of subverion. */
|
||||
|
||||
$config->zentaophp->svnRoot = 'https://zentaophp.googlecode.com/svn/';
|
||||
$config->zentaophp->svnTrunk = 'trunk/';
|
||||
$config->zentaophp->svnTags = 'tags/';
|
||||
|
||||
$config->zentaopms->svnRoot = 'https://ZenTaoPMS.googlecode.com/svn/';
|
||||
$config->zentaopms->svnTrunk = 'trunk/';
|
||||
$config->zentaopms->svnTags = 'tags/';
|
||||
|
||||
if(count($argv) != 4) die(__FILE__ . " repo version releasetype:beta|alpa|stable\n");
|
||||
|
||||
$repo = $argv[1];
|
||||
$version = $argv[2];
|
||||
$release = $argv[3];
|
||||
|
||||
$sourceURL = $config->$repo->svnRoot . $config->$repo->svnTrunk;
|
||||
$targetURL = $config->$repo->svnRoot . $config->$repo->svnTags . $repo . '_' . $version . '_' . $release . '_' . date('Ymd');
|
||||
|
||||
$svnCMD = "svn rm $targetURL -m 'remove it'; svn cp $sourceURL $targetURL -m 'tag $version of $repo'";
|
||||
system($svnCMD);
|
||||
247
build/windows/build.php
Normal file
@@ -0,0 +1,247 @@
|
||||
<?php
|
||||
$buildDir = dirname(__FILE__);
|
||||
chdir($buildDir);
|
||||
|
||||
/* include the file class. */
|
||||
include '../../lib/zfile/zfile.class.php';
|
||||
$file = new zfile();
|
||||
|
||||
/* set xampp package and 7-zip command. */
|
||||
if(count($argv) != 4) die("php build.php xampp.7z 7zip output.\n");
|
||||
$xampp = $argv[1] . '\xampp.7z';
|
||||
$phpmyadmin = $argv[1] . '\phpmyadmin.7z';
|
||||
$sevenz = $argv[2];
|
||||
$output = $argv[3];
|
||||
|
||||
chdir($output);
|
||||
|
||||
/* extract the xampp package. */
|
||||
echo "extracting xampp package ...";
|
||||
echo `$sevenz x -y $xampp`;
|
||||
echo `$sevenz x -y $phpmyadmin`;
|
||||
|
||||
/* rm useless files. */
|
||||
error_reporting(E_ALL);
|
||||
$file->removeDir('./xampp/cgi-bin');
|
||||
$file->removeDir('./xampp/contrib');
|
||||
$file->removeDir('./xampp/install');
|
||||
$file->removeDir('./xampp/licenses');
|
||||
$file->removeDir('./xampp/locale');
|
||||
$file->removeDir('./xampp/mailoutput');
|
||||
$file->removeDir('./xampp/mailtodisk');
|
||||
$file->removeDir('./xampp/perl');
|
||||
$file->removeDir('./xampp/sendmail');
|
||||
$file->removeDir('./xampp/security');
|
||||
$file->batchRemoveFile('./xampp/tmp/*');
|
||||
$file->removeDir('./xampp/webdav');
|
||||
$file->batchRemoveFile('./xampp/*.txt');
|
||||
$file->batchRemoveFile('./xampp/*.bat');
|
||||
$file->batchRemoveFile('./xampp/*.exe');
|
||||
$file->batchRemoveFile('./xampp/*.ini');
|
||||
|
||||
/* Process apache module. */
|
||||
$file->batchRemoveFile('./xampp/apache/*.txt');
|
||||
$file->batchRemoveFile('./xampp/apache/*.bat');
|
||||
$file->rename('./xampp/apache/modules', './xampp/apache/modulesold');
|
||||
$file->mkdir('./xampp/apache/modules');
|
||||
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_access_compat.so', './xampp/apache/modules/mod_access_compat.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_auth_basic.so', './xampp/apache/modules/mod_auth_basic.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_auth_basic.so', './xampp/apache/modules/mod_auth_basic.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_authz_core.so', './xampp/apache/modules/mod_authz_core.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_mime.so', './xampp/apache/modules/mod_mime.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_expires.so', './xampp/apache/modules/mod_expires.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_env.so', './xampp/apache/modules/mod_env.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_rewrite.so', './xampp/apache/modules/mod_rewrite.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_setenvif.so', './xampp/apache/modules/mod_setenvif.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_autoindex.so', './xampp/apache/modules/mod_autoindex.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_authz_user.so', './xampp/apache/modules/mod_authz_user.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_authz_host.so', './xampp/apache/modules/mod_authz_host.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_alias.so', './xampp/apache/modules/mod_alias.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_dir.so', './xampp/apache/modules/mod_dir.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_deflate.so', './xampp/apache/modules/mod_deflate.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_filter.so', './xampp/apache/modules/mod_filter.so');
|
||||
$file->copyFile('./xampp/apache/modulesold/mod_log_config.so', './xampp/apache/modules/mod_log_config.so');
|
||||
$file->removeDir('./xampp/apache/modulesold');
|
||||
|
||||
/* Remove apache's error, icons, include, lib, logs directory. */
|
||||
$file->removeDir('./xampp/apache/cgi-bin');
|
||||
$file->removeDir('./xampp/apache/error');
|
||||
$file->removeDir('./xampp/apache/icons');
|
||||
$file->removeDir('./xampp/apache/include');
|
||||
$file->removeDir('./xampp/apache/lib');
|
||||
$file->removeDir('./xampp/apache/conf/extra');
|
||||
$file->batchRemoveFile('./xampp/apache/logs/*.log');
|
||||
$file->batchRemoveFile('./xampp/apache/*.pl');
|
||||
$file->removeDir('./xampp/apache/manual');
|
||||
|
||||
$file->rename('./xampp/apache/bin', './xampp/apache/binold');
|
||||
$file->mkdir('./xampp/apache/bin');
|
||||
|
||||
$file->copyFile('./xampp/apache/binold/htpasswd.exe', './xampp/apache/bin/htpasswd.exe');
|
||||
$file->copyFile('./xampp/apache/binold/httpd.exe', './xampp/apache/bin/httpd.exe');
|
||||
$file->copyFile('./xampp/apache/binold/libapr-1.dll', './xampp/apache/bin/libapr-1.dll');
|
||||
$file->copyFile('./xampp/apache/binold/libapriconv-1.dll', './xampp/apache/bin/libapriconv-1.dll');
|
||||
$file->copyFile('./xampp/apache/binold/libaprutil-1.dll', './xampp/apache/bin/libaprutil-1.dll');
|
||||
$file->copyFile('./xampp/apache/binold/libhttpd.dll', './xampp/apache/bin/libhttpd.dll');
|
||||
$file->copyFile('./xampp/apache/binold/zlib1.dll', './xampp/apache/bin/zlib1.dll');
|
||||
$file->copyFile('./xampp/apache/binold/pv.exe', './xampp/apache/bin/pv.exe');
|
||||
$file->copyFile('./xampp/apache/binold/libeay32.dll', './xampp/apache/bin/libeay32.dll');
|
||||
$file->copyFile('./xampp/apache/binold/ssleay32.dll', './xampp/apache/bin/ssleay32.dll');
|
||||
$file->copyFile('./xampp/apache/binold/pcre.dll', './xampp/apache/bin/pcre.dll');
|
||||
$file->copyFile('./xampp/apache/binold/msvcr100.dll', './xampp/apache/bin/msvcr100.dll');
|
||||
$file->removeDir('./xampp/apache/binold');
|
||||
|
||||
/* Process the apache's config file. */
|
||||
$file->copyFile($buildDir . '/httpd.conf', './xampp/apache/conf/httpd.conf');
|
||||
|
||||
/* Remove useless config files. */
|
||||
$file->removeDir('./xampp/apache/conf/ssl.crl');
|
||||
$file->removeDir('./xampp/apache/conf/ssl.crt');
|
||||
$file->removeDir('./xampp/apache/conf/ssl.csr');
|
||||
$file->removeDir('./xampp/apache/conf/ssl.key');
|
||||
$file->removeFile('./xampp/apache/conf/magic');
|
||||
$file->removeFile('./xampp/apache/conf/charset.conv');
|
||||
|
||||
/* Empty the htdocs directory. */
|
||||
$file->removeDir('./xampp/htdocs');
|
||||
$file->mkdir('./xampp/htdocs');
|
||||
|
||||
/* Process mysql. */
|
||||
$file->removeDir('./xampp/mysql/backup');
|
||||
$file->removeDir('./xampp/mysql/include');
|
||||
$file->removeDir('./xampp/mysql/lib');
|
||||
$file->removeDir('./xampp/mysql/scripts');
|
||||
$file->removeDir('./xampp/mysql/sql-bench');
|
||||
|
||||
/* Process mysql's bin directory. */
|
||||
$file->rename('./xampp/mysql/bin', './xampp/mysql/binold');
|
||||
$file->mkdir('./xampp/mysql/bin');
|
||||
|
||||
$file->copyFile('./xampp/mysql/binold/mysql.exe', './xampp/mysql/bin/mysql.exe');
|
||||
$file->copyFile('./xampp/mysql/binold/mysqld.exe', './xampp/mysql/bin/mysqld.exe');
|
||||
$file->copyFile('./xampp/mysql/binold/mysqldump.exe', './xampp/mysql/bin/mysqldump.exe');
|
||||
$file->removeFile('./xampp/mysql/binold/my.ini');
|
||||
|
||||
$file->removeDir('./xampp/mysql/binold');
|
||||
|
||||
/* Process mysql's share diectory. */
|
||||
$file->rename('./xampp/mysql/share', './xampp/mysql/shareold');
|
||||
$file->mkdir('./xampp/mysql/share');
|
||||
$file->mkdir('./xampp/mysql/share/english');
|
||||
$file->copyFile('./xampp/mysql/shareold/english/errmsg.sys', './xampp/mysql/share/english/errmsg.sys');
|
||||
$file->removeDir('./xampp/mysql/shareold');
|
||||
$file->removeFile('./xampp/mysql/resetroot.bat');
|
||||
|
||||
/* Process mysql's data directory. */
|
||||
$file->removeDir('./xampp/mysql/data/test');
|
||||
$file->removeDir('./xampp/mysql/data/webauth');
|
||||
$file->removeDir('./xampp/mysql/data/cdcol');
|
||||
$file->removeDir('./xampp/mysql/data/phpmyadmin');
|
||||
$file->batchRemoveFile('./xampp/mysql/data/ib*');
|
||||
$file->batchRemoveFile('./xampp/mysql/data/mysql*');
|
||||
|
||||
/* Remove mysql's useless config files. */
|
||||
$file->batchRemoveFile('./xampp/mysql/my-*');
|
||||
$file->removeFile('./xampp/mysql/README');
|
||||
$file->removeFile('./xampp/mysql/COPYING');
|
||||
|
||||
/* Process mysql's conf file. */
|
||||
$file->copyFile($buildDir . '/my.ini', './xampp/mysql/my.ini');
|
||||
|
||||
/* Processing php. */
|
||||
$file->removeDir('./xampp/php/cfg');
|
||||
$file->removeDir('./xampp/php/extras');
|
||||
$file->removeDir('./xampp/php/data');
|
||||
$file->removeDir('./xampp/php/DB');
|
||||
$file->removeDir('./xampp/php/dev');
|
||||
$file->removeDir('./xampp/php/docs');
|
||||
$file->removeDir('./xampp/php/PEAR');
|
||||
$file->removeDir('./xampp/php/tests');
|
||||
$file->removeDir('./xampp/php/Text');
|
||||
$file->removeDir('./xampp/php/tmp');
|
||||
$file->removeDir('./xampp/php/www');
|
||||
$file->removeDir('./xampp/php/scripts');
|
||||
$file->batchRemoveFile('./xampp/php/dbunit*');
|
||||
$file->batchRemoveFile('./xampp/php/*.bat');
|
||||
$file->batchRemoveFile('./xampp/php/*.txt');
|
||||
$file->batchRemoveFile('./xampp/php/php.ini-*');
|
||||
$file->batchRemoveFile('./xampp/php/*.reg');
|
||||
$file->batchRemoveFile('./xampp/php/pci*');
|
||||
$file->batchRemoveFile('./xampp/php/*.phar');
|
||||
$file->batchRemoveFile('./xampp/php/php-*.exe');
|
||||
$file->batchRemoveFile('./xampp/php/phpcov');
|
||||
$file->batchRemoveFile('./xampp/php/phptok');
|
||||
$file->batchRemoveFile('./xampp/php/phpunit');
|
||||
$file->batchRemoveFile('./xampp/php/*.php');
|
||||
$file->batchRemoveFile('./xampp/php/phpcs');
|
||||
$file->batchRemoveFile('./xampp/php/phpdoc');
|
||||
$file->batchRemoveFile('./xampp/php/phpuml');
|
||||
$file->batchRemoveFile('./xampp/php/*.sh');
|
||||
$file->batchRemoveFile('./xampp/php/logs/*');
|
||||
$file->batchRemoveFile('./xampp/php/php5embed.lib');
|
||||
|
||||
$file->rename('./xampp/php/php5apache2_4.dll', './xampp/php/php5apache2_4.bak');
|
||||
$file->rename('./xampp/php/php5ts.dll', './xampp/php/php5ts.bak');
|
||||
$file->rename('./xampp/php/ssleay32.dll', './xampp/php/ssleay32.dll.bak');
|
||||
$file->rename('./xampp/php/libeay32.dll', './xampp/php/libeay32.dll.bak');
|
||||
$file->rename('./xampp/php/libsasl.dll', './xampp/php/libsasl.dll.bak');
|
||||
$file->batchRemoveFile('./xampp/php/*.dll');
|
||||
$file->rename('./xampp/php/php5apache2_4.bak', './xampp/php/php5apache2_4.dll');
|
||||
$file->rename('./xampp/php/php5ts.bak', './xampp/php/php5ts.dll');
|
||||
$file->rename('./xampp/php/ssleay32.dll.bak', './xampp/php/ssleay32.dll');
|
||||
$file->rename('./xampp/php/libeay32.dll.bak', './xampp/php/libeay32.dll');
|
||||
$file->copyFile('./xampp/php/libsasl.dll.bak', './xampp/apache/bin/libsasl.dll');
|
||||
$file->rename('./xampp/php/libsasl.dll.bak', './xampp/php/libsasl.dll');
|
||||
|
||||
/* Process php ini file. */
|
||||
$file->copyFile($buildDir . '/php.ini', './xampp/php/php.ini');
|
||||
|
||||
/* Process php's ext directory. */
|
||||
$file->rename('./xampp/php/ext', './xampp/php/extold');
|
||||
$file->mkdir('./xampp/php/ext');
|
||||
$file->copyFile('./xampp/php/extold/php_bz2.dll', './xampp/php/ext/php_bz2.dll');
|
||||
$file->copyFile('./xampp/php/extold/php_gd2.dll', './xampp/php/ext/php_gd2.dll');
|
||||
$file->copyFile('./xampp/php/extold/php_imap.dll', './xampp/php/ext/php_imap.dll');
|
||||
$file->copyFile('./xampp/php/extold/php_mbstring.dll', './xampp/php/ext/php_mbstring.dll');
|
||||
$file->copyFile('./xampp/php/extold/php_mysql.dll', './xampp/php/ext/php_mysql.dll');
|
||||
$file->copyFile('./xampp/php/extold/php_mysqli.dll', './xampp/php/ext/php_mysqli.dll');
|
||||
$file->copyFile('./xampp/php/extold/php_pdo_mysql.dll', './xampp/php/ext/php_pdo_mysql.dll');
|
||||
$file->copyFile('./xampp/php/extold/php_sockets.dll', './xampp/php/ext/php_sockets.dll');
|
||||
$file->copyFile('./xampp/php/extold/php_openssl.dll', './xampp/php/ext/php_openssl.dll');
|
||||
$file->copyFile('./xampp/php/extold/php_ldap.dll', './xampp/php/ext/php_ldap.dll');
|
||||
$file->copyFile('./xampp/php/extold/php_curl.dll', './xampp/php/ext/php_curl.dll');
|
||||
$file->removeDir('./xampp/php/extold');
|
||||
|
||||
/* Process phpmyadmin. */
|
||||
$file->removeDir('./xampp/phpMyAdmin');
|
||||
$file->copyDir('./phpMyAdmin-3.5.5-all-languages', './xampp/phpmyadmin/');
|
||||
$file->mkdir('./xampp/phpmyadmin/locale.new');
|
||||
$file->copyDir('./xampp/phpmyadmin/locale/zh_CN', './xampp/phpmyadmin/locale.new/zh_CN');
|
||||
$file->copyDir('./xampp/phpmyadmin/locale/zh_TW', './xampp/phpmyadmin/locale.new/zh_TW');
|
||||
$file->copyDir('./xampp/phpmyadmin/locale/en_GB', './xampp/phpmyadmin/locale.new/en_GB');
|
||||
$file->removeDir('./xampp/phpmyadmin/locale');
|
||||
$file->rename('./xampp/phpmyadmin/locale.new', './xampp/phpmyadmin/locale');
|
||||
$file->copyFile($buildDir . '/phpmyadmin.php', './xampp/phpmyadmin/config.inc.php');
|
||||
$file->removeDir('./xampp/phpmyadmin/themes/original/');
|
||||
$file->removeDir('./xampp/phpmyadmin/examples/');
|
||||
$file->removeDir('./xampp/phpmyadmin/js/openlayers/');
|
||||
$file->removeDir('./xampp/phpmyadmin/libraries/tcpdf/');
|
||||
$file->batchRemoveFile('./xampp/phpmyadmin/Documentation*');
|
||||
|
||||
/* Process the svn. */
|
||||
$file->copyDir($buildDir . '/svn/silksvn/', './xampp/silksvn');
|
||||
$file->mkdir('./xampp/zentao/module/svn/ext/config');
|
||||
$file->copyFile($buildDir . '/svn/svn.php', './xampp/zentao/module/svn/ext/config/svn.php');
|
||||
|
||||
/* Copy index.php. */
|
||||
$file->copyFile($buildDir . '/index.php', './xampp/htdocs/index.php');
|
||||
|
||||
/* Copy ioncube loader. */
|
||||
$file->copyFile($buildDir . '/ioncube_loader_win_5.4.dll', './xampp/php/ext/ioncube_loader_win_5.4.dll');
|
||||
|
||||
/* Copy serive bat file. */
|
||||
$file->copyDir($buildDir . '/services', './xampp/services');
|
||||
|
||||
/* Copy the readme.txt. */
|
||||
$file->copyFile($buildDir . '/readme.txt', './xampp/readme.txt');
|
||||
113
build/windows/httpd.conf
Normal file
@@ -0,0 +1,113 @@
|
||||
# server basic settings.
|
||||
ServerRoot "/xampp/apache"
|
||||
DocumentRoot "/xampp/htdocs"
|
||||
Listen 80
|
||||
ServerAdmin zentao@localhost.net
|
||||
ServerName localhost:80
|
||||
PidFile "logs/httpd.pid"
|
||||
|
||||
# performance settings.
|
||||
Timeout 300
|
||||
KeepAlive On
|
||||
MaxKeepAliveRequests 100
|
||||
KeepAliveTimeout 5
|
||||
UseCanonicalName Off
|
||||
HostnameLookups Off
|
||||
ThreadsPerChild 150
|
||||
MaxRequestsPerChild 0
|
||||
#Win32DisableAcceptEx
|
||||
|
||||
# security
|
||||
AccessFileName .ztaccess
|
||||
ServerTokens Prod
|
||||
ServerSignature Off
|
||||
|
||||
# deflat.
|
||||
AcceptFilter http none
|
||||
DeflateCompressionLevel 9
|
||||
AddOutputFilterByType DEFLATE text/html text/css application/javascript
|
||||
|
||||
# modules
|
||||
LoadModule access_compat_module modules/mod_access_compat.so
|
||||
LoadModule alias_module modules/mod_alias.so
|
||||
LoadModule auth_basic_module modules/mod_auth_basic.so
|
||||
LoadModule authz_core_module modules/mod_authz_core.so
|
||||
LoadModule authz_host_module modules/mod_authz_host.so
|
||||
LoadModule authz_user_module modules/mod_authz_user.so
|
||||
LoadModule deflate_module modules/mod_deflate.so
|
||||
LoadModule dir_module modules/mod_dir.so
|
||||
LoadModule env_module modules/mod_env.so
|
||||
LoadModule expires_module modules/mod_expires.so
|
||||
LoadModule filter_module modules/mod_filter.so
|
||||
LoadModule log_config_module modules/mod_log_config.so
|
||||
LoadModule mime_module modules/mod_mime.so
|
||||
LoadModule rewrite_module modules/mod_rewrite.so
|
||||
LoadModule setenvif_module modules/mod_setenvif.so
|
||||
|
||||
# php module
|
||||
LoadFile "/xampp/php/php5ts.dll"
|
||||
LoadModule php5_module "/xampp/php/php5apache2_4.dll"
|
||||
|
||||
<FilesMatch "\.php$">
|
||||
SetHandler application/x-httpd-php
|
||||
</FilesMatch>
|
||||
<IfModule php5_module>
|
||||
PHPINIDir "/xampp/php"
|
||||
</IfModule>
|
||||
|
||||
<IfModule mime_module>
|
||||
AddType text/html .php .phps
|
||||
</IfModule>
|
||||
|
||||
# directory settings.
|
||||
DirectoryIndex index.html index.htm index.php
|
||||
<Directory />
|
||||
AllowOverride none
|
||||
Require all denied
|
||||
</Directory>
|
||||
<Directory "/xampp/htdocs">
|
||||
Options FollowSymLinks
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
<Files ".zt*">
|
||||
Require all denied
|
||||
</Files>
|
||||
|
||||
# logs
|
||||
ErrorLog "logs/error_log"
|
||||
LogLevel warn
|
||||
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" combined
|
||||
CustomLog "logs/access_log" combined
|
||||
|
||||
# If you want visit zentao like http://localhost/, uncomment these lines.
|
||||
#<VirtualHost *:80>
|
||||
# ServerAdmin zentao@local.net
|
||||
# DocumentRoot "/xampp/zentao/www"
|
||||
# ServerName localhost:80
|
||||
# <Directory />
|
||||
# AllowOverride none
|
||||
# Require all granted
|
||||
# </Directory>
|
||||
# ErrorLog "logs/error_log"
|
||||
# CustomLog "logs/access_log" combind
|
||||
#</VirtualHost>
|
||||
|
||||
# setting for zentao.
|
||||
Alias /zentao "/xampp/zentao/www/"
|
||||
<Directory "/xampp/zentao/www">
|
||||
Order deny,allow
|
||||
Allow from all
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
|
||||
# setting for admin
|
||||
Alias /phpmyadmin "/xampp/phpmyadmin/"
|
||||
<Directory "/xampp/phpmyadmin">
|
||||
AllowOverride AuthConfig
|
||||
Require all granted
|
||||
Order deny,allow
|
||||
Deny from all
|
||||
Allow from 127.0.0.1
|
||||
</Directory>
|
||||
89
build/windows/index.php
Normal file
@@ -0,0 +1,89 @@
|
||||
<?php
|
||||
error_reporting(0);
|
||||
|
||||
$config->langs['cn'] = '中文简体';
|
||||
$config->langs['en'] = 'EN';
|
||||
|
||||
$lang->cn->title = '欢迎使用禅道集成运行环境!';
|
||||
$lang->cn->poweredBy = "由<a href='http://www.apachefriends.org/' target='_blank'>xampp</a>精简而来";
|
||||
|
||||
$lang->cn->links['zentao']['link'] = '/zentao/';
|
||||
$lang->cn->links['zentao']['text'] = '访问禅道';
|
||||
$lang->cn->links['zentao']['target'] = '_self';
|
||||
|
||||
$lang->cn->links['official']['link'] = 'http://www.zentao.net/';
|
||||
$lang->cn->links['official']['text'] = '禅道官网';
|
||||
$lang->cn->links['official']['target'] = '_blank';
|
||||
|
||||
$lang->cn->links['phpmyadmin']['link'] = '/phpmyadmin/';
|
||||
$lang->cn->links['phpmyadmin']['text'] = '数据库管理';
|
||||
$lang->cn->links['phpmyadmin']['target'] = '_blank';
|
||||
|
||||
$lang->cn->links['phpinfo']['link'] = '?mode=phpinfo';
|
||||
$lang->cn->links['phpinfo']['text'] = 'PHP信息';
|
||||
$lang->cn->links['phpinfo']['target'] = '_blank';
|
||||
|
||||
$lang->en->title = 'Welcome to use zentao!';
|
||||
$lang->en->poweredBy = "reduced from <a href='http://www.apachefriends.org/' target='_blank'>xampp</a>";
|
||||
|
||||
$lang->en->links['zentao']['link'] = '/zentao/';
|
||||
$lang->en->links['zentao']['text'] = 'ZenTao';
|
||||
$lang->en->links['zentao']['target'] = '_self';
|
||||
|
||||
$lang->en->links['official']['link'] = 'http://www.zentao.net/';
|
||||
$lang->en->links['official']['text'] = 'Community';
|
||||
$lang->en->links['official']['target'] = '_blank';
|
||||
|
||||
$lang->en->links['phpmyadmin']['link'] = '/phpmyadmin/';
|
||||
$lang->en->links['phpmyadmin']['text'] = 'MySQL';
|
||||
$lang->en->links['phpmyadmin']['target'] = '_blank';
|
||||
|
||||
$lang->en->links['phpinfo']['link'] = '?mode=phpinfo';
|
||||
$lang->en->links['phpinfo']['text'] = 'PHP';
|
||||
$lang->en->links['phpinfo']['target'] = '_blank';
|
||||
|
||||
if(is_file('./my.php')) include './my.php';
|
||||
|
||||
$acceptLang = stripos($_SERVER['HTTP_ACCEPT_LANGUAGE'], 'zh-CN') !== false ? 'cn' : 'en';
|
||||
$acceptLang = isset($_GET['lang']) ? $_GET['lang'] : $acceptLang;
|
||||
$clientLang = $lang->$acceptLang;
|
||||
?>
|
||||
<?php if(isset($_GET['mode']) and $_GET['mode'] == 'phpinfo') die(phpinfo());?>
|
||||
<html xmlns='http://www.w3.org/1999/xhtml'>
|
||||
<head>
|
||||
<meta http-equiv='Content-Type' content='text/html; charset=utf-8' />
|
||||
<meta http-equiv="refresh" content="5; url=/zentao/" />
|
||||
<title><?php echo $clientLang->title;?></title>
|
||||
<link href="/zentao/theme/default/style.css" rel="stylesheet" type="text/css">
|
||||
<link href="/zentao/theme/default/yui.css" rel="stylesheet" type="text/css">
|
||||
<style>
|
||||
html {background-color:#06294e;}
|
||||
table{margin-top:200px; background:white; border:none}
|
||||
tr, th, td{border:none}
|
||||
#welcome{font-size:20px}
|
||||
#logo{width:120px; border-right:1px solid #efefef}
|
||||
#links{padding-left:25px}
|
||||
#links a{display:block; width:100px; height:25px; line-height:25px; float:left; margin-right:5px; border:1px solid gray; background:#efefef; text-decoration:none; text-align:center}
|
||||
#links #zentao{background:green; color:#efefef}
|
||||
#power{background:#efefef}
|
||||
.button-c{width:100px}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<table class='table-5' align='center'>
|
||||
<tr class='colhead'><th colspan='2' id='welcome'><?php echo $clientLang->title;?></th></tr>
|
||||
<tr>
|
||||
<td id='logo'><img src='/zentao/theme/default/images/main/logo2.png' /></td>
|
||||
<td id='links'><?php foreach($clientLang->links as $linkID => $link) echo "<a id='$linkID' href='$link[link]' target='$link[target]'>$link[text]</a>";?></td>
|
||||
</tr>
|
||||
<tr id='power'>
|
||||
<td class='a-right' colspan='2'>
|
||||
<?php
|
||||
echo $clientLang->poweredBy . ' ';
|
||||
foreach($config->langs as $langCode => $langName) echo "<a href='?lang=$langCode'>$langName</a>";
|
||||
?>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
BIN
build/windows/ioncube_loader_win_5.4.dll
Normal file
51
build/windows/my.ini
Normal file
@@ -0,0 +1,51 @@
|
||||
[client]
|
||||
port = 3306
|
||||
socket = "/xampp/mysql/mysql.sock"
|
||||
|
||||
[mysqld]
|
||||
server-id = 1
|
||||
port = 3306
|
||||
socket = "/xampp/mysql/mysql.sock"
|
||||
basedir = "/xampp/mysql"
|
||||
tmpdir = "/xampp/tmp"
|
||||
datadir = "/xampp/mysql/data"
|
||||
pid_file = "mysql.pid"
|
||||
|
||||
key_buffer = 16M
|
||||
max_allowed_packet = 1M
|
||||
table_cache = 64
|
||||
sort_buffer_size = 512K
|
||||
net_buffer_length = 8K
|
||||
read_buffer_size = 256K
|
||||
read_rnd_buffer_size = 512K
|
||||
myisam_sort_buffer_size = 8M
|
||||
|
||||
plugin_dir = "/xampp/mysql/data/lib/plugin/"
|
||||
|
||||
skip-federated
|
||||
skip-innodb
|
||||
default-storage-engine=MyISAM
|
||||
|
||||
log_error = "mysql_error"
|
||||
|
||||
[mysqldump]
|
||||
quick
|
||||
max_allowed_packet = 16M
|
||||
|
||||
[mysql]
|
||||
no-auto-rehash
|
||||
|
||||
[isamchk]
|
||||
key_buffer = 20M
|
||||
sort_buffer_size = 20M
|
||||
read_buffer = 2M
|
||||
write_buffer = 2M
|
||||
|
||||
[myisamchk]
|
||||
key_buffer = 20M
|
||||
sort_buffer_size = 20M
|
||||
read_buffer = 2M
|
||||
write_buffer = 2M
|
||||
|
||||
[mysqlhotcopy]
|
||||
interactive-timeout
|
||||
152
build/windows/php.ini
Normal file
@@ -0,0 +1,152 @@
|
||||
zend_extension = "/xampp/php/ext/ioncube_loader_win_5.4.dll"
|
||||
|
||||
[PHP]
|
||||
engine = On
|
||||
|
||||
short_open_tag = Off
|
||||
asp_tags = Off
|
||||
|
||||
precision = 14
|
||||
y2k_compliance = On
|
||||
|
||||
output_buffering = 4096
|
||||
zlib.output_compression = Off
|
||||
implicit_flush = Off
|
||||
unserialize_callback_func =
|
||||
serialize_precision = 100
|
||||
allow_call_time_pass_reference = Off
|
||||
|
||||
safe_mode = Off
|
||||
safe_mode_gid = Off
|
||||
safe_mode_include_dir =
|
||||
safe_mode_exec_dir =
|
||||
safe_mode_allowed_env_vars = PHP_
|
||||
safe_mode_protected_env_vars = LD_LIBRARY_PATH
|
||||
|
||||
disable_functions =
|
||||
disable_classes =
|
||||
zend.enable_gc = On
|
||||
expose_php = Off
|
||||
|
||||
max_execution_time = 30
|
||||
max_input_time = 60
|
||||
memory_limit = 128M
|
||||
|
||||
error_reporting = E_ALL | E_STRICT
|
||||
display_errors = On
|
||||
display_startup_errors = On
|
||||
log_errors = On
|
||||
log_errors_max_len = 1024
|
||||
ignore_repeated_errors = Off
|
||||
ignore_repeated_source = Off
|
||||
report_memleaks = On
|
||||
track_errors = On
|
||||
html_errors = On
|
||||
error_log = "logs/php_error"
|
||||
|
||||
variables_order = "GPCS"
|
||||
request_order = "GP"
|
||||
register_globals = Off
|
||||
register_long_arrays = Off
|
||||
register_argc_argv = Off
|
||||
auto_globals_jit = On
|
||||
post_max_size = 50M
|
||||
magic_quotes_gpc = Off
|
||||
magic_quotes_runtime = Off
|
||||
|
||||
auto_prepend_file =
|
||||
auto_append_file =
|
||||
|
||||
default_mimetype = "text/html"
|
||||
|
||||
include_path = ".;/xampp/php/PEAR"
|
||||
doc_root =
|
||||
user_dir =
|
||||
|
||||
extension_dir = "/xampp/php/ext"
|
||||
enable_dl = On
|
||||
|
||||
file_uploads = On
|
||||
upload_tmp_dir = "/xampp/tmp"
|
||||
upload_max_filesize = 50M
|
||||
max_file_uploads = 20
|
||||
|
||||
allow_url_fopen = On
|
||||
allow_url_include = Off
|
||||
default_socket_timeout = 60
|
||||
|
||||
extension=php_bz2.dll
|
||||
extension=php_curl.dll
|
||||
extension=php_mbstring.dll
|
||||
extension=php_gd2.dll
|
||||
extension=php_mysql.dll
|
||||
extension=php_mysqli.dll
|
||||
extension=php_pdo_mysql.dll
|
||||
extension=php_sockets.dll
|
||||
extension=php_ldap.dll
|
||||
extension=php_openssl.dll
|
||||
|
||||
[Date]
|
||||
date.timezone = Asia/Shanghai
|
||||
|
||||
[Pdo_mysql]
|
||||
pdo_mysql.cache_size = 2000
|
||||
pdo_mysql.default_socket = "MySQL"
|
||||
|
||||
[MySQL]
|
||||
mysql.allow_local_infile = On
|
||||
mysql.allow_persistent = On
|
||||
mysql.cache_size = 2000
|
||||
mysql.max_persistent = -1
|
||||
mysql.max_links = -1
|
||||
mysql.default_port = 3306
|
||||
mysql.default_socket = "MySQL"
|
||||
mysql.default_host =
|
||||
mysql.default_user =
|
||||
mysql.default_password =
|
||||
mysql.connect_timeout = 3
|
||||
mysql.trace_mode = Off
|
||||
|
||||
[MySQLi]
|
||||
mysqli.max_persistent = -1
|
||||
mysqli.allow_local_infile = On
|
||||
mysqli.allow_persistent = On
|
||||
mysqli.max_links = -1
|
||||
mysqli.cache_size = 2000
|
||||
mysqli.default_port = 3306
|
||||
mysqli.default_socket = "MySQL"
|
||||
mysqli.default_host =
|
||||
mysqli.default_user =
|
||||
mysqli.default_pw =
|
||||
mysqli.reconnect = Off
|
||||
|
||||
[mysqlnd]
|
||||
mysqlnd.collect_statistics = On
|
||||
mysqlnd.collect_memory_statistics = Off
|
||||
|
||||
[Session]
|
||||
session.save_handler = files
|
||||
session.save_path = "/xampp/tmp"
|
||||
session.use_cookies = 1
|
||||
session.use_only_cookies = 0
|
||||
session.name = PHPSESSID
|
||||
session.auto_start = 0
|
||||
session.cookie_lifetime = 0
|
||||
session.cookie_path = /
|
||||
session.cookie_domain =
|
||||
session.cookie_httponly =
|
||||
session.serialize_handler = php
|
||||
session.gc_probability = 1
|
||||
session.gc_divisor = 1000
|
||||
session.gc_maxlifetime = 1440
|
||||
session.bug_compat_42 = On
|
||||
session.bug_compat_warn = On
|
||||
session.referer_check =
|
||||
session.entropy_length = 0
|
||||
session.entropy_file =
|
||||
session.cache_limiter = nocache
|
||||
session.cache_expire = 180
|
||||
session.use_trans_sid = 0
|
||||
session.hash_function = 0
|
||||
session.hash_bits_per_character = 5
|
||||
url_rewriter.tags = "a=href,area=href,frame=src,input=src,form=fakeentry"
|
||||
9
build/windows/phpmyadmin.php
Normal file
@@ -0,0 +1,9 @@
|
||||
<?php
|
||||
$cfg['Servers'][1]['auth_type'] = 'config';
|
||||
$cfg['Servers'][1]['user'] = 'root';
|
||||
$cfg['Servers'][1]['password'] = '';
|
||||
$cfg['Servers'][1]['port'] = '3306';
|
||||
$cfg['Servers'][1]['host'] = 'localhost';
|
||||
$cfg['Servers'][1]['connect_type'] = 'tcp';
|
||||
$cfg['Servers'][1]['extension'] = 'mysqli';
|
||||
$cfg['Servers'][1]['AllowNoPassword'] = true;
|
||||
46
build/windows/readme.txt
Normal file
@@ -0,0 +1,46 @@
|
||||
Ϊ<EFBFBD>˱<EFBFBD>֤<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʹ<EFBFBD>ã<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>֮ǰ<EFBFBD><EFBFBD>ϸ<EFBFBD>Ķ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˵<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
1. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
1.1 һ<><D2BB>Ҫ<EFBFBD><D2AA>xamppĿ¼<C4BF><C2BC><EFBFBD><EFBFBD>ijһ<C4B3><D2BB><EFBFBD>̵ĸ<CCB5>Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD>c:\xampp, d:\xampp<70><70>
|
||||
1.2 <20><><EFBFBD><EFBFBD>xamppĿ¼<C4BF><C2BC>˫<EFBFBD><CBAB>start.bat<61>ű<EFBFBD><C5B1><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||||
1.3 ͨ<><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><F2BCB4BF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʡ<EFBFBD>
|
||||
|
||||
<20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ͨ<EFBFBD><CDA8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>xampp\serviceĿ¼<C4BF><C2BC>˫<EFBFBD><CBAB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>install.bat<61><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD>װ<EFBFBD><D7B0><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
2. ע<><D7A2><EFBFBD><EFBFBD><EFBFBD>
|
||||
|
||||
2.1 <20><>Ҫ<EFBFBD>Ķ<EFBFBD>xampp<70><70>Ŀ¼<C4BF><C2BC><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>⡣
|
||||
2.2 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD>apache<68><65><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˿ں<CBBF><DABA>Ƿ<EFBFBD><C7B7><EFBFBD>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ȷ<EFBFBD>ϲ<EFBFBD><CFB2>Ƕ˿ڳ<CBBF>ͻ<EFBFBD><CDBB><EFBFBD><EFBFBD><DEB7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>뿼<EFBFBD>ǰ<EFBFBD>װvc<76><63><EFBFBD>л<EFBFBD><D0BB><EFBFBD><EFBFBD><EFBFBD>
|
||||
32λϵͳ<CFB5><CDB3><EFBFBD>أ<EFBFBD>http://www.microsoft.com/downloads/details.aspx?FamilyID=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF
|
||||
64λϵͳ<CFB5><CDB3><EFBFBD>أ<EFBFBD>http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=15336
|
||||
2.3 <20><><EFBFBD><EFBFBD>ϵͳĬ<CDB3>ϵĹ<CFB5><C4B9><EFBFBD>Ա<EFBFBD>ʺ<EFBFBD><CABA><EFBFBD>admin<69><6E><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>123456<35><36>
|
||||
2.4 <20><><EFBFBD>ݿ<EFBFBD>Ĭ<EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>root<6F><74><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ϊ<EFBFBD>ա<EFBFBD>
|
||||
2.5 <20><><EFBFBD><EFBFBD><EFBFBD>ķ<EFBFBD><C4B7><EFBFBD>·<EFBFBD><C2B7><EFBFBD><EFBFBD>http://localhost/zentao/ <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʽ<EFBFBD>localhost<73><74><EFBFBD><EFBFBD>ip<69><70>ַ<EFBFBD><D6B7><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>˿ںŲ<DABA><C5B2><EFBFBD>80<38><30><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD>϶˿ںš<DABA>
|
||||
2.6 <20><><EFBFBD>ݿ<EFBFBD><DDBF><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD>http://localhost/phpmyadmin/<2F><>phpmyadminֻ<6E><D6BB><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʡ<EFBFBD>
|
||||
|
||||
<EFBFBD><EFBFBD>ϸ<EFBFBD>Ľ<EFBFBD><EFBFBD>ܣ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ʣ<EFBFBD>http://www.zentao.net/help-read-79597.html
|
||||
|
||||
Please read the flowing notes before you run zentao:
|
||||
|
||||
1. How to start zentao:
|
||||
|
||||
1.1 Please make sure to put xmapp under the root of one driver, for example c:\xampp or d:\xampp.
|
||||
1.2 Enter the xampp directory and double click the start.bat to start the control panel of zentao.
|
||||
1.3 Click the 'Start' button to start zentao.
|
||||
|
||||
If you can't start zentao by the control panel, cd xampp\service, double click the install.bat to install and start services
|
||||
for zentao manually.
|
||||
|
||||
2. Notice:
|
||||
|
||||
2.1 Don't change the directory name of xampp.
|
||||
2.2 If zentao can't start, please check whether the ports of 80 and 3306 conflict with other webserver and database server.
|
||||
If you make sure no conflicts for apache and mysql, please consider to install the vc runtime.
|
||||
32bit: http://www.microsoft.com/downloads/details.aspx?FamilyID=9B2DA534-3E03-4391-8A4D-074B9F2BC1BF
|
||||
64bit: http://www.microsoft.com/download/en/details.aspx?displaylang=en&id=15336
|
||||
2.3 The default administrator for zentao is admin, password is 123456.
|
||||
2.4 The default administrator for database is root, password is empty.
|
||||
2.5 The url for zentao is: http://your ip address/zentao/, if not 80, add it.
|
||||
2.6 To manage database, visit http://localhost/phpmyadmin, which can only be visited from the localhost.
|
||||
|
||||
For more infomation, please visit: http://www.zentao.net/help-read-79597.html.
|
||||
32
build/windows/services/install.bat
Normal file
@@ -0,0 +1,32 @@
|
||||
@echo off
|
||||
set currentDir=%cd%
|
||||
|
||||
echo %currentDir% | find ":\xampp\services" > null
|
||||
if %ERRORLEVEL% == 1 goto notRootDirectory
|
||||
if %ERRORLEVEL% == 0 goto normalStart
|
||||
|
||||
:notRootDirectory
|
||||
echo "Please extract the xampp to root directory, example:D:\\xampp"
|
||||
|
||||
del .\null
|
||||
|
||||
pause
|
||||
exit
|
||||
|
||||
:normalStart
|
||||
echo First I need set the path for php and mysql
|
||||
..\php\php.exe .\set.php
|
||||
|
||||
echo Installing apache 2.4 as service...
|
||||
..\apache\bin\httpd -k install -n apachezt
|
||||
echo starting apache
|
||||
net start apachezt
|
||||
|
||||
echo Installing mysql as service...
|
||||
..\mysql\bin\mysqld.exe --install mysqlzt
|
||||
echo starting mysql
|
||||
net start mysqlzt
|
||||
|
||||
del .\null
|
||||
|
||||
pause
|
||||
18
build/windows/services/remove.bat
Normal file
@@ -0,0 +1,18 @@
|
||||
@echo off
|
||||
|
||||
echo stopping apache 2.4
|
||||
net stop apachezt
|
||||
echo removing apache 2.4
|
||||
..\apache\bin\httpd -k uninstall -n apachezt
|
||||
|
||||
del port.apache
|
||||
|
||||
echo
|
||||
echo stopping mysql
|
||||
net stop mysqlzt
|
||||
echo removing mysql
|
||||
..\mysql\bin\mysqld.exe --remove mysqlzt
|
||||
|
||||
del port.mysql
|
||||
|
||||
pause
|
||||
169
build/windows/services/set.php
Normal file
@@ -0,0 +1,169 @@
|
||||
<?php
|
||||
/**
|
||||
* This file is used to set path and port for apache, mysql and php config files.
|
||||
*/
|
||||
|
||||
/* Config files. */
|
||||
$phpConf = '../php/php.ini';
|
||||
$mysqlConf = '../mysql/my.ini';
|
||||
$apacheConf = '../apache/conf/httpd.conf';
|
||||
$zentaoConf = '../zentao/config/my.php';
|
||||
$pmaConf = '../phpmyadmin/config.inc.php';
|
||||
|
||||
/* Replace drivers for php and mysql. */
|
||||
replaceDriver($phpConf); print("Set driver for php.ini.\n");
|
||||
replaceDriver($mysqlConf); print("Set driver for my.ini.\n");
|
||||
|
||||
/* Set ports of apache and mysql. */
|
||||
$usedPorts = getUsedPorts();
|
||||
|
||||
$apachePort = setApachePort($usedPorts, 88);
|
||||
$apachePort ? print("Apache is using $apachePort port.\n") : "Set apache port error, please check $apacheConf.\n";
|
||||
|
||||
$mysqlPort = setMySQLPort($usedPorts, 3308);
|
||||
if($mysqlPort)
|
||||
{
|
||||
echo "Mysql is using $mysqlPort port.\n";
|
||||
setZenTaoConf($mysqlPort);
|
||||
setPMAConf($mysqlPort);
|
||||
}
|
||||
else
|
||||
{
|
||||
echo "Set mysql port error, please check $mysqlConf.\n";
|
||||
}
|
||||
|
||||
/* Replace a config file with current driver. */
|
||||
function replaceDriver($file)
|
||||
{
|
||||
$driver = getDriver();
|
||||
$lines = file_get_contents($file);
|
||||
$lines = preg_replace('|([a-zA-Z]{1}:){0,1}/xampp/|', "$driver:/xampp/", $lines);
|
||||
file_put_contents($file, $lines);
|
||||
}
|
||||
|
||||
/* Get current driver letter. */
|
||||
function getDriver()
|
||||
{
|
||||
return strtolower(substr(__FILE__, 0, strpos(__FILE__, ':')));
|
||||
}
|
||||
|
||||
/* Set apache port. */
|
||||
function setApachePort($usedPorts, $suggestPort)
|
||||
{
|
||||
if(file_exists('./port.apache')) return trim(file_get_contents('./port.apache'));
|
||||
|
||||
global $apacheConf;
|
||||
|
||||
$currentPort = getApachePort();
|
||||
if(isset($usedPorts[$currentPort]))
|
||||
{
|
||||
$found = false;
|
||||
|
||||
for($port = $suggestPort; $port < 100; $port ++)
|
||||
{
|
||||
if(!isset($usedPorts[$port]))
|
||||
{
|
||||
$apache = file_get_contents($apacheConf);
|
||||
$apache = str_replace($currentPort, $port, $apache);
|
||||
file_put_contents($apacheConf, $apache);
|
||||
|
||||
$found = true;
|
||||
$currentPort = $port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$found) $currentPort = 0;
|
||||
}
|
||||
|
||||
if($currentPort != 0) file_put_contents('./port.apache', $currentPort);
|
||||
return $currentPort;
|
||||
}
|
||||
|
||||
/* Get current port of apache. */
|
||||
function getApachePort()
|
||||
{
|
||||
global $apacheConf;
|
||||
|
||||
preg_match('/Listen\s*([0-9]*)/', file_get_contents($apacheConf), $result);
|
||||
if(isset($result[1])) return trim($result[1]);
|
||||
return 80;
|
||||
}
|
||||
|
||||
/* Set port of mysql. */
|
||||
function setMySQLPort($usedPorts, $suggestPort)
|
||||
{
|
||||
if(file_exists('./port.mysql')) return trim(file_get_contents('./port.mysql'));
|
||||
|
||||
global $mysqlConf;
|
||||
|
||||
$currentPort = getMySQLPort();
|
||||
if(isset($usedPorts[$currentPort]))
|
||||
{
|
||||
$found = false;
|
||||
|
||||
for($port = $suggestPort; $port < 3399; $port ++)
|
||||
{
|
||||
if(!isset($usedPorts[$port]))
|
||||
{
|
||||
$mysql = file_get_contents($mysqlConf);
|
||||
$mysql = str_replace($currentPort, $port, $mysql);
|
||||
file_put_contents($mysqlConf, $mysql);
|
||||
|
||||
$found = true;
|
||||
$currentPort = $port;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!$found) $currentPort = 0;
|
||||
}
|
||||
|
||||
if($currentPort != 0) file_put_contents('./port.mysql', $currentPort);
|
||||
return $currentPort;
|
||||
}
|
||||
|
||||
/* Get current port of mysql. */
|
||||
function getMySQLPort()
|
||||
{
|
||||
global $mysqlConf;
|
||||
|
||||
preg_match('/port\s*=\s*([0-9]*)/', file_get_contents($mysqlConf), $result);
|
||||
if(isset($result[1])) return trim($result[1]);
|
||||
return 3306;
|
||||
}
|
||||
|
||||
/* Get used ports. */
|
||||
function getUsedPorts()
|
||||
{
|
||||
/**
|
||||
* Call netstat -na | find /i 'listening' to get all listening ports, which will output:
|
||||
* TCP 0.0.0.0:135 0.0.0.0:0 LISTENING
|
||||
* TCP 0.0.0.0:445 0.0.0.0:0 LISTENING
|
||||
*/
|
||||
$netstats = `netstat -an |find /i "listening"`;
|
||||
|
||||
/* Using preg to strip all listening ports. */
|
||||
preg_match_all('/:([0-9]*)\s{1,}[0-9]{1}/', $netstats, $results);
|
||||
|
||||
if(isset($results[1])) return array_flip(array_unique($results[1]));
|
||||
return array();
|
||||
}
|
||||
|
||||
/* Set mysql port for my.php. */
|
||||
function setZenTaoConf($mysqlPort)
|
||||
{
|
||||
global $zentaoConf;
|
||||
$lines = file_get_contents($zentaoConf);
|
||||
$lines = preg_replace("/=\s'[0-9]{1,}'/", "= '$mysqlPort'", $lines);
|
||||
file_put_contents($zentaoConf, $lines);
|
||||
}
|
||||
|
||||
/* Set mysql port for phpmyadmin. */
|
||||
function setPMAConf($mysqlPort)
|
||||
{
|
||||
global $pmaConf;
|
||||
$lines = file_get_contents($pmaConf);
|
||||
$lines = preg_replace("/=\s'[0-9]{1,}'/", "= '$mysqlPort'", $lines);
|
||||
file_put_contents($pmaConf, $lines);
|
||||
}
|
||||
9
build/windows/services/start.bat
Normal file
@@ -0,0 +1,9 @@
|
||||
@echo off
|
||||
|
||||
echo starting apache
|
||||
net start apachezt
|
||||
|
||||
echo starting mysql
|
||||
net start mysqlzt
|
||||
|
||||
pause
|
||||
9
build/windows/services/stop.bat
Normal file
@@ -0,0 +1,9 @@
|
||||
@echo off
|
||||
|
||||
echo stopping apache
|
||||
net stop apachezt
|
||||
|
||||
echo stopping mysql
|
||||
net stop mysqlzt
|
||||
|
||||
pause
|
||||