Index: fish.h
===================================================================
--- fish.h	(revision 889193)
+++ fish.h	(working copy)
@@ -19,6 +19,7 @@
 #include <kurl.h>
 #include <kio/global.h>
 #include <kio/slavebase.h>
+#include <kprocess.h>
 #include <kio/authinfo.h>
 #include <time.h>
 
@@ -81,7 +82,11 @@
   /** fd for reading and writing to the process */
   int childFd;
   /** buffer for data to be written */
+#ifndef Q_WS_WIN
   const char *outBuf;
+#else
+  QByteArray outBuf;
+#endif
   /** current write position in buffer */
   KIO::fileoffset_t outBufPos;
   /** length of buffer */
@@ -179,7 +184,11 @@
   int fishCodeLen;
 protected: // Protected methods
   /** manages initial communication setup including password queries */
+#ifndef Q_WS_WIN
   int establishConnection(char *buffer, KIO::fileoffset_t buflen);
+#else
+  int establishConnection(const QByteArray &buffer);
+#endif
   int received(const char *buffer, KIO::fileoffset_t buflen);
   void sent();
   /** builds each FISH request and sets the error counter */
@@ -193,7 +202,11 @@
   /** creates the subprocess */
   bool connectionStart();
   /** writes one chunk of data to stdin of child process */
+#ifndef Q_WS_WIN
   void writeChild(const char *buf, KIO::fileoffset_t len);
+#else
+  void writeChild(const QByteArray &buf, KIO::fileoffset_t len);
+#endif
   /** parses response from server and acts accordingly */
   void manageConnection(const QString &line);
   /** writes to process */
Index: generate_fishcode.py
===================================================================
--- generate_fishcode.py	(revision 0)
+++ generate_fishcode.py	(revision 0)
@@ -0,0 +1,37 @@
+#1 is generate_fishcode.py
+#2 is md5sum
+#3 is the output file
+#4 are the parameters for cut 
+import sys
+import re
+import hashlib
+
+fp = open(sys.argv[1], "rb")
+r = fp.read()
+fp.close()
+
+m = hashlib.md5()
+m.update(r)
+sm = m.hexdigest()
+
+fp = open(sys.argv[1], "r")
+r = fp.read()
+fp.close()
+
+fp = open(sys.argv[3], "wb")
+fp.write('#define CHECKSUM "%s"\n' % sm)
+fp.write('static const char *fishCode(\n')
+
+r = re.sub(r'\\', r'\\\\', r)
+r = re.sub(r'"', r'\\"', r)
+p = re.compile('^[ 	]*', re.M)
+r = p.sub('"', r)
+p = re.compile(r'^"# .*\n*', re.M)
+r = p.sub('', r)
+p = re.compile('[ 	]*$', re.M)
+r = p.sub(r'\\n"', r)
+p = re.compile(r'^"\\n"\n?', re.M)
+r = p.sub('', r)
+r = re.sub(r'{CHECKSUM}', sm, r, 1)
+fp.write(r + ");\n")
+fp.close()
Index: fish.cpp
===================================================================
--- fish.cpp	(revision 889193)
+++ fish.cpp	(working copy)
@@ -108,13 +108,23 @@
 #define sendmimeType(x) mimeType(x)
 #endif
 
+#ifdef Q_WS_WIN
+#define ENDLINE "\r\n"
+#else
+#define ENDLINE '\n'
+#endif
+
 static char *sshPath = NULL;
 static char *suPath = NULL;
 // disabled: currently not needed. Didn't work reliably.
 // static int isOpenSSH = 0;
 
 /** the SSH process used to communicate with the remote end */
+#ifndef Q_WS_WIN
 static pid_t childPid;
+#else
+static KProcess *childPid = 0;
+#endif
 
 #define E(x) ((const char*)remoteEncoding()->encode(x).data())
 
@@ -231,7 +241,11 @@
     if (sshPath == NULL) {
         // disabled: currently not needed. Didn't work reliably.
         // isOpenSSH = !system("ssh -V 2>&1 | grep OpenSSH > /dev/null");
+#ifdef Q_WS_WIN
+        sshPath = strdup(QFile::encodeName(KStandardDirs::findExe("plink")));
+#else
         sshPath = strdup(QFile::encodeName(KStandardDirs::findExe("ssh")));
+#endif
     }
     if (suPath == NULL) {
         suPath = strdup(QFile::encodeName(KStandardDirs::findExe("su")));
@@ -297,8 +311,8 @@
     };
     myDebug( << "subprocess is running" << endl);
 }
-
 // XXX Use KPty! XXX
+#ifndef Q_WS_WIN
 static int open_pty_pair(int fd[2])
 {
 #if defined(HAVE_TERMIOS_H) && defined(HAVE_GRANTPT) && !defined(HAVE_OPENPTY)
@@ -364,6 +378,7 @@
 #endif
 #endif
 }
+#endif
 /**
 creates the subprocess
 */
@@ -372,14 +387,52 @@
     int rc, flags;
     thisFn.clear();
 
+#ifndef Q_WS_WIN
     rc = open_pty_pair(fd);
     if (rc == -1) {
         myDebug( << "socketpair failed, error: " << strerror(errno) << endl);
         return true;
     }
+#endif
 
     if (!requestNetwork()) return true;
     myDebug( << "Exec: " << (local ? suPath : sshPath) << " Port: " << connectionPort << " User: " << connectionUser << endl);
+#ifdef Q_WS_WIN
+    childPid = new KProcess();
+    childPid->setOutputChannelMode(KProcess::MergedChannels);
+    QStringList common_args;
+    common_args << "-l" << connectionUser.toLatin1().constData() << "-x" << connectionHost.toLatin1().constData();
+    common_args << "echo;echo FISH:;exec /bin/sh -c \"if env true 2>/dev/null; then env PS1= PS2= TZ=UTC LANG=C LC_ALL=C LOCALE=C /bin/sh; else PS1= PS2= TZ=UTC LANG=C LC_ALL=C LOCALE=C /bin/sh; fi\"";
+
+    childPid->setProgram(sshPath, common_args);
+    childPid->start();
+    
+    QByteArray buf;
+    int offset = 0;
+    while (!isLoggedIn) {
+        if (outBuf.size()) {
+            rc = childPid->write(outBuf);
+            outBuf.clear();
+        }
+        else rc = 0;
+
+        if(rc < 0) {
+            myDebug( << "write failed, rc: " << rc);
+            outBufPos = -1;
+            //return true;
+        }
+
+        if (childPid->waitForReadyRead(1000)) {
+            QByteArray buf2 = childPid->readAll();
+            buf += buf2;
+
+            int noff = establishConnection(buf);
+            if (noff < 0) return false;
+            if (noff > 0) buf = buf.mid(/*offset+*/noff);
+//             offset = noff;
+        }
+    }
+#else
     childPid = fork();
     if (childPid == -1) {
         myDebug( << "fork failed, error: " << strerror(errno) << endl);
@@ -498,14 +551,20 @@
             }
         }
     }
+#endif
     return false;
 }
 
 /**
 writes one chunk of data to stdin of child process
 */
+#ifndef Q_WS_WIN
 void fishProtocol::writeChild(const char *buf, KIO::fileoffset_t len) {
     if (outBufPos >= 0 && outBuf) {
+#else
+void fishProtocol::writeChild(const QByteArray &buf, KIO::fileoffset_t len) {
+    if (outBufPos >= 0 && outBuf.size()) {
+#endif
 #if 0
         QString debug;
         debug.setLatin1(outBuf,outBufLen);
@@ -521,8 +580,13 @@
 /**
 manages initial communication setup including password queries
 */
+#ifndef Q_WS_WIN
 int fishProtocol::establishConnection(char *buffer, KIO::fileoffset_t len) {
     QString buf = QString::fromLatin1(buffer,len);
+#else
+int fishProtocol::establishConnection(const QByteArray &buffer) {
+    QString buf = buffer;
+#endif
     int pos=0;
     // Strip trailing whitespace
     while (buf.length() && (buf[buf.length()-1] == ' '))
@@ -561,7 +625,7 @@
                 return -1;
             } else if (!connectionPassword.isEmpty()) {
                 myDebug( << "sending cpass" << endl);
-                connectionAuth.password = connectionPassword+'\n';
+                connectionAuth.password = connectionPassword+ENDLINE;
                 connectionPassword.clear();
                 // su does not like receiving a password directly after sending
                 // the password prompt so we wait a while.
@@ -584,7 +648,7 @@
                     }
                 }
                 firstLogin = false;
-                connectionAuth.password += '\n';
+                connectionAuth.password += ENDLINE;
                 if (connectionAuth.username != connectionUser) {
                     KUrl dest = url;
                     dest.setUser(connectionAuth.username);
@@ -605,6 +669,10 @@
                 writeChild(connectionAuth.password.toLatin1(),connectionAuth.password.length());
             }
             thisFn.clear();
+#ifdef Q_WS_WIN
+            return buf.length();
+        }
+#else
             return 0;
         } else if (buf.endsWith('?')) {
             int rc = messageBox(QuestionYesNo,thisFn+buf);
@@ -615,9 +683,23 @@
             }
             thisFn.clear();
             return 0;
-        } else {
+        }
+#endif
+        else {
             myDebug( << "unmatched case in initial handling! should not happen!" << endl);
-          }
+        }
+#ifdef Q_WS_WIN
+        if (buf.endsWith("(y/n)")) {
+            int rc = messageBox(QuestionYesNo,thisFn+buf);
+            if (rc == KMessageBox::Yes) {
+                writeChild("y\n",2);
+            } else {
+                writeChild("n\n",2);
+            }
+            thisFn.clear();
+            return 0;
+        }
+#endif
     }
     return buf.length();
 }
@@ -672,11 +754,17 @@
  */
 void fishProtocol::shutdownConnection(bool forced){
     if (childPid) {
+#ifdef Q_WS_WIN
+        childPid->terminate();
+#else
         int killStatus = kill(childPid,SIGTERM); // We may not have permission...
         if (killStatus == 0) waitpid(childPid, 0, 0);
+#endif
         childPid = 0;
+#ifndef Q_WS_WIN
         ::close(childFd); // ...in which case this should do the trick
         childFd = -1;
+#endif
         if (!forced)
         {
            dropNetwork();
@@ -1330,11 +1418,14 @@
         int rc;
         isRunning = true;
         finished();
+#ifndef Q_WS_WIN
         fd_set rfds, wfds;
         FD_ZERO(&rfds);
+#endif
         char buf[32768];
         int offset = 0;
         while (isRunning) {
+#ifndef Q_WS_WIN
             FD_SET(childFd,&rfds);
             FD_ZERO(&wfds);
             if (outBufPos >= 0) FD_SET(childFd,&wfds);
@@ -1351,18 +1442,31 @@
                 return;
             }
             if (FD_ISSET(childFd,&wfds) && outBufPos >= 0) {
+#else
+            if (outBufPos >= 0) {
+#endif
 #if 0
                 QString debug;
                 debug.setLatin1(outBuf+outBufPos,outBufLen-outBufPos);
                 myDebug( << "now writing " << (outBufLen-outBufPos) << " " << debug.left(40) << "..." << endl);
 #endif
+#ifndef Q_WS_WIN
                 if (outBufLen-outBufPos > 0) rc = ::write(childFd,outBuf+outBufPos,outBufLen-outBufPos);
+#else
+                if (outBufLen-outBufPos > 0) {
+                    rc = childPid->write(outBuf);
+                }
+#endif
                 else rc = 0;
                 if (rc >= 0) outBufPos += rc;
                 else {
+#ifndef Q_WS_WIN
                     if (errno == EINTR)
                         continue;
                     myDebug( << "write failed, rc: " << rc << ", error: " << strerror(errno) << endl);
+#else
+                    myDebug( << "write failed, rc: " << rc);
+#endif
                     error(ERR_CONNECTION_BROKEN,connectionHost);
                     shutdownConnection();
                     return;
@@ -1373,8 +1477,13 @@
                     sent();
                 }
             }
+#ifndef Q_WS_WIN
             if (FD_ISSET(childFd,&rfds)) {
                 rc = ::read(childFd,buf+offset,32768-offset);
+#else
+            if (childPid->waitForReadyRead(1000)) {
+                rc = childPid->read(buf+offset,32768-offset);
+#endif
                 //myDebug( << "read " << rc << " bytes" << endl);
                 if (rc > 0) {
                     int noff = received(buf,rc+offset);
@@ -1382,9 +1491,13 @@
                     //myDebug( << "left " << noff << " bytes: " << QString::fromLatin1(buf,offset) << endl);
                     offset = noff;
                 } else {
+#ifndef Q_WS_WIN
                     if (errno == EINTR)
                         continue;
                     myDebug( << "read failed, rc: " << rc << ", error: " << strerror(errno) << endl);
+#else
+                    myDebug( << "read failed, rc: " << rc );
+#endif
                     error(ERR_CONNECTION_BROKEN,connectionHost);
                     shutdownConnection();
                     return;
Index: CMakeLists.txt
===================================================================
--- CMakeLists.txt	(revision 889193)
+++ CMakeLists.txt	(working copy)
@@ -14,20 +14,26 @@
 configure_file(config-fish.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-fish.h)
 
 ########### next target ###############
-
+if(NOT WIN32)
 # on Linux there is md5sum, on FreeBSD there is md5
 find_program(MD5SUM_EXECUTABLE NAMES md5sum md5 )
+endif(NOT WIN32)
+    
+if (MD5SUM_EXECUTABLE OR WIN32)
 
-if (MD5SUM_EXECUTABLE)
-
    if ("${MD5SUM_EXECUTABLE}" MATCHES "md5sum")
       set(CUT_ARG "-f 1")                            # for md5sum the sum is in the 1st column
    else ("${MD5SUM_EXECUTABLE}" MATCHES "md5sum")
       set(CUT_ARG "-f 4")                            # for md5 the sum is in the 4th column
    endif ("${MD5SUM_EXECUTABLE}" MATCHES "md5sum")
 
+   if (WIN32)
+      set(FISH_GENERATOR "generate_fishcode.py")
+   else (WIN32)
+      set(FISH_GENERATOR "generate_fishcode.sh")
+   endif (WIN32)
    add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/fishcode.h 
-      COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/generate_fishcode.sh ARGS ${CMAKE_CURRENT_SOURCE_DIR}/fish.pl ${MD5SUM_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/fishcode.h "${CUT_ARG}"
+      COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/${FISH_GENERATOR} ARGS ${CMAKE_CURRENT_SOURCE_DIR}/fish.pl ${MD5SUM_EXECUTABLE} ${CMAKE_CURRENT_BINARY_DIR}/fishcode.h "${CUT_ARG}"
       DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/fish.pl )
 
    set(kio_fish_PART_SRCS fish.cpp ${CMAKE_CURRENT_BINARY_DIR}/fishcode.h)
@@ -47,4 +53,4 @@
 
    install( FILES fish.protocol  DESTINATION  ${SERVICES_INSTALL_DIR} )
 
-endif (MD5SUM_EXECUTABLE)
+endif (MD5SUM_EXECUTABLE OR WIN32)
