github.com/readium/readium-lcp-server@v0.0.0-20240101192032-6e95190e99f1/lcpencrypt/lcpencrypt.go (about)

     1  // Copyright 2020 Readium Foundation. All rights reserved.
     2  // Use of this source code is governed by a BSD-style license
     3  // that can be found in the LICENSE file exposed on Github (readium) in the project repository.
     4  
     5  package main
     6  
     7  import (
     8  	"errors"
     9  	"flag"
    10  	"fmt"
    11  	"os"
    12  	"path/filepath"
    13  	"time"
    14  
    15  	"github.com/readium/readium-lcp-server/encrypt"
    16  )
    17  
    18  // showHelpAndExit displays some help and exits.
    19  func showHelpAndExit() {
    20  
    21  	fmt.Println("lcpencrypt encrypts a publication using the LCP DRM.")
    22  	fmt.Println("-input      source epub/pdf/lpf/audiobook file locator (file system or http GET)")
    23  	fmt.Println("-contentid  optional, content identifier; if omitted a uuid is generated")
    24  	fmt.Println("-storage    optional, target location of the encrypted publication, without filename. File system path or s3 bucket")
    25  	fmt.Println("-url        optional, base url associated with the storage, without filename")
    26  	fmt.Println("-filename   optional, file name of the encrypted publication; if omitted, contentid is used")
    27  	fmt.Println("-temp       optional, working folder for temporary files. If not set, the current directory will be used.")
    28  	fmt.Println("-cover      optional, boolean, indicates that covers must be generated when possible")
    29  	fmt.Println("-contentkey optional, base64 encoded content key; if omitted a random content key is generated")
    30  	fmt.Println("-lcpsv      optional, URL, host name of the License Server to be notified; syntax http://username:password@example.com")
    31  	fmt.Println("-v2         optional, boolean, indicates communication with a License Server v2")
    32  	// these parameters are deprecated, let's be silent about them in the help
    33  	//fmt.Println("-login      optional, used along with lcpsv, username for the License server")
    34  	//fmt.Println("-password   optional, used along with lcpsv, password for the License server")
    35  	fmt.Println("-notify     optional, URL, notification endpoint of a CMS; syntax http://username:password@example.com")
    36  	fmt.Println("-verbose    optional, boolean, the information sent to the LCP Server and CMS will be displayed")
    37  	fmt.Println("-output     optional, deprecated, temporary location of encrypted publications, before the License Server moves them. File system path only. This path must be directly accessible from the License Server. If not set, encrypted publications will be temporarily created into the current directory.")
    38  	fmt.Println("-help :     help information")
    39  	os.Exit(0)
    40  }
    41  
    42  // exitWithError outputs an error message and exits.
    43  func exitWithError(context string, err error) {
    44  
    45  	fmt.Println(context, ":", err.Error())
    46  	os.Exit(1)
    47  }
    48  
    49  func main() {
    50  	inputPath := flag.String("input", "", "source epub/pdf/lpf file locator (file system or http GET)")
    51  	contentid := flag.String("contentid", "", "optional, content identifier; if omitted, a uuid is generated")
    52  	storageRepo := flag.String("storage", "", "optional, target location of the encrypted publication, without filename. File system path or s3 bucket")
    53  	storageURL := flag.String("url", "", "optional, base url associated with the storage, without filename")
    54  	storageFilename := flag.String("filename", "", "optional, file name of the encrypted publication; if omitted, contentid is used")
    55  	outputRepo := flag.String("output", "", "optional, target folder of encrypted publications")
    56  	tempRepo := flag.String("temp", "", "optional, working folder for temporary files")
    57  	cover := flag.Bool("cover", false, "optional, boolean, indicates that covers must be generated when possible")
    58  	contentkey := flag.String("contentkey", "", "optional, base64 encoded content key; if omitted a random content key is generated")
    59  	lcpsv := flag.String("lcpsv", "", "URL, host name of the License server which is notified; the preferred syntax is http://username:password@example.com")
    60  	v2 := flag.Bool("v2", false, "optional, boolean, indicates a v2 License serve")
    61  	username := flag.String("login", "", "optional unless lcpsv is used, username for the License server")
    62  	password := flag.String("password", "", "optional unless lcpsv is used, password for the License server")
    63  	notify := flag.String("notify", "", "optional, URL, notification endpoint for a CMS; its syntax is http://username:password@example.com")
    64  	verbose := flag.Bool("verbose", false, "optional, boolean, the information sent to the LCP Server and CMS will be displayed")
    65  
    66  	help := flag.Bool("help", false, "shows information")
    67  
    68  	if !flag.Parsed() {
    69  		flag.Parse()
    70  	}
    71  
    72  	if *help || *inputPath == "" {
    73  		showHelpAndExit()
    74  	}
    75  
    76  	if *storageRepo != "" && *storageURL == "" {
    77  		exitWithError("Parameters", errors.New("incorrect parameters, storage requires url, for more information type 'lcpencrypt -help' "))
    78  	}
    79  	if filepath.Ext(*outputRepo) != "" {
    80  		exitWithError("Parameters", errors.New("incorrect parameters, output must not contain a file name, for more information type 'lcpencrypt -help' "))
    81  	}
    82  	if filepath.Ext(*storageRepo) != "" {
    83  		exitWithError("Parameters", errors.New("incorrect parameters, storage must not contain a file name, for more information type 'lcpencrypt -help' "))
    84  	}
    85  
    86  	start := time.Now()
    87  
    88  	// encrypt the publication
    89  	publication, err := encrypt.ProcessEncryption(*contentid, *contentkey, *inputPath, *tempRepo, *outputRepo, *storageRepo, *storageURL, *storageFilename, *cover)
    90  	if err != nil {
    91  		exitWithError("Error processing a publication", err)
    92  	}
    93  
    94  	elapsed := time.Since(start)
    95  
    96  	// notify the license server
    97  	err = encrypt.NotifyLCPServer(*publication, *lcpsv, *v2, *username, *password, *verbose)
    98  	if err != nil {
    99  		exitWithError("Error notifying the LCP Server", err)
   100  	}
   101  
   102  	// notify a CMS (v2 syntax; username and password are always in the URL)
   103  	err = encrypt.NotifyCMS(*publication, *notify, *verbose)
   104  	if err != nil {
   105  		fmt.Println("Error notifying the CMS:", err.Error())
   106  		// abort the notification of the license server
   107  		err = encrypt.AbortNotification(*publication, *lcpsv, *v2, *username, *password)
   108  		if err != nil {
   109  			exitWithError("Error aborting notification of the LCP Server", err)
   110  		}
   111  	}
   112  
   113  	fmt.Println("The encryption took", elapsed)
   114  	os.Exit(0)
   115  }