public void ConnectToDeki(string dreamAPI, string dekiUserName, string dekiUserPassword) { this._dreamAPI = dreamAPI; this._dekiPlug = Plug.New(_dreamAPI).WithCredentials(dekiUserName, dekiUserPassword); DreamMessage authResponse = _dekiPlug.At("users", "authenticate").GetAsync().Wait(); if (!authResponse.IsSuccessful) { Log.FatalFormat("Could not connect to MT API '{0}' username: '******' password: '******' Error:", _dekiPlug.ToString(), dekiUserName, dekiUserPassword, authResponse.ToString()); throw new DreamAbortException(authResponse); } //Check that user have admin rights DreamMessage userResponse = _dekiPlug.At("users", "=" + Utils.DoubleUrlEncode(dekiUserName)).Get(); XDoc resDoc = userResponse.AsDocument(); string roleName = resDoc["permissions.user/role"].AsText; if ((roleName == null) || (roleName.ToLower() != "admin")) { WriteLineToConsole("User " + dekiUserName + " should have Admin role in Deki."); return; } _connectedToDeki = true; }
public void Bug_MT8962_PostPageContentsWithFile() { Plug adminPlug = Utils.BuildPlugForAdmin(); // Create random contributor string username = null; string userid = null; DreamMessage msg = UserUtils.CreateRandomUser(adminPlug, "Contributor", "password", out userid, out username); // Login as user Plug userPlug = Utils.BuildPlugForUser(username); // Create a page string page_id; string page_path; msg = PageUtils.CreateRandomPage(userPlug, out page_id, out page_path); // Create a file string fileName = FileUtils.CreateRamdomFile(null); msg = DreamMessage.FromFile(fileName); fileName = "foo.jpg"; // Upload file to page msg = userPlug.At("pages", page_id, "files", "=" + fileName).Put(msg); Assert.AreEqual(DreamStatus.Ok, msg.Status, "PUT request failed"); // update the page XDoc pageContents = new XDoc("content"); pageContents.Attr("type", "application/x.deki-text"); pageContents.Attr("unsafe", "false"); pageContents.Start("body"); pageContents.Start("img"); pageContents.Attr("class", "internal default"); pageContents.Attr("src.path", "//"); pageContents.Attr("src.filename", fileName); pageContents.End(); //img pageContents.End(); //body msg = userPlug.At("pages", page_id, "contents") .With("edittime", "now") .With("redirects", 0) .With("reltopath", page_path) .Post(pageContents); Assert.AreEqual(DreamStatus.Ok, msg.Status, "page creation failed!"); msg = userPlug.At("pages", page_id, "contents") .With("mode", "view") .Get(); string contents = msg.AsDocument()["/content/body"].Contents; XDoc imgDoc = XDocFactory.From(contents, MimeType.XML); XUri imgSrcUri = XUri.TryParse(imgDoc["@src"].AsText); Assert.IsNotNull(imgSrcUri, "img src uri is invalid!"); }
public void CheckBannedUsersPerms() { //Assumptions: // //Actions: // Create user1 as contributor // Ban user1 // create public page p1 // Call POST: pages/{p1}/allowed with user1 //Expected result: // user1 should not have access to p1 Plug p = Utils.BuildPlugForAdmin(); string userId = null; string userName = null; DreamMessage msg = UserUtils.CreateRandomContributor(p, out userId, out userName); // confirm user has perms msg = p.At("users", userId).Get(); Assert.IsTrue((msg.AsDocument()["permissions.effective/operations"].AsText ?? string.Empty).ContainsInvariantIgnoreCase("UPDATE"), "user doesnt have expected perms"); // ban the user XDoc ban = new XDoc("bans") .Elem("description", Utils.GetSmallRandomText()) .Elem("date.expires", DateTime.Now.AddDays(10)) .Start("permissions.revoked") .Elem("operations", banRevokemask) .End() .Start("ban.users") .Start("user").Attr("id", userId).End() .End(); msg = p.At("site", "bans").Post(ban); Assert.AreEqual(DreamStatus.Ok, msg.Status); // confirm user has perms msg = p.At("users", userId).Get(); Assert.IsFalse((msg.AsDocument()["permissions.effective/operations"].AsText ?? string.Empty).ContainsInvariantIgnoreCase("UPDATE"), "user doesnt have expected perms"); }
private int CreateDekiPage(Plug p, string pagePath, string pageTitle, DateTime?modified, string content, out string dekiPageUrl) { Log.DebugFormat("Creating page: '{0}' Content? {1}", XUri.DoubleDecode(pagePath), !string.IsNullOrEmpty(content)); Plug pagePlug = p.At("pages", "=" + pagePath, "contents"); pagePlug = pagePlug.With("abort", "never"); modified = modified ?? DateTime.Now; string editTime = Utils.FormatPageDate(modified.Value.ToUniversalTime()); pagePlug = pagePlug.With("edittime", editTime); pagePlug = pagePlug.With("comment", "Created at " + modified.Value.ToShortDateString() + " " + modified.Value.ToShortTimeString()); if (pageTitle != null) { pagePlug = pagePlug.With("title", pageTitle); } DreamMessage msg = DreamMessage.Ok(MimeType.TEXT_UTF8, content); DreamMessage res = pagePlug.PostAsync(msg).Wait(); if (res.Status != DreamStatus.Ok) { WriteLineToConsole("Error converting page \"" + XUri.DoubleDecode(pagePath) + "\""); WriteLineToLog("Edit time: " + editTime); WriteLineToLog("Page title: " + pageTitle); WriteErrorResponse(res); WriteErrorRequest(msg); } else { XDoc createdPage = res.AsDocument(); int pageId = createdPage["page/@id"].AsInt.Value; //dekiPageUrl = createdPage["page/path"].AsText; //Using the uri.ui instead of path to not worry about encodings for links //But this makes the values (mt urls) in the link mapping table unsuitable for page paths //(such as those used in dekiscript for macros). Those need to be converted to paths // via Utils.ConvertPageUriToPath dekiPageUrl = createdPage["page/uri.ui"].AsText; return(pageId); } dekiPageUrl = null; return(-1); }
public void GetPageCreatorInfo() { Plug p = Utils.BuildPlugForAdmin(); string content = "This is test content"; string id = null; string path = null; DreamMessage msg = PageUtils.SavePage(p, string.Empty, PageUtils.GenerateUniquePageName(), content, out id, out path); msg = p.At("users", "current").Get(); var pageCreatorId = msg.AsDocument()["@id"].AsText; PageUtils.SavePage(p, path, "New content"); var pageDoc = p.At("pages", id).Get().ToDocument(); Assert.AreEqual(pageCreatorId, pageDoc["user.createdby/@id"].AsText); Assert.IsTrue((pageDoc["date.created"].AsDate ?? DateTime.MinValue) > DateTime.UtcNow.Subtract(TimeSpan.FromMinutes(5)), "create date missing."); PageUtils.DeletePageByID(p, id, true); }
private int CreateDekiPageHistory(Plug p, string pagePath, string pageTitle, DateTime?modified, string content, out string dekiPageUrl) { Log.DebugFormat("Creating page history: '{0}' Content? {1}", XUri.DoubleDecode(pagePath), !string.IsNullOrEmpty(content)); Plug pagePlug = p.At("pages", "=" + pagePath, "revision"); pagePlug = pagePlug.With("abort", "never"); modified = modified ?? DateTime.Now; string editTime = Utils.FormatPageDate(modified.Value.ToUniversalTime()); pagePlug = pagePlug.With("edittime", editTime); if (pageTitle != null) { pagePlug = pagePlug.With("title", pageTitle); } DreamMessage msg = DreamMessage.Ok(MimeType.TEXT_UTF8, content); DreamMessage res = pagePlug.PostAsync(msg).Wait(); if (res.Status != DreamStatus.Ok) { WriteLineToConsole("Error converting page \"" + XUri.DoubleDecode(pagePath) + "\""); WriteLineToLog("Edit time: " + editTime); WriteLineToLog("Page title: " + pageTitle); WriteErrorResponse(res); WriteErrorRequest(msg); Log.WarnFormat("Error converting page: '{0}'. Request: {0} \nResponse: {1}", msg.ToString(), res.ToString()); } else { XDoc createdPage = res.AsDocument(); int pageId = createdPage["page/@id"].AsInt.Value; dekiPageUrl = createdPage["page/path"].AsText; return(pageId); } dekiPageUrl = null; return(-1); }
private void WriteErrorResponse(DreamMessage response) { WriteLineToLog("Response: " + response.ToString()); XDoc responseDoc = response.AsDocument(); if ((responseDoc == null) || (responseDoc.IsEmpty)) { return; } XDoc messageDoc = responseDoc["message"]; if ((messageDoc == null) || (messageDoc.IsEmpty)) { return; } string messageText = messageDoc.AsText; if (messageText == null) { return; } WriteLineToConsole("Error: " + messageText); }
public void RatePage() { // Build ADMIN plug Plug p = Utils.BuildPlugForAdmin(); // Create random page string id = null; string path = null; DreamMessage msg = PageUtils.CreateRandomPage(p, out id, out path); // Rate page a '1' msg = p.At("pages", id, "ratings").With("score", 1).PostAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "Page rating did not return OK: " + msg.ToString()); // Check to see if returned document elements/attributes are correct Assert.AreEqual(1, msg.AsDocument()["/rating/@score"].AsInt, "Unexpected computed rating"); Assert.AreEqual(1, msg.AsDocument()["/rating/@count"].AsInt, "Unexpected rating count"); Assert.AreEqual(1, msg.AsDocument()["/rating/user.ratedby/@score"].AsInt, "Unexpected user rating"); // Rate page a '0' msg = p.At("pages", id, "ratings").With("score", 0).PostAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "Page rating did not return OK: " + msg.ToString()); // Check to see if returned document elements/attributes are correct Assert.AreEqual(0, msg.AsDocument()["/rating/@score"].AsInt, "Unexpected computed rating"); Assert.AreEqual(1, msg.AsDocument()["/rating/@count"].AsInt, "Unexpected rating count"); Assert.AreEqual(0, msg.AsDocument()["/rating/user.ratedby/@score"].AsInt, "Unexpected user rating"); // Clear page rating msg = p.At("pages", id, "ratings").With("score", String.Empty).PostAsync().Wait(); Assert.AreEqual(DreamStatus.Ok, msg.Status, "Page rating did not return OK: " + msg.ToString()); // Check to see if returned document elements/attributes are correct Assert.AreEqual(String.Empty, msg.ToDocument()["@score"].AsText, "Score attribute contains a value!"); Assert.AreEqual(0, msg.ToDocument()["@count"].AsInt, "Unrated page count does not equal 0!"); // Delete the page PageUtils.DeletePageByID(p, id, true); }
private void MoveGroups() { DreamMessage msg = _dekiPlug.At("groups").With("limit", int.MaxValue).GetAsync().Wait(); if (msg.Status != DreamStatus.Ok) { WriteLineToConsole("Error while receiving groups from Deki. Groups not converted."); WriteErrorResponse(msg); return; } Dictionary <string, string> dekiGroups = new Dictionary <string, string>(); XDoc groupsDoc = msg.AsDocument(); foreach (XDoc groupDoc in groupsDoc["//group"]) { string dekiGroupName = groupDoc["groupname"].AsText; dekiGroups[dekiGroupName.ToLower()] = null; } string[] confluenceGroupNames = _confluenceService.GetGroups(); foreach (string confluenceGroupName in confluenceGroupNames) { string dekiGroupName; if (!_convertedGroups.ContainsKey(confluenceGroupName.ToLower())) { int groupNum = 0; dekiGroupName = confluenceGroupName; while (dekiGroups.ContainsKey(dekiGroupName.ToLower())) { groupNum++; dekiGroupName = confluenceGroupName + groupNum.ToString(); } if (dekiGroupName != confluenceGroupName) { WriteLineToConsole("Confluence group \"" + confluenceGroupName + "\" converted as \"" + dekiGroupName + "\" becouse of existing same group in Deki"); } XDoc newGroupDoc = new XDoc("group"); newGroupDoc.Elem("name", dekiGroupName) .Start("users"); foreach (ACConverterUserInfo convertedUser in _convertedUsers.Values) { if (Array.IndexOf(convertedUser.ConfluenceUserGroupNames, confluenceGroupName) >= 0) { newGroupDoc.Start("user").Attr("id", convertedUser.DekiUserId).End(); } } newGroupDoc.End(); Log.DebugFormat("Creating group: {0}", dekiGroupName); DreamMessage res = _dekiPlug.At("groups").PostAsync(newGroupDoc).Wait(); if (res.Status != DreamStatus.Ok) { WriteLineToLog("Error converting group \"" + confluenceGroupName + "\""); WriteErrorResponse(res); WriteErrorRequest(newGroupDoc); continue; } XDoc resGroupsDoc = res.AsDocument(); int newDekiGroupId = resGroupsDoc["@id"].AsInt.Value; ACConverterGroupInfo convertedGroup = new ACConverterGroupInfo(confluenceGroupName, dekiGroupName, newDekiGroupId); _convertedGroups[confluenceGroupName.ToLower()] = convertedGroup; } else { //This group already converted during previous ACConverter start dekiGroupName = _convertedGroups[confluenceGroupName.ToLower()].DekiGroupName; XDoc usersDoc = new XDoc("users"); foreach (ACConverterUserInfo convertedUser in _convertedUsers.Values) { if (Array.IndexOf(convertedUser.ConfluenceUserGroupNames, confluenceGroupName) >= 0) { usersDoc.Start("user").Attr("id", convertedUser.DekiUserId).End(); } } DreamMessage res = _dekiPlug.At("groups", _convertedGroups[confluenceGroupName.ToLower()].DekiGroupId.ToString(), "users").PutAsync(usersDoc).Wait(); if (res.Status != DreamStatus.Ok) { WriteLineToLog("Error converting group's users"); WriteErrorResponse(res); WriteErrorRequest(usersDoc); } } } }
private void MoveUsers() { string[] userNames = _confluenceService.GetActiveUsers(true); Dictionary <string, string> dekiUsers = new Dictionary <string, string>(); //Restore manifest from disk XDoc spaceManifest = GetManifestFromDisk(null) ?? new XDoc("manifest"); DreamMessage usersResponse = _dekiPlug.At("users").With("limit", int.MaxValue).GetAsync().Wait(); if (usersResponse.Status != DreamStatus.Ok) { WriteLineToConsole("Error while receiving users from Deki. Users not converted."); WriteErrorResponse(usersResponse); throw new DreamAbortException(usersResponse); } XDoc dekiUsersDoc = usersResponse.AsDocument(); foreach (XDoc userDoc in dekiUsersDoc["//user"]) { string dekiUserName = userDoc["nick"].AsText; dekiUsers[dekiUserName.ToLower()] = null; } foreach (string userName in userNames) { if (_convertedUsers.ContainsKey(userName.ToLower())) { continue; //TODO (maxm): even though a user already exists in MindTouch (perhaps created in previous run), because there is // a correlated user within Confluence, the group and url mapping logic should still run. } //while user with same name exist try add number to user name. int userNum = 0; string newUserName = userName; while (dekiUsers.ContainsKey(newUserName.ToLower())) { userNum++; newUserName = userName + userNum.ToString(); } if (newUserName != userName) { WriteLineToConsole("Confluence user \"" + userName + "\" converted as \"" + newUserName + "\" becouse of existing same user in Deki"); } RemoteUser confluenceUser = _confluenceService.GetUser(userName); XDoc usersDoc = new XDoc("user") .Elem("username", newUserName) .Elem("email", confluenceUser.email) .Elem("fullname", confluenceUser.fullname); //.Start("permissions.user") // .Elem("role", "Contributor") //.End(); string newPassword = Guid.NewGuid().ToString(); string[] userGroupNames = _confluenceService.GetUserGroups(confluenceUser.name); Log.DebugFormat("Creating user: {0} email: {1} fullname: {2}", newUserName, confluenceUser.email, confluenceUser.fullname); DreamMessage res = _dekiPlug.At("users").With("accountpassword", newPassword).PostAsync(usersDoc).Wait(); if (res.Status != DreamStatus.Ok) { WriteLineToConsole("Error converting user \"" + userName + "\""); WriteErrorResponse(res); WriteErrorRequest(usersDoc); continue; } XDoc resUserDoc = res.AsDocument(); int dekiUserId = resUserDoc["@id"].AsInt.Value; //TODO (maxm): retrieve the actual username from the XML ACConverterUserInfo newUser = new ACConverterUserInfo(newUserName, newPassword, dekiUserId, userGroupNames); _convertedUsers[confluenceUser.name.ToLower()] = newUser; LogUserConversion(spaceManifest, confluenceUser.name, dekiUserId.ToString(), newUserName, confluenceUser.url); } //Save the space manifest to disk PersistManifestToDisk(null, spaceManifest); }
private void LoadUsersAndGroupsFromXML() { WriteLineToConsole("Reading groups and users from " + ConvertedUsersAndGroupsFileName); Dictionary <string, string> readedDekiUsers = new Dictionary <string, string>(); XDoc doc = XDocFactory.LoadFrom(ConvertedUsersAndGroupsFileName, MimeType.XML); foreach (XDoc user in doc["//" + UserXMLTagName]) { string confluenceUserName = user["@" + ConfluenceUserNameXMLAttributeName].AsText; string dekiName = user["@" + DekiUserNameXMLAttributeName].AsText; if ((confluenceUserName == null) && (dekiName == null)) { WriteLineToConsole("Invalid XML attributes in " + ConvertedUsersAndGroupsFileName); WriteLineToConsole(user.ToString()); continue; } if (confluenceUserName == null) { WriteLineToConsole(ConfluenceUserNameXMLAttributeName + " not specified for " + dekiName + " in " + ConvertedUsersAndGroupsFileName + ". Record skiped."); continue; } if (dekiName == null) { WriteLineToConsole(DekiUserNameXMLAttributeName + " not specified for " + confluenceUserName + " in " + ConvertedUsersAndGroupsFileName + ". Record skiped."); continue; } if (readedDekiUsers.ContainsKey(dekiName.ToLower())) { WriteLineToConsole("Repeating entry of Deki user \"" + dekiName + "\". Record skiped."); continue; } DreamMessage dekiUserMessage = _dekiPlug.At("users", "=" + Utils.DoubleUrlEncode(dekiName)).GetAsync().Wait(); if (dekiUserMessage.Status == DreamStatus.NotFound) { WriteLineToConsole("Deki user \"" + dekiName + "\" is specified in " + ConvertedUsersAndGroupsFileName + " but not exists in Deki. New user created."); continue; } XDoc dekiUserDoc = dekiUserMessage.AsDocument(); int dekiUserId = dekiUserDoc["@id"].AsInt.Value; string newPassword = Guid.NewGuid().ToString(); DreamMessage pass = DreamMessage.Ok(MimeType.TEXT, newPassword); DreamMessage res = _dekiPlug.At("users", dekiUserId.ToString(), "password").PutAsync(pass).Wait(); if (res.Status != DreamStatus.Ok) { WriteLineToConsole("Error converting user \"" + confluenceUserName + "\""); WriteLineToLog("Confluence user name: " + confluenceUserName); WriteLineToLog("Deki user name: " + dekiName); WriteErrorResponse(res); continue; } string[] userGroupNames = new string[0]; bool userExistsInConfluence = _confluenceService.HasUser(confluenceUserName); if (userExistsInConfluence) { userGroupNames = _confluenceService.GetUserGroups(confluenceUserName); } else { WriteLineToConsole("Confluence user name \"" + confluenceUserName + "\" specified in " + ConvertedUsersAndGroupsFileName + " but not exists in Confluence."); } ACConverterUserInfo userInfo = new ACConverterUserInfo(dekiName, newPassword, dekiUserId, userGroupNames); if (_convertedUsers.ContainsKey(confluenceUserName.ToLower())) { WriteLineToConsole("Repeating entry of user \"" + confluenceUserName + "\" into " + ConvertedUsersAndGroupsFileName + ". Last record used."); } _convertedUsers[confluenceUserName.ToLower()] = userInfo; readedDekiUsers[dekiName.ToLower()] = confluenceUserName; } Dictionary <string, string> readedDekiGroups = new Dictionary <string, string>(); foreach (XDoc group in doc["//" + GroupXMLTagName]) { string confluenceGroupName = group["@" + ConfluenceGroupNameXMLAttributeName].AsText; string dekiGroupName = group["@" + DekiGroupNameXMLAttributeName].AsText; if ((confluenceGroupName == null) && (dekiGroupName == null)) { WriteLineToConsole("Invalid XML attributes in " + ConvertedUsersAndGroupsFileName); WriteLineToConsole(group.AsText); continue; } if (confluenceGroupName == null) { WriteLineToConsole(ConfluenceGroupNameXMLAttributeName + " not specified for \"" + dekiGroupName + "\" in " + ConvertedUsersAndGroupsFileName + ". Record skiped."); continue; } if (dekiGroupName == null) { WriteLineToConsole(DekiGroupNameXMLAttributeName + " not specified for \"" + confluenceGroupName + "\" in " + ConvertedUsersAndGroupsFileName + ". Record skiped."); continue; } if (readedDekiGroups.ContainsKey(dekiGroupName.ToLower())) { WriteLineToConsole("Repeating entry of Deki group \"" + dekiGroupName + "\". Record skiped."); continue; } dekiGroupName = dekiGroupName.Replace(" ", "_"); DreamMessage dekiGroupMessage = _dekiPlug.At("groups", "=" + dekiGroupName).GetAsync().Wait(); if (dekiGroupMessage.Status == DreamStatus.NotFound) { WriteLineToConsole("Deki group \"" + dekiGroupName + "\" is specified in " + ConvertedUsersAndGroupsFileName + " but not exists in Deki. New group created."); continue; } XDoc dekiGroupDoc = dekiGroupMessage.AsDocument(); int dekiGroupId = dekiGroupDoc["@id"].AsInt.Value; ACConverterGroupInfo groupInfo = new ACConverterGroupInfo(confluenceGroupName, dekiGroupName, dekiGroupId); if (_convertedUsers.ContainsKey(confluenceGroupName.ToLower())) { WriteLineToConsole("Repeating entry of group \"" + confluenceGroupName + "\" into " + ConvertedUsersAndGroupsFileName + ". Last record used."); } _convertedGroups[confluenceGroupName.ToLower()] = groupInfo; } WriteLineToConsole("Users and groups readed!"); }
public void MoveAttachments(XDoc spaceManifest, int dekiPageID, long confluencePageId) { RemoteAttachment[] attachments = _confluenceService.GetAttachments(confluencePageId); int count = attachments.Length; foreach (RemoteAttachment attachment in attachments) { // This was when a single attachment (the latest) was being handled // byte[] attachmentData; Log.DebugFormat("Processing file: {0} size: {1} #remaining: {2}", attachment.fileName, attachment.fileSize, --count); Plug p = (attachment.creator == null) ? _dekiPlug : GetPlugForConvertedUser(attachment.creator); DreamMessage res = p.At("pages", dekiPageID.ToString(), "files", "=" + Utils.DoubleUrlEncode(attachment.fileName), "info") .GetAsync().Wait(); if (res.Status == DreamStatus.Ok) { Log.DebugFormat("Already converted: {0} MindTouch URL: {1}", attachment.fileName, res.AsDocument()["contents/@href"].AsText); } else { MimeType attachmentMimeType; if (!MimeType.TryParse(attachment.contentType, out attachmentMimeType)) { attachmentMimeType = MimeType.FromFileExtension(attachment.fileName); } // The attachment URL contains the latest actual version of this attachment e.g. // http://confluencesite.com/download/attachments/3604492/excelspreadsheet.xls?version=1 int latestVersion = 1, oldestVersion = 1; if (attachment.url.Contains("version=")) { try { latestVersion = ParseVersionFromUri(attachment.url); } catch {} } try { if (latestVersion > 1) { if ((latestVersion - 5) > 1) { oldestVersion = latestVersion - 5; } } for (int x = oldestVersion; x <= latestVersion; x++) { try { byte[] ThisAttachmentData = _confluenceService.GetAttachmentData(confluencePageId, attachment.fileName, x); DreamMessage msg = new DreamMessage(DreamStatus.Ok, null, attachmentMimeType, ThisAttachmentData); string AttachmentTimeStampComment = attachment.comment + " - attachment version " + x + " originally created on " + attachment.created.Value.ToShortDateString() + " " + attachment.created.Value.ToShortTimeString(); res = p.At("pages", dekiPageID.ToString(), "files", "=" + Utils.DoubleUrlEncode(attachment.fileName)) .With("description", AttachmentTimeStampComment) .PutAsync(msg).Wait(); if (res.Status != DreamStatus.Ok) { Log.WarnFormat("File '{0}' version '{1}' on Confluence pageid '{2}' not converted: {3}", attachment.fileName, x, attachment.pageId, res.ToString()); // added as suggested by Max on the list created here http://projects.mindtouch.com/User:emilyp/Booze_Allen/Conversion_Issues throw new DreamAbortException(res); } XDoc resDoc = res.ToDocument(); string contentUrl = resDoc["contents/@href"].AsText; LogFileConversion(spaceManifest, attachment, contentUrl); } catch (DreamAbortException dEx) { WriteLineToConsole("Error on moving attachment " + attachment.fileName + "version " + x); if (!String.IsNullOrEmpty(dEx.Message)) { WriteLineToLog(dEx.Message); } continue; } catch (System.Web.Services.Protocols.SoapException e) { WriteLineToConsole("Error obtaining attachment data from confluence " + attachment.fileName + "version " + x); if ((e.Detail != null) && (e.Detail.OuterXml != null)) { WriteLineToLog(e.Detail.OuterXml); } continue; } } // for loop to submit revisions } catch (System.Web.Services.Protocols.SoapException e) { WriteLineToConsole("Error on moving attachment " + attachment.fileName); if ((e.Detail != null) && (e.Detail.OuterXml != null)) { WriteLineToLog(e.Detail.OuterXml); } continue; } } } }