Example #1
0
function api_edit_url_update()
{
    if (!isset($_REQUEST['shorturl'])) {
        return array('statusCode' => 400, 'status' => 'fail', 'simple' => "Need a 'shorturl' parameter", 'message' => 'error: missing param');
    }
    if (!isset($_REQUEST['url'])) {
        return array('statusCode' => 400, 'status' => 'fail', 'simple' => "Need a 'url' parameter", 'message' => 'error: missing param');
    }
    $shorturl = $_REQUEST['shorturl'];
    $url = $_REQUEST['url'];
    if (yourls_get_protocol($shorturl)) {
        $keyword = yourls_get_relative_url($shorturl);
    } else {
        $keyword = $shorturl;
    }
    if (!yourls_is_shorturl($keyword)) {
        return array('statusCode' => 404, 'status' => 'fail', 'simple ' => "Error: keyword {$keyword} not found", 'message' => 'error: not found');
    }
    $title = '';
    if (isset($_REQUEST['title'])) {
        $title = $_REQUEST['title'];
    }
    if (yourls_edit_link($url, $keyword, $keyword, $title)) {
        return array('statusCode' => 200, 'simple' => "Keyword {$keyword} updated to {$url}", 'message' => 'success: updated');
    } else {
        return array('statusCode' => 500, 'status' => 'fail', 'simple' => 'Error: could not edit keyword, not sure why :-/', 'message' => 'error: unknown error');
    }
}
Example #2
0
function clayton_api_action_delete()
{
    // We don't want unauthenticated users deleting links
    // If YOURLS is in public mode, force authentication anyway
    if (!yourls_is_private()) {
        yourls_do_action('require_auth');
        require_once YOURLS_INC . '/auth.php';
    }
    // Need 'shorturl' parameter
    if (!isset($_REQUEST['shorturl'])) {
        return array('statusCode' => 400, 'simple' => "Need a 'shorturl' parameter", 'message' => 'error: missing param');
    }
    $shorturl = $_REQUEST['shorturl'];
    // Check if valid shorturl
    if (!yourls_is_shorturl($shorturl)) {
        return array('statusCode' => 404, 'simple ' => 'Error: short URL not found', 'message' => 'error: not found');
    }
    // Is $shorturl a URL (http://sho.rt/abc) or a keyword (abc) ?
    if (yourls_get_protocol($shorturl)) {
        $keyword = yourls_get_relative_url($shorturl);
    } else {
        $keyword = $shorturl;
    }
    // Delete shorturl
    if (yourls_delete_link_by_keyword($keyword)) {
        return array('statusCode' => 200, 'simple' => "Shorturl {$shorturl} deleted", 'message' => 'success: deleted');
    } else {
        return array('statusCode' => 500, 'simple' => 'Error: could not delete shorturl, not sure why :-/', 'message' => 'error: unknown error');
    }
}
Example #3
0
function ozh_yourls_antispam_check_add($false, $url)
{
    // Sanitize URL and make sure there's a protocol
    $url = yourls_sanitize_url($url);
    // only check for 'http(s)'
    if (!in_array(yourls_get_protocol($url), array('http://', 'https://'))) {
        return false;
    }
    if (ozh_yourls_antispam_is_blacklisted($url) != false) {
        return array('status' => 'fail', 'code' => 'error:spam', 'message' => 'This domain is blacklisted', 'errorCode' => '403');
    }
    // All clear, not interrupting the normal flow of events
    return false;
}
Example #4
0
/**
 * Checks and cleans a URL before printing it. Stolen from WP.
 *
 * A number of characters are removed from the URL. If the URL is for displaying
 * (the default behaviour) ampersands are also replaced.
 *
 * @since 1.6
 *
 * @param string $url The URL to be cleaned.
 * @param string $context 'display' or something else. Use yourls_sanitize_url() for database or redirection usage.
 * @param array $protocols Optional. Array of allowed protocols, defaults to global $yourls_allowedprotocols
 * @return string The cleaned $url
 */
function yourls_esc_url($url, $context = 'display', $protocols = array())
{
    // make sure there's only one 'http://' at the beginning (prevents pasting a URL right after the default 'http://')
    $url = str_replace(array('http://*****:*****@)?([^/#?]+)(.*)$!', $url, $matches)) {
        list($all, $scheme, $slashes, $userinfo, $domain, $rest) = $matches;
        $scheme = strtolower($scheme);
        // Domain to lowercase. On URN eg "urn:example:animal:ferret:nose" don't lowercase anything else
        if ($slashes == '//') {
            $domain = strtolower($domain);
        }
        $url = $scheme . $slashes . $userinfo . $domain . $rest;
    }
    $url = preg_replace('|[^a-z0-9-~+_.?#=!&;,/:%@$\\|*\'()\\x80-\\xff]|i', '', $url);
    // Previous regexp in YOURLS was '|[^a-z0-9-~+_.?\[\]\^#=!&;,/:%@$\|*`\'<>"()\\x80-\\xff\{\}]|i'
    // TODO: check if that was it too destructive
    $strip = array('%0d', '%0a', '%0D', '%0A');
    $url = yourls_deep_replace($strip, $url);
    $url = str_replace(';//', '://', $url);
    // Replace ampersands and single quotes only when displaying.
    if ('display' == $context) {
        $url = yourls_kses_normalize_entities($url);
        $url = str_replace('&amp;', '&#038;', $url);
        $url = str_replace("'", '&#039;', $url);
    }
    if (!is_array($protocols) or !$protocols) {
        global $yourls_allowedprotocols;
        $protocols = yourls_apply_filter('esc_url_protocols', $yourls_allowedprotocols);
        // Note: $yourls_allowedprotocols is also globally filterable in functions-kses.php/yourls_kses_init()
    }
    if (!yourls_is_allowed_protocol($url, $protocols)) {
        return '';
    }
    // I didn't use KSES function kses_bad_protocol() because it doesn't work the way I liked (returns //blah from illegal://blah)
    return yourls_apply_filter('esc_url', $url, $original_url, $context);
}
Example #5
0
/**
 * Return an "Add" row for the main table
 *
 * @return string HTML of the edit row
 */
function yourls_table_add_row($keyword, $url, $title = '', $ip, $clicks, $timestamp)
{
    $keyword = yourls_sanitize_string($keyword);
    $id = yourls_string2htmlid($keyword);
    // used as HTML #id
    $shorturl = yourls_link($keyword);
    $statlink = yourls_statlink($keyword);
    $delete_link = yourls_nonce_url('delete-link_' . $id, yourls_add_query_arg(array('id' => $id, 'action' => 'delete', 'keyword' => $keyword), yourls_admin_url('admin-ajax.php')));
    $edit_link = yourls_nonce_url('edit-link_' . $id, yourls_add_query_arg(array('id' => $id, 'action' => 'edit', 'keyword' => $keyword), yourls_admin_url('admin-ajax.php')));
    // Action link buttons: the array
    $actions = array('stats' => array('href' => $statlink, 'id' => "statlink-{$id}", 'title' => yourls_esc_attr__('Stats'), 'anchor' => yourls__('Stats')), 'share' => array('href' => '', 'id' => "share-button-{$id}", 'title' => yourls_esc_attr__('Share'), 'anchor' => yourls__('Share'), 'onclick' => "toggle_share('{$id}');return false;"), 'edit' => array('href' => $edit_link, 'id' => "edit-button-{$id}", 'title' => yourls_esc_attr__('Edit'), 'anchor' => yourls__('Edit'), 'onclick' => "edit_link_display('{$id}');return false;"), 'delete' => array('href' => $delete_link, 'id' => "delete-button-{$id}", 'title' => yourls_esc_attr__('Delete'), 'anchor' => yourls__('Delete'), 'onclick' => "remove_link('{$id}');return false;"));
    $actions = yourls_apply_filter('table_add_row_action_array', $actions);
    // Action link buttons: the HTML
    $action_links = '';
    foreach ($actions as $key => $action) {
        $onclick = isset($action['onclick']) ? 'onclick="' . $action['onclick'] . '"' : '';
        $action_links .= sprintf('<a href="%s" id="%s" title="%s" class="%s" %s>%s</a>', $action['href'], $action['id'], $action['title'], 'button button_' . $key, $onclick, $action['anchor']);
    }
    $action_links = yourls_apply_filter('action_links', $action_links, $keyword, $url, $ip, $clicks, $timestamp);
    if (!$title) {
        $title = $url;
    }
    $protocol_warning = '';
    if (!in_array(yourls_get_protocol($url), array('http://', 'https://'))) {
        $protocol_warning = yourls_apply_filter('add_row_protocol_warning', '<span class="warning" title="' . yourls__('Not a common link') . '">&#9733;</span>');
    }
    // Row cells: the array
    $cells = array('keyword' => array('template' => '<a href="%shorturl%">%keyword_html%</a>', 'shorturl' => yourls_esc_url($shorturl), 'keyword_html' => yourls_esc_html($keyword)), 'url' => array('template' => '<a href="%long_url%" title="%title_attr%">%title_html%</a><br/><small>%warning%<a href="%long_url%">%long_url_html%</a></small>', 'long_url' => yourls_esc_url($url), 'title_attr' => yourls_esc_attr($title), 'title_html' => yourls_esc_html(yourls_trim_long_string($title)), 'long_url_html' => yourls_esc_html(yourls_trim_long_string($url)), 'warning' => $protocol_warning), 'timestamp' => array('template' => '%date%', 'date' => date('M d, Y H:i', $timestamp + YOURLS_HOURS_OFFSET * 3600)), 'ip' => array('template' => '%ip%', 'ip' => $ip), 'clicks' => array('template' => '%clicks%', 'clicks' => yourls_number_format_i18n($clicks, 0, '', '')), 'actions' => array('template' => '%actions% <input type="hidden" id="keyword_%id%" value="%keyword%"/>', 'actions' => $action_links, 'id' => $id, 'keyword' => $keyword));
    $cells = yourls_apply_filter('table_add_row_cell_array', $cells, $keyword, $url, $title, $ip, $clicks, $timestamp);
    // Row cells: the HTML. Replace every %stuff% in 'template' with 'stuff' value.
    $row = "<tr id=\"id-{$id}\">";
    foreach ($cells as $cell_id => $elements) {
        $callback = new yourls_table_add_row_callback($elements);
        $row .= sprintf('<td class="%s" id="%s">', $cell_id, $cell_id . '-' . $id);
        $row .= preg_replace_callback('/%([^%]+)?%/', array($callback, 'callback'), $elements['template']);
        // For the record, in PHP 5.3+ we don't need to introduce a class in order to pass additional parameters
        // to the callback function. Instead, we would have used the 'use' keyword :
        // $row .= preg_replace_callback( '/%([^%]+)?%/', function( $match ) use ( $elements ) { return $elements[ $match[1] ]; }, $elements['template'] );
        $row .= '</td>';
    }
    $row .= "</tr>";
    $row = yourls_apply_filter('table_add_row', $row, $keyword, $url, $title, $ip, $clicks, $timestamp);
    return $row;
}
Example #6
0
/**
 * Explode a URL in an array of ( 'protocol' , 'slashes if any', 'rest of the URL' )
 *
 * Some hosts trip up when a query string contains 'http://' - see http://git.io/j1FlJg
 * The idea is that instead of passing the whole URL to a bookmarklet, eg index.php?u=http://blah.com,
 * we pass it by pieces to fool the server, eg index.php?proto=http:&slashes=//&rest=blah.com
 *
 * Known limitation: this won't work if the rest of the URL itself contains 'http://', for example
 * if rest = blah.com/file.php?url=http://foo.com
 *
 * Sample returns:
 *
 *   with 'mailto:jsmith@example.com?subject=hey' :
 *   array( 'protocol' => 'mailto:', 'slashes' => '', 'rest' => 'jsmith@example.com?subject=hey' )
 *
 *   with 'http://example.com/blah.html' :
 *   array( 'protocol' => 'http:', 'slashes' => '//', 'rest' => 'example.com/blah.html' )
 *
 * @since 1.7
 * @param string $url URL to be parsed
 * @param array $array Optional, array of key names to be used in returned array
 * @return mixed false if no protocol found, array of ('protocol' , 'slashes', 'rest') otherwise
 */
function yourls_get_protocol_slashes_and_rest($url, $array = array('protocol', 'slashes', 'rest'))
{
    $proto = yourls_get_protocol($url);
    if (!$proto or count($array) != 3) {
        return false;
    }
    list($null, $rest) = explode($proto, $url, 2);
    list($proto, $slashes) = explode(':', $proto);
    return array($array[0] => $proto . ':', $array[1] => $slashes, $array[2] => $rest);
}
Example #7
0
/**
 * Lowercase scheme and domain of an URI - see issues 591, 1630, 1889
 *
 * This function is trickier than what seems to be needed at first
 * 
 * First, we need to handle several URI types: http://example.com, mailto:ozh@ozh.ozh, facetime:user@example.com, and so on, see
 * yourls_kses_allowed_protocols() in functions-kses.php
 * The general rule is that the scheme ("stuff://" or "stuff:") is case insensitive and should be lowercase. But then, depending on the
 * scheme, parts of what follows the scheme may or may not be case sensitive.
 *
 * Second, simply using parse_url() and its opposite http_build_url() (see functions-compat.php) is a pretty unsafe process:
 *  - parse_url() can easily trip up on malformed or weird URLs
 *  - exploding a URL with parse_url(), lowercasing some stuff, and glueing things back with http_build_url() does not handle well
 *    "stuff:"-like URI [1] and can result in URLs ending modified [2][3]. We don't want to *validate* URI, we just want to lowercase
 *    what is supposed to be lowercased.
 *
 * So, to be conservative, this functions:
 *  - lowercases the scheme
 *  - does not lowercase anything else on "stuff:" URI
 *  - tries to lowercase only scheme and domain of "stuff://" URI
 *
 * [1] http_build_url(parse_url("mailto:ozh")) == "mailto:///ozh"
 * [2] http_build_url(parse_url("http://blah#omg")) == "http://blah/#omg"
 * [3] http_build_url(parse_url("http://blah?#")) == "http://blah/"
 *
 * @since 1.7.1
 * @param string $url URL
 * @return string URL with lowercase scheme and protocol
 */
function yourls_lowercase_scheme_domain($url)
{
    $scheme = yourls_get_protocol($url);
    if ('' == $scheme) {
        // Scheme not found, malformed URL? Something else? Not sure.
        return $url;
    }
    // Case 1 : scheme like "stuff://" (eg "http://example.com/" or "ssh://joe@joe.com")
    if (substr($scheme, -2, 2) == '//') {
        $parts = parse_url($url);
        // Most likely malformed stuff, could not parse : we'll just lowercase the scheme and leave the rest untouched
        if (false == $parts) {
            $url = str_replace($scheme, strtolower($scheme), $url);
            // URL seems parsable, let's do the best we can
        } else {
            $lower = array();
            $lower['scheme'] = strtolower($parts['scheme']);
            if (isset($parts['host'])) {
                $lower['host'] = strtolower($parts['host']);
            } else {
                $parts['host'] = '***';
            }
            // We're not going to glue back things that could be modified in the process
            unset($parts['path']);
            unset($parts['query']);
            unset($parts['fragment']);
            // original beginning of the URL and its lowercase-where-needed counterpart
            // We trim the / after the domain to avoid avoid "http://example.com" being reconstructed as "http://example.com/"
            $partial_original_url = trim(http_build_url($parts), '/');
            $partial_lower_original_url = trim(http_build_url($parts, $lower), '/');
            $url = str_replace($partial_original_url, $partial_lower_original_url, $url);
        }
        // Case 2 : scheme like "stuff:" (eg "mailto:joe@joe.com" or "bitcoin:15p1o8vnWqNkJBJGgwafNgR1GCCd6EGtQR?amount=1&label=Ozh")
        // In this case, we only lowercase the scheme, because depending on it, things after should or should not be lowercased
    } else {
        $url = str_replace($scheme, strtolower($scheme), $url);
    }
    return $url;
}
Example #8
0
/**
 * Checks and cleans a URL before printing it. Stolen from WP.
 *
 * A number of characters are removed from the URL. If the URL is for displaying
 * (the default behaviour) ampersands are also replaced.
 *
 * @since 1.6
 *
 * @param string $url The URL to be cleaned.
 * @param string $context 'display' or something else. Use yourls_sanitize_url() for database or redirection usage.
 * @param array $protocols Optional. Array of allowed protocols, defaults to global $yourls_allowedprotocols
 * @return string The cleaned $url
 */
function yourls_esc_url($url, $context = 'display', $protocols = array())
{
    // make sure there's only one 'http://' at the beginning (prevents pasting a URL right after the default 'http://')
    $url = str_replace(array('http://*****:*****@$\\|*\'()\\x80-\\xff]|i', '', $url);
    // Previous regexp in YOURLS was '|[^a-z0-9-~+_.?\[\]\^#=!&;,/:%@$\|*`\'<>"()\\x80-\\xff\{\}]|i'
    // TODO: check if that was it too destructive
    $strip = array('%0d', '%0a', '%0D', '%0A');
    $url = yourls_deep_replace($strip, $url);
    $url = str_replace(';//', '://', $url);
    // Replace ampersands and single quotes only when displaying.
    if ('display' == $context) {
        $url = yourls_kses_normalize_entities($url);
        $url = str_replace('&amp;', '&#038;', $url);
        $url = str_replace("'", '&#039;', $url);
    }
    if (!is_array($protocols) or !$protocols) {
        global $yourls_allowedprotocols;
        $protocols = yourls_apply_filter('esc_url_protocols', $yourls_allowedprotocols);
        // Note: $yourls_allowedprotocols is also globally filterable in functions-kses.php/yourls_kses_init()
    }
    if (!yourls_is_allowed_protocol($url, $protocols)) {
        return '';
    }
    // I didn't use KSES function kses_bad_protocol() because it doesn't work the way I liked (returns //blah from illegal://blah)
    $url = substr($url, 0, 1999);
    return yourls_apply_filter('esc_url', $url, $original_url, $context);
}
Example #9
0
/**
 * Check if a URL protocol is allowed
 *
 * Checks a URL against a list of whitelisted protocols. Protocols must be defined with
 * their complete scheme name, ie 'stuff:' or 'stuff://' (for instance, 'mailto:' is a valid
 * protocol, 'mailto://' isn't, and 'http:' with no double slashed isn't either
 *
 * @since 1.6
 *
 * @param string $url URL to be check
 * @param array $protocols Optional. Array of protocols, defaults to global $yourls_allowedprotocols
 * @return boolean true if protocol allowed, false otherwise
 */
function yourls_is_allowed_protocol($url, $protocols = array())
{
    if (!$protocols) {
        global $yourls_allowedprotocols;
        $protocols = $yourls_allowedprotocols;
    }
    $protocol = yourls_get_protocol($url);
    return yourls_apply_filter('is_allowed_protocol', in_array($protocol, $protocols), $url, $protocols);
}