@@ -237,42 +237,51 @@ upload_ftp <- function(file, url, verbose = FALSE) {
237237 curl :: curl_fetch_memory(url , handle = h )
238238}
239239
240- extract_hidden_fields <- function (html_text ) {
241- extract_value <- function (name ) {
242- pattern <- sprintf(' name="%s"[^>]*value="([^"]+)"' , name )
243- match <- regexec(pattern , html_text )
244- result <- regmatches(html_text , match )
245- if (length(result [[1 ]]) > = 2 ) result [[1 ]][2 ] else NA_character_
240+ parse_winbuilder_form <- function (url , version ) {
241+ req <- httr2 :: request(url )
242+ resp <- httr2 :: req_perform(req )
243+ html <- xml2 :: read_html(httr2 :: resp_body_string(resp ))
244+
245+ # Extract hidden fields shared by the whole form
246+ hidden_nodes <- xml2 :: xml_find_all(html , " .//input[@type='hidden']" )
247+ hidden <- as.list(xml2 :: xml_attr(hidden_nodes , " value" ))
248+ names(hidden ) <- xml2 :: xml_attr(hidden_nodes , " name" )
249+
250+ # Find the <h2> heading for the requested version, then grab the file
251+ # input and submit button from the <div> that follows it
252+ headings <- xml2 :: xml_find_all(html , " .//h2" )
253+ heading_texts <- xml2 :: xml_text(headings )
254+ idx <- match(version , heading_texts )
255+ if (is.na(idx )) {
256+ cli :: cli_abort(
257+ " Could not find {.val {version}} section in the WinBuilder form."
258+ )
246259 }
247260
248- list (
249- `__VIEWSTATE` = extract_value( " __VIEWSTATE " ),
250- `__VIEWSTATEGENERATOR` = extract_value( " __VIEWSTATEGENERATOR " ),
251- `__EVENTVALIDATION` = extract_value( " __EVENTVALIDATION " )
261+ section <- xml2 :: xml_find_first( headings [[ idx ]], " following-sibling::div " )
262+ file_field <- xml2 :: xml_attr(
263+ xml2 :: xml_find_first( section , " .//input[@type='file'] " ),
264+ " name "
252265 )
266+ button_field <- xml2 :: xml_attr(
267+ xml2 :: xml_find_first(section , " .//input[@type='submit']" ),
268+ " name"
269+ )
270+
271+ list (hidden = hidden , file_field = file_field , button_field = button_field )
253272}
254273
255274upload_webform <- function (file , version ) {
256- check_installed(" httr2" )
275+ check_installed(c( " httr2" , " xml2 " ) )
257276
258277 upload_url <- " https://win-builder.r-project.org/upload.aspx"
259- req <- httr2 :: request(upload_url )
260- resp <- httr2 :: req_perform(req )
261- html_text <- httr2 :: resp_body_string(resp )
262-
263- field_map <- list (
264- " R-release" = list (file = " FileUpload1" , button = " Button1" ),
265- " R-devel" = list (file = " FileUpload2" , button = " Button2" ),
266- " R-oldrelease" = list (file = " FileUpload3" , button = " Button3" )
267- )
268-
269- fields <- field_map [[version ]]
278+ form <- parse_winbuilder_form(upload_url , version )
270279
271- hidden <- extract_hidden_fields( html_text )
272- hidden [[ fields $ file ]] <- curl :: form_file(file )
273- hidden [[ fields $ button ]] <- " Upload File"
280+ body <- form $ hidden
281+ body [[ form $ file_field ]] <- curl :: form_file(file )
282+ body [[ form $ button_field ]] <- " Upload File"
274283
275284 req <- httr2 :: request(upload_url )
276- req <- httr2 :: req_body_multipart(req , !!! hidden )
285+ req <- httr2 :: req_body_multipart(req , !!! body )
277286 httr2 :: req_perform(req )
278287}
0 commit comments