Skip to content

Commit 7af1f75

Browse files
committed
Fix ipptool regression caused by changes for #4.
Add ippRestore/ippSave APIs to restore and save the current message position for ippFind/NextAttribute and ippGetFirst/NextAttribute. Update documentation.
1 parent 41660d6 commit 7af1f75

7 files changed

Lines changed: 208 additions & 62 deletions

File tree

cups/cupspm.md

Lines changed: 28 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
---
22
title: CUPS Programming Manual
33
author: Michael R Sweet
4-
copyright: Copyright © 2021-2022 by OpenPrinting. All Rights Reserved.
4+
copyright: Copyright © 2021-2023 by OpenPrinting. All Rights Reserved.
55
version: 3.0.0
66
...
77

@@ -1002,6 +1002,31 @@ IPP attributes (`ipp_attribute_t`) that includes a status code (`IPP_STATUS_OK`,
10021002
`IPP_STATUS_ERROR_BAD_REQUEST`, etc.) and the corresponding 32-bit integer
10031003
identifier from the request.
10041004

1005+
CUPS provides many functions to access the attributes and values in an IPP
1006+
response message:
1007+
1008+
- [`ippFindAttribute`](@@) finds the first occurrence of an attribute.
1009+
- [`ippFindNextAttribute`](@@) finds the next occurrence of an attribute.
1010+
- [`ippGetBoolean`](@@) gets a boolean value for an attribute.
1011+
- [`ippGetCollection`](@@) gets a collection value for an attribute.
1012+
- [`ippGetCount`](@@) gets the number of values in an attribute.
1013+
- [`ippGetDate`](@@) gets a date value for an attribute.
1014+
- [`ippGetFirstAttribute`](@@) gets the first attribute in the IPP response.
1015+
- [`ippGetGroupTag`](@@) gets the group tag associated with an attribute.
1016+
- [`ippGetInteger`](@@) gets the integer or enum value for an attribute.
1017+
- [`ippGetName`](@@) gets the name of an attribute.
1018+
- [`ippGetNextAttribute`](@@) gets the next attribute in the IPP response.
1019+
- [`ippGetOctetString`](@@) gets an octetString value for an attribute.
1020+
- [`ippGetRange`](@@) gets a rangeOfInteger value for an attribute.
1021+
- [`ippGetRequestId`](@@) gets the request ID number for the IPP response.
1022+
- [`ippGetResolution`](@@) gets a resolution value for an attribute.
1023+
- [`ippGetStatusCode`](@@) gets the status code for the IPP response.
1024+
- [`ippGetString`](@@) gets a string value for an attribute.
1025+
- [`ippGetValueTag`](@@) gets the value tag ("syntax") for an attribute.
1026+
- [`ippGetVersion`](@@) gets the IPP version used for the IPP response.
1027+
- [`ippRestore`](@@) restores a previous position in the IPP response.
1028+
- [`ippSave`](@@) saves the current position in the IPP response.
1029+
10051030
For example, the following code finds the printer state attributes and prints
10061031
their values:
10071032

@@ -1015,7 +1040,9 @@ if ((attr = ippFindAttribute(response, "printer-state",
10151040
ippEnumString("printer-state", ippGetInteger(attr, 0)));
10161041
}
10171042
else
1043+
{
10181044
puts("printer-state=unknown");
1045+
}
10191046
10201047
if ((attr = ippFindAttribute(response, "printer-state-message",
10211048
IPP_TAG_TEXT)) != NULL)
@@ -1035,14 +1062,6 @@ if ((attr = ippFindAttribute(response, "printer-state-reasons",
10351062
}
10361063
```
10371064

1038-
The [`ippGetCount`](@@) function returns the number of values in an attribute.
1039-
1040-
The [`ippGetInteger`](@@) and [`ippGetString`](@@) functions return a single
1041-
integer or string value from an attribute.
1042-
1043-
The [`ippEnumString`](@@) function converts a enum value to its keyword (string)
1044-
equivalent.
1045-
10461065
Once you are done using the IPP response message, free it using the
10471066
[`ippDelete`](@@) function:
10481067

cups/ipp-private.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// Private IPP definitions for CUPS.
33
//
4-
// Copyright © 2021-2022 by OpenPrinting.
4+
// Copyright © 2021-2023 by OpenPrinting.
55
// Copyright © 2007-2018 by Apple Inc.
66
// Copyright © 1997-2006 by Easy Software Products.
77
//
@@ -23,6 +23,7 @@ extern "C" {
2323

2424
# define IPP_BUF_SIZE (IPP_MAX_LENGTH + 2)
2525
// Size of buffer
26+
# define _IPP_MAX_FIND 8 // Size of find stack
2627

2728

2829
//
@@ -106,6 +107,13 @@ struct _ipp_attribute_s // IPP attribute
106107
_ipp_value_t values[1]; // Values
107108
};
108109

110+
typedef struct _ipp_find_s // IPP find data
111+
{
112+
ipp_attribute_t *attr; // Current attribute
113+
size_t idx; // Current attribute index for hierarchical search
114+
bool atend; // At the end of the message?
115+
} _ipp_find_t;
116+
109117
struct _ipp_s // IPP Request/Response/Notification
110118
{
111119
ipp_state_t state; // State of request
@@ -114,11 +122,12 @@ struct _ipp_s // IPP Request/Response/Notification
114122
ipp_attribute_t *last; // Last attribute in list
115123
ipp_attribute_t *current; // Current attribute (for read/write)
116124
ipp_tag_t curtag; // Current attribute group tag
117-
118125
ipp_attribute_t *prev; // Previous attribute (for read)
119126
size_t use; // Use count
120-
bool atend; // At end of list?
121-
size_t curindex; // Current attribute index for hierarchical search
127+
128+
_ipp_find_t fstack[_IPP_MAX_FIND];
129+
// Find stack
130+
_ipp_find_t *find; // Current find
122131
};
123132

124133
typedef struct _ipp_option_s // Attribute mapping data

cups/ipp.c

Lines changed: 76 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/*
22
* Internet Printing Protocol functions for CUPS.
33
*
4-
* Copyright © 2021-2022 by OpenPrinting.
4+
* Copyright © 2021-2023 by OpenPrinting.
55
* Copyright © 2007-2021 by Apple Inc.
66
* Copyright © 1997-2007 by Easy Software Products, all rights reserved.
77
*
@@ -1819,8 +1819,9 @@ ippFindAttribute(ipp_t *ipp, // I - IPP message
18191819
return (NULL);
18201820

18211821
// Reset the current attribute pointer...
1822-
ipp->current = NULL;
1823-
ipp->atend = false;
1822+
ipp->find->attr = NULL;
1823+
ipp->find->idx = 0;
1824+
ipp->find->atend = false;
18241825

18251826
// Search for the attribute...
18261827
return (ippFindNextAttribute(ipp, name, type));
@@ -1853,9 +1854,9 @@ ippFindNextAttribute(ipp_t *ipp, // I - IPP message
18531854
if (!ipp || !name)
18541855
return (NULL);
18551856

1856-
DEBUG_printf(("3ippFindNextAttribute: atend=%s", ipp->atend ? "true" : "false"));
1857+
DEBUG_printf(("3ippFindNextAttribute: atend=%s", ipp->find->atend ? "true" : "false"));
18571858

1858-
if (ipp->atend)
1859+
if (ipp->find->atend)
18591860
return (NULL);
18601861

18611862
if (strchr(name, '/'))
@@ -1870,59 +1871,55 @@ ippFindNextAttribute(ipp_t *ipp, // I - IPP message
18701871

18711872
*child++ = '\0';
18721873

1873-
if (ipp->current && ipp->current->name && ipp->current->value_tag == IPP_TAG_BEGIN_COLLECTION && !strcmp(parent, ipp->current->name))
1874+
if (ipp->find->attr && ipp->find->attr->name && ipp->find->attr->value_tag == IPP_TAG_BEGIN_COLLECTION && !strcmp(parent, ipp->find->attr->name))
18741875
{
1875-
while (ipp->curindex < ipp->current->num_values)
1876+
while (ipp->find->idx < ipp->find->attr->num_values)
18761877
{
1877-
if ((childattr = ippFindNextAttribute(ipp->current->values[ipp->curindex].collection, child, type)) != NULL)
1878+
if ((childattr = ippFindNextAttribute(ipp->find->attr->values[ipp->find->idx].collection, child, type)) != NULL)
18781879
return (childattr);
18791880

1880-
ipp->curindex ++;
1881-
if (ipp->curindex < ipp->current->num_values && ipp->current->values[ipp->curindex].collection)
1882-
ipp->current->values[ipp->curindex].collection->current = NULL;
1881+
ipp->find->idx ++;
1882+
if (ipp->find->idx < ipp->find->attr->num_values && ipp->find->attr->values[ipp->find->idx].collection)
1883+
ipp->find->attr->values[ipp->find->idx].collection->find->attr = NULL;
18831884
}
18841885

1885-
ipp->prev = ipp->current;
1886-
ipp->current = ipp->current->next;
1887-
ipp->curindex = 0;
1886+
ipp->find->attr = ipp->find->attr->next;
1887+
ipp->find->idx = 0;
18881888

1889-
if (!ipp->current)
1889+
if (!ipp->find->attr)
18901890
{
1891-
ipp->atend = true;
1891+
ipp->find->atend = true;
18921892
return (NULL);
18931893
}
18941894
}
18951895

1896-
if (!ipp->current)
1896+
if (!ipp->find->attr)
18971897
{
1898-
ipp->prev = NULL;
1899-
ipp->current = ipp->attrs;
1900-
ipp->curindex = 0;
1898+
ipp->find->attr = ipp->attrs;
1899+
ipp->find->idx = 0;
19011900
}
19021901

19031902
name = parent;
1904-
attr = ipp->current;
1903+
attr = ipp->find->attr;
19051904
}
1906-
else if (ipp->current)
1905+
else if (ipp->find->attr)
19071906
{
1908-
ipp->prev = ipp->current;
1909-
attr = ipp->current->next;
1907+
attr = ipp->find->attr->next;
19101908
}
19111909
else
19121910
{
1913-
ipp->prev = NULL;
1914-
attr = ipp->attrs;
1911+
attr = ipp->attrs;
19151912
}
19161913

1917-
for (; attr != NULL; ipp->prev = attr, attr = attr->next)
1914+
for (; attr != NULL; attr = attr->next)
19181915
{
19191916
DEBUG_printf(("4ippFindAttribute: attr=%p, name=\"%s\"", (void *)attr, attr->name));
19201917

19211918
value_tag = (ipp_tag_t)(attr->value_tag & IPP_TAG_CUPS_MASK);
19221919

19231920
if (attr->name != NULL && _cups_strcasecmp(attr->name, name) == 0 && (value_tag == type || type == IPP_TAG_ZERO || name == parent || (value_tag == IPP_TAG_TEXTLANG && type == IPP_TAG_TEXT) || (value_tag == IPP_TAG_NAMELANG && type == IPP_TAG_NAME)))
19241921
{
1925-
ipp->current = attr;
1922+
ipp->find->attr = attr;
19261923

19271924
if (name == parent && attr->value_tag == IPP_TAG_BEGIN_COLLECTION)
19281925
{
@@ -1932,20 +1929,21 @@ ippFindNextAttribute(ipp_t *ipp, // I - IPP message
19321929
{
19331930
if ((childattr = ippFindAttribute(attr->values[i].collection, child, type)) != NULL)
19341931
{
1935-
attr->values[0].collection->curindex = i;
1932+
attr->values[0].collection->find->idx = i;
19361933
return (childattr);
19371934
}
19381935
}
19391936
}
19401937
else
1938+
{
19411939
return (attr);
1940+
}
19421941
}
19431942
}
19441943

19451944
// If we get this far, we didn't find it...
1946-
ipp->current = NULL;
1947-
ipp->prev = NULL;
1948-
ipp->atend = true;
1945+
ipp->find->attr = NULL;
1946+
ipp->find->atend = true;
19491947

19501948
return (NULL);
19511949
}
@@ -2063,8 +2061,15 @@ ippGetFirstAttribute(ipp_t *ipp) // I - IPP message
20632061
if (!ipp)
20642062
return (NULL);
20652063

2064+
if (!ipp->find)
2065+
ipp->find = ipp->fstack;
2066+
2067+
ipp->find->attr = ipp->attrs;
2068+
ipp->find->idx = 0;
2069+
ipp->find->atend = ipp->find->attr == NULL;
2070+
20662071
// Return the first attribute...
2067-
return (ipp->current = ipp->attrs);
2072+
return (ipp->find->attr);
20682073
}
20692074

20702075

@@ -2146,11 +2151,14 @@ ipp_attribute_t * // O - Next attribute or `NULL` if none
21462151
ippGetNextAttribute(ipp_t *ipp) // I - IPP message
21472152
{
21482153
// Range check input...
2149-
if (!ipp || !ipp->current)
2154+
if (!ipp || !ipp->find || !ipp->find->attr)
21502155
return (NULL);
21512156

2157+
ipp->find->attr = ipp->find->attr->next;
2158+
ipp->find->atend = ipp->find->attr == NULL;
2159+
21522160
// Return the next attribute...
2153-
return (ipp->current = ipp->current->next);
2161+
return (ipp->find->attr);
21542162
}
21552163

21562164

@@ -2483,6 +2491,7 @@ ippNew(void)
24832491
temp->request.any.version[0] = (ipp_uchar_t)(cg->server_version / 10);
24842492
temp->request.any.version[1] = (ipp_uchar_t)(cg->server_version % 10);
24852493
temp->use = 1;
2494+
temp->find = temp->fstack;
24862495
}
24872496

24882497
DEBUG_printf(("1ippNew: Returning %p", (void *)temp));
@@ -3457,6 +3466,38 @@ ippReadIO(void *src, // I - Data source
34573466
}
34583467

34593468

3469+
//
3470+
// 'ippRestore()' - Restore a previously saved find position.
3471+
//
3472+
3473+
void
3474+
ippRestore(ipp_t *ipp) // I - IPP message
3475+
{
3476+
if (ipp)
3477+
{
3478+
if (ipp->find > ipp->fstack)
3479+
ipp->find --;
3480+
else
3481+
ipp->find = NULL;
3482+
}
3483+
}
3484+
3485+
3486+
//
3487+
// 'ippSave()' - Save the current find position.
3488+
//
3489+
3490+
void
3491+
ippSave(ipp_t *ipp) // I - IPP message
3492+
{
3493+
if (ipp && ipp->find < (ipp->fstack + _IPP_MAX_FIND))
3494+
{
3495+
ipp->find[1] = ipp->find[0];
3496+
ipp->find ++;
3497+
}
3498+
}
3499+
3500+
34603501
//
34613502
// 'ippSetBoolean()' - Set a boolean value in an attribute.
34623503
//

cups/ipp.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//
22
// Internet Printing Protocol definitions for CUPS.
33
//
4-
// Copyright © 2021-2022 by OpenPrinting.
4+
// Copyright © 2021-2023 by OpenPrinting.
55
// Copyright © 2007-2018 by Apple Inc.
66
// Copyright © 1997-2006 by Easy Software Products.
77
//
@@ -631,7 +631,9 @@ extern ipp_op_t ippOpValue(const char *name) _CUPS_PUBLIC;
631631
extern ipp_state_t ippRead(http_t *http, ipp_t *ipp) _CUPS_PUBLIC;
632632
extern ipp_state_t ippReadFile(int fd, ipp_t *ipp) _CUPS_PUBLIC;
633633
extern ipp_state_t ippReadIO(void *src, ipp_io_cb_t cb, bool blocking, ipp_t *parent, ipp_t *ipp) _CUPS_PUBLIC;
634+
extern void ippRestore(ipp_t *ipp) _CUPS_PUBLIC;
634635

636+
extern void ippSave(ipp_t *ipp) _CUPS_PUBLIC;
635637
extern bool ippSetBoolean(ipp_t *ipp, ipp_attribute_t **attr, size_t element, bool boolvalue) _CUPS_PUBLIC;
636638
extern bool ippSetCollection(ipp_t *ipp, ipp_attribute_t **attr, size_t element, ipp_t *colvalue) _CUPS_PUBLIC;
637639
extern bool ippSetDate(ipp_t *ipp, ipp_attribute_t **attr, size_t element, const ipp_uchar_t *datevalue) _CUPS_PUBLIC;

doc/cupspm.epub

408 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)