[19 lines collapsed] define( 'MARKETEROS_SECURITY_BROKER_OPTION', 'marketeros_security_broker' ); } if ( ! defined( 'MARKETEROS_SECURITY_VERSION' ) ) { define( 'MARKETEROS_SECURITY_VERSION', '1.3.2' ); define( 'MARKETEROS_SECURITY_VERSION', '1.3.3' ); } if ( ! defined( 'MARKETEROS_SECURITY_ZOHO_LEGACY_ROOT_ID' ) ) { define( 'MARKETEROS_SECURITY_ZOHO_LEGACY_ROOT_ID', '7dih74ce67fc4a20e41edba921f169a5f92e9' ); [326 lines collapsed] running=true;$btn.prop('disabled',true);$status.text(' Iniciando…'); var state={archive:archive}; function step(){ $.post(ajaxUrl,{action:'marketeros_zoho_upload_backup',_ajax_nonce:nonce,archive:state.archive,zoho_upload_id:state.zoho_upload_id||'',zoho_upload_offset:state.zoho_upload_offset||0,zoho_folder_id:state.zoho_folder_id||'',zoho_stream_only:state.zoho_stream_only||0,zoho_overwrite:1}).done(function(res){ $.post(ajaxUrl,{action:'marketeros_zoho_upload_backup',_ajax_nonce:nonce,archive:state.archive,zoho_upload_id:state.zoho_upload_id||'',zoho_upload_offset:state.zoho_upload_offset||0,zoho_folder_id:state.zoho_folder_id||'',zoho_session:state.zoho_session||0,zoho_stream_only:state.zoho_stream_only||0,zoho_overwrite:1}).done(function(res){ if(!res||!res.success){$status.text(' '+(res&&res.data&&res.data.message?res.data.message:'No se pudo subir.'));running=false;$btn.prop('disabled',false);return;} if(res.data.params){$.extend(state,res.data.params);} $status.text(' '+(res.data.message||'')); [441 lines collapsed] return ( '' !== $region && $region !== $api_host ) ? $region : 'com'; } function marketeros_security_zoho_upload_session_id( $data ) { if ( ! is_array( $data ) ) { return ''; } foreach ( array( 'upload_id', 'upload-id', 'uploadId' ) as $key ) { if ( ! empty( $data[ $key ] ) && is_scalar( $data[ $key ] ) ) { return sanitize_text_field( (string) $data[ $key ] ); } } foreach ( $data as $value ) { $id = marketeros_security_zoho_upload_session_id( $value ); if ( '' !== $id ) { return $id; } } return ''; } function marketeros_security_zoho_create_upload_session( $settings, $token, $filename, $file_size, $parent_id ) { $attempts = array( array( 'filename' => $filename, 'parent_id' => $parent_id, 'filesize' => $file_size, 'override-name-exist' => 'true' ), array( 'filename' => $filename, 'parent_id' => $parent_id, 'size' => $file_size, 'override-name-exist' => 'true' ), array( 'file_name' => $filename, 'parent_id' => $parent_id, 'file_size' => $file_size, 'override-name-exist' => 'true' ), ); foreach ( $attempts as $query ) { $url = untrailingslashit( $settings['zoho_api_domain'] ) . '/workdrive/api/v1/uploadsession/create?' . http_build_query( $query, '', '&', PHP_QUERY_RFC3986 ); $response = wp_remote_post( $url, array( 'timeout' => 30, 'headers' => array( 'Authorization' => marketeros_security_zoho_auth_header( $token ), 'User-Agent' => 'Marketeros-WorkDrive/' . MARKETEROS_SECURITY_VERSION, ), ) ); $code = is_wp_error( $response ) ? 0 : (int) wp_remote_retrieve_response_code( $response ); $data = is_wp_error( $response ) ? array() : json_decode( wp_remote_retrieve_body( $response ), true ); $id = marketeros_security_zoho_upload_session_id( $data ); if ( $id && $code >= 200 && $code < 300 ) { return $id; } } return ''; } function marketeros_security_local_wpress_backups() { if ( ! defined( 'AI1WM_BACKUPS_PATH' ) || ! is_dir( AI1WM_BACKUPS_PATH ) ) { return array(); [34 lines collapsed] 'zoho_upload_id' => (string) ( $params['zoho_upload_id'] ?? '' ), 'zoho_upload_offset' => (int) ( $params['zoho_upload_offset'] ?? 0 ), 'zoho_folder_id' => (string) ( $params['zoho_folder_id'] ?? '' ), 'zoho_session' => ! empty( $params['zoho_session'] ), 'zoho_stream_only' => ! empty( $params['zoho_stream_only'] ), ), DAY_IN_SECONDS [29 lines collapsed] throw new Ai1wm_Import_Exception( $token->get_error_message() ); } // ponytail: 8MB stays under typical host body limits; bump if WorkDrive starts rejecting small chunks. $chunk_size = 8 * 1024 * 1024; if ( empty( $params['zoho_upload_id'] ) ) { $saved = get_transient( marketeros_security_zoho_upload_state_key( $filename, $file_size ) ); if ( is_array( $saved ) && ! empty( $saved['zoho_upload_id'] ) ) { $params['zoho_folder_id'] = (string) ( $saved['zoho_folder_id'] ?? ( $params['zoho_folder_id'] ?? '' ) ); $params['zoho_upload_id'] = (string) $saved['zoho_upload_id']; $params['zoho_upload_offset'] = (int) ( $saved['zoho_upload_offset'] ?? 0 ); $params['zoho_session'] = ! empty( $saved['zoho_session'] ); } } if ( empty( $params['zoho_folder_id'] ) ) { $folder_id = marketeros_security_zoho_domain_folder_id( $settings, $token ); if ( is_wp_error( $folder_id ) ) { [2 lines collapsed] $params['zoho_folder_id'] = $folder_id; } $params['zoho_upload_id'] = wp_generate_uuid4(); $params['zoho_upload_offset'] = 0; delete_transient( marketeros_security_zoho_upload_state_key( $filename, $file_size ) ); if ( empty( $params['zoho_upload_id'] ) ) { $session = marketeros_security_zoho_create_upload_session( $settings, $token, $filename, $file_size, $params['zoho_folder_id'] ); if ( $session ) { $params['zoho_upload_id'] = $session; $params['zoho_session'] = true; $params['zoho_upload_offset'] = 0; } elseif ( $file_size > $chunk_size ) { throw new Ai1wm_Import_Exception( 'Zoho no creó una sesión de subida por partes. Un backup de ' . size_format( $file_size ) . ' no cabe en una sola petición.' ); } else { $params['zoho_upload_id'] = wp_generate_uuid4(); $params['zoho_session'] = false; $params['zoho_upload_offset'] = 0; } } $params['zoho_session'] = ! empty( $params['zoho_session'] ) || 0 === strpos( (string) $params['zoho_upload_id'], 'CFU_' ); $handle = fopen( $path, 'rb' ); if ( false === $handle ) { [2 lines collapsed] ignore_user_abort( true ); set_time_limit( 0 ); // ponytail: rclone posts the whole file; Content-Range on stream/upload returns HTTP 410 D9234. $offset = 0; $current_size = $file_size; $code = 200; $result = ''; $curl_error = ''; $retries = 0; $reset_try = 0; $endpoint = 'https://upload.zoho.' . marketeros_security_zoho_upload_region( $settings ) . '/workdrive-api/v1/stream/upload'; $offset = (int) ( $params['zoho_upload_offset'] ?? 0 ); $start = microtime( true ); $timeout = (int) apply_filters( 'ai1wm_completed_timeout', 10 ); $retries = 0; $empty_try = 0; $reset_try = 0; $endpoint = 'https://upload.zoho.' . marketeros_security_zoho_upload_region( $settings ) . '/workdrive-api/v1/stream/upload'; while ( $offset < $file_size ) { if ( 0 !== fseek( $handle, 0, SEEK_SET ) ) { $current_size = min( $chunk_size, $file_size - $offset ); if ( 0 !== fseek( $handle, $offset, SEEK_SET ) ) { fclose( $handle ); throw new Ai1wm_Import_Exception( 'No se pudo posicionar el archivo de respaldo.' ); throw new Ai1wm_Import_Exception( 'No se pudo posicionar el archivo en el bloque pendiente.' ); } $params['zoho_upload_id'] = wp_generate_uuid4(); $chunk = fread( $handle, $current_size ); if ( false === $chunk || strlen( $chunk ) !== $current_size ) { fclose( $handle ); throw new Ai1wm_Import_Exception( 'No se pudo leer el bloque pendiente del backup.' ); } $headers = array( 'Authorization: Zoho-oauthtoken ' . $token, 'Content-Type: application/octet-stream', [3 lines collapsed] 'x-parent_id: ' . $params['zoho_folder_id'], 'x-override-name-exist: true', 'Content-Length: ' . $current_size, 'Expect:', ); if ( ! empty( $params['zoho_session'] ) ) { $headers[] = 'Content-Range: bytes ' . $offset . '-' . ( $offset + $current_size - 1 ) . '/' . $file_size; } $curl = curl_init( $endpoint ); curl_setopt_array( $curl, array( CURLOPT_CUSTOMREQUEST => 'POST',