diff options
author | Javier Fernandez <jfernandez@igalia.com> | 2013-03-19 18:08:55 +0000 |
---|---|---|
committer | Michael Meeks <michael.meeks@suse.com> | 2013-03-25 13:23:12 +0000 |
commit | 23c44b5745da8f0c63492e2246ffa41a439e3869 (patch) | |
tree | a018f95f6e9a750628ba4492771f467043649464 /wizards | |
parent | a669ee3816eca4cd3c55a5a704eca2dde53ddf59 (diff) |
Init: Added new file FTPDialog.py
Change-Id: Ia5ac3202e602fa5154510c7249847713cc76692e
Diffstat (limited to 'wizards')
-rw-r--r-- | wizards/com/sun/star/wizards/web/FTPDialog.py | 472 |
1 files changed, 472 insertions, 0 deletions
diff --git a/wizards/com/sun/star/wizards/web/FTPDialog.py b/wizards/com/sun/star/wizards/web/FTPDialog.py new file mode 100644 index 000000000000..6cd34aea0dfb --- /dev/null +++ b/wizards/com/sun/star/wizards/web/FTPDialog.py @@ -0,0 +1,472 @@ +# +# This file is part of the LibreOffice project. +# +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. +# +# This file incorporates work covered by the following license notice: +# +# Licensed to the Apache Software Foundation (ASF) under one or more +# contributor license agreements. See the NOTICE file distributed +# with this work for additional information regarding copyright +# ownership. The ASF licenses this file to you under the Apache +# License, Version 2.0 (the "License"); you may not use this file +# except in compliance with the License. You may obtain a copy of +# the License at http://www.apache.org/licenses/LICENSE-2.0 . +import traceback +import uno + +from .WWHID import * +from .FTPDialogResources import FTPDialogResources +from ..ui.UnoDialog2 import UnoDialog2 +from ..ui.UIConsts import UIConsts +from ..ui.event.DataAware import DataAware +from ..ui.event.UnoDataAware import UnoDataAware +from ..common.PropertyNames import PropertyNames +from ..common.SystemDialog import SystemDialog +from ..common.FileAccess import FileAccess +from ..common.HelpIds import HelpIds +from ..common.UCB import UCB +from .data.CGPublish import CGPublish +from .data.CGSettings import CGSettings + +#from com.sun.star.ucb import AuthenticationRequest +#from com.sun.star.ucb import InteractiveAugmentedIOException +#from com.sun.star.ucb import InteractiveNetworkConnectException +#from com.sun.star.ucb import InteractiveNetworkResolveNameException +#from com.sun.star.ucb import OpenCommandArgument2 +#from com.sun.star.ucb import OpenMode + +PushButtonType_OK_value = uno.getConstantByName( "com.sun.star.awt.PushButtonType.OK" ) +PushButtonType_CANCEL_value = uno.getConstantByName( "com.sun.star.awt.PushButtonType.CANCEL" ) +PushButtonType_HELP_value = uno.getConstantByName( "com.sun.star.awt.PushButtonType.HELP" ) + + +# This is the FTP Dialog. <br/> +# The Dialog enables the user: +# (*) entering FTP server and user information. +# (*) testing the connection. +# (*) choosing a directory on the server. +# If a connection was established successfully, the user may +# press OK, which will change +# the CGPublish object propertiers according the user's input. +# If no connection was established. the OK and Choose-Dir button are disabled. +# See the method "disconnect()" which disables them. +# +# I use here the DataAware concept to automatically update +# the members ip, username, and password (via the methods setXXX(...)) +# for details see the ui.events.DataAware classes. <br/> +class FTPDialog(UnoDialog2, UIConsts): + + # A Constant used for the setLabel(int) method to change the + # status-display. "unknown" is the status when the user first + # opens the dialog, or changes the servername/username/password. + STATUS_UNKONWN = 0 + # A Constant used for the setLabel(int) method to change the + # status-display. (connection established) + STATUS_OK = 1 + # A Constant used for the setLabel(int) method to change the + # status-display. + STATUS_USER_PWD_WRONG = 2 + # A Constant used for the setLabel(int) method to change the + # status-display. + STATUS_SERVER_NOT_FOUND = 3 + # A Constant used for the setLabel(int) method to change the + # status-display. + STATUS_NO_RIGHTS = 4 + # A Constant used for the setLabel(int) method to change the + # status-display. + STATUS_HOST_UNREACHABLE = 5 + # A Constant used for the setLabel(int) method to change the + # status-display. + STATUS_CONNECTING = 6 + # The icon url for error + ICON_ERROR = "ftperror.gif" + # The icon url for ok (connection ok) + ICON_OK = "ftpconnected.gif" + # The icon url for unknown - this is the status when + # the user first opens the dialog + ICON_UNKNOWN = "ftpunknown.gif" + # The icon url for an icon representing the "connecting" state. + ICON_CONNECTING = "ftpconnecting.gif" # GUI Components as Class members. + # Fixed Line + ln1 = None + lblFTPAddress = None + txtHost = None + lblUsername = None + txtUsername = None + lblPassword = None + txtPassword = None + # Fixed Line + ln2 = None + btnTestConnection = None + imgStatus = None + lblStatus = None + # Fixed Line + ln3 = None + txtDir = None + btnDir = None + btnOK = None + btnCancel = None + btnHelp = None + # Font Descriptors as Class members. + + # Resources Object + resources = None + dataAware = [] + username = "" + password = "" + + #The ftp host name + host = "" + #The ftp directory. + folder = "" + #the ftp publish object which contains the + #data for this dialog. + publish = None + ucb = None + #used for the status images url. + imagesDirectory = "" + + # constructor. + # constructs the UI. + # @param xmsf + # @param p the publishert object that contains the data + # for this dialog + # @throws Exception + def __init__(self, xmsf, p): + super(FTPDialog, self).__init__(xmsf) + self.publish = p + + #templateDir = p.root.soTemplateDir + templateDir = "" + self.imagesDirectory = FileAccess.connectURLs(templateDir, "../wizard/bitmap/") + + # Load Resources + self.resources = FTPDialogResources(xmsf) + self.ucb = UCB(xmsf) + + # set dialog properties... + uno.invoke(self.xDialogModel, "setPropertyValues", + (("Closeable", + PropertyNames.PROPERTY_HEIGHT, + PropertyNames.PROPERTY_HELPURL, "Moveable", + PropertyNames.PROPERTY_NAME, + PropertyNames.PROPERTY_POSITION_X, + PropertyNames.PROPERTY_POSITION_Y, + "Title", + PropertyNames.PROPERTY_WIDTH), + (True, + 160, + HelpIds.getHelpIdString(HID_FTP), + True, + "FTPDialog", + 167, + 82, + self.resources.resFTPDialog_title, + 222))) + + # add controls to dialog + self.build() + #make the hostname, username and password textfield data-aware. + self.configure() + #make sure we display a disconnected status. + self.disconnect() + + + # Add controls to dialog. + def build(self): + PROPNAMES_LABEL = (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_LABEL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, PropertyNames.PROPERTY_TABINDEX, PropertyNames.PROPERTY_WIDTH) + PROPNAMES_BUTTON = (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, PropertyNames.PROPERTY_LABEL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, PropertyNames.PROPERTY_TABINDEX, PropertyNames.PROPERTY_WIDTH) + PROPNAMES_BUTTON2 = (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, PropertyNames.PROPERTY_LABEL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, "PushButtonType", PropertyNames.PROPERTY_TABINDEX, PropertyNames.PROPERTY_WIDTH) + + ln1 = self.insertFixedLine("ln1", + PROPNAMES_LABEL, + (8, self.resources.resln1_value, "ln1", 6, 6, 0, 210)) + lblFTPAddress = self.insertLabel("lblFTPAddress", + PROPNAMES_LABEL, + (8, self.resources.reslblFTPAddress_value, "lblFTPAddress", 12, 20, 1, 95)) + self.txtHost = self.insertTextField("txtHost", "disconnect", + (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, PropertyNames.PROPERTY_TABINDEX, PropertyNames.PROPERTY_WIDTH), + (12, HelpIds.getHelpIdString(HID_FTP_SERVER), "txtIP", 110, 18, 2, 106), self) + self.lblUsername = self.insertLabel("lblUsername", + PROPNAMES_LABEL, + (8, self.resources.reslblUsername_value, "lblUsername", 12, 36, 3, 85)) + self.txtUsername = self.insertTextField("txtUsername", "disconnect", + (PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, PropertyNames.PROPERTY_TABINDEX, PropertyNames.PROPERTY_WIDTH), + (12, HelpIds.getHelpIdString(HID_FTP_USERNAME), "txtUsername", 110, 34, 4, 106), self) + self.lblPassword = self.insertLabel("lblPassword", + PROPNAMES_LABEL, + (8, self.resources.reslblPassword_value, "lblPassword", 12, 52, 5, 85)) + self.txtPassword = self.insertTextField("txtPassword", "disconnect", + ("EchoChar", PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, PropertyNames.PROPERTY_TABINDEX, PropertyNames.PROPERTY_WIDTH), + (42, 12, HelpIds.getHelpIdString(HID_FTP_PASS), "txtPassword", 110, 50, 6, 106), self) + self.ln2 = self.insertFixedLine("ln2", + PROPNAMES_LABEL, + (8, self.resources.resln2_value, "ln2", 6, 68, 7, 210)) + self.btnTestConnection = self.insertButton("btnConnect", "connect", + PROPNAMES_BUTTON, + (14, HelpIds.getHelpIdString(HID_FTP_TEST), self.resources.resbtnConnect_value, "btnConnect", 12, 80, 8, 50), self) + self.imgStatus = self.insertImage("imgStatus", + ("Border", PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, "ScaleImage", "Tabstop", PropertyNames.PROPERTY_WIDTH), + (0, 14, 68, 80, False, False, 14)) + self.lblStatus = self.insertLabel("lblStatus", + PROPNAMES_LABEL, + (8, self.resources.resFTPDisconnected, "lblStatus", 86, 82, 9, 99)) + self.ln3 = self.insertFixedLine("ln3", + PROPNAMES_LABEL, + (8, self.resources.resln3_value, "ln3", 6, 100, 10, 210)) + self.txtDir = self.insertTextField("txtDir", None, + (PropertyNames.PROPERTY_ENABLED, PropertyNames.PROPERTY_HEIGHT, PropertyNames.PROPERTY_HELPURL, PropertyNames.PROPERTY_NAME, PropertyNames.PROPERTY_POSITION_X, PropertyNames.PROPERTY_POSITION_Y, PropertyNames.PROPERTY_TABINDEX, "Text", PropertyNames.PROPERTY_WIDTH), + (False, 12, HelpIds.getHelpIdString(HID_FTP_TXT_PATH), "txtDir", 12, 113, 11, self.resources.restxtDir_value, 184), self) + self.btnDir = self.insertButton("btnDir", "chooseDirectory", + PROPNAMES_BUTTON, + (14, HelpIds.getHelpIdString(HID_FTP_BTN_PATH), self.resources.resbtnDir_value, "btnDir", 199, 112, 12, 16), self) + self.btnOK = self.insertButton("btnOK", None, + PROPNAMES_BUTTON2, + (14, HelpIds.getHelpIdString(HID_FTP_OK), self.resources.resbtnOK_value, "btnOK", 165, 142, PushButtonType_OK_value, 13, 50), self) + self.btnCancel = self.insertButton("btnCancel", + None, PROPNAMES_BUTTON2, + (14, HelpIds.getHelpIdString(HID_FTP_CANCEL), self.resources.resbtnCancel_value, "btnCancel", 113, 142, PushButtonType_CANCEL_value, 14, 50), self) + self.btnHelp = self.insertButton("btnHelp", None, + PROPNAMES_BUTTON2, + (14, "", self.resources.resbtnHelp_value, "btnHelp", 57, 142, PushButtonType_HELP_value, 15, 50), self) + + + # Make hostname, username and password text fields data aware. + def configure(self): + self.dataAware.append(UnoDataAware.attachEditControl(self, "host", self.txtHost, True)) + self.dataAware.append(UnoDataAware.attachEditControl(self, "username", self.txtUsername, True)) + self.dataAware.append(UnoDataAware.attachEditControl(self, "password", self.txtPassword, True)) + + # Shows the dialog. + # If the user clicks ok, changes the given CGPublish properties to the + # user input. + # @param parent a dialog to center this dialog to. + # @return 0 for cancel, 1 for ok. + # @throws Exception - well, if something goes wrong... + def execute(self, parent): + self.host = self.extractHost(self.publish.cp_URL) + self.username = "" if (self.publish.cp_Username == None) else self.publish.cp_Username + self.password = "" if (self.publish.password == None) else self.publish.password + self.folder = self.extractDir(self.publish.cp_URL) + self.setLabel(self.STATUS_UNKONWN) + + self.enableTestButton() + self.updateUI() + result = self.executeDialogFromParent(parent) + # change the CGPublish properties + if (result == 1): + self.publish.cp_URL = "ftp://" + self.host() + self.getDir() + self.publish.cp_Username = self.username + self.publish.password = self.password + + return result + + # updates the hostname, username, password and + # directory text fields. + # is called uppon initialization. + def updateUI(self): + DataAware.updateUIs(self.dataAware) + self.setDir(self.folder) + + # extract the hostname out of the url used by the + # publisher. This url does not include the username:password string. + # @param ftpUrl + # @return + def extractHost(self, ftpUrl): + if (ftpUrl is None or len(ftpUrl) < 6): + return "" + url = ftpUrl.substring(6) + i = url.indexOf("/") + if (i == -1): + return url + else: + return url.substring(0, i) + + # used to get data from the CGPublish object. + # @param ftpUrl + # @return the directory portion of the ftp-url + def extractDir(self, ftpUrl): + if (ftpUrl is None or len(ftpUrl) < 6): + return "/" + url = ftpUrl.substring(6) + i = url.indexOf("/") + if (i == -1): + return "/" + else: + return url.substring(i) + + # enables/disables the "test" button + # according to the status of the hostname, username, password text fields. + # If one of these fields is empty, the button is disabled. + def enableTestButton(self): + self.setEnabled(self.btnTestConnection, not self.isEmpty(self.host) or self.isEmpty(self.username) or self.isEmpty(self.password)) + + # @param s + # @return True if the string is None or "". + def isEmpty(self, s): + return (s is None) or (s == "") + + # @return the ftp url with username and password, + # but without the directory portion. + def getAcountUrl(self): + return "ftp://" + self.username + ":" + self.password + "@" + self.host() + + # return the host name without the "ftp://" + # @return + def host(self): + return self.host(self.host) + + @classmethod + def host1(self, s): + return s.substring(6) if s.startswith("ftp://") else s + + # @return the full ftp url including username, password and directory portion. + def getFullUrl(self): + return self.getAcountUrl() + self.folder + + # First I try to connect to the full url, including directory. + # If an InteractiveAugmentedIOException accures, I try again, + # this time without the dir spec. If this works, I change the dir + # to "/", if not I say to the user its his problem... + def connect(self): + self.setEnabled(self.btnTestConnection, False) + self.setLabel(self.STATUS_CONNECTING) + success = False + try: + self.connect1(self.getFullUrl()) + success = True + except InteractiveAugmentedIOException as iaioex: + try: + self.connect1(self.getAcountUrl()) + self.setDir("/") + success = True + except Exception: + self.setLabel(self.STATUS_NO_RIGHTS) + except InteractiveNetworkResolveNameException as inrne: + self.setLabel(self.STATUS_SERVER_NOT_FOUND) + except AuthenticationRequest as ar: + self.setLabel(self.STATUS_USER_PWD_WRONG) + except InteractiveNetworkConnectException as incx: + self.setLabel(self.STATUS_HOST_UNREACHABLE) + except Exception: + self.setLabel(-1) + traceback.print_exc() + + if (success): + self.setLabel(self.STATUS_OK) + self.setEnabled(self.btnDir, True) + self.setEnabled(self.btnOK, True) + + self.setEnabled(self.btnTestConnection, True) + + + # To try the conenction I do some actions that + # seem logical to me: <br/> + # I get a ucb content. + # I list the files in this content. + # I call the ucb "open" command. + # I get the PropertyNames.PROPERTY_TITLE property of this content. + # @param acountUrl + # @throws Exception + def connect1(self, acountUrl): + content = self.ucb.getContent(self.acountUrl) + + # list files in the content. + l = self.ucb.listFiles(self.acountUrl, None) + + # open the content + aArg = OpenCommandArgument2() + aArg.Mode = OpenMode.FOLDERS # FOLDER, DOCUMENTS -> simple filter + aArg.Priority = 32768 # Ignored by most implementations + + self.ucb.executeCommand(content, "open", aArg) + + # get the title property of the content. + obj = self.ucb.getContentProperty(content, PropertyNames.PROPERTY_TITLE, str()) + + # changes the ftp subdirectory, in both + # the UI and the data. + # @param s the directory. + def setDir(self, s): + self.folder = s + self.txtDir.Model.Text = self.folder + + # @return the ftp subdirecrtory. + def getDir(self): + return self.folder + + # changes the status label to disconnected status, and + # disables the ok and choose-dir buttons. + # This method is called also when the hostname, username + # and passwordtext fields change. + def disconnect(self): + self.enableTestButton() + self.setEnabled(self.btnOK, False) + self.setEnabled(self.btnDir, False) + self.setLabel(self.STATUS_UNKONWN) + + # changes the status label and icon, according to the + # given status + # @param status one opf the private status-constants. + # if this param is not one of them, an "unknown error" status is displayed. + def setLabel(self, status): + if status == self.STATUS_UNKONWN: + # not connected yet + self.setLabel1(self.resources.resFTPDisconnected, self.ICON_UNKNOWN) + elif status == self.STATUS_OK: + # connected! + self.setLabel1(self.resources.resFTPConnected, self.ICON_OK) + elif status == self.STATUS_USER_PWD_WRONG: + # wronf password + self.setLabel1(self.resources.resFTPUserPwdWrong, self.ICON_ERROR) + elif status == self.STATUS_SERVER_NOT_FOUND: + # problem resolving server name + self.setLabel1(self.resources.resFTPServerNotFound, self.ICON_ERROR) + elif status == self.STATUS_NO_RIGHTS: + # rights problem + self.setLabel1(self.resources.resFTPRights, self.ICON_ERROR) + elif status == self.STATUS_HOST_UNREACHABLE: + # host unreachable (firewall?) + self.setLabel1(self.resources.resFTPHostUnreachable, self.ICON_ERROR) + elif status == self.STATUS_CONNECTING: + self.setLabel1(self.resources.resConnecting, self.ICON_CONNECTING) + else: + self.setLabel1(self.resources.resFTPUnknownError, self.ICON_ERROR) + + # changes the text of the status label and + # (TODO) the status image. + # @param label + # @param image + def setLabel1(self, label, image): + setattr(self.lblStatus.Model, PropertyNames.PROPERTY_LABEL, label) + setattr(self.imgStatus.Model, PropertyNames.PROPERTY_IMAGEURL, self.imageUrl(image)) + + def imageUrl(self, s): + return self.imagesDirectory + s + + # called when the user clicks + # the choose-dir button. ("...") + # Opens the pickFolder dialog. + # checks if the returned folder is an ftp folder. + # sets the textbox and the data to the new selected dir. + def chooseDirectory(self): + sd = SystemDialog.createOfficeFolderDialog(self.xMSF) + newUrl = sd.callFolderDialog(self.resources.resFTPDirectory, "", self.getFullUrl()) + if (newUrl is not None): + # if the user chose a local directory, + # sI do not accept it. + if (newUrl.startswith("ftp://")): + self.setDir(extractDir(newUrl)) + else: + AbstractErrorHandler.showMessage(self.xMSF, self.xUnoDialog.getPeer(), self.resources.resIllegalFolder, ErrorHandler.ERROR_PROCESS_FATAL) + + # practical to have such a method... + # @param p the publisher obejct that contains the ftp connection info. + # @return the full ftp url with username password and everything one needs. + @classmethod + def getFullURL1(self, p): + #return "ftp://" + p.Username + ":" + p.password + "@" + self.host(p.URL) + return "ftp://" + p.cp_Username + ":" + "" + "@" + self.host1(p.cp_URL) |