include(config.m4)dnl #!__CMD_AWK__ -f # __CGIPATH__/search # # Show search results include(src/config.awk) incl(src/api.awk) incl(src/cgi.awk) incl(src/util.awk) function main(search, cmd, count, creator, descr, field, fields, i, iaout, id, item, items, jsout, label, numfound, order, order_names, out, page, rows, searchstr, sel, sort_param, str, title, type, url) { out = "" order_names["addeddate"] = "addeddate" order_names["collection_size"] = "collection_size" order_names["createddate"] = "createddate" order_names["creator"] = "creatorSorter" order_names["date"] = "date" order_names["downloads"] = "downloads" order_names["nav_order"] = "nav_order" order_names["random"] = "random" order_names["title"] = "titleSorter" order_names["week"] = "week" rows = 15 page = 1 order = "" # parse out page number and sort orders numfound = 1 while (numfound == 1) { if (match(search, /\/rows[0-9][0-9]*$/)) { rows = substr(search, RSTART + 5) search = substr(search, 1, RSTART - 1) } else if (match(search, /\/page[0-9][0-9]*$/)) { page = substr(search, RSTART + 5) search = substr(search, 1, RSTART - 1) } else if (match(search, /\/sort[^\/]*$/)) { if (length(order) == 0) { sort_param = substr(search, RSTART + 1) order = substr(sort_param, 5) } search = substr(search, 1, RSTART - 1) } else { numfound = 0 } } iaout = gettemp() jsout = gettemp() # special case for when the search term is an archive.org details URL if (match(search, /^https:\/\/(www\.)?archive\.org\/details\//)) { id = substr(search, RLENGTH + 1) search = "identifier:" id } # special case to list similar items if (match(search, /^similar:/)) { id = substr(search, RLENGTH + 1) url = api_endpoint "/details/" id "?RelatedItemsGet=1" api_request(url, "GET", iaout) # scrape similar items FS = "\t" items = 0 delete item str = "" while ((getline 0) { if (match($0, /iaout close(iaout) for (i = 1; i <= items; i++) { if (i == 1) { search = "identifier:" item[i] } else { search = search "%20OR%20identifier:" item[i] } } } # remove quotes from search string, since it gets quoted later gsub(/"/, "", search) # default sort orders if none were specified if (length(order) == 0) { if (search == "mediatype:collection" || search == "mediatype:(collection)") { order = "collection_size desc" sort_param = "sort" order } else { order = "nav_order desc" sort_param = "sort" order } } # get search results field[1] = "creator" field[2] = "description" field[3] = "identifier" field[4] = "mediatype" field[5] = "title" fields = 5 # remove anyfield, a hobgoblin of consistency searchstr = search gsub(/anyfield:/, "", searchstr) url = sprintf("%s/advancedsearch.php?q=%s&output=json&rows=%d&page=%d", api_endpoint, searchstr, rows, page) if (length(order) > 0) { split(order, parts, " ") url = url sprintf("&sort%%5B0%%5D=%s %s", order_names[parts[1]], parts[2]) } for (i = 1; i <= fields; i++) { url = url sprintf("&fl%%5B%d%%5D=%s", i - 1, field[i]) } api_request(url, "GET", iaout) cmd = sprintf("%s <%s >%s 2>&1", cmd_json2tsv, iaout, jsout) system(cmd) numfound = 0 FS = "\t" while ((getline 0) { if ($1 == ".response.numFound" && $2 == "n") { numfound = $3 } } close(jsout) if (search ~ /^@/) { numfound++ } if (numfound == 0) { info(out, "Your search did not match any items in the Archive.") info(out, "Try different keywords or a more general search.") info(out, "") item(out, "1", "PHAROS", docpath, server, port) unlink(jsout) unlink(iaout) return } else { pages = int(numfound / rows) if (numfound % rows != 0) { pages++ } info(out, sprintf("# %s search results, page %d of %d", numfound, page, pages)) info(out, "") } # format search results as a gopher directory (menu) FS = "\t" creator = "" descr = "" id = "" title = "" type = "" count = 0 if (search ~ /^@/) { sel = cgipath "/account?" search item(out, "1", "Account " search, sel, server, port) } while ((getline 0) { if ($1 == ".response.docs[].creator" && $2 == "s") { creator = $3 } else if ($1 == ".response.docs[].description" && $2 == "s") { descr = $3 } else if ($1 == ".response.docs[].identifier" && $2 == "s") { id = $3 } else if ($1 == ".response.docs[].mediatype" && $2 == "s") { type = $3 } else if ($1 == ".response.docs[].title" && $2 == "s") { # the title field happens to be toward the end of each item title = $3 count++ if (length(creator) > 0) { label = sprintf("[%s] %s by %s", mediatype[type], shorten(title, 40), shorten(creator, 18)) } else { label = sprintf("[%s] %s", mediatype[type], shorten(title, 58)) } if (type == "collection") { sel = sprintf("%s/search?collection:(%s)", cgipath, id) item(out, "1", label, sel, server, port) } else { sel = cgipath "/details?" id item(out, "1", label, sel, server, port) } creator = "" descr = "" id = "" type = "" } } close(jsout) info(out, "") # only show "page back" if the user is past page 1 if (page > 1) { label = sprintf("[<<] Page %d", page - 1) sel = sprintf("%s/search?%s/page%d/rows%d/%s", cgipath, search, page - 1, rows, sort_param) item(out, "1", label, sel, server, port) } # only show "next page" if the current page is completely full if (count == rows) { label = sprintf("1[>>] Page %d", page + 1) sel = sprintf("%s/search?%s/page%d/rows%d/%s", cgipath, search, page + 1, rows, sort_param) item(out, "1", label, sel, server, port) } # only show "sort" if there's more than one item to sort if (count > 1) { sel = cgipath "/sort?" search item(out, "1", "[^v] Sort", sel, server, port) } # only show "search within list" if there's multiple pages of results if (numfound > rows) { sel = cgipath "/wizard/step1?" search item(out, "1", "[\\/] Filter results", sel, server, port) } item(out, "1", "PHAROS", docpath, server, port) unlink(jsout) unlink(iaout) exit 0 } BEGIN { config_init() cgi_init() uri_encode_init() util_init() main(search) }