/** * @param $job_object * @return bool */ public function job_run(BackWPup_Job $job_object) { global $wpdb, $post, $wp_query; $wxr_version = '1.2'; if ($job_object->steps_data[$job_object->step_working]['SAVE_STEP_TRY'] != $job_object->steps_data[$job_object->step_working]['STEP_TRY']) { $job_object->log(sprintf(__('%d. Trying to create a WordPress export to XML file …', 'backwpup'), $job_object->steps_data[$job_object->step_working]['STEP_TRY'])); $job_object->steps_data[$job_object->step_working]['wpexportfile'] = BackWPup::get_plugin_data('TEMP') . $job_object->generate_filename($job_object->job['wpexportfile'], 'xml', TRUE); $job_object->steps_data[$job_object->step_working]['substep'] = 'header'; $job_object->steps_data[$job_object->step_working]['post_ids'] = array(); $job_object->substeps_todo = 10; $job_object->substeps_done = 0; } add_filter('wxr_export_skip_postmeta', array($this, 'wxr_filter_postmeta'), 10, 2); if ($job_object->steps_data[$job_object->step_working]['substep'] == 'header') { if ('all' != $job_object->job['wpexportcontent'] && post_type_exists($job_object->job['wpexportcontent'])) { $ptype = get_post_type_object($job_object->job['wpexportcontent']); if (!$ptype->can_export) { $job_object->log(sprintf(__('WP Export: Post type ā%sā does not allow export.', 'backwpup'), $job_object->job['wpexportcontent']), E_USER_ERROR); return FALSE; } $where = $wpdb->prepare("{$wpdb->posts}.post_type = %s", $job_object->job['wpexportcontent']); } else { $post_types = get_post_types(array('can_export' => true)); $esses = array_fill(0, count($post_types), '%s'); $where = $wpdb->prepare("{$wpdb->posts}.post_type IN (" . implode(',', $esses) . ')', $post_types); $job_object->job['wpexportcontent'] = 'all'; } $where .= " AND {$wpdb->posts}.post_status != 'auto-draft'"; // grab a snapshot of post IDs, just in case it changes during the export $job_object->steps_data[$job_object->step_working]['post_ids'] = $wpdb->get_col("SELECT ID FROM {$wpdb->posts} WHERE {$where}"); $job_object->substeps_todo = $job_object->substeps_todo + count($job_object->steps_data[$job_object->step_working]['post_ids']); $header = '<?xml version="1.0" encoding="' . get_bloginfo('charset') . "\" ?>\n"; $header .= "<!-- This is a WordPress eXtended RSS file generated by the WordPress plugin BackWPup as an export of your site. -->\n"; $header .= "<!-- It contains information about your site's posts, pages, comments, categories, and other content. -->\n"; $header .= "<!-- You may use this file to transfer that content from one site to another. -->\n"; $header .= "<!-- This file is not intended to serve as a complete backup of your site. -->\n\n"; $header .= "<!-- To import this information into a WordPress site follow these steps: -->\n"; $header .= "<!-- 1. Log in to that site as an administrator. -->\n"; $header .= "<!-- 2. Go to Tools: Import in the WordPress admin panel. -->\n"; $header .= "<!-- 3. Install the \"WordPress\" importer from the list. -->\n"; $header .= "<!-- 4. Activate & Run Importer. -->\n"; $header .= "<!-- 5. Upload this file using the form provided on that page. -->\n"; $header .= "<!-- 6. You will first be asked to map the authors in this export file to users -->\n"; $header .= "<!-- on the site. For each author, you may choose to map to an -->\n"; $header .= "<!-- existing user on the site or to create a new user. -->\n"; $header .= "<!-- 7. WordPress will then import each of the posts, pages, comments, categories, etc. -->\n"; $header .= "<!-- contained in this file into your site. -->\n\n"; $header .= "<!-- generator=\"WordPress/" . get_bloginfo_rss('version') . "\" created=\"" . date('Y-m-d H:i') . "\" -->\n"; $header .= "<rss version=\"2.0\" xmlns:excerpt=\"http://wordpress.org/export/{$wxr_version}/excerpt/\" xmlns:content=\"http://purl.org/rss/1.0/modules/content/\" xmlns:wfw=\"http://wellformedweb.org/CommentAPI/\" xmlns:dc=\"http://purl.org/dc/elements/1.1/\" xmlns:wp=\"http://wordpress.org/export/{$wxr_version}/\">\n"; $header .= "<channel>\n"; $header .= "\t<title>" . get_bloginfo_rss('name') . "</title>\n"; $header .= "\t<link>" . get_bloginfo_rss('url') . "</link>\n"; $header .= "\t<description>" . get_bloginfo_rss('description') . "</description>\n"; $header .= "\t<pubDate>" . date('D, d M Y H:i:s +0000') . "</pubDate>\n"; $header .= "\t<language>" . get_bloginfo_rss('language') . "</language>\n"; $header .= "\t<wp:wxr_version>" . $wxr_version . "</wp:wxr_version>\n"; $header .= "\t<wp:base_site_url>" . $this->wxr_site_url() . "</wp:base_site_url>\n"; $header .= "\t<wp:base_blog_url>" . get_bloginfo_rss('url') . "</wp:base_blog_url>\n"; $written = file_put_contents($job_object->steps_data[$job_object->step_working]['wpexportfile'], $header, FILE_APPEND); if ($written === FALSE) { $job_object->log(__('WP Export file could not written.', 'backwpup'), E_USER_ERROR); return FALSE; } unset($header); $job_object->steps_data[$job_object->step_working]['substep'] = 'authors'; $job_object->substeps_done++; $job_object->update_working_data(); $job_object->do_restart_time(); } if ($job_object->steps_data[$job_object->step_working]['substep'] == 'authors') { $written = file_put_contents($job_object->steps_data[$job_object->step_working]['wpexportfile'], $this->wxr_authors_list(), FILE_APPEND); if ($written === FALSE) { $job_object->log(__('WP Export file could not written.', 'backwpup'), E_USER_ERROR); return FALSE; } $job_object->steps_data[$job_object->step_working]['substep'] = 'cats'; $job_object->substeps_done++; $job_object->update_working_data(); $job_object->do_restart_time(); } if ($job_object->steps_data[$job_object->step_working]['substep'] == 'cats') { if ('all' == $job_object->job['wpexportcontent']) { $cats = array(); $categories = (array) get_categories(array('get' => 'all')); // put categories in order with no child going before its parent while ($cat = array_shift($categories)) { if ($cat->parent == 0 || isset($cats[$cat->parent])) { $cats[$cat->term_id] = $cat; } else { $categories[] = $cat; } } $cats_xml = ''; foreach ($cats as $c) { $parent_slug = $c->parent ? $cats[$c->parent]->slug : ''; $cats_xml .= "\t<wp:category><wp:term_id>" . $c->term_id . "</wp:term_id><wp:category_nicename>" . $c->slug . "</wp:category_nicename><wp:category_parent>" . $parent_slug . "</wp:category_parent>" . $this->wxr_cat_name($c) . $this->wxr_category_description($c) . "</wp:category>\n"; } $written = file_put_contents($job_object->steps_data[$job_object->step_working]['wpexportfile'], $cats_xml, FILE_APPEND); if ($written === FALSE) { $job_object->log(__('WP Export file could not written.', 'backwpup'), E_USER_ERROR); return FALSE; } unset($cats_xml); } $job_object->steps_data[$job_object->step_working]['substep'] = 'tags'; $job_object->substeps_done++; $job_object->update_working_data(); $job_object->do_restart_time(); } if ($job_object->steps_data[$job_object->step_working]['substep'] == 'tags') { if ('all' == $job_object->job['wpexportcontent']) { $tags = (array) get_tags(array('get' => 'all')); $tags_xml = ''; foreach ($tags as $t) { $tags_xml .= "\t<wp:tag><wp:term_id>" . $t->term_id . "</wp:term_id><wp:tag_slug>" . $t->slug . "</wp:tag_slug>" . $this->wxr_tag_name($t) . $this->wxr_tag_description($t) . "</wp:tag>\n"; } $written = file_put_contents($job_object->steps_data[$job_object->step_working]['wpexportfile'], $tags_xml, FILE_APPEND); if ($written === FALSE) { $job_object->log(__('WP Export file could not written.', 'backwpup'), E_USER_ERROR); return FALSE; } unset($tags_xml); } $job_object->steps_data[$job_object->step_working]['substep'] = 'terms'; $job_object->substeps_done++; $job_object->update_working_data(); $job_object->do_restart_time(); } if ($job_object->steps_data[$job_object->step_working]['substep'] == 'terms') { if ('all' == $job_object->job['wpexportcontent']) { $terms = array(); $custom_taxonomies = get_taxonomies(array('_builtin' => false)); $custom_terms = (array) get_terms($custom_taxonomies, array('get' => 'all')); // put terms in order with no child going before its parent while ($t = array_shift($custom_terms)) { if ($t->parent == 0 || isset($terms[$t->parent])) { $terms[$t->term_id] = $t; } else { $custom_terms[] = $t; } } $terms_xml = ''; foreach ($terms as $t) { $parent_slug = $t->parent ? $terms[$t->parent]->slug : ''; $terms_xml .= "\t<wp:term><wp:term_id>" . $t->term_id . "</wp:term_id><wp:term_taxonomy>" . $t->taxonomy . "</wp:term_taxonomy><wp:term_slug>" . $t->slug . "</wp:term_slug><wp:term_parent>" . $parent_slug . "</wp:term_parent>" . $this->wxr_term_name($t) . $this->wxr_term_description($t) . "</wp:term>\n"; } $written = file_put_contents($job_object->steps_data[$job_object->step_working]['wpexportfile'], $terms_xml, FILE_APPEND); if ($written === FALSE) { $job_object->log(__('WP Export file could not written.', 'backwpup'), E_USER_ERROR); return FALSE; } unset($terms_xml); } $job_object->steps_data[$job_object->step_working]['substep'] = 'menus'; $job_object->substeps_done++; $job_object->update_working_data(); $job_object->do_restart_time(); } if ($job_object->steps_data[$job_object->step_working]['substep'] == 'menus') { $menu_xml = ''; if ('all' == $job_object->job['wpexportcontent']) { $menu_xml .= $this->wxr_nav_menu_terms(); } $menu_xml .= "\t<generator>http://wordpress.org/?v=" . get_bloginfo_rss('version') . "</generator>\n"; $written = file_put_contents($job_object->steps_data[$job_object->step_working]['wpexportfile'], $menu_xml, FILE_APPEND); if ($written === FALSE) { $job_object->log(__('WP Export file could not written.', 'backwpup'), E_USER_ERROR); return FALSE; } unset($menu_xml); $job_object->steps_data[$job_object->step_working]['substep'] = 'posts'; $job_object->substeps_done++; $job_object->update_working_data(); $job_object->do_restart_time(); } if ($job_object->steps_data[$job_object->step_working]['substep'] == 'posts') { if (!empty($job_object->steps_data[$job_object->step_working]['post_ids'])) { $wp_query->in_the_loop = true; // Fake being in the loop. // fetch 20 posts at a time rather than loading the entire table into memory while ($next_posts = array_splice($job_object->steps_data[$job_object->step_working]['post_ids'], 0, 20)) { $where = 'WHERE ID IN (' . join(',', $next_posts) . ')'; $posts = $wpdb->get_results("SELECT * FROM {$wpdb->posts} {$where}"); $wxr_post = ''; // Begin Loop foreach ($posts as $post) { /* @var WP_Post $post */ $is_sticky = is_sticky($post->ID) ? 1 : 0; $wxr_post .= "\t<item>\n"; $wxr_post .= "\t\t<title>" . apply_filters('the_title_rss', $post->post_title) . "</title>\n"; $wxr_post .= "\t\t<link>" . esc_url(apply_filters('the_permalink_rss', get_permalink($post))) . "</link>\n"; $wxr_post .= "\t\t<pubDate>" . mysql2date('D, d M Y H:i:s +0000', get_post_time('Y-m-d H:i:s', true, $post), false) . "</pubDate>\n"; $wxr_post .= "\t\t<dc:creator>" . $this->wxr_cdata(get_the_author_meta('login', $post->post_author)) . "</dc:creator>\n"; $wxr_post .= "\t\t<guid isPermaLink=\"false\">" . esc_url(get_the_guid($post->ID)) . "</guid>\n"; $wxr_post .= "\t\t<description></description>\n"; $wxr_post .= "\t\t<content:encoded>" . $this->wxr_cdata(apply_filters('the_content_export', $post->post_content)) . "</content:encoded>\n"; $wxr_post .= "\t\t<excerpt:encoded>" . $this->wxr_cdata(apply_filters('the_excerpt_export', $post->post_excerpt)) . "</excerpt:encoded>\n"; $wxr_post .= "\t\t<wp:post_id>" . $post->ID . "</wp:post_id>\n"; $wxr_post .= "\t\t<wp:post_date>" . $post->post_date . "</wp:post_date>\n"; $wxr_post .= "\t\t<wp:post_date_gmt>" . $post->post_date_gmt . "</wp:post_date_gmt>\n"; $wxr_post .= "\t\t<wp:comment_status>" . $post->comment_status . "</wp:comment_status>\n"; $wxr_post .= "\t\t<wp:ping_status>" . $post->ping_status . "</wp:ping_status>\n"; $wxr_post .= "\t\t<wp:post_name>" . $post->post_name . "</wp:post_name>\n"; $wxr_post .= "\t\t<wp:status>" . $post->post_status . "</wp:status>\n"; $wxr_post .= "\t\t<wp:post_parent>" . $post->post_parent . "</wp:post_parent>\n"; $wxr_post .= "\t\t<wp:menu_order>" . $post->menu_order . "</wp:menu_order>\n"; $wxr_post .= "\t\t<wp:post_type>" . $post->post_type . "</wp:post_type>\n"; $wxr_post .= "\t\t<wp:post_password>" . $post->post_password . "</wp:post_password>\n"; $wxr_post .= "\t\t<wp:is_sticky>" . $is_sticky . "</wp:is_sticky>\n"; if ($post->post_type == 'attachment') { $wxr_post .= "\t\t<wp:attachment_url>" . wp_get_attachment_url($post->ID) . "</wp:attachment_url>\n"; } $wxr_post .= $this->wxr_post_taxonomy(); $postmeta = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->postmeta} WHERE post_id = %d", $post->ID)); foreach ($postmeta as $meta) { if (apply_filters('wxr_export_skip_postmeta', false, $meta->meta_key, $meta)) { continue; } $wxr_post .= "\t\t<wp:postmeta>\n\t\t\t<wp:meta_key>" . $meta->meta_key . "</wp:meta_key>\n\t\t\t<wp:meta_value>" . $this->wxr_cdata($meta->meta_value) . "</wp:meta_value>\n\t\t</wp:postmeta>\n"; } $comments = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->comments} WHERE comment_post_ID = %d AND comment_approved <> 'spam'", $post->ID)); foreach ($comments as $c) { $wxr_post .= "\t\t<wp:comment>\n"; $wxr_post .= "\t\t\t<wp:comment_id>" . $c->comment_ID . "</wp:comment_id>\n"; $wxr_post .= "\t\t\t<wp:comment_author>" . $this->wxr_cdata($c->comment_author) . "</wp:comment_author>\n"; $wxr_post .= "\t\t\t<wp:comment_author_email>" . $c->comment_author_email . "</wp:comment_author_email>\n"; $wxr_post .= "\t\t\t<wp:comment_author_url>" . esc_url_raw($c->comment_author_url) . "</wp:comment_author_url>\n"; $wxr_post .= "\t\t\t<wp:comment_author_IP>" . $c->comment_author_IP . "</wp:comment_author_IP>\n"; $wxr_post .= "\t\t\t<wp:comment_date>" . $c->comment_date . "</wp:comment_date>\n"; $wxr_post .= "\t\t\t<wp:comment_date_gmt>" . $c->comment_date_gmt . "</wp:comment_date_gmt>\n"; $wxr_post .= "\t\t\t<wp:comment_content>" . $this->wxr_cdata($c->comment_content) . "</wp:comment_content>\n"; $wxr_post .= "\t\t\t<wp:comment_approved>" . $c->comment_approved . "</wp:comment_approved>\n"; $wxr_post .= "\t\t\t<wp:comment_type>" . $c->comment_type . "</wp:comment_type>\n"; $wxr_post .= "\t\t\t<wp:comment_parent>" . $c->comment_parent . "</wp:comment_parent>\n"; $wxr_post .= "\t\t\t<wp:comment_user_id>" . $c->user_id . "</wp:comment_user_id>\n"; $c_meta = $wpdb->get_results($wpdb->prepare("SELECT * FROM {$wpdb->commentmeta} WHERE comment_id = %d", $c->comment_ID)); foreach ($c_meta as $meta) { $wxr_post .= "\t\t\t<wp:commentmeta>\n\t\t\t\t<wp:meta_key>" . $meta->meta_key . "</wp:meta_key>\n\t\t\t\t<wp:meta_value>" . $this->wxr_cdata($meta->meta_value) . "</wp:meta_value>\n\t\t\t</wp:commentmeta>\n"; } $wxr_post .= "\t\t</wp:comment>\n"; } $wxr_post .= "\t</item>\n"; $job_object->substeps_done++; } $written = file_put_contents($job_object->steps_data[$job_object->step_working]['wpexportfile'], $wxr_post, FILE_APPEND); if ($written === FALSE) { $job_object->log(__('WP Export file could not written.', 'backwpup'), E_USER_ERROR); return FALSE; } $job_object->do_restart_time(); } } $written = file_put_contents($job_object->steps_data[$job_object->step_working]['wpexportfile'], "</channel>\n</rss>", FILE_APPEND); if ($written === FALSE) { $job_object->log(__('WP Export file could not written.', 'backwpup'), E_USER_ERROR); return FALSE; } $job_object->steps_data[$job_object->step_working]['substep'] = 'check'; $job_object->substeps_done++; $job_object->update_working_data(); $job_object->do_restart_time(); } remove_filter('wxr_export_skip_postmeta', array($this, 'wxr_filter_postmeta'), 10); if ($job_object->steps_data[$job_object->step_working]['substep'] == 'check') { if (extension_loaded('simplexml') && class_exists('DOMDocument')) { $job_object->log(__('Check WP Export file …', 'backwpup')); $job_object->need_free_memory(filesize($job_object->steps_data[$job_object->step_working]['wpexportfile']) * 2); $valid = TRUE; $internal_errors = libxml_use_internal_errors(TRUE); $dom = new DOMDocument(); $old_value = NULL; if (function_exists('libxml_disable_entity_loader')) { $old_value = libxml_disable_entity_loader(TRUE); } $success = $dom->loadXML(file_get_contents($job_object->steps_data[$job_object->step_working]['wpexportfile'])); if (!is_null($old_value)) { libxml_disable_entity_loader($old_value); } if (!$success || isset($dom->doctype)) { $errors = libxml_get_errors(); $valid = FALSE; foreach ($errors as $error) { switch ($error->level) { case LIBXML_ERR_WARNING: $job_object->log(E_USER_WARNING, sprintf(__('XML WARNING (%s): %s', 'backwpup'), $error->code, trim($error->message)), $job_object->steps_data[$job_object->step_working]['wpexportfile'], $error->line); break; case LIBXML_ERR_ERROR: $job_object->log(E_USER_WARNING, sprintf(__('XML RECOVERABLE (%s): %s', 'backwpup'), $error->code, trim($error->message)), $job_object->steps_data[$job_object->step_working]['wpexportfile'], $error->line); break; case LIBXML_ERR_FATAL: $job_object->log(E_USER_WARNING, sprintf(__('XML ERROR (%s): %s', 'backwpup'), $error->code, trim($error->message)), $job_object->steps_data[$job_object->step_working]['wpexportfile'], $error->line); break; } } } else { $xml = simplexml_import_dom($dom); unset($dom); // halt if loading produces an error if (!$xml) { $job_object->log(__('There was an error when reading this WXR file', 'backwpup'), E_USER_ERROR); $valid = FALSE; } else { $wxr_version = $xml->xpath('/rss/channel/wp:wxr_version'); if (!$wxr_version) { $job_object->log(__('This does not appear to be a WXR file, missing/invalid WXR version number', 'backwpup'), E_USER_ERROR); $valid = FALSE; } $wxr_version = (string) trim($wxr_version[0]); // confirm that we are dealing with the correct file format if (!preg_match('/^\\d+\\.\\d+$/', $wxr_version)) { $job_object->log(__('This does not appear to be a WXR file, missing/invalid WXR version number', 'backwpup'), E_USER_ERROR); $valid = FALSE; } } } libxml_use_internal_errors($internal_errors); if ($valid) { $job_object->log(__('WP Export file is a valid WXR file.', 'backwpup')); } } else { $job_object->log(__('WP Export file can not be checked, because no XML extension is loaded, to ensure the file verification.', 'backwpup')); } $job_object->steps_data[$job_object->step_working]['substep'] = 'compress'; $job_object->substeps_done++; $job_object->update_working_data(); $job_object->do_restart_time(); } //Compress file if ($job_object->steps_data[$job_object->step_working]['substep'] == 'compress') { if (!empty($job_object->job['wpexportfilecompression'])) { $job_object->log(__('Compressing file …', 'backwpup')); try { $compress = new BackWPup_Create_Archive($job_object->steps_data[$job_object->step_working]['wpexportfile'] . $job_object->job['wpexportfilecompression']); if ($compress->add_file($job_object->steps_data[$job_object->step_working]['wpexportfile'])) { unset($compress); unlink($job_object->steps_data[$job_object->step_working]['wpexportfile']); $job_object->steps_data[$job_object->step_working]['wpexportfile'] .= $job_object->job['wpexportfilecompression']; $job_object->log(__('Compressing done.', 'backwpup')); } } catch (Exception $e) { $job_object->log($e->getMessage(), E_USER_ERROR, $e->getFile(), $e->getLine()); unset($compress); return FALSE; } } $job_object->steps_data[$job_object->step_working]['substep'] = 'addfile'; $job_object->substeps_done++; $job_object->update_working_data(); $job_object->do_restart_time(); } if ($job_object->steps_data[$job_object->step_working]['substep'] == 'addfile') { //add XML file to backup files if (is_readable($job_object->steps_data[$job_object->step_working]['wpexportfile'])) { $job_object->additional_files_to_backup[] = $job_object->steps_data[$job_object->step_working]['wpexportfile']; $filesize = filesize($job_object->steps_data[$job_object->step_working]['wpexportfile']); $job_object->log(sprintf(__('Added XML export "%1$s" with %2$s to backup file list.', 'backwpup'), basename($job_object->steps_data[$job_object->step_working]['wpexportfile']), size_format($filesize, 2))); } $job_object->substeps_done++; $job_object->update_working_data(); } return TRUE; }
/** * @param $job_object * @return bool */ public function job_run_archive(BackWPup_Job $job_object) { $job_object->substeps_todo = 2 + $job_object->backup_filesize; if ($job_object->steps_data[$job_object->step_working]['SAVE_STEP_TRY'] != $job_object->steps_data[$job_object->step_working]['STEP_TRY']) { $job_object->log(sprintf(__('%d. Try to send backup file to an FTP server …', 'backwpup'), $job_object->steps_data[$job_object->step_working]['STEP_TRY']), E_USER_NOTICE); } if (!empty($job_object->job['ftpssl'])) { //make SSL FTP connection if (function_exists('ftp_ssl_connect')) { $ftp_conn_id = ftp_ssl_connect($job_object->job['ftphost'], $job_object->job['ftphostport'], $job_object->job['ftptimeout']); if ($ftp_conn_id) { $job_object->log(sprintf(__('Connected via explicit SSL-FTP to server: %s', 'backwpup'), $job_object->job['ftphost'] . ':' . $job_object->job['ftphostport']), E_USER_NOTICE); } else { $job_object->log(sprintf(__('Cannot connect via explicit SSL-FTP to server: %s', 'backwpup'), $job_object->job['ftphost'] . ':' . $job_object->job['ftphostport']), E_USER_ERROR); return FALSE; } } else { $job_object->log(__('PHP function to connect with explicit SSL-FTP to server does not exist!', 'backwpup'), E_USER_ERROR); return TRUE; } } else { //make normal FTP connection if SSL not work $ftp_conn_id = ftp_connect($job_object->job['ftphost'], $job_object->job['ftphostport'], $job_object->job['ftptimeout']); if ($ftp_conn_id) { $job_object->log(sprintf(__('Connected to FTP server: %s', 'backwpup'), $job_object->job['ftphost'] . ':' . $job_object->job['ftphostport']), E_USER_NOTICE); } else { $job_object->log(sprintf(__('Cannot connect to FTP server: %s', 'backwpup'), $job_object->job['ftphost'] . ':' . $job_object->job['ftphostport']), E_USER_ERROR); return FALSE; } } //FTP Login $job_object->log(sprintf(__('FTP client command: %s', 'backwpup'), 'USER ' . $job_object->job['ftpuser']), E_USER_NOTICE); if ($loginok = @ftp_login($ftp_conn_id, $job_object->job['ftpuser'], BackWPup_Encryption::decrypt($job_object->job['ftppass']))) { $job_object->log(sprintf(__('FTP server response: %s', 'backwpup'), 'User ' . $job_object->job['ftpuser'] . ' logged in.'), E_USER_NOTICE); } else { //if PHP ftp login don't work use raw login $return = ftp_raw($ftp_conn_id, 'USER ' . $job_object->job['ftpuser']); $job_object->log(sprintf(__('FTP server reply: %s', 'backwpup'), $return[0]), E_USER_NOTICE); if (substr(trim($return[0]), 0, 3) <= 400) { $job_object->log(sprintf(__('FTP client command: %s', 'backwpup'), 'PASS *******'), E_USER_NOTICE); $return = ftp_raw($ftp_conn_id, 'PASS ' . BackWPup_Encryption::decrypt($job_object->job['ftppass'])); if (substr(trim($return[0]), 0, 3) <= 400) { $job_object->log(sprintf(__('FTP server reply: %s', 'backwpup'), $return[0]), E_USER_NOTICE); $loginok = TRUE; } else { $job_object->log(sprintf(__('FTP server reply: %s', 'backwpup'), $return[0]), E_USER_ERROR); } } } if (!$loginok) { return FALSE; } //SYSTYPE $job_object->log(sprintf(__('FTP client command: %s', 'backwpup'), 'SYST'), E_USER_NOTICE); $systype = ftp_systype($ftp_conn_id); if ($systype) { $job_object->log(sprintf(__('FTP server reply: %s', 'backwpup'), $systype), E_USER_NOTICE); } else { $job_object->log(sprintf(__('FTP server reply: %s', 'backwpup'), __('Error getting SYSTYPE', 'backwpup')), E_USER_ERROR); } //set actual ftp dir to ftp dir if (empty($job_object->job['ftpdir'])) { $job_object->job['ftpdir'] = trailingslashit(ftp_pwd($ftp_conn_id)); } // prepend actual ftp dir if relative dir if (substr($job_object->job['ftpdir'], 0, 1) != '/') { $job_object->job['ftpdir'] = trailingslashit(ftp_pwd($ftp_conn_id)) . $job_object->job['ftpdir']; } //test ftp dir and create it if not exists if ($job_object->job['ftpdir'] != '/') { @ftp_chdir($ftp_conn_id, '/'); //go to root $ftpdirs = explode('/', trim($job_object->job['ftpdir'], '/')); foreach ($ftpdirs as $ftpdir) { if (empty($ftpdir)) { continue; } if (!@ftp_chdir($ftp_conn_id, $ftpdir)) { if (@ftp_mkdir($ftp_conn_id, $ftpdir)) { $job_object->log(sprintf(__('FTP Folder "%s" created!', 'backwpup'), $ftpdir), E_USER_NOTICE); ftp_chdir($ftp_conn_id, $ftpdir); } else { $job_object->log(sprintf(__('FTP Folder "%s" cannot be created!', 'backwpup'), $ftpdir), E_USER_ERROR); return FALSE; } } } } // Get the current working directory $current_ftp_dir = trailingslashit(ftp_pwd($ftp_conn_id)); if ($job_object->substeps_done == 0) { $job_object->log(sprintf(__('FTP current folder is: %s', 'backwpup'), $current_ftp_dir), E_USER_NOTICE); } //get file size to resume upload @clearstatcache(); $job_object->substeps_done = @ftp_size($ftp_conn_id, $job_object->job['ftpdir'] . $job_object->backup_file); if ($job_object->substeps_done == -1) { $job_object->substeps_done = 0; } //PASV $job_object->log(sprintf(__('FTP client command: %s', 'backwpup'), 'PASV'), E_USER_NOTICE); if ($job_object->job['ftppasv']) { if (ftp_pasv($ftp_conn_id, TRUE)) { $job_object->log(sprintf(__('FTP server reply: %s', 'backwpup'), __('Entering passive mode', 'backwpup')), E_USER_NOTICE); } else { $job_object->log(sprintf(__('FTP server reply: %s', 'backwpup'), __('Cannot enter passive mode', 'backwpup')), E_USER_WARNING); } } else { if (ftp_pasv($ftp_conn_id, FALSE)) { $job_object->log(sprintf(__('FTP server reply: %s', 'backwpup'), __('Entering normal mode', 'backwpup')), E_USER_NOTICE); } else { $job_object->log(sprintf(__('FTP server reply: %s', 'backwpup'), __('Cannot enter normal mode', 'backwpup')), E_USER_WARNING); } } if ($job_object->substeps_done < $job_object->backup_filesize) { $job_object->log(__('Starting upload to FTP  …', 'backwpup'), E_USER_NOTICE); if ($fp = fopen($job_object->backup_folder . $job_object->backup_file, 'rb')) { //go to actual file pos fseek($fp, $job_object->substeps_done); $ret = ftp_nb_fput($ftp_conn_id, $current_ftp_dir . $job_object->backup_file, $fp, FTP_BINARY, $job_object->substeps_done); while ($ret == FTP_MOREDATA) { $job_object->substeps_done = ftell($fp); $job_object->update_working_data(); $job_object->do_restart_time(); $ret = ftp_nb_continue($ftp_conn_id); } if ($ret != FTP_FINISHED) { $job_object->log(__('Cannot transfer backup to FTP server!', 'backwpup'), E_USER_ERROR); return FALSE; } else { $job_object->substeps_done = $job_object->backup_filesize + 1; $job_object->log(sprintf(__('Backup transferred to FTP server: %s', 'backwpup'), $current_ftp_dir . $job_object->backup_file), E_USER_NOTICE); if (!empty($job_object->job['jobid'])) { BackWPup_Option::update($job_object->job['jobid'], 'lastbackupdownloadurl', "ftp://" . $job_object->job['ftpuser'] . ":" . BackWPup_Encryption::decrypt($job_object->job['ftppass']) . "@" . $job_object->job['ftphost'] . ':' . $job_object->job['ftphostport'] . $current_ftp_dir . $job_object->backup_file); } } fclose($fp); } else { $job_object->log(__('Can not open source file for transfer.', 'backwpup'), E_USER_ERROR); return FALSE; } } $backupfilelist = array(); $filecounter = 0; $files = array(); if ($filelist = ftp_nlist($ftp_conn_id, '.')) { foreach ($filelist as $file) { if (basename($file) != '.' && basename($file) != '..') { if ($job_object->is_backup_archive($file)) { $time = ftp_mdtm($ftp_conn_id, $file); if ($time != -1) { $backupfilelist[$time] = basename($file); } else { $backupfilelist[] = basename($file); } } $files[$filecounter]['folder'] = 'ftp://' . $job_object->job['ftphost'] . ':' . $job_object->job['ftphostport'] . $job_object->job['ftpdir']; $files[$filecounter]['file'] = $job_object->job['ftpdir'] . basename($file); $files[$filecounter]['filename'] = basename($file); $files[$filecounter]['downloadurl'] = 'ftp://' . rawurlencode($job_object->job['ftpuser']) . ':' . rawurlencode(BackWPup_Encryption::decrypt($job_object->job['ftppass'])) . '@' . $job_object->job['ftphost'] . ':' . $job_object->job['ftphostport'] . $job_object->job['ftpdir'] . basename($file); $files[$filecounter]['filesize'] = ftp_size($ftp_conn_id, $file); $files[$filecounter]['time'] = ftp_mdtm($ftp_conn_id, $file); $filecounter++; } } } if (!empty($job_object->job['ftpmaxbackups']) && $job_object->job['ftpmaxbackups'] > 0) { //Delete old backups if (count($backupfilelist) > $job_object->job['ftpmaxbackups']) { ksort($backupfilelist); $numdeltefiles = 0; while ($file = array_shift($backupfilelist)) { if (count($backupfilelist) < $job_object->job['ftpmaxbackups']) { break; } if (ftp_delete($ftp_conn_id, $file)) { //delete files on ftp foreach ($files as $key => $filedata) { if ($filedata['file'] == $job_object->job['ftpdir'] . $file) { unset($files[$key]); } } $numdeltefiles++; } else { $job_object->log(sprintf(__('Cannot delete "%s" on FTP server!', 'backwpup'), $job_object->job['ftpdir'] . $file), E_USER_ERROR); } } if ($numdeltefiles > 0) { $job_object->log(sprintf(_n('One file deleted on FTP server', '%d files deleted on FTP server', $numdeltefiles, 'backwpup'), $numdeltefiles), E_USER_NOTICE); } } } set_site_transient('backwpup_' . $job_object->job['jobid'] . '_ftp', $files, YEAR_IN_SECONDS); $job_object->substeps_done++; ftp_close($ftp_conn_id); return TRUE; }
/** * @param $job_object BAckWPup_Job * @return bool */ public function job_run_archive(BackWPup_Job $job_object) { $job_object->substeps_todo = 2 + $job_object->backup_filesize; if ($job_object->steps_data[$job_object->step_working]['SAVE_STEP_TRY'] != $job_object->steps_data[$job_object->step_working]['STEP_TRY']) { $job_object->log(sprintf(__('%d. Trying to send backup file to S3 Service …', 'backwpup'), $job_object->steps_data[$job_object->step_working]['STEP_TRY']), E_USER_NOTICE); } try { $s3 = Aws\S3\S3Client::factory(array('key' => $job_object->job['s3accesskey'], 'secret' => BackWPup_Encryption::decrypt($job_object->job['s3secretkey']), 'region' => $job_object->job['s3region'], 'base_url' => $this->get_s3_base_url($job_object->job['s3region'], $job_object->job['s3base_url']), 'scheme' => 'https', 'ssl.certificate_authority' => BackWPup::get_plugin_data('cacert'))); if ($job_object->steps_data[$job_object->step_working]['SAVE_STEP_TRY'] != $job_object->steps_data[$job_object->step_working]['STEP_TRY'] && $job_object->substeps_done < $job_object->backup_filesize) { if ($s3->doesBucketExist($job_object->job['s3bucket'])) { $bucketregion = $s3->getBucketLocation(array('Bucket' => $job_object->job['s3bucket'])); $job_object->log(sprintf(__('Connected to S3 Bucket "%1$s" in %2$s', 'backwpup'), $job_object->job['s3bucket'], $bucketregion->get('Location')), E_USER_NOTICE); } else { $job_object->log(sprintf(__('S3 Bucket "%s" does not exist!', 'backwpup'), $job_object->job['s3bucket']), E_USER_ERROR); return TRUE; } if ($job_object->job['s3multipart'] && empty($job_object->steps_data[$job_object->step_working]['UploadId'])) { //Check for aboded Multipart Uploads $job_object->log(__('Checking for not aborted multipart Uploads …', 'backwpup')); $multipart_uploads = $s3->listMultipartUploads(array('Bucket' => $job_object->job['s3bucket'], 'Prefix' => (string) $job_object->job['s3dir'])); $uploads = $multipart_uploads->get('Uploads'); if (!empty($uploads)) { foreach ($uploads as $upload) { $s3->abortMultipartUpload(array('Bucket' => $job_object->job['s3bucket'], 'Key' => $upload['Key'], 'UploadId' => $upload['UploadId'])); $job_object->log(sprintf(__('Upload for %s aborted.', 'backwpup'), $upload['Key'])); } } } //transfer file to S3 $job_object->log(__('Starting upload to S3 Service …', 'backwpup')); } if (!$job_object->job['s3multipart'] || $job_object->backup_filesize < 1048576 * 6) { //Prepare Upload if (!($up_file_handle = fopen($job_object->backup_folder . $job_object->backup_file, 'rb'))) { $job_object->log(__('Can not open source file for transfer.', 'backwpup'), E_USER_ERROR); return FALSE; } $create_args = array(); $create_args['Bucket'] = $job_object->job['s3bucket']; $create_args['ACL'] = 'private'; //encrxption if (!empty($job_object->job['s3ssencrypt'])) { $create_args['ServerSideEncryption'] = $job_object->job['s3ssencrypt']; } //Storage Class if (!empty($job_object->job['s3storageclass'])) { $create_args['StorageClass'] = $job_object->job['s3storageclass']; } $create_args['Metadata'] = array('BackupTime' => date('Y-m-d H:i:s', $job_object->start_time)); $create_args['Body'] = $up_file_handle; $create_args['Key'] = $job_object->job['s3dir'] . $job_object->backup_file; $create_args['ContentType'] = $job_object->get_mime_type($job_object->backup_folder . $job_object->backup_file); try { $s3->putObject($create_args); } catch (Aws\Common\Exception\MultipartUploadException $e) { $job_object->log(E_USER_ERROR, sprintf(__('S3 Service API: %s', 'backwpup'), $e->getMessage()), $e->getFile(), $e->getLine()); return FALSE; } } else { //Prepare Upload if ($file_handle = fopen($job_object->backup_folder . $job_object->backup_file, 'rb')) { fseek($file_handle, $job_object->substeps_done); try { if (empty($job_object->steps_data[$job_object->step_working]['UploadId'])) { $args = array('ACL' => 'private', 'Bucket' => $job_object->job['s3bucket'], 'ContentType' => $job_object->get_mime_type($job_object->backup_folder . $job_object->backup_file), 'Key' => $job_object->job['s3dir'] . $job_object->backup_file); if (!empty($job_object->job['s3ssencrypt'])) { $args['ServerSideEncryption'] = $job_object->job['s3ssencrypt']; } if (!empty($job_object->job['s3storageclass'])) { $args['StorageClass'] = empty($job_object->job['s3storageclass']) ? '' : $job_object->job['s3storageclass']; } $upload = $s3->createMultipartUpload($args); $job_object->steps_data[$job_object->step_working]['UploadId'] = $upload->get('UploadId'); $job_object->steps_data[$job_object->step_working]['Parts'] = array(); $job_object->steps_data[$job_object->step_working]['Part'] = 1; } while (!feof($file_handle)) { $chunk_upload_start = microtime(TRUE); $part_data = fread($file_handle, 1048576 * 5); //5MB Minimum part size $part = $s3->uploadPart(array('Bucket' => $job_object->job['s3bucket'], 'UploadId' => $job_object->steps_data[$job_object->step_working]['UploadId'], 'Key' => $job_object->job['s3dir'] . $job_object->backup_file, 'PartNumber' => $job_object->steps_data[$job_object->step_working]['Part'], 'Body' => $part_data)); $chunk_upload_time = microtime(TRUE) - $chunk_upload_start; $job_object->substeps_done = $job_object->substeps_done + strlen($part_data); $job_object->steps_data[$job_object->step_working]['Parts'][] = array('ETag' => $part->get('ETag'), 'PartNumber' => $job_object->steps_data[$job_object->step_working]['Part']); $job_object->steps_data[$job_object->step_working]['Part']++; $time_remaining = $job_object->do_restart_time(); if ($time_remaining < $chunk_upload_time) { $job_object->do_restart_time(TRUE); } $job_object->update_working_data(); } $s3->completeMultipartUpload(array('Bucket' => $job_object->job['s3bucket'], 'UploadId' => $job_object->steps_data[$job_object->step_working]['UploadId'], 'Key' => $job_object->job['s3dir'] . $job_object->backup_file, 'Parts' => $job_object->steps_data[$job_object->step_working]['Parts'])); } catch (Exception $e) { $job_object->log(E_USER_ERROR, sprintf(__('S3 Service API: %s', 'backwpup'), $e->getMessage()), $e->getFile(), $e->getLine()); if (!empty($job_object->steps_data[$job_object->step_working]['uploadId'])) { $s3->abortMultipartUpload(array('Bucket' => $job_object->job['s3bucket'], 'UploadId' => $job_object->steps_data[$job_object->step_working]['uploadId'], 'Key' => $job_object->job['s3dir'] . $job_object->backup_file)); } unset($job_object->steps_data[$job_object->step_working]['UploadId']); unset($job_object->steps_data[$job_object->step_working]['Parts']); unset($job_object->steps_data[$job_object->step_working]['Part']); $job_object->substeps_done = 0; if (is_resource($file_handle)) { fclose($file_handle); } return FALSE; } fclose($file_handle); } else { $job_object->log(__('Can not open source file for transfer.', 'backwpup'), E_USER_ERROR); return FALSE; } } $result = $s3->headObject(array('Bucket' => $job_object->job['s3bucket'], 'Key' => $job_object->job['s3dir'] . $job_object->backup_file)); if ($result->get('ContentLength') == filesize($job_object->backup_folder . $job_object->backup_file)) { $job_object->substeps_done = 1 + $job_object->backup_filesize; $job_object->log(sprintf(__('Backup transferred to %s.', 'backwpup'), $this->get_s3_base_url($job_object->job['s3region'], $job_object->job['s3base_url']) . '/' . $job_object->job['s3bucket'] . '/' . $job_object->job['s3dir'] . $job_object->backup_file), E_USER_NOTICE); if (!empty($job_object->job['jobid'])) { BackWPup_Option::update($job_object->job['jobid'], 'lastbackupdownloadurl', network_admin_url('admin.php') . '?page=backwpupbackups&action=downloads3&file=' . $job_object->job['s3dir'] . $job_object->backup_file . '&jobid=' . $job_object->job['jobid']); } } else { $job_object->log(sprintf(__('Cannot transfer backup to S3! (%1$d) %2$s', 'backwpup'), $result->get("status"), $result->get("Message")), E_USER_ERROR); } } catch (Exception $e) { $job_object->log(E_USER_ERROR, sprintf(__('S3 Service API: %s', 'backwpup'), $e->getMessage()), $e->getFile(), $e->getLine()); return FALSE; } try { $backupfilelist = array(); $filecounter = 0; $files = array(); $args = array('Bucket' => $job_object->job['s3bucket'], 'Prefix' => (string) $job_object->job['s3dir']); $objects = $s3->getIterator('ListObjects', $args); if (is_object($objects)) { foreach ($objects as $object) { $file = basename($object['Key']); $changetime = strtotime($object['LastModified']) + get_option('gmt_offset') * 3600; if ($job_object->is_backup_archive($file)) { $backupfilelist[$changetime] = $file; } $files[$filecounter]['folder'] = $this->get_s3_base_url($job_object->job['s3region'], $job_object->job['s3base_url']) . '/' . $job_object->job['s3bucket'] . '/' . dirname($object['Key']); $files[$filecounter]['file'] = $object['Key']; $files[$filecounter]['filename'] = basename($object['Key']); if (!empty($object['StorageClass'])) { $files[$filecounter]['info'] = sprintf(__('Storage Class: %s', 'backwpup'), $object['StorageClass']); } $files[$filecounter]['downloadurl'] = network_admin_url('admin.php') . '?page=backwpupbackups&action=downloads3&file=' . $object['Key'] . '&jobid=' . $job_object->job['jobid']; $files[$filecounter]['filesize'] = $object['Size']; $files[$filecounter]['time'] = $changetime; $filecounter++; } } if ($job_object->job['s3maxbackups'] > 0 && is_object($s3)) { //Delete old backups if (count($backupfilelist) > $job_object->job['s3maxbackups']) { ksort($backupfilelist); $numdeltefiles = 0; while ($file = array_shift($backupfilelist)) { if (count($backupfilelist) < $job_object->job['s3maxbackups']) { break; } //delete files on S3 $args = array('Bucket' => $job_object->job['s3bucket'], 'Key' => $job_object->job['s3dir'] . $file); if ($s3->deleteObject($args)) { foreach ($files as $key => $filedata) { if ($filedata['file'] == $job_object->job['s3dir'] . $file) { unset($files[$key]); } } $numdeltefiles++; } else { $job_object->log(sprintf(__('Cannot delete backup from %s.', 'backwpup'), $this->get_s3_base_url($job_object->job['s3region'], $job_object->job['s3base_url']) . '/' . $job_object->job['s3bucket'] . '/' . $job_object->job['s3dir'] . $file), E_USER_ERROR); } } if ($numdeltefiles > 0) { $job_object->log(sprintf(_n('One file deleted on S3 Bucket.', '%d files deleted on S3 Bucket', $numdeltefiles, 'backwpup'), $numdeltefiles), E_USER_NOTICE); } } } set_site_transient('backwpup_' . $job_object->job['jobid'] . '_s3', $files, YEAR_IN_SECONDS); } catch (Exception $e) { $job_object->log(E_USER_ERROR, sprintf(__('S3 Service API: %s', 'backwpup'), $e->getMessage()), $e->getFile(), $e->getLine()); return FALSE; } $job_object->substeps_done = 2 + $job_object->backup_filesize; return TRUE; }
/** * Dumps the Database * * @param $job_object BackWPup_Job * * @return bool */ public function job_run(BackWPup_Job $job_object) { $job_object->substeps_todo = 1; if ($job_object->steps_data[$job_object->step_working]['SAVE_STEP_TRY'] != $job_object->steps_data[$job_object->step_working]['STEP_TRY']) { $job_object->log(sprintf(__('%d. Try to backup database …', 'backwpup'), $job_object->steps_data[$job_object->step_working]['STEP_TRY'])); } //build filename if (empty($job_object->steps_data[$job_object->step_working]['dbdumpfile'])) { $job_object->steps_data[$job_object->step_working]['dbdumpfile'] = $job_object->generate_filename($job_object->job['dbdumpfile'], 'sql') . $job_object->job['dbdumpfilecompression']; } try { //Connect to Database $sql_dump = new BackWPup_MySQLDump(array('dumpfile' => BackWPup::get_plugin_data('TEMP') . $job_object->steps_data[$job_object->step_working]['dbdumpfile'])); if ($job_object->steps_data[$job_object->step_working]['SAVE_STEP_TRY'] != $job_object->steps_data[$job_object->step_working]['STEP_TRY']) { $job_object->log(sprintf(__('Connected to database %1$s on %2$s', 'backwpup'), DB_NAME, DB_HOST)); } //Exclude Tables foreach ($sql_dump->tables_to_dump as $key => $table) { if (in_array($table, $job_object->job['dbdumpexclude'], true)) { unset($sql_dump->tables_to_dump[$key]); } } //set steps must done $job_object->substeps_todo = count($sql_dump->tables_to_dump); if ($job_object->substeps_todo == 0) { $job_object->log(__('No tables to backup.', 'backwpup'), E_USER_WARNING); unset($sql_dump); return TRUE; } //dump head if (!isset($job_object->steps_data[$job_object->step_working]['is_head'])) { $sql_dump->dump_head(TRUE); $job_object->steps_data[$job_object->step_working]['is_head'] = TRUE; } //dump tables $i = 0; foreach ($sql_dump->tables_to_dump as $table) { if ($i < $job_object->substeps_done) { $i++; continue; } if (empty($job_object->steps_data[$job_object->step_working]['tables'][$table])) { $num_records = $sql_dump->dump_table_head($table); $job_object->steps_data[$job_object->step_working]['tables'][$table] = array('start' => 0, 'length' => 1000); if ($job_object->is_debug()) { $job_object->log(sprintf(__('Backup database table "%s" with "%s" records', 'backwpup'), $table, $num_records)); } } $while = true; while ($while) { $dump_start_time = microtime(TRUE); $done_records = $sql_dump->dump_table($table, $job_object->steps_data[$job_object->step_working]['tables'][$table]['start'], $job_object->steps_data[$job_object->step_working]['tables'][$table]['length']); $dump_time = microtime(TRUE) - $dump_start_time; if (empty($dump_time)) { $dump_time = 0.01; } if ($done_records < $job_object->steps_data[$job_object->step_working]['tables'][$table]['length']) { //that is the last chunk $while = FALSE; } $job_object->steps_data[$job_object->step_working]['tables'][$table]['start'] = $job_object->steps_data[$job_object->step_working]['tables'][$table]['start'] + $done_records; // dump time per record and set next length $length = ceil($done_records / $dump_time * $job_object->get_restart_time()); if ($length > 25000 || 0 >= $job_object->get_restart_time()) { $length = 25000; } if ($length < 1000) { $length = 1000; } $job_object->steps_data[$job_object->step_working]['tables'][$table]['length'] = $length; $job_object->do_restart_time(); } $sql_dump->dump_table_footer($table); $job_object->substeps_done++; $i++; $job_object->update_working_data(); } //dump footer $sql_dump->dump_footer(); unset($sql_dump); } catch (Exception $e) { $job_object->log($e->getMessage(), E_USER_ERROR, $e->getFile(), $e->getLine()); unset($sql_dump); return FALSE; } $filesize = filesize(BackWPup::get_plugin_data('TEMP') . $job_object->steps_data[$job_object->step_working]['dbdumpfile']); if (!is_file(BackWPup::get_plugin_data('TEMP') . $job_object->steps_data[$job_object->step_working]['dbdumpfile']) || $filesize < 1) { $job_object->log(__('MySQL backup file not created', 'backwpup'), E_USER_ERROR); return FALSE; } else { $job_object->additional_files_to_backup[] = BackWPup::get_plugin_data('TEMP') . $job_object->steps_data[$job_object->step_working]['dbdumpfile']; $job_object->log(sprintf(__('Added database dump "%1$s" with %2$s to backup file list', 'backwpup'), $job_object->steps_data[$job_object->step_working]['dbdumpfile'], size_format($filesize, 2))); } //cleanups unset($job_object->steps_data[$job_object->step_working]['tables']); $job_object->log(__('Database backup done!', 'backwpup')); return TRUE; }
/** * @param $job_object * @return bool */ public function job_run_archive(BackWPup_Job $job_object) { $job_object->substeps_todo = $job_object->backup_filesize + 2; if ($job_object->steps_data[$job_object->step_working]['SAVE_STEP_TRY'] != $job_object->steps_data[$job_object->step_working]['STEP_TRY']) { $job_object->log(sprintf(__('%d. Try sending backup to a Microsoft Azure (Blob) …', 'backwpup'), $job_object->steps_data[$job_object->step_working]['STEP_TRY']), E_USER_NOTICE); } try { set_include_path(get_include_path() . PATH_SEPARATOR . BackWPup::get_plugin_data('plugindir') . '/vendor/PEAR/'); /* @var $blobRestProxy WindowsAzure\Blob\BlobRestProxy */ //https causes an error SSL: Connection reset by peer that is why http $blobRestProxy = WindowsAzure\Common\ServicesBuilder::getInstance()->createBlobService('DefaultEndpointsProtocol=http;AccountName=' . $job_object->job['msazureaccname'] . ';AccountKey=' . BackWPup_Encryption::decrypt($job_object->job['msazurekey'])); if ($job_object->steps_data[$job_object->step_working]['SAVE_STEP_TRY'] != $job_object->steps_data[$job_object->step_working]['STEP_TRY']) { //test vor existing container $containers = $blobRestProxy->listContainers()->getContainers(); $job_object->steps_data[$job_object->step_working]['container_url'] = ''; foreach ($containers as $container) { if ($container->getName() == $job_object->job['msazurecontainer']) { $job_object->steps_data[$job_object->step_working]['container_url'] = $container->getUrl(); break; } } if (!$job_object->steps_data[$job_object->step_working]['container_url']) { $job_object->log(sprintf(__('MS Azure container "%s" does not exist!', 'backwpup'), $job_object->job['msazurecontainer']), E_USER_ERROR); return TRUE; } else { $job_object->log(sprintf(__('Connected to MS Azure container "%s".', 'backwpup'), $job_object->job['msazurecontainer']), E_USER_NOTICE); } $job_object->log(__('Starting upload to MS Azure …', 'backwpup'), E_USER_NOTICE); } //Prepare Upload if ($file_handel = fopen($job_object->backup_folder . $job_object->backup_file, 'rb')) { fseek($file_handel, $job_object->substeps_done); if (empty($job_object->steps_data[$job_object->step_working]['BlockList'])) { $job_object->steps_data[$job_object->step_working]['BlockList'] = array(); } while (!feof($file_handel)) { $data = fread($file_handel, 1048576 * 4); //4MB if (strlen($data) == 0) { continue; } $chunk_upload_start = microtime(TRUE); $block_count = count($job_object->steps_data[$job_object->step_working]['BlockList']) + 1; $block_id = md5($data) . str_pad($block_count, 6, "0", STR_PAD_LEFT); $blobRestProxy->createBlobBlock($job_object->job['msazurecontainer'], $job_object->job['msazuredir'] . $job_object->backup_file, $block_id, $data); $job_object->steps_data[$job_object->step_working]['BlockList'][] = $block_id; $chunk_upload_time = microtime(TRUE) - $chunk_upload_start; $job_object->substeps_done = $job_object->substeps_done + strlen($data); $time_remaining = $job_object->do_restart_time(); if ($time_remaining < $chunk_upload_time) { $job_object->do_restart_time(TRUE); } $job_object->update_working_data(); } fclose($file_handel); } else { $job_object->log(__('Can not open source file for transfer.', 'backwpup'), E_USER_ERROR); return FALSE; } //crate blog list $blocklist = new WindowsAzure\Blob\Models\BlockList(); foreach ($job_object->steps_data[$job_object->step_working]['BlockList'] as $block_id) { $blocklist->addUncommittedEntry($block_id); } unset($job_object->steps_data[$job_object->step_working]['BlockList']); //Commit Blocks $blobRestProxy->commitBlobBlocks($job_object->job['msazurecontainer'], $job_object->job['msazuredir'] . $job_object->backup_file, $blocklist->getEntries()); $job_object->substeps_done++; $job_object->log(sprintf(__('Backup transferred to %s', 'backwpup'), $job_object->steps_data[$job_object->step_working]['container_url'] . '/' . $job_object->job['msazuredir'] . $job_object->backup_file), E_USER_NOTICE); if (!empty($job_object->job['jobid'])) { BackWPup_Option::update($job_object->job['jobid'], 'lastbackupdownloadurl', network_admin_url('admin.php') . '?page=backwpupbackups&action=downloadmsazure&file=' . $job_object->job['msazuredir'] . $job_object->backup_file . '&jobid=' . $job_object->job['jobid']); } } catch (Exception $e) { $job_object->log(E_USER_ERROR, sprintf(__('Microsoft Azure API: %s', 'backwpup'), $e->getMessage()), $e->getFile(), $e->getLine()); $job_object->substeps_done = 0; unset($job_object->steps_data[$job_object->step_working]['BlockList']); if (isset($file_handel) && is_resource($file_handel)) { fclose($file_handel); } return FALSE; } try { $backupfilelist = array(); $filecounter = 0; $files = array(); $blob_options = new WindowsAzure\Blob\Models\ListBlobsOptions(); $blob_options->setPrefix($job_object->job['msazuredir']); $blobs = $blobRestProxy->listBlobs($job_object->job['msazurecontainer'], $blob_options)->getBlobs(); if (is_array($blobs)) { foreach ($blobs as $blob) { $file = basename($blob->getName()); if ($job_object->is_backup_archive($file)) { $backupfilelist[$blob->getProperties()->getLastModified()->getTimestamp()] = $file; } $files[$filecounter]['folder'] = $job_object->steps_data[$job_object->step_working]['container_url'] . "/" . dirname($blob->getName()) . "/"; $files[$filecounter]['file'] = $blob->getName(); $files[$filecounter]['filename'] = basename($blob->getName()); $files[$filecounter]['downloadurl'] = network_admin_url('admin.php') . '?page=backwpupbackups&action=downloadmsazure&file=' . $blob->getName() . '&jobid=' . $job_object->job['jobid']; $files[$filecounter]['filesize'] = $blob->getProperties()->getContentLength(); $files[$filecounter]['time'] = $blob->getProperties()->getLastModified()->getTimestamp() + get_option('gmt_offset') * 3600; $filecounter++; } } // Delete old backups if (!empty($job_object->job['msazuremaxbackups']) && $job_object->job['msazuremaxbackups'] > 0) { if (count($backupfilelist) > $job_object->job['msazuremaxbackups']) { ksort($backupfilelist); $numdeltefiles = 0; while ($file = array_shift($backupfilelist)) { if (count($backupfilelist) < $job_object->job['msazuremaxbackups']) { break; } $blobRestProxy->deleteBlob($job_object->job['msazurecontainer'], $job_object->job['msazuredir'] . $file); foreach ($files as $key => $filedata) { if ($filedata['file'] == $job_object->job['msazuredir'] . $file) { unset($files[$key]); } } $numdeltefiles++; } if ($numdeltefiles > 0) { $job_object->log(sprintf(_n('One file deleted on Microsoft Azure container.', '%d files deleted on Microsoft Azure container.', $numdeltefiles, 'backwpup'), $numdeltefiles), E_USER_NOTICE); } } } set_site_transient('backwpup_' . $job_object->job['jobid'] . '_msazure', $files, YEAR_IN_SECONDS); } catch (Exception $e) { $job_object->log(E_USER_ERROR, sprintf(__('Microsoft Azure API: %s', 'backwpup'), $e->getMessage()), $e->getFile(), $e->getLine()); return FALSE; } $job_object->substeps_done = $job_object->backup_filesize + 2; return TRUE; }