public String[][] search(String search, int... namespaces) throws IOException
    {
        // this varargs thing is really handy, there's no need to define a
        // separate search(String search) while allowing multiple namespaces

        // default to main namespace
        if (namespaces.length == 0)
            namespaces = new int[] { MAIN_NAMESPACE };
        StringBuilder url = new StringBuilder(query);
        url.append("action=query&list=search&srwhat=text&srprop=snippet%7Csectionsnippet&srlimit=max&srsearch=");
        url.append(URLEncoder.encode(search, "UTF-8"));
        url.append("&srnamespace=");
        for (int i = 0; i < namespaces.length; i++)
        {
            url.append(namespaces[i]);
            if (i != namespaces.length - 1)
                url.append("%7C");
        }
        url.append("&sroffset=");

        // some random variables we need later
        boolean done = false;
        ArrayList<String[]> results = new ArrayList<String[]>(5000);

        // fetch and iterate through the search results
        while (!done)
        {
            String line = fetch(url.toString() + results.size(), "search", false);

            // if this is the last page of results then there is no sroffset parameter
            if (!line.contains("sroffset=\""))
                done = true;

            // strip the search results
            // typical form: <p ns="0" title="Main Page" snippet="Blah blah blah" sectiontitle="Section"/>
            for (int x = line.indexOf(" title=\""); x >= 0; x = line.indexOf(" title=\"", x))
            {
                String[] result = new String[3];
                // title
                int a = x + 8;
                int b = line.indexOf('\"', a);
                result[0] = line.substring(a, b);

                // section title (if available). Stupid API documentation is misleading.
                if (line.contains("sectionsnippet=\""))
                {
                    a = line.indexOf("sectionsnippet=\"", x) + 16;
                    b = line.indexOf('\"', a);
                    result[1] = decode(line.substring(a, b));
                }
                else
                    result[1] = "";

                // snippet
                a = line.indexOf("snippet=\"", x) + 9;
                b = line.indexOf('\"', a);
                result[2] = decode(line.substring(a, b));
                results.add(result);
                x = a;
            }
        }
        log(Level.INFO, "Successfully searched for string \"" + search + "\" (" + results.size() + " items found)", "search");
        return results.toArray(new String[0][0]);
    }