作者 陈志颖

refactor:增加合伙人编号

正在显示 37 个修改的文件 包含 1645 行增加1662 行删除
1 appname = partnermg 1 appname = partnermg
2 runmode = "${RUN_MODE||dev}" 2 runmode = "${RUN_MODE||dev}"
3 -httpport = "${HTTP_PORT||8082}" 3 +httpport = "${HTTP_PORT||8083}"
4 4
5 #开启监控 5 #开启监控
6 EnableAdmin = false 6 EnableAdmin = false
@@ -4,7 +4,6 @@ go 1.14 @@ -4,7 +4,6 @@ go 1.14
4 4
5 require ( 5 require (
6 github.com/360EntSecGroup-Skylar/excelize/v2 v2.3.1 6 github.com/360EntSecGroup-Skylar/excelize/v2 v2.3.1
7 - github.com/GeeTeam/gt3-golang-sdk v0.0.0-20200116043922-446ca8a507d2  
8 github.com/Shopify/sarama v1.23.1 7 github.com/Shopify/sarama v1.23.1
9 github.com/ajg/form v1.5.1 // indirect 8 github.com/ajg/form v1.5.1 // indirect
10 github.com/astaxie/beego v1.12.2 9 github.com/astaxie/beego v1.12.2
@@ -17,7 +17,7 @@ type CreatePartnerInfoCommand struct { @@ -17,7 +17,7 @@ type CreatePartnerInfoCommand struct {
17 // 状态(1:启用或者0:禁用) 17 // 状态(1:启用或者0:禁用)
18 Status int `json:"status"` 18 Status int `json:"status"`
19 // 合伙类别 19 // 合伙类别
20 - PartnerCategory []int64 `json:"partnerCategory,omitempty"` 20 + PartnerCategory []*domain.PartnerCategory `json:"partnerCategory,omitempty"`
21 //合作时间 21 //合作时间
22 CooperateTime time.Time `json:"cooperateTime"` 22 CooperateTime time.Time `json:"cooperateTime"`
23 // 区域 23 // 区域
@@ -26,6 +26,8 @@ type CreatePartnerInfoCommand struct { @@ -26,6 +26,8 @@ type CreatePartnerInfoCommand struct {
26 Salesman []domain.Salesman `json:"salesman,omitempty"` 26 Salesman []domain.Salesman `json:"salesman,omitempty"`
27 //公司id 27 //公司id
28 CompanyId int64 `json:"companyId"` 28 CompanyId int64 `json:"companyId"`
  29 + //备注
  30 + Remark string `json:"remark"`
29 } 31 }
30 32
31 func (command CreatePartnerInfoCommand) ValidateCommand() error { 33 func (command CreatePartnerInfoCommand) ValidateCommand() error {
  1 +/**
  2 + @author: stevechan
  3 + @date: 2020/12/29
  4 + @note:
  5 +**/
  6 +
  7 +package command
  8 +
  9 +import (
  10 + "gitlab.fjmaimaimai.com/mmm-go/partnermg/pkg/lib"
  11 +)
  12 +
  13 +// 移除合伙人
  14 +type RemovePartnerInfoCommand struct {
  15 + // 合伙人Id
  16 + Id int64 `json:"id" valid:"Required"`
  17 +}
  18 +
  19 +func (command *RemovePartnerInfoCommand) ValidateCommand() error {
  20 + if command.Id == 0 {
  21 + return lib.ThrowError(lib.ARG_ERROR, "合伙人id错误")
  22 + }
  23 + return nil
  24 +}
@@ -13,7 +13,7 @@ type UpdatePartnerInfoCommand struct { @@ -13,7 +13,7 @@ type UpdatePartnerInfoCommand struct {
13 // 状态(1:启用或者0:禁用) 13 // 状态(1:启用或者0:禁用)
14 Status int `json:"status"` 14 Status int `json:"status"`
15 // 合伙类别 (1.研发合伙人 2.业务合伙人 3.事业) 15 // 合伙类别 (1.研发合伙人 2.业务合伙人 3.事业)
16 - PartnerCategory []int64 `json:"partnerCategory,omitempty"` 16 + PartnerCategory []*domain.PartnerCategory `json:"partnerCategory,omitempty"`
17 // 区域 17 // 区域
18 RegionInfo *domain.RegionInfo `json:"regionInfo"` 18 RegionInfo *domain.RegionInfo `json:"regionInfo"`
19 //关联业务员 19 //关联业务员
@@ -22,6 +22,8 @@ type UpdatePartnerInfoCommand struct { @@ -22,6 +22,8 @@ type UpdatePartnerInfoCommand struct {
22 CooperateTime time.Time `json:"cooperateTime"` 22 CooperateTime time.Time `json:"cooperateTime"`
23 //公司id 23 //公司id
24 CompanyId int64 `json:"companyId"` 24 CompanyId int64 `json:"companyId"`
  25 + //备注
  26 + Remark string `json:"remark"`
25 } 27 }
26 28
27 func (command *UpdatePartnerInfoCommand) ValidateCommand() error { 29 func (command *UpdatePartnerInfoCommand) ValidateCommand() error {
@@ -2,12 +2,13 @@ package query @@ -2,12 +2,13 @@ package query
2 2
3 type ListPartnerInfoQuery struct { 3 type ListPartnerInfoQuery struct {
4 // 合伙人类别 4 // 合伙人类别
5 - Partnertype int `json:"partnerType"` 5 + PartnerType int `json:"partnerType"`
6 //所属区域 6 //所属区域
7 RegionInfo string `json:"regionInfo"` 7 RegionInfo string `json:"regionInfo"`
8 // 合伙人姓名 8 // 合伙人姓名
9 PartnerName string `json:"partnerName"` 9 PartnerName string `json:"partnerName"`
10 - CompanyId int64 `json:"companyId"` 10 + // 公司id
  11 + CompanyId int64 `json:"companyId"`
11 // 查询偏离量 12 // 查询偏离量
12 Offset int `json:"offset"` 13 Offset int `json:"offset"`
13 // 查询限制 14 // 查询限制
@@ -15,6 +16,5 @@ type ListPartnerInfoQuery struct { @@ -15,6 +16,5 @@ type ListPartnerInfoQuery struct {
15 } 16 }
16 17
17 func (q *ListPartnerInfoQuery) ValidateQuery() error { 18 func (q *ListPartnerInfoQuery) ValidateQuery() error {
18 -  
19 return nil 19 return nil
20 } 20 }
@@ -21,7 +21,13 @@ func NewPartnerInfoService(options map[string]interface{}) *PartnerInfoService { @@ -21,7 +21,13 @@ func NewPartnerInfoService(options map[string]interface{}) *PartnerInfoService {
21 return newPartnerInfoService 21 return newPartnerInfoService
22 } 22 }
23 23
24 -// CreatePartnerInfo 创建合伙人 24 +/**
  25 + * @Author SteveChan
  26 + * @Description //TODO 创建合伙人,判断编号是否重复
  27 + * @Date 15:42 2020/12/29
  28 + * @Param
  29 + * @return
  30 + **/
25 func (PartnerInfoService *PartnerInfoService) CreatePartnerInfo(cmd *command.CreatePartnerInfoCommand) (data *domain.PartnerInfo, err error) { 31 func (PartnerInfoService *PartnerInfoService) CreatePartnerInfo(cmd *command.CreatePartnerInfoCommand) (data *domain.PartnerInfo, err error) {
26 var ( 32 var (
27 transactionContext, _ = factory.CreateTransactionContext(nil) 33 transactionContext, _ = factory.CreateTransactionContext(nil)
@@ -35,16 +41,17 @@ func (PartnerInfoService *PartnerInfoService) CreatePartnerInfo(cmd *command.Cre @@ -35,16 +41,17 @@ func (PartnerInfoService *PartnerInfoService) CreatePartnerInfo(cmd *command.Cre
35 defer func() { 41 defer func() {
36 transactionContext.RollbackTransaction() 42 transactionContext.RollbackTransaction()
37 }() 43 }()
  44 +
38 //检查账号是否存在 45 //检查账号是否存在
39 var ( 46 var (
40 - partnerinfoDao *dao.PartnerInfoDao 47 + partnerInfoDao *dao.PartnerInfoDao
41 ) 48 )
42 - if partnerinfoDao, err = factory.CreatePartnerInfoDao(map[string]interface{}{ 49 + if partnerInfoDao, err = factory.CreatePartnerInfoDao(map[string]interface{}{
43 "transactionContext": transactionContext, 50 "transactionContext": transactionContext,
44 }); err != nil { 51 }); err != nil {
45 return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error()) 52 return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
46 } 53 }
47 - ok, err := partnerinfoDao.PartnerAccountExist(cmd.Account, cmd.CompanyId) 54 + ok, err := partnerInfoDao.PartnerAccountExist(cmd.Account, cmd.CompanyId)
48 if err != nil { 55 if err != nil {
49 return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error()) 56 return nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
50 } 57 }
@@ -55,7 +62,7 @@ func (PartnerInfoService *PartnerInfoService) CreatePartnerInfo(cmd *command.Cre @@ -55,7 +62,7 @@ func (PartnerInfoService *PartnerInfoService) CreatePartnerInfo(cmd *command.Cre
55 var ( 62 var (
56 partnerInfoRepository domain.PartnerInfoRepository 63 partnerInfoRepository domain.PartnerInfoRepository
57 categoryRepository domain.PartnerCategoryRepository 64 categoryRepository domain.PartnerCategoryRepository
58 - categorys []domain.PartnerCategory 65 + categories []domain.PartnerCategory
59 ) 66 )
60 if partnerInfoRepository, err = factory.CreatePartnerInfoRepository(map[string]interface{}{ 67 if partnerInfoRepository, err = factory.CreatePartnerInfoRepository(map[string]interface{}{
61 "transactionContext": transactionContext, 68 "transactionContext": transactionContext,
@@ -67,13 +74,18 @@ func (PartnerInfoService *PartnerInfoService) CreatePartnerInfo(cmd *command.Cre @@ -67,13 +74,18 @@ func (PartnerInfoService *PartnerInfoService) CreatePartnerInfo(cmd *command.Cre
67 }); err != nil { 74 }); err != nil {
68 return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error()) 75 return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
69 } 76 }
70 - _, categorys, err = categoryRepository.Find(domain.PartnerCategoryFindQuery{  
71 - Ids: cmd.PartnerCategory, 77 + var ids []int64
  78 + for _, partnerCategory := range cmd.PartnerCategory {
  79 + ids = append(ids, partnerCategory.Id)
  80 + }
  81 + _, categories, err = categoryRepository.Find(domain.PartnerCategoryFindQuery{
  82 + Ids: ids,
72 }) 83 })
73 if err != nil { 84 if err != nil {
74 e := fmt.Sprintf("获取合伙人分类数据失败:%s", err) 85 e := fmt.Sprintf("获取合伙人分类数据失败:%s", err)
75 return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e) 86 return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
76 } 87 }
  88 +
77 newPartnerInfo := domain.PartnerInfo{ 89 newPartnerInfo := domain.PartnerInfo{
78 Partner: domain.Partner{ 90 Partner: domain.Partner{
79 Account: cmd.Account, 91 Account: cmd.Account,
@@ -86,7 +98,7 @@ func (PartnerInfoService *PartnerInfoService) CreatePartnerInfo(cmd *command.Cre @@ -86,7 +98,7 @@ func (PartnerInfoService *PartnerInfoService) CreatePartnerInfo(cmd *command.Cre
86 Salesman: cmd.Salesman, 98 Salesman: cmd.Salesman,
87 CooperateTime: cmd.CooperateTime, 99 CooperateTime: cmd.CooperateTime,
88 CompanyId: cmd.CompanyId, 100 CompanyId: cmd.CompanyId,
89 - PartnerCategoryInfos: categorys, 101 + PartnerCategoryInfos: categories,
90 } 102 }
91 if err = partnerInfoRepository.Save(&newPartnerInfo); err != nil { 103 if err = partnerInfoRepository.Save(&newPartnerInfo); err != nil {
92 return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error()) 104 return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
@@ -106,7 +118,13 @@ func (PartnerInfoService *PartnerInfoService) CreatePartnerInfo(cmd *command.Cre @@ -106,7 +118,13 @@ func (PartnerInfoService *PartnerInfoService) CreatePartnerInfo(cmd *command.Cre
106 return &newPartnerInfo, nil 118 return &newPartnerInfo, nil
107 } 119 }
108 120
109 -// GetPartnerInfo 返回合伙人 121 +/**
  122 + * @Author SteveChan
  123 + * @Description //TODO 返回合伙人,增加合伙人编号字段
  124 + * @Date 15:43 2020/12/29
  125 + * @Param
  126 + * @return
  127 + **/
110 func (PartnerInfoService *PartnerInfoService) GetPartnerInfo(q query.GetPartnerInfoQuery) (data *domain.PartnerInfo, err error) { 128 func (PartnerInfoService *PartnerInfoService) GetPartnerInfo(q query.GetPartnerInfoQuery) (data *domain.PartnerInfo, err error) {
111 var ( 129 var (
112 transactionContext, _ = factory.CreateTransactionContext(nil) 130 transactionContext, _ = factory.CreateTransactionContext(nil)
@@ -123,7 +141,7 @@ func (PartnerInfoService *PartnerInfoService) GetPartnerInfo(q query.GetPartnerI @@ -123,7 +141,7 @@ func (PartnerInfoService *PartnerInfoService) GetPartnerInfo(q query.GetPartnerI
123 var ( 141 var (
124 PartnerInfoRepository domain.PartnerInfoRepository 142 PartnerInfoRepository domain.PartnerInfoRepository
125 categoryRepository domain.PartnerCategoryRepository 143 categoryRepository domain.PartnerCategoryRepository
126 - categorys []domain.PartnerCategory 144 + categories []domain.PartnerCategory
127 partnerData *domain.PartnerInfo 145 partnerData *domain.PartnerInfo
128 ) 146 )
129 if PartnerInfoRepository, err = factory.CreatePartnerInfoRepository(map[string]interface{}{ 147 if PartnerInfoRepository, err = factory.CreatePartnerInfoRepository(map[string]interface{}{
@@ -145,19 +163,19 @@ func (PartnerInfoService *PartnerInfoService) GetPartnerInfo(q query.GetPartnerI @@ -145,19 +163,19 @@ func (PartnerInfoService *PartnerInfoService) GetPartnerInfo(q query.GetPartnerI
145 }); err != nil { 163 }); err != nil {
146 return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error()) 164 return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
147 } 165 }
148 - categoryIds := []int64{} 166 + var categoryIds []int64
149 for _, v := range partnerData.PartnerCategoryInfos { 167 for _, v := range partnerData.PartnerCategoryInfos {
150 categoryIds = append(categoryIds, v.Id) 168 categoryIds = append(categoryIds, v.Id)
151 } 169 }
152 if len(categoryIds) > 0 { 170 if len(categoryIds) > 0 {
153 - _, categorys, err = categoryRepository.Find(domain.PartnerCategoryFindQuery{ 171 + _, categories, err = categoryRepository.Find(domain.PartnerCategoryFindQuery{
154 Ids: categoryIds, 172 Ids: categoryIds,
155 }) 173 })
156 if err != nil { 174 if err != nil {
157 return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error()) 175 return nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
158 } 176 }
159 } 177 }
160 - partnerData.PartnerCategoryInfos = categorys 178 + partnerData.PartnerCategoryInfos = categories
161 err = transactionContext.CommitTransaction() 179 err = transactionContext.CommitTransaction()
162 return partnerData, nil 180 return partnerData, nil
163 } 181 }
@@ -191,15 +209,20 @@ func (PartnerInfoService *PartnerInfoService) UpdatePartnerInfo(cmd *command.Upd @@ -191,15 +209,20 @@ func (PartnerInfoService *PartnerInfoService) UpdatePartnerInfo(cmd *command.Upd
191 }); err != nil { 209 }); err != nil {
192 return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error()) 210 return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
193 } 211 }
  212 + var ids []int64
  213 + for _, partnerCategory := range cmd.PartnerCategory {
  214 + ids = append(ids, partnerCategory.Id)
  215 + }
194 _, categorys, err = categoryRepository.Find(domain.PartnerCategoryFindQuery{ 216 _, categorys, err = categoryRepository.Find(domain.PartnerCategoryFindQuery{
195 - Ids: cmd.PartnerCategory, 217 + Ids: ids,
196 }) 218 })
197 if err != nil { 219 if err != nil {
198 e := fmt.Sprintf("获取合伙人分类数据失败:%s", err) 220 e := fmt.Sprintf("获取合伙人分类数据失败:%s", err)
199 return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e) 221 return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
200 } 222 }
201 partnerInfo, err := partnerInfoRepository.FindOne(domain.PartnerFindOneQuery{ 223 partnerInfo, err := partnerInfoRepository.FindOne(domain.PartnerFindOneQuery{
202 - UserId: cmd.Id, CompanyId: cmd.CompanyId, 224 + UserId: cmd.Id,
  225 + CompanyId: cmd.CompanyId,
203 }) 226 })
204 if err != nil { 227 if err != nil {
205 return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error()) 228 return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
@@ -246,14 +269,13 @@ func (PartnerInfoService *PartnerInfoService) ListPartnerInfo(listPartnerInfoQue @@ -246,14 +269,13 @@ func (PartnerInfoService *PartnerInfoService) ListPartnerInfo(listPartnerInfoQue
246 return 0, nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error()) 269 return 0, nil, lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
247 } 270 }
248 defer func() { 271 defer func() {
249 -  
250 transactionContext.RollbackTransaction() 272 transactionContext.RollbackTransaction()
251 -  
252 }() 273 }()
  274 +
253 var ( 275 var (
254 partnerInfoRepository domain.PartnerInfoRepository 276 partnerInfoRepository domain.PartnerInfoRepository
255 categoryRepository domain.PartnerCategoryRepository 277 categoryRepository domain.PartnerCategoryRepository
256 - categorys []domain.PartnerCategory 278 + categories []domain.PartnerCategory
257 ) 279 )
258 if partnerInfoRepository, err = factory.CreatePartnerInfoRepository(map[string]interface{}{ 280 if partnerInfoRepository, err = factory.CreatePartnerInfoRepository(map[string]interface{}{
259 "transactionContext": transactionContext, 281 "transactionContext": transactionContext,
@@ -271,8 +293,8 @@ func (PartnerInfoService *PartnerInfoService) ListPartnerInfo(listPartnerInfoQue @@ -271,8 +293,8 @@ func (PartnerInfoService *PartnerInfoService) ListPartnerInfo(listPartnerInfoQue
271 PartnerName: listPartnerInfoQuery.PartnerName, 293 PartnerName: listPartnerInfoQuery.PartnerName,
272 CompanyId: listPartnerInfoQuery.CompanyId, 294 CompanyId: listPartnerInfoQuery.CompanyId,
273 } 295 }
274 - if listPartnerInfoQuery.Partnertype > 0 {  
275 - queryOption.PartnerCategory = []int{listPartnerInfoQuery.Partnertype} 296 + if listPartnerInfoQuery.PartnerType > 0 {
  297 + queryOption.PartnerCategory = []int{listPartnerInfoQuery.PartnerType}
276 } 298 }
277 // RegionInfo 299 // RegionInfo
278 if len(listPartnerInfoQuery.RegionInfo) > 0 { 300 if len(listPartnerInfoQuery.RegionInfo) > 0 {
@@ -284,18 +306,18 @@ func (PartnerInfoService *PartnerInfoService) ListPartnerInfo(listPartnerInfoQue @@ -284,18 +306,18 @@ func (PartnerInfoService *PartnerInfoService) ListPartnerInfo(listPartnerInfoQue
284 if count, err = partnerInfoRepository.CountAll(queryOption); err != nil { 306 if count, err = partnerInfoRepository.CountAll(queryOption); err != nil {
285 return 0, nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error()) 307 return 0, nil, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
286 } 308 }
287 - _, categorys, err = categoryRepository.Find(domain.PartnerCategoryFindQuery{}) 309 + _, categories, err = categoryRepository.Find(domain.PartnerCategoryFindQuery{})
288 if err != nil { 310 if err != nil {
289 return count, partnerInfos, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error()) 311 return count, partnerInfos, lib.ThrowError(lib.INTERNAL_SERVER_ERROR, err.Error())
290 } 312 }
291 - categorysMap := make(map[int64]domain.PartnerCategory)  
292 - for i := range categorys {  
293 - categorysMap[categorys[i].Id] = categorys[i] 313 + categoriesMap := make(map[int64]domain.PartnerCategory)
  314 + for i := range categories {
  315 + categoriesMap[categories[i].Id] = categories[i]
294 } 316 }
295 for i := range partnerInfos { 317 for i := range partnerInfos {
296 - categoryInPartner := []domain.PartnerCategory{} 318 + var categoryInPartner []domain.PartnerCategory
297 for _, vv := range partnerInfos[i].PartnerCategoryInfos { 319 for _, vv := range partnerInfos[i].PartnerCategoryInfos {
298 - if categoryData, ok := categorysMap[vv.Id]; ok { 320 + if categoryData, ok := categoriesMap[vv.Id]; ok {
299 categoryInPartner = append(categoryInPartner, categoryData) 321 categoryInPartner = append(categoryInPartner, categoryData)
300 } 322 }
301 } 323 }
@@ -307,6 +329,30 @@ func (PartnerInfoService *PartnerInfoService) ListPartnerInfo(listPartnerInfoQue @@ -307,6 +329,30 @@ func (PartnerInfoService *PartnerInfoService) ListPartnerInfo(listPartnerInfoQue
307 return count, partnerInfos, nil 329 return count, partnerInfos, nil
308 } 330 }
309 331
  332 +/**
  333 + * @Author SteveChan
  334 + * @Description //TODO 移除合伙人
  335 + * @Date 16:40 2020/12/29
  336 + * @Param
  337 + * @return
  338 + **/
  339 +func (PartnerInfoService *PartnerInfoService) RemovePartnerInfo(cmd command.RemovePartnerInfoCommand) (err error) {
  340 + var (
  341 + transactionContext, _ = factory.CreateTransactionContext(nil)
  342 + )
  343 + if err = cmd.ValidateCommand(); err != nil {
  344 + return application.ThrowError(application.ARG_ERROR, err.Error())
  345 + }
  346 + if err = transactionContext.StartTransaction(); err != nil {
  347 + return err
  348 + }
  349 + defer func() {
  350 + transactionContext.RollbackTransaction()
  351 + }()
  352 +
  353 + return nil
  354 +}
  355 +
310 func (PartnerInfoService *PartnerInfoService) UpdateStatus(cmd command.StatusPartnerInfoCommand) (err error) { 356 func (PartnerInfoService *PartnerInfoService) UpdateStatus(cmd command.StatusPartnerInfoCommand) (err error) {
311 if len(cmd.Ids) == 0 { 357 if len(cmd.Ids) == 0 {
312 return nil 358 return nil
@@ -324,14 +370,14 @@ func (PartnerInfoService *PartnerInfoService) UpdateStatus(cmd command.StatusPar @@ -324,14 +370,14 @@ func (PartnerInfoService *PartnerInfoService) UpdateStatus(cmd command.StatusPar
324 transactionContext.RollbackTransaction() 370 transactionContext.RollbackTransaction()
325 }() 371 }()
326 var ( 372 var (
327 - partnerinfoDao *dao.PartnerInfoDao 373 + partnerInfoDao *dao.PartnerInfoDao
328 ) 374 )
329 - if partnerinfoDao, err = factory.CreatePartnerInfoDao(map[string]interface{}{ 375 + if partnerInfoDao, err = factory.CreatePartnerInfoDao(map[string]interface{}{
330 "transactionContext": transactionContext, 376 "transactionContext": transactionContext,
331 }); err != nil { 377 }); err != nil {
332 return lib.ThrowError(lib.TRANSACTION_ERROR, err.Error()) 378 return lib.ThrowError(lib.TRANSACTION_ERROR, err.Error())
333 } 379 }
334 - err = partnerinfoDao.UpdatePartnerStatus(cmd.Ids, cmd.CompanyId, cmd.Status) 380 + err = partnerInfoDao.UpdatePartnerStatus(cmd.Ids, cmd.CompanyId, cmd.Status)
335 if err != nil { 381 if err != nil {
336 e := fmt.Sprintf("更新合伙人(id=%v)的数据失败;%s", cmd.Ids, err) 382 e := fmt.Sprintf("更新合伙人(id=%v)的数据失败;%s", cmd.Ids, err)
337 return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e) 383 return lib.ThrowError(lib.INTERNAL_SERVER_ERROR, e)
@@ -8,14 +8,14 @@ var LOG_LEVEL = "debug" @@ -8,14 +8,14 @@ var LOG_LEVEL = "debug"
8 var LOG_File = "./logs/partnermg.log" 8 var LOG_File = "./logs/partnermg.log"
9 9
10 var ( 10 var (
11 - UCENTER_HOST = "https://suplus-ucenter-dev.fjmaimaimai.com" //统一用户中心地址 11 + UCENTER_HOST = "https://suplus-ucenter-test.fjmaimaimai.com" //统一用户中心地址
12 UCENTER_SECRET = "cykbjnfqgctn" 12 UCENTER_SECRET = "cykbjnfqgctn"
13 UCENTER_APP_KEY = "39aefef9e22744a3b2d2d3791824ae7b" 13 UCENTER_APP_KEY = "39aefef9e22744a3b2d2d3791824ae7b"
14 UCENTER_CHECK_ALT = "rsF0pL!6DwjBO735" 14 UCENTER_CHECK_ALT = "rsF0pL!6DwjBO735"
15 ) 15 )
16 16
17 var ( 17 var (
18 - BUSINESS_ADMIN_HOST = "http://suplus-business-admin-dev.fjmaimaimai.com" //企业平台的地址 18 + BUSINESS_ADMIN_HOST = "http://suplus-business-admin-test.fjmaimaimai.com" //企业平台的地址
19 ) 19 )
20 20
21 func init() { 21 func init() {
@@ -34,9 +34,7 @@ func init() { @@ -34,9 +34,7 @@ func init() {
34 if os.Getenv("UCENTER_CHECK_ALT") != "" { 34 if os.Getenv("UCENTER_CHECK_ALT") != "" {
35 UCENTER_CHECK_ALT = os.Getenv("UCENTER_CHECK_ALT") 35 UCENTER_CHECK_ALT = os.Getenv("UCENTER_CHECK_ALT")
36 } 36 }
37 -  
38 if os.Getenv("BUSINESS_ADMIN_HOST") != "" { 37 if os.Getenv("BUSINESS_ADMIN_HOST") != "" {
39 BUSINESS_ADMIN_HOST = os.Getenv("BUSINESS_ADMIN_HOST") 38 BUSINESS_ADMIN_HOST = os.Getenv("BUSINESS_ADMIN_HOST")
40 } 39 }
41 -  
42 } 40 }
@@ -14,7 +14,7 @@ var KafkaCfg KafkaConfig @@ -14,7 +14,7 @@ var KafkaCfg KafkaConfig
14 14
15 func init() { 15 func init() {
16 KafkaCfg = KafkaConfig{ 16 KafkaCfg = KafkaConfig{
17 - Servers: []string{""}, 17 + Servers: []string{"127.0.0.1:9092"},
18 ConsumerId: "partnermg_local", 18 ConsumerId: "partnermg_local",
19 } 19 }
20 if os.Getenv("KAFKA_HOST") != "" { 20 if os.Getenv("KAFKA_HOST") != "" {
@@ -2,7 +2,7 @@ package constant @@ -2,7 +2,7 @@ package constant
2 2
3 import "os" 3 import "os"
4 4
5 -var POSTGRESQL_DB_NAME = "partner_dev" 5 +var POSTGRESQL_DB_NAME = "partner_test"
6 var POSTGRESQL_USER = "postgres" 6 var POSTGRESQL_USER = "postgres"
7 var POSTGRESQL_PASSWORD = "eagle1010" 7 var POSTGRESQL_PASSWORD = "eagle1010"
8 var POSTGRESQL_HOST = "114.55.200.59" 8 var POSTGRESQL_HOST = "114.55.200.59"
@@ -114,7 +114,7 @@ type OrderBase struct { @@ -114,7 +114,7 @@ type OrderBase struct {
114 DataFrom OrderDataFrom `json:"dataFrom"` 114 DataFrom OrderDataFrom `json:"dataFrom"`
115 //备注 115 //备注
116 Remark OrderBaseRemark `json:"remark"` 116 Remark OrderBaseRemark `json:"remark"`
117 - 117 + //合伙人类型
118 PartnerCategory PartnerCategory `json:"partnerCategory"` 118 PartnerCategory PartnerCategory `json:"partnerCategory"`
119 } 119 }
120 120
@@ -6,6 +6,8 @@ type PartnerCategory struct { @@ -6,6 +6,8 @@ type PartnerCategory struct {
6 Id int64 `json:"id"` 6 Id int64 `json:"id"`
7 // 名称 7 // 名称
8 Name string `json:"name,omitempty"` 8 Name string `json:"name,omitempty"`
  9 + // 合伙人编码
  10 + Code string `json:"code"`
9 } 11 }
10 12
11 type PartnerCategoryFindQuery struct { 13 type PartnerCategoryFindQuery struct {
@@ -48,6 +48,8 @@ type PartnerInfo struct { @@ -48,6 +48,8 @@ type PartnerInfo struct {
48 PartnerCategory int `json:"partnerCategory"` 48 PartnerCategory int `json:"partnerCategory"`
49 //公司id 49 //公司id
50 CompanyId int64 `json:"companyId"` 50 CompanyId int64 `json:"companyId"`
  51 + //备注
  52 + Remark string `json:"remark"`
51 } 53 }
52 54
53 func (p *PartnerInfo) IsUsable() bool { 55 func (p *PartnerInfo) IsUsable() bool {
@@ -78,5 +80,6 @@ type PartnerInfoRepository interface { @@ -78,5 +80,6 @@ type PartnerInfoRepository interface {
78 Save(dm *PartnerInfo) error 80 Save(dm *PartnerInfo) error
79 FindOne(queryOptions PartnerFindOneQuery) (*PartnerInfo, error) 81 FindOne(queryOptions PartnerFindOneQuery) (*PartnerInfo, error)
80 Find(queryOptions PartnerFindQuery) ([]PartnerInfo, error) 82 Find(queryOptions PartnerFindQuery) ([]PartnerInfo, error)
  83 + Remove(Id int64) error
81 CountAll(queryOptions PartnerFindQuery) (int, error) 84 CountAll(queryOptions PartnerFindQuery) (int, error)
82 } 85 }
@@ -42,3 +42,14 @@ func (dao PartnerInfoDao) UpdatePartnerStatus(ids []int64, companyId int64, stat @@ -42,3 +42,14 @@ func (dao PartnerInfoDao) UpdatePartnerStatus(ids []int64, companyId int64, stat
42 Update() 42 Update()
43 return err 43 return err
44 } 44 }
  45 +
  46 +/**
  47 + * @Author SteveChan
  48 + * @Description //TODO 编号查重
  49 + * @Date 17:55 2020/12/28
  50 + * @Param
  51 + * @return
  52 + **/
  53 +func (dao PartnerInfoDao) CheckDuplication() {
  54 +
  55 +}
@@ -7,4 +7,6 @@ type PartnerCategoryInfo struct { @@ -7,4 +7,6 @@ type PartnerCategoryInfo struct {
7 Id int64 7 Id int64
8 // 名称 8 // 名称
9 Name string 9 Name string
  10 + // 合伙人编码
  11 + Code string
10 } 12 }
@@ -36,6 +36,8 @@ type PartnerInfo struct { @@ -36,6 +36,8 @@ type PartnerInfo struct {
36 PartnerCategoryInfos []domain.PartnerCategory 36 PartnerCategoryInfos []domain.PartnerCategory
37 //公司id 37 //公司id
38 CompanyId int64 38 CompanyId int64
  39 + //备注
  40 + Remark string
39 } 41 }
40 42
41 var _ pg.BeforeUpdateHook = (*PartnerInfo)(nil) 43 var _ pg.BeforeUpdateHook = (*PartnerInfo)(nil)
@@ -12,21 +12,6 @@ type PartnerCategoryRepository struct { @@ -12,21 +12,6 @@ type PartnerCategoryRepository struct {
12 transactionContext *transaction.TransactionContext 12 transactionContext *transaction.TransactionContext
13 } 13 }
14 14
15 -func (repository PartnerCategoryRepository) transformPgModelToDomainModel(m *models.PartnerCategoryInfo) (domain.PartnerCategory, error) {  
16 - pc := domain.PartnerCategory{  
17 - Id: m.Id,  
18 - Name: m.Name,  
19 - }  
20 - return pc, nil  
21 -}  
22 -  
23 -func NewPartnerCategoryRepository(transactionContext *transaction.TransactionContext) (*PartnerCategoryRepository, error) {  
24 - if transactionContext == nil {  
25 - return nil, fmt.Errorf("transactionContext参数不能为nil")  
26 - }  
27 - return &PartnerCategoryRepository{transactionContext: transactionContext}, nil  
28 -}  
29 -  
30 func (repository PartnerCategoryRepository) Find(queryOptions domain.PartnerCategoryFindQuery) (int, []domain.PartnerCategory, error) { 15 func (repository PartnerCategoryRepository) Find(queryOptions domain.PartnerCategoryFindQuery) (int, []domain.PartnerCategory, error) {
31 tx := repository.transactionContext.PgTx 16 tx := repository.transactionContext.PgTx
32 var ( 17 var (
@@ -48,3 +33,19 @@ func (repository PartnerCategoryRepository) Find(queryOptions domain.PartnerCate @@ -48,3 +33,19 @@ func (repository PartnerCategoryRepository) Find(queryOptions domain.PartnerCate
48 } 33 }
49 return cnt, partnerCategoryInfos, nil 34 return cnt, partnerCategoryInfos, nil
50 } 35 }
  36 +
  37 +func (repository PartnerCategoryRepository) transformPgModelToDomainModel(m *models.PartnerCategoryInfo) (domain.PartnerCategory, error) {
  38 + pc := domain.PartnerCategory{
  39 + Id: m.Id,
  40 + Name: m.Name,
  41 + Code: m.Code,
  42 + }
  43 + return pc, nil
  44 +}
  45 +
  46 +func NewPartnerCategoryRepository(transactionContext *transaction.TransactionContext) (*PartnerCategoryRepository, error) {
  47 + if transactionContext == nil {
  48 + return nil, fmt.Errorf("transactionContext参数不能为nil")
  49 + }
  50 + return &PartnerCategoryRepository{transactionContext: transactionContext}, nil
  51 +}
@@ -18,50 +18,18 @@ var ( @@ -18,50 +18,18 @@ var (
18 _ domain.PartnerInfoRepository = (*PartnerInfoRepository)(nil) 18 _ domain.PartnerInfoRepository = (*PartnerInfoRepository)(nil)
19 ) 19 )
20 20
21 -func (repository *PartnerInfoRepository) transformPgModelToDomainModel(partnerInfoModel *models.PartnerInfo) (domain.PartnerInfo, error) {  
22 - m := domain.PartnerInfo{  
23 - Partner: domain.Partner{  
24 - Id: partnerInfoModel.Id,  
25 - PartnerName: partnerInfoModel.PartnerName,  
26 - Account: partnerInfoModel.Account,  
27 - },  
28 - PartnerCategory: partnerInfoModel.PartnerCategory,  
29 - Password: partnerInfoModel.Password,  
30 - Status: partnerInfoModel.Status,  
31 - CreateAt: partnerInfoModel.CreateAt,  
32 - Salesman: partnerInfoModel.Salesman,  
33 - RegionInfo: partnerInfoModel.RegionInfo,  
34 - CooperateTime: partnerInfoModel.CooperateTime,  
35 - CompanyId: partnerInfoModel.CompanyId,  
36 - }  
37 - p := []domain.PartnerCategory{}  
38 - for _, v := range partnerInfoModel.PartnerCategoryInfos {  
39 - catagory := domain.PartnerCategory{  
40 - Id: v.Id,  
41 - }  
42 - p = append(p, catagory)  
43 - }  
44 - m.PartnerCategoryInfos = p  
45 - return m, nil  
46 -}  
47 -  
48 -func NewPartnerInfoRepository(transactionContext *transaction.TransactionContext) (*PartnerInfoRepository, error) {  
49 - if transactionContext == nil {  
50 - return nil, fmt.Errorf("transactionContext参数不能为nil")  
51 - }  
52 - return &PartnerInfoRepository{transactionContext: transactionContext}, nil  
53 -}  
54 -  
55 func (repository *PartnerInfoRepository) Save(dm *domain.PartnerInfo) error { 21 func (repository *PartnerInfoRepository) Save(dm *domain.PartnerInfo) error {
56 var ( 22 var (
57 err error 23 err error
58 tx = repository.transactionContext.PgTx 24 tx = repository.transactionContext.PgTx
59 ) 25 )
60 26
61 - categorys := []domain.PartnerCategory{} 27 + var categories []domain.PartnerCategory
62 for _, v := range dm.PartnerCategoryInfos { 28 for _, v := range dm.PartnerCategoryInfos {
63 - categorys = append(categorys, domain.PartnerCategory{  
64 - Id: v.Id, 29 + categories = append(categories, domain.PartnerCategory{
  30 + Id: v.Id,
  31 + Name: v.Name,
  32 + Code: v.Code,
65 }) 33 })
66 } 34 }
67 m := &models.PartnerInfo{ 35 m := &models.PartnerInfo{
@@ -75,7 +43,8 @@ func (repository *PartnerInfoRepository) Save(dm *domain.PartnerInfo) error { @@ -75,7 +43,8 @@ func (repository *PartnerInfoRepository) Save(dm *domain.PartnerInfo) error {
75 RegionInfo: dm.RegionInfo, 43 RegionInfo: dm.RegionInfo,
76 CooperateTime: dm.CooperateTime, 44 CooperateTime: dm.CooperateTime,
77 CompanyId: dm.CompanyId, 45 CompanyId: dm.CompanyId,
78 - PartnerCategoryInfos: categorys, 46 + PartnerCategoryInfos: categories,
  47 + Remark: dm.Remark,
79 } 48 }
80 if m.Id == 0 { 49 if m.Id == 0 {
81 err = tx.Insert(m) 50 err = tx.Insert(m)
@@ -86,7 +55,7 @@ func (repository *PartnerInfoRepository) Save(dm *domain.PartnerInfo) error { @@ -86,7 +55,7 @@ func (repository *PartnerInfoRepository) Save(dm *domain.PartnerInfo) error {
86 } else { 55 } else {
87 _, err = tx.Model(m).WherePK(). 56 _, err = tx.Model(m).WherePK().
88 Column("partner_name", "account", "password", "status", "partner_category", "salesman", 57 Column("partner_name", "account", "password", "status", "partner_category", "salesman",
89 - "region_info", "cooperate_time", "update_at", "partner_category_infos"). 58 + "region_info", "cooperate_time", "update_at", "partner_category_infos, remark").
90 Update() 59 Update()
91 if err != nil { 60 if err != nil {
92 return err 61 return err
@@ -124,7 +93,7 @@ func (repository *PartnerInfoRepository) FindOne(queryOptions domain.PartnerFind @@ -124,7 +93,7 @@ func (repository *PartnerInfoRepository) FindOne(queryOptions domain.PartnerFind
124 93
125 func (repository *PartnerInfoRepository) Find(queryOption domain.PartnerFindQuery) ([]domain.PartnerInfo, error) { 94 func (repository *PartnerInfoRepository) Find(queryOption domain.PartnerFindQuery) ([]domain.PartnerInfo, error) {
126 db := repository.transactionContext.PgTx 95 db := repository.transactionContext.PgTx
127 - partnerModels := []models.PartnerInfo{} 96 + var partnerModels []models.PartnerInfo
128 query := db.Model(&partnerModels) 97 query := db.Model(&partnerModels)
129 if len(queryOption.PartnerName) > 0 { 98 if len(queryOption.PartnerName) > 0 {
130 query = query.Where("partner_name like ?", "%"+queryOption.PartnerName+"%") 99 query = query.Where("partner_name like ?", "%"+queryOption.PartnerName+"%")
@@ -174,7 +143,28 @@ func (repository *PartnerInfoRepository) Find(queryOption domain.PartnerFindQuer @@ -174,7 +143,28 @@ func (repository *PartnerInfoRepository) Find(queryOption domain.PartnerFindQuer
174 return partnerReturn, nil 143 return partnerReturn, nil
175 } 144 }
176 145
177 -func (repository PartnerInfoRepository) CountAll(queryOption domain.PartnerFindQuery) (int, error) { 146 +/**
  147 + * @Author SteveChan
  148 + * @Description //TODO 移除合伙人
  149 + * @Date 15:33 2020/12/29
  150 + * @Param
  151 + * @return
  152 + **/
  153 +func (repository *PartnerInfoRepository) Remove(id int64) error {
  154 + var (
  155 + err error
  156 + tx = repository.transactionContext.PgTx
  157 + )
  158 + m := &models.PartnerInfo{
  159 + Id: id,
  160 + }
  161 + _, err = tx.Model(m).
  162 + Where("id=?", id).
  163 + Delete()
  164 + return err
  165 +}
  166 +
  167 +func (repository *PartnerInfoRepository) CountAll(queryOption domain.PartnerFindQuery) (int, error) {
178 db := repository.transactionContext.PgTx 168 db := repository.transactionContext.PgTx
179 partnerModels := models.PartnerInfo{} 169 partnerModels := models.PartnerInfo{}
180 query := db.Model(&partnerModels) 170 query := db.Model(&partnerModels)
@@ -202,3 +192,40 @@ func (repository PartnerInfoRepository) CountAll(queryOption domain.PartnerFindQ @@ -202,3 +192,40 @@ func (repository PartnerInfoRepository) CountAll(queryOption domain.PartnerFindQ
202 cnt, err := query.Count() 192 cnt, err := query.Count()
203 return cnt, err 193 return cnt, err
204 } 194 }
  195 +
  196 +func (repository *PartnerInfoRepository) transformPgModelToDomainModel(partnerInfoModel *models.PartnerInfo) (domain.PartnerInfo, error) {
  197 + m := domain.PartnerInfo{
  198 + Partner: domain.Partner{
  199 + Id: partnerInfoModel.Id,
  200 + PartnerName: partnerInfoModel.PartnerName,
  201 + Account: partnerInfoModel.Account,
  202 + },
  203 + PartnerCategory: partnerInfoModel.PartnerCategory,
  204 + Password: partnerInfoModel.Password,
  205 + Status: partnerInfoModel.Status,
  206 + CreateAt: partnerInfoModel.CreateAt,
  207 + Salesman: partnerInfoModel.Salesman,
  208 + RegionInfo: partnerInfoModel.RegionInfo,
  209 + CooperateTime: partnerInfoModel.CooperateTime,
  210 + CompanyId: partnerInfoModel.CompanyId,
  211 + Remark: partnerInfoModel.Remark,
  212 + }
  213 + var p []domain.PartnerCategory
  214 + for _, v := range partnerInfoModel.PartnerCategoryInfos {
  215 + category := domain.PartnerCategory{
  216 + Id: v.Id,
  217 + Name: v.Name,
  218 + Code: v.Code,
  219 + }
  220 + p = append(p, category)
  221 + }
  222 + m.PartnerCategoryInfos = p
  223 + return m, nil
  224 +}
  225 +
  226 +func NewPartnerInfoRepository(transactionContext *transaction.TransactionContext) (*PartnerInfoRepository, error) {
  227 + if transactionContext == nil {
  228 + return nil, fmt.Errorf("transactionContext参数不能为nil")
  229 + }
  230 + return &PartnerInfoRepository{transactionContext: transactionContext}, nil
  231 +}
@@ -35,14 +35,14 @@ func (c *PartnerInfoController) Prepare() { @@ -35,14 +35,14 @@ func (c *PartnerInfoController) Prepare() {
35 func (c *PartnerInfoController) CreatePartnerInfo() { 35 func (c *PartnerInfoController) CreatePartnerInfo() {
36 //用与适配前端定义的数据结构 36 //用与适配前端定义的数据结构
37 type Parameter struct { 37 type Parameter struct {
38 - PartnerName string `json:"partnerName"`  
39 - PartnerType []int64 `json:"partnerType"`  
40 - Area string `json:"area"`  
41 - Account string `json:"account"`  
42 - State int `json:"state"`  
43 - CooperationTime string `json:"cooperationTime"`  
44 - SalesmanName string `json:"salesmanName"`  
45 - Phone string `json:"phone"` 38 + PartnerName string `json:"partnerName"`
  39 + PartnerType []*domain.PartnerCategory `json:"partnerType"`
  40 + Area string `json:"area"`
  41 + Account string `json:"account"`
  42 + State int `json:"state"`
  43 + CooperationTime string `json:"cooperationTime"`
  44 + SalesmanName string `json:"salesmanName"`
  45 + Phone string `json:"phone"`
46 } 46 }
47 var ( 47 var (
48 param Parameter 48 param Parameter
@@ -103,13 +103,13 @@ func (c *PartnerInfoController) CreatePartnerInfo() { @@ -103,13 +103,13 @@ func (c *PartnerInfoController) CreatePartnerInfo() {
103 func (c *PartnerInfoController) UpdatePartnerInfo() { 103 func (c *PartnerInfoController) UpdatePartnerInfo() {
104 //用与适配前端定义的数据结构 104 //用与适配前端定义的数据结构
105 type Parameter struct { 105 type Parameter struct {
106 - ID int64 `json:"id"`  
107 - PartnerType []int64 `json:"partnerType"`  
108 - Area string `json:"area"`  
109 - State int `json:"state"`  
110 - CooperationTime string `json:"cooperationTime"`  
111 - SalesmanName string `json:"salesmanName"`  
112 - Phone string `json:"phone"` 106 + ID int64 `json:"id"`
  107 + PartnerType []*domain.PartnerCategory `json:"partnerType"`
  108 + Area string `json:"area"`
  109 + State int `json:"state"`
  110 + CooperationTime string `json:"cooperationTime"`
  111 + SalesmanName string `json:"salesmanName"`
  112 + Phone string `json:"phone"`
113 } 113 }
114 var ( 114 var (
115 param Parameter 115 param Parameter
@@ -195,11 +195,12 @@ func (c *PartnerInfoController) GetPartnerInfo() { @@ -195,11 +195,12 @@ func (c *PartnerInfoController) GetPartnerInfo() {
195 rspResult["salesmanName"] = partnerInfo.Salesman[0].Name 195 rspResult["salesmanName"] = partnerInfo.Salesman[0].Name
196 rspResult["phone"] = partnerInfo.Salesman[0].Telephone 196 rspResult["phone"] = partnerInfo.Salesman[0].Telephone
197 } 197 }
198 - partnerTypes := []map[string]interface{}{} 198 + var partnerTypes []map[string]interface{}
199 for _, v := range partnerInfo.PartnerCategoryInfos { 199 for _, v := range partnerInfo.PartnerCategoryInfos {
200 m := map[string]interface{}{ 200 m := map[string]interface{}{
201 "id": v.Id, 201 "id": v.Id,
202 "name": v.Name, 202 "name": v.Name,
  203 + "code": v.Code,
203 } 204 }
204 partnerTypes = append(partnerTypes, m) 205 partnerTypes = append(partnerTypes, m)
205 } 206 }
@@ -208,6 +209,17 @@ func (c *PartnerInfoController) GetPartnerInfo() { @@ -208,6 +209,17 @@ func (c *PartnerInfoController) GetPartnerInfo() {
208 return 209 return
209 } 210 }
210 211
  212 +/**
  213 + * @Author SteveChan
  214 + * @Description //TODO 移除合伙人
  215 + * @Date 15:31 2020/12/29
  216 + * @Param
  217 + * @return
  218 + **/
  219 +func (c *PartnerInfoController) RemovePartnerInfo() {
  220 +
  221 +}
  222 +
211 //PartnerInfoSetState 合伙人批量禁用.启用 223 //PartnerInfoSetState 合伙人批量禁用.启用
212 func (c *PartnerInfoController) PartnerInfoSetState() { 224 func (c *PartnerInfoController) PartnerInfoSetState() {
213 //用与适配前端定义的数据结构 225 //用与适配前端定义的数据结构
@@ -224,19 +236,19 @@ func (c *PartnerInfoController) PartnerInfoSetState() { @@ -224,19 +236,19 @@ func (c *PartnerInfoController) PartnerInfoSetState() {
224 c.ResponseError(errors.New("json数据解析失败")) 236 c.ResponseError(errors.New("json数据解析失败"))
225 return 237 return
226 } 238 }
227 - comanyId := c.GetUserCompany() 239 + companyId := c.GetUserCompany()
228 var cmd partnerInfoCmd.StatusPartnerInfoCommand 240 var cmd partnerInfoCmd.StatusPartnerInfoCommand
229 switch param.Status { 241 switch param.Status {
230 case 0: 242 case 0:
231 cmd = partnerInfoCmd.StatusPartnerInfoCommand{ 243 cmd = partnerInfoCmd.StatusPartnerInfoCommand{
232 Ids: param.Id, 244 Ids: param.Id,
233 - CompanyId: comanyId, 245 + CompanyId: companyId,
234 Status: domain.PARTNER_STATUS_NO, 246 Status: domain.PARTNER_STATUS_NO,
235 } 247 }
236 case 1: 248 case 1:
237 cmd = partnerInfoCmd.StatusPartnerInfoCommand{ 249 cmd = partnerInfoCmd.StatusPartnerInfoCommand{
238 Ids: param.Id, 250 Ids: param.Id,
239 - CompanyId: comanyId, 251 + CompanyId: companyId,
240 Status: domain.PARTNER_STATUS_YES, 252 Status: domain.PARTNER_STATUS_YES,
241 } 253 }
242 default: 254 default:
@@ -256,7 +268,7 @@ func (c *PartnerInfoController) PartnerInfoSetState() { @@ -256,7 +268,7 @@ func (c *PartnerInfoController) PartnerInfoSetState() {
256 //ListPartnerInfo 合伙人列表 268 //ListPartnerInfo 合伙人列表
257 func (c *PartnerInfoController) ListPartnerInfo() { 269 func (c *PartnerInfoController) ListPartnerInfo() {
258 type Parameter struct { 270 type Parameter struct {
259 - Partnertype int `json:"partnerType"` 271 + PartnerType int `json:"partnerType"`
260 Area string `json:"area"` 272 Area string `json:"area"`
261 PartnerName string `json:"partnerName"` 273 PartnerName string `json:"partnerName"`
262 PageSize int `json:"pageSize"` 274 PageSize int `json:"pageSize"`
@@ -280,7 +292,7 @@ func (c *PartnerInfoController) ListPartnerInfo() { @@ -280,7 +292,7 @@ func (c *PartnerInfoController) ListPartnerInfo() {
280 } 292 }
281 companyId := c.GetUserCompany() 293 companyId := c.GetUserCompany()
282 query := partnerQuery.ListPartnerInfoQuery{ 294 query := partnerQuery.ListPartnerInfoQuery{
283 - Partnertype: param.Partnertype, 295 + PartnerType: param.PartnerType,
284 PartnerName: param.PartnerName, 296 PartnerName: param.PartnerName,
285 RegionInfo: param.Area, 297 RegionInfo: param.Area,
286 Limit: param.PageSize, 298 Limit: param.PageSize,
@@ -294,7 +306,7 @@ func (c *PartnerInfoController) ListPartnerInfo() { @@ -294,7 +306,7 @@ func (c *PartnerInfoController) ListPartnerInfo() {
294 c.ResponseError(err) 306 c.ResponseError(err)
295 return 307 return
296 } 308 }
297 - resp := []map[string]interface{}{} 309 + var resp []map[string]interface{}
298 indexBegin := query.Offset 310 indexBegin := query.Offset
299 for i := range partners { 311 for i := range partners {
300 m := map[string]interface{}{ 312 m := map[string]interface{}{
@@ -32,7 +32,7 @@ func (c *UserController) ListUser() { @@ -32,7 +32,7 @@ func (c *UserController) ListUser() {
32 //用与适配前端定义的数据结构 32 //用与适配前端定义的数据结构
33 type Paramter struct { 33 type Paramter struct {
34 SearchText string `json:"searchText"` 34 SearchText string `json:"searchText"`
35 - PageSize int `json::"pageSize"` 35 + PageSize int `json:"pageSize"`
36 PageNumber int `json:"pageNumber"` 36 PageNumber int `json:"pageNumber"`
37 } 37 }
38 var ( 38 var (
@@ -23,6 +23,7 @@ func init() { @@ -23,6 +23,7 @@ func init() {
23 beego.NSRouter("/edit", &controllers.PartnerInfoController{}, "POST:UpdatePartnerInfo"), 23 beego.NSRouter("/edit", &controllers.PartnerInfoController{}, "POST:UpdatePartnerInfo"),
24 beego.NSRouter("/detail", &controllers.PartnerInfoController{}, "POST:GetPartnerInfo"), 24 beego.NSRouter("/detail", &controllers.PartnerInfoController{}, "POST:GetPartnerInfo"),
25 beego.NSRouter("/batchDisabled", &controllers.PartnerInfoController{}, "POST:PartnerInfoSetState"), 25 beego.NSRouter("/batchDisabled", &controllers.PartnerInfoController{}, "POST:PartnerInfoSetState"),
  26 + beego.NSRouter("/:id", &controllers.PartnerInfoController{}, "DELETE:RemovePartnerInfo"),
26 ), 27 ),
27 beego.NSNamespace("/dividends", 28 beego.NSNamespace("/dividends",
28 beego.NSRouter("/list", &controllers.OrderDividendController{}, "POST:PageListOrderDividend"), 29 beego.NSRouter("/list", &controllers.OrderDividendController{}, "POST:PageListOrderDividend"),
@@ -51,6 +51,7 @@ func (c *MessageConsumer) ConsumeClaim(groupSession sarama.ConsumerGroupSession, @@ -51,6 +51,7 @@ func (c *MessageConsumer) ConsumeClaim(groupSession sarama.ConsumerGroupSession,
51 } 51 }
52 if err = topicHandle(message); err != nil { 52 if err = topicHandle(message); err != nil {
53 logs.Error("Message claimed: kafka消息处理错误 topic =", message.Topic, message.Offset, err) 53 logs.Error("Message claimed: kafka消息处理错误 topic =", message.Topic, message.Offset, err)
  54 +
54 } 55 }
55 groupSession.MarkMessage(message, "") 56 groupSession.MarkMessage(message, "")
56 } 57 }
@@ -30,6 +30,9 @@ func init() { @@ -30,6 +30,9 @@ func init() {
30 if runEnv == "partnermg_prd" { 30 if runEnv == "partnermg_prd" {
31 initHandleRoutersProd() 31 initHandleRoutersProd()
32 } 32 }
  33 + if runEnv == "partnermg_dev" {
  34 + initHandleRoutersDev()
  35 + }
33 } 36 }
34 37
35 func initHandleRoutersTest() { 38 func initHandleRoutersTest() {
@@ -39,3 +42,7 @@ func initHandleRoutersTest() { @@ -39,3 +42,7 @@ func initHandleRoutersTest() {
39 func initHandleRoutersProd() { 42 func initHandleRoutersProd() {
40 TopicHandleRouters["xiangmi_project"] = handles.DataFromXiangMi 43 TopicHandleRouters["xiangmi_project"] = handles.DataFromXiangMi
41 } 44 }
  45 +
  46 +func initHandleRoutersDev() {
  47 + TopicHandleRouters["xiangmi_project_dev"] = handles.DataFromXiangMi
  48 +}
1 -package geetest  
2 -  
3 -import (  
4 - "crypto/md5"  
5 - "encoding/hex"  
6 - "encoding/json"  
7 - "errors"  
8 - "io/ioutil"  
9 - "net/http"  
10 - "net/url"  
11 - "strings"  
12 - "time"  
13 -)  
14 -  
15 -type GeetestLib struct {  
16 - CaptchaID string  
17 - PrivateKey string  
18 - Client *http.Client  
19 -}  
20 -  
21 -type FailbackRegisterRespnse struct {  
22 - Success int `json:"success"`  
23 - GT string `json:"gt"`  
24 - Challenge string `json:"challenge"`  
25 - NewCaptcha int `json:"new_captcha"`  
26 -}  
27 -  
28 -const (  
29 - geetestHost = "http://api.geetest.com"  
30 - registerURL = geetestHost + "/register.php"  
31 - validateURL = geetestHost + "/validate.php"  
32 -)  
33 -  
34 -func MD5Encode(input string) string {  
35 - md5Instant := md5.New()  
36 - md5Instant.Write([]byte(input))  
37 - return hex.EncodeToString(md5Instant.Sum(nil))  
38 -}  
39 -  
40 -// 初始化 GeetestLib  
41 -func NewGeetestLib(capthcaID string, privateKey string, timeOut time.Duration) (geetest GeetestLib){  
42 - client := &http.Client{Timeout: timeOut}  
43 - geetest = GeetestLib{capthcaID, privateKey, client}  
44 - return  
45 -}  
46 -  
47 -func (g *GeetestLib) getFailBackRegisterResponse(success int, challenge string) []byte {  
48 - if challenge == "" {  
49 - challenge = hex.EncodeToString(md5.New().Sum(nil))  
50 - }  
51 -  
52 - response := FailbackRegisterRespnse{  
53 - success,  
54 - g.CaptchaID,  
55 - challenge,  
56 - 1,  
57 - }  
58 - res, _ := json.Marshal(response)  
59 - return res  
60 -}  
61 -  
62 -func (g *GeetestLib) do(req *http.Request) (body []byte, err error) {  
63 - req.Header.Set("Content-Type", "application/x-www-form-urlencoded")  
64 - var resp *http.Response  
65 - if resp, err = g.Client.Do(req); err != nil {  
66 - return  
67 - }  
68 - defer resp.Body.Close()  
69 - if resp.StatusCode >= http.StatusInternalServerError {  
70 - err = errors.New("http status code 5xx")  
71 - return  
72 - }  
73 -  
74 - if body, err = ioutil.ReadAll(resp.Body); err != nil {  
75 - return  
76 - }  
77 - return  
78 -}  
79 -  
80 -func (g *GeetestLib) PreProcess(userID string, userIP string) (int8, []byte) {  
81 - params := url.Values{}  
82 - params.Add("gt", g.CaptchaID)  
83 - params.Add("new_captcha", "1")  
84 - if userID != "" {  
85 - params.Add("user_id", userID)  
86 - }  
87 - if userIP != "" {  
88 - params.Add("ip_adress", userIP)  
89 - }  
90 - req, _ := http.NewRequest("GET", registerURL+"?"+params.Encode(), nil)  
91 - body, err := g.do(req)  
92 - if err != nil {  
93 - return 0, g.getFailBackRegisterResponse(0, "")  
94 - }  
95 - challenge := string(body)  
96 - if len(challenge) != 32 {  
97 - return 0, g.getFailBackRegisterResponse(0, "")  
98 - } else {  
99 - challenge = MD5Encode(challenge + g.PrivateKey)  
100 - return 1, g.getFailBackRegisterResponse(1, challenge)  
101 - }  
102 -}  
103 -  
104 -func (g *GeetestLib) checkParas(challenge string, validate string, seccode string) bool {  
105 - if challenge == "" || validate == "" || seccode == "" {  
106 - return false  
107 - }  
108 - return true  
109 -}  
110 -  
111 -func (g *GeetestLib) checkSuccessRes(challenge string, validate string) bool {  
112 - return MD5Encode(g.PrivateKey+"geetest"+challenge) == validate  
113 -}  
114 -  
115 -func (g *GeetestLib) checkFailbackRes(challenge string, validate string) bool {  
116 - return MD5Encode(challenge) == validate  
117 -}  
118 -  
119 -func (g *GeetestLib) SuccessValidate(challenge string, validate string, seccode string, userID string, userIP string) bool {  
120 - if !g.checkParas(challenge, validate, seccode) {  
121 - return false  
122 - }  
123 - if !g.checkSuccessRes(challenge, validate) {  
124 - return false  
125 - }  
126 - params := url.Values{}  
127 - params.Add("seccode", seccode)  
128 - params.Add("challenge", challenge)  
129 - params.Add("captchaid", g.CaptchaID)  
130 - params.Add("sdk", "golang_v1.0.0")  
131 - if userID != "" {  
132 - params.Add("user_id", userID)  
133 - }  
134 - if userIP != "" {  
135 - params.Add("ip_adress", userIP)  
136 - }  
137 - req, _ := http.NewRequest("POST", validateURL, strings.NewReader(params.Encode()))  
138 - body, err := g.do(req)  
139 - if err != nil {  
140 - return false  
141 - }  
142 - res := string(body)  
143 - return res == MD5Encode(seccode)  
144 -}  
145 -  
146 -func (g *GeetestLib) FailbackValidate(challenge string, validate string, seccode string) bool {  
147 - if !g.checkParas(challenge, validate, seccode) {  
148 - return false  
149 - }  
150 - if !g.checkFailbackRes(challenge, validate) {  
151 - return false  
152 - }  
153 - return true  
154 -}  
1 -language: go  
2 -go:  
3 - - 1.2  
4 - - stable 1 +language: go
  2 +go:
  3 + - 1.2
  4 + - stable
5 - tip 5 - tip
1 -A reader for Microsoft's Compound File Binary File Format.  
2 -  
3 -Example usage:  
4 -  
5 - file, _ := os.Open("test/test.doc")  
6 - defer file.Close()  
7 - doc, err := mscfb.New(file)  
8 - if err != nil {  
9 - log.Fatal(err)  
10 - }  
11 - for entry, err := doc.Next(); err == nil; entry, err = doc.Next() {  
12 - buf := make([]byte, 512)  
13 - i, _ := doc.Read(buf)  
14 - if i > 0 {  
15 - fmt.Println(buf[:i])  
16 - }  
17 - fmt.Println(entry.Name)  
18 - }  
19 -  
20 -The Compound File Binary File Format is also known as the Object Linking and Embedding (OLE) or Component Object Model (COM) format and was used by early MS software such as MS Office. See [http://msdn.microsoft.com/en-us/library/dd942138.aspx](http://msdn.microsoft.com/en-us/library/dd942138.aspx) for more details  
21 -  
22 -Install with `go get github.com/richardlehane/mscfb`  
23 - 1 +A reader for Microsoft's Compound File Binary File Format.
  2 +
  3 +Example usage:
  4 +
  5 + file, _ := os.Open("test/test.doc")
  6 + defer file.Close()
  7 + doc, err := mscfb.New(file)
  8 + if err != nil {
  9 + log.Fatal(err)
  10 + }
  11 + for entry, err := doc.Next(); err == nil; entry, err = doc.Next() {
  12 + buf := make([]byte, 512)
  13 + i, _ := doc.Read(buf)
  14 + if i > 0 {
  15 + fmt.Println(buf[:i])
  16 + }
  17 + fmt.Println(entry.Name)
  18 + }
  19 +
  20 +The Compound File Binary File Format is also known as the Object Linking and Embedding (OLE) or Component Object Model (COM) format and was used by early MS software such as MS Office. See [http://msdn.microsoft.com/en-us/library/dd942138.aspx](http://msdn.microsoft.com/en-us/library/dd942138.aspx) for more details
  21 +
  22 +Install with `go get github.com/richardlehane/mscfb`
  23 +
24 [![Build Status](https://travis-ci.org/richardlehane/mscfb.png?branch=master)](https://travis-ci.org/richardlehane/mscfb) 24 [![Build Status](https://travis-ci.org/richardlehane/mscfb.png?branch=master)](https://travis-ci.org/richardlehane/mscfb)
1 -// +build gofuzz  
2 -  
3 -// fuzzing with https://github.com/dvyukov/go-fuzz  
4 -package mscfb  
5 -  
6 -import (  
7 - "bytes"  
8 - "io"  
9 -)  
10 -  
11 -func Fuzz(data []byte) int {  
12 - doc, err := New(bytes.NewReader(data))  
13 - if err != nil {  
14 - if doc != nil {  
15 - panic("doc != nil on error " + err.Error())  
16 - }  
17 - return 0  
18 - }  
19 - buf := &bytes.Buffer{}  
20 - for entry, err := doc.Next(); ; entry, err = doc.Next() {  
21 - if err != nil {  
22 - if err == io.EOF {  
23 - return 1  
24 - }  
25 - if entry != nil {  
26 - panic("entry != nil on error " + err.Error())  
27 - }  
28 - }  
29 - buf.Reset()  
30 - buf.ReadFrom(entry)  
31 - }  
32 - return 1  
33 -} 1 +// +build gofuzz
  2 +
  3 +// fuzzing with https://github.com/dvyukov/go-fuzz
  4 +package mscfb
  5 +
  6 +import (
  7 + "bytes"
  8 + "io"
  9 +)
  10 +
  11 +func Fuzz(data []byte) int {
  12 + doc, err := New(bytes.NewReader(data))
  13 + if err != nil {
  14 + if doc != nil {
  15 + panic("doc != nil on error " + err.Error())
  16 + }
  17 + return 0
  18 + }
  19 + buf := &bytes.Buffer{}
  20 + for entry, err := doc.Next(); ; entry, err = doc.Next() {
  21 + if err != nil {
  22 + if err == io.EOF {
  23 + return 1
  24 + }
  25 + if entry != nil {
  26 + panic("entry != nil on error " + err.Error())
  27 + }
  28 + }
  29 + buf.Reset()
  30 + buf.ReadFrom(entry)
  31 + }
  32 + return 1
  33 +}
1 -// Copyright 2013 Richard Lehane. All rights reserved.  
2 -//  
3 -// Licensed under the Apache License, Version 2.0 (the "License");  
4 -// you may not use this file except in compliance with the License.  
5 -// You may obtain a copy of the License at  
6 -//  
7 -// http://www.apache.org/licenses/LICENSE-2.0  
8 -//  
9 -// Unless required by applicable law or agreed to in writing, software  
10 -// distributed under the License is distributed on an "AS IS" BASIS,  
11 -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
12 -// See the License for the specific language governing permissions and  
13 -// limitations under the License.  
14 -  
15 -// Package mscfb implements a reader for Microsoft's Compound File Binary File Format (http://msdn.microsoft.com/en-us/library/dd942138.aspx).  
16 -//  
17 -// The Compound File Binary File Format is also known as the Object Linking and Embedding (OLE) or Component Object Model (COM) format and was used by many  
18 -// early MS software such as MS Office.  
19 -//  
20 -// Example:  
21 -// file, _ := os.Open("test/test.doc")  
22 -// defer file.Close()  
23 -// doc, err := mscfb.New(file)  
24 -// if err != nil {  
25 -// log.Fatal(err)  
26 -// }  
27 -// for entry, err := doc.Next(); err == nil; entry, err = doc.Next() {  
28 -// buf := make([]byte, 512)  
29 -// i, _ := entry.Read(buf)  
30 -// if i > 0 {  
31 -// fmt.Println(buf[:i])  
32 -// }  
33 -// fmt.Println(entry.Name)  
34 -// }  
35 -package mscfb  
36 -  
37 -import (  
38 - "encoding/binary"  
39 - "io"  
40 - "strconv"  
41 - "time"  
42 -)  
43 -  
44 -func fileOffset(ss, sn uint32) int64 {  
45 - return int64((sn + 1) * ss)  
46 -}  
47 -  
48 -const (  
49 - signature uint64 = 0xE11AB1A1E011CFD0  
50 - miniStreamSectorSize uint32 = 64  
51 - miniStreamCutoffSize int64 = 4096  
52 - dirEntrySize uint32 = 128 //128 bytes  
53 -)  
54 -  
55 -const (  
56 - maxRegSect uint32 = 0xFFFFFFFA // Maximum regular sector number  
57 - difatSect uint32 = 0xFFFFFFFC //Specifies a DIFAT sector in the FAT  
58 - fatSect uint32 = 0xFFFFFFFD // Specifies a FAT sector in the FAT  
59 - endOfChain uint32 = 0xFFFFFFFE // End of linked chain of sectors  
60 - freeSect uint32 = 0xFFFFFFFF // Speficies unallocated sector in the FAT, Mini FAT or DIFAT  
61 - maxRegStreamID uint32 = 0xFFFFFFFA // maximum regular stream ID  
62 - noStream uint32 = 0xFFFFFFFF // empty pointer  
63 -)  
64 -  
65 -const lenHeader int = 8 + 16 + 10 + 6 + 12 + 8 + 16 + 109*4  
66 -  
67 -type headerFields struct {  
68 - signature uint64  
69 - _ [16]byte //CLSID - ignore, must be null  
70 - minorVersion uint16 //Version number for non-breaking changes. This field SHOULD be set to 0x003E if the major version field is either 0x0003 or 0x0004.  
71 - majorVersion uint16 //Version number for breaking changes. This field MUST be set to either 0x0003 (version 3) or 0x0004 (version 4).  
72 - _ [2]byte //byte order - ignore, must be little endian  
73 - sectorSize uint16 //This field MUST be set to 0x0009, or 0x000c, depending on the Major Version field. This field specifies the sector size of the compound file as a power of 2. If Major Version is 3, then the Sector Shift MUST be 0x0009, specifying a sector size of 512 bytes. If Major Version is 4, then the Sector Shift MUST be 0x000C, specifying a sector size of 4096 bytes.  
74 - _ [2]byte // ministream sector size - ignore, must be 64 bytes  
75 - _ [6]byte // reserved - ignore, not used  
76 - numDirectorySectors uint32 //This integer field contains the count of the number of directory sectors in the compound file. If Major Version is 3, then the Number of Directory Sectors MUST be zero. This field is not supported for version 3 compound files.  
77 - numFatSectors uint32 //This integer field contains the count of the number of FAT sectors in the compound file.  
78 - directorySectorLoc uint32 //This integer field contains the starting sector number for the directory stream.  
79 - _ [4]byte // transaction - ignore, not used  
80 - _ [4]byte // mini stream size cutooff - ignore, must be 4096 bytes  
81 - miniFatSectorLoc uint32 //This integer field contains the starting sector number for the mini FAT.  
82 - numMiniFatSectors uint32 //This integer field contains the count of the number of mini FAT sectors in the compound file.  
83 - difatSectorLoc uint32 //This integer field contains the starting sector number for the DIFAT.  
84 - numDifatSectors uint32 //This integer field contains the count of the number of DIFAT sectors in the compound file.  
85 - initialDifats [109]uint32 //The first 109 difat sectors are included in the header  
86 -}  
87 -  
88 -func makeHeader(b []byte) *headerFields {  
89 - h := &headerFields{}  
90 - h.signature = binary.LittleEndian.Uint64(b[:8])  
91 - h.minorVersion = binary.LittleEndian.Uint16(b[24:26])  
92 - h.majorVersion = binary.LittleEndian.Uint16(b[26:28])  
93 - h.sectorSize = binary.LittleEndian.Uint16(b[30:32])  
94 - h.numDirectorySectors = binary.LittleEndian.Uint32(b[40:44])  
95 - h.numFatSectors = binary.LittleEndian.Uint32(b[44:48])  
96 - h.directorySectorLoc = binary.LittleEndian.Uint32(b[48:52])  
97 - h.miniFatSectorLoc = binary.LittleEndian.Uint32(b[60:64])  
98 - h.numMiniFatSectors = binary.LittleEndian.Uint32(b[64:68])  
99 - h.difatSectorLoc = binary.LittleEndian.Uint32(b[68:72])  
100 - h.numDifatSectors = binary.LittleEndian.Uint32(b[72:76])  
101 - var idx int  
102 - for i := 76; i < 512; i = i + 4 {  
103 - h.initialDifats[idx] = binary.LittleEndian.Uint32(b[i : i+4])  
104 - idx++  
105 - }  
106 - return h  
107 -}  
108 -  
109 -type header struct {  
110 - *headerFields  
111 - difats []uint32  
112 - miniFatLocs []uint32  
113 - miniStreamLocs []uint32 // chain of sectors containing the ministream  
114 -}  
115 -  
116 -func (r *Reader) setHeader() error {  
117 - buf, err := r.readAt(0, lenHeader)  
118 - if err != nil {  
119 - return err  
120 - }  
121 - r.header = &header{headerFields: makeHeader(buf)}  
122 - // sanity check - check signature  
123 - if r.header.signature != signature {  
124 - return Error{ErrFormat, "bad signature", int64(r.header.signature)}  
125 - }  
126 - // check for legal sector size  
127 - if r.header.sectorSize == 0x0009 || r.header.sectorSize == 0x000c {  
128 - r.sectorSize = uint32(1 << r.header.sectorSize)  
129 - } else {  
130 - return Error{ErrFormat, "illegal sector size", int64(r.header.sectorSize)}  
131 - }  
132 - // check for DIFAT overflow  
133 - if r.header.numDifatSectors > 0 {  
134 - sz := (r.sectorSize / 4) - 1  
135 - if int(r.header.numDifatSectors*sz+109) < 0 {  
136 - return Error{ErrFormat, "DIFAT int overflow", int64(r.header.numDifatSectors)}  
137 - }  
138 - if r.header.numDifatSectors*sz+109 > r.header.numFatSectors+sz {  
139 - return Error{ErrFormat, "num DIFATs exceeds FAT sectors", int64(r.header.numDifatSectors)}  
140 - }  
141 - }  
142 - // check for mini FAT overflow  
143 - if r.header.numMiniFatSectors > 0 {  
144 - if int(r.sectorSize/4*r.header.numMiniFatSectors) < 0 {  
145 - return Error{ErrFormat, "mini FAT int overflow", int64(r.header.numMiniFatSectors)}  
146 - }  
147 - if r.header.numMiniFatSectors > r.header.numFatSectors*(r.sectorSize/miniStreamSectorSize) {  
148 - return Error{ErrFormat, "num mini FATs exceeds FAT sectors", int64(r.header.numFatSectors)}  
149 - }  
150 - }  
151 - return nil  
152 -}  
153 -  
154 -func (r *Reader) setDifats() error {  
155 - r.header.difats = r.header.initialDifats[:]  
156 - // return early if no extra DIFAT sectors  
157 - if r.header.numDifatSectors == 0 {  
158 - return nil  
159 - }  
160 - sz := (r.sectorSize / 4) - 1  
161 - n := make([]uint32, 109, r.header.numDifatSectors*sz+109)  
162 - copy(n, r.header.difats)  
163 - r.header.difats = n  
164 - off := r.header.difatSectorLoc  
165 - for i := 0; i < int(r.header.numDifatSectors); i++ {  
166 - buf, err := r.readAt(fileOffset(r.sectorSize, off), int(r.sectorSize))  
167 - if err != nil {  
168 - return Error{ErrFormat, "error setting DIFAT(" + err.Error() + ")", int64(off)}  
169 - }  
170 - for j := 0; j < int(sz); j++ {  
171 - r.header.difats = append(r.header.difats, binary.LittleEndian.Uint32(buf[j*4:j*4+4]))  
172 - }  
173 - off = binary.LittleEndian.Uint32(buf[len(buf)-4:])  
174 - }  
175 - return nil  
176 -}  
177 -  
178 -// set the ministream FAT and sector slices in the header  
179 -func (r *Reader) setMiniStream() error {  
180 - // do nothing if there is no ministream  
181 - if r.direntries[0].startingSectorLoc == endOfChain || r.header.miniFatSectorLoc == endOfChain || r.header.numMiniFatSectors == 0 {  
182 - return nil  
183 - }  
184 - // build a slice of minifat sectors (akin to the DIFAT slice)  
185 - c := int(r.header.numMiniFatSectors)  
186 - r.header.miniFatLocs = make([]uint32, c)  
187 - r.header.miniFatLocs[0] = r.header.miniFatSectorLoc  
188 - for i := 1; i < c; i++ {  
189 - loc, err := r.findNext(r.header.miniFatLocs[i-1], false)  
190 - if err != nil {  
191 - return Error{ErrFormat, "setting mini stream (" + err.Error() + ")", int64(r.header.miniFatLocs[i-1])}  
192 - }  
193 - r.header.miniFatLocs[i] = loc  
194 - }  
195 - // build a slice of ministream sectors  
196 - c = int(r.sectorSize / 4 * r.header.numMiniFatSectors)  
197 - r.header.miniStreamLocs = make([]uint32, 0, c)  
198 - sn := r.direntries[0].startingSectorLoc  
199 - var err error  
200 - for sn != endOfChain {  
201 - r.header.miniStreamLocs = append(r.header.miniStreamLocs, sn)  
202 - sn, err = r.findNext(sn, false)  
203 - if err != nil {  
204 - return Error{ErrFormat, "setting mini stream (" + err.Error() + ")", int64(sn)}  
205 - }  
206 - }  
207 - return nil  
208 -}  
209 -  
210 -func (r *Reader) readAt(offset int64, length int) ([]byte, error) {  
211 - if r.slicer {  
212 - b, err := r.ra.(slicer).Slice(offset, length)  
213 - if err != nil {  
214 - return nil, Error{ErrRead, "slicer read error (" + err.Error() + ")", offset}  
215 - }  
216 - return b, nil  
217 - }  
218 - if length > len(r.buf) {  
219 - return nil, Error{ErrRead, "read length greater than read buffer", int64(length)}  
220 - }  
221 - if _, err := r.ra.ReadAt(r.buf[:length], offset); err != nil {  
222 - return nil, Error{ErrRead, err.Error(), offset}  
223 - }  
224 - return r.buf[:length], nil  
225 -}  
226 -  
227 -func (r *Reader) getOffset(sn uint32, mini bool) (int64, error) {  
228 - if mini {  
229 - num := r.sectorSize / 64  
230 - sec := int(sn / num)  
231 - if sec >= len(r.header.miniStreamLocs) {  
232 - return 0, Error{ErrRead, "minisector number is outside minisector range", int64(sec)}  
233 - }  
234 - dif := sn % num  
235 - return int64((r.header.miniStreamLocs[sec]+1)*r.sectorSize + dif*64), nil  
236 - }  
237 - return fileOffset(r.sectorSize, sn), nil  
238 -}  
239 -  
240 -// check the FAT sector for the next sector in a chain  
241 -func (r *Reader) findNext(sn uint32, mini bool) (uint32, error) {  
242 - entries := r.sectorSize / 4  
243 - index := int(sn / entries) // find position in DIFAT or minifat array  
244 - var sect uint32  
245 - if mini {  
246 - if index < 0 || index >= len(r.header.miniFatLocs) {  
247 - return 0, Error{ErrRead, "minisector index is outside miniFAT range", int64(index)}  
248 - }  
249 - sect = r.header.miniFatLocs[index]  
250 - } else {  
251 - if index < 0 || index >= len(r.header.difats) {  
252 - return 0, Error{ErrRead, "FAT index is outside DIFAT range", int64(index)}  
253 - }  
254 - sect = r.header.difats[index]  
255 - }  
256 - fatIndex := sn % entries // find position within FAT or MiniFAT sector  
257 - offset := fileOffset(r.sectorSize, sect) + int64(fatIndex*4)  
258 - buf, err := r.readAt(offset, 4)  
259 - if err != nil {  
260 - return 0, Error{ErrRead, "bad read finding next sector (" + err.Error() + ")", offset}  
261 - }  
262 - return binary.LittleEndian.Uint32(buf), nil  
263 -}  
264 -  
265 -// Reader provides sequential access to the contents of a MS compound file (MSCFB)  
266 -type Reader struct {  
267 - slicer bool  
268 - sectorSize uint32  
269 - buf []byte  
270 - header *header  
271 - File []*File // File is an ordered slice of final directory entries.  
272 - direntries []*File // unordered raw directory entries  
273 - entry int  
274 -  
275 - ra io.ReaderAt  
276 - wa io.WriterAt  
277 -}  
278 -  
279 -// New returns a MSCFB reader  
280 -func New(ra io.ReaderAt) (*Reader, error) {  
281 - r := &Reader{ra: ra}  
282 - if _, ok := ra.(slicer); ok {  
283 - r.slicer = true  
284 - } else {  
285 - r.buf = make([]byte, lenHeader)  
286 - }  
287 - if err := r.setHeader(); err != nil {  
288 - return nil, err  
289 - }  
290 - // resize the buffer to 4096 if sector size isn't 512  
291 - if !r.slicer && int(r.sectorSize) > len(r.buf) {  
292 - r.buf = make([]byte, r.sectorSize)  
293 - }  
294 - if err := r.setDifats(); err != nil {  
295 - return nil, err  
296 - }  
297 - if err := r.setDirEntries(); err != nil {  
298 - return nil, err  
299 - }  
300 - if err := r.setMiniStream(); err != nil {  
301 - return nil, err  
302 - }  
303 - if err := r.traverse(); err != nil {  
304 - return nil, err  
305 - }  
306 - return r, nil  
307 -}  
308 -  
309 -// ID returns the CLSID (class ID) field from the root directory entry  
310 -func (r *Reader) ID() string {  
311 - return r.File[0].ID()  
312 -}  
313 -  
314 -// Created returns the created field from the root directory entry  
315 -func (r *Reader) Created() time.Time {  
316 - return r.File[0].Created()  
317 -}  
318 -  
319 -// Modified returns the last modified field from the root directory entry  
320 -func (r *Reader) Modified() time.Time {  
321 - return r.File[0].Modified()  
322 -}  
323 -  
324 -// Next iterates to the next directory entry.  
325 -// This isn't necessarily an adjacent *File within the File slice, but is based on the Left Sibling, Right Sibling and Child information in directory entries.  
326 -func (r *Reader) Next() (*File, error) {  
327 - r.entry++  
328 - if r.entry >= len(r.File) {  
329 - return nil, io.EOF  
330 - }  
331 - return r.File[r.entry], nil  
332 -}  
333 -  
334 -// Read the current directory entry  
335 -func (r *Reader) Read(b []byte) (n int, err error) {  
336 - if r.entry >= len(r.File) {  
337 - return 0, io.EOF  
338 - }  
339 - return r.File[r.entry].Read(b)  
340 -}  
341 -  
342 -// Debug provides granular information from an mscfb file to assist with debugging  
343 -func (r *Reader) Debug() map[string][]uint32 {  
344 - ret := map[string][]uint32{  
345 - "sector size": []uint32{r.sectorSize},  
346 - "mini fat locs": r.header.miniFatLocs,  
347 - "mini stream locs": r.header.miniStreamLocs,  
348 - "directory sector": []uint32{r.header.directorySectorLoc},  
349 - "mini stream start/size": []uint32{r.File[0].startingSectorLoc, binary.LittleEndian.Uint32(r.File[0].streamSize[:])},  
350 - }  
351 - for f, err := r.Next(); err == nil; f, err = r.Next() {  
352 - ret[f.Name+" start/size"] = []uint32{f.startingSectorLoc, binary.LittleEndian.Uint32(f.streamSize[:])}  
353 - }  
354 - return ret  
355 -}  
356 -  
357 -const (  
358 - // ErrFormat reports issues with the MSCFB's header structures  
359 - ErrFormat = iota  
360 - // ErrRead reports issues attempting to read MSCFB streams  
361 - ErrRead  
362 - // ErrSeek reports seek issues  
363 - ErrSeek  
364 - // ErrWrite reports write issues  
365 - ErrWrite  
366 - // ErrTraverse reports issues attempting to traverse the child-parent-sibling relations  
367 - // between MSCFB storage objects  
368 - ErrTraverse  
369 -)  
370 -  
371 -type Error struct {  
372 - typ int  
373 - msg string  
374 - val int64  
375 -}  
376 -  
377 -func (e Error) Error() string {  
378 - return "mscfb: " + e.msg + "; " + strconv.FormatInt(e.val, 10)  
379 -}  
380 -  
381 -// Typ gives the type of MSCFB error  
382 -func (e Error) Typ() int {  
383 - return e.typ  
384 -}  
385 -  
386 -// Slicer interface avoids a copy by obtaining a byte slice directly from the underlying reader  
387 -type slicer interface {  
388 - Slice(offset int64, length int) ([]byte, error)  
389 -} 1 +// Copyright 2013 Richard Lehane. All rights reserved.
  2 +//
  3 +// Licensed under the Apache License, Version 2.0 (the "License");
  4 +// you may not use this file except in compliance with the License.
  5 +// You may obtain a copy of the License at
  6 +//
  7 +// http://www.apache.org/licenses/LICENSE-2.0
  8 +//
  9 +// Unless required by applicable law or agreed to in writing, software
  10 +// distributed under the License is distributed on an "AS IS" BASIS,
  11 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +// See the License for the specific language governing permissions and
  13 +// limitations under the License.
  14 +
  15 +// Package mscfb implements a reader for Microsoft's Compound File Binary File Format (http://msdn.microsoft.com/en-us/library/dd942138.aspx).
  16 +//
  17 +// The Compound File Binary File Format is also known as the Object Linking and Embedding (OLE) or Component Object Model (COM) format and was used by many
  18 +// early MS software such as MS Office.
  19 +//
  20 +// Example:
  21 +// file, _ := os.Open("test/test.doc")
  22 +// defer file.Close()
  23 +// doc, err := mscfb.New(file)
  24 +// if err != nil {
  25 +// log.Fatal(err)
  26 +// }
  27 +// for entry, err := doc.Next(); err == nil; entry, err = doc.Next() {
  28 +// buf := make([]byte, 512)
  29 +// i, _ := entry.Read(buf)
  30 +// if i > 0 {
  31 +// fmt.Println(buf[:i])
  32 +// }
  33 +// fmt.Println(entry.Name)
  34 +// }
  35 +package mscfb
  36 +
  37 +import (
  38 + "encoding/binary"
  39 + "io"
  40 + "strconv"
  41 + "time"
  42 +)
  43 +
  44 +func fileOffset(ss, sn uint32) int64 {
  45 + return int64((sn + 1) * ss)
  46 +}
  47 +
  48 +const (
  49 + signature uint64 = 0xE11AB1A1E011CFD0
  50 + miniStreamSectorSize uint32 = 64
  51 + miniStreamCutoffSize int64 = 4096
  52 + dirEntrySize uint32 = 128 //128 bytes
  53 +)
  54 +
  55 +const (
  56 + maxRegSect uint32 = 0xFFFFFFFA // Maximum regular sector number
  57 + difatSect uint32 = 0xFFFFFFFC //Specifies a DIFAT sector in the FAT
  58 + fatSect uint32 = 0xFFFFFFFD // Specifies a FAT sector in the FAT
  59 + endOfChain uint32 = 0xFFFFFFFE // End of linked chain of sectors
  60 + freeSect uint32 = 0xFFFFFFFF // Speficies unallocated sector in the FAT, Mini FAT or DIFAT
  61 + maxRegStreamID uint32 = 0xFFFFFFFA // maximum regular stream ID
  62 + noStream uint32 = 0xFFFFFFFF // empty pointer
  63 +)
  64 +
  65 +const lenHeader int = 8 + 16 + 10 + 6 + 12 + 8 + 16 + 109*4
  66 +
  67 +type headerFields struct {
  68 + signature uint64
  69 + _ [16]byte //CLSID - ignore, must be null
  70 + minorVersion uint16 //Version number for non-breaking changes. This field SHOULD be set to 0x003E if the major version field is either 0x0003 or 0x0004.
  71 + majorVersion uint16 //Version number for breaking changes. This field MUST be set to either 0x0003 (version 3) or 0x0004 (version 4).
  72 + _ [2]byte //byte order - ignore, must be little endian
  73 + sectorSize uint16 //This field MUST be set to 0x0009, or 0x000c, depending on the Major Version field. This field specifies the sector size of the compound file as a power of 2. If Major Version is 3, then the Sector Shift MUST be 0x0009, specifying a sector size of 512 bytes. If Major Version is 4, then the Sector Shift MUST be 0x000C, specifying a sector size of 4096 bytes.
  74 + _ [2]byte // ministream sector size - ignore, must be 64 bytes
  75 + _ [6]byte // reserved - ignore, not used
  76 + numDirectorySectors uint32 //This integer field contains the count of the number of directory sectors in the compound file. If Major Version is 3, then the Number of Directory Sectors MUST be zero. This field is not supported for version 3 compound files.
  77 + numFatSectors uint32 //This integer field contains the count of the number of FAT sectors in the compound file.
  78 + directorySectorLoc uint32 //This integer field contains the starting sector number for the directory stream.
  79 + _ [4]byte // transaction - ignore, not used
  80 + _ [4]byte // mini stream size cutooff - ignore, must be 4096 bytes
  81 + miniFatSectorLoc uint32 //This integer field contains the starting sector number for the mini FAT.
  82 + numMiniFatSectors uint32 //This integer field contains the count of the number of mini FAT sectors in the compound file.
  83 + difatSectorLoc uint32 //This integer field contains the starting sector number for the DIFAT.
  84 + numDifatSectors uint32 //This integer field contains the count of the number of DIFAT sectors in the compound file.
  85 + initialDifats [109]uint32 //The first 109 difat sectors are included in the header
  86 +}
  87 +
  88 +func makeHeader(b []byte) *headerFields {
  89 + h := &headerFields{}
  90 + h.signature = binary.LittleEndian.Uint64(b[:8])
  91 + h.minorVersion = binary.LittleEndian.Uint16(b[24:26])
  92 + h.majorVersion = binary.LittleEndian.Uint16(b[26:28])
  93 + h.sectorSize = binary.LittleEndian.Uint16(b[30:32])
  94 + h.numDirectorySectors = binary.LittleEndian.Uint32(b[40:44])
  95 + h.numFatSectors = binary.LittleEndian.Uint32(b[44:48])
  96 + h.directorySectorLoc = binary.LittleEndian.Uint32(b[48:52])
  97 + h.miniFatSectorLoc = binary.LittleEndian.Uint32(b[60:64])
  98 + h.numMiniFatSectors = binary.LittleEndian.Uint32(b[64:68])
  99 + h.difatSectorLoc = binary.LittleEndian.Uint32(b[68:72])
  100 + h.numDifatSectors = binary.LittleEndian.Uint32(b[72:76])
  101 + var idx int
  102 + for i := 76; i < 512; i = i + 4 {
  103 + h.initialDifats[idx] = binary.LittleEndian.Uint32(b[i : i+4])
  104 + idx++
  105 + }
  106 + return h
  107 +}
  108 +
  109 +type header struct {
  110 + *headerFields
  111 + difats []uint32
  112 + miniFatLocs []uint32
  113 + miniStreamLocs []uint32 // chain of sectors containing the ministream
  114 +}
  115 +
  116 +func (r *Reader) setHeader() error {
  117 + buf, err := r.readAt(0, lenHeader)
  118 + if err != nil {
  119 + return err
  120 + }
  121 + r.header = &header{headerFields: makeHeader(buf)}
  122 + // sanity check - check signature
  123 + if r.header.signature != signature {
  124 + return Error{ErrFormat, "bad signature", int64(r.header.signature)}
  125 + }
  126 + // check for legal sector size
  127 + if r.header.sectorSize == 0x0009 || r.header.sectorSize == 0x000c {
  128 + r.sectorSize = uint32(1 << r.header.sectorSize)
  129 + } else {
  130 + return Error{ErrFormat, "illegal sector size", int64(r.header.sectorSize)}
  131 + }
  132 + // check for DIFAT overflow
  133 + if r.header.numDifatSectors > 0 {
  134 + sz := (r.sectorSize / 4) - 1
  135 + if int(r.header.numDifatSectors*sz+109) < 0 {
  136 + return Error{ErrFormat, "DIFAT int overflow", int64(r.header.numDifatSectors)}
  137 + }
  138 + if r.header.numDifatSectors*sz+109 > r.header.numFatSectors+sz {
  139 + return Error{ErrFormat, "num DIFATs exceeds FAT sectors", int64(r.header.numDifatSectors)}
  140 + }
  141 + }
  142 + // check for mini FAT overflow
  143 + if r.header.numMiniFatSectors > 0 {
  144 + if int(r.sectorSize/4*r.header.numMiniFatSectors) < 0 {
  145 + return Error{ErrFormat, "mini FAT int overflow", int64(r.header.numMiniFatSectors)}
  146 + }
  147 + if r.header.numMiniFatSectors > r.header.numFatSectors*(r.sectorSize/miniStreamSectorSize) {
  148 + return Error{ErrFormat, "num mini FATs exceeds FAT sectors", int64(r.header.numFatSectors)}
  149 + }
  150 + }
  151 + return nil
  152 +}
  153 +
  154 +func (r *Reader) setDifats() error {
  155 + r.header.difats = r.header.initialDifats[:]
  156 + // return early if no extra DIFAT sectors
  157 + if r.header.numDifatSectors == 0 {
  158 + return nil
  159 + }
  160 + sz := (r.sectorSize / 4) - 1
  161 + n := make([]uint32, 109, r.header.numDifatSectors*sz+109)
  162 + copy(n, r.header.difats)
  163 + r.header.difats = n
  164 + off := r.header.difatSectorLoc
  165 + for i := 0; i < int(r.header.numDifatSectors); i++ {
  166 + buf, err := r.readAt(fileOffset(r.sectorSize, off), int(r.sectorSize))
  167 + if err != nil {
  168 + return Error{ErrFormat, "error setting DIFAT(" + err.Error() + ")", int64(off)}
  169 + }
  170 + for j := 0; j < int(sz); j++ {
  171 + r.header.difats = append(r.header.difats, binary.LittleEndian.Uint32(buf[j*4:j*4+4]))
  172 + }
  173 + off = binary.LittleEndian.Uint32(buf[len(buf)-4:])
  174 + }
  175 + return nil
  176 +}
  177 +
  178 +// set the ministream FAT and sector slices in the header
  179 +func (r *Reader) setMiniStream() error {
  180 + // do nothing if there is no ministream
  181 + if r.direntries[0].startingSectorLoc == endOfChain || r.header.miniFatSectorLoc == endOfChain || r.header.numMiniFatSectors == 0 {
  182 + return nil
  183 + }
  184 + // build a slice of minifat sectors (akin to the DIFAT slice)
  185 + c := int(r.header.numMiniFatSectors)
  186 + r.header.miniFatLocs = make([]uint32, c)
  187 + r.header.miniFatLocs[0] = r.header.miniFatSectorLoc
  188 + for i := 1; i < c; i++ {
  189 + loc, err := r.findNext(r.header.miniFatLocs[i-1], false)
  190 + if err != nil {
  191 + return Error{ErrFormat, "setting mini stream (" + err.Error() + ")", int64(r.header.miniFatLocs[i-1])}
  192 + }
  193 + r.header.miniFatLocs[i] = loc
  194 + }
  195 + // build a slice of ministream sectors
  196 + c = int(r.sectorSize / 4 * r.header.numMiniFatSectors)
  197 + r.header.miniStreamLocs = make([]uint32, 0, c)
  198 + sn := r.direntries[0].startingSectorLoc
  199 + var err error
  200 + for sn != endOfChain {
  201 + r.header.miniStreamLocs = append(r.header.miniStreamLocs, sn)
  202 + sn, err = r.findNext(sn, false)
  203 + if err != nil {
  204 + return Error{ErrFormat, "setting mini stream (" + err.Error() + ")", int64(sn)}
  205 + }
  206 + }
  207 + return nil
  208 +}
  209 +
  210 +func (r *Reader) readAt(offset int64, length int) ([]byte, error) {
  211 + if r.slicer {
  212 + b, err := r.ra.(slicer).Slice(offset, length)
  213 + if err != nil {
  214 + return nil, Error{ErrRead, "slicer read error (" + err.Error() + ")", offset}
  215 + }
  216 + return b, nil
  217 + }
  218 + if length > len(r.buf) {
  219 + return nil, Error{ErrRead, "read length greater than read buffer", int64(length)}
  220 + }
  221 + if _, err := r.ra.ReadAt(r.buf[:length], offset); err != nil {
  222 + return nil, Error{ErrRead, err.Error(), offset}
  223 + }
  224 + return r.buf[:length], nil
  225 +}
  226 +
  227 +func (r *Reader) getOffset(sn uint32, mini bool) (int64, error) {
  228 + if mini {
  229 + num := r.sectorSize / 64
  230 + sec := int(sn / num)
  231 + if sec >= len(r.header.miniStreamLocs) {
  232 + return 0, Error{ErrRead, "minisector number is outside minisector range", int64(sec)}
  233 + }
  234 + dif := sn % num
  235 + return int64((r.header.miniStreamLocs[sec]+1)*r.sectorSize + dif*64), nil
  236 + }
  237 + return fileOffset(r.sectorSize, sn), nil
  238 +}
  239 +
  240 +// check the FAT sector for the next sector in a chain
  241 +func (r *Reader) findNext(sn uint32, mini bool) (uint32, error) {
  242 + entries := r.sectorSize / 4
  243 + index := int(sn / entries) // find position in DIFAT or minifat array
  244 + var sect uint32
  245 + if mini {
  246 + if index < 0 || index >= len(r.header.miniFatLocs) {
  247 + return 0, Error{ErrRead, "minisector index is outside miniFAT range", int64(index)}
  248 + }
  249 + sect = r.header.miniFatLocs[index]
  250 + } else {
  251 + if index < 0 || index >= len(r.header.difats) {
  252 + return 0, Error{ErrRead, "FAT index is outside DIFAT range", int64(index)}
  253 + }
  254 + sect = r.header.difats[index]
  255 + }
  256 + fatIndex := sn % entries // find position within FAT or MiniFAT sector
  257 + offset := fileOffset(r.sectorSize, sect) + int64(fatIndex*4)
  258 + buf, err := r.readAt(offset, 4)
  259 + if err != nil {
  260 + return 0, Error{ErrRead, "bad read finding next sector (" + err.Error() + ")", offset}
  261 + }
  262 + return binary.LittleEndian.Uint32(buf), nil
  263 +}
  264 +
  265 +// Reader provides sequential access to the contents of a MS compound file (MSCFB)
  266 +type Reader struct {
  267 + slicer bool
  268 + sectorSize uint32
  269 + buf []byte
  270 + header *header
  271 + File []*File // File is an ordered slice of final directory entries.
  272 + direntries []*File // unordered raw directory entries
  273 + entry int
  274 +
  275 + ra io.ReaderAt
  276 + wa io.WriterAt
  277 +}
  278 +
  279 +// New returns a MSCFB reader
  280 +func New(ra io.ReaderAt) (*Reader, error) {
  281 + r := &Reader{ra: ra}
  282 + if _, ok := ra.(slicer); ok {
  283 + r.slicer = true
  284 + } else {
  285 + r.buf = make([]byte, lenHeader)
  286 + }
  287 + if err := r.setHeader(); err != nil {
  288 + return nil, err
  289 + }
  290 + // resize the buffer to 4096 if sector size isn't 512
  291 + if !r.slicer && int(r.sectorSize) > len(r.buf) {
  292 + r.buf = make([]byte, r.sectorSize)
  293 + }
  294 + if err := r.setDifats(); err != nil {
  295 + return nil, err
  296 + }
  297 + if err := r.setDirEntries(); err != nil {
  298 + return nil, err
  299 + }
  300 + if err := r.setMiniStream(); err != nil {
  301 + return nil, err
  302 + }
  303 + if err := r.traverse(); err != nil {
  304 + return nil, err
  305 + }
  306 + return r, nil
  307 +}
  308 +
  309 +// ID returns the CLSID (class ID) field from the root directory entry
  310 +func (r *Reader) ID() string {
  311 + return r.File[0].ID()
  312 +}
  313 +
  314 +// Created returns the created field from the root directory entry
  315 +func (r *Reader) Created() time.Time {
  316 + return r.File[0].Created()
  317 +}
  318 +
  319 +// Modified returns the last modified field from the root directory entry
  320 +func (r *Reader) Modified() time.Time {
  321 + return r.File[0].Modified()
  322 +}
  323 +
  324 +// Next iterates to the next directory entry.
  325 +// This isn't necessarily an adjacent *File within the File slice, but is based on the Left Sibling, Right Sibling and Child information in directory entries.
  326 +func (r *Reader) Next() (*File, error) {
  327 + r.entry++
  328 + if r.entry >= len(r.File) {
  329 + return nil, io.EOF
  330 + }
  331 + return r.File[r.entry], nil
  332 +}
  333 +
  334 +// Read the current directory entry
  335 +func (r *Reader) Read(b []byte) (n int, err error) {
  336 + if r.entry >= len(r.File) {
  337 + return 0, io.EOF
  338 + }
  339 + return r.File[r.entry].Read(b)
  340 +}
  341 +
  342 +// Debug provides granular information from an mscfb file to assist with debugging
  343 +func (r *Reader) Debug() map[string][]uint32 {
  344 + ret := map[string][]uint32{
  345 + "sector size": []uint32{r.sectorSize},
  346 + "mini fat locs": r.header.miniFatLocs,
  347 + "mini stream locs": r.header.miniStreamLocs,
  348 + "directory sector": []uint32{r.header.directorySectorLoc},
  349 + "mini stream start/size": []uint32{r.File[0].startingSectorLoc, binary.LittleEndian.Uint32(r.File[0].streamSize[:])},
  350 + }
  351 + for f, err := r.Next(); err == nil; f, err = r.Next() {
  352 + ret[f.Name+" start/size"] = []uint32{f.startingSectorLoc, binary.LittleEndian.Uint32(f.streamSize[:])}
  353 + }
  354 + return ret
  355 +}
  356 +
  357 +const (
  358 + // ErrFormat reports issues with the MSCFB's header structures
  359 + ErrFormat = iota
  360 + // ErrRead reports issues attempting to read MSCFB streams
  361 + ErrRead
  362 + // ErrSeek reports seek issues
  363 + ErrSeek
  364 + // ErrWrite reports write issues
  365 + ErrWrite
  366 + // ErrTraverse reports issues attempting to traverse the child-parent-sibling relations
  367 + // between MSCFB storage objects
  368 + ErrTraverse
  369 +)
  370 +
  371 +type Error struct {
  372 + typ int
  373 + msg string
  374 + val int64
  375 +}
  376 +
  377 +func (e Error) Error() string {
  378 + return "mscfb: " + e.msg + "; " + strconv.FormatInt(e.val, 10)
  379 +}
  380 +
  381 +// Typ gives the type of MSCFB error
  382 +func (e Error) Typ() int {
  383 + return e.typ
  384 +}
  385 +
  386 +// Slicer interface avoids a copy by obtaining a byte slice directly from the underlying reader
  387 +type slicer interface {
  388 + Slice(offset int64, length int) ([]byte, error)
  389 +}
1 -// Copyright 2014 Richard Lehane. All rights reserved.  
2 -//  
3 -// Licensed under the Apache License, Version 2.0 (the "License");  
4 -// you may not use this file except in compliance with the License.  
5 -// You may obtain a copy of the License at  
6 -//  
7 -// http://www.apache.org/licenses/LICENSE-2.0  
8 -//  
9 -// Unless required by applicable law or agreed to in writing, software  
10 -// distributed under the License is distributed on an "AS IS" BASIS,  
11 -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
12 -// See the License for the specific language governing permissions and  
13 -// limitations under the License.  
14 -  
15 -package types  
16 -  
17 -import (  
18 - "encoding/binary"  
19 - "strconv"  
20 -)  
21 -  
22 -//The CURRENCY type specifies currency information. It is represented as an 8-byte integer, scaled by 10,000, to give a fixed-point number with 15 digits to the left of the decimal point, and four digits to the right. This representation provides a range of 922337203685477.5807 to –922337203685477.5808. For example, $5.25 is stored as the value 52500.  
23 -  
24 -type Currency int64  
25 -  
26 -func (c Currency) String() string {  
27 - return "$" + strconv.FormatFloat(float64(c)/10000, 'f', -1, 64)  
28 -}  
29 -  
30 -func (c Currency) Type() string {  
31 - return "Currency"  
32 -}  
33 -  
34 -func (c Currency) Length() int {  
35 - return 8  
36 -}  
37 -  
38 -func MakeCurrency(b []byte) (Type, error) {  
39 - if len(b) < 8 {  
40 - return Currency(0), ErrType  
41 - }  
42 - return Currency(binary.LittleEndian.Uint64(b[:8])), nil  
43 -} 1 +// Copyright 2014 Richard Lehane. All rights reserved.
  2 +//
  3 +// Licensed under the Apache License, Version 2.0 (the "License");
  4 +// you may not use this file except in compliance with the License.
  5 +// You may obtain a copy of the License at
  6 +//
  7 +// http://www.apache.org/licenses/LICENSE-2.0
  8 +//
  9 +// Unless required by applicable law or agreed to in writing, software
  10 +// distributed under the License is distributed on an "AS IS" BASIS,
  11 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +// See the License for the specific language governing permissions and
  13 +// limitations under the License.
  14 +
  15 +package types
  16 +
  17 +import (
  18 + "encoding/binary"
  19 + "strconv"
  20 +)
  21 +
  22 +//The CURRENCY type specifies currency information. It is represented as an 8-byte integer, scaled by 10,000, to give a fixed-point number with 15 digits to the left of the decimal point, and four digits to the right. This representation provides a range of 922337203685477.5807 to –922337203685477.5808. For example, $5.25 is stored as the value 52500.
  23 +
  24 +type Currency int64
  25 +
  26 +func (c Currency) String() string {
  27 + return "$" + strconv.FormatFloat(float64(c)/10000, 'f', -1, 64)
  28 +}
  29 +
  30 +func (c Currency) Type() string {
  31 + return "Currency"
  32 +}
  33 +
  34 +func (c Currency) Length() int {
  35 + return 8
  36 +}
  37 +
  38 +func MakeCurrency(b []byte) (Type, error) {
  39 + if len(b) < 8 {
  40 + return Currency(0), ErrType
  41 + }
  42 + return Currency(binary.LittleEndian.Uint64(b[:8])), nil
  43 +}
1 -// Copyright 2014 Richard Lehane. All rights reserved.  
2 -//  
3 -// Licensed under the Apache License, Version 2.0 (the "License");  
4 -// you may not use this file except in compliance with the License.  
5 -// You may obtain a copy of the License at  
6 -//  
7 -// http://www.apache.org/licenses/LICENSE-2.0  
8 -//  
9 -// Unless required by applicable law or agreed to in writing, software  
10 -// distributed under the License is distributed on an "AS IS" BASIS,  
11 -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
12 -// See the License for the specific language governing permissions and  
13 -// limitations under the License.  
14 -  
15 -package types  
16 -  
17 -import (  
18 - "encoding/binary"  
19 - "time"  
20 -)  
21 -  
22 -// http://msdn.microsoft.com/en-us/library/cc237601.aspx  
23 -type Date float64  
24 -  
25 -func (d Date) Time() time.Time {  
26 - start := time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)  
27 - day := float64(time.Hour * 24)  
28 - dur := time.Duration(day * float64(d))  
29 - return start.Add(dur)  
30 -}  
31 -  
32 -func (d Date) String() string {  
33 - return d.Time().String()  
34 -}  
35 -  
36 -func (d Date) Type() string {  
37 - return "Date"  
38 -}  
39 -  
40 -func (d Date) Length() int {  
41 - return 8  
42 -}  
43 -  
44 -func MakeDate(b []byte) (Type, error) {  
45 - if len(b) < 8 {  
46 - return Date(0), ErrType  
47 - }  
48 - return Date(binary.LittleEndian.Uint64(b[:8])), nil  
49 -} 1 +// Copyright 2014 Richard Lehane. All rights reserved.
  2 +//
  3 +// Licensed under the Apache License, Version 2.0 (the "License");
  4 +// you may not use this file except in compliance with the License.
  5 +// You may obtain a copy of the License at
  6 +//
  7 +// http://www.apache.org/licenses/LICENSE-2.0
  8 +//
  9 +// Unless required by applicable law or agreed to in writing, software
  10 +// distributed under the License is distributed on an "AS IS" BASIS,
  11 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +// See the License for the specific language governing permissions and
  13 +// limitations under the License.
  14 +
  15 +package types
  16 +
  17 +import (
  18 + "encoding/binary"
  19 + "time"
  20 +)
  21 +
  22 +// http://msdn.microsoft.com/en-us/library/cc237601.aspx
  23 +type Date float64
  24 +
  25 +func (d Date) Time() time.Time {
  26 + start := time.Date(1899, 12, 30, 0, 0, 0, 0, time.UTC)
  27 + day := float64(time.Hour * 24)
  28 + dur := time.Duration(day * float64(d))
  29 + return start.Add(dur)
  30 +}
  31 +
  32 +func (d Date) String() string {
  33 + return d.Time().String()
  34 +}
  35 +
  36 +func (d Date) Type() string {
  37 + return "Date"
  38 +}
  39 +
  40 +func (d Date) Length() int {
  41 + return 8
  42 +}
  43 +
  44 +func MakeDate(b []byte) (Type, error) {
  45 + if len(b) < 8 {
  46 + return Date(0), ErrType
  47 + }
  48 + return Date(binary.LittleEndian.Uint64(b[:8])), nil
  49 +}
1 -// Copyright 2014 Richard Lehane. All rights reserved.  
2 -//  
3 -// Licensed under the Apache License, Version 2.0 (the "License");  
4 -// you may not use this file except in compliance with the License.  
5 -// You may obtain a copy of the License at  
6 -//  
7 -// http://www.apache.org/licenses/LICENSE-2.0  
8 -//  
9 -// Unless required by applicable law or agreed to in writing, software  
10 -// distributed under the License is distributed on an "AS IS" BASIS,  
11 -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
12 -// See the License for the specific language governing permissions and  
13 -// limitations under the License.  
14 -  
15 -package types  
16 -  
17 -import (  
18 - "encoding/binary"  
19 - "math"  
20 - "math/big"  
21 -)  
22 -  
23 -// http://msdn.microsoft.com/en-us/library/cc237603.aspx  
24 -type Decimal struct {  
25 - res [2]byte  
26 - scale byte  
27 - sign byte  
28 - high32 uint32  
29 - low64 uint64  
30 -}  
31 -  
32 -func (d Decimal) Type() string {  
33 - return "Decimal"  
34 -}  
35 -  
36 -func (d Decimal) Length() int {  
37 - return 16  
38 -}  
39 -  
40 -func (d Decimal) String() string {  
41 - h, l, b := new(big.Int), new(big.Int), new(big.Int)  
42 - l.SetUint64(d.low64)  
43 - h.Lsh(big.NewInt(int64(d.high32)), 64)  
44 - b.Add(h, l)  
45 - q, f, r := new(big.Rat), new(big.Rat), new(big.Rat)  
46 - q.SetFloat64(math.Pow10(int(d.scale)))  
47 - r.Quo(f.SetInt(b), q)  
48 - if d.sign == 0x80 {  
49 - r.Neg(r)  
50 - }  
51 - return r.FloatString(20)  
52 -}  
53 -  
54 -func MakeDecimal(b []byte) (Type, error) {  
55 - if len(b) < 16 {  
56 - return Decimal{}, ErrType  
57 - }  
58 - return Decimal{  
59 - res: [2]byte{b[0], b[1]},  
60 - scale: b[2],  
61 - sign: b[3],  
62 - high32: binary.LittleEndian.Uint32(b[4:8]),  
63 - low64: binary.LittleEndian.Uint64(b[8:16]),  
64 - }, nil  
65 -} 1 +// Copyright 2014 Richard Lehane. All rights reserved.
  2 +//
  3 +// Licensed under the Apache License, Version 2.0 (the "License");
  4 +// you may not use this file except in compliance with the License.
  5 +// You may obtain a copy of the License at
  6 +//
  7 +// http://www.apache.org/licenses/LICENSE-2.0
  8 +//
  9 +// Unless required by applicable law or agreed to in writing, software
  10 +// distributed under the License is distributed on an "AS IS" BASIS,
  11 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +// See the License for the specific language governing permissions and
  13 +// limitations under the License.
  14 +
  15 +package types
  16 +
  17 +import (
  18 + "encoding/binary"
  19 + "math"
  20 + "math/big"
  21 +)
  22 +
  23 +// http://msdn.microsoft.com/en-us/library/cc237603.aspx
  24 +type Decimal struct {
  25 + res [2]byte
  26 + scale byte
  27 + sign byte
  28 + high32 uint32
  29 + low64 uint64
  30 +}
  31 +
  32 +func (d Decimal) Type() string {
  33 + return "Decimal"
  34 +}
  35 +
  36 +func (d Decimal) Length() int {
  37 + return 16
  38 +}
  39 +
  40 +func (d Decimal) String() string {
  41 + h, l, b := new(big.Int), new(big.Int), new(big.Int)
  42 + l.SetUint64(d.low64)
  43 + h.Lsh(big.NewInt(int64(d.high32)), 64)
  44 + b.Add(h, l)
  45 + q, f, r := new(big.Rat), new(big.Rat), new(big.Rat)
  46 + q.SetFloat64(math.Pow10(int(d.scale)))
  47 + r.Quo(f.SetInt(b), q)
  48 + if d.sign == 0x80 {
  49 + r.Neg(r)
  50 + }
  51 + return r.FloatString(20)
  52 +}
  53 +
  54 +func MakeDecimal(b []byte) (Type, error) {
  55 + if len(b) < 16 {
  56 + return Decimal{}, ErrType
  57 + }
  58 + return Decimal{
  59 + res: [2]byte{b[0], b[1]},
  60 + scale: b[2],
  61 + sign: b[3],
  62 + high32: binary.LittleEndian.Uint32(b[4:8]),
  63 + low64: binary.LittleEndian.Uint64(b[8:16]),
  64 + }, nil
  65 +}
1 -// Copyright 2014 Richard Lehane. All rights reserved.  
2 -//  
3 -// Licensed under the Apache License, Version 2.0 (the "License");  
4 -// you may not use this file except in compliance with the License.  
5 -// You may obtain a copy of the License at  
6 -//  
7 -// http://www.apache.org/licenses/LICENSE-2.0  
8 -//  
9 -// Unless required by applicable law or agreed to in writing, software  
10 -// distributed under the License is distributed on an "AS IS" BASIS,  
11 -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
12 -// See the License for the specific language governing permissions and  
13 -// limitations under the License.  
14 -  
15 -package types  
16 -  
17 -import (  
18 - "encoding/binary"  
19 - "time"  
20 -)  
21 -  
22 -// Win FILETIME type  
23 -// http://msdn.microsoft.com/en-us/library/cc230324.aspx  
24 -type FileTime struct {  
25 - Low uint32 // Windows FILETIME structure  
26 - High uint32 // Windows FILETIME structure  
27 -}  
28 -  
29 -const (  
30 - tick uint64 = 10000000  
31 - gregToUnix uint64 = 11644473600  
32 -)  
33 -  
34 -func winToUnix(low, high uint32) int64 {  
35 - gregTime := ((uint64(high) << 32) + uint64(low)) / tick  
36 - if gregTime < gregToUnix {  
37 - return 0  
38 - }  
39 - return int64(gregTime - gregToUnix)  
40 -}  
41 -  
42 -func (f FileTime) Time() time.Time {  
43 - return time.Unix(winToUnix(f.Low, f.High), 0)  
44 -}  
45 -  
46 -func (f FileTime) String() string {  
47 - return f.Time().String()  
48 -}  
49 -  
50 -func (f FileTime) Type() string {  
51 - return "FileTime"  
52 -}  
53 -  
54 -func (f FileTime) Length() int {  
55 - return 8  
56 -}  
57 -  
58 -func MakeFileTime(b []byte) (Type, error) {  
59 - if len(b) < 8 {  
60 - return FileTime{}, ErrType  
61 - }  
62 - return MustFileTime(b), nil  
63 -}  
64 -  
65 -func MustFileTime(b []byte) FileTime {  
66 - return FileTime{  
67 - Low: binary.LittleEndian.Uint32(b[:4]),  
68 - High: binary.LittleEndian.Uint32(b[4:8]),  
69 - }  
70 -} 1 +// Copyright 2014 Richard Lehane. All rights reserved.
  2 +//
  3 +// Licensed under the Apache License, Version 2.0 (the "License");
  4 +// you may not use this file except in compliance with the License.
  5 +// You may obtain a copy of the License at
  6 +//
  7 +// http://www.apache.org/licenses/LICENSE-2.0
  8 +//
  9 +// Unless required by applicable law or agreed to in writing, software
  10 +// distributed under the License is distributed on an "AS IS" BASIS,
  11 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +// See the License for the specific language governing permissions and
  13 +// limitations under the License.
  14 +
  15 +package types
  16 +
  17 +import (
  18 + "encoding/binary"
  19 + "time"
  20 +)
  21 +
  22 +// Win FILETIME type
  23 +// http://msdn.microsoft.com/en-us/library/cc230324.aspx
  24 +type FileTime struct {
  25 + Low uint32 // Windows FILETIME structure
  26 + High uint32 // Windows FILETIME structure
  27 +}
  28 +
  29 +const (
  30 + tick uint64 = 10000000
  31 + gregToUnix uint64 = 11644473600
  32 +)
  33 +
  34 +func winToUnix(low, high uint32) int64 {
  35 + gregTime := ((uint64(high) << 32) + uint64(low)) / tick
  36 + if gregTime < gregToUnix {
  37 + return 0
  38 + }
  39 + return int64(gregTime - gregToUnix)
  40 +}
  41 +
  42 +func (f FileTime) Time() time.Time {
  43 + return time.Unix(winToUnix(f.Low, f.High), 0)
  44 +}
  45 +
  46 +func (f FileTime) String() string {
  47 + return f.Time().String()
  48 +}
  49 +
  50 +func (f FileTime) Type() string {
  51 + return "FileTime"
  52 +}
  53 +
  54 +func (f FileTime) Length() int {
  55 + return 8
  56 +}
  57 +
  58 +func MakeFileTime(b []byte) (Type, error) {
  59 + if len(b) < 8 {
  60 + return FileTime{}, ErrType
  61 + }
  62 + return MustFileTime(b), nil
  63 +}
  64 +
  65 +func MustFileTime(b []byte) FileTime {
  66 + return FileTime{
  67 + Low: binary.LittleEndian.Uint32(b[:4]),
  68 + High: binary.LittleEndian.Uint32(b[4:8]),
  69 + }
  70 +}
1 -// Copyright 2014 Richard Lehane. All rights reserved.  
2 -//  
3 -// Licensed under the Apache License, Version 2.0 (the "License");  
4 -// you may not use this file except in compliance with the License.  
5 -// You may obtain a copy of the License at  
6 -//  
7 -// http://www.apache.org/licenses/LICENSE-2.0  
8 -//  
9 -// Unless required by applicable law or agreed to in writing, software  
10 -// distributed under the License is distributed on an "AS IS" BASIS,  
11 -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
12 -// See the License for the specific language governing permissions and  
13 -// limitations under the License.  
14 -  
15 -package types  
16 -  
17 -import (  
18 - "encoding/binary"  
19 - "encoding/hex"  
20 - "errors"  
21 - "strings"  
22 -)  
23 -  
24 -// Win GUID and UUID type  
25 -// http://msdn.microsoft.com/en-us/library/cc230326.aspx  
26 -type Guid struct {  
27 - DataA uint32  
28 - DataB uint16  
29 - DataC uint16  
30 - DataD [8]byte  
31 -}  
32 -  
33 -func (g Guid) String() string {  
34 - buf := make([]byte, 8)  
35 - binary.BigEndian.PutUint32(buf[:4], g.DataA)  
36 - binary.BigEndian.PutUint16(buf[4:6], g.DataB)  
37 - binary.BigEndian.PutUint16(buf[6:], g.DataC)  
38 - return strings.ToUpper("{" +  
39 - hex.EncodeToString(buf[:4]) +  
40 - "-" +  
41 - hex.EncodeToString(buf[4:6]) +  
42 - "-" +  
43 - hex.EncodeToString(buf[6:]) +  
44 - "-" +  
45 - hex.EncodeToString(g.DataD[:2]) +  
46 - "-" +  
47 - hex.EncodeToString(g.DataD[2:]) +  
48 - "}")  
49 -}  
50 -  
51 -func (g Guid) Type() string {  
52 - return "Guid"  
53 -}  
54 -  
55 -func (g Guid) Length() int {  
56 - return 16  
57 -}  
58 -  
59 -func GuidFromString(str string) (Guid, error) {  
60 - gerr := "Invalid GUID: expecting in format {F29F85E0-4FF9-1068-AB91-08002B27B3D9}, got " + str  
61 - if len(str) != 38 {  
62 - return Guid{}, errors.New(gerr + "; bad length, should be 38 chars")  
63 - }  
64 - trimmed := strings.Trim(str, "{}")  
65 - parts := strings.Split(trimmed, "-")  
66 - if len(parts) != 5 {  
67 - return Guid{}, errors.New(gerr + "; expecting should five '-' separators")  
68 - }  
69 - buf, err := hex.DecodeString(strings.Join(parts, ""))  
70 - if err != nil {  
71 - return Guid{}, errors.New(gerr + "; error decoding hex: " + err.Error())  
72 - }  
73 - return makeGuid(buf, binary.BigEndian), nil  
74 -}  
75 -  
76 -func MakeGuid(b []byte) (Type, error) {  
77 - if len(b) < 16 {  
78 - return Guid{}, ErrType  
79 - }  
80 - return makeGuid(b, binary.LittleEndian), nil  
81 -}  
82 -  
83 -func makeGuid(b []byte, order binary.ByteOrder) Guid {  
84 - g := Guid{  
85 - DataA: order.Uint32(b[:4]),  
86 - DataB: order.Uint16(b[4:6]),  
87 - DataC: order.Uint16(b[6:8]),  
88 - DataD: [8]byte{},  
89 - }  
90 - copy(g.DataD[:], b[8:])  
91 - return g  
92 -}  
93 -  
94 -func MustGuidFromString(str string) Guid {  
95 - g, err := GuidFromString(str)  
96 - if err != nil {  
97 - panic(err)  
98 - }  
99 - return g  
100 -}  
101 -  
102 -func MustGuid(b []byte) Guid {  
103 - return makeGuid(b, binary.LittleEndian)  
104 -}  
105 -  
106 -func GuidFromName(n string) (Guid, error) {  
107 - n = strings.ToLower(n)  
108 - buf, err := charConvert([]byte(n))  
109 - if err != nil {  
110 - return Guid{}, err  
111 - }  
112 - return makeGuid(buf, binary.LittleEndian), nil  
113 -}  
114 -  
115 -func charConvert(in []byte) ([]byte, error) {  
116 - if len(in) != 26 {  
117 - return nil, errors.New("invalid GUID: expecting 26 characters")  
118 - }  
119 - out := make([]byte, 16)  
120 - var idx, shift uint  
121 - var b byte  
122 - for _, v := range in {  
123 - this, ok := characterMapping[v]  
124 - if !ok {  
125 - return nil, errors.New("invalid Guid: invalid character")  
126 - }  
127 - b = b | this<<shift  
128 - if shift >= 3 {  
129 - out[idx] = b  
130 - idx++  
131 - b = this >> (8 - shift) // write any remainder back to b, or 0 if shift is 3  
132 - }  
133 - shift = shift + 5  
134 - if shift > 7 {  
135 - shift = shift - 8  
136 - }  
137 - }  
138 - return out, nil  
139 -}  
140 -  
141 -const (  
142 - charA byte = iota  
143 - charB  
144 - charC  
145 - charD  
146 - charE  
147 - charF  
148 - charG  
149 - charH  
150 - charI  
151 - charJ  
152 - charK  
153 - charL  
154 - charM  
155 - charN  
156 - charO  
157 - charP  
158 - charQ  
159 - charR  
160 - charS  
161 - charT  
162 - charU  
163 - charV  
164 - charW  
165 - charX  
166 - charY  
167 - charZ  
168 - char0  
169 - char1  
170 - char2  
171 - char3  
172 - char4  
173 - char5  
174 -)  
175 -  
176 -var characterMapping = map[byte]byte{  
177 - 'a': charA,  
178 - 'b': charB,  
179 - 'c': charC,  
180 - 'd': charD,  
181 - 'e': charE,  
182 - 'f': charF,  
183 - 'g': charG,  
184 - 'h': charH,  
185 - 'i': charI,  
186 - 'j': charJ,  
187 - 'k': charK,  
188 - 'l': charL,  
189 - 'm': charM,  
190 - 'n': charN,  
191 - 'o': charO,  
192 - 'p': charP,  
193 - 'q': charQ,  
194 - 'r': charR,  
195 - 's': charS,  
196 - 't': charT,  
197 - 'u': charU,  
198 - 'v': charV,  
199 - 'w': charW,  
200 - 'x': charX,  
201 - 'y': charY,  
202 - 'z': charZ,  
203 - '0': char0,  
204 - '1': char1,  
205 - '2': char2,  
206 - '3': char3,  
207 - '4': char4,  
208 - '5': char5,  
209 -} 1 +// Copyright 2014 Richard Lehane. All rights reserved.
  2 +//
  3 +// Licensed under the Apache License, Version 2.0 (the "License");
  4 +// you may not use this file except in compliance with the License.
  5 +// You may obtain a copy of the License at
  6 +//
  7 +// http://www.apache.org/licenses/LICENSE-2.0
  8 +//
  9 +// Unless required by applicable law or agreed to in writing, software
  10 +// distributed under the License is distributed on an "AS IS" BASIS,
  11 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +// See the License for the specific language governing permissions and
  13 +// limitations under the License.
  14 +
  15 +package types
  16 +
  17 +import (
  18 + "encoding/binary"
  19 + "encoding/hex"
  20 + "errors"
  21 + "strings"
  22 +)
  23 +
  24 +// Win GUID and UUID type
  25 +// http://msdn.microsoft.com/en-us/library/cc230326.aspx
  26 +type Guid struct {
  27 + DataA uint32
  28 + DataB uint16
  29 + DataC uint16
  30 + DataD [8]byte
  31 +}
  32 +
  33 +func (g Guid) String() string {
  34 + buf := make([]byte, 8)
  35 + binary.BigEndian.PutUint32(buf[:4], g.DataA)
  36 + binary.BigEndian.PutUint16(buf[4:6], g.DataB)
  37 + binary.BigEndian.PutUint16(buf[6:], g.DataC)
  38 + return strings.ToUpper("{" +
  39 + hex.EncodeToString(buf[:4]) +
  40 + "-" +
  41 + hex.EncodeToString(buf[4:6]) +
  42 + "-" +
  43 + hex.EncodeToString(buf[6:]) +
  44 + "-" +
  45 + hex.EncodeToString(g.DataD[:2]) +
  46 + "-" +
  47 + hex.EncodeToString(g.DataD[2:]) +
  48 + "}")
  49 +}
  50 +
  51 +func (g Guid) Type() string {
  52 + return "Guid"
  53 +}
  54 +
  55 +func (g Guid) Length() int {
  56 + return 16
  57 +}
  58 +
  59 +func GuidFromString(str string) (Guid, error) {
  60 + gerr := "Invalid GUID: expecting in format {F29F85E0-4FF9-1068-AB91-08002B27B3D9}, got " + str
  61 + if len(str) != 38 {
  62 + return Guid{}, errors.New(gerr + "; bad length, should be 38 chars")
  63 + }
  64 + trimmed := strings.Trim(str, "{}")
  65 + parts := strings.Split(trimmed, "-")
  66 + if len(parts) != 5 {
  67 + return Guid{}, errors.New(gerr + "; expecting should five '-' separators")
  68 + }
  69 + buf, err := hex.DecodeString(strings.Join(parts, ""))
  70 + if err != nil {
  71 + return Guid{}, errors.New(gerr + "; error decoding hex: " + err.Error())
  72 + }
  73 + return makeGuid(buf, binary.BigEndian), nil
  74 +}
  75 +
  76 +func MakeGuid(b []byte) (Type, error) {
  77 + if len(b) < 16 {
  78 + return Guid{}, ErrType
  79 + }
  80 + return makeGuid(b, binary.LittleEndian), nil
  81 +}
  82 +
  83 +func makeGuid(b []byte, order binary.ByteOrder) Guid {
  84 + g := Guid{
  85 + DataA: order.Uint32(b[:4]),
  86 + DataB: order.Uint16(b[4:6]),
  87 + DataC: order.Uint16(b[6:8]),
  88 + DataD: [8]byte{},
  89 + }
  90 + copy(g.DataD[:], b[8:])
  91 + return g
  92 +}
  93 +
  94 +func MustGuidFromString(str string) Guid {
  95 + g, err := GuidFromString(str)
  96 + if err != nil {
  97 + panic(err)
  98 + }
  99 + return g
  100 +}
  101 +
  102 +func MustGuid(b []byte) Guid {
  103 + return makeGuid(b, binary.LittleEndian)
  104 +}
  105 +
  106 +func GuidFromName(n string) (Guid, error) {
  107 + n = strings.ToLower(n)
  108 + buf, err := charConvert([]byte(n))
  109 + if err != nil {
  110 + return Guid{}, err
  111 + }
  112 + return makeGuid(buf, binary.LittleEndian), nil
  113 +}
  114 +
  115 +func charConvert(in []byte) ([]byte, error) {
  116 + if len(in) != 26 {
  117 + return nil, errors.New("invalid GUID: expecting 26 characters")
  118 + }
  119 + out := make([]byte, 16)
  120 + var idx, shift uint
  121 + var b byte
  122 + for _, v := range in {
  123 + this, ok := characterMapping[v]
  124 + if !ok {
  125 + return nil, errors.New("invalid Guid: invalid character")
  126 + }
  127 + b = b | this<<shift
  128 + if shift >= 3 {
  129 + out[idx] = b
  130 + idx++
  131 + b = this >> (8 - shift) // write any remainder back to b, or 0 if shift is 3
  132 + }
  133 + shift = shift + 5
  134 + if shift > 7 {
  135 + shift = shift - 8
  136 + }
  137 + }
  138 + return out, nil
  139 +}
  140 +
  141 +const (
  142 + charA byte = iota
  143 + charB
  144 + charC
  145 + charD
  146 + charE
  147 + charF
  148 + charG
  149 + charH
  150 + charI
  151 + charJ
  152 + charK
  153 + charL
  154 + charM
  155 + charN
  156 + charO
  157 + charP
  158 + charQ
  159 + charR
  160 + charS
  161 + charT
  162 + charU
  163 + charV
  164 + charW
  165 + charX
  166 + charY
  167 + charZ
  168 + char0
  169 + char1
  170 + char2
  171 + char3
  172 + char4
  173 + char5
  174 +)
  175 +
  176 +var characterMapping = map[byte]byte{
  177 + 'a': charA,
  178 + 'b': charB,
  179 + 'c': charC,
  180 + 'd': charD,
  181 + 'e': charE,
  182 + 'f': charF,
  183 + 'g': charG,
  184 + 'h': charH,
  185 + 'i': charI,
  186 + 'j': charJ,
  187 + 'k': charK,
  188 + 'l': charL,
  189 + 'm': charM,
  190 + 'n': charN,
  191 + 'o': charO,
  192 + 'p': charP,
  193 + 'q': charQ,
  194 + 'r': charR,
  195 + 's': charS,
  196 + 't': charT,
  197 + 'u': charU,
  198 + 'v': charV,
  199 + 'w': charW,
  200 + 'x': charX,
  201 + 'y': charY,
  202 + 'z': charZ,
  203 + '0': char0,
  204 + '1': char1,
  205 + '2': char2,
  206 + '3': char3,
  207 + '4': char4,
  208 + '5': char5,
  209 +}
1 -// Copyright 2014 Richard Lehane. All rights reserved.  
2 -//  
3 -// Licensed under the Apache License, Version 2.0 (the "License");  
4 -// you may not use this file except in compliance with the License.  
5 -// You may obtain a copy of the License at  
6 -//  
7 -// http://www.apache.org/licenses/LICENSE-2.0  
8 -//  
9 -// Unless required by applicable law or agreed to in writing, software  
10 -// distributed under the License is distributed on an "AS IS" BASIS,  
11 -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
12 -// See the License for the specific language governing permissions and  
13 -// limitations under the License.  
14 -  
15 -package types  
16 -  
17 -import (  
18 - "encoding/binary"  
19 - "strings"  
20 - "unicode/utf16"  
21 -)  
22 -  
23 -func nullTerminated(s string) string {  
24 - return s[:strings.Index(s, "\x00")]  
25 -}  
26 -  
27 -type UnicodeString []uint16  
28 -  
29 -func (s UnicodeString) Type() string {  
30 - return "UnicodeString"  
31 -}  
32 -  
33 -func (s UnicodeString) Length() int {  
34 - return 4 + len(s)*2  
35 -}  
36 -  
37 -func (s UnicodeString) String() string {  
38 - if len(s) == 0 {  
39 - return ""  
40 - }  
41 - return nullTerminated(string(utf16.Decode(s)))  
42 -}  
43 -  
44 -func MakeUnicode(b []byte) (Type, error) {  
45 - if len(b) < 4 {  
46 - return UnicodeString{}, ErrType  
47 - }  
48 - l := int(binary.LittleEndian.Uint32(b[:4]))  
49 - if l == 0 {  
50 - return UnicodeString{}, nil  
51 - }  
52 - if len(b) < l*2+4 {  
53 - return UnicodeString{}, ErrType  
54 - }  
55 - s := make(UnicodeString, l)  
56 - for i := range s {  
57 - start := i*2 + 4  
58 - s[i] = binary.LittleEndian.Uint16(b[start : start+2])  
59 - }  
60 - return s, nil  
61 -}  
62 -  
63 -type CodeString struct {  
64 - id CodePageID  
65 - Chars []byte  
66 -}  
67 -  
68 -func (s *CodeString) SetId(i CodePageID) {  
69 - s.id = i  
70 -}  
71 -  
72 -func (s *CodeString) Encoding() string {  
73 - return CodePageIDs[s.id]  
74 -}  
75 -  
76 -func (s *CodeString) Type() string {  
77 - return "CodeString"  
78 -}  
79 -  
80 -func (s *CodeString) Length() int {  
81 - return 4 + len(s.Chars)  
82 -}  
83 -  
84 -func (s *CodeString) String() string {  
85 - if len(s.Chars) == 0 {  
86 - return ""  
87 - }  
88 - if s.id == 1200 {  
89 - chars := make([]uint16, len(s.Chars)/2)  
90 - for i := range chars {  
91 - chars[i] = binary.LittleEndian.Uint16(s.Chars[i*2 : i*2+2])  
92 - }  
93 - return nullTerminated(string(utf16.Decode(chars)))  
94 - }  
95 - return nullTerminated(string(s.Chars))  
96 -}  
97 -  
98 -func MakeCodeString(b []byte) (Type, error) {  
99 - if len(b) < 4 {  
100 - return &CodeString{}, ErrType  
101 - }  
102 - s := &CodeString{}  
103 - l := int(binary.LittleEndian.Uint32(b[:4]))  
104 - if l == 0 {  
105 - return s, nil  
106 - }  
107 - if len(b) < l+4 {  
108 - return s, ErrType  
109 - }  
110 - s.Chars = make([]byte, l)  
111 - copy(s.Chars, b[4:l+4])  
112 - return s, nil  
113 -}  
114 -  
115 -type CodePageID uint16  
116 -  
117 -var CodePageIDs map[CodePageID]string = map[CodePageID]string{  
118 - 37: "IBM037 - IBM EBCDIC US-Canada",  
119 - 437: "IBM437 - OEM United States",  
120 - 500: "IBM500 - IBM EBCDIC International",  
121 - 708: "ASMO-708 - Arabic (ASMO 708)",  
122 - 709: "Arabic (ASMO-449+, BCON V4)",  
123 - 710: "Arabic - Transparent Arabic",  
124 - 720: "DOS-720 - Arabic (Transparent ASMO); Arabic (DOS)",  
125 - 737: "ibm737 - OEM Greek (formerly 437G); Greek (DOS)",  
126 - 775: "ibm775 - OEM Baltic; Baltic (DOS)",  
127 - 850: "ibm850 - OEM Multilingual Latin 1; Western European (DOS)",  
128 - 852: "ibm852 - OEM Latin 2; Central European (DOS)",  
129 - 855: "IBM855 - OEM Cyrillic (primarily Russian)",  
130 - 857: "ibm857 - OEM Turkish; Turkish (DOS)",  
131 - 858: "IBM00858 - OEM Multilingual Latin 1 + Euro symbol",  
132 - 860: "IBM860 - OEM Portuguese; Portuguese (DOS)",  
133 - 861: "ibm861 - OEM Icelandic; Icelandic (DOS)",  
134 - 862: "DOS-862 - OEM Hebrew; Hebrew (DOS)",  
135 - 863: "IBM863 - OEM French Canadian; French Canadian (DOS)",  
136 - 864: "IBM864 - OEM Arabic; Arabic (864)",  
137 - 865: "IBM865 - OEM Nordic; Nordic (DOS)",  
138 - 866: "cp866 - OEM Russian; Cyrillic (DOS)",  
139 - 869: "ibm869 - OEM Modern Greek; Greek, Modern (DOS)",  
140 - 870: "IBM870 - IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2",  
141 - 874: "windows-874 - ANSI/OEM Thai (ISO 8859-11); Thai (Windows)",  
142 - 875: "cp875 - IBM EBCDIC Greek Modern",  
143 - 932: "shift_jis - ANSI/OEM Japanese; Japanese (Shift-JIS)",  
144 - 936: "gb2312 - ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312)",  
145 - 949: "ks_c_5601-1987 - ANSI/OEM Korean (Unified Hangul Code)",  
146 - 950: "big5 - ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5)",  
147 - 1026: "IBM1026 - IBM EBCDIC Turkish (Latin 5)",  
148 - 1047: "IBM01047 - BM EBCDIC Latin 1/Open System",  
149 - 1140: "IBM01140 - IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro)",  
150 - 1141: "IBM01141 - IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro)",  
151 - 1142: "IBM01142 - IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro)",  
152 - 1143: "IBM01143 - IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro)",  
153 - 1144: "IBM01144 - IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro)",  
154 - 1145: "IBM01145 - IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro)",  
155 - 1146: "IBM01146 - IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro)",  
156 - 1147: "IBM01147 - IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro)",  
157 - 1148: "IBM01148 - IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro)",  
158 - 1149: "IBM01149 - IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro)",  
159 - 1200: "utf-16 - Unicode UTF-16, little endian byte order (BMP of ISO 10646); available only to managed applications",  
160 - 1201: "unicodeFFFE - Unicode UTF-16, big endian byte order; available only to managed applications",  
161 - 1250: "windows-1250 - ANSI Central European; Central European (Windows)",  
162 - 1251: "windows-1251 - ANSI Cyrillic; Cyrillic (Windows)",  
163 - 1252: "windows-1252 - ANSI Latin 1; Western European (Windows)",  
164 - 1253: "windows-1253 - ANSI Greek; Greek (Windows)",  
165 - 1254: "windows-1254 - ANSI Turkish; Turkish (Windows)",  
166 - 1255: "windows-1255 - ANSI Hebrew; Hebrew (Windows)",  
167 - 1256: "windows-1256 - ANSI Arabic; Arabic (Windows)",  
168 - 1257: "windows-1257 - ANSI Baltic; Baltic (Windows)",  
169 - 1258: "windows-1258 - ANSI/OEM Vietnamese; Vietnamese (Windows)",  
170 - 1361: "Johab - Korean (Johab)",  
171 - 10000: "macintosh - MAC Roman; Western European (Mac)",  
172 - 10001: "x-mac-japanese - Japanese (Mac)",  
173 - 10002: "x-mac-chinesetrad - MAC Traditional Chinese (Big5); Chinese Traditional (Mac)",  
174 - 10003: "x-mac-korean - Korean (Mac)",  
175 - 10004: "x-mac-arabic - Arabic (Mac)",  
176 - 10005: "x-mac-hebrew - Hebrew (Mac)",  
177 - 10006: "x-mac-greek - Greek (Mac)",  
178 - 10007: "x-mac-cyrillic - Cyrillic (Mac)",  
179 - 10008: "x-mac-chinesesimp - MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac)",  
180 - 10010: "x-mac-romanian - Romanian (Mac)",  
181 - 10017: "x-mac-ukrainian - Ukrainian (Mac)",  
182 - 10021: "x-mac-thai - Thai (Mac)",  
183 - 10029: "x-mac-ce - MAC Latin 2; Central European (Mac)",  
184 - 10079: "x-mac-icelandic - Icelandic (Mac)",  
185 - 10081: "x-mac-turkish - Turkish (Mac)",  
186 - 10082: "x-mac-croatian - Croatian (Mac)",  
187 - 12000: "utf-32 - Unicode UTF-32, little endian byte order; available only to managed applications",  
188 - 12001: "utf-32BE - Unicode UTF-32, big endian byte order; available only to managed applications",  
189 - 20000: "x-Chinese_CNS - CNS Taiwan; Chinese Traditional (CNS)",  
190 - 20001: "x-cp20001 - TCA Taiwan",  
191 - 20002: "x_Chinese-Eten - Eten Taiwan; Chinese Traditional (Eten)",  
192 - 20003: "x-cp20003 - IBM5550 Taiwan",  
193 - 20004: "x-cp20004 - TeleText Taiwan",  
194 - 20005: "x-cp20005 - Wang Taiwan",  
195 - 20105: "x-IA5 - IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5)",  
196 - 20106: "x-IA5-German - IA5 German (7-bit)",  
197 - 20107: "x-IA5-Swedish - IA5 Swedish (7-bit)",  
198 - 20108: "x-IA5-Norwegian - IA5 Norwegian (7-bit)",  
199 - 20127: "us-ascii - US-ASCII (7-bit)",  
200 - 20261: "x-cp20261 - T.61",  
201 - 20269: "x-cp20269 - ISO 6937 Non-Spacing Accent",  
202 - 20273: "IBM273 - IBM EBCDIC Germany",  
203 - 20277: "IBM277 - IBM EBCDIC Denmark-Norway",  
204 - 20278: "IBM278 - IBM EBCDIC Finland-Sweden",  
205 - 20280: "IBM280 - IBM EBCDIC Italy",  
206 - 20284: "IBM284 - IBM EBCDIC Latin America-Spain",  
207 - 20285: "IBM285 - IBM EBCDIC United Kingdom",  
208 - 20290: "IBM290 - IBM EBCDIC Japanese Katakana Extended",  
209 - 20297: "IBM297 - IBM EBCDIC France",  
210 - 20420: "IBM420 - IBM EBCDIC Arabic",  
211 - 20423: "IBM423 - IBM EBCDIC Greek",  
212 - 20424: "IBM424 - IBM EBCDIC Hebrew",  
213 - 20833: "x-EBCDIC-KoreanExtended - IBM EBCDIC Korean Extended",  
214 - 20838: "IBM-Thai - IBM EBCDIC Thai",  
215 - 20866: "koi8-r - Russian (KOI8-R); Cyrillic (KOI8-R)",  
216 - 20871: "IBM871 - IBM EBCDIC Icelandic",  
217 - 20880: "IBM880 - IBM EBCDIC Cyrillic Russian",  
218 - 20905: "IBM905 - IBM EBCDIC Turkish",  
219 - 20924: "IBM00924 - IBM EBCDIC Latin 1/Open System (1047 + Euro symbol)",  
220 - 20932: "EUC-JP - Japanese (JIS 0208-1990 and 0212-1990)",  
221 - 20936: "x-cp20936 - Simplified Chinese (GB2312); Chinese Simplified (GB2312-80)",  
222 - 20949: "x-cp20949 - Korean Wansung",  
223 - 21025: "cp1025 - IBM EBCDIC Cyrillic Serbian-Bulgarian",  
224 - 21027: "(deprecated)",  
225 - 21866: "koi8-u - Ukrainian (KOI8-U); Cyrillic (KOI8-U)",  
226 - 28591: "iso-8859-1 - ISO 8859-1 Latin 1; Western European (ISO)",  
227 - 28592: "iso-8859-2 - ISO 8859-2 Central European; Central European (ISO)",  
228 - 28593: "iso-8859-3 - ISO 8859-3 Latin 3",  
229 - 28594: "iso-8859-4 - ISO 8859-4 Baltic",  
230 - 28595: "iso-8859-5 - ISO 8859-5 Cyrillic",  
231 - 28596: "iso-8859-6 - ISO 8859-6 Arabic",  
232 - 28597: "iso-8859-7 - ISO 8859-7 Greek",  
233 - 28598: "iso-8859-8 - ISO 8859-8 Hebrew; Hebrew (ISO-Visual)",  
234 - 28599: "iso-8859-9 - ISO 8859-9 Turkish",  
235 - 28603: "iso-8859-13 - ISO 8859-13 Estonian",  
236 - 28605: "iso-8859-15 - ISO 8859-15 Latin 9",  
237 - 29001: "x-Europa - Europa 3",  
238 - 38598: "iso-8859-8-i - ISO 8859-8 Hebrew; Hebrew (ISO-Logical)",  
239 - 50220: "iso-2022-jp - ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS)",  
240 - 50221: "csISO2022JP - ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana)",  
241 - 50222: "iso-2022-jp - ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI)",  
242 - 50225: "iso-2022-kr - ISO 2022 Korean",  
243 - 50227: "x-cp50227 - ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022)",  
244 - 50229: "ISO 2022 - Traditional Chinese",  
245 - 50930: "EBCDIC - Japanese (Katakana) Extended",  
246 - 50931: "EBCDIC - US-Canada and Japanese",  
247 - 50933: "EBCDIC - Korean Extended and Korean",  
248 - 50935: "EBCDIC - Simplified Chinese Extended and Simplified Chinese",  
249 - 50936: "EBCDIC - Simplified Chinese",  
250 - 50937: "EBCDIC - US-Canada and Traditional Chinese",  
251 - 50939: "EBCDIC - Japanese (Latin) Extended and Japanese",  
252 - 51932: "euc-jp - EUC Japanese",  
253 - 51936: "EUC-CN - EUC Simplified Chinese; Chinese Simplified (EUC)",  
254 - 51949: "euc-kr - EUC Korean",  
255 - 51950: "EUC - Traditional Chinese",  
256 - 52936: "hz-gb-2312 - HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ)",  
257 - 54936: "GB18030 - Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030)",  
258 - 57002: "x-iscii-de - ISCII Devanagari",  
259 - 57003: "x-iscii-be - ISCII Bengali",  
260 - 57004: "x-iscii-ta - ISCII Tamil",  
261 - 57005: "x-iscii-te - ISCII Telugu",  
262 - 57006: "x-iscii-as - ISCII Assamese",  
263 - 57007: "x-iscii-or - ISCII Oriya",  
264 - 57008: "x-iscii-ka - ISCII Kannada",  
265 - 57009: "x-iscii-ma - ISCII Malayalam",  
266 - 57010: "x-iscii-gu - ISCII Gujarati",  
267 - 57011: "x-iscii-pa - ISCII Punjabi",  
268 - 65000: "utf-7 - Unicode (UTF-7)",  
269 - 65001: "utf-8 - Unicode (UTF-8)",  
270 -} 1 +// Copyright 2014 Richard Lehane. All rights reserved.
  2 +//
  3 +// Licensed under the Apache License, Version 2.0 (the "License");
  4 +// you may not use this file except in compliance with the License.
  5 +// You may obtain a copy of the License at
  6 +//
  7 +// http://www.apache.org/licenses/LICENSE-2.0
  8 +//
  9 +// Unless required by applicable law or agreed to in writing, software
  10 +// distributed under the License is distributed on an "AS IS" BASIS,
  11 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +// See the License for the specific language governing permissions and
  13 +// limitations under the License.
  14 +
  15 +package types
  16 +
  17 +import (
  18 + "encoding/binary"
  19 + "strings"
  20 + "unicode/utf16"
  21 +)
  22 +
  23 +func nullTerminated(s string) string {
  24 + return s[:strings.Index(s, "\x00")]
  25 +}
  26 +
  27 +type UnicodeString []uint16
  28 +
  29 +func (s UnicodeString) Type() string {
  30 + return "UnicodeString"
  31 +}
  32 +
  33 +func (s UnicodeString) Length() int {
  34 + return 4 + len(s)*2
  35 +}
  36 +
  37 +func (s UnicodeString) String() string {
  38 + if len(s) == 0 {
  39 + return ""
  40 + }
  41 + return nullTerminated(string(utf16.Decode(s)))
  42 +}
  43 +
  44 +func MakeUnicode(b []byte) (Type, error) {
  45 + if len(b) < 4 {
  46 + return UnicodeString{}, ErrType
  47 + }
  48 + l := int(binary.LittleEndian.Uint32(b[:4]))
  49 + if l == 0 {
  50 + return UnicodeString{}, nil
  51 + }
  52 + if len(b) < l*2+4 {
  53 + return UnicodeString{}, ErrType
  54 + }
  55 + s := make(UnicodeString, l)
  56 + for i := range s {
  57 + start := i*2 + 4
  58 + s[i] = binary.LittleEndian.Uint16(b[start : start+2])
  59 + }
  60 + return s, nil
  61 +}
  62 +
  63 +type CodeString struct {
  64 + id CodePageID
  65 + Chars []byte
  66 +}
  67 +
  68 +func (s *CodeString) SetId(i CodePageID) {
  69 + s.id = i
  70 +}
  71 +
  72 +func (s *CodeString) Encoding() string {
  73 + return CodePageIDs[s.id]
  74 +}
  75 +
  76 +func (s *CodeString) Type() string {
  77 + return "CodeString"
  78 +}
  79 +
  80 +func (s *CodeString) Length() int {
  81 + return 4 + len(s.Chars)
  82 +}
  83 +
  84 +func (s *CodeString) String() string {
  85 + if len(s.Chars) == 0 {
  86 + return ""
  87 + }
  88 + if s.id == 1200 {
  89 + chars := make([]uint16, len(s.Chars)/2)
  90 + for i := range chars {
  91 + chars[i] = binary.LittleEndian.Uint16(s.Chars[i*2 : i*2+2])
  92 + }
  93 + return nullTerminated(string(utf16.Decode(chars)))
  94 + }
  95 + return nullTerminated(string(s.Chars))
  96 +}
  97 +
  98 +func MakeCodeString(b []byte) (Type, error) {
  99 + if len(b) < 4 {
  100 + return &CodeString{}, ErrType
  101 + }
  102 + s := &CodeString{}
  103 + l := int(binary.LittleEndian.Uint32(b[:4]))
  104 + if l == 0 {
  105 + return s, nil
  106 + }
  107 + if len(b) < l+4 {
  108 + return s, ErrType
  109 + }
  110 + s.Chars = make([]byte, l)
  111 + copy(s.Chars, b[4:l+4])
  112 + return s, nil
  113 +}
  114 +
  115 +type CodePageID uint16
  116 +
  117 +var CodePageIDs map[CodePageID]string = map[CodePageID]string{
  118 + 37: "IBM037 - IBM EBCDIC US-Canada",
  119 + 437: "IBM437 - OEM United States",
  120 + 500: "IBM500 - IBM EBCDIC International",
  121 + 708: "ASMO-708 - Arabic (ASMO 708)",
  122 + 709: "Arabic (ASMO-449+, BCON V4)",
  123 + 710: "Arabic - Transparent Arabic",
  124 + 720: "DOS-720 - Arabic (Transparent ASMO); Arabic (DOS)",
  125 + 737: "ibm737 - OEM Greek (formerly 437G); Greek (DOS)",
  126 + 775: "ibm775 - OEM Baltic; Baltic (DOS)",
  127 + 850: "ibm850 - OEM Multilingual Latin 1; Western European (DOS)",
  128 + 852: "ibm852 - OEM Latin 2; Central European (DOS)",
  129 + 855: "IBM855 - OEM Cyrillic (primarily Russian)",
  130 + 857: "ibm857 - OEM Turkish; Turkish (DOS)",
  131 + 858: "IBM00858 - OEM Multilingual Latin 1 + Euro symbol",
  132 + 860: "IBM860 - OEM Portuguese; Portuguese (DOS)",
  133 + 861: "ibm861 - OEM Icelandic; Icelandic (DOS)",
  134 + 862: "DOS-862 - OEM Hebrew; Hebrew (DOS)",
  135 + 863: "IBM863 - OEM French Canadian; French Canadian (DOS)",
  136 + 864: "IBM864 - OEM Arabic; Arabic (864)",
  137 + 865: "IBM865 - OEM Nordic; Nordic (DOS)",
  138 + 866: "cp866 - OEM Russian; Cyrillic (DOS)",
  139 + 869: "ibm869 - OEM Modern Greek; Greek, Modern (DOS)",
  140 + 870: "IBM870 - IBM EBCDIC Multilingual/ROECE (Latin 2); IBM EBCDIC Multilingual Latin 2",
  141 + 874: "windows-874 - ANSI/OEM Thai (ISO 8859-11); Thai (Windows)",
  142 + 875: "cp875 - IBM EBCDIC Greek Modern",
  143 + 932: "shift_jis - ANSI/OEM Japanese; Japanese (Shift-JIS)",
  144 + 936: "gb2312 - ANSI/OEM Simplified Chinese (PRC, Singapore); Chinese Simplified (GB2312)",
  145 + 949: "ks_c_5601-1987 - ANSI/OEM Korean (Unified Hangul Code)",
  146 + 950: "big5 - ANSI/OEM Traditional Chinese (Taiwan; Hong Kong SAR, PRC); Chinese Traditional (Big5)",
  147 + 1026: "IBM1026 - IBM EBCDIC Turkish (Latin 5)",
  148 + 1047: "IBM01047 - BM EBCDIC Latin 1/Open System",
  149 + 1140: "IBM01140 - IBM EBCDIC US-Canada (037 + Euro symbol); IBM EBCDIC (US-Canada-Euro)",
  150 + 1141: "IBM01141 - IBM EBCDIC Germany (20273 + Euro symbol); IBM EBCDIC (Germany-Euro)",
  151 + 1142: "IBM01142 - IBM EBCDIC Denmark-Norway (20277 + Euro symbol); IBM EBCDIC (Denmark-Norway-Euro)",
  152 + 1143: "IBM01143 - IBM EBCDIC Finland-Sweden (20278 + Euro symbol); IBM EBCDIC (Finland-Sweden-Euro)",
  153 + 1144: "IBM01144 - IBM EBCDIC Italy (20280 + Euro symbol); IBM EBCDIC (Italy-Euro)",
  154 + 1145: "IBM01145 - IBM EBCDIC Latin America-Spain (20284 + Euro symbol); IBM EBCDIC (Spain-Euro)",
  155 + 1146: "IBM01146 - IBM EBCDIC United Kingdom (20285 + Euro symbol); IBM EBCDIC (UK-Euro)",
  156 + 1147: "IBM01147 - IBM EBCDIC France (20297 + Euro symbol); IBM EBCDIC (France-Euro)",
  157 + 1148: "IBM01148 - IBM EBCDIC International (500 + Euro symbol); IBM EBCDIC (International-Euro)",
  158 + 1149: "IBM01149 - IBM EBCDIC Icelandic (20871 + Euro symbol); IBM EBCDIC (Icelandic-Euro)",
  159 + 1200: "utf-16 - Unicode UTF-16, little endian byte order (BMP of ISO 10646); available only to managed applications",
  160 + 1201: "unicodeFFFE - Unicode UTF-16, big endian byte order; available only to managed applications",
  161 + 1250: "windows-1250 - ANSI Central European; Central European (Windows)",
  162 + 1251: "windows-1251 - ANSI Cyrillic; Cyrillic (Windows)",
  163 + 1252: "windows-1252 - ANSI Latin 1; Western European (Windows)",
  164 + 1253: "windows-1253 - ANSI Greek; Greek (Windows)",
  165 + 1254: "windows-1254 - ANSI Turkish; Turkish (Windows)",
  166 + 1255: "windows-1255 - ANSI Hebrew; Hebrew (Windows)",
  167 + 1256: "windows-1256 - ANSI Arabic; Arabic (Windows)",
  168 + 1257: "windows-1257 - ANSI Baltic; Baltic (Windows)",
  169 + 1258: "windows-1258 - ANSI/OEM Vietnamese; Vietnamese (Windows)",
  170 + 1361: "Johab - Korean (Johab)",
  171 + 10000: "macintosh - MAC Roman; Western European (Mac)",
  172 + 10001: "x-mac-japanese - Japanese (Mac)",
  173 + 10002: "x-mac-chinesetrad - MAC Traditional Chinese (Big5); Chinese Traditional (Mac)",
  174 + 10003: "x-mac-korean - Korean (Mac)",
  175 + 10004: "x-mac-arabic - Arabic (Mac)",
  176 + 10005: "x-mac-hebrew - Hebrew (Mac)",
  177 + 10006: "x-mac-greek - Greek (Mac)",
  178 + 10007: "x-mac-cyrillic - Cyrillic (Mac)",
  179 + 10008: "x-mac-chinesesimp - MAC Simplified Chinese (GB 2312); Chinese Simplified (Mac)",
  180 + 10010: "x-mac-romanian - Romanian (Mac)",
  181 + 10017: "x-mac-ukrainian - Ukrainian (Mac)",
  182 + 10021: "x-mac-thai - Thai (Mac)",
  183 + 10029: "x-mac-ce - MAC Latin 2; Central European (Mac)",
  184 + 10079: "x-mac-icelandic - Icelandic (Mac)",
  185 + 10081: "x-mac-turkish - Turkish (Mac)",
  186 + 10082: "x-mac-croatian - Croatian (Mac)",
  187 + 12000: "utf-32 - Unicode UTF-32, little endian byte order; available only to managed applications",
  188 + 12001: "utf-32BE - Unicode UTF-32, big endian byte order; available only to managed applications",
  189 + 20000: "x-Chinese_CNS - CNS Taiwan; Chinese Traditional (CNS)",
  190 + 20001: "x-cp20001 - TCA Taiwan",
  191 + 20002: "x_Chinese-Eten - Eten Taiwan; Chinese Traditional (Eten)",
  192 + 20003: "x-cp20003 - IBM5550 Taiwan",
  193 + 20004: "x-cp20004 - TeleText Taiwan",
  194 + 20005: "x-cp20005 - Wang Taiwan",
  195 + 20105: "x-IA5 - IA5 (IRV International Alphabet No. 5, 7-bit); Western European (IA5)",
  196 + 20106: "x-IA5-German - IA5 German (7-bit)",
  197 + 20107: "x-IA5-Swedish - IA5 Swedish (7-bit)",
  198 + 20108: "x-IA5-Norwegian - IA5 Norwegian (7-bit)",
  199 + 20127: "us-ascii - US-ASCII (7-bit)",
  200 + 20261: "x-cp20261 - T.61",
  201 + 20269: "x-cp20269 - ISO 6937 Non-Spacing Accent",
  202 + 20273: "IBM273 - IBM EBCDIC Germany",
  203 + 20277: "IBM277 - IBM EBCDIC Denmark-Norway",
  204 + 20278: "IBM278 - IBM EBCDIC Finland-Sweden",
  205 + 20280: "IBM280 - IBM EBCDIC Italy",
  206 + 20284: "IBM284 - IBM EBCDIC Latin America-Spain",
  207 + 20285: "IBM285 - IBM EBCDIC United Kingdom",
  208 + 20290: "IBM290 - IBM EBCDIC Japanese Katakana Extended",
  209 + 20297: "IBM297 - IBM EBCDIC France",
  210 + 20420: "IBM420 - IBM EBCDIC Arabic",
  211 + 20423: "IBM423 - IBM EBCDIC Greek",
  212 + 20424: "IBM424 - IBM EBCDIC Hebrew",
  213 + 20833: "x-EBCDIC-KoreanExtended - IBM EBCDIC Korean Extended",
  214 + 20838: "IBM-Thai - IBM EBCDIC Thai",
  215 + 20866: "koi8-r - Russian (KOI8-R); Cyrillic (KOI8-R)",
  216 + 20871: "IBM871 - IBM EBCDIC Icelandic",
  217 + 20880: "IBM880 - IBM EBCDIC Cyrillic Russian",
  218 + 20905: "IBM905 - IBM EBCDIC Turkish",
  219 + 20924: "IBM00924 - IBM EBCDIC Latin 1/Open System (1047 + Euro symbol)",
  220 + 20932: "EUC-JP - Japanese (JIS 0208-1990 and 0212-1990)",
  221 + 20936: "x-cp20936 - Simplified Chinese (GB2312); Chinese Simplified (GB2312-80)",
  222 + 20949: "x-cp20949 - Korean Wansung",
  223 + 21025: "cp1025 - IBM EBCDIC Cyrillic Serbian-Bulgarian",
  224 + 21027: "(deprecated)",
  225 + 21866: "koi8-u - Ukrainian (KOI8-U); Cyrillic (KOI8-U)",
  226 + 28591: "iso-8859-1 - ISO 8859-1 Latin 1; Western European (ISO)",
  227 + 28592: "iso-8859-2 - ISO 8859-2 Central European; Central European (ISO)",
  228 + 28593: "iso-8859-3 - ISO 8859-3 Latin 3",
  229 + 28594: "iso-8859-4 - ISO 8859-4 Baltic",
  230 + 28595: "iso-8859-5 - ISO 8859-5 Cyrillic",
  231 + 28596: "iso-8859-6 - ISO 8859-6 Arabic",
  232 + 28597: "iso-8859-7 - ISO 8859-7 Greek",
  233 + 28598: "iso-8859-8 - ISO 8859-8 Hebrew; Hebrew (ISO-Visual)",
  234 + 28599: "iso-8859-9 - ISO 8859-9 Turkish",
  235 + 28603: "iso-8859-13 - ISO 8859-13 Estonian",
  236 + 28605: "iso-8859-15 - ISO 8859-15 Latin 9",
  237 + 29001: "x-Europa - Europa 3",
  238 + 38598: "iso-8859-8-i - ISO 8859-8 Hebrew; Hebrew (ISO-Logical)",
  239 + 50220: "iso-2022-jp - ISO 2022 Japanese with no halfwidth Katakana; Japanese (JIS)",
  240 + 50221: "csISO2022JP - ISO 2022 Japanese with halfwidth Katakana; Japanese (JIS-Allow 1 byte Kana)",
  241 + 50222: "iso-2022-jp - ISO 2022 Japanese JIS X 0201-1989; Japanese (JIS-Allow 1 byte Kana - SO/SI)",
  242 + 50225: "iso-2022-kr - ISO 2022 Korean",
  243 + 50227: "x-cp50227 - ISO 2022 Simplified Chinese; Chinese Simplified (ISO 2022)",
  244 + 50229: "ISO 2022 - Traditional Chinese",
  245 + 50930: "EBCDIC - Japanese (Katakana) Extended",
  246 + 50931: "EBCDIC - US-Canada and Japanese",
  247 + 50933: "EBCDIC - Korean Extended and Korean",
  248 + 50935: "EBCDIC - Simplified Chinese Extended and Simplified Chinese",
  249 + 50936: "EBCDIC - Simplified Chinese",
  250 + 50937: "EBCDIC - US-Canada and Traditional Chinese",
  251 + 50939: "EBCDIC - Japanese (Latin) Extended and Japanese",
  252 + 51932: "euc-jp - EUC Japanese",
  253 + 51936: "EUC-CN - EUC Simplified Chinese; Chinese Simplified (EUC)",
  254 + 51949: "euc-kr - EUC Korean",
  255 + 51950: "EUC - Traditional Chinese",
  256 + 52936: "hz-gb-2312 - HZ-GB2312 Simplified Chinese; Chinese Simplified (HZ)",
  257 + 54936: "GB18030 - Windows XP and later: GB18030 Simplified Chinese (4 byte); Chinese Simplified (GB18030)",
  258 + 57002: "x-iscii-de - ISCII Devanagari",
  259 + 57003: "x-iscii-be - ISCII Bengali",
  260 + 57004: "x-iscii-ta - ISCII Tamil",
  261 + 57005: "x-iscii-te - ISCII Telugu",
  262 + 57006: "x-iscii-as - ISCII Assamese",
  263 + 57007: "x-iscii-or - ISCII Oriya",
  264 + 57008: "x-iscii-ka - ISCII Kannada",
  265 + 57009: "x-iscii-ma - ISCII Malayalam",
  266 + 57010: "x-iscii-gu - ISCII Gujarati",
  267 + 57011: "x-iscii-pa - ISCII Punjabi",
  268 + 65000: "utf-7 - Unicode (UTF-7)",
  269 + 65001: "utf-8 - Unicode (UTF-8)",
  270 +}
1 -// Copyright 2014 Richard Lehane. All rights reserved.  
2 -//  
3 -// Licensed under the Apache License, Version 2.0 (the "License");  
4 -// you may not use this file except in compliance with the License.  
5 -// You may obtain a copy of the License at  
6 -//  
7 -// http://www.apache.org/licenses/LICENSE-2.0  
8 -//  
9 -// Unless required by applicable law or agreed to in writing, software  
10 -// distributed under the License is distributed on an "AS IS" BASIS,  
11 -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
12 -// See the License for the specific language governing permissions and  
13 -// limitations under the License.  
14 -  
15 -package types  
16 -  
17 -import (  
18 - "encoding/binary"  
19 - "errors"  
20 -)  
21 -  
22 -// MakeVariant is defined in vectorArray.go. It calls Evaluate, which refers to the MakeTypes map, so must add at runtime  
23 -func init() { MakeTypes[VT_VARIANT] = MakeVariant }  
24 -  
25 -var (  
26 - ErrType = errors.New("msoleps: error coercing byte stream to type")  
27 - ErrUnknownType = errors.New("msoleps: unknown type error")  
28 -)  
29 -  
30 -type Type interface {  
31 - String() string  
32 - Type() string  
33 - Length() int  
34 -}  
35 -  
36 -const (  
37 - vector uint16 = iota + 1  
38 - array  
39 -)  
40 -  
41 -func Evaluate(b []byte) (Type, error) {  
42 - if len(b) < 4 {  
43 - return I1(0), ErrType  
44 - }  
45 - id := TypeID(binary.LittleEndian.Uint16(b[:2]))  
46 - f, ok := MakeTypes[id]  
47 - if !ok {  
48 - return I1(0), ErrUnknownType  
49 - }  
50 - switch binary.LittleEndian.Uint16(b[2:4]) {  
51 - case vector:  
52 - return MakeVector(f, b[4:])  
53 - case array:  
54 - return MakeArray(f, b[4:])  
55 - }  
56 - return f(b[4:])  
57 -}  
58 -  
59 -type TypeID uint16  
60 -  
61 -const (  
62 - VT_EMPTY TypeID = iota // 0x00  
63 - VT_NULL  
64 - VT_I2  
65 - VT_I4  
66 - VT_R4  
67 - VT_R8  
68 - VT_CY  
69 - VT_DATE  
70 - VT_BSTR  
71 - _  
72 - VT_ERROR  
73 - VT_BOOL  
74 - VT_VARIANT  
75 - _  
76 - VT_DECIMAL  
77 - _  
78 - VT_I1  
79 - VT_U1  
80 - VT_UI2  
81 - VT_UI4  
82 - VT_I8  
83 - VT_UI8  
84 - VT_INT  
85 - VT_UINT //0x17  
86 - _ = iota + 5  
87 - VT_LPSTR //0x1E  
88 - VT_LPWSTR  
89 - VT_FILETIME = iota + 0x25 // 0x40  
90 - VT_BLOB  
91 - VT_STREAM  
92 - VT_STORAGE  
93 - VT_STREAMED_OBJECT  
94 - VT_STORED_OBJECT  
95 - VT_BLOB_OBJECT  
96 - VT_CF  
97 - VT_CLSID  
98 - VT_VERSIONED_STREAM // 0x49  
99 -)  
100 -  
101 -type MakeType func([]byte) (Type, error)  
102 -  
103 -var MakeTypes map[TypeID]MakeType = map[TypeID]MakeType{  
104 - VT_I2: MakeI2,  
105 - VT_I4: MakeI4,  
106 - VT_R4: MakeR4,  
107 - VT_R8: MakeR8,  
108 - VT_CY: MakeCurrency,  
109 - VT_DATE: MakeDate,  
110 - VT_BSTR: MakeCodeString,  
111 - VT_BOOL: MakeBool,  
112 - VT_DECIMAL: MakeDecimal,  
113 - VT_I1: MakeI1,  
114 - VT_U1: MakeUI1,  
115 - VT_UI2: MakeUI2,  
116 - VT_UI4: MakeUI4,  
117 - VT_I8: MakeI8,  
118 - VT_UI8: MakeUI8,  
119 - VT_INT: MakeI4,  
120 - VT_UINT: MakeUI4,  
121 - VT_LPSTR: MakeCodeString,  
122 - VT_LPWSTR: MakeUnicode,  
123 - VT_FILETIME: MakeFileTime,  
124 - VT_CLSID: MakeGuid,  
125 -} 1 +// Copyright 2014 Richard Lehane. All rights reserved.
  2 +//
  3 +// Licensed under the Apache License, Version 2.0 (the "License");
  4 +// you may not use this file except in compliance with the License.
  5 +// You may obtain a copy of the License at
  6 +//
  7 +// http://www.apache.org/licenses/LICENSE-2.0
  8 +//
  9 +// Unless required by applicable law or agreed to in writing, software
  10 +// distributed under the License is distributed on an "AS IS" BASIS,
  11 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +// See the License for the specific language governing permissions and
  13 +// limitations under the License.
  14 +
  15 +package types
  16 +
  17 +import (
  18 + "encoding/binary"
  19 + "errors"
  20 +)
  21 +
  22 +// MakeVariant is defined in vectorArray.go. It calls Evaluate, which refers to the MakeTypes map, so must add at runtime
  23 +func init() { MakeTypes[VT_VARIANT] = MakeVariant }
  24 +
  25 +var (
  26 + ErrType = errors.New("msoleps: error coercing byte stream to type")
  27 + ErrUnknownType = errors.New("msoleps: unknown type error")
  28 +)
  29 +
  30 +type Type interface {
  31 + String() string
  32 + Type() string
  33 + Length() int
  34 +}
  35 +
  36 +const (
  37 + vector uint16 = iota + 1
  38 + array
  39 +)
  40 +
  41 +func Evaluate(b []byte) (Type, error) {
  42 + if len(b) < 4 {
  43 + return I1(0), ErrType
  44 + }
  45 + id := TypeID(binary.LittleEndian.Uint16(b[:2]))
  46 + f, ok := MakeTypes[id]
  47 + if !ok {
  48 + return I1(0), ErrUnknownType
  49 + }
  50 + switch binary.LittleEndian.Uint16(b[2:4]) {
  51 + case vector:
  52 + return MakeVector(f, b[4:])
  53 + case array:
  54 + return MakeArray(f, b[4:])
  55 + }
  56 + return f(b[4:])
  57 +}
  58 +
  59 +type TypeID uint16
  60 +
  61 +const (
  62 + VT_EMPTY TypeID = iota // 0x00
  63 + VT_NULL
  64 + VT_I2
  65 + VT_I4
  66 + VT_R4
  67 + VT_R8
  68 + VT_CY
  69 + VT_DATE
  70 + VT_BSTR
  71 + _
  72 + VT_ERROR
  73 + VT_BOOL
  74 + VT_VARIANT
  75 + _
  76 + VT_DECIMAL
  77 + _
  78 + VT_I1
  79 + VT_U1
  80 + VT_UI2
  81 + VT_UI4
  82 + VT_I8
  83 + VT_UI8
  84 + VT_INT
  85 + VT_UINT //0x17
  86 + _ = iota + 5
  87 + VT_LPSTR //0x1E
  88 + VT_LPWSTR
  89 + VT_FILETIME = iota + 0x25 // 0x40
  90 + VT_BLOB
  91 + VT_STREAM
  92 + VT_STORAGE
  93 + VT_STREAMED_OBJECT
  94 + VT_STORED_OBJECT
  95 + VT_BLOB_OBJECT
  96 + VT_CF
  97 + VT_CLSID
  98 + VT_VERSIONED_STREAM // 0x49
  99 +)
  100 +
  101 +type MakeType func([]byte) (Type, error)
  102 +
  103 +var MakeTypes map[TypeID]MakeType = map[TypeID]MakeType{
  104 + VT_I2: MakeI2,
  105 + VT_I4: MakeI4,
  106 + VT_R4: MakeR4,
  107 + VT_R8: MakeR8,
  108 + VT_CY: MakeCurrency,
  109 + VT_DATE: MakeDate,
  110 + VT_BSTR: MakeCodeString,
  111 + VT_BOOL: MakeBool,
  112 + VT_DECIMAL: MakeDecimal,
  113 + VT_I1: MakeI1,
  114 + VT_U1: MakeUI1,
  115 + VT_UI2: MakeUI2,
  116 + VT_UI4: MakeUI4,
  117 + VT_I8: MakeI8,
  118 + VT_UI8: MakeUI8,
  119 + VT_INT: MakeI4,
  120 + VT_UINT: MakeUI4,
  121 + VT_LPSTR: MakeCodeString,
  122 + VT_LPWSTR: MakeUnicode,
  123 + VT_FILETIME: MakeFileTime,
  124 + VT_CLSID: MakeGuid,
  125 +}
1 -// Copyright 2015 Richard Lehane. All rights reserved.  
2 -//  
3 -// Licensed under the Apache License, Version 2.0 (the "License");  
4 -// you may not use this file except in compliance with the License.  
5 -// You may obtain a copy of the License at  
6 -//  
7 -// http://www.apache.org/licenses/LICENSE-2.0  
8 -//  
9 -// Unless required by applicable law or agreed to in writing, software  
10 -// distributed under the License is distributed on an "AS IS" BASIS,  
11 -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  
12 -// See the License for the specific language governing permissions and  
13 -// limitations under the License.  
14 -  
15 -package types  
16 -  
17 -import (  
18 - "encoding/binary"  
19 -)  
20 -  
21 -type Vector []Type  
22 -  
23 -func (v Vector) String() string {  
24 - return ""  
25 -}  
26 -  
27 -func (v Vector) Type() string {  
28 - if len(v) > 0 {  
29 - return "Vector of " + v[0].Type()  
30 - }  
31 - return "Vector (empty)"  
32 -}  
33 -  
34 -func (v Vector) Length() int {  
35 - ret := 4  
36 - for _, t := range v {  
37 - ret += t.Length()  
38 - }  
39 - return ret  
40 -}  
41 -  
42 -func MakeVector(f MakeType, b []byte) (Type, error) {  
43 - if len(b) < 4 {  
44 - return Vector{}, ErrType  
45 - }  
46 - l := int(binary.LittleEndian.Uint32(b[:4]))  
47 - v := make(Vector, l)  
48 - place := 4  
49 - for i := 0; i < l; i++ {  
50 - t, err := f(b[place:])  
51 - if err != nil {  
52 - return Vector{}, ErrType  
53 - }  
54 - v[i] = t  
55 - place += t.Length()  
56 - }  
57 - return v, nil  
58 -}  
59 -  
60 -type Array [][]Type  
61 -  
62 -func (a Array) String() string {  
63 - return ""  
64 -}  
65 -  
66 -func (a Array) Type() string {  
67 - if len(a) > 0 && len(a[0]) > 0 {  
68 - return "Array of " + a[0][0].Type()  
69 - }  
70 - return "Array (empty)"  
71 -}  
72 -  
73 -func (a Array) Length() int {  
74 - return 0  
75 -}  
76 -  
77 -func MakeArray(f MakeType, b []byte) (Type, error) {  
78 - return Array{}, nil  
79 -}  
80 -  
81 -type Variant struct {  
82 - t Type  
83 -}  
84 -  
85 -func (v Variant) String() string {  
86 - return "Typed Property Value containing " + v.t.String()  
87 -}  
88 -  
89 -func (v Variant) Type() string {  
90 - return "Typed Property Value containing " + v.t.Type()  
91 -}  
92 -  
93 -func (v Variant) Length() int {  
94 - return 4 + v.t.Length()  
95 -}  
96 -  
97 -func MakeVariant(b []byte) (Type, error) {  
98 - t, err := Evaluate(b)  
99 - if err != nil {  
100 - return Variant{}, err  
101 - }  
102 - return Variant{t}, nil  
103 -} 1 +// Copyright 2015 Richard Lehane. All rights reserved.
  2 +//
  3 +// Licensed under the Apache License, Version 2.0 (the "License");
  4 +// you may not use this file except in compliance with the License.
  5 +// You may obtain a copy of the License at
  6 +//
  7 +// http://www.apache.org/licenses/LICENSE-2.0
  8 +//
  9 +// Unless required by applicable law or agreed to in writing, software
  10 +// distributed under the License is distributed on an "AS IS" BASIS,
  11 +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12 +// See the License for the specific language governing permissions and
  13 +// limitations under the License.
  14 +
  15 +package types
  16 +
  17 +import (
  18 + "encoding/binary"
  19 +)
  20 +
  21 +type Vector []Type
  22 +
  23 +func (v Vector) String() string {
  24 + return ""
  25 +}
  26 +
  27 +func (v Vector) Type() string {
  28 + if len(v) > 0 {
  29 + return "Vector of " + v[0].Type()
  30 + }
  31 + return "Vector (empty)"
  32 +}
  33 +
  34 +func (v Vector) Length() int {
  35 + ret := 4
  36 + for _, t := range v {
  37 + ret += t.Length()
  38 + }
  39 + return ret
  40 +}
  41 +
  42 +func MakeVector(f MakeType, b []byte) (Type, error) {
  43 + if len(b) < 4 {
  44 + return Vector{}, ErrType
  45 + }
  46 + l := int(binary.LittleEndian.Uint32(b[:4]))
  47 + v := make(Vector, l)
  48 + place := 4
  49 + for i := 0; i < l; i++ {
  50 + t, err := f(b[place:])
  51 + if err != nil {
  52 + return Vector{}, ErrType
  53 + }
  54 + v[i] = t
  55 + place += t.Length()
  56 + }
  57 + return v, nil
  58 +}
  59 +
  60 +type Array [][]Type
  61 +
  62 +func (a Array) String() string {
  63 + return ""
  64 +}
  65 +
  66 +func (a Array) Type() string {
  67 + if len(a) > 0 && len(a[0]) > 0 {
  68 + return "Array of " + a[0][0].Type()
  69 + }
  70 + return "Array (empty)"
  71 +}
  72 +
  73 +func (a Array) Length() int {
  74 + return 0
  75 +}
  76 +
  77 +func MakeArray(f MakeType, b []byte) (Type, error) {
  78 + return Array{}, nil
  79 +}
  80 +
  81 +type Variant struct {
  82 + t Type
  83 +}
  84 +
  85 +func (v Variant) String() string {
  86 + return "Typed Property Value containing " + v.t.String()
  87 +}
  88 +
  89 +func (v Variant) Type() string {
  90 + return "Typed Property Value containing " + v.t.Type()
  91 +}
  92 +
  93 +func (v Variant) Length() int {
  94 + return 4 + v.t.Length()
  95 +}
  96 +
  97 +func MakeVariant(b []byte) (Type, error) {
  98 + t, err := Evaluate(b)
  99 + if err != nil {
  100 + return Variant{}, err
  101 + }
  102 + return Variant{t}, nil
  103 +}
@@ -3,9 +3,6 @@ @@ -3,9 +3,6 @@
3 github.com/360EntSecGroup-Skylar/excelize/v2 3 github.com/360EntSecGroup-Skylar/excelize/v2
4 # github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798 4 # github.com/DataDog/zstd v1.3.6-0.20190409195224-796139022798
5 github.com/DataDog/zstd 5 github.com/DataDog/zstd
6 -# github.com/GeeTeam/gt3-golang-sdk v0.0.0-20200116043922-446ca8a507d2  
7 -## explicit  
8 -github.com/GeeTeam/gt3-golang-sdk/geetest  
9 # github.com/Shopify/sarama v1.23.1 6 # github.com/Shopify/sarama v1.23.1
10 ## explicit 7 ## explicit
11 github.com/Shopify/sarama 8 github.com/Shopify/sarama