Skip to content
GitLab
Explore
Sign in
Primary navigation
Search or go to…
Project
I
Imldeployment
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Container registry
Model registry
Operate
Environments
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
GitLab community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
IML Open Source
Imldeployment
Merge requests
!66
php8 only; added variable types; short array syntax; remove glyphicons
Code
Review changes
Check out branch
Download
Patches
Plain diff
Expand sidebar
Merged
php8 only; added variable types; short array syntax; remove glyphicons
7359-update-php83
into
master
Overview
0
Commits
61
Pipelines
0
Changes
1
Merged
Hahn Axel (hahn)
requested to merge
7359-update-php83
into
master
10 months ago
Overview
0
Commits
61
Pipelines
0
Changes
1
0
0
Merge request reports
Viewing commit
eea7a809
Prev
Next
Show latest version
1 file
+
256
−
230
Inline
Compare changes
Side-by-side
Inline
Show whitespace changes
Show one file at a time
eea7a809
update api/index.php
· eea7a809
Hahn Axel (hahn)
authored
10 months ago
public_html/api/index.php
+
256
−
230
View file @ eea7a809
Edit in single-file editor
Open in Web IDE
Show full file
@@ -11,245 +11,271 @@
* ----------------------------------------------------------------------
* 2020-06-16 v0.9 <axel.hahn@iml.unibe.ch>
* 2021-03-29 v1.2 <axel.hahn@iml.unibe.ch> support slashes in branch names
* 2024-09-02 v1.3 <axel.hahn@unibe.ch> php8 only; added variable types; short array syntax
* ======================================================================
*/
$bDebug
=
false
;
ini_set
(
'display_errors'
,
1
);
ini_set
(
'display_startup_errors'
,
1
);
error_reporting
(
E_ALL
);
require_once
(
"../../config/inc_projects_config.php"
);
$sDirClasses
=
__DIR__
.
'/../deployment/classes/'
;
require_once
(
$sDirClasses
.
'/project.class.php'
);
require_once
(
$sDirClasses
.
'logger.class.php'
);
$iMaxAge
=
60
;
// ----------------------------------------------------------------------
// FUNCTIONS
// ----------------------------------------------------------------------
/**
* write debug text (if enabled)
* @global boolean $bDebug
* @param string $s message
* @param string $sLevel level; one of info|
* @return boolean
*/
function
_wd
(
$s
,
$sLevel
=
'info'
){
global
$bDebug
;
if
(
$bDebug
){
echo
'<div class="debug debug-'
.
$sLevel
.
'">DEBUG: '
.
$s
.
'</div>'
;
}
return
true
;
$bDebug
=
false
;
ini_set
(
'display_errors'
,
1
);
ini_set
(
'display_startup_errors'
,
1
);
error_reporting
(
E_ALL
);
/**
* Path to deployment classes
* @var string
*/
$sDirClasses
=
__DIR__
.
'/../deployment/classes/'
;
/**
* Allowed time delta for client or server
* @var integer
*/
$iMaxAge
=
60
;
require_once
(
"../../config/inc_projects_config.php"
);
require_once
(
$sDirClasses
.
'/project.class.php'
);
require_once
(
$sDirClasses
.
'logger.class.php'
);
// ----------------------------------------------------------------------
// FUNCTIONS
// ----------------------------------------------------------------------
/**
* Write debug text (if enabled)
*
* @global boolean $bDebug
*
* @param string $s message
* @param string $sLevel level; one of info|
* @return boolean
*/
function
_wd
(
string
$s
,
string
$sLevel
=
'info'
):
bool
{
global
$bDebug
;
if
(
$bDebug
)
{
echo
"<div class=
\"
debug debug-
$sLevel
\"
>DEBUG:
$s
</div>"
;
}
/**
* abort execution with error
* @param string $s message
* @param integer $iStatus http status code to send
*/
function
_quit
(
$s
,
$iStatus
=
400
){
$aStatus
=
array
(
400
=>
'HTTP/1.0 400 Bad Request'
,
403
=>
'HTTP/1.0 403 Access denied'
,
404
=>
'HTTP/1.0 404 Not found'
,
);
header
(
$aStatus
[
$iStatus
]);
_done
(
array
(
'status'
=>
$iStatus
,
'info'
=>
$aStatus
[
$iStatus
],
'message'
=>
$s
));
return
true
;
}
/**
* Abort execution of API requestwith error
*
* @param string $s message
* @param integer $iStatus http status code to send
*/
function
_quit
(
string
$s
,
int
$iStatus
=
400
):
void
{
$aStatus
=
[
400
=>
'HTTP/1.0 400 Bad Request'
,
403
=>
'HTTP/1.0 403 Access denied'
,
404
=>
'HTTP/1.0 404 Not found'
,
];
header
(
$aStatus
[
$iStatus
]);
_done
([
'status'
=>
$iStatus
,
'info'
=>
$aStatus
[
$iStatus
],
'message'
=>
$s
]);
}
/**
* End with OK output
*
* @param array $Data array data to show as JSON
* @return void
*/
function
_done
(
array
$Data
):
void
{
echo
is_array
(
$Data
)
?
json_encode
(
$Data
,
JSON_PRETTY_PRINT
)
:
$Data
;
die
();
}
/**
* Check authorization in the http request header and age of timestamp
* On a failed check the request will be terminated
*
* @global int $iMaxAge max allowed age
*
* @param string $sProjectSecret
* @return boolean
*/
function
_checkAuth
(
string
$sProjectSecret
):
bool
{
global
$iMaxAge
;
$aReqHeaders
=
apache_request_headers
();
_wd
(
'<pre>'
.
print_r
(
$aReqHeaders
,
1
)
.
'</pre>'
);
if
(
!
isset
(
$aReqHeaders
[
'Authorization'
]))
{
_quit
(
'Access denied. Missing authorization.'
,
403
);
}
/**
* end with OK output
* @param type $Data
*/
function
_done
(
$Data
){
echo
is_array
(
$Data
)
?
json_encode
(
$Data
,
JSON_PRETTY_PRINT
)
:
$Data
;
die
();
if
(
!
isset
(
$aReqHeaders
[
'Date'
]))
{
_quit
(
'Access denied. Missing field "Date:" in the request header.'
,
403
);
}
/**
* Check authorization in the http request header and age of timestamp
* On a failed check the request will be terminated
* @global int $iMaxAge max allowed age
* @param string $sProjectSecret
* @return boolean
*/
function
_checkAuth
(
$sProjectSecret
){
global
$iMaxAge
;
$aReqHeaders
=
apache_request_headers
();
_wd
(
'<pre>'
.
print_r
(
$aReqHeaders
,
1
)
.
'</pre>'
);
if
(
!
isset
(
$aReqHeaders
[
'Authorization'
])){
_quit
(
'Access denied. Missing authorization.'
,
403
);
}
if
(
!
isset
(
$aReqHeaders
[
'Date'
])){
_quit
(
'Access denied. Missing field "Date:" in the request header.'
,
403
);
}
$sGotHash
=
preg_replace
(
'/^.*\:/'
,
''
,
$aReqHeaders
[
'Authorization'
]);
$sGotDate
=
$aReqHeaders
[
'Date'
];
$sGotMethod
=
$_SERVER
[
'REQUEST_METHOD'
];
$sGotReq
=
$_SERVER
[
'REQUEST_URI'
];
$sMyData
=
"
$sGotMethod
\n
$sGotReq
\n
$sGotDate
\n
"
;
$sMyHash
=
base64_encode
(
hash_hmac
(
"sha1"
,
$sMyData
,
$sProjectSecret
));
_wd
(
'Hash: '
.
$sGotHash
.
' -- from header'
);
_wd
(
'Hash: '
.
$sMyHash
.
' -- rebuilt'
);
if
(
$sGotHash
!==
$sMyHash
){
_quit
(
'Access denied. Invalid hash.'
,
403
);
}
$iAge
=
date
(
'U'
)
-
date
(
'U'
,
strtotime
(
$sGotDate
));
_wd
(
'Date: '
.
$sGotDate
.
' - age: '
.
$iAge
.
' sec'
);
if
(
$iAge
>
$iMaxAge
){
_quit
(
'Access denied. Hash is out of date: '
.
$iAge
.
' sec is older '
.
$iMaxAge
.
' sec. Maybe client or server is out of sync.'
,
403
);
}
if
(
$iAge
<-
$iMaxAge
){
_quit
(
'Access denied. Hash is '
.
$iAge
.
' sec in future but only '
.
$iMaxAge
.
' sec are allowed. Maybe client or server is out of sync.'
,
403
);
}
return
true
;
$sGotHash
=
preg_replace
(
'/^.*\:/'
,
''
,
$aReqHeaders
[
'Authorization'
]);
$sGotDate
=
$aReqHeaders
[
'Date'
];
$sGotMethod
=
$_SERVER
[
'REQUEST_METHOD'
];
$sGotReq
=
$_SERVER
[
'REQUEST_URI'
];
$sMyData
=
"
$sGotMethod
\n
$sGotReq
\n
$sGotDate
\n
"
;
$sMyHash
=
base64_encode
(
hash_hmac
(
"sha1"
,
$sMyData
,
$sProjectSecret
));
_wd
(
'Hash: '
.
$sGotHash
.
' -- from header'
);
_wd
(
'Hash: '
.
$sMyHash
.
' -- rebuilt'
);
if
(
$sGotHash
!==
$sMyHash
)
{
_quit
(
'Access denied. Invalid hash.'
,
403
);
}
$iAge
=
date
(
'U'
)
-
date
(
'U'
,
strtotime
(
$sGotDate
));
_wd
(
'Date: '
.
$sGotDate
.
' - age: '
.
$iAge
.
' sec'
);
if
(
$iAge
>
$iMaxAge
)
{
_quit
(
'Access denied. Hash is out of date: '
.
$iAge
.
' sec is older '
.
$iMaxAge
.
' sec. Maybe client or server is out of sync.'
,
403
);
}
// ----------------------------------------------------------------------
// MAIN
// ----------------------------------------------------------------------
if
(
!
$bDebug
){
header
(
'Content-Type: application/json'
);
if
(
$iAge
<
-
$iMaxAge
)
{
_quit
(
'Access denied. Hash is '
.
$iAge
.
' sec in future but only '
.
$iMaxAge
.
' sec are allowed. Maybe client or server is out of sync.'
,
403
);
}
_wd
(
'Start: '
.
date
(
'Y-m-d H:i:s'
)
.
'<style>body{background:#eee; color:#456;}
return
true
;
}
// ----------------------------------------------------------------------
// MAIN
// ----------------------------------------------------------------------
if
(
!
$bDebug
)
{
header
(
'Content-Type: application/json'
);
}
_wd
(
'Start: '
.
date
(
'Y-m-d H:i:s'
)
.
'<style>body{background:#eee; color:#456;}
.debug{background:#ddd; margin-bottom: 2px;}
</style>'
);
_wd
(
'request uri is '
.
$_SERVER
[
"REQUEST_URI"
]);
_wd
(
'<pre>GET: '
.
print_r
(
$_GET
,
1
)
.
'</pre>'
);
// ---------- SPLIT URL
$aUriSplit
=
explode
(
'/'
,
preg_replace
(
'/\?.*$/'
,
''
,
$_SERVER
[
"REQUEST_URI"
]));
array_shift
(
$aUriSplit
);
array_shift
(
$aUriSplit
);
_wd
(
'<pre>$aUriSplit: '
.
print_r
(
$aUriSplit
,
1
)
.
'</pre>'
);
/*
/api/v1/projects/ci/build/...
$aUriSplit: Array
(
[0] => v1
[1] => projects
[2] => ci
[3] => build
)
*/
$sApiVersion
=
isset
(
$aUriSplit
[
0
])
?
$aUriSplit
[
0
]
:
false
;
$sApiItem
=
isset
(
$aUriSplit
[
1
])
?
$aUriSplit
[
1
]
:
false
;
if
(
!
$sApiVersion
){
_quit
(
'ERROR: no param for api version was found.'
);
}
if
(
!
$sApiItem
){
_quit
(
'ERROR: no param for item was found.'
);
}
switch
(
$sApiVersion
){
case
'v1'
:
switch
(
$sApiItem
){
case
'projects'
:
$oProject
=
new
project
();
$aList
=
$oProject
->
getProjects
();
_wd
(
'<pre>'
.
print_r
(
$aList
,
1
)
.
'</pre>'
);
_done
(
$aList
);
break
;;
case
'project'
:
// path /api/v1/project
$sPrjId
=
isset
(
$aUriSplit
[
2
])
?
$aUriSplit
[
2
]
:
false
;
$sPrjAction
=
isset
(
$aUriSplit
[
3
])
?
$aUriSplit
[
3
]
:
false
;
$sBranch
=
implode
(
'/'
,
array_slice
(
$aUriSplit
,
4
));
// $sParam4 = isset($aUriSplit[4]) ? $aUriSplit[4] : false;
// $sParam5 = isset($aUriSplit[5]) ? $aUriSplit[5] : false;
$sMethod
=
$_SERVER
[
'REQUEST_METHOD'
];
_wd
(
'$sPrjId = '
.
$sPrjId
);
_wd
(
'$sPrjAction = '
.
$sPrjAction
);
_wd
(
'$sBranch = '
.
$sBranch
);
$oCLog
=
new
logger
();
// try to init the given project
try
{
ob_start
();
$oProject
=
new
project
(
$sPrjId
);
// $oProject->setProjectById($sPrjId);
ob_end_clean
();
}
catch
(
Exception
$exc
)
{
_quit
(
'ERROR: project with id ['
.
$sPrjId
.
'] does not exist.'
,
404
);
}
// get secret
$aPrjCfg
=
$oProject
->
getConfig
();
$sProjectSecret
=
isset
(
$aPrjCfg
[
'api'
][
'secret'
])
?
$aPrjCfg
[
'api'
][
'secret'
]
:
false
;
if
(
!
$sProjectSecret
){
_quit
(
'Access denied. API access is disabled.'
);
}
// check authorization
_checkAuth
(
$sProjectSecret
);
// echo "OK: request was authorized successfully.\n";
$oProject
->
oUser
->
setUser
(
'api'
);
switch
(
$sPrjAction
){
case
"build"
:
if
(
$sBranch
){
$aResult
=
$oProject
->
setBranchname
(
$sBranch
);
}
$sBranchname
=
$oProject
->
getBranchname
();
$aRepodata
=
$oProject
->
getRemoteBranches
(
true
);
// ignore cache = true
if
(
!
isset
(
$aRepodata
[
$sBranchname
])){
_quit
(
'ERROR: branch not found: '
.
$sBranchname
,
404
);
}
// echo "branch is set to ".$oProject->getBranchname()."\n";
if
(
$sMethod
===
'GET'
){
$sNext
=
$oProject
->
getNextPhase
();
_done
(
array
(
'branch'
=>
$sBranchname
,
'phase'
=>
$sNext
,
'repo'
=>
$aRepodata
[
$sBranchname
]
));
}
if
(
$sMethod
===
'POST'
){
echo
"starting build() ..."
;
flush
();
echo
$oProject
->
build
();
}
break
;;
case
"phases"
:
_done
(
$oProject
->
getAllPhaseInfos
());
break
;;
default
:
_quit
(
'ERROR: Wrong action ['
.
$sApiItem
.
'].'
);
}
break
;;
default
:
_quit
(
'ERROR: item ['
.
$sApiItem
.
'] is invalid.'
);
}
break
;
default
:
_quit
(
'ERROR: Wrong (unsupported) api version.'
);
}
\ No newline at end of file
_wd
(
'request uri is '
.
$_SERVER
[
"REQUEST_URI"
]);
_wd
(
'<pre>GET: '
.
print_r
(
$_GET
,
1
)
.
'</pre>'
);
// ---------- SPLIT URL
$aUriSplit
=
explode
(
'/'
,
preg_replace
(
'/\?.*$/'
,
''
,
$_SERVER
[
"REQUEST_URI"
]));
array_shift
(
$aUriSplit
);
array_shift
(
$aUriSplit
);
_wd
(
'<pre>$aUriSplit: '
.
print_r
(
$aUriSplit
,
1
)
.
'</pre>'
);
/*
/api/v1/projects/ci/build/...
$aUriSplit: Array
(
[0] => v1
[1] => projects
[2] => ci
[3] => build
)
*/
$sApiVersion
=
isset
(
$aUriSplit
[
0
])
?
$aUriSplit
[
0
]
:
false
;
$sApiItem
=
isset
(
$aUriSplit
[
1
])
?
$aUriSplit
[
1
]
:
false
;
if
(
!
$sApiVersion
)
{
_quit
(
'ERROR: no param for api version was found.'
);
}
if
(
!
$sApiItem
)
{
_quit
(
'ERROR: no param for item was found.'
);
}
switch
(
$sApiVersion
)
{
case
'v1'
:
switch
(
$sApiItem
)
{
case
'projects'
:
$oProject
=
new
project
();
$aList
=
$oProject
->
getProjects
();
_wd
(
'<pre>'
.
print_r
(
$aList
,
1
)
.
'</pre>'
);
_done
(
$aList
);
break
;
;
case
'project'
:
// path /api/v1/project
$sPrjId
=
isset
(
$aUriSplit
[
2
])
?
$aUriSplit
[
2
]
:
false
;
$sPrjAction
=
isset
(
$aUriSplit
[
3
])
?
$aUriSplit
[
3
]
:
false
;
$sBranch
=
implode
(
'/'
,
array_slice
(
$aUriSplit
,
4
));
// $sParam4 = isset($aUriSplit[4]) ? $aUriSplit[4] : false;
// $sParam5 = isset($aUriSplit[5]) ? $aUriSplit[5] : false;
$sMethod
=
$_SERVER
[
'REQUEST_METHOD'
];
_wd
(
'$sPrjId = '
.
$sPrjId
);
_wd
(
'$sPrjAction = '
.
$sPrjAction
);
_wd
(
'$sBranch = '
.
$sBranch
);
$oCLog
=
new
logger
();
// try to init the given project
try
{
ob_start
();
$oProject
=
new
project
(
$sPrjId
);
// $oProject->setProjectById($sPrjId);
ob_end_clean
();
}
catch
(
Exception
$exc
)
{
_quit
(
'ERROR: project with id ['
.
$sPrjId
.
'] does not exist.'
,
404
);
}
// get secret
$aPrjCfg
=
$oProject
->
getConfig
();
$sProjectSecret
=
isset
(
$aPrjCfg
[
'api'
][
'secret'
])
?
$aPrjCfg
[
'api'
][
'secret'
]
:
false
;
if
(
!
$sProjectSecret
)
{
_quit
(
'Access denied. API access is disabled.'
);
}
// check authorization
_checkAuth
(
$sProjectSecret
);
// echo "OK: request was authorized successfully.\n";
$oProject
->
oUser
->
setUser
(
'api'
);
switch
(
$sPrjAction
)
{
case
"build"
:
if
(
$sBranch
)
{
$aResult
=
$oProject
->
setBranchname
(
$sBranch
);
}
$sBranchname
=
$oProject
->
getBranchname
();
$aRepodata
=
$oProject
->
getRemoteBranches
(
true
);
// ignore cache = true
if
(
!
isset
(
$aRepodata
[
$sBranchname
]))
{
_quit
(
'ERROR: branch not found: '
.
$sBranchname
,
404
);
}
// echo "branch is set to ".$oProject->getBranchname()."\n";
if
(
$sMethod
===
'GET'
)
{
$sNext
=
$oProject
->
getNextPhase
();
_done
([
'branch'
=>
$sBranchname
,
'phase'
=>
$sNext
,
'repo'
=>
$aRepodata
[
$sBranchname
]
]);
}
if
(
$sMethod
===
'POST'
)
{
echo
"starting build() ..."
;
flush
();
echo
$oProject
->
build
();
}
break
;
;
case
"phases"
:
_done
(
$oProject
->
getAllPhaseInfos
());
break
;
;
default
:
_quit
(
'ERROR: Wrong action ['
.
$sApiItem
.
'].'
);
}
break
;
;
default
:
_quit
(
'ERROR: item ['
.
$sApiItem
.
'] is invalid.'
);
}
break
;
default
:
_quit
(
'ERROR: Wrong (unsupported) api version.'
);
}
\ No newline at end of file
Loading