From: kkalev Date: Sat, 10 Aug 2002 16:49:21 +0000 (+0000) Subject: * Add support for groups in SQL. Added several new files and modified a few more. X-Git-Url: https://git.entuzijast.net/?a=commitdiff_plain;h=f3d5071d0ac66aa1a58f59dc0859a47f7ac9a5b2;p=freeradius-dialup-admin.git * Add support for groups in SQL. Added several new files and modified a few more. * Default values in SQL are now extracted from the group membership. Added a lib/sql/defaults.php3 file. As a result the default operator is not '=' anymore but whatever we find in the group check and reply tables. * In lib/sql/user_info.php3 set user_exists in more than one places. * Add support for the '=*' and '!*' operators * Added a HELP_WANTED file describing what are the major things missing which people could contribute. * Updated TODO --- diff --git a/AUTHORS b/AUTHORS index 74a6616..439babe 100644 --- a/AUTHORS +++ b/AUTHORS @@ -15,4 +15,4 @@ A number of bug reports and a lot of crash testing Alex Savguira: alexs@ravdata.com Ido Shavit -Patches for auto generate password and sql group support +Patches for auto generate password diff --git a/Changelog b/Changelog index 89f3327..698bca1 100644 --- a/Changelog +++ b/Changelog @@ -1,3 +1,11 @@ +Ver 1.50: +* Add support for groups in SQL. Added several new files and modified a few more. +* Default values in SQL are now extracted from the group membership. Added a lib/sql/defaults.php3 file. + As a result the default operator is not '=' anymore but whatever we find in the group check and reply tables. +* In lib/sql/user_info.php3 set user_exists in more than one places. +* Add support for the '=*' and '!*' operators +* Added a HELP_WANTED file describing what are the major things missing which people could contribute. +* Updated TODO Ver 1.30: * Add limit of results returned in accounting.php3 * Fix a bug in time2strclock() in lib/functions.php3. Seconds ammount more than 9 would not show. diff --git a/HELP_WANTED b/HELP_WANTED new file mode 100644 index 0000000..c5c7b81 --- /dev/null +++ b/HELP_WANTED @@ -0,0 +1,7 @@ +What you can contribute: + +o Billing and statistics pages. Fancy bars and diagrams are needed for dialup_admin to be complete. + +o Documentation. + +o Attribute help pages like those that already exist. diff --git a/TODO b/TODO index 90e6b00..c6736ce 100644 --- a/TODO +++ b/TODO @@ -10,3 +10,7 @@ sql db if it cannot get user info from the nas server * Check out dbx library. It seems very promising for database independent code. We 'll see where it goes. +* Add billing and statistics pages. Billing is a must. The page should also create + reports which could be printed or sent by email to the users containing their billing + information. We also need more statistics pages with fancy bars and diagrams. Ideas + are welcome. diff --git a/conf/user_edit.attrs b/conf/user_edit.attrs index f83d651..3d723eb 100644 --- a/conf/user_edit.attrs +++ b/conf/user_edit.attrs @@ -15,8 +15,8 @@ Framed-Compression Session Timeout +Idle-Timeout Idle Timeout #Termination-Action #Login-LAT-Service #Login-LAT-Node diff --git a/htdocs/buttons.html b/htdocs/buttons.html index a6555f5..f75ef49 100644 --- a/htdocs/buttons.html +++ b/htdocs/buttons.html @@ -53,6 +53,17 @@ function myout(a) { New User + +
+ + Edit Group +
+ + + + New Group + + Check Server diff --git a/htdocs/group_admin.php3 b/htdocs/group_admin.php3 new file mode 100644 index 0000000..83b3b8c --- /dev/null +++ b/htdocs/group_admin.php3 @@ -0,0 +1,118 @@ +Group Administration Page + + + +
+This page is only available if you are using sql as general library type + + +EOM; + exit(); +} + +if (is_file("../lib/$config[general_lib_type]/group_info.php3")){ + include("../lib/$config[general_lib_type]/group_info.php3"); + if ($group_exists == 'no'){ + echo <<Group Administration Page + + + +
+ +Group Name   + +  does not exist
+ + + +EOM; + exit(); + } +} +?> + + + +Group Administration Page + + + +
+ + + + +
+ + + + +
+
+ + + + + +
+ + +
+ Group Administration  +
+
+ + +
+ + + + + + > + + + + + + + + + + +
+Group Members (Check to Delete) + + +
+New Group Member + + +
+
+ + +
+
+ + diff --git a/htdocs/group_new.php3 b/htdocs/group_new.php3 new file mode 100644 index 0000000..0af6e32 --- /dev/null +++ b/htdocs/group_new.php3 @@ -0,0 +1,139 @@ + + + + +New group creation page + + + +
+ + + + +
+ +
+ + + + + +
+ + +
+ Preferences for new group  +
+
+ + +
+ +The group $login already exists in the group database +EOM; + } + else{ + if (is_file("../lib/$config[general_lib_type]/create_group.php3")) + include("../lib/$config[general_lib_type]/create_group.php3"); + if (is_file("../lib/$config[general_lib_type]/group_info.php3")) + include("../lib/$config[general_lib_type]/group_info.php3"); + } +} +?> +
+ + + + + + + + + + +EOM; + foreach($show_attrs as $key => $desc){ + $name = $attrmap["$key"]; + if ($name == 'none') + continue; + $oper_name = $name . '_op'; + $val = ($item_vals["$key"][0] != "") ? $item_vals["$key"][0] : $default_vals["$key"]; + print << + +EOM; + + if ($show_ops) + print << + + +EOM; + + print << + + + +EOM; + } +?> +
+ Group name + + +
+ First member + + +
+$desc +
+
+ +

+ +
+
+
+ + diff --git a/htdocs/help/idle_timeout_help.html b/htdocs/help/idle_timeout_help.html new file mode 100644 index 0000000..eafc611 --- /dev/null +++ b/htdocs/help/idle_timeout_help.html @@ -0,0 +1,35 @@ + + +Idle Timeout Help Page + + + +
+ + + + + +
+ + +
Idle Timeout Help Page 
+
+ + + + +
+
+
+
+  This Attribute sets the maximum number of consecutive seconds of
+  idle connection allowed to the user before termination of the
+  session or prompt.
+
+
+Close Window +
+
+ + diff --git a/htdocs/help/session_timeout_help.html b/htdocs/help/session_timeout_help.html new file mode 100644 index 0000000..b246443 --- /dev/null +++ b/htdocs/help/session_timeout_help.html @@ -0,0 +1,34 @@ + + +Session Timeout Help Page + + + +
+ + + + + +
+ + +
Session Timeout Help Page 
+
+ + + + +
+
+
+
+  This Attribute sets the maximum number of seconds of service to be
+  provided to the user before termination of the session or prompt.
+
+
+Close Window +
+
+ + diff --git a/htdocs/user_delete.php3 b/htdocs/user_delete.php3 index b41bf27..f0f2bc0 100644 --- a/htdocs/user_delete.php3 +++ b/htdocs/user_delete.php3 @@ -1,12 +1,26 @@ -delete user $login ($cn) +EOM; + +if ($user_type != 'group') + echo "delete user $login ($cn)\n"; +else + echo "delete group $login\n"; + +echo << @@ -20,7 +34,10 @@ echo << EOM; -include("../html/user_toolbar.html.php3"); +if ($user_type != 'group') + include("../html/user_toolbar.html.php3"); +else + include("../html/group_toolbar.html.php3"); print << @@ -32,7 +49,7 @@ print <<
- User $login Deletion  + $whatisL $login Deletion 
@@ -42,8 +59,14 @@ print << @@ -61,7 +84,7 @@ EOM;
-Are you sure you want to delete user ? +Are you sure you want to delete ?
diff --git a/htdocs/user_edit.php3 b/htdocs/user_edit.php3 index b7f5c3c..3e2c30c 100644 --- a/htdocs/user_edit.php3 +++ b/htdocs/user_edit.php3 @@ -1,9 +1,19 @@ -subscription configuration for $login ($cn) +EOM; + +if ($user_type != 'group') + echo " subscription configuration for $login ($cn)\n"; +else + echo " subscription configuration for $login\n"; + +echo << EOM; -include("password_generator.jsc"); +if ($user_type != 'group') + include("password_generator.jsc"); echo << @@ -37,7 +55,10 @@ echo << EOM; -include("../html/user_toolbar.html.php3"); +if ($user_type != 'group') + include("../html/user_toolbar.html.php3"); +else + include("../html/group_toolbar.html.php3"); print << @@ -61,10 +82,16 @@ EOM; if ($change == 1){ if (is_file("../lib/$config[general_lib_type]/change_attrs.php3")) include("../lib/$config[general_lib_type]/change_attrs.php3"); - if ($passwd != '' && is_file("../lib/$config[general_lib_type]/change_passwd.php3")) - include("../lib/$config[general_lib_type]/change_passwd.php3"); - if (is_file("../lib/$config[general_lib_type]/user_info.php3")) - include("../lib/$config[general_lib_type]/user_info.php3"); + if ($user_type != 'group'){ + if ($passwd != '' && is_file("../lib/$config[general_lib_type]/change_passwd.php3")) + include("../lib/$config[general_lib_type]/change_passwd.php3"); + if (is_file("../lib/$config[general_lib_type]/user_info.php3")) + include("../lib/$config[general_lib_type]/user_info.php3"); + } + else{ + if (is_file("../lib/$config[general_lib_type]/group_info.php3")) + include("../lib/$config[general_lib_type]/group_info.php3"); + } } else if ($badusers == 1){ if (is_file("../lib/add_badusers.php3")) @@ -74,19 +101,24 @@ else if ($badusers == 1){ ?>
> + > + - - $desc){ $name = $attrmap["$key"]; if ($name == 'none') @@ -102,7 +134,7 @@ User Password (changes only) } else{ $vals[] = $default_vals["$key"]; - $ops[] = '='; + $ops[] = ($default_vals["$key"][operator] != '') ? $default_vals["$key"][operator] : '='; } if ($add && $name == $add_attr){ array_push($vals, $default_vals["$key"]); @@ -142,6 +174,8 @@ EOM; + + +EOM; +} +?>
bgcolor="#d0ddb0"> + User Password (changes only)
+Member of + + +

+


+EOM; +} +?>
diff --git a/html/group_toolbar.html.php3 b/html/group_toolbar.html.php3 new file mode 100644 index 0000000..0763565 --- /dev/null +++ b/html/group_toolbar.html.php3 @@ -0,0 +1,12 @@ + + +ADMIN + +EDIT + +DELETE + +EOM; +?> diff --git a/lib/operators.php3 b/lib/operators.php3 index b4841af..95525cb 100644 --- a/lib/operators.php3 +++ b/lib/operators.php3 @@ -10,6 +10,8 @@ $op_lt = '<'; $op_le = '<='; $op_regeq = '=~'; $op_regne = '!~'; +$op_exst = '=*'; +$op_nexst = '!*'; // Check the operator if it is allowed for this type of // attribute (check or reply). @@ -32,6 +34,8 @@ function check_operator($op,$type) case '<=': case '=~': case '!~': + case '=*': + case '!*': return ($type == 1) ? 0 : -1; } } diff --git a/lib/sql/change_attrs.php3 b/lib/sql/change_attrs.php3 index bc09b11..fce0ba4 100644 --- a/lib/sql/change_attrs.php3 +++ b/lib/sql/change_attrs.php3 @@ -27,12 +27,13 @@ if ($link){ $name = $attrmap["$key"] . $i; $sql_attr=$attrmap["$key"]; + $query_key = ($user_type == 'group') ? 'GroupName' : 'UserName'; if ($attr_type["$key"] == 'checkItem'){ - $table = $config[sql_check_table]; + $table = ($user_type == 'group') ? $config[sql_groupcheck_table] : $config[sql_check_table]; $type = 1; } else if ($attr_type["$key"] == 'replyItem'){ - $table = $config[sql_reply_table]; + $table = ($user_type == 'group') ? $config[sql_groupreply_table] : $config[sql_reply_table]; $type = 2; } if ($use_ops){ @@ -50,7 +51,7 @@ if ($link){ if ($use_ops && isset($item_vals["$key"][operator][$j]) && $op_val != $item_vals["$key"][operator][$j] ){ $res = @da_sql_query($link,$config, - "UPDATE $table SET op = '$op_val' WHERE UserName = '$login' + "UPDATE $table SET op = '$op_val' WHERE $query_key = '$login' AND Attribute = '$sql_attr' AND Value = '$val';"); if (!$res || !@da_sql_affected_rows($link,$res,$config)) echo "Operator change failed for attribute $key
\n"; @@ -62,7 +63,7 @@ if ($link){ // if value is null and corresponding value exists then delete else if (($val == $default_vals["$key"] || $val == '') && isset($item_vals["$key"][$j])){ $res = @da_sql_query($link,$config, - "DELETE FROM $table WHERE UserName = '$login' AND Attribute = '$sql_attr';"); + "DELETE FROM $table WHERE $query_key = '$login' AND Attribute = '$sql_attr';"); if (!$res || !@da_sql_affected_rows($link,$res,$config)) echo "Delete failed for attribute $key
\n"; } @@ -74,12 +75,12 @@ if ($link){ if (isset($item_vals["$key"][$j])){ $old_val = $item_vals["$key"][$j]; $res = @da_sql_query($link,$config, - "UPDATE $table SET Value = '$val' WHERE UserName = '$login' AND + "UPDATE $table SET Value = '$val' WHERE $query_key = '$login' AND Attribute = '$sql_attr' AND Value = '$old_val';"); } else $res = @da_sql_query($link,$config, - "INSERT INTO $table (UserName,Attribute,Value $text2) + "INSERT INTO $table ($query_key,Attribute,Value $text2) VALUES ('$login','$sql_attr','$val' $op_val2);"); if (!$res || !@da_sql_affected_rows($link,$res,$config)) echo "Change failed for attribute $key
\n"; diff --git a/lib/sql/create_group.php3 b/lib/sql/create_group.php3 new file mode 100644 index 0000000..1f4e70c --- /dev/null +++ b/lib/sql/create_group.php3 @@ -0,0 +1,58 @@ +Could not include SQL library
\n"; + exit(); +} +if ($config[sql_use_operators] == 'true'){ + include("../lib/operators.php3"); + $text = ',op'; + $passwd_op = ",':='"; +} +$da_abort=0; +$link = @da_sql_pconnect($config); +if ($link){ + $res = @da_sql_query($link,$config, + "INSERT INTO $config[sql_usergroup_table] (UserName,GroupName) + VALUES ('$member','$login');"); + if (!$res || !@da_sql_affected_rows($link,$res,$config)){ + echo "Unable to add group $login. SQL error
\n"; + $da_abort=1; + } + if (!$da_abort){ + foreach($show_attrs as $key => $attr){ + if ($attrmap["$key"] == 'none') + continue; + if ($attr_type[$key] == 'checkItem'){ + $table = "$config[sql_groupcheck_table]"; + $type = 1; + } + else if ($attr_type[$key] == 'replyItem'){ + $table = "$config[sql_groupreply_table]"; + $type = 2; + } + $val = $$attrmap["$key"]; + $op_name = $attrmap["$key"] . '_op'; + $op_val = $$op_name; + if ($op_val != ''){ + if (check_operator($op_val,$type) == -1){ + echo "Invalid operator ($op_val) for attribute $key
\n"; + coninue; + } + $op_val = ",'$op_val'"; + } + if ($val == '' || $val == $default_vals["$key"]) + continue; + $res = @da_sql_query($link,$config, + "INSERT INTO $table (Attribute,Value,GroupName $text) + VALUES ('$attrmap[$key]','$val','$login' $op_val);"); + if (!$res || !@da_sql_affected_rows($link,$res,$config)) + echo "Query failed for attribute $key
\n"; + } + } + echo "Group created successfully
\n"; +} +else + echo "Could not connect to database
\n"; +?> diff --git a/lib/sql/defaults.php3 b/lib/sql/defaults.php3 new file mode 100644 index 0000000..06bec34 --- /dev/null +++ b/lib/sql/defaults.php3 @@ -0,0 +1,74 @@ +Could not include SQL library
\n"; + exit(); +} +if ($config[sql_use_operators] == 'true'){ + $op = ',op'; + $use_op = 1; +}else{ + $op = ""; + $use_op = 0; +} +unset($item_vals); +unset($tmp); +$link = @da_sql_pconnect($config); +if ($link){ + $res = @da_sql_query($link,$config, + "SELECT GroupName FROM $config[sql_usergroup_table] WHERE UserName = '$login';"); + if ($res){ + while(($row = @da_sql_fetch_array($res,$config))) + $member_groups[] = $row[GroupName]; + } + if (isset($member_groups)){ + foreach ($member_groups as $group){ + $res = @da_sql_query($link,$config, + "SELECT Attribute,Value $op FROM $config[sql_groupcheck_table] WHERE GroupName = '$group';"); + if ($res){ + while(($row = @da_sql_fetch_array($res,$config))){ + $attr = $row[Attribute]; + $val = $row[Value]; + if ($use_op){ + $oper = $row[op]; + $tmp["$attr"][operator][]="$oper"; + } + $tmp["$attr"][]="$val"; + $tmp["$attr"][count]++; + } + $res = @da_sql_query($link,$config, + "SELECT Attribute,Value $op FROM $config[sql_groupreply_table] WHERE GroupName = '$group';"); + if ($res){ + while(($row = @da_sql_fetch_array($res,$config))){ + $attr = $row[Attribute]; + $val = $row[Value]; + if ($use_op){ + $oper = $row[op]; + $tmp["$attr"][operator][]="$oper"; + } + $tmp["$attr"][] = "$val"; + $tmp["$attr"][count]++; + } + } + else + echo "Database query failed partially
\n"; + } + else + echo "Database query failed
\n"; + foreach($attrmap as $key => $val){ + if (isset($tmp[$val])){ + if ($tmp[$val][0] != '') + $default_vals["$key"] = $tmp[$val][0]; + if ($use_op) + if ($tmp[$val][operator][0] != '') + $default_vals["$key"][operator] = $tmp[$val][operator][0]; + } + } + } + } +} +else + echo "Could not connect to database
\n"; +?> diff --git a/lib/sql/delete_group.php3 b/lib/sql/delete_group.php3 new file mode 100644 index 0000000..917a13e --- /dev/null +++ b/lib/sql/delete_group.php3 @@ -0,0 +1,31 @@ +Could not include SQL library
\n"; + exit(); +} +$link = @da_sql_pconnect($config); +if ($link){ + $res = @da_sql_query($link,$config, + "DELETE FROM $config[sql_groupreply_table] WHERE GroupName = '$login';"); + if ($res){ + $res = @da_sql_query($link,$config, + "DELETE FROM $config[sql_groupcheck_table] WHERE GroupName = '$login';"); + if ($res){ + $res = @da_sql_query($link,$config, + "DELETE FROM $config[sql_usergroup_table] WHERE GroupName = '$login';"); + if ($res) + echo "Group $login deleted successfully
\n"; + else + echo "Error deleting group $login from usergroup table
\n"; + } + else + echo "Error deleting group $login from group check table
\n"; + } + else + echo "Error deleting group $login from group reply table
\n"; +} +else + echo "Could not connect to database
\n"; +?> diff --git a/lib/sql/delete_user.php3 b/lib/sql/delete_user.php3 index c8729f9..c068e1f 100644 --- a/lib/sql/delete_user.php3 +++ b/lib/sql/delete_user.php3 @@ -13,6 +13,10 @@ if ($link){ $res = @da_sql_query($link,$config, "DELETE FROM $config[sql_check_table] WHERE UserName = '$login';"); if ($res){ + $res = @da_sql_query($link,$config, + "DELETE FROM $config[sql_usergroup_table] WHERE UserName = '$login';"); + if (!$res) + echo "Error deleting user $login from user group table
\n"; if ($config[sql_use_user_info_table] == 'true'){ $res = @da_sql_query($link,$config, "DELETE FROM $config[sql_user_info_table] WHERE UserName = '$login';"); diff --git a/lib/sql/group_admin.php3 b/lib/sql/group_admin.php3 new file mode 100644 index 0000000..90fc433 --- /dev/null +++ b/lib/sql/group_admin.php3 @@ -0,0 +1,37 @@ +Could not include SQL library
\n"; + exit(); +} +$link = @da_sql_pconnect($config); +if ($link){ + if (isset($del_members)){ + foreach ($del_members as $del){ + $res = @da_sql_query($link,$config, + "DELETE FROM $config[sql_usergroup_table] WHERE UserName = '$del' AND GroupName = '$login';"); + if (!$res) + echo "Could not delete user $del from group. SQL Error
\n"; + } + } + if ($new_member != ''){ + $res = @da_sql_query($link,$config, + "SELECT UserName FROM $config[sql_usergroup_table] WHERE UserName = '$new_member' AND GroupName = '$login';"); + if ($res){ + if (@da_sql_num_rows($res,$config)) + echo "User $new_member already is a member of the group
\n"; + else{ + $res = @da_sql_query($link,$config, + "INSERT INTO $config[sql_usergroup_table] (GroupName,UserName) VALUES ('$login','$new_member');"); + if (!$res) + echo "Error while adding user $new_member to group
\n"; + } + } + else + echo "Could not add new member $new_member. SQL Error
\n"; + } +} +else + echo "Could not connect to database
\n"; +?> diff --git a/lib/sql/group_info.php3 b/lib/sql/group_info.php3 new file mode 100644 index 0000000..684e517 --- /dev/null +++ b/lib/sql/group_info.php3 @@ -0,0 +1,83 @@ +Could not include SQL library
\n"; + exit(); +} +if ($config[sql_use_operators] == 'true'){ + $op = ',op'; + $use_op = 1; +}else{ + $op = ""; + $use_op = 0; +} +$group_exists = 'no'; +unset($item_vals); +unset($tmp); +unset($group_members); +$link = @da_sql_pconnect($config); +if ($link){ + $res = @da_sql_query($link,$config, + "SELECT Attribute,Value $op FROM $config[sql_groupcheck_table] WHERE GroupName = '$login';"); + if ($res){ + if (@da_sql_num_rows($res,$config)) + $group_exists = 'yes'; + while(($row = @da_sql_fetch_array($res,$config))){ + $attr = $row[Attribute]; + $val = $row[Value]; + if ($use_op){ + $oper = $row[op]; + $tmp["$attr"][operator][]="$oper"; + } + $tmp["$attr"][]="$val"; + $tmp["$attr"][count]++; + } + $res = @da_sql_query($link,$config, + "SELECT Attribute,Value $op FROM $config[sql_groupreply_table] WHERE GroupName = '$login';"); + if ($res){ + if (@da_sql_num_rows($res,$config)) + $group_exists = 'yes'; + while(($row = @da_sql_fetch_array($res,$config))){ + $attr = $row[Attribute]; + $val = $row[Value]; + if ($use_op){ + $oper = $row[op]; + $tmp["$attr"][operator][]="$oper"; + } + $tmp["$attr"][] = "$val"; + $tmp["$attr"][count]++; + } + } + else + echo "Database query failed partially
\n"; + $res = @da_sql_query($link,$config, + "SELECT UserName FROM $config[sql_usergroup_table] WHERE GroupName = '$login' ORDER BY UserName;"); + if ($res){ + if (@da_sql_num_rows($res,$config)) + $group_exists = 'yes'; + while(($row = @da_sql_fetch_array($res,$config))){ + $member = $row[UserName]; + $group_members[] = "$member"; + } + } + else + echo "Database query failed partially
\n"; + foreach($attrmap as $key => $val){ + if (isset($tmp[$val])){ + $item_vals["$key"] = $tmp[$val]; + $item_vals["$key"][count] = $tmp[$val][count]; + if ($use_op) + $item_vals["$key"][operator] = $tmp[$val][operator]; + + } + } + + } + else + echo "Database query failed
\n"; +} +else + echo "Could not connect to database
\n"; +?> diff --git a/lib/sql/user_info.php3 b/lib/sql/user_info.php3 index 0a99248..be6efb8 100644 --- a/lib/sql/user_info.php3 +++ b/lib/sql/user_info.php3 @@ -36,6 +36,8 @@ if ($link){ $res = @da_sql_query($link,$config, "SELECT Attribute,Value $op FROM $config[sql_reply_table] WHERE UserName = '$login';"); if ($res){ + if (@da_sql_num_rows($res,$config)) + $user_exists = 'yes'; while(($row = @da_sql_fetch_array($res,$config))){ $attr = $row[Attribute]; $val = $row[Value]; @@ -50,6 +52,8 @@ if ($link){ $res = @da_sql_query($link,$config, "SELECT * FROM $config[sql_user_info_table] WHERE UserName = '$login';"); if ($res){ + if (@da_sql_num_rows($res,$config)) + $user_exists = 'yes'; if (($row = @da_sql_fetch_array($res,$config))){ $cn = ($row[Name]) ? $row[Name] : '-'; $telephonenumber = ($row[WorkPhone]) ? $row[WorkPhone] : '-';