コード例 #1
0
function delete_edges_with($source = '*', $label = '*', $destination = '*')
{
    $paths = edges_with($source, $label, $destination);
    foreach ($paths as $link_path) {
        if (is_link($link_path)) {
            //Get the name of the parent label directory so that we can check whether it is empty after we delete the destination link.
            $label_path = dirname($link_path);
            //Remove the link itself.
            if (!unlink($link_path)) {
                $unlink_error = error_get_last();
                exit_with_error_json("Deletion of link \"" . $link_path . "\" failed: " . $unlink_error['message']);
            }
            //If the label directory is now empty, delete it.
            $remaining_destinations = glob($label_path . PATH_SEPARATOR . NODE_NAME_WILDCARD, GLOB_ONLYDIR);
            if ($remaining_destinations === FALSE) {
                $glob_error = error_get_last();
                exit_with_error_json("Check for destination symlinks in \"" . $label_path . "\" failed: " . $glob_error['message']);
            }
            if (count($remaining_destinations) < 1) {
                if (!rmdir($label_path)) {
                    $rmdir_error = error_get_last();
                    exit_with_error_json("Deletion of empty label directory \"" . $label_path . "\" failed: " . $rmdir_error['message']);
                }
                //end of if we failed to delete the empty label directory
            }
            //end of if the label folder is now empty.
        }
        //end of if the link exists and is a symbolic link
    }
    //end of loop through all edges found
}
コード例 #2
0
function node_text_with_path($path)
{
    $text_file_path = $path . FILE_PATH_SEPARATOR . TEXT_FILE_NAME;
    $text = file_get_contents($text_file_path);
    if ($text === FALSE) {
        $fgc_error = error_get_last();
        exit_with_error_json("Attempt to read text from file \"" . $text_file_path . "\" failed: " . $fgc_error['message']);
    }
    return $text;
}
コード例 #3
0
ファイル: edges_with.php プロジェクト: adamgcraig/mindmap
function edges_with($source = '*', $label = '*', $destination = '*')
{
    $link_path_pattern = NODE_PATH . $source . PATH_SEPARATOR . $label . PATH_SEPARATOR . $destination;
    $paths = glob($link_path_pattern);
    if ($paths === FALSE) {
        $glob_error = error_get_last();
        exit_with_error_json("Search for paths matching pattern \"" . $link_path_pattern . "\" failed: " . $glob_error['message']);
    }
    //end of if we failed to search for edge links
    return $paths;
}
コード例 #4
0
function get_node_or_exit($node_role)
{
    if (!isset($_REQUEST[$node_role])) {
        exit_with_error_json("The request did not include a " . $node_role . " node.");
    }
    $node = $_REQUEST[$node_role];
    exit_on_bad_node_name($node);
    if (!is_dir(NODE_PATH . $node)) {
        exit_with_error_json("The requested " . $node_role . " node, " . $node . ", does not exist.");
    }
    return $node;
}
コード例 #5
0
function exit_on_bad_node_name($name)
{
    //Check that the name includes only Perl word characters, i.e., alphanumeric characters and '_'s.
    //This is more strict than we need to be but safer than letting the user use every character other than '/'
    //and still flexible enough that the user can devise a wide variety of descriptive node names.
    $name_has_bad_char = preg_match('/[\\W]+/', $name);
    //Check that preg_match has not failed.
    if ($name_has_bad_char === FALSE) {
        switch (preg_last_error()) {
            case PREG_NO_ERROR:
                $error_message = "no error";
                break;
            case PREG_INTERNAL_ERROR:
                $error_message = "internal error";
                break;
            case PREG_BACKTRACK_LIMIT_ERROR:
                $error_message = "too many backtracks";
                break;
            case PREG_RECURSION_LIMIT_ERROR:
                $error_message = "too many recursions";
                break;
            case PREG_BAD_UTF8_ERROR:
                $error_message = "bad UTF8 character";
                break;
            case PREG_BAD_UTF8_OFFSET_ERROR:
                $error_message = "bad UTF8 offset";
                break;
            default:
                $error_message = "unknown error";
        }
        //end of switch over different error codes for regular expression matcher
        exit_with_error_json("An error occurred during checking of the filename for bad characters: " . $error_message);
    }
    //end of if preg_match failed
    if ($name_has_bad_char) {
        exit_with_error_json("The name \"" . $name . "\" contains a character that was not a letter, number, or underscore.");
    }
    //Check that the name is not too long.
    if (strlen($name) > MAX_NAME_LENGTH) {
        exit_with_error_json("The name \"" . $name . "\" is longer than " . MAX_NAME_LENGTH . " bytes.");
    }
    //Check that the name is not the empty string.
    if (strlen($name) < 1) {
        exit_with_error_json("The name is an empty string.");
    }
    //Check that creating the directory will leave a safe amount of free disk space.
    //Since Linux keeps various temporary files around until it needs to clear them, this may not reflect all the memory potentially available.
    //if( disk_free_space('.') - strlen($name) <  MEMORY_SAFETY_MARGIN) {
    //    exit_with_error_json("Creating a file or directory named \"".$name."\" would leave fewer than ".MEMORY_SAFETY_MARGIN." bytes of disk space. ".disk_free_space('.')." bytes currently free.");
    //}
}
コード例 #6
0
ファイル: findview.php プロジェクト: adamgcraig/mindmap
    //end of loop through paths
}
//end of if we have a target name
//echo("array of view info arrays with distances:");
//print_r($view_array);
function compare_closeness($view1, $view2)
{
    $output = 0;
    //Try case-insensitive name similarity.
    if (!$output && isset($view1[DISTANCE_BY_NAME_CASE_INSENSITIVE])) {
        $output = $view1[DISTANCE_BY_NAME_CASE_INSENSITIVE] - $view2[DISTANCE_BY_NAME_CASE_INSENSITIVE];
        //Then try case-sensitive name similarity.
        if (!$output) {
            $output = $view1[DISTANCE_BY_NAME] - $view2[DISTANCE_BY_NAME];
        }
    }
    //If we did not receive a target name or got ties on both case-insensitive and case-sensitive comparisons, sort lexicographically.
    //Recall that names must be unique.
    if (!$output) {
        $output = strcmp($view1[NAME], $view2[NAME]);
    }
    return $output;
}
//end of function compare_closeness
$result = usort($view_array, 'compare_closeness');
if ($result === FALSE) {
    exit_with_error_json("Attempt to sort views failed.");
}
//echo("array of view info arrays sorted:");
//print_r($view_array);
exit(json_encode(array('results' => $view_array)));
コード例 #7
0
ファイル: deleteview.php プロジェクト: adamgcraig/mindmap
<?php

//SUMMARY: Given an HTTP request with the name of a view, deletes that view.
require_once 'includes/consts.php';
require_once 'includes/exit_with_error_json.php';
require_once 'includes/exit_on_bad_node_name.php';
//Check that the request includes a name.
if (!isset($_REQUEST[NAME])) {
    exit_with_error_json("The request did not contain a view name.");
}
//end of if no name provided
$name = $_REQUEST[NAME];
//We hold views to the same naming conventions as we do nodes.
exit_on_bad_node_name($name);
$view_path = VIEW_PATH . $name . VIEW_FILE_TYPE;
if (!unlink($view_path)) {
    $unlink_error = error_get_last();
    exit_with_error_json("Deletion of file \"" . $view_path . "\" failed: " . $unlink_error['message']);
}
exit(json_encode(array('success' => TRUE)));
コード例 #8
0
ファイル: findnode.php プロジェクト: adamgcraig/mindmap
    if (isset($node1[DISTANCE_BY_TEXT_CASE_INSENSITIVE])) {
        $output = $node1[DISTANCE_BY_TEXT_CASE_INSENSITIVE] - $node2[DISTANCE_BY_TEXT_CASE_INSENSITIVE];
        //Then try case-sensitive text similarity.
        if (!$output) {
            $output = $node1[DISTANCE_BY_TEXT] - $node2[DISTANCE_BY_TEXT];
        }
    }
    //If we had a target name but no target text or a tie when comparing by text, try case-insensitive name similarity.
    if (!$output && isset($node1[DISTANCE_BY_NAME_CASE_INSENSITIVE])) {
        $output = $node1[DISTANCE_BY_NAME_CASE_INSENSITIVE] - $node2[DISTANCE_BY_NAME_CASE_INSENSITIVE];
        //Then try case-sensitive name similarity.
        if (!$output) {
            $output = $node1[DISTANCE_BY_NAME] - $node2[DISTANCE_BY_NAME];
        }
    }
    //If we did not receive either kind of target or got ties on both targets, sort lexicographically by text.
    if (!$output) {
        $output = strcmp($node1[TEXT], $node2[TEXT]);
    }
    //If we are still tied, sort lexicographically by name. Recall that names must be unique.
    if (!$output) {
        $output = strcmp($node1[NAME], $node2[NAME]);
    }
    return $output;
}
//end of function compare_closeness
$result = usort($node_array, 'compare_closeness');
if ($result === FALSE) {
    exit_with_error_json("Attempt to sort nodes failed.");
}
exit(json_encode(array('nodes' => $node_array)));
コード例 #9
0
ファイル: makeview.php プロジェクト: adamgcraig/mindmap
}
//Give it permissions that will allow the scripts to work.
if (chmod($view_path, FILE_PERMISSIONS) === FALSE) {
    $chmod_error = error_get_last();
    exit_with_error_json("Setting of permissions of \"" . $view_path . "\" failed: " . $chmod_error['message']);
}
$dest_edit_history_path = EDIT_HISTORY_PATH . $name;
//Serialize the edits.
//For this to work, the top-level array must be associative.
$dest_edits_assoc = array();
$dest_edits_assoc[UPDATES] = $dest_edits;
$dest_edits_string = json_encode($dest_edits_assoc);
if ($dest_edits_string === FALSE) {
    exit_with_error_json("Attempt to serialize edit history failed.");
}
//Check that we have enough free disk space.
//This check produces false positives on Linux servers, because they tend to use free memory for temporary files and clear it as needed.
//if( disk_free_space(".") - strlen($dest_edits_string) <  MEMORY_SAFETY_MARGIN) {
//    exit_with_error_json("Creating the new edit history \"".$dest_edit_history_path."\" would leave fewer than ".MEMORY_SAFETY_MARGIN." bytes of disk space.");
//}
//Write the edits to the file.
if (file_put_contents($dest_edit_history_path, $dest_edits_string, LOCK_EX) == FALSE) {
    $fpc_error = error_get_last();
    exit_with_error_json("Attempt to write to file " . $dest_edit_history_path . " failed: " . $fpc_error['message']);
}
//Give it permissions that will allow the script to access the file in the future.
if (chmod($dest_edit_history_path, FILE_PERMISSIONS) === FALSE) {
    $chmod_error = error_get_last();
    exit_with_error_json("Setting of permissions of \"" . $dest_edit_history_path . "\" failed: " . $chmod_error['message']);
}
exit(json_encode(array('view_path' => $view_path)));
コード例 #10
0
         exit_with_error_json("Edit history file is incorrectly formatted, missing key " . UPDATES . ".");
     }
     $new_update_count = count($edits);
     //If there are more updates we have not yet sent, send them.
     //There should be, since the file was modified, but check just in case some other process somehow modified the file.
     if ($new_update_count > $update_count) {
         //If the client has received 0 edits, send all of them.
         //                        ...1 edits, send all but the first (index 0).
         //                        ...2 edits, send all but the first, and second (index 0 and index 1).
         //                        ...3 edits, send all but the first, second, and third (index 0, index 1, index 2).
         $new_edits_numeric = array_slice($edits, $update_count);
         $new_edits_assoc = array();
         $new_edits_assoc[UPDATES] = $new_edits_numeric;
         $new_edits_string = json_encode($new_edits_assoc);
         if ($new_edits_string === FALSE) {
             exit_with_error_json("Attempt to serialize new edits failed: " . json_last_error());
         }
         //Set the retry "The reconnection time to use when attempting to send the event."
         echo "retry: 1000\n";
         //milliseconds
         //A stream broadcast must begin with "data:".
         echo "data: " . $new_edits_string;
         //A stream broadcast must end with an empty line.
         $should_send = TRUE;
         //We now have content to send.
         //Set update_count so we do not send the same updates again.
         $update_count = $new_update_count;
     }
     //end of if we have updates to send
 }
 //end of if the file has been modified since we last checked
コード例 #11
0
ファイル: setnode.php プロジェクト: adamgcraig/mindmap
        exit_with_error_json("Creation of directory \"" . $node_path . "\" failed: " . $mkdir_error['message']);
    }
    //end of if directory creation failed
}
//end of if directory does not exist
//If the request does not include a separate text string, use the directory name for the text content.
if (isset($_REQUEST[TEXT])) {
    $text = $_REQUEST[TEXT];
} else {
    $text = $name;
}
//Do not allow PHP scripts in the text file.
$safe_text = preg_replace('/<\\?php/', "<!notphp", $text);
$text_file_path = $node_path . PATH_SEPARATOR . TEXT_FILE_NAME;
//Take into account that, since we overwrite any old content, take that into account when we consider memory use.
if (is_file($text_file_path)) {
    $existing_file_size = filesize($text_file_path);
} else {
    $existing_file_size = 0;
}
//Check that the text will leave a safe amount of free disk space.
if (disk_free_space(".") - strlen($safe_text) + $existing_file_size < MEMORY_SAFETY_MARGIN) {
    exit_with_error_json("Writing text \"" . $safe_text . "\" to file \"" . $text_file_path . "\" would leave fewer than " . MEMORY_SAFETY_MARGIN . " bytes of disk space.");
}
//Try to save the text to a file.
$text_write_outcome = file_put_contents($text_file_path, $safe_text, LOCK_EX);
if ($text_write_outcome === FALSE) {
    $fpc_error = error_get_last();
    exit_with_error_json("Attempt to write text \"" . $safe_text . "\" to file \"" . $text_file_path . "\" failed: " . $fpc_error['message']);
}
exit(json_encode(array('text_file_path' => $text_file_path)));
コード例 #12
0
ファイル: deletenode.php プロジェクト: adamgcraig/mindmap
$node_path = NODE_PATH . $name;
$files = scandir($node_path);
foreach ($files as $file) {
    //Skip over the loopback link to the directory itself and the parent directory backlink.
    if ($file == '.' || $file == '..') {
        continue;
    }
    //Create the path to the file relative to our current directory.
    $file_path = $node_path . '/' . $file;
    //For now, we only try to delete files instead of looking for non-label directories and trying to delete them recursively.
    if (is_file($file_path)) {
        if (!unlink($file_path)) {
            $unlink_error = error_get_last();
            exit_with_error_json("Deletion of file \"" . $file_path . "\" failed: " . $unlink_error['message']);
        }
        //end of if file deletion failed
    }
    //end of if is a file
}
//end of deleting any files in the node directory
//reminder: scandir includes '.' and '..' even when the directory is empty, so a directory with 1 item has 3 scandir results
if (count(scandir($node_path)) >= 3) {
    exit_with_error_json("Directory \"" . $node_path . "\" contains something other than label directories and regular files, so we cannot delete it.");
}
//end of if the directory is still not empty
if (!rmdir($node_path)) {
    $rmdir_error = error_get_last();
    exit_with_error_json("Deletion of empty node directory \"" . $node_path . "\" failed: " . $rmdir_error['message']);
}
//end of if we failed to delete the empty node directory
exit(json_encode(array('success' => TRUE)));
コード例 #13
0
ファイル: makeedge.php プロジェクト: adamgcraig/mindmap
//It checks beforehand that all three directories exist as subdirectories of the nodes directory,
//and that the link does not already exist.
require_once 'includes/consts.php';
require_once 'includes/exit_with_error_json.php';
require_once 'includes/get_node_or_exit.php';
$source = get_node_or_exit(SOURCE);
$label = get_node_or_exit(LABEL);
$destination = get_node_or_exit(DESTINATION);
//Since this is a relative symbolic link, we have to specify the destination relative to the location of the link.
//In this case, that means going up two levels,
//out of the label directory and out of the directory folder,
//to the nodes directory then down to the destination directory.
$target_path = '../../' . $destination;
$label_path = NODE_PATH . $source . PATH_SEPARATOR . $label;
$link_path = $label_path . PATH_SEPARATOR . $destination;
if (is_link($link_path)) {
    exit_with_error_json("The link \"" . $link_path . "\"->\"" . $target_path . "\" already exists.");
}
if (!is_dir($label_path)) {
    if (mkdir($label_path, DIRECTORY_PERMISSIONS, true) === FALSE) {
        $mkdir_error = error_get_last();
        exit_with_error_json("Creation of directory \"" . $label_path . "\" failed:" . $mkdir_error['message']);
    }
    //end of if we failed to make the label sub-directory
}
//end of if the label sub-directory does not exist
if (!symlink($target_path, $link_path)) {
    $link_error = error_get_last();
    exit_with_error_json("Creation of link \"" . $link_path . "\"->\"" . $target_path . "\" failed: " . $link_error['message']);
}
exit(json_encode(array('edge_href' => $link_path)));