export async function createSelfSignedCert(publisher: string) {
  const tmpDir = new TmpDir()
  const targetDir = process.cwd()
  const tempPrefix = path.join(await tmpDir.getTempDir({prefix: "self-signed-cert-creator"}), sanitizeFileName(publisher))
  const cer = `${tempPrefix}.cer`
  const pvk = `${tempPrefix}.pvk`

  log.info(chalk.bold('When asked to enter a password ("Create Private Key Password"), please select "None".'))

  try {
    await ensureDir(path.dirname(tempPrefix))
    const vendorPath = path.join(await getSignVendorPath(), "windows-10", process.arch)
    await exec(path.join(vendorPath, "makecert.exe"),
      ["-r", "-h", "0", "-n", `CN=${quoteString(publisher)}`, "-eku", "1.3.6.1.5.5.7.3.3", "-pe", "-sv", pvk, cer])

    const pfx = path.join(targetDir, `${sanitizeFileName(publisher)}.pfx`)
    await unlinkIfExists(pfx)
    await exec(path.join(vendorPath, "pvk2pfx.exe"), ["-pvk", pvk, "-spc", cer, "-pfx", pfx])
    log.info({file: pfx}, `created. Please see https://electron.build/code-signing how to use it to sign.`)

    const certLocation = "Cert:\\LocalMachine\\TrustedPeople"
    log.info({file: pfx, certLocation}, `importing. Operation will be succeed only if runned from root. Otherwise import file manually.`)
    await spawn("powershell.exe", ["Import-PfxCertificate", "-FilePath", `"${pfx}"`, "-CertStoreLocation", ""])
  }
  finally {
    await tmpDir.cleanup()
  }
}
  async download(url: string, destination: string, options?: DownloadOptions | null): Promise<string> {
    if (options == null || !options.skipDirCreation) {
      await ensureDir(path.dirname(destination))
    }

    if (this.httpsAgentPromise == null) {
      this.httpsAgentPromise = createAgent()
    }

    const agent = await this.httpsAgentPromise
    return await new BluebirdPromise<string>((resolve, reject) => {
      const parsedUrl = parseUrl(url)
      this.doDownload(configureRequestOptions({
        hostname: parsedUrl.hostname,
        path: parsedUrl.path,
        headers: (options == null ? null : options.headers) || undefined,
        agent: agent,
      }), destination, 0, options || {}, (error: Error) => {
        if (error == null) {
          resolve(destination)
        }
        else {
          reject(error)
        }
      })
    })
  }
  async download(url: string, destination: string, options: DownloadOptions = {cancellationToken: new CancellationToken()}): Promise<string> {
    if (!options.skipDirCreation) {
      await ensureDir(path.dirname(destination))
    }

    if (this.httpsAgentPromise == null) {
      this.httpsAgentPromise = createAgent()
    }

    const agent = await this.httpsAgentPromise
    return await options.cancellationToken.createPromise<string>((resolve, reject, onCancel) => {
      const parsedUrl = parseUrl(url)
      this.doDownload(configureRequestOptions({
        hostname: parsedUrl.hostname,
        path: parsedUrl.path,
        headers: options.headers || undefined,
        agent,
      }), destination, 0, options, (error: Error) => {
        if (error == null) {
          resolve(destination)
        }
        else {
          reject(error)
        }
      }, onCancel)
    })
  }
Exemple #4
0
  async prepareWine(wineDir: string) {
    await emptyDir(wineDir)
    //noinspection SpellCheckingInspection
    const env = Object.assign({}, process.env, {
      WINEDLLOVERRIDES: "winemenubuilder.exe=d",
      WINEPREFIX: wineDir
    })

    await exec("wineboot", ["--init"], {env: env})

    // regedit often doesn't modify correctly
    let systemReg = await readFile(path.join(wineDir, "system.reg"), "utf8")
    systemReg = systemReg.replace('"CSDVersion"="Service Pack 3"', '"CSDVersion"=" "')
    systemReg = systemReg.replace('"CurrentBuildNumber"="2600"', '"CurrentBuildNumber"="10240"')
    systemReg = systemReg.replace('"CurrentVersion"="5.1"', '"CurrentVersion"="10.0"')
    systemReg = systemReg.replace('"ProductName"="Microsoft Windows XP"', '"ProductName"="Microsoft Windows 10"')
    systemReg = systemReg.replace('"CSDVersion"=dword:00000300', '"CSDVersion"=dword:00000000')
    await writeFile(path.join(wineDir, "system.reg"), systemReg)

    // remove links to host OS
    const desktopDir = path.join(this.userDir, "Desktop")
    await BluebirdPromise.all([
      unlinkIfExists(desktopDir),
      unlinkIfExists(path.join(this.userDir, "My Documents")),
      unlinkIfExists(path.join(this.userDir, "My Music")),
      unlinkIfExists(path.join(this.userDir, "My Pictures")),
      unlinkIfExists(path.join(this.userDir, "My Videos")),
    ])

    await ensureDir(desktopDir)
    return env
  }
 await BluebirdPromise.each(dirToCreate.get(parentDir)!, (it): any => {
   if (dirToCreate.has(parentDir + path.sep + it)) {
     // already created
     return null
   }
   else {
     return ensureDir(base + path.sep + it)
   }
 })
  //noinspection JSMethodCanBeStatic
  protected async doFlat(appPath: string, outFile: string, identity: Identity, keychain: string | n): Promise<any> {
    // productbuild doesn't created directory for out file
    await ensureDir(path.dirname(outFile))

    const args = prepareProductBuildArgs(identity, keychain)
    args.push("--component", appPath, "/Applications")
    args.push(outFile)
    return await exec("productbuild", args)
  }
 await BluebirdPromise.map(dirToCreate.keys(), async parentDir => {
   const base = unpackedDest + path.sep + parentDir
   await ensureDir(base)
   await BluebirdPromise.each(dirToCreate.get(parentDir)!, (it): any => {
     if (dirToCreate.has(parentDir + path.sep + it)) {
       // already created
       return null
     }
     else {
       return ensureDir(base + path.sep + it)
     }
   })
 }, CONCURRENCY)
function doDownload(url: string, destination: string, redirectCount: number, callback: (error: Error) => void) {
  const ensureDirPromise = ensureDir(path.dirname(destination))

  const parsedUrl = parseUrl(url)
  // user-agent must be specified, otherwise some host can return 401 unauthorised
  const request = https.request({
    hostname: parsedUrl.hostname,
    path: parsedUrl.path,
    headers: {
      "User-Agent": "electron-builder"
    }
  }, (response: IncomingMessage) => {
    if (response.statusCode >= 400) {
      callback(new Error("Request error, status " + response.statusCode + ": " + response.statusMessage))
      return
    }

    const redirectUrl = response.headers.location
    if (redirectUrl != null) {
      if (redirectCount < maxRedirects) {
        doDownload(redirectUrl, destination, redirectCount++, callback)
      }
      else {
        callback(new Error("Too many redirects (> " + maxRedirects + ")"))
      }
      return
    }

    ensureDirPromise
      .then(() => {
        const downloadStream = createWriteStream(destination)
        response.pipe(downloadStream)
        downloadStream.on("finish", () => downloadStream.close(callback))
      })
      .catch(callback)

    let ended = false
    response.on("end", () => {
      ended = true
    })

    response.on("close", () => {
      if (!ended) {
        callback(new Error("Request aborted"))
      }
    })
  })
  addTimeOutHandler(request, callback)
  request.on("error", callback)
  request.end()
}
export async function copyAppFiles(fileSet: FileSet, packager: Packager) {
  const metadata = fileSet.metadata
  const transformedFiles = fileSet.transformedFiles
  // search auto unpacked dir
  const unpackedDirs = new Set<string>()
  const taskManager = new AsyncTaskManager(packager.cancellationToken)
  const dirToCreateForUnpackedFiles = new Set<string>(unpackedDirs)

  const fileCopier = new FileCopier()
  const links: Array<Link> = []
  for (let i = 0, n = fileSet.files.length; i < n; i++) {
    const file = fileSet.files[i]
    const stat = metadata.get(file)
    if (stat == null) {
      // dir
      continue
    }

    const relativePath = file.replace(fileSet.src, fileSet.destination)
    if (stat.isFile()) {
      const fileParent = path.dirname(file)
      // const dirNode = this.fs.getOrCreateNode(this.getRelativePath(fileParent))

      const newData = transformedFiles == null ? null : transformedFiles[i] as string | Buffer
      if (newData != null) {
        transformedFiles[i] = null
      }

      if (!dirToCreateForUnpackedFiles.has(fileParent)) {
        dirToCreateForUnpackedFiles.add(fileParent)
        await ensureDir(fileParent.replace(fileSet.src, fileSet.destination))
      }

      taskManager.addTask(copyFileOrData(fileCopier, newData, file, relativePath, stat))
      if (taskManager.tasks.length > MAX_FILE_REQUESTS) {
        await taskManager.awaitTasks()
      }
    }
    else if (stat.isSymbolicLink()) {
      links.push({file: relativePath, link: await readlink(file)})
    }
  }

  if (taskManager.tasks.length > MAX_FILE_REQUESTS) {
    await taskManager.awaitTasks()
  }
  if (links.length > 0) {
    BluebirdPromise.map(links, it => symlink(it.link, it.file), CONCURRENCY)
  }
}
  // http://docs.aws.amazon.com/sdk-for-javascript/v2/developer-guide/s3-example-creating-buckets.html
  async upload(task: UploadTask): Promise<any> {
    const fileName = path.basename(task.file)
    const cancellationToken = this.context.cancellationToken

    const target = (this.options.path == null ? "" : `${this.options.path}/`) + fileName

    if (process.env.__TEST_S3_PUBLISHER__ != null) {
      const testFile = path.join(process.env.__TEST_S3_PUBLISHER__!, target)
      await ensureDir(path.dirname(testFile))
      await symlink(task.file, testFile)
      return
    }

    const s3Options: CreateMultipartUploadRequest  = {
      Key: target,
      Bucket: this.getBucketName(),
      ContentType: mime.getType(task.file) || "application/octet-stream"
    }
    this.configureS3Options(s3Options)

    const contentLength = task.fileContent == null ? (await stat(task.file)).size : task.fileContent.length
    const uploader = new Uploader(new S3(this.createClientConfiguration()), s3Options, task.file, contentLength, task.fileContent)

    const progressBar = this.createProgressBar(fileName, uploader.contentLength)
    if (progressBar != null) {
      const callback = new ProgressCallback(progressBar)
      uploader.on("progress", () => {
        if (!cancellationToken.cancelled) {
          callback.update(uploader.loaded, uploader.contentLength)
        }
      })
    }

    return await cancellationToken.createPromise((resolve, reject, onCancel) => {
      onCancel(() => uploader.abort())
      uploader.upload()
        .then(() => {
          try {
            log.debug({provider: this.providerName, file: fileName, bucket: this.getBucketName()}, "uploaded")
          }
          finally {
            resolve()
          }
        })
        .catch(reject)
    })
  }