changes
This commit is contained in:
37
reference/Wpress-Extractor-master/README.md
Normal file
37
reference/Wpress-Extractor-master/README.md
Normal file
@ -0,0 +1,37 @@
|
||||
# Wpress-Extractor Windows/Mac
|
||||
A simple windows app that allows you to extract .wpress files created by the awesome All-in-one-Wp-Migration Wordpress plugin
|
||||
|
||||
## Credits
|
||||
The extractor source code : [https://github.com/yani-/wpress](https://github.com/yani-/wpress). I had to make a tiny modification to their reader.go file to allow it to run on Windows systems.
|
||||
|
||||
## Download link
|
||||
[Windows - Download now](https://github.com/fifthsegment/Wpress-Extractor/raw/master/dist/wpress-extractor.exe)
|
||||
|
||||
[Mac - Download now](https://github.com/fifthsegment/Wpress-Extractor/blob/master/dist/mac/wpress_extractor?raw=true)
|
||||
*IMPORTANT FOR MAC: Don't forget to make the binary executable by running a `chmod +x wpress_extractor` on the downloaded file via the Terminal.
|
||||
|
||||
|
||||
## How to extract/open .wpress files ?
|
||||
Simply provide a path to your downloaded .wpress file as the first commandline argument to the program.
|
||||
`./wpress_extractor /path/to/my/backup.wpress`
|
||||
|
||||
## I'm not very technical - How to use this thing?
|
||||
### Windows Instructions
|
||||
|
||||
Simply download the extractor then drop your.wpress file onto the executable (Wpress-extractor.exe). ([Thanks hughc](https://github.com/hughc)!)
|
||||
|
||||
|
||||
OR
|
||||
|
||||
|
||||
|
||||
1. Download the extractor
|
||||
2. Create a directory where you wish your files to be extracted to
|
||||
3. Copy the downloaded extractor to that directory
|
||||
4. Copy your .wpress file to that directory as well
|
||||
5. Open up a command prompt
|
||||
6. CD into the directory you just created, let's say its C:\Wordpress-Backup. The command you'll run would be `cd C:\Wordpress-Backup`
|
||||
7. Now run the following command `wpress-extractor <name-of-your.wpress file>`. For example my .wpress file was fifthsegment.wpress so the command I ran was `wpress-extractor fifthsegment.wpress`.
|
||||
8. You'll find your files extracted into the same directory where the extractor was run. In my case it was `C:\Wordpress-Backup`
|
||||
|
||||
|
147
reference/Wpress-Extractor-master/inc/common.go
Normal file
147
reference/Wpress-Extractor-master/inc/common.go
Normal file
@ -0,0 +1,147 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Yani Iliev <yani@iliev.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package wpress
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
const (
|
||||
headerSize = 4377 // length of the header
|
||||
filenameSize = 255 // maximum number of bytes allowed for filename
|
||||
contentSize = 14 // maximum number of bytes allowed for content size
|
||||
mtimeSize = 12 // maximum number of bytes allowed for last modified date
|
||||
prefixSize = 4096 // maximum number of bytes allowed for prefix
|
||||
)
|
||||
|
||||
// Header block format of a file
|
||||
// Field Name Offset Length Contents
|
||||
// Name 0 255 filename (no path, no slash)
|
||||
// Size 255 14 length of file contents
|
||||
// Mtime 269 12 last modification date
|
||||
// Prefix 281 4096 path name, no trailing slashes
|
||||
type Header struct {
|
||||
Name []byte
|
||||
Size []byte
|
||||
Mtime []byte
|
||||
Prefix []byte
|
||||
}
|
||||
|
||||
// PopulateFromBytes populates header struct from bytes array
|
||||
func (h *Header) PopulateFromBytes(block []byte) {
|
||||
h.Name = block[0:255]
|
||||
h.Size = block[255:269]
|
||||
h.Mtime = block[269:281]
|
||||
h.Prefix = block[281:4377]
|
||||
}
|
||||
|
||||
// PopulateFromFilename populates header struct from passed filename
|
||||
func (h *Header) PopulateFromFilename(filename string) error {
|
||||
|
||||
// try to open the file
|
||||
file, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// get the fileinfo
|
||||
fi, err := file.Stat()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// validate if filename fits the allowed length
|
||||
if len(fi.Name()) > filenameSize {
|
||||
return errors.New("filename is longer than max allowed")
|
||||
}
|
||||
// create filename buffer
|
||||
h.Name = make([]byte, filenameSize)
|
||||
// copy filename to the buffer leaving available space as zero-bytes
|
||||
copy(h.Name, fi.Name())
|
||||
|
||||
// get filesize as string
|
||||
size := strconv.FormatInt(fi.Size(), 10)
|
||||
// validate if filesize fits the allowed length
|
||||
if len(size) > contentSize {
|
||||
return errors.New("file size is larger than max allowed")
|
||||
}
|
||||
// create size buffer
|
||||
h.Size = make([]byte, contentSize)
|
||||
// copy content size length to the buffer
|
||||
copy(h.Size, size)
|
||||
|
||||
// get last modified date as string
|
||||
unixTime := strconv.FormatInt(fi.ModTime().Unix(), 10)
|
||||
if len(unixTime) > mtimeSize {
|
||||
return errors.New("last modified date is after than max allowed")
|
||||
}
|
||||
// create mtime buffer
|
||||
h.Mtime = make([]byte, mtimeSize)
|
||||
// copy mtime to the buffer
|
||||
copy(h.Mtime, unixTime)
|
||||
|
||||
// get the path to the file
|
||||
_path := filepath.Dir(filename)
|
||||
// validate if path fits the allowed length
|
||||
if len(_path) > prefixSize {
|
||||
return errors.New("prefix size is longer than max allowed")
|
||||
}
|
||||
// create buffer to put the prefix in
|
||||
h.Prefix = make([]byte, prefixSize)
|
||||
// put the prefix in the buffer
|
||||
copy(h.Prefix, _path)
|
||||
|
||||
// close the file
|
||||
err = file.Close()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetHeaderBlock returns byte sequence of header block populated with data
|
||||
func (h Header) GetHeaderBlock() []byte {
|
||||
block := append(h.Name, h.Size...)
|
||||
block = append(block, h.Mtime...)
|
||||
block = append(block, h.Prefix...)
|
||||
return block
|
||||
}
|
||||
|
||||
// GetSize returns content size
|
||||
func (h Header) GetSize() (int, error) {
|
||||
// remove any trailing zero bytes, convert to string, then convert to integer
|
||||
return strconv.Atoi(string(bytes.Trim(h.Size, "\x00")))
|
||||
}
|
||||
|
||||
// GetEOFBlock returns byte sequence describing EOF
|
||||
func (h Header) GetEOFBlock() []byte {
|
||||
// generate zero-byte sequence of length headerSize
|
||||
return bytes.Repeat([]byte("\x00"), headerSize)
|
||||
}
|
226
reference/Wpress-Extractor-master/inc/reader.go
Normal file
226
reference/Wpress-Extractor-master/inc/reader.go
Normal file
@ -0,0 +1,226 @@
|
||||
/**
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* Copyright (c) 2014 Yani Iliev <yani@iliev.me>
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
* of this software and associated documentation files (the "Software"), to deal
|
||||
* in the Software without restriction, including without limitation the rights
|
||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
* copies of the Software, and to permit persons to whom the Software is
|
||||
* furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in
|
||||
* all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
package wpress
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const PATH_SEPARATOR_WIN = '\\'
|
||||
const PATH_SEPARATOR_UNIX = '/'
|
||||
|
||||
// Reader structure
|
||||
type Reader struct {
|
||||
Filename string
|
||||
File *os.File
|
||||
NumberOfFiles int
|
||||
}
|
||||
|
||||
// NewReader creates a new Reader instance and calls its constructor
|
||||
func NewReader(filename string) (*Reader, error) {
|
||||
// create a new instance of Reader
|
||||
r := &Reader{filename, nil, 0}
|
||||
|
||||
// call the constructor
|
||||
err := r.Init()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// return Reader instance
|
||||
return r, nil
|
||||
}
|
||||
|
||||
// Init is the constructor of Reader struct
|
||||
func (r *Reader) Init() error {
|
||||
// try to open the file
|
||||
file, err := os.Open(r.Filename)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// file was openned, assign the handle to the holding variable
|
||||
r.File = file
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// ExtractFile extracts file that matches tha filename and path from archive
|
||||
func (r Reader) ExtractFile(filename string, path string) ([]byte, error) {
|
||||
// TODO: implement
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
// Extract all files from archive
|
||||
func (r Reader) Extract() (int, error) {
|
||||
// put pointer at the beginning of the file
|
||||
r.File.Seek(0, 0)
|
||||
|
||||
// loop until end of file was reached
|
||||
iteration := 0;
|
||||
for {
|
||||
iteration++;
|
||||
// read header block
|
||||
block, err := r.GetHeaderBlock()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// initialize new header
|
||||
h := &Header{}
|
||||
|
||||
// check if block equals EOF sequence
|
||||
if bytes.Compare(block, h.GetEOFBlock()) == 0 {
|
||||
// EOF reached, stop the loop
|
||||
break
|
||||
}
|
||||
|
||||
// populate header from our block bytes
|
||||
h.PopulateFromBytes(block)
|
||||
|
||||
pathToFile := path.Clean("." + string(os.PathSeparator) + string(bytes.Trim(h.Prefix, "\x00")) + string(os.PathSeparator) + string(bytes.Trim(h.Name, "\x00")))
|
||||
if runtime.GOOS == "windows" {
|
||||
sep := fmt.Sprintf("%c", PATH_SEPARATOR_UNIX)
|
||||
pathToFile = strings.Replace(pathToFile,"\\",sep,-1)
|
||||
fmt.Println(pathToFile)
|
||||
}
|
||||
|
||||
err = os.MkdirAll(path.Dir(pathToFile), 0777)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return r.NumberOfFiles, err
|
||||
}
|
||||
|
||||
// try to open the file
|
||||
|
||||
|
||||
|
||||
file, err := os.Create(pathToFile)
|
||||
if err != nil {
|
||||
return r.NumberOfFiles, err
|
||||
}
|
||||
|
||||
totalBytesToRead, _ := h.GetSize()
|
||||
for {
|
||||
bytesToRead := 512
|
||||
if bytesToRead > totalBytesToRead {
|
||||
bytesToRead = totalBytesToRead
|
||||
}
|
||||
|
||||
if bytesToRead == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
content := make([]byte, bytesToRead)
|
||||
bytesRead, err := r.File.Read(content)
|
||||
if err != nil {
|
||||
return r.NumberOfFiles, err
|
||||
}
|
||||
|
||||
totalBytesToRead -= bytesRead
|
||||
contentRead := content[0:bytesRead]
|
||||
|
||||
_, err = file.Write(contentRead)
|
||||
if err != nil {
|
||||
return r.NumberOfFiles, err
|
||||
}
|
||||
}
|
||||
|
||||
file.Close()
|
||||
|
||||
// increment file counter
|
||||
r.NumberOfFiles++
|
||||
}
|
||||
|
||||
return r.NumberOfFiles, nil
|
||||
}
|
||||
|
||||
// GetHeaderBlock reads and returns header block from archive
|
||||
func (r Reader) GetHeaderBlock() ([]byte, error) {
|
||||
// create buffer to keep the header block
|
||||
block := make([]byte, headerSize)
|
||||
|
||||
// read the header block
|
||||
bytesRead, err := r.File.Read(block)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if bytesRead != headerSize {
|
||||
return nil, errors.New("unable to read header block size")
|
||||
}
|
||||
|
||||
return block, nil
|
||||
}
|
||||
|
||||
// GetFilesCount returns the number of files in archive
|
||||
func (r Reader) GetFilesCount() (int, error) {
|
||||
// test if we have enumerated the archive already
|
||||
if r.NumberOfFiles != 0 {
|
||||
return r.NumberOfFiles, nil
|
||||
}
|
||||
|
||||
// put pointer at the beginning of the file
|
||||
r.File.Seek(0, 0)
|
||||
|
||||
// loop until end of file was reached
|
||||
for {
|
||||
// read header block
|
||||
block, err := r.GetHeaderBlock()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// initialize new header
|
||||
h := &Header{}
|
||||
|
||||
// check if block equals EOF sequence
|
||||
if bytes.Compare(block, h.GetEOFBlock()) == 0 {
|
||||
// EOF reached, stop the loop
|
||||
break
|
||||
}
|
||||
|
||||
// populate header from our block bytes
|
||||
h.PopulateFromBytes(block)
|
||||
|
||||
// set pointer after file content, to the next header block
|
||||
size, err := h.GetSize()
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
r.File.Seek(int64(size), 1)
|
||||
|
||||
// increment file counter
|
||||
r.NumberOfFiles++
|
||||
}
|
||||
|
||||
return r.NumberOfFiles, nil
|
||||
}
|
33
reference/Wpress-Extractor-master/wpress-extractor.go
Normal file
33
reference/Wpress-Extractor-master/wpress-extractor.go
Normal file
@ -0,0 +1,33 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"github.com/yani-/wpress"
|
||||
"os"
|
||||
)
|
||||
|
||||
func main() {
|
||||
fmt.Printf("Wpress Extracter.\n")
|
||||
|
||||
if ( len(os.Args) == 2 ){
|
||||
pathTofile := os.Args[1]
|
||||
fmt.Println(pathTofile);
|
||||
archiver, _ := wpress.NewReader(pathTofile)
|
||||
_ , err := archiver.Extract();
|
||||
if (err!=nil){
|
||||
fmt.Println("Error = ");
|
||||
fmt.Println(err);
|
||||
}else{
|
||||
fmt.Println("All done!");
|
||||
}
|
||||
|
||||
|
||||
// fmt.Println("total files = ", i, " files read = ", x);
|
||||
}else{
|
||||
fmt.Println("Inorder to run the extractor please provide the path to the .wpress file as the first argument.");
|
||||
}
|
||||
|
||||
// wpress.Init(archiver);
|
||||
|
||||
|
||||
}
|
Reference in New Issue
Block a user