コード例 #1
0
        public Yield PostImport(DreamContext context, DreamMessage request, Result<DreamMessage> response) {
            string uri = context.GetParam("uri", null);
            string reltopath = context.GetParam("reltopatch", "/");
            DreamMessage packageMessage = request;
            if(!string.IsNullOrEmpty(uri)) {
                Result<DreamMessage> packageResult;
                yield return packageResult = Plug.New(uri).InvokeEx("GET", DreamMessage.Ok(), new Result<DreamMessage>());
                packageMessage = packageResult.Value;
                if(!packageMessage.IsSuccessful) {
                    throw new DreamAbortException(DreamMessage.BadRequest(string.Format("Unable to retrieve package from Uri '{0}': {1}", uri, packageMessage.Status)));
                }
            }
            string tempFile = Path.GetTempFileName();
            Stream tempStream = File.Create(tempFile);
            Result<long> copyResult;

            // TODO (steveb): use WithCleanup() to dispose of resources in case of failure
            yield return copyResult = packageMessage.ToStream().CopyTo(tempStream, packageMessage.ContentLength, new Result<long>()).Catch();
            tempStream.Dispose();
            if(copyResult.HasException) {
                response.Throw(copyResult.Exception);
                yield break;
            }
            ArchivePackageReader archivePackageReader = new ArchivePackageReader(File.OpenRead(tempFile));
            Result<ImportManager> importerResult;
            Plug authorizedDekiApi = _dekiApi.WithHeaders(request.Headers);

            // TODO (steveb): use WithCleanup() to dispose of resources in case of failure
            yield return importerResult = ImportManager.CreateAsync(authorizedDekiApi, reltopath, archivePackageReader, new Result<ImportManager>()).Catch();
            if(importerResult.HasException) {
                archivePackageReader.Dispose();
                File.Delete(tempFile);
                response.Throw(importerResult.Exception);
                yield break;
            }
            ImportManager importManager = importerResult.Value;
            Result importResult;
            yield return importResult = importManager.ImportAsync(new Result()).Catch();
            archivePackageReader.Dispose();
            File.Delete(tempFile);
            if(importResult.HasException) {
                response.Throw(importResult.Exception);
                yield break;
            }
            response.Return(DreamMessage.Ok());
            yield break;
        }
コード例 #2
0
        public void Pack_and_unpack_manifest() {

            // Arrange
            string archiveFile = Path.Combine(Path.GetTempPath(), StringUtil.CreateAlphaNumericKey(6)+".zip");
            List<XDoc> docs = new List<XDoc>();
            docs.Add(new XDoc("doc1").Attr("dataid", "a"));
            docs.Add(new XDoc("doc2").Attr("dataid", "b"));
            docs.Add(new XDoc("doc3").Attr("dataid", "c"));
            List<Tuplet<string, MemoryStream>> data = new List<Tuplet<string, MemoryStream>>();
            foreach(XDoc doc in docs) {
                string id = doc["@dataid"].AsText;
                data.Add(new Tuplet<string, MemoryStream>(id, new MemoryStream(doc.ToBytes())));
            }
            XDoc manifest = new XDoc("manifest")
                .Start("page").Attr("dataid", "a").End()
                .Start("page").Attr("dataid", "b").End()
                .Start("page").Attr("dataid", "c").End();

            // Act
            using(ArchivePackageWriter packageWriter = new ArchivePackageWriter(archiveFile)) {
                foreach (Tuplet<string, MemoryStream> tuple in data) {
                    var item = new ExportItem(tuple.Item1, tuple.Item2, tuple.Item2.Length,new XDoc("item").Elem("path","abc"));
                    packageWriter.WriteDataAsync(item, new Result()).Wait();
                }
                packageWriter.WriteManifest(manifest, new Result()).Wait();
            }
            XDoc manifest2 = null;
            List<XDoc> docs2 = new List<XDoc>();
            using(ArchivePackageReader packageReader = new ArchivePackageReader(archiveFile)) {
                manifest2 = packageReader.ReadManifest(new Result<XDoc>()).Wait();
                foreach (XDoc id in manifest2["*/@dataid"]) {
                    using (ImportItem item = packageReader.ReadData(new ImportItem(id.AsText,null,null), new Result<ImportItem>()).Wait()) {
                        using (StreamReader reader = new StreamReader(item.Data)) {
                            docs2.Add(XDocFactory.From(reader, MimeType.TEXT_XML));
                        }
                    }
                }
            }

            // Asssert
            Assert.IsTrue(File.Exists(archiveFile));
            Assert.AreEqual(manifest, manifest2);
            Assert.AreEqual(docs.Count, docs2.Count);
            foreach(var doc in docs) {
                Assert.IsTrue(docs2.Select(x => x == doc).Any());
            }
        }
コード例 #3
0
ファイル: ImportProgram.cs プロジェクト: heran/DekiWiki
 private static void Import(Opts opts) {
     bool createdTempFile = false;
     if(opts.FilePath.StartsWith("http:") || opts.FilePath.StartsWith("https:")) {
         DreamMessage packageMessage = Plug.New(opts.FilePath).InvokeEx("GET", DreamMessage.Ok(), new Result<DreamMessage>()).Wait();
         if(!packageMessage.IsSuccessful) {
             throw new Exception(string.Format("Unable to download package from '{0}'", opts.FilePath));
         }
         opts.FilePath = Path.GetTempFileName();
         opts.Archive = true;
         createdTempFile = true;
         using(Stream tempStream = File.Create(opts.FilePath)) {
             packageMessage.ToStream().CopyTo(tempStream, packageMessage.ContentLength, new Result<long>()).Wait();
         }
     }
     IPackageReader packageReader;
     if(opts.Archive) {
         if(!File.Exists(opts.FilePath)) {
             throw new ConfigurationException("No such file: {0}", opts.FilePath);
         }
         if(opts.Test) {
             return;
         }
         packageReader = new ArchivePackageReader(opts.FilePath);
     } else {
         if(!Directory.Exists(opts.FilePath)) {
             throw new ConfigurationException("No such directory: {0}", opts.FilePath);
         }
         if(opts.Test) {
             return;
         }
         packageReader = new FilePackageReader(opts.FilePath);
     }
     ImportManager manager;
     try {
         var manifest = packageReader.ReadManifest(new Result<XDoc>()).Wait();
         FixupManifest(manifest, opts);
         var forceOverwrite = !(opts.PreserveLocalChanges ?? true);
         var importer = opts.ImportRelto.HasValue
             ? Importer.CreateAsync(opts.DekiApi, manifest, opts.ImportRelto.Value, forceOverwrite, new Result<Importer>()).Wait()
             : Importer.CreateAsync(opts.DekiApi, manifest, opts.ImportReltoPath, forceOverwrite, new Result<Importer>()).Wait();
         manager = new ImportManager(importer, packageReader);
     } catch(Exception e) {
         if(createdTempFile) {
             File.Delete(opts.FilePath);
         }
         throw new Exception(string.Format("Import failed: {0}", e.Message), e);
     }
     manager.MaxRetries = opts.Retries;
     Result result = manager.ImportAsync(new Result());
     int completed = 0;
     Console.WriteLine("Importing:");
     while(!result.HasFinished) {
         Thread.Sleep(200);
         if(manager.CompletedItems <= completed) {
             continue;
         }
         if(SysUtil.IsUnix) {
             Console.WriteLine("  {0} of {1} files ({2:0}%)", manager.CompletedItems, manager.TotalItems, 100.0 * manager.CompletedItems / manager.TotalItems);
         } else {
             Console.Write("  {0} of {1} files ({2:0}%)      \r", manager.CompletedItems, manager.TotalItems, 100.0 * manager.CompletedItems / manager.TotalItems);
         }
         completed = manager.CompletedItems;
     }
     if(!SysUtil.IsUnix) {
         Console.WriteLine();
     }
     if(createdTempFile) {
         File.Delete(opts.FilePath);
     }
     if(result.HasException) {
         ImportException importException = result.Exception as ImportException;
         if(importException != null) {
             Console.WriteLine("Import failed on Item:\r\n{0}", importException.ManifestItem.ToPrettyString());
         }
         throw new Exception(string.Format("Import failed: {0}", result.Exception.Message), result.Exception);
     }
 }
コード例 #4
0
 public static Result<ImportManager> CreateArchiveImportManagerAsync(Plug dekiApi, string reltopath, string archiveFilename, Result<ImportManager> result) {
     var archivePackageReader = new ArchivePackageReader(archiveFilename);
     return CreateAsync(dekiApi, reltopath, archivePackageReader, result);
 }
コード例 #5
0
ファイル: PackageUpdater.cs プロジェクト: heran/DekiWiki
        private IEnumerator<IYield> UpdatePackages_Helper(Plug api, string wikiId, string apikey, bool force, bool init, Result<XDoc> result) {
            try {
                _status = PackageUpdaterStatus.Importing;
                yield return Coroutine.Invoke(AuthenticateImportUser, api, wikiId, apikey, new Result<Plug>()).Set(x => api = x);
                XDoc license = null;
                yield return api.At("license").With("apikey", apikey).Get(new Result<XDoc>()).Set(x => license = x);
                var importReport = new XDoc("packages");
                var first = true;
                foreach(var directory in Directory.GetDirectories(_templatePackagePath)) {
                    var directoryName = Path.GetFileName(directory);
                    string restriction = null;
                    if(directoryName.EqualsInvariantIgnoreCase("public")) {
                        restriction = "Public";
                    } else if(directoryName.EqualsInvariantIgnoreCase("semi-public")) {
                        restriction = "Semi-Public";
                    } else if(directoryName.EqualsInvariantIgnoreCase("private")) {
                        restriction = "Private";
                    }
                    foreach(var package in Directory.GetFiles(directory, "*.mt*").OrderBy(x => x)) {
                        var ext = Path.GetExtension(package);
                        if(!(ext.EqualsInvariantIgnoreCase(".mtarc") || ext.EqualsInvariantIgnoreCase(".mtapp"))) {
                            continue;
                        }
                        if(!first) {
                            importReport.End();
                        }
                        first = false;
                        importReport.Start("package").Elem("path", package);
                        ArchivePackageReader packageReader;
                        _log.DebugFormat("contemplating import of '{0}' for '{1}'", package, wikiId);
                        try {
                            packageReader = new ArchivePackageReader(package);
                        } catch(Exception e) {
                            SetError(importReport, wikiId, "error", e, "Unable to open package.");
                            continue;
                        }
                        Result<XDoc> manifestResult;
                        yield return manifestResult = packageReader.ReadManifest(new Result<XDoc>()).Catch();
                        if(manifestResult.HasException) {
                            SetError(importReport, wikiId, "error", manifestResult.Exception, "Unable to read package manifest.");
                            continue;
                        }
                        var manifest = manifestResult.Value;

                        // check for required capabilities
                        var capabilitiesSatisfied = true;
                        foreach(var capability in manifest["capability"]) {
                            var capabilityName = capability["@name"].AsText;
                            var capabilityValue = capability["@value"].AsText.IfNullOrEmpty("enabled");
                            if(string.IsNullOrEmpty(capabilityName)) {
                                continue;
                            }
                            var licenseCapabilityValue = DekiLicense.GetCapability(license, capabilityName) ?? "";
                            if(!string.IsNullOrEmpty(capabilityName) && licenseCapabilityValue.EqualsInvariant(capabilityValue)) {
                                continue;
                            }
                            capabilitiesSatisfied = false;
                            SetError(importReport, wikiId, "error", null, "Missing capability '{0}' or incorrect capability value, expected '{1}' and got '{2}'.", capabilityName, capabilityValue, licenseCapabilityValue);
                        }
                        if(!capabilitiesSatisfied) {
                            continue;
                        }

                        // add security xml if we are in a restriction enforcing path
                        if(!string.IsNullOrEmpty(restriction)) {
                            manifest.Start("security")
                                .Start("permissions.page")
                                .Elem("restriction", restriction)
                                .End()
                                .End();
                        }

                        // if package predates @date.created, take file modified
                        var dateCreated = manifest["@date.created"].AsDate ?? new FileInfo(package).LastWriteTime;

                        // check whether we should import this package
                        var filename = Path.GetFileName(package);
                        var importOnce = manifest["@import-once"].AsBool ?? false;
                        var initPackage = manifest["@init-only"].AsBool ?? false;
                        importReport.Elem("name", filename).Attr("date.created", dateCreated).Attr("preserve-local", manifest["@preserve-local"].AsBool ?? false);
                        var importPropertyName = XUri.EncodeSegment(PACKAGE_PROPERTY_NS + filename);
                        if(initPackage && !init && !force) {
                            SetError(importReport, wikiId, "skipped", null, "package '{0}' is an init package and neither init or force flags were set, skipping", package);
                            continue;
                        }
                        if(force && !importOnce) {
                            _log.DebugFormat("force is set and package '{0}' is not marked as oneTimeOnly, proceeding with import", package);
                        } else {
                            DreamMessage propertyResponse = null;
                            yield return api.At("site", "properties", importPropertyName).Get(new Result<DreamMessage>()).Set(x => propertyResponse = x);
                            if(propertyResponse.IsSuccessful) {
                                var importedPackage = propertyResponse.ToDocument();
                                var importedPackageDate = importedPackage["date.created"].AsDate;
                                if(!importedPackageDate.HasValue) {
                                    _log.WarnFormat("unable to retrieve imported package date.created for '{0}', treating package as new", package);
                                } else if(dateCreated > importedPackageDate.Value) {
                                    _log.DebugFormat("package '{0}' is newer, proceed with import ({1} > {2}", package, dateCreated, importedPackageDate.Value);
                                } else {
                                    SetError(importReport, wikiId, "skipped", null,
                                             "package '{0}' is not newer, skip import ({1} <= {2}.)",
                                             package,
                                             dateCreated,
                                             importedPackageDate.Value);
                                    continue;
                                }
                            } else if(propertyResponse.Status == DreamStatus.Unauthorized) {
                                _log.WarnFormat("apiuri has lost its authentication, dropping out");
                                throw new UnauthorizedAccessException("Authentication for was lost");
                            } else {
                                _log.DebugFormat("package '{0}' has not previously been imported, proceeding with import", package);
                            }
                        }

                        // import package
                        Result<Importer> importerResult;
                        yield return importerResult = Importer.CreateAsync(api, manifest, "/", new Result<Importer>()).Catch();
                        if(importerResult.HasException) {
                            SetError(importReport, wikiId, "error", importerResult.Exception, "Unable to create importer for package.");
                            continue;
                        }
                        var importer = importerResult.Value;
                        var importManager = new ImportManager(importer, packageReader);
                        Result importResult;
                        yield return importResult = importManager.ImportAsync(new Result()).Catch();
                        if(importResult.HasException) {
                            SetError(importReport, wikiId, "error", importResult.Exception, "Import did not complete successfully.");
                            continue;
                        }

                        // write import data as site property
                        yield return api.At("site", "properties", importPropertyName)
                            .With("abort", "never")
                            .With("description", string.Format("Import of package '{0}'", filename))
                            .Put(new XDoc("package").Elem("date.created", dateCreated), new Result<DreamMessage>());
                        importReport.Start("status").Attr("code", "ok").End();
                        _log.DebugFormat("sucessfully imported package '{0}'", package);
                    }
                }
                if(!first) {
                    importReport.End();
                }
                result.Return(importReport);
                yield break;
            } finally {
                _status = PackageUpdaterStatus.Idle;
            }
        }
コード例 #6
0
        public static Result <ImportManager> CreateArchiveImportManagerAsync(Plug dekiApi, string reltopath, string archiveFilename, Result <ImportManager> result)
        {
            var archivePackageReader = new ArchivePackageReader(archiveFilename);

            return(CreateAsync(dekiApi, reltopath, archivePackageReader, result));
        }