<?php

include_once("../../AccessControl.php");

function EvaluateFilter($sqlstring) {
    # Lets do a series of tests to see if we should throw any warnings at the user,
    # because builing a query could potatially be dangerous for abuse or high server load times
    $warning="";

    # Warn if a user has a wildcard at start of string
    if (strpos($sqlstring,"'%")!==FALSE) {
        $warning .= "<b><i>". _WARNING .":</b></i> "._WARNING_LIKE_FILTER . "<br/>";
    }
    # Warn if a user uses the same field twice in an AND condtion
    if (getOperator($sqlstring)=="AND") {
        $wordcount = [];
        foreach(arrayConditions($sqlstring) as $condition) {
            # We're only interested in the first part
            $condition = trim($condition);
            $str = substr($condition, 0, strpos($condition, " "));
            if (isset($str) && $str !== '') {
                $wordcount[$str]++;
            }
        }
        
        foreach($wordcount as $key => $val){ 
            if ($val > 1) {
                $warning .= "<b><i>". _WARNING .":</b></i> ". str_replace("%K%", $key,  str_replace("%V%", $val, _WARNING_DOUBLE_FIELD_FILTER )) ."<br/>";
            }
        }
    } else {
        # Warn if a user uses NOT LIKE or != in an OR condition
        if (count(arrayConditions($sqlstring)) > 1 && hasNegativeCondition($sqlstring)==true) {
            $warning .= "<b><i>". _WARNING .":</b></i> "._WARNING_MULTI_NEGATIVE_FILTER;
        }
    }
    return $warning;
}

function DeleteSegmentDatafiles($seg_id){
    global $profile;

    if(DATAFILE_METHOD == "ziparchive"){
        # remove the segment files from the zip
        $zips = glob($profile->datamanagerDir.$profile->profilename."/reports/*/*.zip");
        $segmentfiles = array();
        foreach ($zips as $zipfile) {
            $f = listzip($zipfile,"\/.*(.S\-{$seg_id}).*");
            if(empty($f)){
                continue;
            }
            $segmentfiles[ $zipfile] = $f;
        }

        $zip = new ziparchive;
        foreach ($segmentfiles as $zf => $files) {
            if ($zip->open($zf) === TRUE) {
                foreach ($files as $file) {
                    $zip->deleteName($file);
                }
                $zip->close();
            }
        }

    } else {
        # Do it the old normal way.
        $segmentDatafiles = glob($profile->datamanagerDir.$profile->profilename."/reports/*/*/*.S-{$seg_id}*");
        if(empty($segmentDatafiles)){
            return false;
        }
        foreach($segmentDatafiles as $file){
            unlink($file);
        }
    }
}

$categories = array();

$q = $db->Execute("select profileid,category,id,sourcecondition,sourcename,userid from ".TBL_TRAFFIC_SOURCES." where profileid='{$profile->profileid}' or profileid='' order by category, sourcename");
if (!$q) {
    # Probably no table.  When we create a test, we'll create the table.
} else {
    while($row = $q->FetchRow()){
        if( !$session->isAdmin() ){
            # is there a userid set for this record, i.e. a private segment ?
            if(!empty($row['userid'])){
                # if it is not a source of this user then GTFO!
                if($row['userid'] != $session->userinfo['userid']){
                    continue;
                }
            }
        }
        if(empty($categories[ $row['category'] ])){
            $categories[ $row['category'] ] = array();
        }
        $categories[ $row['category'] ][] = $row;
    }
}

if(empty($_POST['save']) && empty($_POST['del'])){
    die(json_encode(array( "Status" => "Success", "Categories" => $categories )));
}

if(!empty($_POST['del'])){

    $change_check = $db->Execute("SELECT * FROM ".TBL_TRAFFIC_SOURCES." WHERE id=". $db->Quote($_POST['del']) ."");
    $check = $change_check->fetchRow();

    // check if we are allowed to edit this filter
    if (!$session->isAdmin() && $check['profileid']==0 && $check['userid']!=$session->userinfo['userid']) {
        $status = "Error";
        $msg=_ACCESS_DENIED;
        die(json_encode(array( "Status" => $status, "Message" => $msg )));
    }

    $posts = array(
        $_POST['del']
    );
    $db->Execute("DELETE from ".TBL_TRAFFIC_SOURCES." where id = ?", $posts);
    die(json_encode(array( "Status" => "Success", "Message" => _SEGMENT_DELETED)));
}

# We want to save stuff so lets get to it..

$validfields = array("ipnumber", "useragent", "is_mobile");
$columns = $db->MetaColumns($profile->tablename);

foreach ($columns as $column) {
    if ($column->name != "id" && $column->name != "timestamp" && $column->name != "status" && $column->name != "bytes" && $column->name != "crawl") {
        $validfields[] = $column->name;
    }
}

$i = 0;

$filtername = $filtername ?? $_POST["name"];
$category = $category ?? $_POST["category"];
$newcategory = $newcategory ?? $_POST["newcategory"];
$edit = $edit ?? $_POST["filterid"];

if ($newcategory != "") {
    $category = $newcategory;
}

if (isset($_POST["andor"]) && ($_POST["andor"] == "AND" || $_POST["andor"] == "OR")) {
    $andor = $_POST["andor"];
} else {
    die('{ "Status": "Error", "Message": "' . _INVALID_INPUT . '"}');
}

while ($i < 25) {
    $cvalue = $cvalue ?? $_POST["cvalue$i"];
    if (!empty($cvalue)) {
        # verify the $_POST["andor"] field is valid
        if (isset($_POST["field$i"]) && in_array($_POST["field$i"], $validfields)) {
            $field = $_POST["field$i"];
        } else {
            die('{ "Status": "Error", "Message": "'. _INVALID_FIELD .'"}');
        }

        if (isset($_POST["condition$i"])) {
            $condition = $_POST["condition$i"];
        } else {
            die('{ "Status": "Error", "Message": "'. _INVALID_INPUT .'"}');
        }

        # make sql string or a valid condition
        if ($condition=="contains") {
            $op = "$field LIKE ".$db->Quote("%$cvalue%");
        } else if ($condition=="nocontain") {
            $op = "$field NOT LIKE ".$db->Quote("%$cvalue%");
            $warn_nocontain = 1;
        } else if ($condition=="nostart") {
            $op = "$field NOT LIKE ".$db->Quote("$cvalue%");
            $warn_nocontain = 1;
        } else if ($condition=="start") {
            $op = "$field LIKE ".$db->Quote("$cvalue%");
        } else if ($condition=="end") {
            $op = "$field LIKE ".$db->Quote("%$cvalue");
        } else if ($condition=="is") {
            $op = "$field =".$db->Quote($cvalue);
        } else if ($condition=="isnot") {
            $op = "$field !=".$db->Quote($cvalue);
        }
        if ($i == 0) {
            $sqlstring="$op";
        } else {
            $sqlstring.=" $andor $op";
        }
    }
    $i++;
}

// do we want this to be a private segment?
if(isset($_REQUEST['segment_access']) && $_REQUEST['segment_access']=="private") {
    $userid = $session->userinfo['userid'];
} else {
    $userid = 0;
}

// do we want this to be a global segment?
if(isset($_REQUEST['segment_profile']) && $_REQUEST['segment_profile']=="global") {
    // if we are not an admin, global segments are always private
    if (!$session->isAdmin()) {
        $userid = $session->userinfo['userid'];
    }
    $profileid = 0;
} else {
    $profileid = $profile->profileid;
}

# preset return message 
$status = "Success";
$msg = "";

if(empty($_POST['filterid']) || !is_numeric($_POST['filterid'])){
    if(!empty($sqlstring)){
        if ($filtername=="") {
            $filtername=_UNNAMED_FILTER;
        }
        $db->Execute("insert into ".TBL_TRAFFIC_SOURCES." (profileid,sourcename,sourcecondition,category,userid) values ('{$profileid}', ". $db->Quote($filtername).",". $db->Quote($sqlstring) .",". $db->Quote($category).",". $db->Quote($userid)." )");
        $edit = $db->Insert_ID();
        $msg= "<b>"._NEW_FILTER_SAVED.":</b> $filtername ($category)";
    } else {
        $status = "Error";
        $msg = _PROBLEM_NOTHING_TO_SAVE;
    }
} else { # for saving existing filters

    $change_check = $db->Execute("SELECT * FROM ".TBL_TRAFFIC_SOURCES." WHERE id=". $db->Quote($edit) ."");
    while($check = $change_check->fetchRow()){

        // check if we are allowed to edit this filter
        if (!$session->isAdmin() && $check['profileid']==0 && $check['userid']!=$session->userinfo['userid']) {
            $status = "Error";
            $msg=_ACCESS_DENIED;
            die(json_encode(array( "Status" => $status, "Message" => $msg )));
        }

        if( md5($check["sourcecondition"]) !== md5($sqlstring) ){
            DeleteSegmentDatafiles($edit);
        }
    }

    $db->Execute("update ".TBL_TRAFFIC_SOURCES." set profileid='$profileid', sourcename=". $db->Quote($filtername) .",sourcecondition=". $db->Quote($sqlstring) .", category=". $db->Quote($category) .", userid=". $db->Quote($userid) ." where id=". $db->Quote($edit) ."");
    $msg = "<b>"._FILTER_UPDATED.":</b> $filtername ($category)";

    # when a filter has been edited, we need to reset the old table;
    $db->Execute("drop table if exists ".$profile->tablename."_SEGMENT_".$edit);
    # ;insert into _logaholic_users set username='hacked';
    $profile->SetOtherSettings("SEGMENT_".$edit."_Range","0");
}

if(!empty($sqlstring) && !empty($warn_nocontain)){
    $msg .= "<br/>" . EvaluateFilter($sqlstring);
}

die(json_encode(array( "Status" => $status, "Message" => $msg )));
?>