How to upload a Google Docs document in Haskell? - haskell

I want to create a Google Docs document from within Haskell, so basically I want to do in Haskell what this little C# program does (adapted from a Google sample program):
using Google.GData.Documents;
using Google.GData.Client;
namespace DocListUploader
{
public class GDocConsole
{
static void Main()
{
var user = "...";
var passwd = "...";
var file = "...";
service = new DocumentsService("DocListUploader");
service.setUserCredentials(user, passwd);
service.UploadDocument(file, null);
}
}
}
From the Google Docs API description here
and this SO answer here I understood it's "only" a matter of sending a couple of HTTP POSTs and getting the OAuth authentification done, but just how? Has anybody already done it and has some code samples for me...?
EDIT: Still could not figure out how to use the oauth libraries, so I just wrote a little C# wrapper:
using Google.GData.Documents;
using Google.GData.Client;
public class GoogleDoc
{
public static int Upload(string user, string passwd, string file)
{
try
{
var service = new DocumentsService("DocListUploader");
service.setUserCredentials(user, passwd);
service.UploadDocument(file, null);
return 0;
}
catch
{
return -1;
}
}
}
and called this wrapper from Haskell via hs-dotnet:
module Upload where
import NET
upload :: String -> String -> String -> IO (Int)
upload user passed file =
invokeStatic "[GoogleDoc.dll]GoogleDoc" "Upload" (user, passed, file)
testLocal :: IO ()
testLocal = do
let user = "..."
let passwd = "..."
let file = "..."
returnCode <- upload user passwd file
putStrLn (show returnCode)

You can use the haskell-oauth library to do the oauth and to upload the documentation, like mentioned already, you can try the http package from Haskell.

Related

Programmatically modify ACL to give application pool all permissions to application (IIS)

I have a process that creates an application and application pool using the Server Manager object in the Microsoft.Web.Administration namespace, the application pool is created first and then the application, assigning the newly created app pool to the application, code below.
protected TResult UseServerManagerWrapper<TResult>(Func<ServerManager, TResult> func)
{
using (var serverManager = new ServerManager())
{
return func(serverManager);
}
}
Application creation function
public void CreateApplication(String siteName, String parentApplicationName, String organisationName, String applicationName, String applicationPoolName)
{
UseServerManagerWrapper(serverManager =>
{
var site = serverManager.Sites[siteName];
var newApplication =
site.Applications.Add(
GetApplicationPath(parentApplicationName, organisationName, applicationName),
this.GetGeneratedApplicationPhysicalPath(siteName, parentApplicationName, organisationName, applicationName));
newApplication.ApplicationPoolName = applicationPoolName;
serverManager.CommitChanges();
return true;
});
}
and app pool creation.
public Boolean CreateApplicationPool(String applicationPoolName)
{
return UseServerManagerWrapper(serverManager =>
{
var appPool = serverManager.ApplicationPools.Add(applicationPoolName);
appPool.ManagedPipelineMode = ManagedPipelineMode.Integrated;
appPool.ManagedRuntimeVersion = "";
serverManager.CommitChanges();
return true;
});
}
This all works fine, the only problem I have is that I have to go into the application folder and manually assign permissions for the application pool.
I can't see anything in the ServerManager documentation that can help me and I can't figure out a way to use the Directory.SetAccessControl Method to give an application pool permissions. Is there anyway to do this in code?
Apologies if I'm using wrong terminology or anything, I'm new to publishing in general. Let me know if you need anymore info.
Ok, so after a lot of searching and some trial and error I've found the resolution and it's nothing to do with the ServerManager object. First of all to get this to work in ASP.NET Core 2.1 (1.x/2.x) I needed the System.IO.FileSystem.AccessControl Nuget and the Namespaces below.
using System.Security.AccessControl;
using System.Security.Principal;
These give the ability to modify the ACL of files and folders and then the CreateApplication function becomes the below.
public void CreateApplication(String siteName, String parentApplicationName, String organisationName, String applicationName, String applicationPoolName)
{
UseServerManagerWrapper(serverManager =>
{
var site = serverManager.Sites[siteName];
var generatedPath = this.GetGeneratedApplicationPhysicalPath(siteName, parentApplicationName, organisationName, applicationName);
var newApplication =
site.Applications.Add(
GetApplicationPath(parentApplicationName, organisationName, applicationName),
generatedPath);
newApplication.ApplicationPoolName = applicationPoolName;
var dInfo = new DirectoryInfo(generatedPath);
var acl = dInfo.GetAccessControl();
var acct = new NTAccount($"IIS APPPOOL\\{applicationPoolName}");
acl.AddAccessRule(new FileSystemAccessRule(acct, FileSystemRights.FullControl, InheritanceFlags.ContainerInherit | InheritanceFlags.ObjectInherit, PropagationFlags.NoPropagateInherit, AccessControlType.Allow));
dInfo.SetAccessControl(acl);
serverManager.CommitChanges();
return true;
});
}
The code between "newApplication.ApplicationPoolName = applicationPoolName" and "serverManager.CommitChanges()" gets the ACL from the newly generated directory giving the ability to modify it and reassign with a new FileSystemAccessRule.

c# Ftpclient not working and python can retrive the data

I'm trying to use the c# library to download a file from an FTP. The code we are using is straight forward.
static void Main(string[] args)
{
Connect(true, true, true);
}
private static void Connect(bool keepAlive, bool useBinary, bool usePassive)
{
string RemoteFtpPath = "ftp://ftp.xxxx.ac.uk/incoming/testExtractCSVcoursesContacts.csv";
const string Username = "anonymous";
const string Password = "anonymous#xxxx.ac.uk";
var request = (FtpWebRequest)WebRequest.Create(new Uri(RemoteFtpPath));
request.Method = WebRequestMethods.Ftp.DownloadFile;
request.KeepAlive = keepAlive;
request.UsePassive = usePassive;
request.UseBinary = useBinary;
request.Credentials = new NetworkCredential(Username, Password);
request.Timeout = 30000;
try
{
var response = (FtpWebResponse)request.GetResponse();
var responseStream = response.GetResponseStream();
var reader = new StreamReader(responseStream);
var fileString = reader.ReadToEnd();
Console.WriteLine(
$"Success! keepAlive={keepAlive}, useBinary={useBinary}, usePassive={usePassive} Length={fileString.Length}");
reader.Close();
response.Close();
}
catch (Exception e)
{
Console.WriteLine(
$"Failed! keepAlive={keepAlive}, useBinary={useBinary}, usePassive={usePassive}, message={e.Message}");
}
}
`
we also tried to set passive = true with identical results.
When we run it, using wireshark we are getting : Wireshark log c#
Now we tried the same with Python and it's working just fine:
import urllib.request
data = urllib.request.urlretrieve('path')
print(data)
the wireshark log looks quite different:
So tried different things, but not able to sort this out.
Some ftp servers don't support OPTS UTF8 but still transmit file names in UTF8. (Note that 'OPTs UTF8' is NOT required by the FTP Internationalization Standard, although supporting UTF8 file names is.) The .NET Ftp classes will use the default code page if they don't get an OK response to OPTS UTF8... It's unfortunate that MS didn't provide some way to use UTF8 anyway, since this leaves you unable to transmit international file names to and from otherwise UTF8-compliant servers.
The issue is sorted after using a different library as FtpWebRequest doesn't support it

Image downloaded from Azure Storage not being displayed

I'm new to Xamarin. I'm trying display a list of downloaded images. I am downloading images from an APP API on Azure, where I stored the file on Azure Storage.
My server code is the following:
public HttpResponseMessage Get(string PK, string RK)
{
//Creating CloudBlockBlolb...
byte[] bytes = new byte[blockBlob.Properties.Length]
for(int i = 0; i < blockBlob.Properties.Length; i++){
bytes[i] = 0x20;
}
blockBlob.DownloadToByteArray(bytes, 0);
HttpResponseMessage resp = new HttpResponseMessage(HttpStatusCode.OK);
resp.Content = new ByteArrayContent(bytes);
resp.Content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue("image/jpg");
return resp;
}
My Xamarin code is the following:
public MainPage ()
{
//...
List<PicturePost> list = new List<PicturePost>{
new PicturePost("title", "subtitle", "link/api/Pictures?PK=xxx&RK=yyy")
};
InitializeComponent ();
listView.ItemTemplate = new DataTemplate (typeof(CustomImageCell));
listView.HasUnevenRows = true;
listView.ItemsSource = list;
//...
}
And here is the relevant code for CustomImageCell:
var image = new Image ();
image.SetBinding (Image.SourceProperty, "image");
//...
horizontalLayout.Children.Add (image);
I know that my API call works, because when I test it on the browser, it returns the image. I also know that if I use any random links such as http://www.natureasia.com/common/img/splash/thailand.jpg the image is downloaded and displayed properly. It is only when I use the API link that it doesn't seem to be working. Can someone tell me what I am doing wrong?
so in my public MainPage(), I added the following:
listView.BeginRefresh ();
listView.EndRefresh ();
I realized at some point that the images would take some time to download. I assume that when the listView was created, the images were not finished downloading, so I added the code above... Pretty sure this is not the best way to do this (probably an await would be better, but I don't know where).

Downloading bulk files from sharepoint library

I want to download the files from a sharepoint document library through code as there are thousand of files in the document library.
I am thinking of creating console application, which I will run on sharepoint server and download files. Is this approach correct or, there is some other efficient way to do this.
Any help with code will be highly appreciated.
Like SigarDave said, it's perfectly possible to achieve this without writing a single line of code. But if you really want to code the solution for this, it's something like:
static void Main(string[] args)
{
// Change to the URL of your site
using (var site = new SPSite("http://MySite"))
using (var web = site.OpenWeb())
{
var list = web.Lists["MyDocumentLibrary"]; // Get the library
foreach (SPListItem item in list.Items)
{
if (item.File != null)
{
// Concat strings to get the absolute URL
// to pass to an WebClient object.
var fileUrl = string.Format("{0}/{1}", site.Url, item.File.Url);
var result = DownloadFile(fileUrl, "C:\\FilesFromMyLibrary\\", item.File.Name);
Console.WriteLine(result ? "Downloaded \"{0}\"" : "Error on \"{0}\"", item.File.Name);
}
}
}
Console.ReadKey();
}
private static bool DownloadFile(string url, string dest, string fileName)
{
var client = new WebClient();
// Change the credentials to the user that has the necessary permissions on the
// library
client.Credentials = new NetworkCredential("Username", "Password", "Domain");
var bytes = client.DownloadData(url);
try
{
using (var file = File.Create(dest + fileName))
{
file.Write(bytes, 0, bytes.Length); // Write file to disk
return true;
}
}
catch (Exception)
{
return false;
}
}
another way without using any scripts is by opening the document library using IE then in the ribbon you can click on Open in File Explorer where you can then drag and drop the files right on your desktop!

Shared Variable in C# .Net MVC Thread

I am uploading videos to server in .Net MVC application. Since it is takes some time I am doing in a background thread. On the other hand I am tracking the upload progress and display it to the user.
Here is my code
public class MyController : Controller
{
long chunkSize = 256 * 1024;
private static string _progress = ""; //if I make nonstatic it fails
//..........
//Some codes here
//..........
//Upload file Request
public ActionResult VideoUploader()
{
var client = (VimeoClient)Session["client"];
Ticket t = client.vimeo_videos_upload_getTicket();
string path = #"E:\d2.MOV"; //Hardcoded value for testing purposes
new Thread(() => Transfer(client, t, path)).Start(); //Push file to server in background
return PartialView("_progress", "Preparing to upload...");
}
//Worker Thread
private void Transfer(VimeoClient client, Ticket t, string path)
{
FileInfo UploadFile = new FileInfo(path);
int chunks = (int)Math.Floor(Convert.ToDouble(UploadFile.Length / chunkSize));
for (int i = 0; i <= chunks; i++)
{
string output = client.PostVideo(t, i, path,(int) chunkSize);
var v = client.vimeo_videos_upload_verifyChunks(t);
double percentage = (Convert.ToDouble(i + 1) / (chunks + 1)) * 100;
_progress = percentage.ToString() + "%"; // value sharing between two actions
}
string name = client.vimeo_videos_upload_complete(path, t);
client.vimeo_videos_embed_setPreset(client.Token, "200772", name);
}
//This method is calling from front end using jQuery to display progress
public ActionResult Progress()
{
//returning updated shared "_progress" varibal
return Json(_progress, JsonRequestBehavior.AllowGet);
}
}
My problem is when I made "_progress" nonstatic variable(private static _progress) it is not working. Value is always empty.
What I trying to do is share _progress variable between main thread and new thread. But it is failing when it nonstatic.
Please help me to correct. If you have a better option please share
Thanks in advance
You should be returning some sort of "operation ID" to the client as part of the original response. The Progress method should then take this operation ID as a parameter. The upload service should then store its progress against that operation ID (e.g. in a database, to allow you to scale horizontally).
Basically, you should imagine the situation where there are multiple transfers involved - you need some way of getting the progress for the right transfer.
Instance of MyController is created per request.
After you spin the worker thread you return the page to the client and that instance is gone.
You can pass this(i.e. the controller instance) to the Transfer method like this
new Thread(() => Transfer(this, client, t, path)).Start();
and then access the _progress variable in the Transfer method like this
private void Transfer(MyController controller,
VimeoClient client, Ticket t, string path)
{
controller._progress
the page is already returned, so you'll just be able to access the instance _progress field, but then how do you update the client?
you can either
return in the view an animated gif and make a periodical request to the server with javascript OR
use a library like SignalR to 'push' the progress update to the client

Resources