예제 #1
0
void clSSH::DoOpenChannel() throw(clException)
{
    if(m_channel) return;

    m_channel = ssh_channel_new(m_session);
    if(!m_channel) {
        throw clException(ssh_get_error(m_session));
    }

    int rc = ssh_channel_open_session(m_channel);
    if(rc != SSH_OK) {
        throw clException(ssh_get_error(m_session));
    }

    rc = ssh_channel_request_pty(m_channel);
    if(rc != SSH_OK) {
        throw clException(ssh_get_error(m_session));
    }

    rc = ssh_channel_change_pty_size(m_channel, 80, 24);
    if(rc != SSH_OK) {
        throw clException(ssh_get_error(m_session));
    }

    rc = ssh_channel_request_shell(m_channel);
    if(rc != SSH_OK) {
        throw clException(ssh_get_error(m_session));
    }
}
예제 #2
0
파일: clPatch.cpp 프로젝트: eranif/codelite
void
clPatch::Patch(const wxFileName& patchFile, const wxString& workingDirectory, const wxString& args) 
{
    // Sanity
    if(!m_patch.FileExists()) {
        throw clException("Could not locate patch executable");
    }

    if(!patchFile.FileExists()) {
        throw clException("Patch failed. File: '" + patchFile.GetFullPath() + "' does not exist");
    }

    // Prepare the command
    wxString command;
    command << m_patch.GetFullPath();

    ::WrapWithQuotes(command);

    if(!args.IsEmpty()) {
        command << " " << args;
    }

    // Change directory to the working directory requested by the user
    DirSaver ds;
    wxSetWorkingDirectory(workingDirectory.IsEmpty() ? ::wxGetCwd() : workingDirectory);

    wxString patch = patchFile.GetFullPath();

    command << " " << ::WrapWithQuotes(patch);
    ::WrapInShell(command);

    ProcUtils::SafeExecuteCommand(command);
}
예제 #3
0
void clSFTP::Mkpath(const wxString& remoteDirFullpath) throw(clException)
{
    if(!m_sftp) {
        throw clException("SFTP is not initialized");
    }

    wxString tmpPath = remoteDirFullpath;
    tmpPath.Replace("\\", "/");
    if(!tmpPath.StartsWith("/")) {
        throw clException("Mkpath: path must be absolute");
    }

    wxFileName fn(remoteDirFullpath, "");
    const wxArrayString& dirs = fn.GetDirs();
    wxString curdir;

    curdir << "/";
    for(size_t i = 0; i < dirs.GetCount(); ++i) {
        curdir << dirs.Item(i);
        sftp_attributes attr = sftp_stat(m_sftp, curdir.mb_str(wxConvISO8859_1).data());
        if(!attr) {
            // directory does not exists
            CreateDir(curdir);

        } else {
            // directory already exists
            sftp_attributes_free(attr);
        }
        curdir << "/";
    }
}
예제 #4
0
wxString clSFTP::Read(const wxString& remotePath) throw (clException)
{
    if ( !m_sftp ) {
        throw clException("SFTP is not initialized");
    }

    sftp_file file = sftp_open(m_sftp, remotePath.mb_str(wxConvISO8859_1).data(), O_RDONLY, 0);
    if (file == NULL) {
        throw clException(wxString() << _("Failed to open remote file: ") << remotePath << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp));
    }

    wxString content;
    char buffer[1024];
    int nbytes = 0;
    memset(buffer, 0, sizeof(buffer));
    nbytes = sftp_read(file, buffer, sizeof(buffer));
    while (nbytes > 0) {
        content << wxString(buffer, nbytes);

        memset(buffer, 0, sizeof(buffer));
        nbytes = sftp_read(file, buffer, sizeof(buffer));
    }

    if ( nbytes < 0 ) {
        sftp_close(file);
        throw clException(wxString() << _("Failed to read remote file: ") << remotePath << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp));
    }
    sftp_close( file );
    return content;
}
예제 #5
0
void clSFTP::Write(const wxFileName& localFile, const wxString& remotePath) throw(clException)
{
    if(!m_connected) {
        throw clException("scp is not initialized!");
    }

    if(!localFile.Exists()) {
        throw clException(wxString() << "scp::Write file '" << localFile.GetFullPath() << "' does not exist!");
    }

    wxFFile fp(localFile.GetFullPath(), "rb");
    if(!fp.IsOpened()) {
        throw clException(wxString() << "scp::Write could not open file '" << localFile.GetFullPath() << "'. "
                                     << ::strerror(errno));
    }

    char buffer[4096];
    wxMemoryBuffer memBuffer;
    size_t nbytes(0);
    while(!fp.Eof()) {
        nbytes = fp.Read(buffer, sizeof(buffer));
        if(nbytes == 0) break;
        memBuffer.AppendData(buffer, nbytes);
    }
    fp.Close();
    Write(memBuffer, remotePath);
}
예제 #6
0
void clSFTP::Write(const wxMemoryBuffer& fileContent, const wxString& remotePath) throw(clException)
{
    if(!m_sftp) {
        throw clException("SFTP is not initialized");
    }

    int access_type = O_WRONLY | O_CREAT | O_TRUNC;
    sftp_file file;
    wxString tmpRemoteFile = remotePath;
    tmpRemoteFile << ".codelitesftp";

    file = sftp_open(m_sftp, tmpRemoteFile.mb_str(wxConvUTF8).data(), access_type, 0644);
    if(file == NULL) {
        throw clException(wxString() << _("Can't open file: ") << tmpRemoteFile << ". "
                                     << ssh_get_error(m_ssh->GetSession()),
                          sftp_get_error(m_sftp));
    }

    char* p = (char*)fileContent.GetData();
    const int maxChunkSize = 65536;
    wxInt64 bytesLeft = fileContent.GetDataLen();

    while(bytesLeft > 0) {
        wxInt64 chunkSize = bytesLeft > maxChunkSize ? maxChunkSize : bytesLeft;
        wxInt64 bytesWritten = sftp_write(file, p, chunkSize);
        if(bytesWritten < 0) {
            sftp_close(file);
            throw clException(wxString() << _("Can't write data to file: ") << tmpRemoteFile << ". "
                                         << ssh_get_error(m_ssh->GetSession()),
                              sftp_get_error(m_sftp));
        }
        bytesLeft -= bytesWritten;
        p += bytesWritten;
    }
    sftp_close(file);

    // Unlink the original file if it exists
    bool needUnlink = false;
    {
        // Check if the file exists
        sftp_attributes attr = sftp_stat(m_sftp, remotePath.mb_str(wxConvISO8859_1).data());
        if(attr) {
            needUnlink = true;
            sftp_attributes_free(attr);
        }
    }

    if(needUnlink && sftp_unlink(m_sftp, remotePath.mb_str(wxConvUTF8).data()) < 0) {
        throw clException(wxString() << _("Failed to unlink file: ") << remotePath << ". "
                                     << ssh_get_error(m_ssh->GetSession()),
                          sftp_get_error(m_sftp));
    }

    // Rename the file
    if(sftp_rename(m_sftp, tmpRemoteFile.mb_str(wxConvUTF8).data(), remotePath.mb_str(wxConvUTF8).data()) < 0) {
        throw clException(wxString() << _("Failed to rename file: ") << tmpRemoteFile << " -> " << remotePath << ". "
                                     << ssh_get_error(m_ssh->GetSession()),
                          sftp_get_error(m_sftp));
    }
}
예제 #7
0
파일: cl_ssh.cpp 프로젝트: eranif/codelite
bool clSSH::AuthenticateServer(wxString& message)
{
    int state;
    unsigned char* hash = NULL;
    char* hexa = NULL;

    message.Clear();
    state = ssh_is_server_known(m_session);

#if LIBSSH_VERSION_INT < SSH_VERSION_INT(0, 6, 1)
    int hlen = 0;
    hlen = ssh_get_pubkey_hash(m_session, &hash);
    if(hlen < 0) { throw clException("Unable to obtain server public key!"); }
#else
    size_t hlen = 0;
    ssh_key key = NULL;
    ssh_get_publickey(m_session, &key);
    ssh_get_publickey_hash(key, SSH_PUBLICKEY_HASH_SHA1, &hash, &hlen);
    if(hlen == 0) { throw clException("Unable to obtain server public key!"); }
#endif

    switch(state) {
    case SSH_SERVER_KNOWN_OK:
        free(hash);
        return true;

    case SSH_SERVER_KNOWN_CHANGED:
        hexa = ssh_get_hexa(hash, hlen);
        message << _("Host key for server changed: it is now:\n") << hexa << "\n" << _("Accept server authentication?");
        free(hexa);
        free(hash);
        return false;

    case SSH_SERVER_FOUND_OTHER:
        message << _("The host key for this server was not found but another type of key exists.\n")
                << _("An attacker might change the default server key to confuse your client into thinking the key "
                     "does not exist\n")
                << _("Accept server authentication?");
        free(hash);
        return false;

    case SSH_SERVER_FILE_NOT_FOUND:
        message << _("Could not find known host file.\n")
                << _("If you accept the host key here, the file will be automatically created.\n");
    /* fallback to SSH_SERVER_NOT_KNOWN behavior */
    case SSH_SERVER_NOT_KNOWN:
        hexa = ssh_get_hexa(hash, hlen);
        message << _("The server is unknown. Do you trust the host key?\n") << _("Public key hash: ") << hexa << "\n"
                << _("Accept server authentication?");
        free(hexa);
        free(hash);
        return false;

    default:
    case SSH_SERVER_ERROR:
        throw clException(wxString() << "An error occurred: " << ssh_get_error(m_session));
    }
    return false;
}
예제 #8
0
파일: spline.cpp 프로젝트: hklaufus/GridLab
dMatrix clSpline::GetCoordinates(const dMatrix &uSpec)
{
  dMatrix coord;

  if(uSpec.GetNumberColumns() != 1 || uSpec.GetNumberRows() == 0)
  {
    throw clException("clSpline", "GetCoordinates", "Invalid dimensions of matrix uSpec.");
  }
  else
  {
    coord.SetNumberRows(uSpec.GetNumberRows());
    coord.SetNumberColumns(3);

    if(!initialised)
    {
      Initialise();
    }

    // Do for all specified u's
    for(int i=1; i<=uSpec.GetNumberRows(); i++)
    {
      if(uSpec(i, 1) < 0 || uSpec(i, 1) > 1)
      {
        throw clException("clSpline", "GetCoordinates", "Invalid value for uSpec.");
      }
      else
      {
        // Now find the position of uSpec
        double uu = uSpec(i, 1)*GetSplineLength();

        int j = 1;
        while((uu - u(j+1, 1) > 0) && (j<u.GetNumberRows()-1))
        {
          j++;
        }

        // Now calculate the coefficients
        double A = (u(j+1, 1)-uu)/(u(j+1, 1)-u(j,1));
        double B = 1-A;
        double C = (A*A*A-A)/6 * (u(j+1, 1)-u(j, 1))*(u(j+1, 1)-u(j, 1));
        double D = (B*B*B-B)/6 * (u(j+1, 1)-u(j, 1))*(u(j+1, 1)-u(j, 1));

        // Finally calculate the coordinates
        coord.SetElement(i, 1, A*X(j, 1) + B*X(j+1, 1) + C*X2(j, 1) + D*X2(j+1, 1));
        coord.SetElement(i, 2, A*Y(j, 1) + B*Y(j+1, 1) + C*Y2(j, 1) + D*Y2(j+1, 1));
        coord.SetElement(i, 3, A*Z(j, 1) + B*Z(j+1, 1) + C*Z2(j, 1) + D*Z2(j+1, 1));
      }
    }
  }

  return (coord);
}
예제 #9
0
SFTPAttribute::Ptr_t clSFTP::Stat(const wxString& path) throw (clException)
{
    if ( !m_sftp ) {
        throw clException("SFTP is not initialized");
    }

    sftp_attributes attr = sftp_stat(m_sftp, path.mb_str(wxConvISO8859_1).data());
    if ( !attr ) {
        throw clException(wxString() << _("Could not stat: ") << path << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp));
    }
    SFTPAttribute::Ptr_t pattr( new SFTPAttribute(attr) );
    return pattr;
}
예제 #10
0
void clSFTP::CreateDir(const wxString& dirname) throw (clException)
{
    if ( !m_sftp ) {
        throw clException("SFTP is not initialized");
    }

    int rc;
    rc = sftp_mkdir(m_sftp, dirname.mb_str(wxConvISO8859_1).data(), S_IRWXU);

    if ( rc != SSH_OK ) {
        throw clException(wxString() << _("Failed to create directory: ") << dirname << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp));
    }
}
예제 #11
0
void clSSHChannel::Execute(const wxString& command, wxEvtHandler* sink)
{
    // Sanity
    if(m_readerThread) { throw clException("Channel is busy"); }
    if(!IsOpen()) { throw clException("Channel is not opened"); }
    int rc = ssh_channel_request_exec(m_channel, command.mb_str(wxConvUTF8).data());
    if(rc != SSH_OK) {
        Close();
        throw clException(BuildError("Execute failed"));
    }
    m_readerThread = new clSSHChannelReader(sink, m_channel);
    m_readerThread->Start();
}
예제 #12
0
void clSFTP::UnlinkFile(const wxString& path) throw (clException)
{
    if ( !m_sftp ) {
        throw clException("SFTP is not initialized");
    }

    int rc;
    rc = sftp_unlink(m_sftp,
                     path.mb_str(wxConvISO8859_1).data());

    if ( rc != SSH_OK ) {
        throw clException(wxString() << _("Failed to unlink path: ") << path << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp));
    }
}
예제 #13
0
void clSSHChannel::Open()
{
    if(IsOpen()) { return; }
    if(!m_ssh) { throw clException("ssh session is not opened"); }
    m_channel = ssh_channel_new(m_ssh->GetSession());
    if(!m_channel) { throw clException(BuildError("Failed to allocte ssh channel")); }

    int rc = ssh_channel_open_session(m_channel);
    if(rc != SSH_OK) {
        ssh_channel_free(m_channel);
        m_channel = NULL;
        throw clException(BuildError("Failed to open ssh channel"));
    }
}
예제 #14
0
void clSFTP::Rename(const wxString& oldpath, const wxString& newpath) throw(clException)
{
    if(!m_sftp) {
        throw clException("SFTP is not initialized");
    }

    int rc;
    rc = sftp_rename(m_sftp, oldpath.mb_str(wxConvISO8859_1).data(), newpath.mb_str(wxConvISO8859_1).data());

    if(rc != SSH_OK) {
        throw clException(wxString() << _("Failed to rename path. ") << ssh_get_error(m_ssh->GetSession()),
                          sftp_get_error(m_sftp));
    }
}
예제 #15
0
파일: cl_ssh.cpp 프로젝트: eranif/codelite
void clSSH::ExecuteShellCommand(wxEvtHandler* owner, const wxString& command)
{
    DoOpenChannel();

    m_owner = owner;
    if(!m_owner) { throw clException(wxString() << "No owner specified for output"); }

    wxCharBuffer buffer = command.mb_str(wxConvUTF8);
    int rc = ssh_channel_write(m_channel, buffer.data(), buffer.length());
    if(rc != (int)buffer.length()) { throw clException("SSH Socket error"); }

    // Start a timer to check for the output on 10ms intervals
    if(!m_timer->IsRunning()) { m_timer->Start(50); }
}
예제 #16
0
SFTPAttribute::List_t clSFTP::List(const wxString& folder, size_t flags, const wxString& filter) throw(clException)
{
    sftp_dir dir;
    sftp_attributes attributes;

    if(!m_sftp) {
        throw clException("SFTP is not initialized");
    }

    dir = sftp_opendir(m_sftp, folder.mb_str(wxConvUTF8).data());
    if(!dir) {
        throw clException(wxString() << _("Failed to list directory: ") << folder << ". "
                                     << ssh_get_error(m_ssh->GetSession()),
                          sftp_get_error(m_sftp));
    }

    // Keep the current folder name
    m_currentFolder = dir->name;

    // Ensure the directory is closed
    SFTPDirCloser dc(dir);
    SFTPAttribute::List_t files;

    attributes = sftp_readdir(m_sftp, dir);
    while(attributes) {

        SFTPAttribute::Ptr_t attr(new SFTPAttribute(attributes));
        attributes = sftp_readdir(m_sftp, dir);

        // Don't show files ?
        if(!(flags & SFTP_BROWSE_FILES) && !attr->IsFolder()) {
            continue;

        } else if((flags & SFTP_BROWSE_FILES) && !attr->IsFolder() // show files
                  &&
                  filter.IsEmpty()) { // no filter is given
            files.push_back(attr);

        } else if((flags & SFTP_BROWSE_FILES) && !attr->IsFolder() // show files
                  &&
                  !::wxMatchWild(filter, attr->GetName())) { // but the file does not match the filter
            continue;

        } else {
            files.push_back(attr);
        }
    }
    files.sort(SFTPAttribute::Compare);
    return files;
}
예제 #17
0
void clSFTP::Initialize() throw(clException)
{
    if(m_sftp) return;

    m_sftp = sftp_new(m_ssh->GetSession());
    if(m_sftp == NULL) {
        throw clException(wxString() << "Error allocating SFTP session: " << ssh_get_error(m_ssh->GetSession()));
    }

    int rc = sftp_init(m_sftp);
    if(rc != SSH_OK) {
        throw clException(wxString() << "Error initializing SFTP session: " << ssh_get_error(m_ssh->GetSession()),
                          sftp_get_error(m_sftp));
    }
    m_connected = true;
}
예제 #18
0
void clSSH::AcceptServerAuthentication() throw(clException)
{
    if(!m_session) {
        throw clException("NULL SSH session");
    }
    ssh_write_knownhost(m_session);
}
예제 #19
0
void clSFTP::Read(const wxString& remotePath, wxMemoryBuffer& buffer) throw(clException)
{
    if(!m_sftp) {
        throw clException("SFTP is not initialized");
    }

    sftp_file file = sftp_open(m_sftp, remotePath.mb_str(wxConvUTF8).data(), O_RDONLY, 0);
    if(file == NULL) {
        throw clException(wxString() << _("Failed to open remote file: ") << remotePath << ". "
                                     << ssh_get_error(m_ssh->GetSession()),
                          sftp_get_error(m_sftp));
    }

    SFTPAttribute::Ptr_t fileAttr = Stat(remotePath);
    if(!fileAttr) {
        throw clException(wxString() << _("Could not stat file:") << remotePath << ". "
                                     << ssh_get_error(m_ssh->GetSession()),
                          sftp_get_error(m_sftp));
    }
    wxInt64 fileSize = fileAttr->GetSize();
    if(fileSize == 0) return;

    // Allocate buffer for the file content
    char pBuffer[65536]; // buffer

    // Read the entire file content
    wxInt64 bytesLeft = fileSize;
    wxInt64 bytesRead = 0;
    while(bytesLeft > 0) {
        wxInt64 nbytes = sftp_read(file, pBuffer, sizeof(pBuffer));
        bytesRead += nbytes;
        bytesLeft -= nbytes;
        buffer.AppendData(pBuffer, nbytes);
    }

    if(bytesRead != fileSize) {
        sftp_close(file);
        buffer.Clear();
        throw clException(wxString() << _("Could not read file:") << remotePath << ". "
                                     << ssh_get_error(m_ssh->GetSession()),
                          sftp_get_error(m_sftp));
    }
    sftp_close(file);
}
예제 #20
0
파일: cl_ssh.cpp 프로젝트: eranif/codelite
void clSSH::DoConnectWithRetries(int retries)
{
    while(retries) {
        int rc = ssh_connect(m_session);
        if(rc == SSH_AGAIN) {
            if(wxThread::IsMain()) { ::wxSafeYield(); }
            wxThread::Sleep(10);
            --retries;
            continue;
        }
        if(rc == SSH_OK) {
            m_connected = true;
            return;
        } else {
            throw clException(ssh_get_error(m_session));
        }
    }
    throw clException("Connect timeout");
}
예제 #21
0
void clSFTP::Write(const wxFileName& localFile, const wxString& remotePath) throw (clException)
{
    if ( !m_connected ) {
        throw clException("scp is not initialized!");
    }

    if ( !localFile.Exists() ) {
        throw clException(wxString() << "scp::Write file '" << localFile.GetFullPath() << "' does not exist!");
    }

    wxFFile fp(localFile.GetFullPath(), "rb");
    if ( !fp.IsOpened() ) {
        throw clException(wxString() << "scp::Write could not open file '" << localFile.GetFullPath() << "'. " << ::strerror(errno) );
    }

    wxString fileContent;
    fp.ReadAll(&fileContent);

    Write(fileContent, remotePath);
}
예제 #22
0
void clSFTP::Write(const wxString& fileContent, const wxString& remotePath) throw (clException)
{
    if ( !m_sftp ) {
        throw clException("SFTP is not initialized");
    }

    int access_type = O_WRONLY | O_CREAT | O_TRUNC;
    sftp_file file;
    std::string str = fileContent.mb_str(wxConvUTF8).data();

    file = sftp_open(m_sftp, remotePath.mb_str(wxConvUTF8).data(), access_type, 0644);
    if (file == NULL) {
        throw clException(wxString() << _("Can't open file: ") << remotePath << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp));
    }

    size_t nbytes = sftp_write(file, str.c_str(), str.length());
    if (nbytes != str.length()) {
        sftp_close(file);
        throw clException(wxString() << _("Can't write data to file: ") << remotePath << ". " << ssh_get_error(m_ssh->GetSession()), sftp_get_error(m_sftp));
    }

    sftp_close(file);
}
예제 #23
0
파일: spline.cpp 프로젝트: hklaufus/GridLab
void clSpline::SetControlPoints(const dMatrix &cPointsX, const dMatrix &cPointsY, const dMatrix &cPointsZ)
{
  // Check if dimensions are correct
  if((cPointsX.GetNumberColumns() != 1 || cPointsY.GetNumberColumns() != 1 || cPointsZ.GetNumberColumns() != 1) ||
     (cPointsX.GetNumberRows() != cPointsY.GetNumberRows()) ||
     (cPointsX.GetNumberRows() != cPointsZ.GetNumberRows()))
  {
    throw clException("clSpline", "SetControlPoints", "Dimensions of matrices do not match.");
  }
  else
  {
    X = cPointsX;
    Y = cPointsY;
    Z = cPointsZ;
  }
}
예제 #24
0
파일: cl_ssh.cpp 프로젝트: eranif/codelite
void clSSH::Connect(int seconds)
{
    m_session = ssh_new();
    if(!m_session) { throw clException("ssh_new failed!"); }

    ssh_set_blocking(m_session, 0);
    int verbosity = SSH_LOG_NOLOG;
    ssh_options_set(m_session, SSH_OPTIONS_HOST, m_host.mb_str(wxConvUTF8).data());
    ssh_options_set(m_session, SSH_OPTIONS_LOG_VERBOSITY, &verbosity);
    ssh_options_set(m_session, SSH_OPTIONS_PORT, &m_port);
    ssh_options_set(m_session, SSH_OPTIONS_USER, GetUsername().mb_str().data());

    // Connect the session
    int retries = seconds * 100;
    if(retries < 0) { retries = 1; }
    DoConnectWithRetries(retries);
    ssh_set_blocking(m_session, 1);
}
예제 #25
0
파일: spline.cpp 프로젝트: hklaufus/GridLab
void clSpline::SetControlPoints(const dMatrix &cPoints)
{
  // Check if matrix is in correct format.
  //   3 columns; 1 = x; 2 = y; 3 = z
  //   Number of rows is number of control points
  if(cPoints.GetNumberColumns() != 3)
  {
    throw clException("clSpline", "SetControlPoints", "Incorrect number of columns.");
  }
  else
  {
    int rmax = cPoints.GetNumberColumns();
    X.SetNumberRows(rmax); X.SetNumberColumns(1);
    Y.SetNumberRows(rmax); Y.SetNumberColumns(1);
    Z.SetNumberRows(rmax); Z.SetNumberColumns(1);

    for(int i=1; i<=rmax; i++)
    {
      X.SetElement(i, 1, cPoints(i, 1));
      Y.SetElement(i, 1, cPoints(i, 2));
      Z.SetElement(i, 1, cPoints(i, 3));
    }
  }
}
예제 #26
0
파일: spline.cpp 프로젝트: hklaufus/GridLab
void clSpline::SecondDerivatives(void)
{
  // Get maximum number of rows
  int rmax = u.GetNumberRows();

  // Check for minimum size matrix
  if(rmax<3)
  {
    throw clException("clSpline", "SecondDerivatives", "Need at least 3 points to create spline.");
  }

  // Set up matrices
  dMatrix tri(rmax-2, 3);

  dMatrix SX(rmax-2, 1);
  dMatrix SY(rmax-2, 1);
  dMatrix SZ(rmax-2, 1);

  // Set up all coefficients
  for(int i=2; i<rmax; i++)
  {
    double alpha = u(i, 1)-u(i-1, 1)       + PRECISION;
    double beta  = 2*(u(i+1, 1)-u(i-1, 1)) + PRECISION;
    double gamma = u(i+1, 1)-u(i, 1)       + PRECISION;

    int j=i-1;
    tri.SetElement(j, 1, alpha);
    tri.SetElement(j, 2, beta);
    tri.SetElement(j, 3, gamma);

    SX.SetElement(j, 1, 6*((X(i+1, 1) - X(i  , 1))/gamma - (X(i  , 1) - X(i-1, 1))/alpha) + PRECISION);
    SY.SetElement(j, 1, 6*((Y(i+1, 1) - Y(i  , 1))/gamma - (Y(i  , 1) - Y(i-1, 1))/alpha) + PRECISION);
    SZ.SetElement(j, 1, 6*((Z(i+1, 1) - Z(i  , 1))/gamma - (Z(i  , 1) - Z(i-1, 1))/alpha) + PRECISION);
  }

  // Calculate the second derivatives
  tri.SolveTri(SX);
  tri.SolveTri(SY);
  tri.SolveTri(SZ);

  // Substitute in appropiate vectors
  X2.SetNumberRows(rmax); X2.SetNumberColumns(1);
  Y2.SetNumberRows(rmax); Y2.SetNumberColumns(1);
  Z2.SetNumberRows(rmax); Z2.SetNumberColumns(1);

  {
    for(int i=1; i<=rmax; i++)
    {
      if(i==1 || i==rmax)
      {
        X2.SetElement(i, 1, (double)(0));
        Y2.SetElement(i, 1, (double)(0));
        Z2.SetElement(i, 1, (double)(0));
      }
      else
      {
        X2.SetElement(i, 1, SX(i-1, 1));
        Y2.SetElement(i, 1, SY(i-1, 1));
        Z2.SetElement(i, 1, SZ(i-1, 1));
      }
    }
  }
}