Display all Debug::debug_message() function output
131 |
132 |
check 'Display debug in web page'
133 |
134 |
135 |
Filter output from Debug::debug_message()
136 |
137 |
Insert comma separated list of tags to be shown in page - Debug tags
138 |
Insert comma separated list of string to be matched agains tags or parts of the message - Debug filters
139 |
140 |
141 |
View logs from \$_Session['xdebug']
142 |
143 |
by default logs are displayed in \$_Session['xdebug']
144 |
use Dump \$_SESSION button to visualize them
145 |
146 |
send all xdebug logs in log file
147 |
148 |
check dump_xdebug
149 |
150 |
display all xdebug logs on screen
151 |
152 |
check dump_xdebug field
153 |
check 'Display logs on web' field
154 |
155 |
display just xdebug logs from specific tags on screen
156 |
157 |
check dump_xdebug
158 |
check 'Display logs on web' field
159 |
add the tags in debug_modules field
160 |
161 |
enable/disable debug buttons
162 |
163 |
check/uncheck 'Enable debug buttons' option
164 |
165 |
",
166 | "no_escape"=>true),
167 |
168 |
169 | // Setting php ini
170 | "objtitle2"=>array("display"=> "objtitle" , "value"=> "Overwriting settings from php.ini"),
171 | "error_reporting"=>array($errors, "display"=>"select", "comment"=>"Controls php error_reporting. If set it will be kept in session and it will modify error_reporting until logging out or modifying it again from this form."),
172 | "display_errors"=>array("value"=>$display_errors, "display"=>"checkbox", "comment"=>"Controls php display_errors. If set it will be kept in session and it will modify error_reporting until logging out or modifying it again from this form."),
173 | "log_errors"=>array("value"=>$log_errors, "display"=>"checkbox", "comment"=>"Controls php log_errors. If set it will be kept in session and it will modify error_reporting until logging out or modifying it again from this form."),
174 | "error_log"=>array("value"=>$error_log/*, "display"=>"checkbox"*/),
175 | );
176 |
177 | if (is_auth("debug"))
178 | unset($arr["pass_debug"]);
179 |
180 | $submit_button = "";
181 | $reset_button = "";
182 |
183 | $cancel_link = previous_page_link();
184 | $cancel_button = "";
185 |
186 | $arr["buttons"] = array("display"=>"custom_submit", "value"=>$submit_button . " " . $reset_button . " " . $cancel_button);
187 |
188 | ?>
189 | $value) {
247 | // print $key. ' '. $value.' ';
248 | if($value == $err) {
249 | $error_reporting = $key;
250 | break;
251 | }
252 | }
253 | if(!$error_reporting)
254 | $error_reporting = $err;
255 | ini_set("error_reporting",$error_reporting);
256 | $_SESSION["error_reporting"] = $error_reporting;
257 | // ini_set('error_reporting', E_ALL);
258 |
259 | $display_errors = (getparam("display_errors") == "on") ? true : false;
260 |
261 | ini_set("display_errors",$display_errors);
262 | $_SESSION["display_errors"] = $display_errors;
263 |
264 | $log_errors = (getparam("log_errors") == "on") ? true : false;
265 | ini_set("log_errors",$log_errors);
266 | $_SESSION["log_errors"] = $log_errors;
267 |
268 | $error_log = getparam("error_log");
269 | ini_set("error_log", $error_log);
270 | $_SESSION["error_log"] = $error_log;
271 |
272 |
273 | $previous_link = previous_page_link() ;
274 |
275 | message("Settings were saved!Back to previous page.", "no", "", false);
276 |
277 | debug();
278 | }
279 |
280 | function previous_page_link()
281 | {
282 | if (isset($_SESSION["previous_link"]))
283 | $previous_link = $_SESSION["previous_link"];
284 | else
285 | $previous_link = str_replace("/ansql/debug_all.php", "", $_SERVER["PHP_SELF"]) . "/main.php";
286 |
287 | $request_protocol = get_request_protocol();
288 |
289 | return $request_protocol . "://" . $_SERVER["HTTP_HOST"] . $previous_link;
290 | }
291 | ?>
292 |
293 |
294 |
--------------------------------------------------------------------------------
/lib_json_requests.php:
--------------------------------------------------------------------------------
1 |
18 |
75 |
76 |
77 |
78 |
79 |
80 |
81 | Expecting with type application/json
82 |
83 |
84 | "2"); // "Not yet implemented"
105 | }
106 |
107 | $params = array();
108 | foreach($vars as $name=>$var) {
109 | if (!isset($arr[$name]))
110 | continue;
111 | $value = get_param($arr, $name);
112 | if ($var->isRequired() && !strlen($value)) {
113 | //send_error(406, "Not Acceptable");
114 | return array(false, "code"=>"10");
115 | }
116 | $params[$name] = $value;
117 | }
118 | if ($obj_id != "__no_id") {
119 | $id = ($obj_id) ? $obj_id : $obj->getIdName();
120 | // make sure we have $params[$id] in case class was not correctly defined
121 | if (!isset($params[$id]) || !strlen($params[$id])) {
122 | //send_error(406, "Not Acceptable");
123 | return array(false, "code"=>"10");
124 | }
125 |
126 | $db_obj = Model::selection($class_name, array($id=>$params[$id]));
127 | if (count($db_obj)) {
128 | // this object already exists and we should modify it
129 | $obj = $db_obj[0];
130 | if ($edit_function == "edit") {
131 | if ($obj_id)
132 | $res = $obj->edit($params,array($obj_id=>$params[$obj_id]));
133 | else
134 | $res = $obj->edit($params);
135 | } elseif ($edit_function == "fieldupdate") {
136 | $params_to_edit = array();
137 | foreach($arr as $name=>$value) {
138 | if ($name == $obj_id)
139 | continue;
140 | $obj->{$name} = $value;
141 | $params_to_edit[] = $name;
142 | }
143 | $res = $obj->fieldUpdate(array($obj_id=>$params[$obj_id]),$params_to_edit);
144 | } else {
145 | //send_error(500, "Internal Server Error");
146 | return array(false, "code"=>"98"); // Internal Server Error:: called wrong function
147 | }
148 | } else {
149 | $res = $obj->add($params);
150 | }
151 | } else {
152 | $res = $obj->add($params);
153 | }
154 | if (!$res[0]) {
155 | //send_error(406, "Not Acceptable");
156 | return array(false, "code"=>$res[1]);
157 | }
158 | return array(true, "code"=>"0", "obj"=>$obj);
159 | }
160 |
161 | function check_response($out)
162 | {
163 | Debug::func_start(__FUNCTION__,func_get_args(),"ansql");
164 |
165 | $arr = array();
166 | foreach ($out as $name=>$val) {
167 | if (is_array($val))
168 | $arr[$name] = check_response($val);
169 | else {
170 | if ($name == "error_code" && $val=="")
171 | $val = "0";
172 | $arr[$name] = $val;
173 | }
174 | }
175 | return $arr;
176 | }
177 |
178 | function translate_error_to_code($res, $exception_true=false)
179 | {
180 | Debug::func_start(__FUNCTION__,func_get_args(),"ansql");
181 |
182 | // if (is_array($res) && count($res)==1 && $res[0]===true)
183 | // return $res;
184 |
185 | if (!is_array($res) || (count($res)<2 && (($res[0]===false) || !isset($res[0]))) || !isset($res[0]))
186 | return array(false, "code"=>"99"); // Internal Server Error: wrong result format from called function
187 |
188 | if ($res[0] && $exception_true) {
189 | if (!isset($res["code"]))
190 | return array(true);
191 | return array(true, "code"=>$res["code"]); // this code will define a user/contact not success of request
192 | }
193 | elseif ($res[0]/* && !$exception_true*/) {
194 | return $res; // normal success case
195 | } elseif (!$res[0] && $exception_true) {
196 | if (!isset($res["code"])) // succes and default contact already existed
197 | return array(true);
198 | return array(true, "code"=>$res["code"]); // this code will define a user/contact not success of request
199 | }
200 | $new_res = array(false);
201 | if (isset($res[1])) {
202 | if (substr($res[1], -12)==" is required" || substr($res[1], -9)==" not set.")
203 | $new_res["code"] = "10"; // Missing or empty parameters
204 | else
205 | $new_res["code"] = "97";
206 | } elseif (isset($res["code"]))
207 | $new_res["code"] = $res["code"];
208 | else
209 | $new_res["code"] = "99";
210 |
211 | // even if error, if more fields set in result (with non numeric key) copy them to response
212 | if (count($res)>2 || (count($res)>1 && !isset($res[1]))) {
213 | foreach ($res as $key=>$val) {
214 | if (!is_numeric($key))
215 | $new_res[$key] = $val;
216 | }
217 | }
218 |
219 | return $new_res;
220 | }
221 |
222 | function clean_session()
223 | {
224 | Debug::func_start(__FUNCTION__,func_get_args(),"ansql");
225 |
226 | global $direct_request;
227 |
228 | // taken from comments on php site for session_unset
229 | /* session_unset();
230 | session_destroy();
231 | session_write_close();
232 | setcookie(session_name(),'',0,'/');
233 | session_regenerate_id(true);*/
234 |
235 |
236 | // Unset all of the session variables.
237 | $_SESSION = array();
238 |
239 | if (isset($direct_request))
240 | return;
241 |
242 | // If it's desired to kill the session, also delete the session cookie.
243 | // Note: This will destroy the session, and not just the session data!
244 | if (ini_get("session.use_cookies")) {
245 | $params = session_get_cookie_params();
246 | setcookie(session_name(), '', time() - 42000,
247 | $params["path"], $params["domain"],
248 | $params["secure"], $params["httponly"]
249 | );
250 | }
251 |
252 | if (isset($_SESSION))
253 | // Finally, destroy the session.
254 | session_destroy();
255 | }
256 |
257 |
258 | function set_session()
259 | {
260 | Debug::func_start(__FUNCTION__,func_get_args(),"ansql");
261 |
262 | global $sesslife_json;
263 |
264 | if (isset($sesslife_json))
265 | session_set_cookie_params($sesslife_json);
266 | if (!session_id()) {
267 | $res = session_start();
268 | if (!$res)
269 | return array(false,"code"=>"105");
270 | }
271 | return array(true);
272 | }
273 |
274 | function retrieve_json()
275 | {
276 | Debug::func_start(__FUNCTION__,func_get_args(),"ansql");
277 |
278 | global $json;
279 |
280 | $json = file_get_contents('php://input');
281 | $inp = json_decode($json,true);
282 | if ($inp === null)
283 | return array(false,"code"=>"6");
284 | return array(true,"json"=>$inp);
285 | }
286 |
287 | function write_response($out)
288 | {
289 | Debug::func_start(__FUNCTION__,func_get_args(),"ansql");
290 |
291 | global $error_codes, $add_newline, $enable_logs, $logs_file;
292 | global $start_time, $med_time;
293 | global $func_name, $class_name, $request_id;
294 | global $json, $used_backup, $current_input;
295 |
296 | if (isset($error_codes[$out["code"]]) && !isset($out["message"]))
297 | $out["message"] = $error_codes[$out["code"]];
298 | $out = check_response($out);
299 | send_content();
300 | $o_json = json_encode($out);
301 | print $o_json;
302 | if (isset($add_newline) && in_array($func_name,$add_newline))
303 | print "\n";
304 |
305 | $end_time = microtime(true);
306 | if ($enable_logs) {
307 | $day = date("Y-m-d");
308 | $file = str_replace(".txt","$day.txt",$logs_file);
309 | $fh = fopen($file, "a");
310 | if (!$fh) {
311 | print ("Could not open logs file $file");
312 | exit;
313 | }
314 | $aprox_duration = round($end_time - $start_time,4);
315 | $id = (isset($_SESSION["user_id"])) ? ", user_id=".$_SESSION["user_id"] : "";
316 | $captcha = isset($_SESSION["req_captcha"])? ", captcha_sess=".$_SESSION["req_captcha"] : "";
317 | fwrite($fh, "------ ".date("Y-m-d H:i:s").", ip=".$_SERVER['REMOTE_ADDR'].", func=$func_name, class=$class_name"."$id, request_id='$request_id', aprox_duration=$aprox_duration, med_time=$med_time"."$captcha \n");
318 | fwrite($fh, "Json: $json"."\n");
319 | fwrite($fh, "Input: ".str_replace("\n"," ",print_r($current_input,true))."\n");
320 | fwrite($fh, "Output: ".str_replace("\n"," ",print_r($out,true))."\n");
321 | fwrite($fh, "JsonOut: $o_json"."\n");
322 | if (isset($used_backup))
323 | fwrite($fh,$used_backup."\n");
324 | fclose($fh);
325 | }
326 | }
327 |
328 | function process_request($inp, $func="arr_to_db", $class_name=NULL, $exit_after_func_ok=false)
329 | {
330 | Debug::func_start(__FUNCTION__,func_get_args(),"ansql");
331 |
332 | global $json, $enable_r_logs, $request_id, $r_logs_file;
333 |
334 | $request_id = rand();
335 |
336 | if ($enable_r_logs) {
337 | $day = date("Y-m-d");
338 | $file = str_replace(".txt","$day.txt",$r_logs_file);
339 |
340 | $fh = fopen($file, "a");
341 | if (!$fh)
342 | // "Internal Server Error: Could not open requests logs file."
343 | return array(false, "code"=>"101");
344 | fwrite($fh, "------ ".date("Y-m-d H:i:s").", ip=".$_SERVER['REMOTE_ADDR'].", func=$func, class=$class_name".", request_id='$request_id'\n");
345 | fwrite($fh, "Json: $json"."\n");
346 | fclose($fh);
347 | }
348 |
349 | $return_error = get_param($inp,"returnerror");
350 | if (missing_param($return_error)) {
351 | if ($class_name)
352 | $res = $func($inp, $class_name);
353 | else
354 | $res = $func($inp);
355 | } else {
356 | if (substr($return_error,0,7) == "timeout") {
357 | $time = str_replace("timeout:","",$return_error);
358 | // max_execution_time = 30 in php.ini so requester should get timeout
359 | sleep($time);
360 | //print "This should not be seen if you set timeout parameter when making request.";
361 | //exit();
362 | if ($class_name)
363 | $res = $func($inp, $class_name);
364 | else
365 | $res = $func($inp);
366 | } else
367 | $res = array(false, "code"=>$return_error);
368 | }
369 | if (isset($res["obj"]))
370 | unset($res["obj"]);
371 | if (!isset($res[0]))
372 | return array(false, "code"=>"99"); // Internal server error: wrong result format from called function
373 |
374 | $res = translate_error_to_code($res);
375 | if ($res[0] && $exit_after_func_ok)
376 | // for get_captcha type of request: don't return anything by default
377 | exit;
378 | if (!$res[0]) {
379 | unset($res[0]);
380 | return $res;
381 | } else
382 | unset($res[0]);
383 |
384 | if (!isset($res[1])) {
385 | $ret = array("code"=>"0");
386 | if (count($res))
387 | $ret = array_merge($ret,$res);
388 | return $ret;
389 | } else {
390 | if (!isset($res[1]["code"]))
391 | $res[1]["code"] = 0;
392 | return $res[1];
393 | }
394 | }
395 |
396 | // in case backup database connection is used, call this function to record this in the logs
397 | function log_used_backup_conn($connection_index)
398 | {
399 | Debug::func_start(__FUNCTION__,func_get_args(),"ansql");
400 |
401 | global $used_backup, $server_id;
402 |
403 | $used_backup = "Used backup connection '$connection_index' for server_id=$server_id";
404 | }
405 | ?>
406 |
--------------------------------------------------------------------------------
/api/lib_api.php:
--------------------------------------------------------------------------------
1 |
23 | 200,
51 | "message" => "OK",
52 | "params" => $params,
53 | "download" => $data["download"],
54 | "data" => $data["archive"]
55 | );
56 | $res = array(
57 | "code" => 200,
58 | "message" => "OK",
59 | "params" => $params,
60 | "data" => array("code" => 0, "answer_list"=>$data)
61 | );
62 | if ($extra)
63 | $res["data"]["extra"] = $extra;
64 | return $res;
65 | }
66 |
67 | function build_error($code, $message, $params=array(), $extra=null)
68 | {
69 | $res = array(
70 | "code" => $code,
71 | "message" => $message,
72 | "params" => $params,
73 | "data" => array(
74 | "code" => $code,
75 | "message" => $message
76 | )
77 | );
78 | if ($extra)
79 | $res["data"]["extra"] = $extra; // keeps more details of the broadcast aggregate data
80 | return $res;
81 |
82 | }
83 |
84 | function log_request($inp, $out = null, $write_api_logs = false, $start_time = 0, $custom_content = "")
85 | {
86 | Debug::func_start(__FUNCTION__,func_get_args(),"api");
87 | global $logs_file;
88 | global $logs_dir;
89 | global $func_manage_log_request_content;
90 | global $db_log, $log_db_conn, $save_api_log_to_db;
91 |
92 | $addr = (isset($_SERVER['REMOTE_ADDR'])) ? $_SERVER['REMOTE_ADDR'] : "unknown";
93 |
94 | // If $func_manage_log_request_content is set in defaults.php file, the function result will be added to the requests log files from json_api directory.
95 | if (isset($func_manage_log_request_content) && is_callable($func_manage_log_request_content)) {
96 | call_user_func_array($func_manage_log_request_content, array(&$inp, &$out));
97 | }
98 |
99 | if ($out === null)
100 | $out = "";
101 | elseif (json_encode($out))
102 | $out = "JsonOut: ".json_encode($out)."\n";
103 | else
104 | $out = "DataOut: ". $out."\n";
105 |
106 | $content = "------ " . date("Y-m-d H:i:s") . ", ip=$addr\nURI: ".$_SERVER['REQUEST_URI'];
107 |
108 | // If the user id of the request owner is present, add it to the logs file.
109 | if ($custom_content)
110 | $content .= $custom_content;
111 |
112 | $content .= "\nJson: " . json_encode($inp)."\n$out";
113 |
114 | $request_duration = microtime(true) - $start_time;
115 | $content .= sprintf("Handled: %0.3f seconds\n",$request_duration);
116 |
117 | if (isset($db_log) && $db_log===true && isset($save_api_log_to_db)) {
118 | // if true or 'both'
119 | if ($save_api_log_to_db) {
120 | $log_type = "api_logs";
121 | add_db_log($content,$log_type,"api_logs");
122 | }
123 |
124 | if ($save_api_log_to_db === true)
125 | return;
126 | }
127 |
128 | if ($write_api_logs) {
129 | // the path where all products will write the API logs
130 | $logs_dir = "/var/log/json_api";
131 | $logs_file = (is_writeable($logs_dir)) ? "$logs_dir/requests_log.txt" : null;
132 | }
133 |
134 | if (!$logs_file) {
135 | if (false !== $logs_file)
136 | Debug::xdebug("api", "Not writeable $logs_dir");
137 | return;
138 | }
139 |
140 | $day = date("Y-m-d");
141 | $file = str_replace(".txt","$day.txt",$logs_file);
142 | $fh = fopen($file, "a");
143 | if (!$fh) {
144 | Debug::xdebug("api", "Can't write to $file");
145 | return;
146 | }
147 | fwrite($fh, $content);
148 | fclose($fh);
149 | }
150 |
151 | function decode_post_put($ctype, $method, $uri)
152 | {
153 | Debug::func_start(__FUNCTION__,func_get_args(),"api");
154 | if ($ctype == "application/json" || $ctype == "text/x-json") {
155 | $input = json_decode(file_get_contents('php://input'), true);
156 | if ($input === null)
157 | return array(null, null, null);
158 | if (isset($input["request"])) {
159 | if (isset($input["params"]))
160 | return array($input["request"], $input["params"],@$input["node"]);
161 | else
162 | return array($input["request"], array(),@$input["node"]);
163 | }
164 | } else {
165 | if ($method == "PUT") {
166 | $input = array();
167 | parse_str(file_get_contents("php://input"), $input);
168 | foreach ($input as $key => $value) {
169 | unset($input[$key]);
170 | $input[str_replace('amp;', '', $key)] = $value;
171 | }
172 | } else
173 | $input = $_POST;
174 | $input = array_merge($input, $uri["params"]);
175 | }
176 |
177 | return array(strtolower($method) . "_" . $uri["object"], $input,@$input["node"]);
178 | }
179 |
180 | /**
181 | * Return the actual format of the request that needs to be sent to equipment
182 | * @param $handling String: broadcast, failover, proxy etc
183 | * @param $type String: npdb, subscriber etc
184 | */
185 | function format_api_request($handling, $type, $input)
186 | {
187 | Debug::func_start(__FUNCTION__,func_get_args(),"api");
188 | global $requests_with_set;
189 |
190 | $ctype = $input["ctype"];
191 | $method = $input["method"];
192 | $output = array();
193 |
194 | if ($method == "POST" || $method == "PUT") {
195 | list($output["request"], $output["params"], $output["node"]) =
196 | decode_post_put($ctype, $method, $input);
197 | if ($output["params"] === null)
198 | return array("code"=>415, "message"=>"Unparsable JSON content");
199 | } elseif ($method == "GET") {
200 | $output["request"] = "get_" . $input["object"];
201 | $output["params"] = $_GET;
202 | } elseif ($method == "DELETE") {
203 | $output["request"] = "del_" . $input["object"];
204 | $output["params"] = $input["params"];
205 | }
206 |
207 | if (in_array($type, $requests_with_set)) {
208 | //$output["node"] = "npdb";
209 | $req = explode("_", $output["request"]);
210 | $method = strtoupper($req[0]);
211 |
212 | if ($method == "PUT" || $method == "POST")
213 | $output["request"] = "set_".$input["object"];
214 | }
215 |
216 | // for npdb there are no ids, but will be used for other cases in the future
217 | if (isset($input["id"]))
218 | $output[$input["object"] . "_id"] = $input["id"];
219 |
220 | Debug::xdebug("api", "Builded params with the format of the request: \n".print_r($output,true));
221 | return $output;
222 | }
223 | /**
224 | * Depending on set $handling make request to $equipment and aggregate response (if needed)
225 | * @param $handling String: broadcast, failover, proxy etc
226 | * @param $node_type
227 | * @param $equipment - list of IPs->name equipment returned from get_api_nodes
228 | * @param $request_params - returned from format_api_request
229 | * @param $methods - array that customizes handling for this node_type -- from $predefined_requests
230 | */
231 | function run_api_requests($handling, $node_type, $equipment, $request_params, $methods=array())
232 | {
233 | Debug::func_start(__FUNCTION__,func_get_args(),"api");
234 | $equipment_ips = array_keys($equipment);
235 |
236 | $extra = "";
237 | $extra_err = $extra_succ = "";
238 | $message = "";
239 | $aggregate_response = array();
240 | $have_errors = false;
241 |
242 | $answer = array();
243 | if ($handling == "broadcast") {
244 | foreach ($equipment_ips as $management_link) {
245 | $equipment_name = $equipment[$management_link];
246 | Debug::xdebug("api", "Type of request: 'broadcast' send to equipment '$management_link' with request_params: \n".print_r($request_params,true));
247 | $res = send_api_request($request_params,$management_link);
248 |
249 | // request fails, aggregate the messages and put extra info about the fail/success
250 | if ($res["code"] != 0) {
251 | $have_errors = true;
252 | $code = $res["code"];
253 | if (strlen($extra_err))
254 | $extra_err .= ", ";
255 | $extra_err .= $equipment_name;
256 | /* // Not needed. It used a aggregate message
257 | if (strlen($message))
258 | $message .= " | ";
259 | $message .= $equipment_name.": [".$code."]: " .$res["message"];*/
260 | } else {
261 | // Not needed. Used to aggregate the successful requests
262 | /*foreach ($res as $k=>$response) {
263 | if ($k == "code")
264 | continue;
265 | //$aggregate_response[$k][][$equipment_name] = $response;
266 | $aggregate_response[$k][$equipment_name] = $response;
267 | }*/
268 | if (strlen($extra_succ))
269 | $extra_succ .= ", ";
270 | $extra_succ .= $equipment_name;
271 | }
272 |
273 | $answer[] = array_merge(array("equipment_name"=>$equipment_name), $res);
274 |
275 | // GET requests will not be broadcast to all NPDB nodes, unless $out["params"]["broadcast"] = true
276 | // it is assumed that all the NPDB nodes are kept in synchronization
277 | $cb = (isset($methods["cb_exception_to_broadcast"])) ? $methods["cb_exception_to_broadcast"] : "exception_to_broadcast";
278 | if (is_callable($cb) && call_user_func_array($cb, array($request_params,$handling,$node_type)))
279 | break;
280 | }
281 |
282 | if ($have_errors) {
283 | $extra = "Request ".$request_params["request"]." failed for equipment: ". $extra_err. "\n";
284 | if (strlen($extra_succ))
285 | $extra .= "Request ".$request_params["request"]." succeeded for equipment: ".$extra_succ;
286 | /*return build_error($code, $message, $request_params, $extra);*/
287 |
288 | } else {
289 |
290 | $extra .= "Request ".$request_params["request"]." was successful for equipment: ".$extra_succ;
291 | /*return build_success($aggregate_response, $request_params, $extra);*/
292 | }
293 |
294 | return build_success($answer, $request_params, $extra);
295 |
296 | } elseif ($handling == "failover") {
297 |
298 | foreach ($equipment_ips as $management_link) {
299 | $equipment_name = $equipment[$management_link];
300 | Debug::xdebug("api", "Type of request: 'failover' send to equipment: '$management_link' with request_params: \n".print_r($request_params,true));
301 | $res = send_api_request($request_params,$management_link);
302 |
303 | // simulate positive response for query_data because actual data registration in UCN is needed to get this answer
304 | //if ($equipment_name=="ucn136")
305 | // $res = array("code"=>0, "data_session"=>array("imsi"=>"aaa", "msisdn"=>"aaa", "apn"=>"internet"));
306 |
307 | // return response from first server that returns a positive response
308 | if ($res["code"] === 0) {
309 | $answer[] = array_merge(array("equipment_name"=>$equipment_name), $res);
310 | return build_success($answer, $request_params, "Request ".$request_params["request"]." was successful from equipment $equipment_name");
311 | }
312 | }
313 |
314 | // return the last received error inside a positive MMI response
315 | $answer[] = array_merge(array("equipment_name"=>$equipment_name), $res);
316 | return build_success($answer, $request_params, "Request ".$request_params["request"]." failed: ".$res["message"]);
317 |
318 | /*return build_error($res["code"], $res["message"], $request_params);*/
319 | }
320 | }
321 |
322 | function send_api_request($request_params,$management_link)
323 | {
324 | Debug::func_start(__FUNCTION__,func_get_args(),"api");
325 | $out = array(
326 | "node" => $request_params["node"],
327 | "request" => $request_params["request"],
328 | "params" => isset($request_params["params"]) ? $request_params["params"] : array()
329 | );
330 | $url = "http://$management_link/api.php";
331 | return make_request($out,$url);
332 | }
333 |
334 | function exception_to_broadcast($request_params,$handling,$node_type)
335 | {
336 | // GET requests will not be broadcast to all NPDB nodes, unless $out["params"]["broadcast"] = true
337 | // it is assumed that all the NPDB nodes are kept in synchronization
338 | if (substr($request_params["request"],0,3) == "get" && (!isset($request_params["params"]["broadcast"]) || !$request_params["params"]["broadcast"]))
339 | return true;
340 |
341 | return false;
342 | }
343 |
--------------------------------------------------------------------------------
/api/api.php:
--------------------------------------------------------------------------------
1 |
18 | $req, "params" => $params);
91 | if (stream_resolve_include_path($filename)) {
92 | $req = $renamed_req;
93 | } else {
94 | $filename = "api/requests/" . $req . ".php";
95 | if (!stream_resolve_include_path($filename)) {
96 | Debug::xdebug("api", "Filename $filename doesn't exist.");
97 | return build_error(405, "Method not allowed", $log_params);
98 | }
99 | }
100 |
101 | require_once $filename;
102 |
103 | // in some cases function with same name as request, exits in one of the included libs
104 | // before calling function with same name as request, see if api_$req exists
105 | $func_name = (is_callable("api_".$req)) ? "api_".$req : $req;
106 |
107 | // If $func_specific_process_request is set the auth token is checked and validate and then the API is called.
108 | if (isset($func_specific_process_request) && is_callable($func_specific_process_request)) {
109 | $res = call_user_func_array($func_specific_process_request, array($func_name, $params));
110 | } else {
111 | $res = call_user_func($func_name, $params);
112 | }
113 |
114 | // $log_params = array("request" => $req, "params" => $params);
115 | if ($res[0]) {
116 | /*Check if the global variable is set and its name is a valid function.*/
117 | if (isset($func_build_success_api_response) && is_callable($func_build_success_api_response)) {
118 | $others = (isset($res[2])) ? $res[2] : array();
119 | return $func_build_success_api_response($res[1], $log_params, $others);
120 | }
121 | if (isset($res[2]))
122 | return build_success($res[1], $log_params, $res[2]);
123 | return build_success($res[1], $log_params);
124 | }
125 |
126 | // If $func_build_error_api_response sets the response will contain HTTP 200 "OK" Code, but the response towards the user will be {"code": "Error Code", "message": "Error Message"}.
127 | if (isset($func_build_error_api_response) && is_callable($func_build_error_api_response))
128 | return $func_build_error_api_response($res, $log_params);
129 | if (isset($res[3]))
130 | return build_error($res[1], $res[2], $log_params, $res[3]);
131 | return build_error($res[1], $res[2], $log_params);
132 | }
133 |
134 | function do_request($method = "POST")
135 | {
136 | Debug::func_start(__FUNCTION__,func_get_args(),"api");
137 |
138 | global $cors_origin, $api_secret, $predefined_requests;
139 |
140 | // if (!$api_secret)
141 | // $api_secret = "mmi_secret";
142 |
143 | if (("OPTIONS" == $_SERVER["REQUEST_METHOD"])
144 | && isset($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"])
145 | && ($_SERVER["HTTP_ACCESS_CONTROL_REQUEST_METHOD"] == $method)) {
146 | header("Access-Control-Allow-Origin: $cors_origin");
147 | header("Access-Control-Allow-Methods: $method");
148 | header("Access-Control-Allow-Headers: Content-Type");
149 | header("Content-Type: text/plain");
150 | exit;
151 | }
152 | $errcode = 0;
153 | $errtext = "";
154 | $orig = isset($_SERVER["HTTP_ORIGIN"]) ? $_SERVER["HTTP_ORIGIN"] : "*";
155 | if (("*" != $cors_origin) && (0 !== strpos($orig,$cors_origin)))
156 | return build_error(403, "Access Forbidden");
157 |
158 | if (("" != $api_secret) && !isset($_SERVER["HTTP_X_AUTHENTICATION"]))
159 | return build_error(401, "API Authentication Required");
160 |
161 | if (("" != $api_secret) && ($_SERVER["HTTP_X_AUTHENTICATION"] != $api_secret))
162 | return build_error(403, "API Authentication Rejected");
163 |
164 | $ctype = isset($_SERVER["CONTENT_TYPE"]) ? strtolower($_SERVER["CONTENT_TYPE"]) : "";
165 | $ctype = preg_replace('/[[:space:]]*;.*$/',"",$ctype);
166 |
167 | if (!valid_ctype($ctype))
168 | return build_error(415, "Unsupported Media Type");
169 |
170 | /* URI parsing example for '/v1/equipment/12' | '/v1/np/series' (with predefined requests)
171 | * [0]=> string(20) "/v1/equipment/12" | [0]=> string(20) "/v1/np/series"
172 | * [1]=> string(2) "v1" | [1]=> string(2) "v1"
173 | * [2]=> string(9) "equipment" | [2]=> string(2) "np"
174 | * [3]=> string(3) "/12" | [3]=> string(3) "/series"
175 | * [4]=> string(2) "12" | [4]=> string(2) "series"
176 | *
177 | * Match indices are always the same, even if some of the subpatterns
178 | * are not present.
179 | *
180 | * ^\/([a-z][[:alnum:]_]*)\/([[:alnum:]_-]+)(\/([^\/]*))?(\/([^\/]*))?$
181 | * starts with literal '/'
182 | * 1 lowercase letter [a-z]
183 | * any number of numbers, letters or literal '_' [[:alnum:]_]
184 | * literal char '/'
185 | * at least one number, letter or literal '_' or '-' [:alnum:]_-]
186 | * 0-2 patterns consisting of a literal '/' followed by any number of
187 | * any characters except '/' (\/([^\/]*))?(\/([^\/]*))?
188 | * end of pattern $
189 | *
190 | * Example of parsing when uri is /v1 -- mmi/api/v1
191 | * array(2) {
192 | * [0]=>
193 | * string(3) "/v1"
194 | * [1]=>
195 | * string(2) "v1"
196 | * }
197 | * $
198 | */
199 |
200 | // see the type of URI that was used: if long uri (mmi/api/v1/equipment/12 or mmi/api/v1/no ) or short uri ( mmi/api/v1 - common for all requests )
201 | if (!preg_match('/^\/([a-z][[:alnum:]_]*)\/([[:alnum:]_-]+)(\/([^\/]*))?(\/([^\/]*))?$/', $_SERVER["PATH_INFO"], $match)) {
202 |
203 | if (!preg_match('/^\/([a-z][[:alnum:]_]*)(\/([^\/]*))?$/', $_SERVER["PATH_INFO"], $match)) {
204 | return build_error(400, "Invalid URI");
205 | }
206 | }
207 |
208 | if ($match[1] != "v1")
209 | return build_error(501, "Unsupported API version");
210 |
211 | Debug::xdebug("api", "The relevant part from the URI that was taken from 'PATH_INFO' (".$_SERVER["PATH_INFO"]."): \n".print_r($match,true));
212 |
213 | /*
214 | * Example: npdb
215 | * $predefined_requests = array(
216 | * "broadcast" => array(
217 | * "npdb" => array(
218 | * "cb_get_api_nodes" => "custom_get_npdb_nodes", // if missing a default get_api_nodes() will be called
219 | * "cb_format_params" => "custom_format_params", // if missing a default function format_api_request() will be called
220 | * "cb_run_request" => "custom_apply_request", // if missing a default function run_api_requests() will be called
221 | * )
222 | * )
223 | * );
224 | *
225 | */
226 | if (isset($predefined_requests)) {
227 | $uri = array(
228 | "method" => $_SERVER["REQUEST_METHOD"],
229 | "ctype" => $ctype,
230 | "object" => @$match[4],
231 | "id" => @$match[6],
232 | "params" => array()
233 | );
234 | parse_str($_SERVER["QUERY_STRING"], $uri["params"]);
235 |
236 | Debug::xdebug("api", "The built data from the URI that will be used with the predefined requests: \n".print_r($uri,true));
237 |
238 | $methods_allowed = array("GET","POST","PUT","DELETE");
239 | if (!in_array($_SERVER["REQUEST_METHOD"], $methods_allowed)) {
240 | Debug::xdebug("api", "The REQUEST_METHOD received is not allowed: ".$_SERVER["REQUEST_METHOD"]);
241 | return build_error(405, "Method Not Allowed");
242 | }
243 |
244 | foreach ($predefined_requests as $handling=>$types) {
245 |
246 | foreach ($types as $type=>$methods) {
247 |
248 | // in case type of api was not specified in the path, try to guess to type
249 | // WE SHOULD NOT have same request name in multiple types
250 | if (isset($match[2]) && $type!=@$match[2])
251 | continue;
252 |
253 | $cb = "get_api_nodes";
254 | if (isset($methods["cb_get_api_nodes"]))
255 | $cb = str_replace ("custom_","",$methods["cb_get_api_nodes"]);
256 |
257 | // get the ips of the nodes where the requests will be sent to
258 | $ips = call_user_func_array($cb, array($handling,$type));
259 |
260 | // build the format for the new requests to be send to API using a custom function or the default function
261 | if (isset($methods["cb_format_params"]))
262 | $params_request = call_user_func_array(str_replace("custom_","",$methods["cb_format_params"]), array($handling,$type,$uri));
263 | else
264 | $params_request = format_api_request($handling,$type,$uri);
265 |
266 | // if node_type was not specified in uri, make sure it was added in JSON, otherwise all requests will be prisoners
267 | $node = null;
268 | if (isset($match[2]))
269 | $node = $match[2];
270 | elseif (array_key_exists("node", $params_request))
271 | $node = $params_request["node"];
272 |
273 | if (!$node || $node!=$type)
274 | continue;
275 |
276 | $params_request["node"] = $node;
277 |
278 | Debug::xdebug("api", "The parameters of the request: \n".print_r($params_request,true));
279 |
280 | if (isset($params_request["code"]))
281 | return build_error($params_request["code"],$params_request["message"]);
282 |
283 | // return the response from API after running the custom function to process the API requests
284 | if (isset($methods["cb_run_request"]))
285 | return call_user_func_array(str_replace("custom_","",$methods["cb_run_request"]), array($handling,$type,$ips,$params_request));
286 |
287 | // if not all requests are forwarded for this node, verify that this request is set in accepted requests list
288 | if (!isset($methods["requests"]) || (!is_array($methods["requests"]) && $methods["requests"]!="*"))
289 | return build_error(500,"Internal server error");
290 |
291 | if (is_array($methods["requests"]) && !in_array($params_request["request"], $methods["requests"]) ) {
292 | Debug::xdebug("api", "Request ".$params_request["request"]." is not set in the predefined requests: \n".print_r($methods["requests"],true));
293 | return build_error(405, "Method not allowed");
294 | }
295 |
296 | // return the response from API after running the default function to process the API requests
297 | return run_api_requests($handling,$type,$ips,$params_request,$methods);
298 | }
299 | }
300 | }
301 |
302 | $uri = array(
303 | "object" => @$match[2],
304 | "id" => @$match[4],
305 | "params" => array()
306 | );
307 | parse_str($_SERVER["QUERY_STRING"], $uri["params"]);
308 |
309 | if ("POST" == $_SERVER["REQUEST_METHOD"] || "PUT" == $_SERVER["REQUEST_METHOD"])
310 | return do_post_put($ctype, $_SERVER["REQUEST_METHOD"], $uri);
311 |
312 | if ("GET" == $_SERVER["REQUEST_METHOD"])
313 | return do_get($ctype, $uri);
314 |
315 | if ("DELETE" == $_SERVER["REQUEST_METHOD"])
316 | return do_delete($ctype, $uri);
317 |
318 | return build_error(405, "Method Not Allowed");
319 | }
320 |
321 | function valid_ctype($ctype)
322 | {
323 | $valid_ctypes = array("application/json", "text/x-json", "application/x-www-form-urlencoded", "multipart/form-data","");
324 | return in_array($ctype, $valid_ctypes);
325 | }
326 |
327 | function do_post_put($ctype, $method, $uri)
328 | {
329 | Debug::func_start(__FUNCTION__,func_get_args(),"api");
330 | list($method, $input, $node_type) = decode_post_put($ctype, $method, $uri);
331 |
332 | if ($input === null)
333 | return array("code"=>415, "message"=>"Unparsable JSON content");
334 |
335 | if (@$uri["id"])
336 | $input[$uri["object"] . "_id"] = $uri["id"];
337 |
338 | return process_request($method, $input);
339 | }
340 |
341 | function do_get($ctype, $uri)
342 | {
343 | Debug::func_start(__FUNCTION__,func_get_args(),"api");
344 | $input = $_GET;
345 | if ($uri["id"])
346 | $input[$uri["object"] . "_id"] = $uri["id"];
347 | return process_request("get_" . $uri["object"], $input);
348 | }
349 |
350 | function do_delete($ctype, $uri)
351 | {
352 | Debug::func_start(__FUNCTION__,func_get_args(),"api");
353 | $input = array();
354 | if ($uri["id"])
355 | $input[$uri["object"] . "_id"] = $uri["id"];
356 | return process_request("delete_" . $uri["object"], $input);
357 | }
358 |
--------------------------------------------------------------------------------
/sdr_config/check_validity_fields_ybts.php:
--------------------------------------------------------------------------------
1 |
20 | array("128","251"),
29 | "900" => array("0","124","975","1023"),
30 | "1800" => array("512","885"),
31 | "1900" => array("512","810")
32 | );
33 |
34 | foreach ($permitted_values as $radio_band_val => $radio_c0_val) {
35 | if ($restricted_value == $radio_band_val) {
36 | $field_value = explode("-",$field_value);
37 | if (!isset($field_value[1]))
38 | $field_value = null;
39 | else
40 | $field_value = $field_value[1];
41 | $int_value = (int)$field_value;
42 | $min = $radio_c0_val[0];
43 | $max = $radio_c0_val[1];
44 |
45 | if (!isset($radio_c0_val[2])) {
46 |
47 | if ($int_value<$min || $int_value>$max)
48 | return array(false, "Field $field_name selected, is not in the right range for the Radio.Band chosen.");
49 | return array(true);
50 |
51 | } elseif (isset($radio_c0_val[2])) {
52 | $min2 = $radio_c0_val[2];
53 | $max2 = $radio_c0_val[3];
54 | if (($int_value>=$min && $int_value<=$max) || ($int_value>=$min2 && $int_value<=$max2))
55 | return array(true);
56 | return array(false, "Field $field_name selected, is not in the right range for the Radio.Band chosen.");
57 | }
58 |
59 | }
60 | }
61 |
62 | return array(false, "The given value for $field_name is not a permitted one.");
63 | }
64 |
65 | /**
66 | * Test if Radio.PowerManager.MinAttenDB is less or equal to Radio.PowerManager.MaxAttenDB.
67 | *
68 | * $field_value = getparam("Radio.PowerManager.MinAttenD");
69 | * $restricted_value = getparam("Radio.PowerManager.MaxAttenDB");
70 | */
71 | function check_radio_powermanager($field_name, $field_value, $restricted_value)
72 | {
73 | $valid = check_valid_number($field_name, $field_value);
74 | if (!$valid[0])
75 | return $valid;
76 |
77 | if ((int)$field_value > $restricted_value)
78 | return array(false, "Radio.PowerManager.MinAttenDB, must be less or equal to Radio.PowerManager.MaxAttenDB");
79 |
80 | return array(true);
81 | }
82 |
83 | function validate_gsm_time_sync_check($field_name, $field_value)
84 | {
85 | $valid = check_valid_number($field_name, $field_value);
86 | if (!$valid[0])
87 | return $valid;
88 |
89 | if ($field_value!=0 && $field_value<2000 && $field_value>10000)
90 | return array(false, "Field $field_name is not valid. The value must be 0 or in interval [2000,10000].");
91 |
92 | return array(true);
93 | }
94 |
95 | /**
96 | * VEA ([control]) field value depends on CellSelection.NECI ([gsm_advanced])
97 | * this fields are in different section
98 | * if one of the interest params was written in config file
99 | * validate the other in form
100 | * This has to be valid:
101 | * If VEA is selected, [gsm_advanced] CellSelection.NECI should be set to 1.
102 | */
103 | function validate_neci_vea($field_name, $field_value)
104 | {
105 | if ($field_name == "VEA" && ( $field_value == "off" || $field_value == "no" || $field_value == "0")) {
106 | $neci = getparam("CellSelection_NECI");
107 | if ($neci=="1")
108 | return array(true, "Field $field_name from Control Tab doesn't have a recommended value. It has to be checked because CellSelection.NECI param from Radio tab in GSM Advanced subsection was set to 1.");
109 | }
110 |
111 | if ($field_name == "CellSelection.NECI" && $field_value != "1") {
112 | $vea = getparam("VEA");
113 | if ($vea=='on')
114 | return array(true, "Field $field_name doesn't have a recommended value. It has to be selected the 'New establisment causes are supported' because VEA parameter from Control Tab was selected.");
115 | }
116 |
117 | return array(true);
118 | }
119 |
120 | /**
121 | * Timer.ImplicitDetach : should be at least 240 seconds greater than SGSN.Timer.RAUpdate.
122 | * Interval allowed 2000:4000(10).
123 | *
124 | * $field_value => is the value of Timer.ImplicitDetach from form
125 | * $restricted_value => is the value of Timer.RAUpdate from form
126 | */
127 | function check_timer_implicitdetach($field_name, $field_value, $restricted_value)
128 | {
129 | $valid = check_valid_number($field_name, $field_value);
130 | if (!$valid[0]) {
131 | return $valid;
132 | }
133 |
134 | //first test if $field_value is in the allowed interval
135 | if ($field_value<2000 || $field_value>4000 || $field_value%10!=0)
136 | return array(false, "Field $field_name is not valid. The value must be in interval [2000,4000] and should be a factor of 10.");
137 |
138 | if ($field_value-$restricted_value < 240)
139 | return array(true, "Field $field_name doesn't have a recommended value. It should be at least 240 seconds greater than Timer.RAUpdate.");
140 |
141 | return array(true);
142 | }
143 |
144 | /**
145 | * [gprs_advanced] param: Timer.RAUpdate
146 | * Setting to 0 or >12000 deactivates entirely, i.e., sets the timer to effective infinity.
147 | * Note: to prevent GPRS Routing Area Updates you must set both this and GSM.Timer.T3212 to 0.
148 | * Interval allowed 0:11160(2). Defaults to 3240.
149 | */
150 | function check_timer_raupdate($field_name, $field_value)
151 | {
152 | $valid = check_valid_number($field_name, $field_value);
153 | if (!$valid[0])
154 | return $valid;
155 |
156 | if (($field_value<0 || $field_value>11160 || $field_value%2!=0) && $field_value<12000)
157 | return array(false, "Field $field_name is not valid. The value must be in interval [0,11160] and should be a factor of 2 or greater than 12000.");
158 |
159 | $timerT3212 = getparam("Timer_T3212");
160 | if ($field_value!=0 && $timerT3212=="0") {
161 | return array(true, "To prevent GPRS Routing Area Updates it is recommended you set $field_name also to 0, setting field Timer.T3212 from Radio Tab set to 0 is not enough.");
162 | }
163 |
164 | return array(true);
165 | }
166 |
167 | /**
168 | * [gprs_advanced] param: Uplink.Persist
169 | * If non-zero, must be greater than GPRS.Uplink.KeepAlive.
170 | * This is broadcast in the beacon and it cannot be changed once BTS is started.
171 | * Allowed interval 0:6000(100).
172 | */
173 | function check_uplink_persistent($field_name, $field_value, $restricted_value)
174 | {
175 | $valid = check_valid_number($field_name, $field_value);
176 | if (!$valid[0])
177 | return $valid;
178 |
179 | $field_value = (int)$field_value;
180 | if ($field_value<0 || $field_value>6000 || $field_value%100!=0)
181 | return array(false, "Field $field_name is not valid. The value must be in interval [0,6000] and should be a factor of 100.");
182 |
183 | if ($field_value != 0 || $field_value != "0") {
184 | if ($field_value < (int)$restricted_value)
185 | return array(true, "Field $field_name doesn't have a recommended value. This value must be greater than Uplink.KeepAlive value.");
186 | }
187 |
188 | return array(true);
189 | }
190 |
191 | /**
192 | * [gprs_advanced] param: Downlink.Persist
193 | * If non-zero, must be greater than GPRS.Downlink.KeepAlive.
194 | */
195 | function check_downlink_persistent($field_name, $field_value, $restricted_value)
196 | {
197 | $valid = check_valid_number($field_name, $field_value);
198 | if (!$valid[0])
199 | return $valid;
200 |
201 | $field_value = (int) $field_value;
202 | $restricted_value = (int)$restricted_value;
203 |
204 | if ($field_value < 0 || $field_value > 10000)
205 | return array(false, "Field $field_name is not valid. It has to be smaller than 10000.");
206 | if ($field_value != 0) {
207 | if ($field_value < $restricted_value)
208 | return array(true, "Field $field_name doesn't have a recommended value. This value must be greater than Downlink.KeepAlive value.");
209 | }
210 |
211 | return array(true);
212 | }
213 |
214 | /**
215 | * Test for [gprs_advanced] param: ChannelCodingControl.RSS.
216 | * This value should normally be GSM.Radio.RSSITarget + 10 dB.
217 | * Interval allowed -65:-15.
218 | */
219 | function check_channelcodingcontrol_rssi($field_name, $field_value)
220 | {
221 | $valid = check_valid_number($field_name, $field_value);
222 | if (!$valid[0])
223 | return $valid;
224 |
225 | $field_value = (int) $field_value;
226 |
227 | if ($field_value<-65 || $field_value>-15)
228 | return array(false, "Field $field_name is not valid. The value must be in interval [-65,-15].");
229 |
230 | $radio_RSSITarget = (int)getparam("Radio_RSSITarget");
231 |
232 | if ($radio_RSSITarget+10 != $field_value)
233 | return array(true, "Field $field_name doesn't have a recommended value. This value should normally be Radio.RSSITarget + 10 dB, value added from tab Radio, from GSM Advanced that has the value: $radio_RSSITarget.");
234 |
235 | return array(true);
236 | }
237 |
238 | /**
239 | * validate field Radio.RSSITarget to be ChannelCodingControl.RSS-10 dB.
240 | */
241 | function check_radio_rssitarget($field_name, $field_value)
242 | {
243 | $valid = check_valid_number($field_name, $field_value);
244 | if (!$valid[0])
245 | return $valid;
246 |
247 | $field_value = (int) $field_value;
248 |
249 | if ($field_value<-75 || $field_value>-25)
250 | return array(false, "Field $field_name is not valid. The value must be in interval [-75,-25].");
251 |
252 | $chancontrol_rss = (int) getparam("ChannelCodingControl_RSSI");
253 | if ($chancontrol_rss -10 < $field_value)
254 | return array(true, "Field $field_name doesn't have a recommended value. This value should be the value of ChannelCodingControl.RSSI -10dB, parameter already added from submenu GPRS Advanced with the value: $chancontrol_rss.");
255 |
256 | return array(true);
257 | }
258 |
259 | /**
260 | * validate t3260
261 | */
262 | function check_t3260($field_name, $field_value)
263 | {
264 | $valid = check_valid_number($field_name, $field_value);
265 | if (!$valid[0])
266 | return $valid;
267 |
268 | $field_value = (int) $field_value;
269 |
270 | if ($field_value<5000 || $field_value>3600000)
271 | return array(false, "Field $field_name is not valid. Interval allowed: 5000..3600000.");
272 |
273 | return array(true);
274 | }
275 |
276 | /**
277 | * Validate reg_sip from [roaming] section in ybts.conf: ip:port or just ip
278 | */
279 | function valid_reg_sip($field_name, $field_value)
280 | {
281 | if (!strlen($field_value))
282 | return array(true);
283 |
284 | $expl = explode(":",$field_value);
285 | $ip = $expl[0];
286 | if (!filter_var($ip, FILTER_VALIDATE_IP))
287 | return array(false, "Field $field_name '$field_value' doesn't contain a valid IP address.");
288 |
289 | $port = (isset($expl[1])) ? $expl[1] : null;
290 | if ($port && !filter_var($port,FILTER_VALIDATE_INT))
291 | return array(false, "Field $field_name '$field_value' doesn't contain a valid port.");
292 |
293 | return array(true);
294 | }
295 |
296 | /**
297 | * Validate nodes_sip from [roaming] section in ybts.conf
298 | */
299 | function valid_nodes_sip($field_name, $field_value)
300 | {
301 | if (!strlen($field_value))
302 | return array(true);
303 |
304 | $field_value = htmlspecialchars_decode($field_value);
305 | $decoded = json_decode($field_value);
306 |
307 | if ($decoded===null)
308 | return array(false, "Field $field_name '$field_value' isn't a valid JSON object.");
309 |
310 | return array(true);
311 | }
312 |
313 | function check_rach_ac($field_name, $field_value)
314 | {
315 | if (!strlen($field_value))
316 | return array(true);
317 |
318 | if (substr($field_value,0,2)!="0x") {
319 | $res = check_field_validity($field_name, $field_value, 0, 65535);
320 | if (!$res[0])
321 | return $res;
322 | $emergency_disabled = $field_value & 0x0400;
323 | } else {
324 | $hex = substr($field_value,2);
325 | if (!ctype_xdigit($hex))
326 | return array(false, "Invalid hex value '$field_value' for $field_name.");
327 | if (strcasecmp($hex,"ffff")>0)
328 | return array(false, "Value '$field_value' for $field_name exceeds limit 0xffff.");
329 | $hex = base_convert($hex,16,10);
330 | $emergency_disabled = $hex & 0x0400;
331 | }
332 | if (!$emergency_disabled) {
333 | /*if (is_file($yate_conf_dir."/subscribers.conf")) {
334 | $conf = new ConfFile($yate_conf_dir."/subscribers.conf");
335 | if (!isset($conf->sections["general"]["gw_sos"]) || !strlen($conf->sections["general"]["gw_sos"]))
336 | return array(false, "You enabled emergency calls in RACH.CA. DON'T MODIFY THIS UNLESS YOU ARE A REAL OPERATOR. You might catch real emergency calls than won't ever be answered. If you really want to enable them, first set 'Gateway SOS' in Subscribers>Country code and SMSC.");
337 | }
338 |
339 | warning_note("You enabled emergency calls in RACH.CA. DON'T MODIFY THIS UNLESS YOU ARE A REAL OPERATOR. You might catch real emergency calls than won't ever be answered.");*/
340 | }
341 |
342 | return array(true);
343 | }
344 |
345 | /**
346 | * Validate sos_sip from [roaming] section
347 | * String: host:port where SIP emergency calls are sent.
348 | * If not set any emergency calls will be delivered to reg_sip or nodes_sip.
349 | * Ex: sos_sip=192.168.1.215:5059
350 | */
351 | function valid_sos_sip($field_name, $field_value)
352 | {
353 | if (!strlen($field_value))
354 | return array(true);
355 |
356 | $expl = explode(":",$field_value);
357 | $ip = $expl[0];
358 | if (!filter_var($ip, FILTER_VALIDATE_IP))
359 | return array(false, "Field $field_name '$field_value' doesn't contain a valid IP address.");
360 |
361 | $port = (isset($expl[1])) ? $expl[1] : null;
362 |
363 | if (!$port || !filter_var($port,FILTER_VALIDATE_INT))
364 | return array(false, "Field $field_name '$field_value' doesn't contain a valid port.");
365 |
366 | return array(true);
367 | }
368 |
369 | function validate_roaming_params()
370 | {
371 | $required = array("nnsf_bits", "gstn_location");
372 |
373 | foreach ($required as $field_name)
374 | if (!getparam($field_name))
375 | return array(false, "Field $field_name is required in roaming mode.", array($field_name));
376 |
377 | $reg_sip = getparam("reg_sip");
378 | $nodes_sip = getparam("nodes_sip");
379 | if (!$reg_sip && !$nodes_sip)
380 | return array(false, "You need to set 'Reg sip' or 'Nodes sip' in roaming mode.", array("reg_sip", "nodes_sip"));
381 |
382 | $nnsf_bits = getparam("nnsf_bits");
383 | $expires = getparam("expires");
384 | if (valid_param($expires) && !is_valid_number($expires))
385 | return array(false, "Field 'Expires' field should be numeric.", array("expires"));
386 | if (valid_param($nnsf_bits) && (!is_valid_number($nnsf_bits) || $nnsf_bits<0))
387 | return array(false, "Field 'NNSF bits' should be a positive int.", array("nnsf_bits"));
388 |
389 | return array(true);
390 | }
391 |
392 | function validate_piece_roaming()
393 | {
394 | // verify fields from roaming as well, if set
395 | $nnsf_bits = getparam("nnsf_bits");
396 | $expires = getparam("expires");
397 | if (valid_param($expires) && !is_valid_number($expires))
398 | return array(false, "Field 'Expires' field should be numeric.", array("expires"));
399 | if (valid_param($nnsf_bits) && (!is_valid_number($nnsf_bits) || $nnsf_bits<0))
400 | return array(false, "Field 'NNSF bits' should be a positive int.", array("nnsf_bits"));
401 |
402 | $reg_sip = getparam("reg_sip");
403 | $nodes_sip = getparam("nodes_sip");
404 | if (!$reg_sip && !$nodes_sip)
405 | return array(false, "You need to set 'Reg sip' or 'Nodes sip' in dataroam mode.", array("reg_sip", "nodes_sip"));
406 |
407 | return array(true);
408 | }
409 |
410 | function validate_dataroam_params()
411 | {
412 | $nnsf_bits = getparam("gprs_nnsf_bits");
413 | if (valid_param($nnsf_bits) && (!is_valid_number($nnsf_bits) || $nnsf_bits<0))
414 | return array(false, "NNSF bits must be a positive int, if set.", array("gprs_nnsf_bits"));
415 |
416 | $map = getparam("network_map");
417 | if (!strlen($map))
418 | return array(false, "You need to set at least one 'Explicitly map network nodes to IP addresses' in dataroam mode.", array("network_map"));
419 |
420 | $map = explode("\n", $map);
421 | foreach ($map as $map_entry) {
422 | $entry = explode("=",$map_entry);
423 | if (count($entry)!=2)
424 | return array(false, "Invalid format for 'Network map'.", array("network_map"));
425 | if (Numerify($entry[0])=="NULL")
426 | return array(false, "Invalid value '".$entry[0]."'. Should be numeric.", array("network_map"));
427 | if (filter_var(trim($entry[1]),FILTER_VALIDATE_IP)===false)
428 | return array(false, "Invalid value '".$entry[1]."'. Should be a valid IP address.", array("network_map"));
429 | }
430 |
431 | return array(true);
432 | }
433 |
434 | ?>
435 |
--------------------------------------------------------------------------------
/sdr_config/bts_tabbed_settings.php:
--------------------------------------------------------------------------------
1 |
20 | current_section = $this->default_section;
40 | $this->current_subsection = $this->default_subsection;
41 | $this->open_tabs = $open_tabs;
42 | $this->subsections_advanced = array("GSM advanced", "GPRS advanced", "Control");
43 | }
44 |
45 | function getMenuStructure()
46 | {
47 | Debug::func_start(__METHOD__, func_get_args(), "tabs_bts");
48 | //The key is the MENU alias the sections from $fields
49 | //and for each menu is an array that has the submenu data with subsections
50 |
51 | $structure = array(
52 | "Radio" => array("GSM","GPRS"/*TBI: ,"Bearers"*/, "GSM advanced", "GPRS advanced", "Control", "Calibration"),
53 | "Core" => array(),
54 |
55 | "Hardware" => array("Site info", "Site equipment", "Shutdown"),
56 | "System" => array("YBTS", "Security", "Transceiver"),
57 | "Test" => array("Test", "Tapping")
58 | );
59 |
60 | if (!isset($_SESSION["sdr_mode"])) {
61 | Debug::xdebug("tabs_bts", "Could not set 'Core' in structure menu, working mode not set.");
62 | return $structure;
63 | }
64 |
65 | $sdr_mode = $_SESSION["sdr_mode"];
66 |
67 | if ($sdr_mode == "dataroam") {
68 | $structure["Core"] = array("Roaming", "GPRS roaming", "Handover", "SGSN", "GGSN");
69 | }
70 | elseif ($sdr_mode == "roaming") {
71 | $structure["Core"] = array("Roaming", "Handover", "SGSN", "GGSN");
72 | }
73 | else
74 | $structure["Core"] = array("SGSN", "GGSN");
75 |
76 | return $structure;
77 | }
78 |
79 | function getSectionsDescription()
80 | {
81 | Debug::func_start(__METHOD__, func_get_args(), "tabs_bts");
82 |
83 | return array(
84 | "gsm" => "Section [gsm] controls basic GSM operation. \n
85 | You MUST set and review all parameters here before starting the BTS!",
86 | "gsm_advanced" => "Section [gsm_advanced] controls more advanced GSM features.\n
87 | You normally don't need to make changes in this section",
88 | "gprs" => "Section [gprs] controls basic GPRS operation.\n
89 | You should review all parameters in this section.",
90 | "gprs_advanced" => "Section [gprs_advanced] controls more advanced GPRS features.\n
91 | You normally don't need to make changes in this section.",
92 | "calibration" => "Parameters used in configuration of radio calibration module.",
93 | "ggsn" => "Section [ggsn] has internal GGSN function configuration.\n
94 | Used in 'GPRS with Local breakout setup'.\n
95 | Additionally, you need to have IP Forwarding enabled and to define NAT rule that forwards the data coming from your phones to local internet connection.",
96 | "sgsn" => "Section [sgsn] has internal SGSN function configuration.\n
97 | Used in 'GPRS with Local breakout setup'.",
98 | "control" => "Section [control] - configuration for various MBTS controls.\n
99 | You normally don't need to change anything in this section.",
100 | "transceiver" => "Section [transceiver] controls how the radio transceiver is started and operates.",
101 | "tapping" => "Section [tapping] - settings control if radio layer GSM and GPRS packets are tapped to Wireshark.",
102 | "test" => "Section [test] has special parameters used to simulate errors.",
103 | "ybts" => "Section [ybts] configures ybts related parameters.",
104 | "security" => "Section [security] configures security related parameters.",
105 | "roaming" => "Section [roaming] controls parameters used by roaming.js when connecting YateBTS to a core network.",
106 | "handover" => "Section [handover] controls handover parameters used by roaming.js.",
107 | "gprs_roaming" => "Section [gprs_roaming] controls parameters used by dataroam.js when connecting YateBTS to a core data network.",
108 |
109 | "site_info" => "Site specific information.",
110 | "site_equipment" => "This is an area for customer-specific parameters for other site equipment,
111 | like antennas, cables, and anything else too \"dumb\" to carry its own
112 | configuration and identifying information.\n
113 | No defaults are provided.",
114 | "shutdown" => "Parameters for safety shutdown of SatSite components.\n
115 | Raising these parameters above their default values may result in damage to the eNodeB hardware or reduced equipment life. \n
116 | This parameters are ignored in Labkit units."
117 | );
118 | }
119 |
120 | function getApiFields()
121 | {
122 | Debug::func_start(__METHOD__, func_get_args(), "tabs_bts");
123 |
124 | $response_fields = request_api(array(), "get_bts_node", "node");
125 | if (!isset($response_fields["ybts"])) {
126 | Debug::xdebug("tabs_bts", "Could not retrieve ybts fields in " . __METHOD__);
127 | return null;
128 | }
129 | $res = $response_fields["ybts"];
130 |
131 | if (isset($response_fields["sdr"])) {
132 | $hardware_settings = $response_fields["sdr"];
133 | if (isset($hardware_settings["basic"])) {
134 | $hardware_settings["site_info"] = $hardware_settings["basic"];
135 | unset($hardware_settings["basic"]);
136 | }
137 | foreach ($hardware_settings as $section=>$section_def)
138 | $res[$section] = $section_def;
139 | }
140 |
141 | if (isset($res["gsm"]["Radio.Band"]))
142 | $_SESSION["Radio.Band"] = $res["gsm"]["Radio.Band"];
143 |
144 | $this->storeCalibrationFields($response_fields, $res);
145 | return $res;
146 | }
147 |
148 | function getDefaultFields()
149 | {
150 | return get_default_fields_ybts();
151 | }
152 |
153 | function buildParticularParam($data = null, $param = null, $request_fields = array())
154 | {
155 | //there is a particular case for Radio.C0 that is build from value_radio.band."-".value_radio.c0,
156 | $new_data = $data;
157 | if ($param == "Radio.C0")
158 | $new_data = $request_fields['gsm']['Radio.Band']."-".$data;
159 |
160 | return $new_data;
161 | }
162 |
163 | // Returns the field names which don't need invalid value detection
164 | function skip_detectInvalidFields_dropdown() {
165 | return array("my_sip");
166 | }
167 |
168 | /**
169 | * Build form fields by applying response fields over default fields
170 | * @param $request_fields Array. Fields retrived using getApiFields
171 | * @param $exists_in_response Bool. Verify if field exists in $request_fields otherwise add special marker. Default false
172 | * @return Array
173 | */
174 | function applyRequestFields($request_fields=null,$exists_in_response = false)
175 | {
176 | global $openvpn_interface;
177 | Debug::func_start(__METHOD__, func_get_args(), "tabs_bts");
178 |
179 | $structure = $this->buildConfSections(); //get_fields_structure_from_menu();
180 | $fields = $this->getDefaultFields();
181 |
182 | if (!$request_fields)
183 | return $fields;
184 |
185 | foreach ($structure as $section=>$data) {
186 | foreach ($data as $key=>$subsection) {
187 | if ($exists_in_response) {
188 | if (!isset($request_fields[$subsection])) {
189 | $fields["not_in_response"] = true;
190 | break 2;
191 | }
192 |
193 | foreach ($fields[$section][$subsection] as $paramname=>$data_fields) {
194 | $allow_empty_params = array("Args", "DNS", "ShellScript", "MS.IP.Route", "Logfile.Name", "peer_arg");
195 | if (!in_array($paramname, $allow_empty_params) && !isset($request_fields[$subsection][$paramname])) {
196 | $fields["not_in_response"] = true;
197 | break 3;
198 | }
199 | }
200 | }
201 | }
202 | }
203 |
204 | // verify if we have openvpn ip and preset it.
205 | if (!isset($request_fields["roaming"]["my_sip"]) && isset($fields["core"]["roaming"]["my_sip"][0]) && $openvpn_interface) {
206 | foreach ($fields["core"]["roaming"]["my_sip"][0] as $key=>$my_sip_ip) {
207 | if ($key == "custom")
208 | continue;
209 | if (strpos($my_sip_ip["my_sip"],$openvpn_interface)!==FALSE && $fields["core"]["roaming"]["my_sip"][0][$key+1]["my_sip_id"] != "__disabled") {
210 | $fields["core"]["roaming"]["my_sip"][0]["selected"]=$fields["core"]["roaming"]["my_sip"][0][$key+1]["my_sip"];
211 | $fields["core"]["roaming"]["my_sip"]["display"] = "select_without_non_selected";
212 | break;
213 | }
214 | }
215 | }
216 |
217 | $custom_site_equipment = "";
218 | $network_map = "";
219 | foreach ($structure as $section=>$data) {
220 | foreach ($data as $key=>$subsection) {
221 | if (isset($request_fields[$subsection])) {
222 | foreach ($request_fields[$subsection] as $param=>$data) {
223 | if (!isset($fields[$section][$subsection]))
224 | continue;
225 | if ($subsection=="gprs_roaming" && Numerify($param)!="NULL") {
226 | if (strlen($network_map))
227 | $network_map .= "\r\n";
228 | $network_map .= "$param=$data";
229 | continue;
230 | }
231 | if ($subsection=="gprs_roaming" && $param=="nnsf_bits")
232 | $param = "gprs_nnsf_bits";
233 | if ($subsection=="sgsn" && $param=="Debug")
234 | $param = "sgsn_debug";
235 | if (!isset($fields[$section][$subsection][$param])) {
236 | if ($subsection!="site_equipment")
237 | continue;
238 | if (strlen($custom_site_equipment))
239 | $custom_site_equipment .= "\n";
240 | $custom_site_equipment .= "$param=$data";
241 | continue;
242 | }
243 |
244 | if (isset($fields[$section][$subsection][$param]["display"]) && ($fields[$section][$subsection][$param]["display"] == "select" || $fields[$section][$subsection][$param]["display"] == "select_without_non_selected")) {
245 | if ($data=="" && in_array("Factory calibrated", $fields[$section][$subsection][$param][0]))
246 | $data = "Factory calibrated";
247 | // if IP address configured for my_sip is not in IPs scaned with
248 | // get_net_addresses add it in dropdown with label "--not available--"
249 | if ($subsection == "roaming" && $param == "my_sip") {
250 | $add_my_sip = true;
251 | foreach ($fields[$section]["roaming"]["my_sip"][0] as $key => $ip) {
252 | if ($key == "custom" || ( isset($ip["my_sip_id"]) && $ip["my_sip_id"] == "__disabled" ))
253 | continue;
254 | if (isset($ip["my_sip_id"]) && $data === $ip["my_sip"])
255 | $add_my_sip = false;
256 | }
257 | if ($add_my_sip) {
258 | $fields[$section][$subsection]["my_sip"][0][] = array("my_sip_id" => "__disabled", "my_sip" => "--not available--");
259 | $fields[$section][$subsection]["my_sip"][0][] = array("my_sip_id" => $data, "my_sip" => $data);
260 | //move custom value to the end of dropdown
261 | $custom = $fields[$section][$subsection]["my_sip"][0]["custom"];
262 | unset($fields[$section][$subsection]["my_sip"][0]["custom"]);
263 | $fields[$section][$subsection]["my_sip"][0]["custom"] = $custom;
264 | }
265 | $fields["core"]["roaming"]["my_sip"]["display"] = "select_without_non_selected";
266 | }
267 | $fields[$section][$subsection][$param][0]["selected"] = $data;
268 |
269 | } elseif (isset($fields[$section][$subsection][$param]["display"]) && $fields[$section][$subsection][$param]["display"] == "checkbox") {
270 | $fields[$section][$subsection][$param]["value"] = ($data == "yes" || $data=="on" || $data=="1") ? "on" : "off";
271 | } elseif (isset($fields[$section][$subsection][$param]["display"]) && in_array($fields[$section][$subsection][$param]["display"], array("message","objtitle","fixed","custom_field"))) {
272 | continue;
273 | } else {
274 | $fields[$section][$subsection][$param]["value"] = $data;
275 | }
276 | }
277 | }
278 | }
279 | }
280 | if (strlen($network_map))
281 | $fields["core"]["gprs_roaming"]["network_map"]["value"] = $network_map;
282 | if (strlen($custom_site_equipment))
283 | $fields["hardware"]["site_equipment"]["custom_parameters"]["value"] = $custom_site_equipment;
284 |
285 | if (isset($fields['radio']['gsm']['Radio.Band'][0]["selected"]) && isset($fields['radio']['gsm']["Radio.C0"][0]["selected"])) {
286 | $particle = $fields['radio']['gsm']['Radio.Band'][0]["selected"];
287 | $fields['radio']['gsm']["Radio.C0"][0]["selected"] = "$particle-".$fields['radio']['gsm']["Radio.C0"][0]["selected"];
288 | }
289 | return $fields;
290 | }
291 |
292 | function validateFields($section, $subsection)
293 | {
294 | Debug::func_start(__METHOD__, func_get_args(), "tabs_bts");
295 |
296 | $parent_res = parent::validateFields($section, $subsection);
297 | if (!$parent_res[0])
298 | return $parent_res;
299 |
300 | $extra_validations = array(
301 | array("mode"=>"roaming", "subsection"=>"roaming", "cb"=>"validate_roaming_params"),
302 | array("mode"=>"dataroam","subsection"=>"gprs_roaming", "cb"=>"validate_dataroam_params"),
303 | array("mode"=>"dataroam","subsection"=>"roaming", "cb"=>"validate_piece_roaming")
304 | );
305 |
306 | foreach ($extra_validations as $validation) {
307 | if (getparam("mode")==$validation["mode"] && $subsection==$validation["subsection"]) {
308 | $res = $validation["cb"]();
309 | if (!$res[0])
310 | $this->error_field[] = array($res[1], $res[2][0]);
311 | elseif ($res[0] && isset($res[1]))
312 | $this->warning_field[] = array($res[1], $res[2][0]);
313 | }
314 | }
315 |
316 | if (count($this->error_field))
317 | return array(false, "fields"=>$parent_res["fields"], "request_fields"=>$parent_res["request_fields"]);
318 | return $parent_res;
319 | }
320 |
321 | // Send API request to save BTS configuration
322 | // Break error message in case of error and mark section/subsection tobe opened
323 | function storeFormResult(array $fields)
324 | {
325 | //if no errors encountered on validate data fields then send API request
326 | Debug::func_start(__METHOD__, func_get_args(), "tabs_bts");
327 |
328 | $c0 = $fields['gsm']['Radio.C0'];
329 | $c0 = explode("-",$c0);
330 | $c0 = $c0[1];
331 | $fields['gsm']['Radio.C0'] = $c0;
332 |
333 | if (isset($fields['gprs_roaming'])) {
334 |
335 | $fields['gprs_roaming']['nnsf_bits'] = $fields['gprs_roaming']['gprs_nnsf_bits'];
336 | unset($fields['gprs_roaming']['gprs_nnsf_bits']);
337 |
338 | $network_map = $fields['gprs_roaming']['network_map'];
339 | $network_map = explode("\r\n",$network_map);
340 | unset($fields['gprs_roaming']['network_map']);
341 | foreach ($network_map as $assoc) {
342 | $assoc = explode("=",$assoc);
343 | if (count($assoc)!=2)
344 | continue;
345 | $fields['gprs_roaming'][$assoc[0]] = trim($assoc[1]);
346 | }
347 | }
348 |
349 | $fields['sgsn']['Debug'] = $fields['sgsn']['sgsn_debug'];
350 | unset($fields['sgsn']['sgsn_debug']);
351 |
352 | if (strpos(getparam("my_sip"),"Custom")!==FALSE)
353 | $fields["roaming"]["my_sip"] = getparam("custom_my_sip");
354 |
355 | $satsite = array();
356 | $satsite_sections = array("site_info", "site_equipment", "shutdown");
357 | foreach ($satsite_sections as $satsite_section) {
358 | $section_name = ($satsite_section!="site_info") ? $satsite_section : "basic";
359 | $satsite[$section_name] = $fields[$satsite_section];
360 | unset($fields[$satsite_section]);
361 | }
362 |
363 | $fields = array("ybts"=>$fields);
364 | if (count($satsite))
365 | $fields["sdr"] = $satsite;
366 |
367 | if (isset($fields["sdr"]["site_equipment"]["custom_parameters"])) {
368 | if (strlen($fields["sdr"]["site_equipment"]["custom_parameters"])) {
369 | $custom = explode("\r\n",$fields["sdr"]["site_equipment"]["custom_parameters"]);
370 | foreach ($custom as $custom_param) {
371 | $custom_param = explode("=",$custom_param);
372 | if (count($custom_param)!=2)
373 | continue;
374 | $fields["sdr"]["site_equipment"][trim($custom_param[0])] = trim($custom_param[1]);
375 | }
376 |
377 | }
378 | unset($fields["sdr"]["site_equipment"]["custom_parameters"]);
379 | }
380 |
381 | $fields["calibrate"] = $this->setCalibrationFields($fields["ybts"]);
382 |
383 | $res = make_request($fields, "set_bts_node");
384 |
385 | if (!isset($res["code"]) || $res["code"]!=0) {
386 | // find subsection where error was detected so it can be opened
387 | $mess = substr($res["message"],-15);
388 | $pos_section = strrpos($mess,"'",-5);
389 | $subsection = substr($mess,$pos_section+1);
390 | $subsection = substr($subsection,0,strpos($subsection,"'"));
391 | $section = $this->findSection($subsection);
392 |
393 | if (!$section) {
394 | Debug::output('bts tabs', "Could not find section for subsection '$subsection'");
395 | $section = $this->default_section;
396 | $subsection = $this->default_subsection;
397 | }
398 |
399 | $this->current_subsection = $subsection;
400 | $this->current_section = $section;
401 | $_SESSION[$this->title]["subsection"] = $subsection;
402 | $_SESSION[$this->title]["section"] = $section;
403 |
404 | $code = "";
405 | if (isset($res["code"]))
406 | $code = "[API: ".$res["code"]."] ";
407 |
408 | return array(false, $code.$res["message"]);
409 | } else {
410 | unset($_SESSION[$this->title]["section"], $_SESSION[$this->title]["subsection"]);
411 | return array(true);
412 | }
413 | }
414 |
415 | function cleanSession()
416 | {
417 | unset($_SESSION['Radio.Band']);
418 | }
419 |
420 | }
421 |
422 | ?>
423 |
--------------------------------------------------------------------------------
/COPYING:
--------------------------------------------------------------------------------
1 | GNU GENERAL PUBLIC LICENSE
2 | Version 2, June 1991
3 |
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc.
5 | 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
6 | Everyone is permitted to copy and distribute verbatim copies
7 | of this license document, but changing it is not allowed.
8 |
9 | Preamble
10 |
11 | The licenses for most software are designed to take away your
12 | freedom to share and change it. By contrast, the GNU General Public
13 | License is intended to guarantee your freedom to share and change free
14 | software--to make sure the software is free for all its users. This
15 | General Public License applies to most of the Free Software
16 | Foundation's software and to any other program whose authors commit to
17 | using it. (Some other Free Software Foundation software is covered by
18 | the GNU Library General Public License instead.) You can apply it to
19 | your programs, too.
20 |
21 | When we speak of free software, we are referring to freedom, not
22 | price. Our General Public Licenses are designed to make sure that you
23 | have the freedom to distribute copies of free software (and charge for
24 | this service if you wish), that you receive source code or can get it
25 | if you want it, that you can change the software or use pieces of it
26 | in new free programs; and that you know you can do these things.
27 |
28 | To protect your rights, we need to make restrictions that forbid
29 | anyone to deny you these rights or to ask you to surrender the rights.
30 | These restrictions translate to certain responsibilities for you if you
31 | distribute copies of the software, or if you modify it.
32 |
33 | For example, if you distribute copies of such a program, whether
34 | gratis or for a fee, you must give the recipients all the rights that
35 | you have. You must make sure that they, too, receive or can get the
36 | source code. And you must show them these terms so they know their
37 | rights.
38 |
39 | We protect your rights with two steps: (1) copyright the software, and
40 | (2) offer you this license which gives you legal permission to copy,
41 | distribute and/or modify the software.
42 |
43 | Also, for each author's protection and ours, we want to make certain
44 | that everyone understands that there is no warranty for this free
45 | software. If the software is modified by someone else and passed on, we
46 | want its recipients to know that what they have is not the original, so
47 | that any problems introduced by others will not reflect on the original
48 | authors' reputations.
49 |
50 | Finally, any free program is threatened constantly by software
51 | patents. We wish to avoid the danger that redistributors of a free
52 | program will individually obtain patent licenses, in effect making the
53 | program proprietary. To prevent this, we have made it clear that any
54 | patent must be licensed for everyone's free use or not licensed at all.
55 |
56 | The precise terms and conditions for copying, distribution and
57 | modification follow.
58 |
59 | GNU GENERAL PUBLIC LICENSE
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
61 |
62 | 0. This License applies to any program or other work which contains
63 | a notice placed by the copyright holder saying it may be distributed
64 | under the terms of this General Public License. The "Program", below,
65 | refers to any such program or work, and a "work based on the Program"
66 | means either the Program or any derivative work under copyright law:
67 | that is to say, a work containing the Program or a portion of it,
68 | either verbatim or with modifications and/or translated into another
69 | language. (Hereinafter, translation is included without limitation in
70 | the term "modification".) Each licensee is addressed as "you".
71 |
72 | Activities other than copying, distribution and modification are not
73 | covered by this License; they are outside its scope. The act of
74 | running the Program is not restricted, and the output from the Program
75 | is covered only if its contents constitute a work based on the
76 | Program (independent of having been made by running the Program).
77 | Whether that is true depends on what the Program does.
78 |
79 | 1. You may copy and distribute verbatim copies of the Program's
80 | source code as you receive it, in any medium, provided that you
81 | conspicuously and appropriately publish on each copy an appropriate
82 | copyright notice and disclaimer of warranty; keep intact all the
83 | notices that refer to this License and to the absence of any warranty;
84 | and give any other recipients of the Program a copy of this License
85 | along with the Program.
86 |
87 | You may charge a fee for the physical act of transferring a copy, and
88 | you may at your option offer warranty protection in exchange for a fee.
89 |
90 | 2. You may modify your copy or copies of the Program or any portion
91 | of it, thus forming a work based on the Program, and copy and
92 | distribute such modifications or work under the terms of Section 1
93 | above, provided that you also meet all of these conditions:
94 |
95 | a) You must cause the modified files to carry prominent notices
96 | stating that you changed the files and the date of any change.
97 |
98 | b) You must cause any work that you distribute or publish, that in
99 | whole or in part contains or is derived from the Program or any
100 | part thereof, to be licensed as a whole at no charge to all third
101 | parties under the terms of this License.
102 |
103 | c) If the modified program normally reads commands interactively
104 | when run, you must cause it, when started running for such
105 | interactive use in the most ordinary way, to print or display an
106 | announcement including an appropriate copyright notice and a
107 | notice that there is no warranty (or else, saying that you provide
108 | a warranty) and that users may redistribute the program under
109 | these conditions, and telling the user how to view a copy of this
110 | License. (Exception: if the Program itself is interactive but
111 | does not normally print such an announcement, your work based on
112 | the Program is not required to print an announcement.)
113 |
114 | These requirements apply to the modified work as a whole. If
115 | identifiable sections of that work are not derived from the Program,
116 | and can be reasonably considered independent and separate works in
117 | themselves, then this License, and its terms, do not apply to those
118 | sections when you distribute them as separate works. But when you
119 | distribute the same sections as part of a whole which is a work based
120 | on the Program, the distribution of the whole must be on the terms of
121 | this License, whose permissions for other licensees extend to the
122 | entire whole, and thus to each and every part regardless of who wrote it.
123 |
124 | Thus, it is not the intent of this section to claim rights or contest
125 | your rights to work written entirely by you; rather, the intent is to
126 | exercise the right to control the distribution of derivative or
127 | collective works based on the Program.
128 |
129 | In addition, mere aggregation of another work not based on the Program
130 | with the Program (or with a work based on the Program) on a volume of
131 | a storage or distribution medium does not bring the other work under
132 | the scope of this License.
133 |
134 | 3. You may copy and distribute the Program (or a work based on it,
135 | under Section 2) in object code or executable form under the terms of
136 | Sections 1 and 2 above provided that you also do one of the following:
137 |
138 | a) Accompany it with the complete corresponding machine-readable
139 | source code, which must be distributed under the terms of Sections
140 | 1 and 2 above on a medium customarily used for software interchange; or,
141 |
142 | b) Accompany it with a written offer, valid for at least three
143 | years, to give any third party, for a charge no more than your
144 | cost of physically performing source distribution, a complete
145 | machine-readable copy of the corresponding source code, to be
146 | distributed under the terms of Sections 1 and 2 above on a medium
147 | customarily used for software interchange; or,
148 |
149 | c) Accompany it with the information you received as to the offer
150 | to distribute corresponding source code. (This alternative is
151 | allowed only for noncommercial distribution and only if you
152 | received the program in object code or executable form with such
153 | an offer, in accord with Subsection b above.)
154 |
155 | The source code for a work means the preferred form of the work for
156 | making modifications to it. For an executable work, complete source
157 | code means all the source code for all modules it contains, plus any
158 | associated interface definition files, plus the scripts used to
159 | control compilation and installation of the executable. However, as a
160 | special exception, the source code distributed need not include
161 | anything that is normally distributed (in either source or binary
162 | form) with the major components (compiler, kernel, and so on) of the
163 | operating system on which the executable runs, unless that component
164 | itself accompanies the executable.
165 |
166 | If distribution of executable or object code is made by offering
167 | access to copy from a designated place, then offering equivalent
168 | access to copy the source code from the same place counts as
169 | distribution of the source code, even though third parties are not
170 | compelled to copy the source along with the object code.
171 |
172 | 4. You may not copy, modify, sublicense, or distribute the Program
173 | except as expressly provided under this License. Any attempt
174 | otherwise to copy, modify, sublicense or distribute the Program is
175 | void, and will automatically terminate your rights under this License.
176 | However, parties who have received copies, or rights, from you under
177 | this License will not have their licenses terminated so long as such
178 | parties remain in full compliance.
179 |
180 | 5. You are not required to accept this License, since you have not
181 | signed it. However, nothing else grants you permission to modify or
182 | distribute the Program or its derivative works. These actions are
183 | prohibited by law if you do not accept this License. Therefore, by
184 | modifying or distributing the Program (or any work based on the
185 | Program), you indicate your acceptance of this License to do so, and
186 | all its terms and conditions for copying, distributing or modifying
187 | the Program or works based on it.
188 |
189 | 6. Each time you redistribute the Program (or any work based on the
190 | Program), the recipient automatically receives a license from the
191 | original licensor to copy, distribute or modify the Program subject to
192 | these terms and conditions. You may not impose any further
193 | restrictions on the recipients' exercise of the rights granted herein.
194 | You are not responsible for enforcing compliance by third parties to
195 | this License.
196 |
197 | 7. If, as a consequence of a court judgment or allegation of patent
198 | infringement or for any other reason (not limited to patent issues),
199 | conditions are imposed on you (whether by court order, agreement or
200 | otherwise) that contradict the conditions of this License, they do not
201 | excuse you from the conditions of this License. If you cannot
202 | distribute so as to satisfy simultaneously your obligations under this
203 | License and any other pertinent obligations, then as a consequence you
204 | may not distribute the Program at all. For example, if a patent
205 | license would not permit royalty-free redistribution of the Program by
206 | all those who receive copies directly or indirectly through you, then
207 | the only way you could satisfy both it and this License would be to
208 | refrain entirely from distribution of the Program.
209 |
210 | If any portion of this section is held invalid or unenforceable under
211 | any particular circumstance, the balance of the section is intended to
212 | apply and the section as a whole is intended to apply in other
213 | circumstances.
214 |
215 | It is not the purpose of this section to induce you to infringe any
216 | patents or other property right claims or to contest validity of any
217 | such claims; this section has the sole purpose of protecting the
218 | integrity of the free software distribution system, which is
219 | implemented by public license practices. Many people have made
220 | generous contributions to the wide range of software distributed
221 | through that system in reliance on consistent application of that
222 | system; it is up to the author/donor to decide if he or she is willing
223 | to distribute software through any other system and a licensee cannot
224 | impose that choice.
225 |
226 | This section is intended to make thoroughly clear what is believed to
227 | be a consequence of the rest of this License.
228 |
229 | 8. If the distribution and/or use of the Program is restricted in
230 | certain countries either by patents or by copyrighted interfaces, the
231 | original copyright holder who places the Program under this License
232 | may add an explicit geographical distribution limitation excluding
233 | those countries, so that distribution is permitted only in or among
234 | countries not thus excluded. In such case, this License incorporates
235 | the limitation as if written in the body of this License.
236 |
237 | 9. The Free Software Foundation may publish revised and/or new versions
238 | of the General Public License from time to time. Such new versions will
239 | be similar in spirit to the present version, but may differ in detail to
240 | address new problems or concerns.
241 |
242 | Each version is given a distinguishing version number. If the Program
243 | specifies a version number of this License which applies to it and "any
244 | later version", you have the option of following the terms and conditions
245 | either of that version or of any later version published by the Free
246 | Software Foundation. If the Program does not specify a version number of
247 | this License, you may choose any version ever published by the Free Software
248 | Foundation.
249 |
250 | 10. If you wish to incorporate parts of the Program into other free
251 | programs whose distribution conditions are different, write to the author
252 | to ask for permission. For software which is copyrighted by the Free
253 | Software Foundation, write to the Free Software Foundation; we sometimes
254 | make exceptions for this. Our decision will be guided by the two goals
255 | of preserving the free status of all derivatives of our free software and
256 | of promoting the sharing and reuse of software generally.
257 |
258 | NO WARRANTY
259 |
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
268 | REPAIR OR CORRECTION.
269 |
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
278 | POSSIBILITY OF SUCH DAMAGES.
279 |
280 | END OF TERMS AND CONDITIONS
281 |
282 | How to Apply These Terms to Your New Programs
283 |
284 | If you develop a new program, and you want it to be of the greatest
285 | possible use to the public, the best way to achieve this is to make it
286 | free software which everyone can redistribute and change under these terms.
287 |
288 | To do so, attach the following notices to the program. It is safest
289 | to attach them to the start of each source file to most effectively
290 | convey the exclusion of warranty; and each file should have at least
291 | the "copyright" line and a pointer to where the full notice is found.
292 |
293 |
294 | Copyright (C) 19yy
295 |
296 | This program is free software; you can redistribute it and/or modify
297 | it under the terms of the GNU General Public License as published by
298 | the Free Software Foundation; either version 2 of the License, or
299 | (at your option) any later version.
300 |
301 | This program is distributed in the hope that it will be useful,
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
304 | GNU General Public License for more details.
305 |
306 | You should have received a copy of the GNU General Public License
307 | along with this program; if not, write to the Free Software
308 | Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
309 |
310 | Also add information on how to contact you by electronic and paper mail.
311 |
312 | If the program is interactive, make it output a short notice like this
313 | when it starts in an interactive mode:
314 |
315 | Gnomovision version 69, Copyright (C) 19yy name of author
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
317 | This is free software, and you are welcome to redistribute it
318 | under certain conditions; type `show c' for details.
319 |
320 | The hypothetical commands `show w' and `show c' should show the appropriate
321 | parts of the General Public License. Of course, the commands you use may
322 | be called something other than `show w' and `show c'; they could even be
323 | mouse-clicks or menu items--whatever suits your program.
324 |
325 | You should also get your employer (if you work as a programmer) or your
326 | school, if any, to sign a "copyright disclaimer" for the program, if
327 | necessary. Here is a sample; alter the names:
328 |
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker.
331 |
332 | , 1 April 1989
333 | Ty Coon, President of Vice
334 |
335 | This General Public License does not permit incorporating your program into
336 | proprietary programs. If your program is a subroutine library, you may
337 | consider it more useful to permit linking proprietary applications with the
338 | library. If this is what you want to do, use the GNU Library General
339 | Public License instead of this License.
340 |
--------------------------------------------------------------------------------
/lib_files.php:
--------------------------------------------------------------------------------
1 |
18 | filename = $file_name;
32 | }
33 |
34 | function openForRead()
35 | {
36 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
37 | if (isset($this->read_handler))
38 | return;
39 |
40 | if(!is_file($this->filename)) {
41 | $this->setError("File doesn't exist.");
42 | } else {
43 | $this->read_handler = fopen($this->filename,"r");
44 | if (!$this->read_handler)
45 | $this->setError("Could not open file for reading.");
46 | }
47 | }
48 |
49 | function openForWrite()
50 | {
51 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
52 | if (isset($this->write_handler))
53 | return;
54 |
55 | $this->write_handler = fopen($this->filename,"w");
56 | if (!$this->write_handler)
57 | $this->setError("Could not open file for writting.");
58 | }
59 |
60 | function getHandler($type="r")
61 | {
62 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
63 | if ($type == "r")
64 | $this->openForRead();
65 | elseif ($type == "w")
66 | $this->openForWrite();
67 |
68 | if (!$this->status())
69 | return;
70 |
71 | return ($type=="r") ? $this->read_handler : $this->write_handler;
72 | }
73 |
74 | function close()
75 | {
76 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
77 | if (isset($this->read_handler)) {
78 | fclose($this->read_handler);
79 | unset($this->read_handler);
80 | }
81 | if (isset($this->write_handler)) {
82 | fclose($this->write_handler);
83 | unset($this->write_handler);
84 | }
85 | }
86 |
87 | function createBackup()
88 | {
89 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
90 | $backup = $this->filename.".tmp";
91 |
92 | if (!file_exists($this->filename))
93 | return;
94 |
95 | if (!copy($this->filename, $backup))
96 | $this->setError("Failed to create backup of existing file: ".$this->filename);
97 | }
98 |
99 | function restoreBackup()
100 | {
101 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
102 | $backup_file = $this->filename.".tmp";
103 |
104 | if (!file_exists($backup_file))
105 | return;
106 |
107 | if (!copy($backup_file, $this->filename))
108 | return $this->setError("Failed to restore backup for file: ".$this->filename);
109 |
110 | $this->removeBackup();
111 | }
112 |
113 | function removeBackup()
114 | {
115 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
116 | $bk_file = $this->filename.".tmp";
117 |
118 | if (file_exists($bk_file))
119 | if (!unlink($bk_file))
120 | $this->setError("Failed to remove backup file ".$bk_file);
121 | }
122 |
123 | function safeSave($content=NULL)
124 | {
125 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
126 | $this->createBackup();
127 | if (!$this->status())
128 | return;
129 |
130 | if (!method_exists($this,"save"))
131 | return $this->setError("Please implement 'save' method for class ".get_class($this));
132 |
133 | $this->save($content);
134 | if (!$this->status()) {
135 | $this->restoreBackup();
136 | return;
137 | }
138 |
139 | $this->removeBackup();
140 | }
141 | }
142 |
143 | class CsvFile extends GenericFile
144 | {
145 | public $file_content = array();
146 | private $formats = array();
147 | private $sep;
148 | private $change_header;
149 |
150 | function __construct($file_name, $formats, $file_content=array(), $test_header=true, $read=true, $sep=",", $change_header=true)
151 | {
152 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
153 | parent::__construct($file_name);
154 | $this->formats = (is_array($formats)) ? $formats : array();
155 | $this->sep = $sep;
156 | $this->file_content = $file_content;
157 | $this->test_header = $test_header;
158 | $this->change_header = $change_header;
159 |
160 | if ($read)
161 | $this->read();
162 | }
163 |
164 | function read()
165 | {
166 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
167 | $this->openForRead();
168 | if (!$this->status())
169 | return;
170 |
171 | $content = fread($this->read_handler,filesize($this->filename));
172 | $content = preg_replace(array('/"="/',"/'='/",'/"/',"/'/"),"",$content);
173 | $content = explode("\n",$content);
174 |
175 | $bad_format = false;
176 | $first_row = explode(',',trim($content[0]));
177 | foreach ($first_row as $key => $data)
178 | $first_row[$key] = str_replace(" ","_", strtolower($first_row[$key]));
179 | for ($i=0;$iformats);$i++) {
180 | $form = str_replace(" ", "_", strtolower($this->formats[$i]));
181 | if (!in_array($form, $first_row)) {
182 | $bad_format = true;
183 | break;
184 | }
185 | }
186 |
187 | if ($this->test_header && count($this->formats) && $bad_format)
188 | return $this->setError("The format of the file is incorrect.");
189 |
190 | for ($i=0; $iformats))
194 | continue;
195 |
196 | if (!$this->test_header) {
197 | for ($j=0; $jformats) && isset($this->formats[$j]))
199 | $this->file_content[$i][$this->formats[$j]] = $row[$j];
200 | elseif (!count($this->formats))
201 | $this->file_content[$i][$j] = $row[$j];
202 | }
203 | } else {
204 | if (count($this->formats) && $i == 0)
205 | continue;
206 |
207 | if (count($this->formats)) {
208 | for ($n = 0 ; $nformats); $n++) {
209 | $pos = array_search(str_replace(" ", "_", strtolower($this->formats[$n])), $first_row);
210 | if ($pos !== false)
211 | $this->file_content[$i-1][$this->formats[$n]] = $row[$pos];
212 | }
213 | }
214 | }
215 |
216 | if ($i%10 == 0 && $this->exceeded_script_memory())
217 | return $this->setError("Your about to reach your php memory_limit allowed for this script. The csv file reading is stopped. Use smaller csv files.");
218 |
219 | }
220 | $this->close();
221 | }
222 |
223 | //The same functionality as write_in_file function from ansql/lib.php
224 | function write($key_val_arr=true, $col_header=true)
225 | {
226 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
227 |
228 | $this->openForWrite();
229 | if (!$this->status())
230 | return;
231 |
232 | $col_nr = 0;
233 |
234 | if (!$this->formats && count($this->file_content))
235 | foreach($this->file_content[0] as $name=>$val)
236 | $this->formats[$name] = $name;
237 |
238 | if ($col_header && $this->formats!="no") {
239 | foreach($this->formats as $column_name => $var_name) {
240 | $exploded = explode(":",$column_name);
241 | if (count($exploded)>1)
242 | $name = $exploded[1];
243 | else {
244 | $name = $column_name;
245 | if(substr($column_name, 0, 9) == "function_")
246 | $name = substr($column_name,9);
247 | if(is_numeric($column_name))
248 | $name = $var_name;
249 | }
250 | if ($this->change_header) {
251 | $val = str_replace("_"," ",ucfirst($name));
252 | $val = str_replace(" "," ",$val);
253 | } else {
254 | $val = $name;
255 | }
256 | $val = ($col_nr) ? $this->sep."\"$val\"" : "\"$val\"";
257 | fwrite($this->write_handler, $val);
258 | if ($col_nr%10 == 0 && $this->exceeded_script_memory())
259 | return $this->setError("Your about to reach your php memory_limit allowed for scripts. The writing of the file will be stopped.");
260 | $col_nr++;
261 | }
262 | fwrite($this->write_handler,"\n");
263 | }
264 | for ($i=0; $ifile_content); $i++) {
265 | $col_nr = 0;
266 | if ($key_val_arr) {
267 | foreach($this->formats as $column_name=>$names_in_array) {
268 | $use_vars = explode(",", $names_in_array);
269 | $exploded_col = explode(":", $column_name);
270 | $column_value = '';
271 |
272 | if (substr($exploded_col[0],0,9) == "function_") {
273 | $function_name = substr($exploded_col[0],9,strlen($exploded_col[0]));
274 | if (count($use_vars)) {
275 | $params = array();
276 | for($var_nr=0; $var_nrfile_content[$i][$use_vars[$var_nr]]);
278 | $column_value = call_user_func_array($function_name,$params);
279 | }
280 | } elseif(isset($this->file_content[$i][$names_in_array])) {
281 | $column_value = $this->file_content[$i][$names_in_array];
282 | }
283 | if (!strlen($column_value))
284 | $column_value = "";
285 | $column_value = "\"=\"\"".$column_value."\"\"\"";
286 | if ($col_nr)
287 | $column_value = $this->sep.$column_value;
288 | fwrite($this->write_handler,$column_value);
289 | if ($col_nr%10 == 0 && $this->exceeded_script_memory())
290 | return $this->setError("Your about to reach your php memory_limit allowed for scripts. The writing of the file will be stopped.");
291 |
292 | $col_nr++;
293 | }
294 | } else {
295 | for ($j=0; $jfile_content[$i]);$j++) {
296 | $column_value = "\"".$this->file_content[$i][$j]."\"";
297 | if ($col_nr)
298 | $column_value = $sep.$column_value;
299 | fwrite($this->write_handler,$column_value);
300 |
301 | if ($col_nr%10 == 0 && $this->exceeded_script_memory())
302 | return $this->setError("Your about to reach your php memory_limit allowed for scripts. The writing of the file will be stopped.");
303 |
304 | $col_nr++;
305 | }
306 | }
307 | fwrite($this->write_handler,"\n");
308 | }
309 | $this->close();
310 | }
311 |
312 | function exceeded_script_memory()
313 | {
314 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
315 | $script_memory_limit = $this->return_bytes(ini_get("memory_limit"));
316 | if ($script_memory_limit - memory_get_usage() < 3000)
317 | return true;
318 | return false;
319 | }
320 |
321 | function return_bytes($size_str)
322 | {
323 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
324 | switch (substr($size_str, -1)){
325 | case 'M':
326 | case 'm':
327 | return (int)$size_str * 1048576;
328 | case 'K':
329 | case 'k':
330 | return (int)$size_str * 1024;
331 | case 'G':
332 | case 'g':
333 | return (int)$size_str * 1073741824;
334 | default:
335 | return $size_str;
336 | }
337 | }
338 | }
339 |
340 | class ConfFile extends GenericFile
341 | {
342 | public $sections = array();
343 | public $structure = array();
344 | public $chr_comment = array(";","#");
345 | public $initial_comment = null;
346 | public $write_comments = false;
347 | public $lines = "\n";
348 |
349 | function __construct($file_name,$read=true,$write_comments=true,$lines="\n")
350 | {
351 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
352 | parent::__construct($file_name);
353 | $this->write_comments = $write_comments;
354 | $this->lines = $lines;
355 |
356 | if ($read)
357 | $this->read();
358 | }
359 |
360 | function read($close=true)
361 | {
362 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
363 | $this->openForRead();
364 | if (!$this->status())
365 | return;
366 |
367 | $last_section = "";
368 | while(!feof($this->read_handler))
369 | {
370 | $row = fgets($this->read_handler);
371 | $row = trim($row);
372 | if (!strlen($row))
373 | continue;
374 | if ($row == "")
375 | continue;
376 | // new section started
377 | // the second paranthesis is kind of weird but i got both cases
378 | if (substr($row,0,1)=="[" && substr($row,-1,1)) {
379 | $last_section = substr($row,1,strlen($row)-2);
380 | $this->sections[$last_section] = array();
381 | $this->structure[$last_section] = array();
382 | continue;
383 | }
384 | if (in_array(substr($row,0,1),$this->chr_comment)) {
385 | if ($last_section == "")
386 | array_push($this->structure, $row);
387 | else
388 | array_push($this->structure[$last_section], $row);
389 | continue;
390 | }
391 | // this is not a section (it's part of a section or file does not have sections)
392 | $params = explode("=", $row, 2);
393 | if (count($params)>2 || count($params)<2)
394 | // skip row (wrong format)
395 | continue;
396 | if (is_numeric($params[0]))
397 | // if key is numeric add __ so we don't get this mixed up with comments
398 | $params[0] = "__".$params[0];
399 | if ($last_section == ""){
400 | $this->sections[$params[0]] = trim($params[1]);
401 | $this->structure[$params[0]] = trim($params[1]);
402 | } else {
403 | $this->sections[$last_section][$params[0]] = trim($params[1]);
404 | $this->structure[$last_section][$params[0]] = trim($params[1]);
405 | }
406 | }
407 | if ($close)
408 | $this->close();
409 | }
410 |
411 | public function save()
412 | {
413 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
414 | $this->openForWrite();
415 | if (!$this->status())
416 | return;
417 |
418 | $wrote_something = false;
419 | if ($this->initial_comment)
420 | fwrite($this->write_handler, $this->initial_comment."\n");
421 |
422 | foreach($this->structure as $name=>$value)
423 | {
424 | // make sure we don't write the initial comment over and over
425 | if ($this->initial_comment && !$wrote_something && !is_array($value) && in_array(substr($value,0,1),$this->chr_comment) && $this->write_comments)
426 | continue;
427 | if (!is_array($value)) {
428 | if(in_array(substr($value,0,1),$this->chr_comment) && is_numeric($name)) {
429 |
430 | //writing a comment
431 | if ($this->write_comments)
432 | fwrite($this->write_handler, $value."\n");
433 | continue;
434 | }
435 | $wrote_something = true;
436 | fwrite($this->write_handler, "$name=".ltrim($value).$this->lines);
437 | continue;
438 | }else
439 | fwrite($this->write_handler, "[".$name."]\n");
440 | $section = $value;
441 | foreach($section as $param=>$value)
442 | {
443 | // if key was numeric __ was added when reading
444 | if (substr($param,0,2)=="__")
445 | $param = substr($param,2);
446 |
447 | if (is_array($value)) {
448 | foreach($value as $key => $val)
449 | fwrite($this->write_handler, $param."=".ltrim($val).$this->lines);
450 | } else {
451 | //writing a comment
452 | if (in_array(substr($value,0,1),$this->chr_comment) && is_numeric($param)) {
453 | if ($this->write_comments)
454 | fwrite($this->write_handler, $value."\n");
455 | continue;
456 | }
457 |
458 | $wrote_something = true;
459 | fwrite($this->write_handler, "$param=".ltrim($value).$this->lines);
460 | }
461 | }
462 | fwrite($this->write_handler, "\n");
463 | }
464 |
465 | $this->close();
466 | }
467 |
468 | function getSection($section)
469 | {
470 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
471 | if (!strlen($section)) {
472 | $this->setError("Please specify section name.");
473 | return;
474 | }
475 | if (!isset($this->structure[$section])) {
476 | $this->setError("Section '$section' was not found.");
477 | return;
478 | }
479 | return $this->structure[$section];
480 | }
481 | }
482 |
483 |
484 | class JsObjFile extends GenericFile
485 | {
486 | protected $block;
487 | protected $prefix = "";
488 | protected $suffix = "";
489 |
490 | public function __construct($filename, $prefix="", $suffix="", $block=array())
491 | {
492 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
493 | parent::__construct($filename, false);
494 |
495 | $this->block = (is_array($block)) ? $block : array();
496 | $this->prefix = $prefix;
497 | $this->suffix = $suffix;
498 | }
499 |
500 | public function read($close=true)
501 | {
502 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
503 | $this->openForRead();
504 | if (!$this->status())
505 | return;
506 |
507 | $content = "";
508 | while (!feof($this->read_handler)) {
509 | $row = fgets($this->read_handler);
510 | //$row = trim($row);
511 | //if (!strlen($row))
512 | // continue;
513 | //if ($row=="" || $row==$this->prefix || $row==$this->suffix)
514 | // continue;
515 |
516 | $content .= $row;
517 | }
518 |
519 | if (substr($content,0,strlen($this->prefix))==$this->prefix)
520 | $content = substr($content,strlen($this->prefix));
521 |
522 | $len = strlen($this->suffix)+1;
523 | //if (substr($content,-$len)==$this->suffix)
524 | $content = substr($content,0,strlen($content)-strlen($this->suffix)-1);
525 |
526 | $content = "{".$content."}";
527 |
528 |
529 | $this->block = json_decode($content,true);
530 | if (!$this->block)
531 | $this->setError("Could not decode file: ".$this->filename);
532 |
533 | if ($close)
534 | $this->close();
535 | }
536 |
537 | public function save()
538 | {
539 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
540 | $this->openForWrite();
541 | if (!$this->status())
542 | return;
543 |
544 | if (strlen($this->prefix))
545 | fwrite($this->write_handler, $this->prefix."\n");
546 |
547 | $arr_index = 0;
548 | $count = count($this->block);
549 | foreach ($this->block as $index=>$obj) {
550 | ++$arr_index;
551 | fwrite($this->write_handler, json_encode($index).":".json_encode($obj));
552 | if ($count>$arr_index)
553 | fwrite($this->write_handler,",\n");
554 | else
555 | fwrite($this->write_handler,"\n");
556 | }
557 | //fwrite($this->write_handler, json_encode($this->block));
558 | if (strlen($this->suffix))
559 | fwrite($this->write_handler, $this->suffix."\n");
560 |
561 | $this->close();
562 | }
563 |
564 | public static function runUnitTests()
565 | {
566 | $test_path = "";
567 |
568 | $files = array(
569 | "Default test" => "test_js1.js"); //, "Defaul2" => "test_js2.js");
570 |
571 | $objects = array(
572 | "Default test" => array(
573 | "block" => array(
574 | "0010155667788" => array("ki"=>"8383838202fklndsiri", "op"=>NULL, "active"=>1),
575 | "0010155667789" => array("ki"=>"8383838202fklndaaai", "op"=>NULL, "active"=>1),
576 | "0010155667790" => array("ki"=>"8383838202fklbbbbbbbi", "op"=>NULL, "active"=>0)
577 | ),
578 | "prefix" => "var subscribers = {",
579 | "suffix" => "};"
580 | )
581 | );
582 |
583 | // write
584 | foreach ($objects as $test_name=>$obj_arr) {
585 |
586 | $test_file = $test_path.$files[$test_name];
587 | $output_file = $test_path."write/".str_replace("test_","",$files[$test_name]);
588 |
589 | Debug::Output("Running writing test '$test_name'");
590 | $js_objs = new JsObjFile($output_file, $obj_arr["prefix"], $obj_arr["suffix"], $obj_arr["block"]);
591 | $js_objs->safeSave();
592 | $ok = true;
593 | if (!$js_objs->status()) {
594 | Debug::output($js_objs->getError());
595 | $ok = false;
596 | } elseif (file_get_contents($test_file)!=file_get_contents($output_file)) {
597 | Debug::output("Test file $test_file and output file $output_file don't match.");
598 | $ok = false;
599 | }
600 | if ($ok)
601 | Debug::output("-------------------- OK");
602 | else
603 | Debug::output("-------------------- Failed");
604 | }
605 |
606 | // read
607 | foreach ($objects as $test_name=>$obj_arr) {
608 |
609 | $test_file = $test_path.$files[$test_name];
610 | $js_objs = new JsObjFile($test_file, $obj_arr["prefix"], $obj_arr["suffix"]);
611 | $js_objs->read();
612 |
613 | Debug::Output("Running reading test '$test_name'");
614 |
615 | $ok = true;
616 | if (!$js_objs->status()) {
617 | Debug::output($js_objs->getError());
618 | $ok = false;
619 | } elseif ($js_objs->block!=$objects[$test_name]["block"]) {
620 | Debug::output("Parsed block doesn't match test. parsed block=".print_r($js_objs->block,true). ", test block=".print_r($objects[$test_name]["block"],true));
621 | $ok = false;
622 | }
623 |
624 | if ($ok)
625 | Debug::output("-------------------- OK");
626 | else
627 | Debug::output("-------------------- Failed");
628 | }
629 | }
630 |
631 | public function getObject()
632 | {
633 | Debug::func_start(__METHOD__,func_get_args(),"ansql");
634 | return $this->block;
635 | }
636 | }
637 |
638 | ?>
639 |
--------------------------------------------------------------------------------
/sdr_config/enb_tabbed_settings.php:
--------------------------------------------------------------------------------
1 |
20 | "add_mme_");
31 | protected $default_section = "radio";
32 | protected $default_subsection = "enodeb";
33 | protected $title = "ENB";
34 | protected $menu_css = "menu menu_enb";
35 |
36 | function __construct()
37 | {
38 | $this->current_section = $this->default_section;
39 | $this->current_subsection = $this->default_subsection;
40 | $this->open_tabs = 2;
41 | }
42 |
43 | function getMenuStructure()
44 | {
45 | global $developers_tab;
46 |
47 | Debug::func_start(__METHOD__, func_get_args(), "tabs_enb");
48 |
49 | if (!$developers_tab)
50 | $developers_tab = false;
51 |
52 | //The key is the MENU alias the sections from $fields
53 | //and for each menu is an array that has the submenu data with subsections
54 | $structure = array(
55 | "Radio" => array("eNodeB", "Calibration"/*, "Bearers"*/),
56 | "Core" => array("GTP", "MME"/*, "S1AP"*/),
57 | // "Access channels" => array("PRACH",/* "PDSCH",*/ "PUSCH", "PUCCH", "PDCCH"),
58 |
59 | "Hardware" => array("Site info", "Site equipment", "Shutdown"),
60 | "System" => array("System information"/*, "Scheduler", "Advanced", "RadioHardware", "Measurements"*/),
61 | );
62 |
63 | if ($developers_tab)
64 | $structure["Developers"] = array("Radio", "General", "Uu-simulator", "Uu-loopback", "Test-Enb", "Test-scheduler");
65 |
66 | return $structure;
67 | }
68 |
69 | function getSectionsDescription()
70 | {
71 | global $developers_tab;
72 | Debug::func_start(__METHOD__, func_get_args(), "tabs_enb");
73 |
74 | if (!$developers_tab)
75 | $developers_tab = false;
76 |
77 | $desc = array(
78 | "enodeb" => "These are the most basic configuration parameters and the ones most likely to be changed.
79 | They are gathered in this section to make them easy to find.", //basic section from file
80 | // "bearers" => "Bearer parameters (RLC and PDCP layers)",
81 |
82 | "calibration" => "Parameters used in configuration of radio calibration module.",
83 | "gtp" => "S1-U interface parameters",
84 |
85 | "mme" => "Hand-configured MME. \n
86 | The eNodeB normally selects an MME using DNS,
87 | but explicit MME selection is also possible. \n
88 | This is an example of an explicit MME configuration:
89 |
90 | address = 192.168.56.62
91 | local = 192.168.56.1
92 | streams = 5
93 | dscp = expedited",
94 |
95 | // "scheduler" => "Parameters related to the MAC scheduler",
96 | /* "advanced" => "Here, \"advanced\" just means parameters that are not normally changed. \n
97 | It is not a reference to LTE-Advanced features.",*/
98 | // "measurements" => "KPI-related performance measurements",
99 | // "radiohardware" => "Control parameters for the lower PHY",
100 |
101 | "site_info" => "Site specific information.",
102 | "site_equipment" => "This is an area for customer-specific parameters for other site equipment,
103 | like antennas, cables, and anything else too \"dumb\" to carry its own
104 | configuration and identifying information. \n
105 | No defaults are provided.",
106 | "shutdown" => "Parameters for safety shutdown of SatSite components. \n
107 | Raising these parameters above their default values may result in damage to the eNodeB hardware or reduced equipment life. \n
108 | This parameters are ignored in Labkit units."
109 | );
110 |
111 | if ($developers_tab) {
112 | $desc["radio"] = "These are parameters for configuring the radio device";
113 | $desc["general"] = "Global configuration for the ENB Yate Module";
114 | $desc["uu-simulator"] = "Configuration parameters for the Uu interface simulator";
115 | $desc["uu-loopback"] = "Configuration parameters for the UeConnection test fixture";
116 | $desc["test-enb"] = "This section controls special test modes of the eNodeB.";
117 | $desc["test-scheduler"] = "This section controls special test modes of the eNodeB.";
118 | }
119 |
120 | return $desc;
121 | }
122 |
123 | // Retrieve settings using get_enb_node and build array with renamed sections to match interface fields
124 | function getApiFields()
125 | {
126 | global $developers_tab;
127 | Debug::func_start(__METHOD__, func_get_args(), "tabs_enb");
128 |
129 | $response_fields = request_api(array(), "get_enb_node", "node");
130 | if (!isset($response_fields["yateenb"])) {
131 | Debug::xdebug("tabs_enb", "Could not retrieve yateenb fields in " . __METHOD__);
132 | return null;
133 | }
134 |
135 | $res = $response_fields["yateenb"];
136 | if (isset($response_fields["gtp"]["ran_u"])) {
137 | $gtp_settings = $response_fields["gtp"]["ran_u"];
138 | if (isset($gtp_settings["addr4"]) && ($gtp_settings["addr4"]=="false" || !$gtp_settings["addr4"]))
139 | unset($gtp_settings["addr4"]);
140 | if (isset($gtp_settings["addr6"]) && ($gtp_settings["addr6"]=="false" || !$gtp_settings["addr6"]))
141 | unset($gtp_settings["addr6"]);
142 | } else {
143 | $gtp_settings = array();
144 | Debug::xdebug("tabs_enb", "Could not retrieve gtp fields in " . __METHOD__);
145 | }
146 | $res["gtp"] = $gtp_settings;
147 |
148 | if (isset($response_fields["sdr"])) {
149 | $hardware_settings = $response_fields["sdr"];
150 | if (isset($hardware_settings["basic"])) {
151 | $hardware_settings["site_info"] = $hardware_settings["basic"];
152 | unset($hardware_settings["basic"]);
153 | }
154 | foreach ($hardware_settings as $section=>$section_def)
155 | $res[$section] = $section_def;
156 | }
157 |
158 | // set mme fields
159 | foreach ($response_fields["yateenb"] as $section_name=>$section_def) {
160 | if (substr($section_name,0,3)!="mme")
161 | continue;
162 | $index = substr($section_name, 3);
163 | if ($index=="1") {
164 | $res["mme"] = $section_def;
165 | $res["mme"]["mme_address"] = $res["mme"]["address"];
166 | unset($res["mme"]["address"]);
167 | } else {
168 | foreach ($section_def as $param_name=>$param_value)
169 | $res["mme"][$param_name."_$index"] = $param_value;
170 | $res["mme"]["mme_address"."_$index"] = $res["mme"]["address_$index"];
171 | unset($res["mme"]["address_$index"]);
172 | }
173 | }
174 |
175 | // rename some of the sections the parameters appear under: basic->enodeb, basic-> all subsections under access channels, basic-> system_information
176 | $aggregated_subsections = array("enodeb","system_information",/*"pdsch","pusch","pucch","prach","pdcch"*/);
177 | foreach ($aggregated_subsections as $subsection)
178 | if (isset($res["basic"]))
179 | $res[$subsection] = $res["basic"];
180 |
181 | if (!$developers_tab)
182 | $developers_tab = false;
183 |
184 | if ($developers_tab) {
185 | if (isset($res["test-enb"]))
186 | $res["test-scheduler"] = $res["test-enb"];
187 | if (!isset($res["general"]["mode"]))
188 | $res["general"]["mode"] = "";
189 | }
190 |
191 | $this->storeCalibrationFields($response_fields, $res);
192 |
193 | return $res;
194 | }
195 |
196 | function getDefaultFields()
197 | {
198 | Debug::func_start(__METHOD__, func_get_args(), "tabs_enb");
199 |
200 | return get_default_fields_enb();
201 | }
202 |
203 | function buildParticularParam($data=null, $param=null, $request_fields=array())
204 | {
205 | return $data;
206 | }
207 |
208 | // Returns the field names which don't need invalid value detection
209 | function skip_detectInvalidFields_dropdown() {
210 | return array("addr4","addr6");
211 | }
212 |
213 | /**
214 | * Build form fields by applying response fields over default fields
215 | * @param $request_fields Array. Fields retrived using getApiFields
216 | * @param $exists_in_response Bool. Verify if field exists in $request_fields otherwise add special marker. Default false
217 | * @return Array
218 | */
219 | function applyRequestFields($request_fields=null,$exists_in_response=null)
220 | {
221 | global $developers_tab, $openvpn_interface;
222 | Debug::func_start(__METHOD__, func_get_args(), "tabs_enb");
223 |
224 | $structure = $this->buildConfSections();
225 | $fields = $this->getDefaultFields();
226 |
227 | if (!$request_fields)
228 | return $fields;
229 | if (!$developers_tab)
230 | $developers_tab = false;
231 |
232 | // verify if we have openvpn ip and preset it.
233 | if ((!isset($request_fields["gtp"]["addr4"]) && !isset($request_fields["gtp"]["addr6"])) && isset($fields["core"]["gtp"]["addr4"][0]) && $openvpn_interface) {
234 | foreach ($fields["core"]["gtp"]["addr4"][0] as $key=>$addr) {
235 | if (strpos($addr["addr4"],$openvpn_interface)!==FALSE && $fields["core"]["gtp"]["addr4"][0][$key+1]["addr4_id"]!="__disabled") {
236 | $fields["core"]["gtp"]["addr4"][0]["selected"]=$fields["core"]["gtp"]["addr4"][0][$key+1]["addr4"];
237 | break;
238 | }
239 | }
240 | }
241 |
242 | $custom_site_equipment = "";
243 | foreach ($structure as $section=>$data) {
244 | foreach ($data as $key=>$subsection) {
245 | if (isset($request_fields[$subsection])) {
246 | foreach ($request_fields[$subsection] as $param=>$data) {
247 |
248 | if ($subsection=="measurements" && $param=="reportingPeriod") {
249 | $param = "kpi_reportingPeriod";
250 | }
251 |
252 | if (!isset($fields[$section][$subsection]))
253 | continue;
254 |
255 | if (!isset($fields[$section][$subsection][$param])) {
256 | if ($subsection!="site_equipment")
257 | continue;
258 | if (strlen($custom_site_equipment))
259 | $custom_site_equipment .= "\n";
260 | $custom_site_equipment .= "$param=$data";
261 | continue;
262 | }
263 |
264 | if (isset($fields[$section][$subsection][$param]["display"]) && ($fields[$section][$subsection][$param]["display"]=="select" || $fields[$section][$subsection][$param]["display"]=="select_without_non_selected")) {
265 |
266 | if ($data=="" && in_array("Factory calibrated", $fields[$section][$subsection][$param][0]))
267 | $data = "Factory calibrated";
268 |
269 | // if IP(ipv4/ipv6) address configured for gtp is not in IPs scaned with
270 | // get_net_addresses add it in dropdown with label "--not available--"
271 | if (in_array($param, array("addr4","addr6")) && $subsection=="gtp") {
272 | $add_addr = true;
273 | foreach ($fields[$section]["gtp"][$param][0] as $addr)
274 | if ($data === $addr[$param])
275 | $add_addr = false;
276 | if ($add_addr ) {
277 | $fields[$section]["gtp"][$param][0][] = array($param."_id" => "__disabled", $param => "--not available--");
278 | $fields[$section]["gtp"][$param][0][] = array($param."_id" => $data, $param => $data);
279 | }
280 |
281 | }
282 |
283 | $fields[$section][$subsection][$param][0]["selected"] = $data;
284 |
285 | } elseif (isset($fields[$section][$subsection][$param]["display"]) && $fields[$section][$subsection][$param]["display"] == "checkbox")
286 |
287 | $fields[$section][$subsection][$param]["value"] = ($data=="yes" || $data=="on" || $data=="1") ? "on" : "off";
288 |
289 | elseif ( !isset($fields[$section][$subsection][$param]["display"]) || $fields[$section][$subsection][$param]["display"]!="fixed" )
290 | $fields[$section][$subsection][$param]["value"] = $data;
291 | elseif (isset($fields[$section][$subsection][$param]["display"]) && in_array(isset($fields[$section][$subsection][$param]["display"]), array("message","objtitle","fixed","custom_field")))
292 | continue;
293 |
294 |
295 | // unmark triggered fields if they are set
296 | if ((strlen($data) || getparam($param)) && isset($this->trigger_names[$subsection])) {
297 | $trigger_name = $this->trigger_names[$subsection];
298 | if (isset($fields[$section][$subsection][$param]["triggered_by"]) && ctype_digit(strval($fields[$section][$subsection][$param]["triggered_by"]))) {
299 | $triggered_by = $fields[$section][$subsection][$param]["triggered_by"];
300 | $former_trigger = $triggered_by - 1;
301 |
302 | if (isset($fields[$section][$subsection][$trigger_name.$former_trigger]))
303 | unset($fields[$section][$subsection][$trigger_name.$former_trigger]);
304 |
305 | $fld = $fields[$section][$subsection];
306 |
307 | foreach ($fld as $fldn=>$fldd) {
308 | if (isset($fldd["triggered_by"]) && $fldd["triggered_by"]==$triggered_by) {
309 | unset($fields[$section][$subsection][$fldn]["triggered_by"]);
310 | }
311 | }
312 |
313 | unset($fields[$section][$subsection][$param]["triggered_by"]);
314 | }
315 | }
316 | }
317 | }
318 | }
319 | }
320 |
321 | // SRB fields
322 | $ack_fields = array("rlcTPollRetransmit", "rlcTReordering", "rlcTStatusProhibit", "rlcMaxRetxThreshold", "rlcPollPdu", "rlcPollByte");
323 | $unack_fields = array("rlcSnFieldLength" ,"rlcTReordering");
324 |
325 | // unset triggered_by for SRB depending on selected mode
326 | /* for ($i=1; $i<3; $i++) {
327 | if (strlen(getparam("Srb$i.mode")))
328 | $srb_mode = getparam("Srb$i.mode");
329 | elseif (isset($fields["radio"]["bearers"]["Srb$i.mode"][0]["selected"]))
330 | $srb_mode = $fields["radio"]["bearers"]["Srb$i.mode"][0]["selected"];
331 | else
332 | $srb_mode = '';
333 |
334 | $trigger = array();
335 | if ($srb_mode=="acknowledged")
336 | $trigger = $ack_fields;
337 | elseif ($srb_mode=="unacknowledged")
338 | $trigger = $unack_fields;
339 | for ($j=0; $j"gtp", "cb"=>"validate_gtp_params"),
362 | array("subsection"=>"mme", "cb"=>"validate_mme_params")
363 | );
364 |
365 | foreach ($extra_validations as $validation) {
366 | if ($subsection==$validation["subsection"]) {
367 | $res = call_user_func($validation["cb"]);
368 | if (!$res[0])
369 | $this->error_field[] = array($res[1], $res[2][0]);
370 | elseif ($res[0] && isset($res[1]))
371 | $this->warning_field[] = array($res[1], $res[2][0]);
372 | }
373 | }
374 |
375 | if (count($this->error_field))
376 | return array(false, "fields"=>$parent_res["fields"], "request_fields"=>$parent_res["request_fields"]);
377 | return $parent_res;
378 | }
379 |
380 | // Send API request to save ENB configuration
381 | // Break error message in case of error and mark section/subsection to be opened
382 | function storeFormResult(array $fields)
383 | {
384 | global $developers_tab;
385 | //if no errors encountered on validate data fields then send API request
386 | Debug::func_start(__METHOD__, func_get_args(), "tabs_enb");
387 |
388 | if (!$developers_tab)
389 | $developers_tab = false;
390 |
391 | $request_fields = array("yateenb"=>array("basic"=>array()));//, "gtp"=>array());
392 | $request_fields["calibrate"] = $this->setCalibrationFields($fields);
393 |
394 | $basic_sections = array("enodeb","system_information"/*,"pdsch","pusch","pucch","prach","pdcch"*/);
395 | foreach ($basic_sections as $basic_section) {
396 | $request_fields["yateenb"]["basic"] = array_merge($request_fields["yateenb"]["basic"], $fields[$basic_section]);
397 | unset($fields[$basic_section]);
398 | }
399 |
400 | $gtp = $fields["gtp"];
401 | unset($fields["gtp"]);
402 |
403 | $satsite = array();
404 | $satsite_sections = array("site_info", "site_equipment", "shutdown");
405 | foreach ($satsite_sections as $satsite_section) {
406 | $section_name = ($satsite_section!="site_info") ? $satsite_section : "basic";
407 | $satsite[$section_name] = $fields[$satsite_section];
408 | unset($fields[$satsite_section]);
409 | }
410 | if (count($satsite))
411 | $request_fields["sdr"] = $satsite;
412 |
413 | if (isset($fields["measurements"]["kpi_reportingPeriod"])) {
414 | $fields["measurements"]["reportingPeriod"] = $fields["measurements"]["kpi_reportingPeriod"];
415 | unset($fields["measurements"]["kpi_reportingPeriod"]);
416 | }
417 |
418 | if (strlen($fields["mme"]["mme_address"])) {
419 |
420 | $index = 1;
421 | $mme_fields = array("mme_address"=>"address","local","streams","dscp");
422 |
423 | while(true) {
424 | $suffix = ($index>1) ? "_$index" : "";
425 | $custom_mme = array();
426 | if (isset($fields["mme"]["mme_address$suffix"]) && strlen($fields["mme"]["mme_address$suffix"])) {
427 | foreach ($mme_fields as $field_index=>$field_name) {
428 | $form_name = (is_numeric($field_index)) ? $field_name.$suffix : $field_index.$suffix;
429 | $custom_mme[$field_name] = $fields["mme"][$form_name];
430 | }
431 | $fields["mme$index"] = $custom_mme;
432 | $index++;
433 | } else
434 | break;
435 | }
436 | }
437 | unset($fields["mme"]);
438 |
439 | if (isset($request_fields["sdr"]["site_equipment"]["custom_parameters"])) {
440 | if (strlen($request_fields["sdr"]["site_equipment"]["custom_parameters"])) {
441 | $custom = explode("\r\n",$request_fields["sdr"]["site_equipment"]["custom_parameters"]);
442 | foreach ($custom as $custom_param) {
443 | $custom_param = explode("=",$custom_param);
444 | if (count($custom_param)!=2)
445 | continue;
446 | $request_fields["sdr"]["site_equipment"][trim($custom_param[0])] = trim($custom_param[1]);
447 | }
448 |
449 | }
450 | unset($request_fields["sdr"]["site_equipment"]["custom_parameters"]);
451 | }
452 |
453 | if (isset($fields["bearers"]))
454 | $fields["bearers"] = $this->setBearers($fields["bearers"]);
455 |
456 | $request_fields["yateenb"] = array_merge($request_fields["yateenb"],$fields);
457 |
458 | if ($developers_tab) {
459 | foreach ($fields["test-scheduler"] as $p_name=>$p_value)
460 | $request_fields["yateenb"]["test-enb"][$p_name] = $p_value;
461 |
462 | unset($request_fields["yateenb"]["test-scheduler"]);
463 | }
464 |
465 | $request_fields["gtp"]["ran_u"] = $gtp;
466 |
467 | $res = make_request($request_fields, "set_enb_node");
468 |
469 | if (!isset($res["code"]) || $res["code"]!=0) {
470 | // find subsection where error was detected so it can be opened
471 | $mess = substr($res["message"],-15);
472 | $pos_section = strrpos($mess,"'",-5);
473 | $subsection = substr($mess,$pos_section+1);
474 | $subsection = substr($subsection,0,strpos($subsection,"'"));
475 | if (substr($subsection,0,3)=="mme")
476 | $subsection = "mme";
477 |
478 | $section = $this->findSection($subsection);
479 | if (!$section) {
480 | Debug::output('enb tabs', "Could not find section for subsection '$subsection'");
481 | $section = $this->default_section;
482 | $subsection = $this->default_subsection;
483 | }
484 |
485 | $this->current_subsection = $subsection;
486 | $this->current_section = $section;
487 | $_SESSION[$this->title]["subsection"] = $subsection;
488 | $_SESSION[$this->title]["section"] = $section;
489 |
490 | $code = "";
491 | if (isset($res["code"]))
492 | $code = "[API: ".$res["code"]."] ";
493 |
494 | return array(false, $code.$res["message"]);
495 | } else {
496 | unset($_SESSION[$this->title]["section"], $_SESSION[$this->title]["subsection"]);
497 | return array(true);
498 | }
499 | }
500 |
501 | function setBearers($form_data)
502 | {
503 | $bearers = array();
504 |
505 | // SRB
506 | $ack_fields = array("rlcTPollRetransmit", "rlcTReordering", "rlcTStatusProhibit", "rlcMaxRetxThreshold", "rlcPollPdu", "rlcPollByte");
507 | $unack_fields = array("rlcSnFieldLength" ,"rlcTReordering");
508 |
509 | for ($i=1 ; $i<3 ; $i++) {
510 | $mode = $form_data["Srb$i.mode"];
511 | if ($mode=="acknowledged")
512 | $set = $ack_fields;
513 | elseif ($mode=="unacknowledged")
514 | $set = $unack_fields;
515 | else
516 | $set = array();
517 |
518 | $bearers["Srb$i.mode"] = $mode;
519 | foreach ($set as $key) {
520 | $value = (isset($form_data["Srb$i.$key"])) ? $form_data["Srb$i.$key"] : "";
521 | $bearers["Srb$i.$key"] = $value;
522 | }
523 | }
524 |
525 | // DBR
526 | // set all drb params
527 | foreach ($form_data as $key=>$value) {
528 | if (substr($key,0,3)=="Drb")
529 | $bearers[$key] = $value;
530 | }
531 |
532 | return $bearers;
533 | }
534 | }
535 | ?>
536 |
--------------------------------------------------------------------------------