示例#1
0
function copy_folder_to_cloudfiles($channel, $observer_hash, $srcpath, $cloudpath)
{
    if (!is_dir($srcpath) || !is_readable($srcpath)) {
        logger('Error reading source path: ' . $srcpath, LOGGER_NORMAL);
        return false;
    }
    $nodes = array_diff(scandir($srcpath), array('.', '..'));
    foreach ($nodes as $node) {
        $clouddir = $cloudpath . '/' . $node;
        // Sub-folder in cloud files destination
        $nodepath = $srcpath . '/' . $node;
        // Sub-folder in source path
        if (is_dir($nodepath)) {
            $x = attach_mkdirp($channel, $observer_hash, array('pathname' => $clouddir));
            if (!$x['success']) {
                logger('Error creating cloud path: ' . $clouddir, LOGGER_NORMAL);
                return false;
            }
            // Recursively call this function where the source and destination are the subfolders
            $success = copy_folder_to_cloudfiles($channel, $observer_hash, $nodepath, $clouddir);
            if (!$success) {
                logger('Error copying contents of folder: ' . $nodepath, LOGGER_NORMAL);
                return false;
            }
        } elseif (is_file($nodepath) && is_readable($nodepath)) {
            $x = attach_store($channel, $observer_hash, 'import', array('directory' => $cloudpath, 'src' => $nodepath, 'filename' => $node, 'filesize' => @filesize($nodepath), 'preserve_original' => true));
            if (!$x['success']) {
                logger('Error copying file: ' . $nodepath, LOGGER_NORMAL);
                logger('Return value: ' . json_encode($x), LOGGER_NORMAL);
                return false;
            }
        } else {
            logger('Error scanning source path', LOGGER_NORMAL);
            return false;
        }
    }
    return true;
}
示例#2
0
/**
 * A lot going on in this function, and some of it is old cruft and some is new cruft
 * and the entire thing probably needs to be refactored. It started out just storing
 * files, before we had DAV. It was made extensible to do extra stuff like edit an 
 * existing file or optionally store a separate revision using $options to choose between different
 * storage models. Along the way we moved from
 * DB data storage to file system storage. 
 * Then DAV came along and used different upload methods depending on whether the 
 * file was stored as a DAV directory object or updated as a file object. One of these 
 * is essentially an update and the other is basically an upload, but doesn't use the traditional PHP
 * upload workflow. 
 * Then came hubzilla and we tried to merge photo functionality with the file storage. Most of
 * that integration occurs within this function. 
 * This required overlap with the old photo_upload stuff and photo albums were
 * completely different concepts from directories which needed to be reconciled somehow.
 * The old revision stuff is kind of orphaned currently. There's new revision stuff for photos
 * which attaches (2) etc. onto the name, but doesn't integrate with the attach table revisioning.
 * That's where it sits currently. I repeat it needs to be refactored, and this note is here
 * for future explorers and those who may be doing that work to understand where it came
 * from and got to be the monstrosity of tangled unrelated code that it currently is.
 */
function attach_store($channel, $observer_hash, $options = '', $arr = null)
{
    require_once 'include/photos.php';
    call_hooks('photo_upload_begin', $arr);
    $ret = array('success' => false);
    $channel_id = $channel['channel_id'];
    $sql_options = '';
    $source = $arr ? $arr['source'] : '';
    $album = $arr ? $arr['album'] : '';
    $newalbum = $arr ? $arr['newalbum'] : '';
    $hash = $arr && $arr['hash'] ? $arr['hash'] : null;
    $upload_path = $arr && $arr['directory'] ? $arr['directory'] : '';
    $visible = $arr && $arr['visible'] ? $arr['visible'] : '';
    $observer = array();
    if ($observer_hash) {
        $x = q("select * from xchan where xchan_hash = '%s' limit 1", dbesc($observer_hash));
        if ($x) {
            $observer = $x[0];
        }
    }
    logger('arr: ' . print_r($arr, true));
    if (!perm_is_allowed($channel_id, $observer_hash, 'write_storage')) {
        $ret['message'] = t('Permission denied.');
        return $ret;
    }
    $str_group_allow = perms2str($arr['group_allow']);
    $str_contact_allow = perms2str($arr['contact_allow']);
    $str_group_deny = perms2str($arr['group_deny']);
    $str_contact_deny = perms2str($arr['contact_deny']);
    // The 'update' option sets db values without uploading a new attachment
    // 'replace' replaces the existing uploaded data
    // 'revision' creates a new revision with new upload data
    // Default is to upload a new file
    // revise or update must provide $arr['hash'] of the thing to revise/update
    // By default remove $src when finished
    $remove_when_processed = true;
    if ($options === 'import') {
        $src = $arr['src'];
        $filename = $arr['filename'];
        $filesize = @filesize($src);
        $hash = $arr['resource_id'];
        if (array_key_exists('hash', $arr)) {
            $hash = $arr['hash'];
        }
        if (array_key_exists('type', $arr)) {
            $type = $arr['type'];
        }
        if ($arr['preserve_original']) {
            $remove_when_processed = false;
        }
        // if importing a directory, just do it now and go home - we're done.
        if (array_key_exists('is_dir', $arr) && intval($arr['is_dir'])) {
            $x = attach_mkdir($channel, $observer_hash, $arr);
            if ($x['message']) {
                logger('import_directory: ' . $x['message']);
            }
            return;
        }
    } elseif ($options !== 'update') {
        $f = array('src' => '', 'filename' => '', 'filesize' => 0, 'type' => '');
        call_hooks('photo_upload_file', $f);
        call_hooks('attach_upload_file', $f);
        if (x($f, 'src') && x($f, 'filesize')) {
            $src = $f['src'];
            $filename = $f['filename'];
            $filesize = $f['filesize'];
            $type = $f['type'];
        } else {
            if (!x($_FILES, 'userfile')) {
                $ret['message'] = t('No source file.');
                return $ret;
            }
            $src = $_FILES['userfile']['tmp_name'];
            $filename = basename($_FILES['userfile']['name']);
            $filesize = intval($_FILES['userfile']['size']);
        }
    }
    $existing_size = 0;
    if ($options === 'replace') {
        $x = q("select id, hash, filesize from attach where id = %d and uid = %d limit 1", intval($arr['id']), intval($channel_id));
        if (!$x) {
            $ret['message'] = t('Cannot locate file to replace');
            return $ret;
        }
        $existing_id = $x[0]['id'];
        $existing_size = intval($x[0]['filesize']);
        $hash = $x[0]['hash'];
    }
    if ($options === 'revise' || $options === 'update') {
        $sql_options = " order by revision desc ";
        if ($options === 'update' && $arr && array_key_exists('revision', $arr)) {
            $sql_options = " and revision = " . intval($arr['revision']) . " ";
        }
        $x = q("select id, aid, uid, filename, filetype, filesize, hash, revision, folder, os_storage, is_photo, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where hash = '%s' and uid = %d {$sql_options} limit 1", dbesc($arr['hash']), intval($channel_id));
        if (!$x) {
            $ret['message'] = t('Cannot locate file to revise/update');
            return $ret;
        }
        $hash = $x[0]['hash'];
    }
    $def_extension = '';
    $is_photo = 0;
    $gis = @getimagesize($src);
    logger('getimagesize: ' . print_r($gis, true), LOGGER_DATA);
    if ($gis && ($gis[2] === IMAGETYPE_GIF || $gis[2] === IMAGETYPE_JPEG || $gis[2] === IMAGETYPE_PNG)) {
        $is_photo = 1;
        if ($gis[2] === IMAGETYPE_GIF) {
            $def_extension = '.gif';
        }
        if ($gis[2] === IMAGETYPE_JPEG) {
            $def_extension = '.jpg';
        }
        if ($gis[2] === IMAGETYPE_PNG) {
            $def_extension = '.png';
        }
    }
    $pathname = '';
    if ($is_photo) {
        if ($newalbum) {
            $pathname = filepath_macro($newalbum);
        } elseif (array_key_exists('folder', $arr)) {
            $x = q("select filename from attach where hash = '%s' and uid = %d limit 1", dbesc($arr['folder']), intval($channel['channel_id']));
            if ($x) {
                $pathname = $x[0]['filename'];
            }
        } else {
            $pathname = filepath_macro($album);
        }
    } else {
        $pathname = filepath_macro($upload_path);
    }
    $darr = array('pathname' => $pathname);
    // if we need to create a directory, use the channel default permissions.
    $darr['allow_cid'] = $channel['allow_cid'];
    $darr['allow_gid'] = $channel['allow_gid'];
    $darr['deny_cid'] = $channel['deny_cid'];
    $darr['deny_gid'] = $channel['deny_gid'];
    $direct = null;
    if ($pathname) {
        $x = attach_mkdirp($channel, $observer_hash, $darr);
        $folder_hash = $x['success'] ? $x['data']['hash'] : '';
        $direct = $x['success'] ? $x['data'] : null;
        if (!$str_contact_allow && !$str_group_allow && !$str_contact_deny && !$str_group_deny) {
            $str_contact_allow = $x['data']['allow_cid'];
            $str_group_allow = $x['data']['allow_gid'];
            $str_contact_deny = $x['data']['deny_cid'];
            $str_group_deny = $x['data']['deny_gid'];
        }
    } else {
        $folder_hash = $arr && array_key_exists('folder', $arr) ? $arr['folder'] : '';
    }
    if (!$options || $options === 'import') {
        // A freshly uploaded file. Check for duplicate and resolve with the channel's overwrite settings.
        $r = q("select filename, id, hash, filesize from attach where filename = '%s' and folder = '%s' ", dbesc($filename), dbesc($folder_hash));
        if ($r) {
            $overwrite = get_pconfig($channel_id, 'system', 'overwrite_dup_files');
            if ($overwrite) {
                $options = 'replace';
                $existing_id = $x[0]['id'];
                $existing_size = intval($x[0]['filesize']);
                $hash = $x[0]['hash'];
            } else {
                if (strpos($filename, '.') !== false) {
                    $basename = substr($filename, 0, strrpos($filename, '.'));
                    $ext = substr($filename, strrpos($filename, '.'));
                } else {
                    $basename = $filename;
                    $ext = $def_extension;
                }
                $r = q("select filename from attach where ( filename = '%s' OR filename like '%s' ) and folder = '%s' ", dbesc($basename . $ext), dbesc($basename . '(%)' . $ext), dbesc($folder_hash));
                if ($r) {
                    $x = 1;
                    do {
                        $found = false;
                        foreach ($r as $rr) {
                            if ($rr['filename'] === $basename . '(' . $x . ')' . $ext) {
                                $found = true;
                                break;
                            }
                        }
                        if ($found) {
                            $x++;
                        }
                    } while ($found);
                    $filename = $basename . '(' . $x . ')' . $ext;
                } else {
                    $filename = $basename . $ext;
                }
            }
        }
    }
    if (!$hash) {
        $hash = random_string();
    }
    // Check storage limits
    if ($options !== 'update') {
        $maxfilesize = get_config('system', 'maxfilesize');
        if ($maxfilesize && $filesize > $maxfilesize) {
            $ret['message'] = sprintf(t('File exceeds size limit of %d'), $maxfilesize);
            if ($remove_when_processed) {
                @unlink($src);
            }
            call_hooks('photo_upload_end', $ret);
            return $ret;
        }
        $limit = service_class_fetch($channel_id, 'attach_upload_limit');
        if ($limit !== false) {
            $r = q("select sum(filesize) as total from attach where aid = %d ", intval($channel['channel_account_id']));
            if ($r && $r[0]['total'] + $filesize > $limit - $existing_size) {
                $ret['message'] = upgrade_message(true) . sprintf(t("You have reached your limit of %1\$.0f Mbytes attachment storage."), $limit / 1024000);
                if ($remove_when_processed) {
                    @unlink($src);
                }
                call_hooks('photo_upload_end', $ret);
                return $ret;
            }
        }
        $mimetype = isset($type) && $type ? $type : z_mime_content_type($filename);
    }
    $os_basepath = 'store/' . $channel['channel_address'] . '/';
    $os_relpath = '';
    if ($folder_hash) {
        $curr = find_folder_hash_by_attach_hash($channel_id, $folder_hash, true);
        if ($curr) {
            $os_relpath .= $curr . '/';
        }
        $os_relpath .= $folder_hash . '/';
    }
    $os_relpath .= $hash;
    if ($src) {
        @file_put_contents($os_basepath . $os_relpath, @file_get_contents($src));
    }
    if (array_key_exists('created', $arr)) {
        $created = $arr['created'];
    } else {
        $created = datetime_convert();
    }
    if (array_key_exists('edited', $arr)) {
        $edited = $arr['edited'];
    } else {
        $edited = $created;
    }
    if ($options === 'replace') {
        $r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', filesize = %d, os_storage = %d, is_photo = %d, data = '%s', edited = '%s' where id = %d and uid = %d", dbesc($filename), dbesc($mimetype), dbesc($folder_hash), intval($filesize), intval(1), intval($is_photo), dbesc($os_relpath), dbesc($created), intval($existing_id), intval($channel_id));
    } elseif ($options === 'revise') {
        $r = q("insert into attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, data, created, edited, allow_cid, allow_gid, deny_cid, deny_gid )\n\t\t\tVALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", intval($x[0]['aid']), intval($channel_id), dbesc($x[0]['hash']), dbesc($observer_hash), dbesc($filename), dbesc($mimetype), dbesc($folder_hash), intval($filesize), intval($x[0]['revision'] + 1), intval(1), intval($is_photo), dbesc($os_relpath), dbesc($created), dbesc($created), dbesc($x[0]['allow_cid']), dbesc($x[0]['allow_gid']), dbesc($x[0]['deny_cid']), dbesc($x[0]['deny_gid']));
    } elseif ($options === 'update') {
        $r = q("update attach set filename = '%s', filetype = '%s', folder = '%s', edited = '%s', os_storage = %d, is_photo = %d, \n\t\t\tallow_cid = '%s', allow_gid = '%s', deny_cid = '%s', deny_gid  = '%s' where id = %d and uid = %d", dbesc(array_key_exists('filename', $arr) ? $arr['filename'] : $x[0]['filename']), dbesc(array_key_exists('filetype', $arr) ? $arr['filetype'] : $x[0]['filetype']), dbesc($folder_hash ? $folder_hash : $x[0]['folder']), dbesc($created), dbesc(array_key_exists('os_storage', $arr) ? $arr['os_storage'] : $x[0]['os_storage']), dbesc(array_key_exists('is_photo', $arr) ? $arr['is_photo'] : $x[0]['is_photo']), dbesc(array_key_exists('allow_cid', $arr) ? $arr['allow_cid'] : $x[0]['allow_cid']), dbesc(array_key_exists('allow_gid', $arr) ? $arr['allow_gid'] : $x[0]['allow_gid']), dbesc(array_key_exists('deny_cid', $arr) ? $arr['deny_cid'] : $x[0]['deny_cid']), dbesc(array_key_exists('deny_gid', $arr) ? $arr['deny_gid'] : $x[0]['deny_gid']), intval($x[0]['id']), intval($x[0]['uid']));
    } else {
        $r = q("INSERT INTO attach ( aid, uid, hash, creator, filename, filetype, folder, filesize, revision, os_storage, is_photo, data, created, edited, allow_cid, allow_gid,deny_cid, deny_gid )\n\t\t\tVALUES ( %d, %d, '%s', '%s', '%s', '%s', '%s', %d, %d, %d, %d, '%s', '%s', '%s', '%s', '%s', '%s', '%s' ) ", intval($channel['channel_account_id']), intval($channel_id), dbesc($hash), dbesc(get_observer_hash()), dbesc($filename), dbesc($mimetype), dbesc($folder_hash), intval($filesize), intval(0), intval(1), intval($is_photo), dbesc($os_relpath), dbesc($created), dbesc($created), dbesc($arr && array_key_exists('allow_cid', $arr) ? $arr['allow_cid'] : $str_contact_allow), dbesc($arr && array_key_exists('allow_gid', $arr) ? $arr['allow_gid'] : $str_group_allow), dbesc($arr && array_key_exists('deny_cid', $arr) ? $arr['deny_cid'] : $str_contact_deny), dbesc($arr && array_key_exists('deny_gid', $arr) ? $arr['deny_gid'] : $str_group_deny));
    }
    if ($is_photo) {
        $args = array('source' => $source, 'visible' => $visible, 'resource_id' => $hash, 'album' => basename($pathname), 'os_path' => $os_basepath . $os_relpath, 'filename' => $filename, 'getimagesize' => $gis, 'directory' => $direct);
        if ($arr['contact_allow']) {
            $args['contact_allow'] = $arr['contact_allow'];
        }
        if ($arr['group_allow']) {
            $args['group_allow'] = $arr['group_allow'];
        }
        if ($arr['contact_deny']) {
            $args['contact_deny'] = $arr['contact_deny'];
        }
        if ($arr['group_deny']) {
            $args['group_deny'] = $arr['group_deny'];
        }
        if (array_key_exists('allow_cid', $arr)) {
            $args['allow_cid'] = $arr['allow_cid'];
        }
        if (array_key_exists('allow_gid', $arr)) {
            $args['allow_gid'] = $arr['allow_gid'];
        }
        if (array_key_exists('deny_cid', $arr)) {
            $args['deny_cid'] = $arr['deny_cid'];
        }
        if (array_key_exists('deny_gid', $arr)) {
            $args['deny_gid'] = $arr['deny_gid'];
        }
        $args['created'] = $created;
        $args['edited'] = $edited;
        if ($arr['item']) {
            $args['item'] = $arr['item'];
        }
        $p = photo_upload($channel, $observer, $args);
        if ($p['success']) {
            $ret['body'] = $p['body'];
        }
    }
    if ($options !== 'update' && $remove_when_processed) {
        @unlink($src);
    }
    if (!$r) {
        $ret['message'] = t('File upload failed. Possible system limit or action terminated.');
        call_hooks('photo_upload_end', $ret);
        return $ret;
    }
    // Caution: This re-uses $sql_options set further above
    $r = q("select id, aid, uid, hash, creator, filename, filetype, filesize, revision, folder, os_storage, is_photo, flags, created, edited, allow_cid, allow_gid, deny_cid, deny_gid from attach where uid = %d and hash = '%s' {$sql_options} limit 1", intval($channel_id), dbesc($hash));
    if (!$r) {
        $ret['message'] = t('Stored file could not be verified. Upload failed.');
        call_hooks('photo_upload_end', $ret);
        return $ret;
    }
    $ret['success'] = true;
    $ret['data'] = $r[0];
    if (!$is_photo) {
        // This would've been called already with a success result in photos_upload() if it was a photo.
        call_hooks('photo_upload_end', $ret);
    }
    return $ret;
}
示例#3
0
 function post()
 {
     $action = $_REQUEST['action'];
     if ($action) {
         switch ($action) {
             case 'scan':
                 // the state of this variable tracks whether website files have been scanned (null, true, false)
                 $cloud = null;
                 // Website files are to be imported from an uploaded zip file
                 if ($_FILES && array_key_exists('zip_file', $_FILES) && isset($_POST['w_upload'])) {
                     $source = $_FILES["zip_file"]["tmp_name"];
                     $type = $_FILES["zip_file"]["type"];
                     $okay = false;
                     $accepted_types = array('application/zip', 'application/x-zip-compressed', 'multipart/x-zip', 'application/x-compressed');
                     foreach ($accepted_types as $mime_type) {
                         if ($mime_type == $type) {
                             $okay = true;
                             break;
                         }
                     }
                     if (!$okay) {
                         notice(t('Invalid file type.') . EOL);
                         return;
                     }
                     $zip = new \ZipArchive();
                     if ($zip->open($source) === true) {
                         $tmp_folder_name = random_string(5);
                         $website = dirname($source) . '/' . $tmp_folder_name;
                         $zip->extractTo($website);
                         // change this to the correct site path
                         $zip->close();
                         @unlink($source);
                         // delete the compressed file now that the content has been extracted
                         $cloud = false;
                     } else {
                         notice(t('Error opening zip file') . EOL);
                         return null;
                     }
                 }
                 // Website files are to be imported from the channel cloud files
                 if ($_POST && array_key_exists('path', $_POST) && isset($_POST['cloudsubmit'])) {
                     $channel = \App::get_channel();
                     $dirpath = get_dirpath_by_cloudpath($channel, $_POST['path']);
                     if (!$dirpath) {
                         notice(t('Invalid folder path.') . EOL);
                         return null;
                     }
                     $cloud = true;
                 }
                 // If the website files were uploaded or specified in the cloud files, then $cloud
                 // should be either true or false
                 if ($cloud !== null) {
                     require_once 'include/import.php';
                     $elements = [];
                     if ($cloud) {
                         $path = $_POST['path'];
                     } else {
                         $path = $website;
                     }
                     $elements['pages'] = scan_webpage_elements($path, 'page', $cloud);
                     $elements['layouts'] = scan_webpage_elements($path, 'layout', $cloud);
                     $elements['blocks'] = scan_webpage_elements($path, 'block', $cloud);
                     $_SESSION['blocks'] = $elements['blocks'];
                     $_SESSION['layouts'] = $elements['layouts'];
                     $_SESSION['pages'] = $elements['pages'];
                     if (!(empty($elements['pages']) && empty($elements['blocks']) && empty($elements['layouts']))) {
                         //info( t('Webpages elements detected.') . EOL);
                         $_SESSION['action'] = 'import';
                     } else {
                         notice(t('No webpage elements detected.') . EOL);
                         $_SESSION['action'] = null;
                     }
                 }
                 // If the website elements were imported from a zip file, delete the temporary decompressed files
                 if ($cloud === false && $website && $elements) {
                     $_SESSION['tempimportpath'] = $website;
                     //rrmdir($website);	// Delete the temporary decompressed files
                 }
                 break;
             case 'importselected':
                 require_once 'include/import.php';
                 $channel = \App::get_channel();
                 // Import layout first so that pages that reference new layouts will find
                 // the mid of layout items in the database
                 // Obtain the user-selected layouts to import and import them
                 $checkedlayouts = $_POST['layout'];
                 $layouts = [];
                 if (!empty($checkedlayouts)) {
                     foreach ($checkedlayouts as $name) {
                         foreach ($_SESSION['layouts'] as &$layout) {
                             if ($layout['name'] === $name) {
                                 $layout['import'] = 1;
                                 $layoutstoimport[] = $layout;
                             }
                         }
                     }
                     foreach ($layoutstoimport as $elementtoimport) {
                         $layouts[] = import_webpage_element($elementtoimport, $channel, 'layout');
                     }
                 }
                 $_SESSION['import_layouts'] = $layouts;
                 // Obtain the user-selected blocks to import and import them
                 $checkedblocks = $_POST['block'];
                 $blocks = [];
                 if (!empty($checkedblocks)) {
                     foreach ($checkedblocks as $name) {
                         foreach ($_SESSION['blocks'] as &$block) {
                             if ($block['name'] === $name) {
                                 $block['import'] = 1;
                                 $blockstoimport[] = $block;
                             }
                         }
                     }
                     foreach ($blockstoimport as $elementtoimport) {
                         $blocks[] = import_webpage_element($elementtoimport, $channel, 'block');
                     }
                 }
                 $_SESSION['import_blocks'] = $blocks;
                 // Obtain the user-selected pages to import and import them
                 $checkedpages = $_POST['page'];
                 $pages = [];
                 if (!empty($checkedpages)) {
                     foreach ($checkedpages as $pagelink) {
                         foreach ($_SESSION['pages'] as &$page) {
                             if ($page['pagelink'] === $pagelink) {
                                 $page['import'] = 1;
                                 $pagestoimport[] = $page;
                             }
                         }
                     }
                     foreach ($pagestoimport as $elementtoimport) {
                         $pages[] = import_webpage_element($elementtoimport, $channel, 'page');
                     }
                 }
                 $_SESSION['import_pages'] = $pages;
                 if (!(empty($_SESSION['import_pages']) && empty($_SESSION['import_blocks']) && empty($_SESSION['import_layouts']))) {
                     info(t('Import complete.') . EOL);
                 }
                 if (isset($_SESSION['tempimportpath'])) {
                     rrmdir($_SESSION['tempimportpath']);
                     // Delete the temporary decompressed files
                     unset($_SESSION['tempimportpath']);
                 }
                 break;
             case 'exportzipfile':
                 if (isset($_POST['w_download'])) {
                     $_SESSION['action'] = 'export_select_list';
                     $_SESSION['export'] = 'zipfile';
                     if (isset($_POST['zipfilename']) && $_POST['zipfilename'] !== '') {
                         $filename = filter_var($_POST['zipfilename'], FILTER_SANITIZE_ENCODED);
                     } else {
                         $filename = 'website.zip';
                     }
                     $_SESSION['zipfilename'] = $filename;
                 }
                 break;
             case 'exportcloud':
                 if (isset($_POST['exportcloudpath']) && $_POST['exportcloudpath'] !== '') {
                     $_SESSION['action'] = 'export_select_list';
                     $_SESSION['export'] = 'cloud';
                     $_SESSION['exportcloudpath'] = filter_var($_POST['exportcloudpath'], FILTER_SANITIZE_ENCODED);
                 }
                 break;
             case 'cloud':
             case 'zipfile':
                 $channel = \App::get_channel();
                 $tmp_folder_name = random_string(10);
                 $zip_folder_name = random_string(10);
                 $zip_filename = $_SESSION['zipfilename'];
                 $tmp_folderpath = '/tmp/' . $tmp_folder_name;
                 $zip_folderpath = '/tmp/' . $zip_folder_name;
                 if (!mkdir($zip_folderpath, 0770, false)) {
                     logger('Error creating zip file export folder: ' . $zip_folderpath, LOGGER_NORMAL);
                     json_return_and_die(array('message' => 'Error creating zip file export folder'));
                 }
                 $zip_filepath = '/tmp/' . $zip_folder_name . '/' . $zip_filename;
                 $checkedblocks = $_POST['block'];
                 $blocks = [];
                 if (!empty($checkedblocks)) {
                     foreach ($checkedblocks as $mid) {
                         $b = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig \n\t\t\t\t\t\t\t\t\t\t\t\tleft join item on item.id = iconfig.iid \n\t\t\t\t\t\t\t\t\t\t\t\twhere mid = '%s' and item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'BUILDBLOCK' order by iconfig.v asc limit 1", dbesc($mid), intval($channel['channel_id']));
                         if ($b) {
                             $b = $b[0];
                             $blockinfo = array('body' => $b['body'], 'mimetype' => $b['mimetype'], 'title' => $b['title'], 'name' => $b['v'], 'json' => array('title' => $b['title'], 'name' => $b['v'], 'mimetype' => $b['mimetype']));
                             switch ($blockinfo['mimetype']) {
                                 case 'text/html':
                                     $block_ext = 'html';
                                     break;
                                 case 'text/bbcode':
                                     $block_ext = 'bbcode';
                                     break;
                                 case 'text/markdown':
                                     $block_ext = 'md';
                                     break;
                                 case 'application/x-pdl':
                                     $block_ext = 'pdl';
                                     break;
                                 case 'application/x-php':
                                     $block_ext = 'php';
                                     break;
                                 default:
                                     $block_ext = 'bbcode';
                                     break;
                             }
                             $block_filename = $blockinfo['name'] . '.' . $block_ext;
                             $tmp_blockfolder = $tmp_folderpath . '/blocks/' . $blockinfo['name'];
                             $block_filepath = $tmp_blockfolder . '/' . $block_filename;
                             $blockinfo['json']['contentfile'] = $block_filename;
                             $block_jsonpath = $tmp_blockfolder . '/block.json';
                             if (!is_dir($tmp_blockfolder) && !mkdir($tmp_blockfolder, 0770, true)) {
                                 logger('Error creating temp export folder: ' . $tmp_blockfolder, LOGGER_NORMAL);
                                 json_return_and_die(array('message' => 'Error creating temp export folder'));
                             }
                             file_put_contents($block_filepath, $blockinfo['body']);
                             file_put_contents($block_jsonpath, json_encode($blockinfo['json'], JSON_UNESCAPED_SLASHES));
                         }
                     }
                 }
                 $checkedlayouts = $_POST['layout'];
                 $layouts = [];
                 if (!empty($checkedlayouts)) {
                     foreach ($checkedlayouts as $mid) {
                         $l = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig \n\t\t\t\t\t\t\t\t\t\t\t\tleft join item on item.id = iconfig.iid \n\t\t\t\t\t\t\t\t\t\t\t\twhere mid = '%s' and item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'PDL' order by iconfig.v asc limit 1", dbesc($mid), intval($channel['channel_id']));
                         if ($l) {
                             $l = $l[0];
                             $layoutinfo = array('body' => $l['body'], 'mimetype' => $l['mimetype'], 'description' => $l['title'], 'name' => $l['v'], 'json' => array('description' => $l['title'], 'name' => $l['v'], 'mimetype' => $l['mimetype']));
                             switch ($layoutinfo['mimetype']) {
                                 case 'text/bbcode':
                                 default:
                                     $layout_ext = 'bbcode';
                                     break;
                             }
                             $layout_filename = $layoutinfo['name'] . '.' . $layout_ext;
                             $tmp_layoutfolder = $tmp_folderpath . '/layouts/' . $layoutinfo['name'];
                             $layout_filepath = $tmp_layoutfolder . '/' . $layout_filename;
                             $layoutinfo['json']['contentfile'] = $layout_filename;
                             $layout_jsonpath = $tmp_layoutfolder . '/layout.json';
                             if (!is_dir($tmp_layoutfolder) && !mkdir($tmp_layoutfolder, 0770, true)) {
                                 logger('Error creating temp export folder: ' . $tmp_layoutfolder, LOGGER_NORMAL);
                                 json_return_and_die(array('message' => 'Error creating temp export folder'));
                             }
                             file_put_contents($layout_filepath, $layoutinfo['body']);
                             file_put_contents($layout_jsonpath, json_encode($layoutinfo['json'], JSON_UNESCAPED_SLASHES));
                         }
                     }
                 }
                 $checkedpages = $_POST['page'];
                 $pages = [];
                 if (!empty($checkedpages)) {
                     foreach ($checkedpages as $mid) {
                         $p = q("select * from iconfig left join item on iconfig.iid = item.id \n\t\t\t\t\t\t\t\t\t\t\t\twhere item.uid = %d and item.mid = '%s' and iconfig.cat = 'system' and iconfig.k = 'WEBPAGE' and item_type = %d", intval($channel['channel_id']), dbesc($mid), intval(ITEM_TYPE_WEBPAGE));
                         if ($p) {
                             foreach ($p as $pp) {
                                 // Get the associated layout
                                 $layoutinfo = array();
                                 if ($pp['layout_mid']) {
                                     $l = q("select iconfig.v, iconfig.k, mimetype, title, body from iconfig \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tleft join item on item.id = iconfig.iid \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\twhere mid = '%s' and item.uid = %d and iconfig.cat = 'system' and iconfig.k = 'PDL' order by iconfig.v asc limit 1", dbesc($pp['layout_mid']), intval($channel['channel_id']));
                                     if ($l) {
                                         $l = $l[0];
                                         $layoutinfo = array('body' => $l['body'], 'mimetype' => $l['mimetype'], 'description' => $l['title'], 'name' => $l['v'], 'json' => array('description' => $l['title'], 'name' => $l['v']));
                                         switch ($layoutinfo['mimetype']) {
                                             case 'text/bbcode':
                                             default:
                                                 $layout_ext = 'bbcode';
                                                 break;
                                         }
                                         $layout_filename = $layoutinfo['name'] . '.' . $layout_ext;
                                         $tmp_layoutfolder = $tmp_folderpath . '/layouts/' . $layoutinfo['name'];
                                         $layout_filepath = $tmp_layoutfolder . '/' . $layout_filename;
                                         $layoutinfo['json']['contentfile'] = $layout_filename;
                                         $layout_jsonpath = $tmp_layoutfolder . '/layout.json';
                                         if (!is_dir($tmp_layoutfolder) && !mkdir($tmp_layoutfolder, 0770, true)) {
                                             logger('Error creating temp export folder: ' . $tmp_layoutfolder, LOGGER_NORMAL);
                                             json_return_and_die(array('message' => 'Error creating temp export folder'));
                                         }
                                         file_put_contents($layout_filepath, $layoutinfo['body']);
                                         file_put_contents($layout_jsonpath, json_encode($layoutinfo['json'], JSON_UNESCAPED_SLASHES));
                                     }
                                 }
                                 switch ($pp['mimetype']) {
                                     case 'text/html':
                                         $page_ext = 'html';
                                         break;
                                     case 'text/bbcode':
                                         $page_ext = 'bbcode';
                                         break;
                                     case 'text/markdown':
                                         $page_ext = 'md';
                                         break;
                                     case 'application/x-pdl':
                                         $page_ext = 'pdl';
                                         break;
                                     case 'application/x-php':
                                         $page_ext = 'php';
                                         break;
                                     default:
                                         break;
                                 }
                                 $pageinfo = array('title' => $pp['title'], 'body' => $pp['body'], 'pagelink' => $pp['v'], 'mimetype' => $pp['mimetype'], 'contentfile' => $pp['v'] . '.' . $page_ext, 'layout' => x($layoutinfo, 'name') ? $layoutinfo['name'] : '', 'json' => array('title' => $pp['title'], 'pagelink' => $pp['v'], 'mimetype' => $pp['mimetype'], 'layout' => x($layoutinfo, 'name') ? $layoutinfo['name'] : ''));
                                 $page_filename = $pageinfo['pagelink'] . '.' . $page_ext;
                                 $tmp_pagefolder = $tmp_folderpath . '/pages/' . $pageinfo['pagelink'];
                                 $page_filepath = $tmp_pagefolder . '/' . $page_filename;
                                 $page_jsonpath = $tmp_pagefolder . '/page.json';
                                 $pageinfo['json']['contentfile'] = $page_filename;
                                 if (!is_dir($tmp_pagefolder) && !mkdir($tmp_pagefolder, 0770, true)) {
                                     logger('Error creating temp export folder: ' . $tmp_pagefolder, LOGGER_NORMAL);
                                     json_return_and_die(array('message' => 'Error creating temp export folder'));
                                 }
                                 file_put_contents($page_filepath, $pageinfo['body']);
                                 file_put_contents($page_jsonpath, json_encode($pageinfo['json'], JSON_UNESCAPED_SLASHES));
                             }
                         }
                     }
                 }
                 if ($action === 'zipfile') {
                     // Generate the zip file
                     \Zotlabs\Lib\ExtendedZip::zipTree($tmp_folderpath, $zip_filepath, \ZipArchive::CREATE);
                     // Output the file for download
                     header('Content-disposition: attachment; filename="' . $zip_filename . '"');
                     header("Content-Type: application/zip");
                     $success = readfile($zip_filepath);
                 } elseif ($action === 'cloud') {
                     // Only zipfile or cloud should be possible values for $action here
                     if (isset($_SESSION['exportcloudpath'])) {
                         require_once 'include/attach.php';
                         $cloudpath = urldecode($_SESSION['exportcloudpath']);
                         $channel = \App::get_channel();
                         $dirpath = get_dirpath_by_cloudpath($channel, $cloudpath);
                         if (!$dirpath) {
                             $x = attach_mkdirp($channel, $channel['channel_hash'], array('pathname' => $cloudpath));
                             $folder_hash = $x['success'] ? $x['data']['hash'] : '';
                             if (!$x['success']) {
                                 logger('Failed to create cloud file folder', LOGGER_NORMAL);
                             }
                             $dirpath = get_dirpath_by_cloudpath($channel, $cloudpath);
                             if (!is_dir($dirpath)) {
                                 logger('Failed to create cloud file folder', LOGGER_NORMAL);
                             }
                         }
                         $success = copy_folder_to_cloudfiles($channel, $channel['channel_hash'], $tmp_folderpath, $cloudpath);
                     }
                 }
                 if (!$success) {
                     logger('Error exporting webpage elements', LOGGER_NORMAL);
                 }
                 rrmdir($zip_folderpath);
                 rrmdir($tmp_folderpath);
                 // delete temporary files
                 break;
             default:
                 break;
         }
     }
 }