summaryrefslogtreecommitdiffstats
path: root/fitsy/socketgz.C
blob: 56dc4daf4adffff23c22ab18be71b2696b10b2e3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright (C) 1999-2018
// Smithsonian Astrophysical Observatory, Cambridge, MA, USA
// For conditions of distribution and use, see copyright notice in "copyright"

#include "socketgz.h"
#include "util.h"

#ifndef __WIN32

#include <sys/types.h>
#include <sys/socket.h>

#define ASCII_FLAG   0x01 /* bit 0 set: file probably ascii text */
#define HEAD_CRC     0x02 /* bit 1 set: header CRC present */
#define EXTRA_FIELD  0x04 /* bit 2 set: extra field present */
#define ORIG_NAME    0x08 /* bit 3 set: original file name present */
#define COMMENT      0x10 /* bit 4 set: file comment present */
#define RESERVED     0xE0 /* bits 5..7: reserved */

FitsSocketGZ::FitsSocketGZ(int s, const char* ext) 
{
  parse(ext);
  if (!valid_)
    return;

  // reset
  valid_ =0;

  if (!s)
    return;

  stream_ = new gzStream_;
  stream_->id = s;
  stream_->transparent = 0;
  memset(stream_->header,'\0',2);
  stream_->useHeader = 0;
  stream_->buf = new unsigned char[B4KB];

  // magic bytes
  if (recv(stream_->id , stream_->header, 2, 0) != 2) {
    internalError("Fitsy++ socketgz can't read magic bytes in header");
    return;
  }

  if (stream_->header[0] != 0x1f || stream_->header[1] != 0x8b) {
    stream_->transparent = 1;
    stream_->useHeader = 1;
  }
  else {
    ((z_stream*)stream_)->next_in = NULL;
    ((z_stream*)stream_)->avail_in = 0;
    ((z_stream*)stream_)->zalloc = NULL;
    ((z_stream*)stream_)->zfree = NULL;
    ((z_stream*)stream_)->opaque = NULL;

    if (inflateInit2((z_stream*)stream_, -MAX_WBITS) != Z_OK) {
      internalError("Fitsy++ socketgz inflateInit error");
      return;
    }

    unsigned char buf[128];

    // method/flags
    if (recv(stream_->id , buf, 2, 0) != 2) {
      internalError("Fitsy++ socketgz can't read method/flags bytes in header");
      return;
    }
    int method = buf[0];
    int flags = buf[1];

    if (method != Z_DEFLATED || (flags & RESERVED) != 0) {
      internalError("Fitsy++ socketgz bad method/flags");
      return;
    }

    // Discard time, xflags and OS code
    if (recv(stream_->id , buf, 6, 0) != 6) {
      internalError("Fitsy++ socketgz can't read time/xflags/os bytes in header");
      return;
    }

    // skip the extra field
    if ((flags & EXTRA_FIELD) != 0) {
      if (recv(stream_->id , buf, 2, 0) != 2) {
	internalError("Fitsy++ socketgz can't read extra field length bytes in header");
	return;
      }

      int len  =  buf[0];
      len += buf[1]<<8;

      if (recv(stream_->id , buf, len, 0) != len) {
	internalError("Fitsy++ socketgz can't read extra field bytes in header");
	return;
      }
    }

    // skip the original file name
    if ((flags & ORIG_NAME) != 0) { 
      while (recv(stream_->id , buf, 1, 0) == 1 && buf[0] != 0) ;
    }

    // skip the .gz file comment
    if ((flags & COMMENT) != 0) {
      while (recv(stream_->id , buf, 1, 0) == 1 && buf[0] != 0) ;
    }

    // skip the header crc
    if ((flags & HEAD_CRC) != 0) {
      if (recv(stream_->id , buf, 2, 0) != 2) {
	internalError("Fitsy++ socketgz can't read header crc bytes in header");
	return;
      }
    }
  }

  if (DebugGZ)
    cerr << "inflateInt Complete" << endl;

  // so far, so good
  valid_ = 1;
}

FitsSocketGZ::~FitsSocketGZ() 
{
  if (stream_->buf)
    delete [] stream_->buf;
  if (stream_)
    delete stream_;
  stream_ = NULL;
}

#else

FitsSocketGZ::FitsSocketGZ(int s, const char* ext)
{
  valid_ =0;
}

FitsSocketGZ::~FitsSocketGZ() {}

#endif