Compare commits

..

2 Commits

Author SHA1 Message Date
wangyidong
befa7343c7 + add 4.2.beta tag. 2013-07-08 06:18:50 +00:00
wangyidong
d6d2087d65 + add 4.2.beta tag. 2013-07-08 05:53:28 +00:00
1453 changed files with 22639 additions and 19439 deletions

9
.gitignore vendored
View File

@@ -1,9 +0,0 @@
config/my.php
www/data/
release/*
tmp/extensions/*
tmp/log/*
tmp/model/*
tmp/cache/*
tmp/extension/*
.gitkeep

View File

@@ -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

View File

@@ -1 +0,0 @@
欢迎访问<a href='http://www.zentao.net' target='_blank'>禅道项目管理软件</a>主站,获得最新动态和文档支持。

View File

@@ -1 +1 @@
5.3.stable
4.2.beta

BIN
app/corona/Icon-72.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

BIN
app/corona/Icon-hdpi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

BIN
app/corona/Icon-ldpi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.7 KiB

BIN
app/corona/Icon-mdpi.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

BIN
app/corona/Icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

BIN
app/corona/Icon@2x.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
app/corona/Thumbs.db Normal file

Binary file not shown.

103
app/corona/autoLogin.lua Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.6 KiB

BIN
app/corona/background.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

15
app/corona/build.settings Normal file
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
app/corona/button_over.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

12
app/corona/config.lua Normal file
View File

@@ -0,0 +1,12 @@
-- config.lua
application =
{
content =
{
width = 320,
height = 480,
scale = "letterbox"
},
}

806
app/corona/dkjson.lua Normal file
View 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
View 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 =
{
["&nbsp;"] = " ",
["&bull;"] = " * ",
["?"] = "<",
["?"] = ">",
["&trade;"] = "(tm)",
["&frasl;"] = "/",
["<"] = "<",
[">"] = ">",
["&copy;"] = "(c)",
["&reg;"] = "(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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

206
app/corona/login.lua Normal file
View 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
View 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
View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

206
app/corona/scrollView.lua Normal file
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
app/corona/tab1_over.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
app/corona/tab2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
app/corona/tab2_over.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
app/corona/tab3.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
app/corona/tab3_over.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
app/corona/tab4.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
app/corona/tab4_over.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

BIN
app/corona/tabBar.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

420
app/corona/tableView.lua Normal file
View 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
View 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
View 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
View 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
View 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

View 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
View 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
View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.5 KiB

BIN
app/corona/zentao.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

View File

@@ -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

View File

@@ -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"

View File

@@ -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
View 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
View 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
View 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
View 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>

Binary file not shown.

600
build/linux/lamppctl Executable file
View 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=""
boff=""
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
View 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
View 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
View 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
View 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
View 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

View File

@@ -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;
}
}

View File

@@ -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';

View File

@@ -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';

View File

@@ -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)
{

View File

@@ -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";

View File

@@ -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 ------------------------------ //

View File

@@ -1,5 +1,5 @@
<?php
include '../config/config.php';
include '../../config/config.php';
connectDB();
$databases[] = 'zentao_03';

22
build/tools/tags.php Executable file
View 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
View 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
View 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
View 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>

Binary file not shown.

51
build/windows/my.ini Normal file
View 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
View 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"

View 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
View 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.

View 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

View 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

View 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);
}

View File

@@ -0,0 +1,9 @@
@echo off
echo starting apache
net start apachezt
echo starting mysql
net start mysqlzt
pause

View File

@@ -0,0 +1,9 @@
@echo off
echo stopping apache
net stop apachezt
echo stopping mysql
net stop mysqlzt
pause

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

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