diff options
Diffstat (limited to 'back-end/src')
-rw-r--r-- | back-end/src/Endpoints/BookmarkEndpoint.cs | 39 | ||||
-rw-r--r-- | back-end/src/ImportExportUtil.cs | 77 |
2 files changed, 115 insertions, 1 deletions
diff --git a/back-end/src/Endpoints/BookmarkEndpoint.cs b/back-end/src/Endpoints/BookmarkEndpoint.cs index ec46097..05b72d0 100644 --- a/back-end/src/Endpoints/BookmarkEndpoint.cs +++ b/back-end/src/Endpoints/BookmarkEndpoint.cs @@ -30,7 +30,9 @@ using FluentValidation.Results; using Microsoft.EntityFrameworkCore; using VNLib.Utils; -using VNLib.Utils.Logging; +using VNLib.Utils.IO; +using VNLib.Utils.Memory; +using VNLib.Net.Http; using VNLib.Plugins; using VNLib.Plugins.Essentials; using VNLib.Plugins.Essentials.Accounts; @@ -113,6 +115,41 @@ namespace SimpleBookmark.Endpoints return VirtualOk(entity, webm); } + /* + * Allow exporting the current user's bookmark collection as a + * netscape file for compatability. + * + * Future support for CSV file via an accept content type header + */ + if(entity.QueryArgs.ContainsKey("export")) + { + if (entity.Server.Accepts(ContentType.Html)) + { + //Get the collection of bookmarks + List<BookmarkEntry> list = Bookmarks.ListRental.Rent(); + await Bookmarks.GetUserPageAsync(list, entity.Session.UserID, 0, (int)BmConfig.PerPersonQuota); + + //Alloc memory stream for output + VnMemoryStream output = new(MemoryUtil.Shared, 16 * 1024, false); + try + { + //Write the bookmarks as a netscape file and return the file + ImportExportUtil.ExportToNetscapeFile(list, output); + output.Seek(0, System.IO.SeekOrigin.Begin); + return VirtualClose(entity, HttpStatusCode.OK, ContentType.Html, output); + } + catch + { + output.Dispose(); + throw; + } + } + else + { + return VirtualClose(entity, HttpStatusCode.NotAcceptable); + } + } + //Get query parameters _ = entity.QueryArgs.TryGetNonEmptyValue("limit", out string? limitS); _ = uint.TryParse(limitS, out uint limit); diff --git a/back-end/src/ImportExportUtil.cs b/back-end/src/ImportExportUtil.cs new file mode 100644 index 0000000..3610ef6 --- /dev/null +++ b/back-end/src/ImportExportUtil.cs @@ -0,0 +1,77 @@ +// Copyright (C) 2024 Vaughn Nugent +// +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as +// published by the Free Software Foundation, either version 3 of the +// License, or (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see <https://www.gnu.org/licenses/>. + +using System; +using System.IO; +using SimpleBookmark.Model; +using System.Collections.Generic; +using VNLib.Utils.IO; + + + +namespace SimpleBookmark +{ + internal static class ImportExportUtil + { + /// <summary> + /// Exports a colletion of bookmarks to a netscape bookmark file + /// </summary> + /// <param name="bookmarks">The bookmark collection to export</param> + /// <param name="outputStream">The bookmark output stream to write data to</param> + public static void ExportToNetscapeFile(IEnumerable<BookmarkEntry> bookmarks, Stream outputStream) + { + using VnStreamWriter writer = new(outputStream, System.Text.Encoding.UTF8, 1024) + { + NewLine = "\r\n" + }; + + writer.WriteLine("<!DOCTYPE NETSCAPE-Bookmark-file-1>"); + writer.WriteLine("<META HTTP-EQUIV=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">"); + writer.WriteLine("<TITLE>Bookmarks</TITLE>"); + writer.WriteLine("<H1>Bookmarks</H1>"); + writer.WriteLine("<DL><p>"); + + //Add each bookmark + foreach (BookmarkEntry entry in bookmarks) + { + writer.Write("<DT><A HREF=\""); + writer.Write(entry.Url); + + writer.Write("\" ADD_DATE=\""); + writer.Write(new DateTimeOffset(entry.Created).ToUnixTimeSeconds()); + + writer.Write("\" LAST_VISIT=\""); + writer.Write(new DateTimeOffset(entry.LastModified).ToUnixTimeSeconds()); + + //tags + writer.Write("\" TAGS=\""); + writer.Write(entry.Tags); + + writer.Write("\">"); + writer.Write(entry.Name); + writer.WriteLine("</A>"); + + //description + writer.Write("<DD>"); + writer.WriteLine(entry.Description); + + } + + //Close document + writer.WriteLine("</DL></p>"); + writer.Flush(); + } + } +} |