Ejemplo n.º 1
0
Archivo: winurl.c Proyecto: rdebath/sgt
void do_launch_urls(void)
{
    HGLOBAL clipdata;
    char *s = NULL, *t = NULL, *p, *q, *r, *e;
    int len, ret, in_url = 0, n = 0;

    if (!OpenClipboard(NULL)) {
	goto error; /* unable to read clipboard */
    }
    clipdata = GetClipboardData(CF_TEXT);
    CloseClipboard();
    if (!clipdata) {
	goto error; /* clipboard contains no text */
    }
    s = GlobalLock(clipdata);
    if (!s) {
        goto error; /* unable to lock clipboard memory */
    }

    /*
     * Now strip (some) whitespace from the URL text.
     * In a future version this might be made configurable.
     */
    len = strlen(s);
    t = malloc(len+8);                 /* leading "http://" plus trailing \0 */
    if (!t) {
	GlobalUnlock(s);
	goto error;		       /* out of memory */
    }

    p = s;
    q = t;
    /* Strip leading whitespace. */
    while (p[0] && our_isspace(p[0]))
	p++;

    /* Find any newlines, and close up any white-space around them. */
    while ((r = strpbrk(p, "\r\n"))) {
	char *rr = r;
	/* Strip whitespace before newline(s) */
	while (our_isspace(rr[0]))
	    rr--;
	while (p <= rr)
	    *q++ = *p++;
	/* Strip newline(s) and following whitespace */
	p = r;
	while (p[0] && our_isspace(p[0]))
	    p++;
    }

    /* Strip any trailing whitespace */
    r = p + strlen(p);
    while (r > p && our_isspace(r[-1]))
	r--;
    while (p < r)
	*q++ = *p++;

    *q = '\0';

    GlobalUnlock(s);

    /*
     * Now we have whitespace-filtered text in t.
     * First look for <>-delimited strings per RFC3986, and try to
     * launch any we find as URLs.
     */
    q = t;
    while ((e = strpbrk(q, "<>"))) {
	switch (*e) {
	  case '<':
	    q = e+1;
	    in_url = 1;
	    break;
	  case '>':
	    if (in_url) {
		/* deal with RFC1738 <URL:...> */
		if (strncmp(q, "URL:", 4) == 0)
		    q += 4;
		/* Remove whitespace between < / <URL: / > and URL. */
		while (our_isspace(*q)) q++;
		{
		    char *ee = e-1;
		    while (our_isspace(*ee)) ee--;
		    ee[1] = '\0';
		}
		/* We may as well allow non-RFC <*****@*****.**> and
		 * indeed <URL:www.example.com>. */
		(void) launch_url(q);
		n++;
		in_url = 0;
	    }
	    q = e+1;
	    break;
	}
    }

    if (!n) {
	/* Didn't find any URLs by that method. Try parsing the string
	 * as a whole as one. */
	ret = launch_url(t);
    }

    free(t);

    error:
    /*
     * Not entirely sure what we should do in case of error here.
     * Perhaps a simple beep might be suitable. Then again, `out of
     * memory' is a bit scarier. FIXME: should probably do
     * different error handling depending on context.
     */
    ;
}
Ejemplo n.º 2
0
/* Stand alone implementation of sscanf.  We used to call libc's vsscanf while
 * trying to isolate errno (i#238), but these days sscanf calls malloc (i#762).
 * Therefore, we roll our own.
 */
int
our_vsscanf(const char *str, const char *fmt, va_list ap)
{
    int num_parsed = 0;
    const char *fp = fmt;
    const char *sp = str;
    int c;

    while (*fp != '\0' && *sp != '\0') {
        specifer_t spec = SPEC_INT;
        int_sz_t int_size = SZ_INT;
        uint base = 10;
        bool is_signed = false;
        bool is_ignored = false;
        uint width = 0;

        /* Handle literal characters and spaces up front. */
        c = *fp++;
        if (our_isspace(c)) {
            /* Space means consume any number of spaces. */
            while (our_isspace(*sp)) {
                sp++;
            }
            continue;
        } else if (c != '%') {
            /* Literal, so check mismatch. */
            if (c != *sp)
                return num_parsed;
            sp++;
            continue;
        }

        /* Parse the format specifier. */
        ASSERT(c == '%');
        while (true) {
            c = *fp++;
            switch (c) {
            /* Modifiers, should all continue the loop. */
            case 'l':
                ASSERT(int_size != SZ_LONGLONG && "too many longs");
                if (int_size == SZ_LONG)
                    int_size = SZ_LONGLONG;
                else
                    int_size = SZ_LONG;
                continue;
            case 'h':
                int_size = SZ_SHORT;
                continue;
            case '*':
                is_ignored = true;
                continue;
            case '0': case '1': case '2': case '3': case '4':
            case '5': case '6': case '7': case '8': case '9':
                /* We honor the specified width for strings to prevent buffer
                 * overruns, but we don't honor it for integers.  Honoring the
                 * width for integers would require our own integer parser.
                 */
                width = width * 10 + c - '0';
                continue;

            /* Specifiers, should all break the loop. */
            case 'u':
                spec = SPEC_INT;
                is_signed = false;
                goto spec_done;
            case 'd':
                spec = SPEC_INT;
                is_signed = true;
                goto spec_done;
            case 'x':
                spec = SPEC_INT;
                is_signed = false;
                base = 16;
                goto spec_done;
            case 'p':
                int_size = SZ_PTR;
                spec = SPEC_INT;
                is_signed = false;
                base = 16;
                goto spec_done;
            case 'c':
                spec = SPEC_CHAR;
                goto spec_done;
            case 's':
                spec = SPEC_STRING;
                goto spec_done;
            default:
                ASSERT(false && "unknown specifier");
                return num_parsed;
            }
        }
spec_done:

        /* Parse the string. */
        switch (spec) {
        case SPEC_CHAR:
            if (!is_ignored) {
                *va_arg(ap, char*) = *sp;
            }
            sp++;
            break;
        case SPEC_STRING:
            if (is_ignored) {
                while (*sp != '\0' && !our_isspace(*sp)) {
                    sp++;
                }
            } else {
                char *str_out = va_arg(ap, char*);
                if (width > 0) {
                    int i = 0;
                    while (i < width && *sp != '\0' && !our_isspace(*sp)) {
                        *str_out++ = *sp++;
                        i++;
                    }
                    /* Spec says only null terminate if we hit width. */
                    if (i < width)
                        *str_out = '\0';
                } else {
                    while (*sp != '\0' && !our_isspace(*sp)) {
                        *str_out++ = *sp++;
                    }
                    *str_out = '\0';
                }
            }
            break;
        case SPEC_INT: {
            uint64 res;
            sp = parse_int(sp, &res, base, width, is_signed);
            if (sp == NULL)
                return num_parsed;

            if (!is_ignored) {
                if (int_size == SZ_SHORT)
                    *va_arg(ap, short *) = (short)res;
                else if (int_size == SZ_INT)
                    *va_arg(ap, int *) = (int)res;
                else if (int_size == SZ_LONG)
                    *va_arg(ap, long *) = (long)res;
                else if (int_size == SZ_LONGLONG)
                    *va_arg(ap, long long *) = (long long)res;
                else
                    ASSERT_NOT_REACHED();
            }
            break;
        }
        default:
            /* Format parsing code above should return an error earlier. */
            ASSERT_NOT_REACHED();
        }

        if (!is_ignored)
            num_parsed++;
    }
    return num_parsed;
}