private void HandleExecuteScalar()
        {
            var startIndex = CommandText.IndexOf(ExecuteScalarBeginDelimiter);

            if (startIndex == -1)
            {
                return;
            }

            var endIndex = CommandText.IndexOf(ExecuteScalarEndDelimiter, startIndex);

            if (endIndex == -1)
            {
                return;
            }

            var commandText = CommandText;
            var fullText    = CommandText.Substring(startIndex, (endIndex + ExecuteScalarEndDelimiter.Length) - startIndex);

            CommandText = fullText.Substring(ExecuteScalarBeginDelimiter.Length, fullText.Length - (ExecuteScalarEndDelimiter.Length + ExecuteScalarBeginDelimiter.Length));

            var value = ExecuteScalar();

            CommandText = commandText.Replace(fullText, GetFormattedValue(value));
        }
Exemple #2
0
        public object ExecuteScalar()
        {
            logger.WriteDbOperation($"Execute scalar command: {CommandText}");

            if (CommandText == "error")
            {
                ThrowError();
            }

            // Are we checking if schemaversions exists
            if (CommandText.IndexOf(schemaTableName, StringComparison.OrdinalIgnoreCase) != -1)
            {
                if (runScripts != null)
                {
                    return(1);
                }
                return(0);
            }

            if (scalarResults.ContainsKey(CommandText))
            {
                return(scalarResults[CommandText]());
            }

            return(null);
        }
Exemple #3
0
        /// <summary>
        /// EXAMPLE QUERY
        /// CREATE INDEX idx_lastname
        /// ON Persons(LastName);
        /// </summary>
        protected override void ParseQuery()
        {
            // find index of open bracket in create query, where are descriptions of columns
            var openBacket = CommandText.IndexOf('(');
            // find index of close bracket in create query, where are descriptions of columns
            var closeBacket = CommandText.LastIndexOf(')');

            if (openBacket == -1 || closeBacket == -1 || openBacket == closeBacket)
            {
                throw new CreateIndexParse($"Command has incorrect signature. Check brackets.");
            }
            // get columns name
            var commandWords = CommandText?
                               .Substring(0, openBacket)
                               .Trim()
                               .Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            if (commandWords[0].ToLower() != "create")
            {
                throw new CreateIndexParse($"Command has incorrect signature.");
            }
            if (commandWords.Length == 5)
            {
                if (commandWords[2].ToLower() != "index")
                {
                    throw new CreateIndexParse($"Command has incorrect signature.");
                }
                // find 'ON' into query
                if (commandWords[3].ToLower() != "on")
                {
                    throw new CreateIndexParse($"Command has incorrect signature.");
                }
                TableName = commandWords[4];
                IndexName = commandWords[2];
                IndexType = IndexType.DenseIndex;
            }
            else if (commandWords.Length == 6)
            {
                if (commandWords[3].ToLower() != "index")
                {
                    throw new CreateIndexParse($"Command has incorrect signature.");
                }
                throw new CreateIndexParse($"Command has not released.");
            }
            else
            {
                throw new CreateIndexParse($"Command has incorrect signature.");
            }

            var columnName = CommandText?
                             .Substring(openBacket + 1, closeBacket - 1 - openBacket);

            if (columnName.Length == 0)
            {
                throw new CreateIndexParse($"Command has incorrect signature. Can not parse columns name.");
            }

            TableName = commandWords[2].Trim();
        }
Exemple #4
0
        public IDataReader ExecuteReader()
        {
            logger.WriteDbOperation($"Execute reader command: {CommandText}");

            if (CommandText == "error")
            {
                ThrowError();
            }

            // Reading SchemaVersions
            if (CommandText.IndexOf(schemaTableName, StringComparison.OrdinalIgnoreCase) != -1)
            {
                return(new ScriptReader(runScripts));
            }

            return(new EmptyReader());
        }
Exemple #5
0
        protected override void ParseQuery()
        {
            // find index of open bracket in create query, where are descriptions of columns
            var openBacket = CommandText.IndexOf('(');
            // find index of close bracket in create query, where are descriptions of columns
            var closeBacket = CommandText.LastIndexOf(')');

            if (openBacket == -1 || closeBacket == -1 || openBacket == closeBacket)
            {
                throw new CreateTableParse($"Command has incorrect signature. Check brackets.");
            }
            // get command words, words befor descriptions of columns
            var commandWords = CommandText?
                               .Substring(0, openBacket)
                               .Trim()
                               .Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

            if (commandWords.Length != 3)
            {
                throw new CreateTableParse($"Command has incorrect signature. Check table name.");
            }
            // set table name and database name if format [dbname].[tableName]
            var tableAndDatabaseNames = commandWords[2].Split('.');

            if (tableAndDatabaseNames.Length == 2)
            {
                DatabaseName = tableAndDatabaseNames[0];
                TableName    = tableAndDatabaseNames[1];
            }
            else
            {
                TableName = tableAndDatabaseNames[0];
            }
            //
            Columns = CommandText?
                      .Substring(openBacket + 1, closeBacket - openBacket - 1)
                      .Trim()
                      .Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            if (Columns.Length == 0)
            {
                throw new CreateTableParse($"Command does not have new columns description.");
            }
        }
Exemple #6
0
        private Boolean CheckFunctionNeedsColumnDefinitionList()
        {
            // If and only if a function returns "record" and has no OUT ("o" in proargmodes), INOUT ("b"), or TABLE
            // ("t") return arguments to characterize the result columns, we must provide a column definition list.
            // See http://pgfoundry.org/forum/forum.php?thread_id=1075&forum_id=519
            // We would use our Output and InputOutput parameters to construct that column definition list.  If we have
            // no such parameters, skip the check: we could only construct "AS ()", which yields a syntax error.

            // Updated after 0.99.3 to support the optional existence of a name qualifying schema and allow for case insensitivity
            // when the schema or procedure name do not contain a quote.
            // The hard-coded schema name 'public' was replaced with code that uses schema as a qualifier, only if it is provided.

            String returnRecordQuery;

            StringBuilder parameterTypes = new StringBuilder("");

            // Process parameters

            Boolean seenDef = false;

            foreach (NpgsqlParameter p in Parameters)
            {
                if ((p.Direction == ParameterDirection.Input) || (p.Direction == ParameterDirection.InputOutput))
                {
                    parameterTypes.Append(Connection.Connector.OidToNameMapping[p.TypeInfo.Name].OID.ToString() + " ");
                }

                if ((p.Direction == ParameterDirection.Output) || (p.Direction == ParameterDirection.InputOutput))
                {
                    seenDef = true;
                }
            }

            if (!seenDef)
            {
                return(false);
            }

            // Process schema name.

            String schemaName    = String.Empty;
            String procedureName = String.Empty;

            String[] fullName = CommandText.Split('.');

            String predicate = "prorettype = ( select oid from pg_type where typname = 'record' ) "
                               + "and proargtypes=:proargtypes and proname=:proname "
                               // proargmodes && array['o','b','t']::"char"[] performs just as well, but it requires PostgreSQL 8.2.
                               + "and ('o' = any (proargmodes) OR 'b' = any (proargmodes) OR 't' = any (proargmodes)) is not true";

            if (fullName.Length == 2)
            {
                returnRecordQuery =
                    "select count(*) > 0 from pg_proc p left join pg_namespace n on p.pronamespace = n.oid where " + predicate + " and n.nspname=:nspname";

                schemaName    = (fullName[0].IndexOf("\"") != -1) ? fullName[0] : fullName[0].ToLower();
                procedureName = (fullName[1].IndexOf("\"") != -1) ? fullName[1] : fullName[1].ToLower();
            }
            else
            {
                // Instead of defaulting don't use the nspname, as an alternative, query pg_proc and pg_namespace to try and determine the nspname.
                //schemaName = "public"; // This was removed after build 0.99.3 because the assumption that a function is in public is often incorrect.
                returnRecordQuery =
                    "select count(*) > 0 from pg_proc p where " + predicate;

                procedureName = (CommandText.IndexOf("\"") != -1) ? CommandText : CommandText.ToLower();
            }

            bool ret;

            using (NpgsqlCommand c = new NpgsqlCommand(returnRecordQuery, Connection))
            {
                c.Parameters.Add(new NpgsqlParameter("proargtypes", NpgsqlDbType.Oidvector));
                c.Parameters.Add(new NpgsqlParameter("proname", NpgsqlDbType.Name));

                c.Parameters[0].Value = parameterTypes.ToString();
                c.Parameters[1].Value = procedureName;

                if (schemaName != null && schemaName.Length > 0)
                {
                    c.Parameters.Add(new NpgsqlParameter("nspname", NpgsqlDbType.Name));
                    c.Parameters[2].Value = schemaName;
                }

                ret = (Boolean)c.ExecuteScalar();
            }

            return(ret);
        }
        /// <summary>
        /// Finds the next command for auto completion
        /// </summary>
        /// <param name="partialCommand">The partial command being completed</param>
        /// <param name="lastResult">The last result returned. Null to get the first match</param>
        /// <param name="registries">The list of registries to search for matches</param>
        /// <returns>The next command matching the partial string</returns>
        public static string FindNextCommand(ReadOnlySpan <char> partialCommand, ReadOnlySpan <char> lastResult, IEnumerable <TerminalRegistry> registries)
        {         //****************************************
            ReadOnlySpan <char> CommandText, PartialText;
            ReadOnlySpan <char> Prefix       = default;
            ReadOnlySpan <char> InstanceName = default;

            int CharIndex;

            TerminalTypeSet?     TypeSet = null;
            TerminalTypeInstance?TypeInstance;

            var PartialMatches = new List <string>();

            //****************************************

            if (partialCommand.StartsWith("help ".AsSpan(), StringComparison.InvariantCultureIgnoreCase))
            {
                partialCommand = partialCommand.Slice(5);

                Prefix = "Help ".AsSpan();
            }

            //****************************************

            // Find the first word (split on a space)
            CharIndex = partialCommand.IndexOf(' ');

            // If there's a space, we're parsing an Instance Type and optional Instance Name, with a partial Command/Variable
            if (CharIndex != -1)
            {
                CommandText = partialCommand.Slice(0, CharIndex);
                PartialText = partialCommand.Slice(CharIndex + 1);

                CharIndex = CommandText.IndexOf('.');

                // Split into Type and Name if necessary
                if (CharIndex != -1)
                {
                    InstanceName = CommandText.Slice(CharIndex + 1);
                    CommandText  = CommandText.Slice(0, CharIndex);
                }

                foreach (var Registry in registries)
                {
                    if (Registry.TryGetTypeSet(CommandText, out TypeSet))
                    {
                        break;
                    }
                }

                // If the instance type doesn't match, return the partial command as is
                if (TypeSet == null)
                {
                    return(Prefix.Concat(partialCommand));
                }

                if (InstanceName == null)
                {
                    TypeInstance = TypeSet.Default;
                    CommandText  = TypeSet.TypeName.AsSpan();
                }
                else
                {
                    if (!TypeSet.TryGetNamedInstance(InstanceName, out TypeInstance))
                    {
                        return(Prefix.Concat(partialCommand));
                    }

                    CommandText = $"{TypeSet.TypeName}.{TypeInstance.Name}".AsSpan();
                }

                // If the instance doesn't exist, return as is
                if (TypeInstance == null)
                {
                    return(Prefix.Concat(partialCommand));
                }

                // Add matching commands
                foreach (var MyCommand in TypeInstance.Type.Commands)
                {
                    if (MyCommand.Name.StartsWith(PartialText, StringComparison.InvariantCultureIgnoreCase))
                    {
                        PartialMatches.Add(CommandText.Concat(" ", MyCommand.Name));
                    }
                }

                // Add matching variables
                foreach (var MyVariable in TypeInstance.Type.Variables)
                {
                    if (MyVariable.Name.StartsWith(PartialText, StringComparison.InvariantCultureIgnoreCase))
                    {
                        PartialMatches.Add(CommandText.Concat(" ", MyVariable.Name));
                    }
                }
            }
            else
            {
                CharIndex = partialCommand.IndexOf('.');

                // If there's a dot, we're parsing an Instance Type, with a partial Instance Name
                if (CharIndex != -1)
                {
                    CommandText = partialCommand.Slice(0, CharIndex);
                    PartialText = partialCommand.Slice(CharIndex + 1);

                    foreach (var MyRegistry in registries)
                    {
                        if (MyRegistry.TryGetTypeSet(CommandText, out TypeSet))
                        {
                            break;
                        }
                    }

                    // If the instance type doesn't match, return the partial command as is
                    if (TypeSet == null)
                    {
                        return(Prefix.Concat(partialCommand));
                    }

                    foreach (var MyInstanceName in TypeSet.Instances)
                    {
                        if (MyInstanceName.StartsWith(PartialText, StringComparison.InvariantCultureIgnoreCase))
                        {
                            PartialMatches.Add(string.Format("{0}.{1}", TypeSet.TypeName, MyInstanceName));
                        }
                    }
                }
                else
                {
                    // No dot, we're parsing a partial Command/Variable/Instance Type
                    foreach (var Registry in registries)
                    {
                        // Add matching commands
                        foreach (var Command in Registry.Commands)
                        {
                            if (Command.Name.StartsWith(partialCommand, StringComparison.InvariantCultureIgnoreCase))
                            {
                                PartialMatches.Add(Command.Name);
                            }
                        }

                        // Add matching variables (with an equals sign, so they can't be the same as commands)
                        foreach (var Variable in Registry.Variables)
                        {
                            if (Variable.Name.StartsWith(partialCommand, StringComparison.InvariantCultureIgnoreCase))
                            {
                                PartialMatches.Add(Variable.Name);
                            }
                        }

                        foreach (var Instance in Registry.DefaultInstances)
                        {
                            foreach (var Command in Instance.Type.Commands)
                            {
                                if (Command.Name.StartsWith(partialCommand, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    PartialMatches.Add(Command.Name);
                                }
                            }

                            // Add matching variables (with an equals sign, so they can't be the same as commands)
                            foreach (var Variable in Instance.Type.Variables)
                            {
                                if (Variable.Name.StartsWith(partialCommand, StringComparison.InvariantCultureIgnoreCase))
                                {
                                    PartialMatches.Add(Variable.Name);
                                }
                            }
                        }

                        // Add matching type sets
                        foreach (var Type in Registry.TypeSets)
                        {
                            // Only add ones that have an instance
                            if (Type.TypeName.StartsWith(partialCommand, StringComparison.InvariantCultureIgnoreCase) && Type.HasInstance)
                            {
                                PartialMatches.Add(Type.TypeName);
                            }
                        }
                    }
                }
            }

            //****************************************

            // Any results?
            if (PartialMatches.Count == 0)
            {
                return("");
            }

            // Sort them, so we can pick the next matching result
            PartialMatches.Sort();

            if (lastResult != null)
            {
                // Find one greater than our last match (user has requested the next one)
                foreach (var NextCommand in PartialMatches)
                {
                    if (NextCommand.AsSpan().CompareTo(lastResult, StringComparison.OrdinalIgnoreCase) > 0)
                    {
                        return(Prefix.Concat(NextCommand));
                    }
                }
                // Nothing greater, go back to the start
            }

            return(Prefix.Concat(PartialMatches[0]));
        }
        void CommandReceived(IAsyncResult arg)
        {
            _activecommand = false;
            int CommandSize = 0;

            try { CommandSize = _clientSocket.EndReceive(arg); }
            catch { }
            if (CommandSize == 0)
            {
                Disconnect();
                //return;
            }

            // Wait for the next command to be sent by the client
            try
            {
                _clientSocket.BeginReceive(_portBuffer, 0, _portBuffer.Length, SocketFlags.None, new AsyncCallback(CommandReceived), null);
            }
            catch
            {
                Disconnect();
                return;
            }

            _lastcmdtime = DateTime.Now;
            string CommandText;

            if (_utf8)
            {
                CommandText = Encoding.UTF8.GetString(_portBuffer, 0, CommandSize).TrimStart(' ');
            }
            else
            {
                CommandText = Encoding.ASCII.GetString(_portBuffer, 0, CommandSize).TrimStart(' ');
            }
            string CmdArguments = null, Command = null;
            int    End = 0;

            if ((End = CommandText.IndexOf(' ')) == -1)
            {
                End = (CommandText = CommandText.Trim()).Length;
            }
            else
            {
                CmdArguments = CommandText.Substring(End).TrimStart(' ');
            }
            Command = CommandText.Substring(0, End).ToUpper();

            if (CmdArguments != null && CmdArguments.EndsWith("\r\n"))
            {
                CmdArguments = CmdArguments.Substring(0, CmdArguments.Length - 2);
            }
            bool CommandExecued = false;

            switch (Command)
            {
            case "USER":
                _activecommand = true;
                if (CmdArguments != null && CmdArguments.Length > 0)
                {
                    SendMessage("331 Password required!");
                    _connuser = CmdArguments;
                }
                CommandExecued = true;
                break;

            case "PASS":
                _activecommand = true;
                if (_connuser == "")
                {
                    SendMessage("503 Invalid User Name");
                    return;
                }
                if (_server.Users[_connuser] != null)
                {
                    if (_server.Users[_connuser].SHA1Password == HelperFunctions.SHA1Hash(CmdArguments))
                    {
                        _isAuthenticated = true;
                        _currentDir      = "/";
                        _currentperms    = _server.Users.GetPermissions(_connuser);
                        if (string.IsNullOrEmpty(_server.Users[_connuser].Startupdir) || _server.Users[_connuser].Startupdir == "/")
                        {
                            _localpath = _server.StartupDir;
                        }
                        else
                        {
                            _localpath = _server.Users[_connuser].Startupdir;
                        }
                        _server.Call_Log(new FTPLogEventArgs(FTPLogEventType.UserConnect, _connuser, true, 230, "none"));
                        SendMessage("230 Authentication Successful");
                    }
                    else
                    {
                        SendMessage("530 Authentication Failed!");
                        _server.Call_Log(new FTPLogEventArgs(FTPLogEventType.UserConnect, _connuser, false, 530, "none"));
                    }
                }
                else
                {
                    SendMessage("530 Authentication Failed!");
                    _server.Call_Log(new FTPLogEventArgs(FTPLogEventType.UserConnect, _connuser, false, 530, "none"));
                }
                CommandExecued = true;
                break;
            }
            if (!CommandExecued)
            {
                if (!_isAuthenticated)
                {
                    SendMessage("530 Access Denied! Authenticate first");
                    return;
                }
                switch (Command.ToUpper())
                {
                case "CWD":
                    _activecommand = true;
                    CWD(CmdArguments);
                    break;

                case "CDUP":
                    _activecommand = true;
                    string[] pathParts = _currentDir.Split('/');
                    if (pathParts.Length > 1)
                    {
                        _currentDir = "";
                        for (int i = 0; i < (pathParts.Length - 2); i++)
                        {
                            _currentDir += pathParts[i] + "/";
                        }
                        if (_currentDir.Length == 0)
                        {
                            _currentDir = "/";
                        }
                    }
                    SendMessage("250 CDUP command successful.");
                    break;

                case "QUIT":
                    _activecommand = true;
                    SendMessage("221 FTP server signing off");
                    Disconnect();
                    break;

                case "PWD":
                    _activecommand = true;
                    SendMessage("257 \"" + _currentDir + "\"");
                    break;

                case "PORT":
                    _activecommand = true;
                    PORT(CmdArguments);     //done
                    break;

                case "PASV":
                    _activecommand = true;
                    PASV(CmdArguments);     //done
                    break;

                case "TYPE":
                    _activecommand = true;
                    TYPE(CmdArguments);     //done
                    break;

                case "SYST":
                    _activecommand = true;
                    SendMessage("215 Windows_NT");
                    break;

                case "NOOP":
                    _activecommand = true;
                    SendMessage("200 OK");
                    break;

                case "RETR":
                    _activecommand = true;
                    RETR(CmdArguments);
                    break;

                case "STOR":
                    _activecommand = true;
                    STOR(CmdArguments, false);
                    break;

                case "APPE":
                    _activecommand = true;
                    APPE(CmdArguments);
                    break;

                case "RNFR":
                    _activecommand = true;
                    RNFR(CmdArguments);
                    break;

                case "RNTO":
                    _activecommand = true;
                    RNTO(CmdArguments);
                    break;

                case "DELE":
                    _activecommand = true;
                    DELE(CmdArguments);
                    break;

                case "RMD":
                    _activecommand = true;
                    RMD(CmdArguments);
                    break;

                case "MKD":
                    _activecommand = true;
                    MKD(CmdArguments);
                    break;

                case "LIST":
                    _activecommand = true;
                    LIST(_currentDir);
                    break;

                case "NLST":
                    _activecommand = true;
                    NLST(CmdArguments);
                    break;

                /*case "CLNT":
                 *  break;*/
                case "MDTM":
                    _activecommand = true;
                    MDTM(CmdArguments);
                    break;

                case "SIZE":
                    _activecommand = true;
                    SIZE(CmdArguments);
                    break;

                case "OPTS":
                    _activecommand = true;
                    OPTS(CmdArguments);
                    break;

                case "REIN":
                    _activecommand = true;
                    REIN(CmdArguments);
                    break;

                case "STOU":
                    _activecommand = true;
                    STOR(CmdArguments, true);
                    break;

                case "ABOR":
                case "SHUTDOWN":
                    if (_datasocket != null && _datasocket.Connected)
                    {
                        _datasocket.Close();
                    }
                    _datasocket = null;
                    GC.Collect();
                    SendMessage("200 Data transfer aborted");
                    _server.Call_Log(new FTPLogEventArgs(FTPLogEventType.Abort, _connuser, true, 200));
                    break;

                case "FEAT":
                    SendMessage("  SIZE");
                    SendMessage("  MTDM");
                    SendMessage("211 Feature list end");
                    _server.Call_Log(new FTPLogEventArgs(FTPLogEventType.FeatureList, _connuser, true, 211));
                    break;

                default:
                    SendMessage("500 Unknown Command.");
                    _server.Call_Log(new FTPLogEventArgs(FTPLogEventType.UnknownCommand, _connuser, true, 500, Command, CmdArguments));
                    break;

                    //	case "STAT":
                    //		break;

                    //	case "HELP":
                    //		break;

                    //	case "REST":
                    //		break;
                }
            }
        }